arrow-left

All pages
gitbookPowered by GitBook
1 of 1

Loading...

Assigning Samples to New Workflows

It is sometimes necessary to assign a sample to a new workflow from within another workflow.

You can do this in the BaseSpace Clarity LIMS Operations Interface, by manually adding the sample to the desired workflow. However, it is also possible to perform this action through the API.

hashtag
Solution

This example shows how to use the API to automate the addition of samples to a specified workflow, based on a UDF value.

  • The script can be run off any protocol step whose underlying process is configured with Analyte inputs and a single per-input ResultFile output.

  • The process may have any number of per-all-input ResultFile outputs, as they will be ignored by the script.

  • A Result File UDF, named Validate, will control which samples will be added to the specified workflow.

hashtag
Parameters

The script accepts the following parameters:

-i
The limsid of the process invoking the script (Required)
The {processLuid} token

hashtag
Step 1: Create Result File UDF

Before the example script can be used, first create the ResultFile's Validate UDF in the Operations Interface. This is a single-line text UDF with preset values of 'Yes' and 'No'.

hashtag
Step 2: Create and Configure Process Type

Also in the Operations Interface, create a new process type named Cookbook Workflow Addition.

This process type must:

  • Have Analyte inputs.

  • Have a single per-input ResultFile output.

  • Apply the Validate UDF on its ResultFile outputs.

hashtag
Step 3: Configure an EPP call on this process type as follows:

hashtag
Step 4: Modify the file paths to suit your server's Groovy installation.

hashtag
Step 3: Create Protocol

Once the process type is created, in the Clarity LIMS Web Interface, create a protocol named Cookbook Workflow Addition Protocol.

This protocol should have one the protocol step - Cookbook Workflow Addition.

hashtag
Step 6: Configure EPP

Configure the EPP script to automatically initiate at the end of the Cookbook Workflow Addition step:

hashtag
Step 7: Create workflows

To finish configuration, create two workflows:

  • Destination Workflow: THis workflow should contain the DNA Initial QC protocol only.

  • Sending Workflow: This workflow should contain the new Cookbook Workflow Addition Protocol.

hashtag

hashtag
About the code

Once the script has processed the input parameters and ensured that all the required information is available, we can start processing the samples to determine if they should be assigned to the new workflow.

  1. To begin, we retrieve the process from the API. This gives us access to the input-output maps of the process. These will be used to determine which ResultFiles we will examine.

  2. Next, we retrieve the protocol step action list. This contains a list of the input analytes' URIs and their next steps.

  3. We then search this list for and collect all analyte URIs whose next action has been set to Mark as protocol complete.

hashtag
User Interaction

  1. Assuming samples have been placed in the Switching Workflow, the user proceeds as normal through the protocol step.

  2. In the Record Details screen, the user enters Validate values in the ResultFile UDFs.

  3. The user then proceeds to the Assign Next Steps screen, provides a variety of Next Steps, and completes the protocol step.

hashtag
Assumptions and Notes

  • The attached file is placed on the Clarity LIMS server, in the /opt/gls/clarity/customextensions folder.

  • GLSRestApiUtils.groovy is placed in the Groovy lib folder.

  • The required configuration has been set up, as described in Configuration.

hashtag
Attachments

SwitchingWorkflows.groovy:

Next, we gather the per-input ResultFile input-output maps. We can collect the ResultFile URIs of those related to the analytes who have been marked as complete. NOTE: It is important that we strip any extra state information from the URIs. The URIs found in the next action list do not contain any state information and, when compared against a non-stripped URI, will return 'false'.

  • Once we have the ResultFile URIs, we can retrieve them with batchGET. It is important that the list contains unique URIs, as the batchGET will fail otherwise.

  • After we have retrieved the ResultFiles, we can iterate through the list, adding the parent sample's URI to our list of sample URIs if the ResultFile's Validate UDF is set to Yes. We also increment a counter which will allow us to report to the user how many samples were assigned to the new workflow.

  • Since we don't assign samples themselves to workflows, we first need to retrieve the samples' derived artifacts. We can do this by iterating through each sample URI, retrieving it, and adding its artifact's URI to a list.

  • Before we can add the artifacts to the workflow, we need to determine the destination workflow's URI. By retrieving a list of all the workflows in the system, we can find the one that matches our input workflow name.

  • Assigning artifacts to workflows requires the posting of a routing command to the routing endpoint.

    • We first generate the required XML by using a Streaming Markup Builder.

    • We then dynamically build our XML by looping inside of the markup declaration. // Create a new routing assignment using the Markup Builder

  • To create our routing command, we pass the workflow URI and the artifact URIs that we wish to assign to the workflow to a method containing the above code. This will generate the required node.

  • We then perform an httpPOST to the routing endpoint to perform the action.

  • Finally, we define our success message to the user. This will allow us to inform the user of the results of the script.

  • A message displays, alerting the user of the execution of a custom script.

  • When the script completes, a success message displays and the samples are added to the specified workflow.

  • The example code is provided for illustrative purposes only. It does not contain sufficient exception handling for use 'as is' in a production environment.

    -s

    The URI of the step that launches the script (Required)

    The {stepURI:v2:http} token (in the form http://<YourIP>/api/v2/steps/<ProtocolStepLimsid>)

    -u

    The username of the current user (Required)

    The {username} token

    -p

    The password of the current user (Required)

    The {password} token

    -w

    The name of the destination workflow (Required)

    file-download
    7KB
    SwitchingWorkflows.groovy
    arrow-up-right-from-squareOpen
    Assigning_samples_to_workflows_ResultFileUDF.png
    Assigning_samples_to_workflows_Protocol.png
    Assigning_samples_to_workflows_protEpp.png

    The {workflow} token

    // Gather the PerInput ResultFile mappings
    def inputOutputMaps = process.'input-output-map'.findAll { it.'output'[0].@'output-generation-type' == PER_INPUT }
             
    // Determine which ResultFiles to examine and retrieve them
    def resultFilesURIs = inputOutputMaps.findAll { completedAnalyteURIs.contains(GLSRestApiUtils.stripQuery(it.'input'[0].@uri)) }.collect { it.'output'[0].@uri }.unique()
    def resultFiles = GLSRestApiUtils.batchGET(resultFilesURIs, username, password)
    // Determine which artifacts should be assigned
    List sampleURIs = []
    resultFiles.each {
        if(it.'udf:field'.find { VALIDATION_UDF == it.@name }.value()[0] == YES) {
            sampleURIs.add(it.'sample'[0].@uri)
            switched++
        }
    }
    // Gather the sample artifacts URIs
    List artifactsToAssignURIs = []
    sampleURIs.each {
        Node sample = GLSRestApiUtils.httpGET(it, username, password)
        artifactsToAssignURIs.add(sample.'artifact'[0].@uri)
    }
    // Retrieve workflow URI
    def workflowList = GLSRestApiUtils.httpGET(baseURI + '/configuration/workflows', username, password)
    String workflowURI = workflowList.find { it.@name == workflow }.@uri
    
    def assignmentOrder = builder.bind {
        mkp.xmlDeclaration()
        mkp.declareNamespace(rt: 'http://genologics.com/ri/routing')
        'rt:routing' {
            if(artifactURIsToNewWorkflow.size() != 0) {
                'assign'('workflow-uri': workflowURI) {
                    artifactURIsToNewWorkflow.each {
                        'artifact'(uri: it)
                    }
                }
            }
        }
    }
     
    return GLSRestApiUtils.xmlStringToNode(assignmentOrder.toString())
    // Create and post the assignment
    Node assignmentNode = createAssignmentNode(workflowURI, artifactsToAssignURIs)
    GLSRestApiUtils.httpPOST(assignmentNode, baseURI + '/route/artifacts/', username, password)  
    // Define the success message to the user
    outputMessage = "Script has completed successfully.${LINE_TERMINATOR}" +
        "${switched} samples were assigned to the '${workflow}' workflow.${LINE_TERMINATOR}" +
        "You can find them queued in the 'DNA Initial QC' protocol."
    bash -c "/opt/gls/groovy/current/bin/groovy -cp /opt/groovy/lib /opt/gls/clarity/customextensions/SwitchingWorkflows.groovy -u {username} -p {password} -s {stepURI:v2:http} -i {processURI:v2:http} -w 'Destination Workflow'"
    // Retrieve the process
    def process = GLSRestApiUtils.httpGET(processURI, username, password)
             
    // Retrieve the analytes which have been set to complete
    def actionsList = GLSRestApiUtils.httpGET(stepURI + '/actions', username, password)
    def completedAnalyteURIs = actionsList.'next-actions'.'next-action'.findAll { it.@action == COMPLETE }.collect { it.@'artifact-uri' }
    Assigning_samples_to_workflows_Send.png
    Assigning_samples_to_workflows_Inputs.png
    Assigning_samples_to_workflows_Message.png