Process Execution with EPP/Automation Support
Compatibility: API version 2 revision 21 and later
Throughout the API documentation, you will see the terms External Program Integration Plug-in (EPP) and EPP node.
In LIMS v3.5, v4.1, and v4.2, in the LIMS web interface, the term automation replaces EPP and the term Automated Informatics (AI) node replaces EPP node . However, the Operations Interface still uses the term EPP.
At the completion of a process, EPP can invoke any external program that runs from a command line. In this example, a process with a reference to a declared EPP program is configured and executed entirely via the API.
1. | You have defined a process that has: |
• | An input of type analyte. |
• | A single output per input. |
• | A single shared result file. |
2. | The process type is associated with an external program that has: |
• | At least one process-parameter defined - named TestProcessParam. |
• | A parameter string of: |
bash -c "echo HelloWorld > {compoundOutputFileLuid0}.txt"
3. | Samples have been added to the LIMS. |
The example Running a Process/Step is similar to this example. The differences are that this example will have minimal input/output and will post a reference to a pre-defined EPP process-parameter.
To run a process on a sample, you must first identify the sample to be used as the input to the process.
For this example, we will run the process on the first highlighted sample, shown below:
Once we have identified the sample, we can use its LIMS ID to as a parameter for the script.
The artifact URI is then used as the input in constructing the XML to POST and execute a process.
Step 2: Identify the Container
In addition, this example requires a container in which to store the results of the process execution. An example of how to do this is included in the Groovy script attached to this page.
The following code block outlines this action and obtains the container's URI for the process execution POST.
// Create a new container using the StreamingMarkupBuilder
def containerDoc = builder.bind {
mkp.xmlDeclaration()
mkp.declareNamespace(con: 'http://genologics.com/ri/container')
mkp.declareNamespace(udf: 'http://genologics.com/ri/userdefined')
'con:container'{
'name'("HiSEQ POST${randomNumGen.nextInt()}")
'type'(uri:"http://${hostname}/api/v2/containertypes/1", name:"96 well plate")
}
}
// Post the new container to the API
containerNode = GLSRestApiUtils.xmlStringToNode(containerDoc.toString())
returnNode = GLSRestApiUtils.httpPOST(containerNode, containersListURI, username, password)
container96WellsURI = returnNode.@uri
As shown in other examples, you can use StreamingMarkupBuilder to construct the XML needed for the POST.
Step 3: Construct and POST the XML to execute the process
We now have all the pieces of data to construct the XML for the process execution:
// Create the required URIs
processListURI = "http://${hostname}/api/v2/processes"
researcherURI = "http://${hostname}/api/v2/researchers/1"
analyteURI = "http://${hostname}/api/v2/artifacts/${inputAnalyeLIMSID}"
// Retrieve the Process-Type
processParamName = 'TestProcessParam'
processTypeNode = GLSRestApiUtils.httpGET(processTypeURI, username, password)
// Create a new process using the StreamingMarkupBuilder
def processDoc = new StreamingMarkupBuilder().bind {
mkp.xmlDeclaration()
mkp.declareNamespace(prx:'http://genologics.com/ri/processexecution')
'prx:process'{
'type'(processTypeNode.'@name')
'technician'(uri:researcherURI)
'input-output-map' {
'input'(uri:analyteURI)
'output'(type:'Analyte') {
'location' {
'container'(uri:container96WellsURI)
'value'("A:1")
}
}
}
'input-output-map'(shared:'true') {
'input'(uri:analyteURI)
'output'(type:'ResultFile')
}
'process-parameter'(name:processParamName)
}
}
// Post the process to the API
unresolvedProcessNode = GLSRestApiUtils.xmlStringToNode(processDoc.toString())
returnNode = GLSRestApiUtils.httpPOST(unresolvedProcessNode, "${processListURI}", username, password)
println GLSRestApiUtils.nodeToXmlString(returnNode)
Executing a process uses the processexecution (prx) namespace. The required elements for a successful POST are as follows:
• | type - the name of the process being run |
• | technician uri - the URI for the technician that will be listed as running the process |
• | input-output-map - one input-output-map element for each pair of inputs and outputs |
• | input uri - the URI for the input artifact |
• | output type - the type of artifact of the output |
If the outputs of the process are analytes, then the following elements are also required:
• | container uri - the URI for the container the output will be placed in |
• | value - the well placement for the output |
To also use the configured EPP process, the following element is required:
• | process-parameter - the name of the configured EPP to be executed when this process is posted. |
1. | The process type, technician, input artifact, container, and EPP parameter matching the processParamName variable must all exist in the system before the process can be executed. |
2. | In the case of analyte outputs, if there are no containers with empty wells in the system, you must create one before running the process. |
3. | The XML constructed must match the configuration of the process type. For example, if the process is configured to have both analytes and a shared result file as outputs, you must have: |
• | An input-output-map for each pair of analyte inputs and outputs. |
• | An additional input-output-map for the shared result file. |
4. | The name on the process execution XML must match one of the possibly-declared EPP parameter names. This is true for any EPP parameters. |
If the POST is Successful
• | The process XML will be returned. |
In the following example, note there are two <input-output-map> elements. The second instance has an output-generation-type of PerAllInputs, which indicates that the result file is shared, and only one is produced regardless of the number of inputs.
<prc:process uri="http://localhost/api/v2/processes/ROB-QSK-110525-24-109084" limsid="ROB-QSK-110525-24-109084">
<type uri="http://localhost/api/v2/processtypes/1979">robtype1</type>
<date-run>2014-11-14</date-run>
<technician uri="http://localhost/api/v2/researchers/11651">
<first-name>John-Luck</first-name>
<last-name> Pikkard </last-name>
</technician>
<input-output-map>
<input post-process-uri="http://localhost/api/v2/artifacts/LIT2693A1SAM1?state=8564"uri="http://localhost/api/v2/artifacts/LIT2693A1SAM1?state=8562" limsid="LIT2693A1SAM1"/>
<output uri="http://localhost/api/v2/artifacts/LIT2693A1RO10?state=8563" output-type="Analyte" limsid="LIT2693A1RO10"/>
</input-output-map>
<input-output-map>
<input post-process-uri="http://localhost/api/v2/artifacts/ADM793A1PA1?state=3896" uri="http://localhost/api/v2/artifacts/ADM793A1PA1?state=3893" limsid="ADM793A1PA1"/>
<output uri="http://localhost/api/v2/artifacts/ADM793A1RO2?state=3894" output-generation-type="PerAllInputs" output-type="ResultFile" limsid="ADM793A1RO2"/>
</input-output-map>
<process-parameter name="TestProcessParam"/>
</prc:process>
If the POST is Not Successful
• | The XML that is returned will contain the error that occurred when the POST completed. For example: |
<exc:exception xmlns:exc="http://genologics.com/ri/exception">
<message>The process type named 'HiSEQ POST' cannot produce the following types of shared outputs: 'ResultFile'.</message>
</exc:exception>
The response XML will contain the <process-parameter> tag. The automatedInformatics.log file will contain an entry similar to the following:
Command string: bash -c "echo HelloWorld > LIT1143A1RO6.txt"
In the LIMS Operations Interface, the process summary view will show the parameter string name.
In addition, the file generated by the EPP will also be visible, and when opened should contain "HelloWorld."
Attachments
• | ExecuteProcessWithEPP.groovy.txt |
• | autocomplete-process.py.txt |