Template File Examples
The following examples show how to use tokens and metadata elements in template files. For a list of all supported tokens and metadata elements, see Template File Contents .

The LIMS provides configuration to support generation of sample sheets that are compatible with some Illumina instruments. For details, see the Illumina Instrument Integrations documentation.

The LIMS provides configured automations that generate sample sheets compatible with some QC instruments.

Command line:
bash -l -c "/opt/gls/clarity/bin/java -jar /opt/gls/clarity/extensions/ngs-common/v5/EPP/DriverFileGenerator.jar -u {username} -p {password} \
script:driver_file_generator \
-i {processURI:v2} \
-t /opt/gls/clarity/extensions/ngs-common/v5/EPP/conf/readonly/bioA_driver_file_template.csv \
-o {compoundOutputFileLuid0}.csv \
-l {compoundOutputFileLuid1} \
&& /opt/gls/clarity/bin/java -jar /opt/gls/clarity/extensions/ngs-common/v5/EPP/ngs-extensions.jar
-u {username}
-p {password} \ script:addBlankLines \
-i {stepURI:v2} \ -f {compoundOutputFileLuid0}.csv \
-l {compoundOutputFileLuid1} \
-sep COMMA \
-b ',False,' \
-h 1 \
-c LIMSID \
-pre 'Sample '"
Template file content:
INCLUDE.OUTPUT.RESULTFILES
<HEADER_BLOCK>
</HEADER_BLOCK>
<HEADER>
"\"Sample Name\",\"Sample Comment\",\"Rest. Digest\",\"Observation\""
</HEADER>
<DATA>
${OUTPUT.LIMSID},,False,
</DATA>
<FOOTER>
Ladder,,False,"\"
Chip Lot #\",\"Reagent Kit Lot #\"
,
\"QC1 Min [%]\",\"QC1 Max [%]\",\"QC2 Min [%]\",\"QC2 Max [%]\"
,,,
\"Chip Comment\”
"
</FOOTER>

Command line:
bash -l -c "/opt/gls/clarity/bin/java -jar /opt/gls/clarity/extensions/ngs-common/v5/EPP/DriverFileGenerator.jar -u {username} -p {password} \
script:driver_file_generator \
-i {processURI:v2} \
-t /opt/gls/clarity/extensions/ngs-common/v5/EPP/conf/readonly/nd_driver_file_template.csv \
-o {compoundOutputFileLuid0}.csv \
-l {compoundOutputFileLuid1}"
Template file content:
INCLUDE.OUTPUT.RESULTFILES
<HEADER_BLOCK>
</HEADER_BLOCK>
<HEADER>
"Well Location, Sample Name"
</HEADER>
<DATA>
${INPUT.CONTAINER.PLACEMENT},${INPUT.CONTAINER.NAME}_${INPUT.CONTAINER.PLACEMENT}_${INPUT.NAME}
</DATA>

Command line:
bash -l -c "/opt/gls/clarity/bin/java -jar /opt/gls/clarity/extensions/ngs-common/v5/EPP/DriverFileGenerator.jar -u {username} -p {password} \
script:driver_file_generator \
-i {processURI:v2} \
-t /opt/gls/clarity/extensions/ngs-common/v5/EPP/conf/readonly/tapestation_driver_file_template.csv \
-o {compoundOutputFileLuid0}.csv \
-l {compoundOutputFileLuid1}"
Template file content:
INCLUDE.OUTPUT.RESULTFILES
SORT.BY.${INPUT.LIMSID}
<DATA>
${OUTPUT.LIMSID}_${INPUT.NAME}
</DATA>

Command line:
bash -c "/opt/gls/clarity/bin/java -cp /opt/gls/clarity/extensions/ngs-common/v5/EPP/DriverFileGenerator.jar driver_file_generator \-i {processURI} -u {username} -p {password} -t /opt/gls/clarity/extensions/conf/driverfiletemplates/GenomeStudioGeneExpressionTemplate.csv \-o {compoundOutputFileLuid0}.csv -l {compoundOutputFileLuid1}.html"
Template file content:
INCLUDE.OUTPUT.RESULTFILES
OUTPUT.SEPARATOR,COMMA
LIST.SEPARATOR,";"
ILLEGAL.CHARACTERS,COMMA
ILLEGAL.CHARACTER.REPLACEMENTS,_SORT.BY.${INPUT.CONTAINER.NAME}${INPUT.CONTAINER.ROW}${INPUT.CONTAINER.COLUMN}
<HEADER_BLOCK>
[HEADER]Investigator Name ${PROCESS.TECHNICIAN}
Project Name, ${SAMPLE.PROJECT.NAME.ALL}
Experiment Name
Date, ${DATE}
[Manifests]
${PROCESS.UDF.Manifest A}
</HEADER_BLOCK>
<HEADER>
[DATA]
Sample_Name,Sample_Well,Sample_Plate,Pool_ID,Sentrix_ID,Sentrix_Position
</HEADER>
<DATA>
${INPUT.NAME},,,,${INPUT.CONTAINER.NAME},${INPUT.CONTAINER.PLACEMENT}
</DATA>
<PLACEMENT>
// inputs to this section are String row, String column, Node containerTypeNode
int convertAlphaToNumeric(String letters)
{
int result = 0letters = letters.toUpperCase()
for (int i = 0; i < letters.length(); i++) {
result += (letters.charAt(i).minus('A' as char) + 1) * (26 ** (letters.length() - i - 1))
}
return result
}
int SENTRIX_POS_THRESHOLD = 12
int WELL_PLATE_SIZE_96 = 96
int xSize = containerTypeNode.'x-dimension'.size.text().toInteger()
int ySize = containerTypeNode.'y-dimension'.size.text().toInteger()
int containerSize = xSize * ySize
boolean xIsAlpha = containerTypeNode.'x-dimension'.'is-alpha'.text().toBoolean()
boolean yIsAlpha = containerTypeNode.'y-dimension'.'is-alpha'.text().toBoolean()
if (containerSize <= SENTRIX_POS_THRESHOLD && (xIsAlpha || yIsAlpha)) {
return row
}
// R001_C001 for 96 well plate, r01c01 for other container types
if (containerSize == WELL_PLATE_SIZE_96) {
def numFormat = java.text.NumberFormat.getNumberInstance() numFormat.setMinimumIntegerDigits(3)
String xStr = numFormat.format(column.isInteger() ? column as int : convertAlphaToNumeric(column))
String yStr = numFormat.format(row.isInteger() ? row as int : convertAlphaToNumeric(row))
// Row is mapped to x coordinate, while column is mapped to y.
// When creating an array type of size 96, swap the row and column dimension.
// e.g 12 x 8 array should be mapped as an 8 x 12 array
//
// This mapping has been in RI for a while.
// In AddIlluminaArraysStep, all 2D Illumina arrays added have a dimension of 8 x 12.
// This driver file template then converts it back to 12 x 8.
// This logic is now corrected to follow other arrays to make sure the driver file.
// generated is compatible with existing arrays and software.
return "R"+xStr+"_C"+yStr
} else {
def numFormat = java.text.NumberFormat.getNumberInstance()
numFormat.setMinimumIntegerDigits(2)
String xStr = numFormat.format(column.isInteger() ? column as int : convertAlphaToNumeric(column))
String yStr = numFormat.format(row.isInteger() ? row as int : convertAlphaToNumeric(row))
// row is mapped to y, column is mapped to x
return "r"+yStr +"c"+xStr
}
</PLACEMENT>

In the template file, the following OUTPUT.FILE.NAME metadata element renames the generated template file 'NewTemplateFileName':
OUTPUT.FILE.NAME, NewTemplateFileName.csv
In the automation command line, the following will attach the generated file to the {compoundOutputFileLuid0} placeholder, with the name defined by the OUTPUT.FILE.NAME metadata element.
bash -c "/opt/gls/clarity/bin/java -cp /opt/gls/clarity/extensions/ngs-common/v5/EPP/DriverFileGenerator.jar
script:driver_file_generator
-i {stepURI:v2}
-u {username}
-p {password}
-t /opt/gls/clarity/customextensions/Robot.csv
-q true -destLIMSID {compoundOutputFileLuid0}
-o extended_driver_x384.csv
-l {compoundOutputFileLuid2}
When the LIMS attaches a file to a placeholder in the LIMS, it assumes that the file is named with the step LIMSID, and uses this LIMSID to identify the placeholder to which the file should be attached.
However, when using OUTPUT.FILE.NAME, you can give the file a name that does not begin with the LIMSID of the placeholder to which it will be attached. To do this, you must use the quickAttach and destLIMSID parameters in the automation command line.
• | If the quickAttach parameter is provided without destLIMSID parameter, the script logs an error and stops execution. |
• | If destLIMSID is provided without using quickAttach, it is ignored. |

The OUTPUT.FILE.NAME and OUTPUT.TARGET.DIR metadata elements support token values. This allows you to name files based on input / output values of the step - the input or output container name, for example.
The following tokens are supported for this feature:
• | PROCESS.LIMSID |
• | PROCESS.UDF.<UDF NAME> |
• | PROCESS.TECHNICIAN |
• | DATE |
• | INPUT.CONTAINER.NAME |
• | INPUT.CONTAINER.TYPE |
• | INPUT.CONTAINER.LIMSID |
• | OUTPUT.CONTAINER.NAME |
• | OUTPUT.CONTAINER.TYPE |
• | OUTPUT.CONTAINER.LIMSID |
Rules and Constraints
When using token values in file names, the following rules and constraints apply:
• | Container-related functions will return the value from a single container, even if there are multiple containers. |
• | Other tokens will function, but will only return the value for the first row of the file (first input or output). |
• | If the OUTPUT.FILE.NAME specified does not match the LIMS ID of the file, the output file will not be attached in the LIMS user interface. To ensure that the file is attached, include the quickAttach and destLIMSID parameters in the command-line string. |
• | It is highly recommended that you do not use SAMPLE.PROJECT.NAME.ALL or SAMPLE.PROJECT.CONTACT.ALL, because the result is prone to surpassing the maximum length of a file name. There are similar issues with other SAMPLE tokens when dealing with pools. |
• | Only the following characters are supported in the file name. Any other characters will be replaced by an _ (underscore) by default. This replacement character can be configured with the OUTPUT.FILE.NAME.ILLEGAL.CHARACTER.REPLACEMENT metadata element.a-z. |
– | A-Z |
– | 0–9 |
– | _ (underscore) |
– | - (dash) |
– | . (period) |
Providing a full file path for OUTPUT.FILE.NAME is still supported, but deprecated. If the full path is provided, the file/directory separator will be automatically detected and will not be replaced in the static parts of the file name. Any of these separators derived from the result of a token value will be replaced.

You can use the CONTROL.SAMPLE.DEFAULT.PROJECT.NAME metadata element to define a project name for control samples. The value specified by this token will be used when determining one or more values for the SAMPLE.PROJECT.NAME and SAMPLE.PROJECT.NAME.ALL tokens.
Example:
CONTROL.SAMPLE.DEFAULT.PROJECT.NAME, My Control Sample Project
Rules and Constraints
• | If the token is found in the template, but with no value then no project name will be given for control samples. |
• | If the token is not found in the template, then no project name will be given for control samples. |
• | If multiple values are provided, the first one will be used. |
• | The SAMPLE.PROJECT.NAME.ALL list will include the control project name. |

You can use tthe HIDE metadata element to optionally hide a column if it contains no data. The following lines in the metadata will hide a data column when empty:
HIDE, ${OUTPUT.UDF.SAMPLEUDF}, IF, NODATA
Assuming ${OUTPUT.UDF.SAMPLEUDF} is one of the data columns specified in the template, then that column will be hidden whenever there is no data to show in the output file. If a list of fields is provided, then any empty ones will be hidden:
HIDE, ${OUTPUT.UDF.SAMPLEUDF},${PROCESS.TECHNICIAN}, ${PROCESS.LIMSID}, IF, NODATA
You may also hide only one representation of a specific column or field:
HIDE, ${PROCESS.TECHNICIAN##FirstName}, IF, NODATA

You can also use the HIDE metadata element with tokens in the header section. If one or more tokens are used for a header key value pair, and there are no values for any of the tokens, the entire row will be hidden.
Assuming ${OUTPUT.UDF.SAMPLEUDF} is one of the rows specified in the template header section, that header row will be hidden whenever there is no data to display in the output file.
If a list of tokens is provided for the value, the row will only be shown if one or more of the tokens resolves to a value:
HIDE, ${OUTPUT.UDF.SAMPLEUDF},${PROCESS.TECHNICIAN}, ${PROCESS.LIMSID}, IF, NODATA

If you would like to generate multiple files, you can use the following GROUP.FILES.BY metadata elements:
• | GROUP.FILES.BY.INPUT.CONTAINERS |
• | GROUP.FILES.BY.OUTPUT.CONTAINERS |
These elements allow a file to be created per instance of the specified element in the step, for example, one file per input or per output container. Step level information appears in all files, but sample information is specific to the samples in the given container.
For example, suppose that a step has two samples - each in their own container - with a template file calling for information about process UDFs and sample names. Using this metadata will produce two files, each of which will contain:
• | One sample entry |
• | The same process UDF information |
As a best practice, we recommend storing a copy of generated files in the LIMS. To do this, you must use the quickAttach script parameter. This parameter must be used with the destLIMSID parameter, which tells the Template File Generator script which file placeholder to use. (For details, see Script Parameters.)
Naming The Files
When generating multiple files, the script gathers them all into one zip file so only one file placeholder is needed regardless of how many containers are in the step.
The zip file name may be provided in the metadata as follows:
GROUP.FILES.BY.INPUT.CONTAINERS,<zip file name>
GROUP.FILES.BY.OUTPUT.CONTAINERS,<zip file name>
Inside the zip file, include any paths specified for where files should be written. An example final structure inside the zip, where the subfolders are specified using the container name token, could be as follows:
GROUP.FILES.BY.INPUT.CONTAINERS,MyZip.zip
MyZip.zip
---- Container1
---- SampleSheet.csv
---- Container2
---- SampleSheet.csv
The file naming, writing, and uploading process works as follows:
• | The outputPath parameter element is required for the script. You can use this parameter to specify the path to which the generated files will be written and/or the name to use for the file. Use this in the following scenarios: |
– | When the target path/name is constant.-or- |
– | When the target path/name includes something that can only be passed to the script via the command line - for example, if you want to include the value of a {compoundOutputFileLuidN} in the path. |
• | The OUTPUT.TARGET.DIR metadata element overrides any path provided by outputPath , but does not change the file name. Use this:When the target path includes something that can only be accessed with token templates - for example, the name of the user who ran the step. |
• | The OUTPUT.FILE.NAME metadata element overrides any value provided by outputPath entirely. This token determines the name of the files that are produced for each container - for example, SampleSheet.csv. It may also contain tokens to access information, such as the container name, and it may also contain a path. |
If you provide all three of outputPath, OUTPUT.TARGT.DIR, and OUTPUT.FILE.NAME, the result is that outputPath is ignored and the path specified by OUTPUT.TARGET.DIR is used as the parent under which OUTPUT.FILE.NAME is created, even if OUTPUT.FILE.NAME includes a path in addition to the file name.
If you wish to only attach files to placeholders in the LIMS and do not wish to also write anything to disk, then omit OUTPUT.TARGET.DIR and provide the outputPath parameter value as ".". This will cause files to only be written to the temporary directory that is cleaned up after the automation completes.
To produce the example of MyZip.zip, you could use the following:
• | Script parameters: |
-outputPath SampleSheet.csv
-q 'true'
-destLIMSID {compoundOutputFileLuid0}
• | Template: |
GROUP.FILES.BY.OUTPUT.CONTAINERS,MyZip.zip
OUTPUT.TARGET.DIR,${OUTPUT.CONTAINER.NAME}
Rules and Constraints
• | You can only use one GROUP.FILES.BY metadata element in each template file. |
• | To attach the files in the LIMS as a zip file, you must provide the quickAttach parameter along with the destLIMSID. |
• | The zip file name may optionally be specified with the GROUP.FILES.BY metadata. |
• | If quickAttach is used and no zip name is specified in the template, the zip will be named using the destLIMSID parameter value. |
• | The zip file name, file paths, and file names should not contain characters that are illegal for directories and files on the target operating system. Illegal characters will be replaced with underscores. |
• | If a file name is not unique to the target directory, eg, if multiple SampleSheet.csv files are being written to /my/target/path, an error will be thrown and no files written. |
• | When specifying the OUTPUT.TARGET.DIR metadata element, if a token is used that may resolve to multiple values for a single path (for example, using INPUT.NAME in the path when it will resolve to multiple sample names), one value will be chosen arbitrarily for the path. For example, you may end up with /Container1/Sample1/myfile.csv when there are two samples in the container. |