Updating Sample UDF Based on Analyte QC Flags

by Mark Luszniak on May 17, 2013 in Technology
Technology Image

When running through a workflow, you might want to save some data so that it can be easily viewed from a later protocol step. A simple solution is to reflect your analyte data in its parent sample. In this example, I will show you how to store an analytes QC value in a sample UDF.

The Beginning

To begin, we set up the entrance to our script.

// Define the script’s parameters

className = getClass().simpleName
def cli = new CliBuilder(usage: "groovy ${className}.groovy -i PROCESSURI -u USERNAME -p PASSWORD -udf UDFNAME")
cli.i(argName:'processURI', longOpt:'processURI', required:true, args:1, 'Process URI (Required)')
cli.u(argName:'username',   longOpt:'username',   required:true, args:1, 'LIMS username (Required)')
cli.p(argName:'password',   longOpt:'password',   required:true, args:1, 'LIMS password (Required)')
cli.udf(argName:'udfName',  longOpt:'udfName',    required:true, args:1, 'Name of the destination Sample UDF (Required)')// Check to ensure all requirements are fulfilled
def opt = cli.parse(args)
if (!opt) {

// Store your inputs into variables

processURI = opt.i
username = opt.u
password = opt.p
sampleUDFName = opt.udf

The first block of code describes what parameters this script requires in order to complete successfully. In our case, command line options -i, -u, -p and -udf are required.

The second block ensures that all of the parameters have been provided with values. It will alert the user if this is not the case and exit the script.

Finally we save the input parameters into descriptively named variables to prevent any later confusion.

Doing the Work

Before we can process our data, we must first retrieve it from the API.

// Retrieve the process

Node processNode = GLSRestApiUtils.httpGET(processURI, username, password)

// Collect the unique input URIs

def inputURIs = processNode.'input-output-map'.collect { GLSRestApiUtils.stripQuery(it.'input'[0].@uri) }.unique()

// Retrieve the artifacts

def artifacts = GLSRestApiUtils.batchGET(inputURIs, username, password)

We can retrieve the process using our processURI parameter. Then we collect the unique input URIs. Their uniqueness is important, since it is a requirement of the batchGET method.

Please note: It is important that we strip the state of the artifacts. Since the input-output maps are completed before a user can edit the QC flags, the linked state will not reflect the correct data. The stripQuery() method removes the state from the URI.

Now we can retrieve the input analytes using batchGET.

Once we have all the input analytes we can iterate through our list to process them.

// Process each artifact and save its QC status to the given sample UDF

def allSamples = []
try {
artifacts.each {

// Retrieve its sample

Node sample = GLSRestApiUtils.httpGET(it.'sample'[0].@uri, username, password)

// Process each QC flag case

switch(it.'qc-flag'[0].text()) {
case 'PASSED':
GLSRestApiUtils.setUdfValue(sample, sampleUDFName, 'True')
case 'FAILED':
GLSRestApiUtils.setUdfValue(sample, sampleUDFName, 'False')

// If no QC flag is set, throw an error to alert the user

throw new Exception("${it.'name'[0].text()}'s QC flag has not been set.")

// Add the sample to the update list

} catch (Exception error) {

// Display the error to the user and exit the script as a QC Flag is missing

println error.message

We start by defining a storage list called ‘allSamples’ to store our updated samples until we put them back into the API.

Our each loop processes the analytes. For each analyte, we retrieve its parent sample. Then, we update the UDF with the same name as given in the -udf parameter, based on the following cases:

  1. If the analyte’s QC flag is ‘Pass’, which is stored as ‘PASSED’ in the API, we set the sample UDF to ‘True’.
  2. If the analyte’s QC flag is ‘Fail’, which is stored as ‘FAILED’ in the API, we set the sample UDF to ‘False’.
  3. If the user forgets to enter a QC value for a sample, alert the user and stop the script.

The first two cases are easily performed in the switch statement using the utility method ‘setUdfValue’ to place the chosen value in the sample UDF.

The third case requires a little more work. If the user has missed a setting a QC flag, we want the script to stop and alert the user to which sample was missed. This can be solved by wrapping our each inside of a try-catch block. If the QC flag of our analyte has not been set, we will throw an exception containing the message to display.

If an analyte’s QC flag has been set, and we successfully update its sample UDF, its modified sample is added to our sample update list.

Once we have processed all the input analytes we can update their corresponding samples in the API. We do this by iterating through our list and calling httpPUT on each sample.

// Update all of the samples in the API

allSamples.each {
GLSRestApiUtils.httpPUT(it, it.@uri, username, password)
}// Define the user success message
println "Script has successfully set ${allSamples.size()} samples '${sampleUDFName}' UDF."

Finally, we print a success message to the user informing them that all of the given samples have been processed.

The above script can be downloaded here: ArtifactUDFToSampleUDF.groovy