Each sample in a Sample Type must have a unique name/id. If your data does not already contain unique identifiers for each row, the system can generate them upon import using a Naming Pattern (previously referred to as a name expression) as part of the Sample Type definition.

Overview and Basic Examples

Administrators can customize how sample IDs are generated using templates that build a unique name from syntax elements including:

  • String constants
  • Incrementing numbers
  • Dates and partial dates
  • Values from the imported data file, such as tissue types, lab names, subject ids, etc.
For example, this simple naming pattern uses a string constant 'S', a dash, and an incrementing number:
S-${genId}

...to generate sample IDs:

S-1
S-2
S-3
and so on...

This example builds a sample ID from values in the imported data file, and trusts that the combination of these column values is always unique in order to keep sample IDs unique:

${ParticipantId}_${DrawDate}_${PortionNumber}

...which might generate IDs like:

123456_2021-2-28_1
123456_2021-2-28_2
123456_2021-2-28_3

Naming Pattern Elements/Tokens

Naming patterns can incorporate the following elements. When surrounded by ${ } syntax, they will be substituted during sample creation; most can also accommodate various formatting options detailed below.

Name ElementDescriptionScope0000000000000000000000000
genIdAn incrementing number starting from 1. This counter is specific to the individual Sample Type or Data Class.Current Sample Type / Data Class
nowThe current date, which you can format using string formatters.Current Sample Type / Data Class
<SomeDataColumn>Loads data from some field in the data being imported. For example, if the data being imported has a column named "SampleType", use the element/token "${SampleType}"Current Sample Type / Data Class
dailySampleCountAn incrementing counter, starting with the integer '1', that resets each day.All Sample Types / Data Classes in the current folder
weeklySampleCountAn incrementing counter, starting with the integer '1', that resets each week.All Sample Types / Data Classes in the current folder
monthlySampleCountAn incrementing counter, starting with the integer '1', that resets each month.All Sample Types / Data Classes in the current folder
yearlySampleCountAn incrementing counter, starting with the integer '1', that resets each year.All Sample Types / Data Classes in the current folder
randomIdA four digit random number for each sample row. Note that this random number is not guaranteed to be unique.Current Sample Type / Data Class
batchRandomIdA four digit random number applied to the entire set of incoming sample records. On each import event, this random batch number will be regenerated.Current Sample Type / Data Class
InputsA collection of all DataInputs and MaterialInputs for the current sample. You can concatenate using one or more values from the collection.Current Sample Type / Data Class
DataInputsA collection of all DataInputs for the current sample. You can concatenate using one or more values from the collection.Current Sample Type / Data Class
MaterialInputsA collection of all MaterialInputs for the current sample. You can concatenate using one or more values from the collection.Current Sample Type / Data Class

Format Number Values

You can use formatting syntax to control how the tokens are added. For example, "${genId}" generates an incrementing counter 1, 2, 3. If you use a format like the following, the incrementing counter will have three digits: 001, 002, 003.

${genId:number('000')}

Learn more about formatting numbers and date/time values in this topic: Date and Number Formats Reference

Include Default Values

When you are using a data column in your string expression, you can specify a default to use if no value is provided. Use the defaultValue string modifier with the following syntax. The 'value' argument provided must be a String in ' single straight quotes. Double quotes or curly quotes will cause an error during sample creation.

${ColumnName:defaultValue('value')}

Use String Modifiers

Most naming pattern elements can be modified with string modifiers, including but not limited to:

  • :date - Use only the date portion of a datetime value.
  • :date('yy-MM-dd') - Use only the date portion of a datetime value and format it with the given format.
  • :suffix('-') - Apply the suffix shown in the argument if the value is not null.
  • :join('_') - Combine a collection of values with the given argument as separator.
  • :first - Use the first of a series of values.
The supported options are described in this topic: Some string modifier examples:

Name Expression00000000000000000000000000000000000000000000000Example Output000000000000000000Description
S-${Column1}-${now:date}-${batchRandomId}S-Blood-20170103-9001 
S-${Column1:suffix('-')}${Column2:suffix('-')}${batchRandomId}S-Blood-PT101-5862 
${Column1:defaultValue('S')}-${now:date('yy-MM-dd')}-${randomId}Blood-17-01-03-2370
S-17-01-03-1166
${Column1:defaultValue('S')} means 'Use the value of Column1, but if that is null, then use the default: the letter S'
${DataInputs:first:defaultValue('S')}-${Column1}Nucleotide1-5
S-6
${DataInputs:first:defaultValue('S')} means 'Use the first DataInput value, but if that is null, use the default: the letter S'
${DataInputs:join('_'):defaultValue('S')}-${Column1}Nucleotide1_Nucleotide2-1${DataInputs:join('_'):defaultValue('S')} means 'Join together all of the DataInputs separated by undescores, but if that is null, then use the default: the letter S'

Incorporate Lineage Lookups

Incorporate Lineage Lookups

To include properties of sample sources or parents in sample names, use lookups into the lineage of the sample.

  • General parent input: Inputs/propertyA, MaterialInputs/propertyA, DataInputs/propertyA
  • Specific data type inputs: MaterialInputs/SampleType1/propertyA, DataInputs/DataClass2/propertyA, etc.
  • Import alias references: parentSampleA/propertyA, parentSourceA/propertyA, etc.
For example, to include source metadata (e.g. my blood sample was derived from this mouse, I would like to put the mouse strain in my sample name), the derived sample's naming expression might look like:
Blood-${DataInputs/Mouse/Strain}-${genId}

You can use the qualifier :first to select the first of a given set of inputs when there might be several.

If there might be multiple parent samples, you could choose the first one in a naming pattern like this:

Blood-${parentBlood/SampleID:first}-${genId}

Naming Pattern Examples

Name ExpressionExample OutputDescription
${genId}1
2
3
4
a simple sequence
S-${genId}S-1
S-2
S-3
S-1
S- + a simple sequence
${Lab:defaultValue('Unknown')}_${genId}Hanson_1
Hanson_2
Krouse_3
Unknown_4
The originating Lab + a simple sequence. If the Lab value is null, then use the string 'Unknown'.
S_${randomId}S_3294
S_1649
S_9573
S_8843
S_ + random numbers
S_${now:date}_${dailySampleCount}S_20170202_1
S_20170202_2
S_20170202_3
S_20170202_4
S_ + the current date + daily resetting incrementing integer
S_${Column1}_${Column2}S_Blood_PT101Create an id from the letter 'S' and two values from the current row of data, separated by underscore characters.
${OriginalCellLine/Name}-${genId}CHO-1, CHO-2Here OriginalCellLine is a lookup field to a table of orginating cell lines. Use a slash to 'walk the lookup'. Useful when you are looking up an integer-keyed table but want to use a different display field.

Incorporate Sample Counters

Date Based Counters

Several sample counters are available that will be incremented for the date when the sample is inserted, but can use a different date by attaching the counter to a date column.

  • dailySampleCount
  • weeklySampleCount
  • monthlySampleCount
  • yearlySampleCount
All of these counters can be used as standalone elements of a name expression, i.e. ${dailySampleCount}, in which case they will provide a counter across all sample types in a container. Note that these counters are incrementing, but since they apply to all sample types, within a given sample type, values will be sequential but not necessarily contiguous.

In addition, you can "attach" the counter to another date column by using the same element as a modifier after a colon, i.e. ${SampleDate:dailySampleCount}. This would use the date found in the row's "SampleDate" column (or today's date if the column has no value) and so provide a daily count for that "SampleDate".

withCounter Modifier

Another alternative for adding a counter to a field is to use :withCounter, a nested substitution syntax allowing you to add a counter specific to any column value when you create new samples. This modifier is particularly useful when naming aliquots which incorporate the name of the parent sample, and the desire is to provide a counter for only the aliquots of that particular sample. Using :withCounter will guarantee unique values, meaning that if a name with counter would match an existing sample, that counter will be skipped.

The syntax for using :withCounter is to prefix it with an expression that will be evaluated first, then surround the outer modified expression in ${ } brackets so that it too will be evaluated at creation time. The default naming pattern for creating aliquots combines the value in the AliquotedFrom column (the originating Sample ID), a dash, and a counter specific to that Sample ID:

${${AliquotedFrom}-:withCounter}

You could also use this modifier with another column name as well as strings in the inner expression. Given the example shown for an XML counter in the next section, names like Blood-A-1, Blood-A-2, etc would be generated with this expression:

${Blood-${Lot}-:withCounter}

Learn more about using this syntax in naming patterns for aliquots here:

You can use a starting value and number formats with this modifier. For example, to have a three digit counter starting at 42, (i.e. S-1-042, S-1-043, etc.) use:
${${AliquotedFrom}-:withCounter(42,'000')}

Advanced Options: XML Counter Columns

Another way to create a sequential counter based on values in other columns, such as an incrementing series for each lot of material on a plate, is to use XML metadata to define a new "counter" column paired with one or more existing columns to provide and store this incrementing value. You then use the new column in your name expression.

For example, consider that you would like to generate the following sample type for a given plate:

Name (from expression)LotSampleInLotPlate Id
Blood-A-1A1P1234
Blood-A-2A2P1234
Blood-B-1B1P1234
Blood-B-2B2P1234

The "SampleInLot" column contains a value that increments from 1 independently for each value in the "Lot" column. In this example, the name expression would be S-${Lot}-${SampleInLot}. To define the "SampleInLot" column, you would create it with data type integer, then use XML metadata similar to this:

<tables xmlns="http://labkey.org/data/xml">
<table tableName="MySampType" tableDbType="NOT_IN_DB">
<javaCustomizer class="org.labkey.experiment.api.CountOfUniqueValueTableCustomizer">
<properties>
<property name="counterName">SampleCounter</property>
<property name="counterType">org.labkey.api.data.UniqueValueCounterDefinition</property>
<!-- one or more pairedColumns used to derive the unique value -->
<property name="pairedColumn">Lot</property>
<!-- one or more attachedColumns where the incrementing counter value is placed -->
<property name="attachedColumn">SampleInLot</property>
</properties>
</javaCustomizer>
</table>
</tables>

The following rules apply to these XML counters:

  • The counter you create is scoped to a single Sample Type.
  • The definition of the counter column uses one or more columns to determine the unique value. When you use the counter in a name expression, be sure to also include all the paired columns in addition to your counter column to ensure the sample name generated will be unique.
  • The incrementing counter is maintained within the LabKey database.
  • Gaps in the counter's sequence are possible because it is incremented outside the transaction. It will be sequential, but not necessarily contiguous.
  • When you insert into a sample type with a unique counter column defined, you can supply a value for this unique counter column, but the value must be equal to or less than the current counter value for the given paired column.

Related Topics

Was this content helpful?

Log in or register an account to provide feedback


previousnext
 
expand allcollapse all