Viewing the Inputs and Outputs of a Process/Step

Compatibility: API version 2 revision 21 and later

When samples are processed in the lab, they generally produce 'child' samples that are altered in some way. Eventually, the samples are analyzed on an instrument, with the end result being a data file. Often these data are analyzed further, which produces additional data files.

The sample processing that occurs in the lab is modeled as steps in the LIMS web interface. In the REST API, this processing is modeled as processes, and the samples and files that are processed are represented as artifacts. Understanding the representation of inputs and outputs within the XML for an individual process is critical to being able to use the REST API effectively.

Prerequisites

LIMS v4.2 and earlier:

You have added samples to the LIMS.
In the Operations Interface, you have defined a process that has an analyte input and an analyte output; this process also generates a shared result file output.
You have run the process on some samples.

LIMS v5 and later:

You have added samples to the LIMS.
In the LIMS configuration area, on the Lab Work tab, you have configured a step that generates derived samples.
On the Master Step Settings screen of the step, on the Record Details milestone, you have configured a file placeholder for a sample measurement file to be generated and attached by an automation script at run time.
On the Automation tab, you have configured an automation that generates the sample measurement file and have enabled it on the step.
On the Step Settings screen of the step, on the Record Details milestone, you have configured the automation triggers.
You have run the step on some samples.

Code Example

LIMS v4.2 and earlier:

In the LIMS Operations Interface, in the process summary view, the Input/Output Explorerlists the inputs and outputs for each process. If you select an input, the corresponding output is highlighted.

Similarly, if you select an output, the corresponding input(s) will be highlighted.

LIMS v5 and later:

As of BaseSpace Clarity LIMS v5, the Operations Interface Java client has been deprecated. In LIMS v5 and later, there is no equivalent screen to the Input/Output Explorer (shown above) in which to select step inputs/outputs and generated files and view their corresponding inputs/outputs, and files.

However, the API code example described below is still relevant and will produce the same results.

Step 1. Request individual process resource

The first step in this example is to request the individual process resource via a GET method. The full XML representation returned includes the input-output-map.

To illustrate the relationships between the inputs and outputs, we will save them using a Groovy Map data structure. This will map the output LIMS IDs to a list of input LIMS IDs associated with each output.

outputToInputMap = [:] processURI = "http://${hostname}/api/v2/processes/${processLIMSID}" p+cess = GLSRestApiUtils.httpGET(processURI, username, password)

The process variable now holds the complete XMLstructure returned from the processURI.

In the following example XML snippet, elements of the input-output-map are labeled with <input-output-map>.

<prc:process uri="http://IPAddress/api/v2/processes/TES-SA1-130107-24-5259" limsid="TES-SA1-130107-24-5259"> <type uri="http://IPAddress/api/v2/processtypes/355">Cookbook Example Process</type> <date-run>2013-01-07</date-run> <technician uri="http://IPAddress/api/v2/researchers/1"> <first-name>System</first-name> <last-name>Administrator</last-name> </technician> <input-output-map> <input post-process-uri="http://IPAddress/api/v2/artifacts/ADM224A3PA1?state=8055" uri="http://IPAddress/api/v2/artifacts/ADM224A3PA1?state=8040" limsid="ADM224A3PA1" /> <output uri="http://IPAddress/api/v2/artifacts/92-13007?state=8065" output-generation-type="PerAllInputs" output-type="ResultFile" limsid="92-13007" /> </input-output-map> <input-output-map> <input post-process-uri="http://IPAddress/api/v2/artifacts/ADM224A3PA1?state=8055" uri="http://IPAddress/api/v2/artifacts/ADM224A3PA1?state=8040" limsid="ADM224A3PA1" /> <output uri="http://IPAddress/api/v2/artifacts/ADM224A3TE3?state=8054" output-generation-type="PerInput" output-type="Analyte" limsid="ADM224A3TE3" /> </input-output-map> <input-output-map> <input post-process-uri="http://IPAddress/api/v2/artifacts/ADM224A5PA1?state=8053" uri="http://IPAddress/api/v2/artifacts/ADM224A5PA1?state=8047" limsid="ADM224A5PA1" /> <output uri="http://IPAddress/api/v2/artifacts/92-13007?state=8065" output-generation-type="PerAllInputs" output-type="ResultFile" limsid="92-13007" /> </input-output-map> <input-output-map> <input post-process-uri="http://IPAddress/api/v2/artifacts/ADM224A5PA1?state=8053" uri="http://IPAddress/api/v2/artifacts/ADM224A5PA1?state=8047" limsid="ADM224A5PA1" /> <output uri="http://IPAddress/api/v2/artifacts/ADM224A5TE3?state=8060" output-generation-type="PerInput" output-type="Analyte" limsid="ADM224A5TE3" /> </input-output-map> <input-output-map> <input post-process-uri="http://IPAddress/api/v2/artifacts/ADM224A2PA1?state=8056" uri="http://IPAddress/api/v2/artifacts/ADM224A2PA1?state=8042" limsid="ADM224A2PA1" /> <output uri="http://IPAddress/api/v2/artifacts/92-13007?state=8065" output-generation-type="PerAllInputs" output-type="ResultFile" limsid="92-13007" /> </input-output-map> <input-output-map> <input post-process-uri="http://IPAddress/api/v2/artifacts/ADM224A2PA1?state=8056" uri="http://IPAddress/api/v2/artifacts/ADM224A2PA1?state=8042" limsid="ADM224A2PA1" /> <output uri="http://IPAddress/api/v2/artifacts/ADM224A2TE3?state=8059" output-generation-type="PerInput" output-type="Analyte" limsid="ADM224A2TE3" /> </input-output-map> <input-output-map> <input post-process-uri="http://IPAddress/api/v2/artifacts/ADM224A4PA1?state=8063" uri="http://IPAddress/api/v2/artifacts/ADM224A4PA1?state=8048" limsid="ADM224A4PA1" /> <output uri="http://IPAddress/api/v2/artifacts/92-13007?state=8065" output-generation-type="PerAllInputs" output-type="ResultFile" limsid="92-13007" /> </input-output-map> <input-output-map> <input post-process-uri="http://IPAddress/api/v2/artifacts/ADM224A4PA1?state=8063" uri="http://IPAddress/api/v2/artifacts/ADM224A4PA1?state=8048" limsid="ADM224A4PA1" /> <output uri="http://IPAddress/api/v2/artifacts/ADM224A4TE3?state=8057" output-generation-type="PerInput" output-type="Analyte" limsid="ADM224A4TE3" /> </input-output-map> <input-output-map> <input post-process-uri="http://IPAddress/api/v2/artifacts/ADM224A1PA1?state=8061" uri="http://IPAddress/api/v2/artifacts/ADM224A1PA1?state=8046" limsid="ADM224A1PA1" /> <output uri="http://IPAddress/api/v2/artifacts/92-13007?state=8065" output-generation-type="PerAllInputs" output-type="ResultFile" limsid="92-13007" /> </input-output-map> <input-output-map> <input post-process-uri="http://IPAddress/api/v2/artifacts/ADM224A1PA1?state=8061" uri="http://IPAddress/api/v2/artifacts/ADM224A1PA1?state=8046" limsid="ADM224A1PA1" /> <output uri="http://IPAddress/api/v2/artifacts/ADM224A1TE3?state=8058" output-generation-type="PerInput" output-type="Analyte" limsid="ADM224A1TE3" /> </input-output-map> <input-output-map> <input post-process-uri="http://IPAddress/api/v2/artifacts/ADM224A6PA1?state=8064" uri="http://IPAddress/api/v2/artifacts/ADM224A6PA1?state=8045" limsid="ADM224A6PA1" /> <output uri="http://IPAddress/api/v2/artifacts/92-13007?state=8065" output-generation-type="PerAllInputs" output-type="ResultFile" limsid="92-13007" /> </input-output-map> <input-output-map> <input post-process-uri="http://IPAddress/api/v2/artifacts/ADM224A6PA1?state=8064" uri="http://IPAddress/api/v2/artifacts/ADM224A6PA1?state=8045" limsid="ADM224A6PA1" /> <output uri="http://IPAddress/api/v2/artifacts/ADM224A6TE3?state=8062" output-generation-type="PerInput" output-type="Analyte" limsid="ADM224A6TE3" /> </input-output-map></prc:process>

Artifact state

Notice how all the input and output URIs include a ?state= some number. State allows the LIMS to track historical values for QC, volume, and concentration, so you can compare the state of an analyte before and after a process was run. However, when you make changes to an artifact you should always work with the most current state.

To ensure that you are getting the current state when you do a GET request, simply remove the state from the artifact URI.

Step 2. Map output LIMS IDs to input LIMS IDs

You can examine each input-output-map to find details about the relationship represented between inputs and outputs. The following code puts the output and input LIMS IDs into an array called outputToInputMap.

As the output type is also important for further processing, outputToInputMap is formatted as follows: outputLIMSID -> [output-type, inputLIMSID-1, inputLIMSID-2, inputLIMSID-3, ...|output-type, inputLIMSID-1, inputLIMSID-2, inputLIMSID-3, ...].

If the output is shared for all inputs (i.e., in this case, the sample measurement file with LIMS ID 92-13007), all of the inputs to the process will be listed.
If the output relates to an individual input, only the LIMS ID for that particular input will be listed.

// For each io-map in the process, add its information to outputToInputMap process.'input-output-map'.each { outputType = it.'output'[0].'@output-type' outputLIMSID = it.'output'[0].@limsid inputLIMSID = it.'input'[0].@limsid // outputToInputMap stores all the output type and LIMS IDs of all the inputs to the output if (!outputToInputMap[outputLIMSID]) { outputToInputMap[outputLIMSID] = [outputType, inputLIMSID] } else { // If entry already exists, add another input to the list outputToInputMap[outputLIMSID] << inputLIMSID }}

Key concept

Shared outputs are represented by multiple input-output-maps that have the same LIMS ID for the output.
Inputs with multiple outputs are represented by multiple input-output-maps with the same LIMS ID for the input.
Output per input relationships are represented by a single input-output-map for each input and output.

Outputs are listed in multiple input-output-map elements when they have multiple input files generating them. The first time any particular output LIMS ID is seen, the output type and input LIMS ID in the input-output-map are added to the list, stored in outputToInputMap.

If the output LIMS ID already has a list in outputToInputMap, then the code adds input LIMS ID to the list.

Step 3. Print out the list

One way to access the information is to print it out. You can run through each key-value pair and print the information it contains:

// Print the contents of the map, which stores the inputs LIMSIDs under the output's LIMSID o+tputToInputMap.each { key, value -> println "$key is a(n) ${value[0]} with input:" for (int i = 1; i < value.size(); i++) { println '\t' + value[i] } }

Expected output and results

After running the script on the command line, an output similar to the following will be generated, whereby the inputs used to generate each output are listed.

92-13007 is a(n) ResultFile with input: 27-2028 27-2029 27-2030 27-2031 27-2032 27-2033 27-2034 is a(n) Analyte with input: 27-2028 27-2035 is a(n) Analyte with input: 27-2029 27-2036 is a(n) Analyte with input: 27-2030 27-2037 is a(n) Analyte with input: 27-2031 27-2038 is a(n) Analyte with input: 27-2032 27-2039 is a(n) Analyte with input: 27-2033

Attachments

GetProcessInputOutput.groovy.txt