Pool Samples with Reagent Labels

Before pooling samples in a multiplexed workflow, apply reagent labels using one of the methods described in Work with Multiplexing. After the analyte (derived sample) artifacts are labeled, they can be pooled together without loss of traceability.

Pooling samples is accomplished either by running a pooling step in the user interface, or by using the process resource in the REST API.

For an overview of how REST resources are structured, and to learn how the process resource is used to track workflow in Clarity LIMS, see REST General Concepts and Structure of REST Resources.

Prerequisites

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

  • Reagent types that are configured in Clarity LIMS and are named index 1 through index 6.

  • Reagents of type index 1 through index 6 that have been added to Clarity LIMS.

  • A compatible version of API (v2 r21 or later).

Code Example

Pooling in the User Interface

The following screenshot shows a pooling step run from Clarity LIMS.

Pooling in the API with a Process POST

Pooling samples in the API is accomplished with a process resource. Information about a step is also stored in the process resource. Such a process has many input samples that map to a shared output sample, such that the shared output is a pool of those inputs. This is achieved with Run a Process/Step, where a single input-output-map element in the XML defines the shared output and all its related inputs.

In general, automation scripts access information about a step using the processURI, which links to the individual process resource. The input-output-map in the XML returned by the individual process resource gives the script access to the artifacts that were inputs and outputs to the process.

Information about a derived sample is stored in the analyte resource. This is used as the input and output of a step, and also used to record specific details from lab processing. The XML representation for an individual analyte contains a link to the URI of its submitted sample, and to the URI of the process that generated it (parent process).

The following example pools all samples found in a given container into a tube it creates.

NOTE: No special code is required to handle reagent labels. As processes execute, reagent labels automatically flow from inputs to outputs.

// Create the required URIs
containerToPoolUri = "http://${hostname}/api/v2/containers/${containerLIMSID}"
researcherURI = "http://${hostname}/api/v2/researchers/1"
 
// Find the artifacts to pool in the given container
containerToPool = GLSRestApiUtils.httpGET(containerToPoolUri, username, password)
artifactURIsToPool = containerToPool.'placement'.@uri
 
def builder = new StreamingMarkupBuilder()
builder.encoding = "UTF-8"
 
// Create a new container using the Markup Builder
def containerDoc = builder.bind {
    mkp.xmlDeclaration()
    mkp.declareNamespace(con: 'http://genologics.com/ri/container')
    mkp.declareNamespace(udf: 'http://genologics.com/ri/userdefined')
    'con:container'{
        'name'("Pooled contents from ${containerToPool.name.text()}")
        'type'(uri:"http://${hostname}/api/v2/containertypes/2", name:"Tube")
    }
}
// Post the new container to the API
containerNode = GLSRestApiUtils.xmlStringToNode(containerDoc.toString())
container = GLSRestApiUtils.httpPOST(containerNode, "http://${hostname}/api/v2/containers", username, password)
 
 
// Create a new Pool Samples process using the StreamingMarkupBuilder
processDoc = new StreamingMarkupBuilder().bind {
    mkp.declareNamespace(prx: 'http://genologics.com/ri/processexecution')
    'prx:process'{
        'type'('Pool Samples')
        'technician'(uri:researcherURI)
        'input-output-map'(shared:'true') {
            artifactURIsToPool.each { 'input'(uri:it) }
            'output'(type:'Analyte') {
                'location' {
                    'container'(uri:container.@uri)
                    'value'('1:1')
                }
            }
        }
    }
}
// Post the Pool Samples process to the API
processNode = GLSRestApiUtils.xmlStringToNode(processDoc.toString())
returnNode = GLSRestApiUtils.httpPOST(processNode, "http://${hostname}/api/v2/processes", username, password)
println GLSRestApiUtils.nodeToXmlString(returnNode)

Verify with the REST API

Irrespective of whether you use the user interface or the REST API to pool samples, the pooled sample is available via process GET requests.

The following example shows one pooled output (LIMS ID 2-424) created from three inputs - LIMS IDs RCY1A103PA1, RCY1A104PA1, and RCY1A105PA1:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<prc:process xmlns:udf="http://genologics.com/ri/userdefined"
    xmlns:file="http://genologics.com/ri/file" xmlns:prc="http://genologics.com/ri/process"
    uri="http://yourIPaddress/api/v2/processes/PSA-RCX-110812-122-221"
    limsid="PSA-RCX-110812-122-221">
    <type uri="http://yourIPaddress/api/v2/processtypes/37">Pool Samples</type>
    <date-run>2011-08-12</date-run>
    <technician uri="http://yourIPaddress/api/v2/researchers/4">
        <first-name>RC</first-name>
        <last-name>RC</last-name>
    </technician>
    <input-output-map>
        <input post-process-uri="http://yourIPaddress/api/v2/artifacts/RCY1A104PA1?state=319"
            uri="http://yourIPaddress/api/v2/artifacts/RCY1A104PA1?state=315"
            limsid="RCY1A104PA1" />
        <output uri="http://yourIPaddress/api/v2/artifacts/2-424?state=316"
            output-generation-type="PerAllInputs" output-type="Sample" limsid="2-424" />
    </input-output-map>
    <input-output-map>
        <input post-process-uri="http://yourIPaddress/api/v2/artifacts/RCY1A105PA1?state=317"
            uri="http://yourIPaddress/api/v2/artifacts/RCY1A105PA1?state=314"
            limsid="RCY1A105PA1" />
        <output uri="http://yourIPaddress/api/v2/artifacts/2-424?state=316"
            output-generation-type="PerAllInputs" output-type="Sample" limsid="2-424" />
    </input-output-map>
    <input-output-map>
        <input post-process-uri="http://yourIPaddress/api/v2/artifacts/RCY1A103PA1?state=318"
            uri="http://yourIPaddress/api/v2/artifacts/RCY1A103PA1?state=310"
            limsid="RCY1A103PA1" />
        <output uri="http://yourIPaddress/api/v2/artifacts/2-424?state=316"
            output-generation-type="PerAllInputs" output-type="Sample" limsid="2-424" />
    </input-output-map>
</prc:process>
 

Besides deriving from the ancestral sample artifacts, the resulting pooled sample artifact inherits the reagent labels from all inputs. The pooled output produced by the pooling step appears as follows. The pooled artifact shows multiple reagent labels, and multiple ancestor samples.

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<art:artifact xmlns:udf="http://genologics.com/ri/userdefined"
    xmlns:file="http://genologics.com/ri/file" xmlns:art="http://genologics.com/ri/artifact"
    uri="http://yourIPaddress/api/v2/artifacts/2-424?state=316" limsid="2-424">
    <name>Pool of SAM-1 - Index 1 + SAM-2 - Index 2 + SAM-3 - Index 3</name>
    <type>Analyte</type>
    <output-type>Sample</output-type>
    <parent-process
        uri="http://yourIPaddress/api/v2/processes/PSA-RCX-110812-122-221"
        limsid="PSA-RCX-110812-122-221" />
    <volume unit="uL">0.0</volume>
    <qc-flag>UNKNOWN</qc-flag>
    <location>
        <container uri="http://yourIPaddress/api/v2/containers/27-16"
            limsid="27-16" />
        <value>1:1</value>
    </location>
    <working-flag>true</working-flag>
    <sample uri="http://yourIPaddress/api/v2/samples/RCY1A104"
        limsid="RCY1A104" />
    <sample uri="http://yourIPaddress/api/v2/samples/RCY1A105"
        limsid="RCY1A105" />
    <sample uri="http://yourIPaddress/api/v2/samples/RCY1A103"
        limsid="RCY1A103" />
    <reagent-label name="Index 1" />
    <reagent-label name="Index 2" />
    <reagent-label name="Index 3" />
</art:artifact> 

As processes are executed, reagent labels flow from inputs to outputs.

Attachments

PoolingSamplesWithReagents.groovy:

Last updated