Rearray Samples

In high throughput labs, samples are worked on in batches and some work is executed by a robot. Sometimes, a set of plates must be rearrayed to one larger plate before the robot can begin the lab step.

This example accomplishes this using two scripts. One script is configured on a derived sample automation, while the second script is included in a command line configured on a step automation.

Prerequisites

Before you follow the example, make sure that you have the following items:

  • A project containing samples assigned to a workflow in Clarity LIMS.

  • The workflow name.

  • Given samples are assigned to the same workflow stage.

Code Example

This example demonstrates the following scripts:

  • AssignToRearrayWf.groovy—Executed as a derived sample automation, this script assigns selected samples to the rearray step.

  • AssignToLastRemoved.groovy—Executed after the rearray step, this script assigns the samples to the stage to which they were originally assigned. The script is included in a command line configured on a step automation.

Configure the Assign To Rearray Automation

  1. In Clarity LIMS, under Configuration, select the Automation tab.

  2. Select the Derived Sample Automation tab.

  3. Select New Automation and create an automation that prompts the user for the workflow stage name to be used.

In the example, note the following:

  • The {groovy_bin_location} and {script_location} parameters must be customized to reflect the locations on your computer.

  • The –w option allows for user input to be passed to the script as a command-line variable.

AssignToRearrayWf Script Methods

Step 1. Retrieve the Artifact Nodes Using the Artifact LIMS IDs

The AssignToRearrayWf script has a list of artifact (sample) LIMS IDs given on the command line. To begin, use this script to build a list of artifact nodes.

The following code example builds a list of artifact URIs using the artifact LIMS ID list and the getArtifactNodes function. The resulting artifact URI list can then be used for a batchGET call to return the artifact nodes.

def getArtifactNodes(artifactList, hostname, username, password) {
    artifactURIList = artifactList.collect{"${hostname}v2/artifacts/${it}"}
    return GLSRestApiUtils.batchGET(artifactURIList, username, password)

Step 2. Retrieve Workflow Name and URI

In this example, you can assume that the workflow name is known by the user and is passed to the script by user input when the automation is initiated.

The workflow can then be queried for using the passed workflow name. The workflow name is first encoded, and from this, you can retrieve the workflow URI.

encodedWorkflowName = URLEncoder.encode(workflowName, "UTF-8")
workflowURI = GLSRestApiUtils.httpGET("${hostname}v2/configuration/workflows?name=${encodedWorkflowName}", username, password)?.workflow?.getAt(0)?.@uri

Step 3. Make Sure that the Samples Belong to the Same Workflow Stage

For the samples to be placed in the same container, they must all belong to the same workflow and be currently queued to the same stage in that workflow.

Using the workflow name passed in by the user, do the following:

  1. Search the workflow stage list of the first artifact and store the URI of the most recent stage that is part of the workflow, if it is queued. Otherwise, the script exits with an error message.

  2. After storing the workflow stage URI of the first artifact, use the checkMatch function check against the remaining artifacts in the list to verify they are all currently queued to the same stage.

If all artifacts are queued for the stage, they are removed from the queue of the stage under the lastWfStageURI function.

def checkMatch (artifactNodeList, workflowURI, username, password) {
    def lastWfStageURI
    def valid = false
    firstArtifactStageList = artifactNodeList[0].'workflow-stages'.'workflow-stage'
    for (i = 0; i < firstArtifactStageList.size(); i++) {
        if (firstArtifactStageList[i].@status.toString().equals('QUEUED')) {
            stageWfURI = GLSRestApiUtils.httpGET(firstArtifactStageList[i].@uri, username, password)?.workflow?.@uri[0].toString()
            if (stageWfURI.equals(workflowURI.toString())) {
                valid = true
                lastWfStageURI = firstArtifactStageList[i].@uri
                if (firstArtifactStageList[i+1]?.@status.toString().equals('REMOVED')) {
                    valid = false
                }
            }
        }
    }
    if (!valid) {
        println "artifact " + artifactNodeList[0].name.text() + " is not currently queued to this workflow"
        System.exit(-1)
    }
    for (i = 1; i < artifactNodeList.size(); i++) {
        valid = false
        artifactNodeList[i].'workflow-stages'.'workflow-stage'.each {
            if (it.@uri.toString().equals(lastWfStageURI.toString())) {
                if (it.@status.toString().equals('QUEUED')) {
                    valid = true
                } else {
                    valid = false
                }
            }
        }
        if (!valid) {
            println "Artifact " + artifactNodeList[i].name.text() + " is not currently queued to this workflow"
            System.exit(-1)
        }
    }  

Step 4. Build the XML for stage assignment using Streaming Markup Builder

In this example, all the artifacts are unassigned from the previous workflow stage returned and assigned to the rearray stage using the queuePlacementStep function. The previous methods have verified that the artifacts in the list can be rearrayed together.

def queuePlacementStep (artifactNodeList, unassignStageURI, workflowToAssign) {
    def builder = new StreamingMarkupBuilder()
    builder.encoding = "UTF-8"
    def placementStepAssignment = builder.bind {
        mkp.xmlDeclaration()
        mkp.declareNamespace(rt: 'http://genologics.com/ri/routing')
        'rt:routing' {
            'unassign'('stage-uri': unassignStageURI) {
                artifactNodeList.each { artifactNode ->
                    'artifact'(uri: artifactNode.@uri)
                }
            }
            'assign'('workflow-uri': workflowToAssign) {
                artifactNodeList.each { artifactNode ->
                    'artifact'(uri: artifactNode.@uri)
                }
            }
        }
    }
    return GLSRestApiUtils.xmlStringToNode(placementStepAssignment.toString())
}

The returned XML node is then posted using httpPOST.

Step 2. Configuring Placement Workflow, Protocol, and Step

  1. In Clarity LIMS, under Configuration, select the Lab Work tab.

  2. Create a master step of Standard step type.

  3. From Configuration, select the Automation tab.

  4. Select the Step Automation tab.

  5. Create an automation for the AssignToLastRemoved.groovy script.

    The {groovy_bin_location} and {script_location} parameters must be customized to reflect the locations on your computer.

  6. Enable the automation on the master step you created in step 2.

  7. Configure a new protocol and step as follows.

    • On the Lab Work tab, create a non-QC protocol.

    • In the Protocols list, select the new protocol and then add a new step to it. Base the new step on the master step you created in step 2.

    • On the Step Settings form, in the Automation section, you see the step automation you configured. Configure the automation triggers as follows.

      • Trigger Location—Step

      • Trigger Style—Automatic upon exit

    • On the Placement milestone, Add 96 well plate and 384 well plate as the permitted destination container types for the step.

    • Remove the default Tube container type.

    • Save the step.

  8. Configure a new workflow as follows:

    • On the Lab Work tab, create a workflow.

    • Add the protocol you created to the workflow.

AssignToLastRemovedStage Script Methods

Step 1. Build List of Artifact Nodes from the Step Input-Output Map

The first step of AssignToLastRemovedStage script is the same as for the AssignToRearrayWf script: return the artifact node list.

However, in this script, you are not directly given the artifact LIMS IDs. Instead, because you receive the step URI from the process parameter command line, you can collect the artifact URIs from the inputs of the step details input-output map using the getArtifactNodes function.

An example step details URI might be {hostname}/api/v2/steps/{stepLIMSID}/details.

def getArtifactNodes (stepDetails, username, password) {
    artifactURIList = GLSRestApiUtils.httpGET(stepDetails, username, password)\
        .'input-output-maps'.'input-output-map'.collect{it.input.@uri[0]}.toSet()
    return GLSRestApiUtils.batchGET(artifactURIList, username, password)

Step 2. Assign Artifacts Back to the Original Stage

Each artifact in the list was removed from this stage before going through the rearray step.

With this in mind, and because the Clarity LIMS API stores artifact history by time (including stage history), the stage to which you now want to assign the samples to be the second-to-last stage in the workflow-stage list.

The following method finds the stage from which the artifacts were removed using the getLastRemoved function:

def getLastRemoved (artifactNodeList) {
    def stageList = artifactNodeList[0].'workflow-stages'.'workflow-stage'
    stageToQueue = (stageList[(stageList.size()) - 2].@status.toString().equals('REMOVED')) ? stageList[(stageList.size()) - 2].@uri : null 

Step 3. Make Sure that Artifacts are Assigned to the Same Stage

You can then check to make sure all artifacts originated in this stage. This helps you avoid the scenario where the AssignToRearrayStage.groovy script was run on two groups of artifacts queried while in different workflow stages.

if (!stageToQueue) {
        println "Failed to requeue, ${artifactNodeList[0].name.text()} may have been assigned to a new workflow"
        System.exit(-1)
    } else {
        artifactNodeList.each {
            nodeStageList = it.'workflow-stages'.'workflow-stage'
            lastRemoved = nodeStageList[(nodeStageList.size() -2)].@status.toString().equals('REMOVED') ? nodeStageList[(nodeStageList.size()) -2].@uri : null
            if (!lastRemoved.toString().equals(stageToQueue.toString())) {
                println "Sample ${it.name.text()} started in a separate stage, verify all samples are being arrayed for the same workflow"
                System.exit(-1)
            }
        }
    } 

Step 4. Build the XML to Assign the Samples Back to the Returned Stage

Function: assignStage

This returned stage URI is then used to build the assignment XML to assign all the samples back to this stage with the assignStage function.

def assignStage (artifactNodeList, assignStageURI) {
    def builder = new StreamingMarkupBuilder()
    builder.encoding = "UTF-8"
    def assignmentXML = builder.bind {
        mkp.xmlDeclaration()
        mkp.declareNamespace(rt: 'http://genologics.com/ri/routing')
        'rt:routing' {
            'assign'('stage-uri': assignStageURI) {
                artifactNodeList.each { artifactNode ->
                    'artifact'(uri: artifactNode.@uri)
                }
            }
        }
    }
    return GLSRestApiUtils.xmlStringToNode(assignmentXML.toString())

After posting this XML node, the samples are assigned back to the stage in which they began.

Step 3. Running the Assign to Rearray Automation

  1. In the Projects Dashboard, select the samples to be rearrayed and run the 'Assign to Rearray' automation.

    On automation trigger, the {userinput} phrase will invoke a dialog that prompts for the full name of the workflow.

Step 4. Placing the Samples and Running the Rearray Step

  1. In Clarity LIMS, under Lab View, select the protocol you created in Step 2. Configuring Placement Workflow, Protocol, and Step.

    The samples assigned by the Assign to Rearray automation is available to assign to a new container.

  2. Add the samples to the Ice Bucket and begin work.

  3. The placement screen opens, allowing you to place the samples into the new container, in your desired placement pattern.

  4. Proceed to the Record Details screen, then on to Next Steps. Do not perform any actions on these screens.

  5. In the next step drop-down list, select Mark Protocol as Complete and select Apply.

  6. Selec Next. This initiates the 'Assign to last removed' trigger, which assigns the samples back to the step from which they were removed.

Attachments

AssignToRearrayWf.groovy:

AssignToLastRemoved.groovy:

Last updated