Hello everyone!
I have written an ExpressionTool that is supposed to take files/directories as input and put them all into a folder. When using this ExpressionTool in the context of a workflow i always get the following errors:
[step pooling_output] start
invalid field `nameroot`, expected one of: 'class', 'location', 'path', 'basename', 'listing'
invalid field `nameext`, expected one of: 'class', 'location', 'path', 'basename', 'listing'
[step pooling_output] completed success
I don't know what these are supposed to mean, and i don't know which part of the code is responsible. nameext isn't even referenced in the ExpressionTool. What makes me confused is that the error messages only show up when i use the ExpressionTool as part of a Workflow (example below). I tried running several workflows up to the point where the ExpressionTool would be used and collected their output at this point. When i then feed these exact outputs into the ExpressionTool, no error messages will show up. Could this just a be bug in cwltool? I now meticulously check the output of every workflow i run out of fear that the tool might somehow garble the output (which it has done once in the past, but that specific problem has been fixed).
A big thank you to anyone who can provide insight! Cheers
The ExpressionTool:
(I suspect this might strike some as a horrifying solution. Especially because of the separate inputs for arrays and single items. But i have yet to find a better way to do this in cwl. Happy to take suggestions!)
cwlVersion: v1.0
class: ExpressionTool
label: Returns a directory named after inputs.newname, containing all input files and directories.
requirements:
InlineJavascriptRequirement: {}
inputs:
file_single:
type: File?
label: A single file which will be placed in the output directory.
file_array:
type: File[]?
label: An array of files which will be placed in the output directory.
directory_single:
type: Directory?
label: A single directory which will be placed in the output directory as a subdirectory.
directory_array:
type: Directory[]?
label: An array of directories which will be placed in the output directory as subdirectories.
newname:
type: string?
label: Name of the output-directory. If no input is provided, tool will try use the nameroot of file_single, directory_single, file_array[0], directory_array[0] (in this order).
outputs:
pool_directory:
type: Directory
label: Directory where all input files and subdirectories will be pooled. Named after inputs.newname.
expression: |
${
//Check if an input for newname was provided. If yes, use this as new directory name.
var newName = "";
var needName = true;
if ( inputs.newname != undefined ) {
newName = inputs.newname;
needName = false;
}
//Check which input files / directories are present. Add them to the new directory.
//If no input for newname was provided, use the name of one of the files or directories.
var outputList = [];
if ( inputs.file_single != undefined ) {
outputList.push( inputs.file_single );
if ( needName == true ) {
newName = inputs.file_single.nameroot;
needName = false;
}
}
if ( inputs.directory_single != undefined ) {
outputList.push( inputs.directory_single );
if ( needName == true ) {
newName = inputs.directory_single.basename;
needName = false;
}
}
if ( inputs.file_array != undefined ) {
for ( var count = 0; count < inputs.file_array.length; count++ ) {
var nextfile = inputs.file_array[count];
outputList.push( nextfile );
}
if ( needName == true ) {
newName = ((inputs.file_array)[0]).nameroot;
needName = false;
}
}
if ( inputs.directory_array != undefined ) {
for ( var count = 0; count < inputs.directory_array.length; count++ ) {
var nextdir = inputs.directory_array[count];
outputList.push( nextdir );
}
if ( needName == true ) {
newName = ((inputs.directory_array)[0]).basename;
needName = false;
}
}
return {
"pool_directory": {
"class": "Directory",
"basename": newName,
"listing": outputList
}
};
}
A simple workflow which uses it:
cwlVersion: v1.0
class: Workflow
label: Uses various quality control tools on the input assembly.
requirements:
StepInputExpressionRequirement: {}
hints:
SoftwareRequirement:
packages:
quast:
specs: [ https://identifiers.org/RRID:SCR_001228 ]
version: [ "5.0.2" ]
inputs:
assembly:
label: Assembly to perform qc on.
type: File
worker_threads:
label: Number of CPU-threads used in computationally intensive steps.
type: int
default: 1
outputs:
assembly_qc_directory:
type: Directory
outputSource: pooling_output/pool_directory
steps:
quast:
run: ../quastTool.cwl
in:
assembly: assembly
worker_threads: worker_threads
out: [report_directory]
pooling_output:
run: ../poolingTool.cwl
in:
directory_single: quast/report_directory
newname:
valueFrom: assembly-qc-reports
out: [pool_directory]
FYI, this sounds like an error in
cwltool
, I am investigating