Automated Removal of Controls from a Workflow
At times, control samples in the lab need only be used in a portion of a workflow. For example, E. coli genomic DNA is often prepared alongside samples in Library Preparation protocols and then validated during a Library Validation QC protocol to confirm that nothing went wrong during Library Preparation.
Because the utility of such a control sample is short-lived, there is no need to spend sequencing effort on it. In this scenario, it is advantageous to prevent control samples from advancing in the workflow automatically.
This can be accomplished through the API by implementing an EPP/automation script that removes the control at the end of a step. This example shows how to automate the removal of control samples at the end of a step and remove them from workflows. You can use this method on any step configured to generate individual derived sample (analyte) or ResultFile (measurement) outputs. The step can have any number of per-all-input result file (shared file) outputs, as they will be ignored by the script.
In the API, an artifact is an item generated by an earlier step. There are two types of artifacts: analyte (derived sample) and resultfile (measurement). In the Clarity LIMS web interface, the terms artifact, analyte, and resultfile have been replaced with derived sample or measurement. However, some areas of the Operations Interface (in Clarity LIMS v4.2 and earlier) still refer to the former terms.

Before you follow the example, make sure that you have done the following actions:
• | You have GLSRestApiUtils.groovy in your Groovy lib folder. |
• | You have downloaded the ControlSampleRemoval.groovy file and have placed it in /opt/gls/clarity/customextensions/. |
• | You have completed the required configuration steps. |

Before you can use this example script, you will must complete the following configuration steps.

1. | In the Clarity LIMS Operations Interface, create a process type named Cookbook Control Removal. |
The process can have any combination of inputs, and any number of outputs.
2. | On the new process type, on the External Programs tab, configure a process parameter named Remove Controls. |
3. | In the Command Line Call field, enter the following example code. |
Modifying the file paths for the Groovy installation on your server.
bash -c "/opt/gls/groovy/current/bin/groovy -cp /opt/groovy/current/lib /opt/gls/clarity/customextensions/cookbook_examples/ControlSampleRemoval.groovy -u {username} -p {password} -s {stepURI:v2:http}"
4. | In the Clarity LIMS Web Interface, on the Configuration screen, create a protocol named Cookbook Control Removal Protocol. |
This protocol should have the Cookbook Control Removal process type as its only step.
5. | On the Reagents and Controls screen, enable one or more control samples on the Cookbook Control Removal step. |
6. | Configure the Cookbook Control Removal step. On the Automation tab, configure the trigger timing such that the script is initiated automatically at the end of the step. ![]() |
7. | From Configuration, create a workflow named Cookbook Control Removal Workflow. This workflow should contain the Cookbook Control Removal Protocol. |
You can add the script to any step in any workflow, and you do not need to create a separate step to run it. For this example, it can also be beneficial to add a second step (any type) after this removal step to make sure that the controls were removed.

Complete the following steps in the Clarity LIMS Configuration area.
1. | On the Lab Work tab, create a master step named Cookbook Control Removal. |
The master step can be of any type that generates derived samples or measurements. It can generate any number of derived sample or measurement outputs.
2. | On the Lab Work tab, create a protocol named Cookbook Control Removal Protocol. |
3. | Add a new Cookbook Control Removal step to the protocol based on the Cookbook Control Removal master step. ![]() |
4. | On the Automation tab, configure a step automation and name the automation Remove Controls. |
5. | In the Command Line field, enter the following code example. |
Modifying the file paths for the Groovy installation on your server.
bash -c "/opt/gls/groovy/current/bin/groovy -cp /opt/groovy/current/lib /opt/gls/clarity/customextensions/cookbook_examples/ControlSampleRemoval.groovy -u {username} -p {password} -s {stepURI:v2:http}"
6. | Enable the automation on the Cookbook Control Removal master step. |
You can now configure the automation trigger on the step or the master step. If you configure the trigger on the master step, the settings are locked on all steps derived from the master step.
7. | On the Lab Work tab, select the master step or step. |
8. | On the Master Step Settings or Step Settings form, in the Automation section, configure the automation trigger as follows so that the script is initiated automatically at the end of the step. |
• | Trigger Location—Step |
• | Trigger Style—Automatic upon exit |
• | From Consumables, select the Control Samples tab. |
• | In the Control Samples tab, enable one or more control samples on the Cookbook Control Removal step. |
9. | On the Lab Work tab, create a workflow named Cookbook Control Removal Workflow. |
This workflow should contain the Cookbook Control Removal Protocol. You can add the script to any step in any workflow, and you do not need to create a separate step to run it.
For this example, it can also be beneficial to add a second step (any type) after this removal step to make sure that the controls were removed.

The following table defines the three parameters/tokens used by the script. As of Clarity LIMS v5.0, the term command-line parameter has been replaced with token.
Parameter/Token |
Definition |
---|---|
-s {stepURI} |
This is the protocol step URI in the http://<YourIP>/api/v2/steps/<ProtocolStepLimsid> format. |
-u {username} |
This is the Clarity LIMS username. It is required. |
-p {password} |
This is the Clarity LIMS password. It is required. |
After the script has processed the parameters / tokens and ensured that all the required information is available, it can begin to process the samples to determine if they should be removed.

To begin, retrieve the list of permitted actions for the step from the API. This contains a list of the URIs for the input analytes and their next steps.
You can use this information to get the URI of the current step, which allows you to obtain the information for the step itself.
// Retrieve the next steps and protocol step informationdef actionsList = GLSRestApiUtils.httpGET(stepURI + '/actions', username, password)def currentProtocolStepURI = actionsList.'configuration'[0].@uridef currentProtocolStep = GLSRestApiUtils.httpGET(currentProtocolStepURI, username, password)

Next, look at the possible next steps that can be used in this step. In doing so, you are able to collect the next-step-uri values that are associated with the next step names within the NEXT_STEPS map.
In this case, you are looking for the URI associated with the Remove from workflow option.
// Determine the uris of the desired next stepscurrentProtocolStep.'transitions'.'transition'.each { if(NEXT_STEPS.containsKey(it.@name)) { NEXT_STEPS[it.@name] = it.@'next-step-uri' }}

After you have retrieved the URIs for the desired next steps, you can iterate through the actions list checking artifacts to see if they are controls. If the artifact associated with any next action is a control, change the next action of the artifact to be the removal next step URI you retrieved previously.
// Feedback variableint controlSamples = 0// Collect and batchGet to retrieve a list of artifacts that are at the end of stepdef artifactList = GLSRestApiUtils.batchGET(actionsList.'next-actions'.'next-action'.collect { it.@'artifact-uri' }, username, password)// Single out the artifacts that belong to controlsdef controlList = artifactList.findAll{it.'control-type'.@'uri'}// Convert the artifact list of removals to just the stripped down URIsdef removalList = controlList.collect { it.@'uri'.split(/\?/)[0] }// Go through the original action list (what we need to put) and modify// next steps if their artifact URI is in the removal listactionsList.'next-actions'.'next-action'.each { if(removalList.contains(it.@'artifact-uri')){ controlSamples++ it.@'action' = 'remove' it.@'step-uri' = NEXT_STEPS[REMOVAL_STEP] }}

Finally, send the change for the next step information to the desired endpoint and then define our success message to the user. The message allows you to inform the user of the results of the script.
// Update the next steps in the APIGLSRestApiUtils.httpPUT(actionsList, stepURI + '/actions', username, password)// Define the success message to the useroutputMessage = "Script has completed successfully.${LINE_TERMINATOR}" + "${controlSamples} controls were removed and ${samples} were not removed from the workflow(s)."

Assuming samples and a control sample have been placed in the Cookbook Control Removal Workflow Ice Bucket, you can proceed as normal through the step.
a. | On the Assign Next Steps screen, provide various Next Step values, if desired. |
b. | Proceed with the completion of the step. A message box displays, alerting you to the execution of a custom script. |
c. | When the script completes, a success message displays and the controls have been removed from the workflow. |