User Tools

Site Tools


neuroimagen:xnat_pipelines

Differences

This shows you the differences between two versions of the page.

Link to this comparison view

Both sides previous revision Previous revision
Next revision
Previous revision
neuroimagen:xnat_pipelines [2019/10/29 01:13]
daniel
neuroimagen:xnat_pipelines [2020/04/14 01:49]
daniel
Line 113: Line 113:
 ==== Estructura de un pipeline ==== ==== Estructura de un pipeline ====
  
-Un //pipeline// se define en un archivo XML dentro de un subdirectorio de ''pipeline/catalog'' que se crea al instalar en //pipeline engine// (dentro de ''/nas/data/xnat''). En el subdirectorio se recomienda la siguiente estructura:+Un //pipeline// se define en un archivo XML dentro de un subdirectorio de ''pipeline/catalog'' que se crea al instalar el //pipeline engine// (dentro de ''/nas/data/xnat''). En el subdirectorio se recomienda la siguiente estructura:
   * descripción XML del //pipeline//   * descripción XML del //pipeline//
   * ''resources'': subdirectorio con definiciones XML para llamar a programas externos   * ''resources'': subdirectorio con definiciones XML para llamar a programas externos
   * ''scripts'': subdirectorio con los scripts o programas externos propios del //pipeline//   * ''scripts'': subdirectorio con los scripts o programas externos propios del //pipeline//
- 
-**Ejemplo:** el pipeline ... 
  
 La descripción del //pipeline// se hace en un documento XML con la siguiente estructura: La descripción del //pipeline// se hace en un documento XML con la siguiente estructura:
  
-<code>+<code xml> 
 +<?xml version="1.0" encoding="UTF-8"?> 
 + 
 +<Pipeline xmlns="http://nrg.wustl.edu/pipeline" 
 +          xmlns:xi="http://www.w3.org/2001/XInclude" 
 +          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
 +          xsi:schemaLocation="http://nrg.wustl.edu/pipeline ..\schema\pipeline.xsd" 
 +          xmlns:fileUtils="http://www.xnat.org/java/org.nrg.imagingtools.utils.FileUtils"> 
 + 
 + <name>Name of the Pileline</name> 
 + <location>Directory</location> 
 + <description>A brief description</description> 
 + 
 + <resourceRequirements>...</resourceRequirements> 
 + 
 + <!-- info about the pipeline and input parameters received from Xnat --> 
 + <documentation> 
 + <authors>...</authors> 
 + <version>0</version> 
 + <input-parameters> 
 + <parameter>...</parameter> 
 + ... 
 + </input-parameters> 
 + </documentation> 
 + 
 + <!-- what sort of data the pipeline applies to --> 
 + <xnatInfo appliesTo="xnat:mrSessionData"/> 
 + 
 + <!-- directory where log output is written --> 
 + <outputFileNamePrefix>...</outputFileNamePrefix> 
 + 
 + <!-- parameter on which to iterate steps through PIPELINE_LOOPON(iter) --> 
 + <loop id="iter" xpath="..."/> 
 + 
 + <!-- other parameters defined in the pipeline --> 
 + <parameters> 
 + <parameter>...</parameter> 
 + ... 
 + </parameters> 
 + 
 + <!-- processing steps --> 
 + <steps>  
 + <!-- first step (workdirectory and flow control options are shown as an example) --> 
 + <step id="1" description="Step 1" workdirectory="..." continueOnFailure="false" precondition="EXISTS(...)"> 
 + <!-- command to be run (described as a resource XML) --> 
 + <resource name="command" location="directory"
 + <argument id="arg"> 
 + <value>arg value</value> 
 + </argument> 
 + </resource> 
 + </step> 
 + ... 
 + </steps> 
 + 
 +</Pipeline> 
  
 </code> </code>
  
-==== Ejemplo: modificación del //pipeline// ... ====+==== Ejemplo: modificación del pipeline dcm2nii/DicomToNifti_X.xml ====
  
 +Queremos cambiar el modo en que se llama a dcm2niix desde este pipeline, de manera que se agreguen en los nombres de los archivos NII generados el nombre del paciente (%n), el número de adquisición de la serie (%s) y la descripción o tipo de serie (%d).
  
-==== Ejemplo: limpieza de las series en una sesión DICOM ====+Para ello, primero definimos un //input-parameter// con la cadena de formato que se pasará a dcm2niix desde Xnat (que, en teoría, podríamos modificar al llamar al pipeline):
  
-Aquí se describirá el //pipeline// ''CleanMRSession'' que lleva a cabo la selección de los scans de una serie DICOM de forma análoga a la descrita en la página [[neuroimagen:xnat_api|Usar la API de XNAT]].+<code xml> 
 +<input-parameters> 
 + ... 
 + <parameter> 
 + <name>output_nifti_filename_format</name> 
 + <values> 
 + <csv>%n_%s_%d</csv> 
 + </values> 
 + <description>Filename format</description> 
 + </parameter> 
 +</input-parameters> 
 +</code>
  
-Este //pipeline// consta de los siguientes archivos:+Luego, modificaremos la llamada a dcm2niix en el //step// "CONVERT" seleccionando nuestro argumento output_filename_format (usando la sintaxis XPath). Aprovechamos para añadir el nuevo argumento ignore_derived, para que en el procesamiento se ignoren las imágenes derivadas, los localizers y las imágenes 2D.
  
-  * ''CleanMRSession.xml'' +<code xml>
-  * ''resources/cleanMRSession.xml'' +
-  * ''scripts/cleanMRSession.sh'' (script Bash)+
  
-== CleanMRSession.xml ==+ <step id="CONVERT" description="Convert each DICOM series into a 4d NIFTI file" precondition="EXISTS(^concat(/Pipeline/parameters/parameter[name='niidir']/values/unique/text(),'/',PIPELINE_LOOPON(series))^)" continueOnFailure="true"> 
 + <resource name="dcm2niix" location="dcm2niix/resources"> 
 + <argument id="gzip"> 
 + <value>y</value><!-- compress --> 
 + </argument> 
 + <argument id="ignore_derived"><!-- new argument --> 
 + <value>y</value> 
 + </argument> 
 + <argument id="output_filename_format"> 
 + <value>^/Pipeline/parameters/parameter[name='output_nifti_filename_format']/values/unique/text()^</value><!-- selection from parameters --> 
 + </argument> 
 + <argument id="output"> 
 + <value>^concat(/Pipeline/parameters/parameter[name='niidir']/values/unique/text(),'/',PIPELINE_LOOPON(series))^</value> 
 + </argument> 
 + <argument id="input"> 
 + <value>^concat(/Pipeline/parameters/parameter[name='rawdir']/values/unique/text(),'/',PIPELINE_LOOPON(series))^</value> 
 + </argument> 
 + </resource> 
 + </step> 
 + 
 +</code> 
 + 
 +Lo que sucede es que el //resource// dcm2niix/resources/dcm2niix.xml no contempla el argumento ignore_derived, así que tenemos que añadírselo:
  
-++++ El código, completo, es así: | 
 <code xml> <code xml>
 + <argument id="ignore_derived">
 + <name>i</name>
 + <description>ignore derived [y|n]</description>
 + </argument>
 +</code>
 +
 +
 +++++ El código del nuevo DicomToNifti_Y.xml queda así |
 +<file xml DicomToNifti_Y.xml>
 +<?xml version="1.0" encoding="UTF-8"?>
 +<Pipeline xmlns="http://nrg.wustl.edu/pipeline" xmlns:xi="http://www.w3.org/2001/XInclude" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://nrg.wustl.edu/pipeline ..\schema\pipeline.xsd" xmlns:fileUtils="http://www.xnat.org/java/org.nrg.imagingtools.utils.FileUtils">
 +
 +<name>DicomToNifti_Y</name>
 +
 +<location>dcm2niix</location>
 +
 +<description>Pipeline creates NIFTI files from DICOM files using dcm2niix (modified).</description>
 +
 +<documentation>
 + <authors>
 + <author>
 + <lastname>Flavin</lastname>
 + <firstname>John</firstname>
 + <contact>
 + <email>flavinj@mir.wustl.edu</email>
 + </contact>
 + </author>
 + </authors>
 + <version>20180811</version>
 + <input-parameters>
 + <parameter>
 + <name>scanids</name>
 + <values>
 + <schemalink>xnat:imageSessionData/scans/scan/ID</schemalink>
 + </values>
 + <description>Scan ids of all the scans of the session</description>
 + </parameter>
 + <parameter>
 + <name>output_nifti_filename_format</name>
 + <values>
 + <csv>%n_%s_%d</csv>
 + </values>
 + <description>Filename format</description>
 + </parameter>
 + </input-parameters>
 +</documentation>
 +
 +<outputFileNamePrefix>^concat(/Pipeline/parameters/parameter[name='logdir']/values/unique/text(),'/',/Pipeline/parameters/parameter[name='label']/values/unique/text())^</outputFileNamePrefix>
 +
 +<loop id="series" xpath="^/Pipeline/parameters/parameter[name='scanids']/values/list^"/>
 +
 +<parameters>
 + <parameter>
 + <name>workdir</name>
 + <values>
 + <unique>^concat(/Pipeline/parameters/parameter[name='builddir']/values/unique/text(),'/',/Pipeline/parameters/parameter[name='label']/values/unique/text())^</unique>
 + </values>
 + </parameter>
 + <parameter>
 + <name>logdir</name>
 + <values>
 + <unique>^concat(/Pipeline/parameters/parameter[name='workdir']/values/unique/text(),'/LOGS')^</unique>
 + </values>
 + </parameter>
 + <parameter>
 + <name>rawdir</name>
 + <values>
 + <unique>^concat(/Pipeline/parameters/parameter[name='workdir']/values/unique/text(),'/RAW')^</unique>
 + </values>
 + </parameter>
 + <parameter>
 + <name>niidir</name>
 + <values>
 + <unique>^concat(/Pipeline/parameters/parameter[name='workdir']/values/unique/text(),'/NIFTI')^</unique>
 + </values>
 + </parameter>
 +</parameters>
 +
 +<steps>
 + <step id="MKDIR_RAW" description="Create RAW folder">
 + <resource name="mkdir" location="commandlineTools">
 + <argument id="dirname">
 + <value>^/Pipeline/parameters/parameter[name='rawdir']/values/unique/text()^</value>
 + </argument>
 + </resource>
 + </step>
 +
 + <step id="MKDIR_NII" description="Create NIFTI folder">
 + <resource name="mkdir" location="commandlineTools">
 + <argument id="dirname">
 + <value>^/Pipeline/parameters/parameter[name='niidir']/values/unique/text()^</value>
 + </argument>
 + </resource>
 + </step>
 +
 + <step id="MKDIR_RAW_SCAN" description="Create folder for each series in RAW subfolder" workdirectory="^/Pipeline/parameters/parameter[name='rawdir']/values/unique/text()^">
 + <resource name="mkdir" location="commandlineTools">
 + <argument id="dirname">
 + <value>^PIPELINE_LOOPON(series)^</value>
 + </argument>
 + </resource>
 + </step>
 +
 + <step id="GET_SCANS" description="Download scan DICOMs" workdirectory="^concat(/Pipeline/parameters/parameter[name='rawdir']/values/unique/text(),'/',PIPELINE_LOOPON(series))^">
 + <resource name="XnatDataClient" location="xnat_tools">
 + <argument id="sessionId">
 + <value>^fileUtils:getJSESSION('DUMMY')^</value>
 + </argument>
 + <argument id="absolutePath"/>
 + <argument id="batch"/>
 + <argument id="method">
 + <value>GET</value>
 + </argument>
 + <argument id="remote">
 + <value>^concat('"',/Pipeline/parameters/parameter[name='host']/values/unique/text(),'/data/experiments/',/Pipeline/parameters/parameter[name='id']/values/unique/text(),'/scans/',PIPELINE_LOOPON(series),'/resources/DICOM/files"')^</value>
 + </argument>
 + </resource>
 + </step>
 + <step id="RMEMPTYDIRS" description="Removes empty dirs" precondition="EXISTS(^concat(/Pipeline/parameters/parameter[name='rawdir']/values/unique/text(),'/',PIPELINE_LOOPON(series))^)" continueOnFailure="true">
 + <!-- rmdir ../$SERIES -->
 + <resource name="rmdir" location="commandlineTools" >
 + <!-- resource not in standard xnat pipelines catalog -->
 + <argument id="dir">
 + <value>^concat(/Pipeline/parameters/parameter[name='rawdir']/values/unique/text(),'/',PIPELINE_LOOPON(series))^</value>
 + </argument>
 + </resource>
 + </step>
 +
 + <step id="MKDIR_NII_SCAN" description="Create folder for each series in NIFTI subfolder" precondition="EXISTS(^concat(/Pipeline/parameters/parameter[name='rawdir']/values/unique/text(),'/',PIPELINE_LOOPON(series))^)" workdirectory="^/Pipeline/parameters/parameter[name='niidir']/values/unique/text()^">
 + <resource name="mkdir" location="commandlineTools">
 + <argument id="dirname">
 + <value>^PIPELINE_LOOPON(series)^</value>
 + </argument>
 + </resource>
 + </step>
 + <step id="CONVERT" description="Convert each DICOM series into a 4d NIFTI file" precondition="EXISTS(^concat(/Pipeline/parameters/parameter[name='niidir']/values/unique/text(),'/',PIPELINE_LOOPON(series))^)" continueOnFailure="true">
 + <resource name="dcm2niix" location="dcm2niix/resources">
 + <argument id="gzip">
 + <value>y</value>
 + </argument>
 + <argument id="ignore_derived"><!-- new argument -->
 + <value>y</value>
 + </argument>
 + <argument id="output_filename_format">
 + <value>^/Pipeline/parameters/parameter[name='output_nifti_filename_format']/values/unique/text()^</value>
 + </argument>
 + <argument id="output">
 + <value>^concat(/Pipeline/parameters/parameter[name='niidir']/values/unique/text(),'/',PIPELINE_LOOPON(series))^</value>
 + </argument>
 + <argument id="input">
 + <value>^concat(/Pipeline/parameters/parameter[name='rawdir']/values/unique/text(),'/',PIPELINE_LOOPON(series))^</value>
 + </argument>
 + </resource>
 + </step>
 + <step id="UPLOAD" description="Upload NIFTI files" precondition="EXISTS(^concat(/Pipeline/parameters/parameter[name='niidir']/values/unique/text(),'/',PIPELINE_LOOPON(series))^)" continueOnFailure="true">
 + <resource name="XnatDataClient" location="xnat_tools">
 + <argument id="sessionId">
 + <value>^fileUtils:getJSESSION('DUMMY')^</value>
 + </argument>
 + <argument id="method">
 + <value>PUT</value>
 + </argument>
 + <argument id="remote">
 + <value>^concat('"',/Pipeline/parameters/parameter[name='host']/values/unique/text(),'/data/experiments/',/Pipeline/parameters/parameter[name='id']/values/unique/text(),'/scans/',PIPELINE_LOOPON(series),'/resources/NIFTI/files?overwrite=true&amp;format=NIFTI&amp;content=NIFTI_RAW&amp;reference=',/Pipeline/parameters/parameter[name='niidir']/values/unique/text(),'/',PIPELINE_LOOPON(series),'&amp;event_id=',/Pipeline/parameters/parameter[name='workflowid']/values/unique/text(),'"')^</value>
 + </argument>
 + </resource>
 + </step>
 +</steps>
 +
 +</Pipeline>
 +</file>
 +++++
 +
 +++++ El código de dcm2niix.xml queda así |
 +<file xml dcm2niix.xml>
 +<?xml version="1.0" encoding="UTF-8"?>
 +<Resource xmlns="http://nrg.wustl.edu/pipeline">
 + <name>dcm2niix</name>
 +    <commandPrefix>source /nas/data/xnat/pipeline/scripts/dcm2niix_setup.sh;</commandPrefix>
 + <type>Executable</type>
 + <description>Generates NIFTI files from DICOM</description>
 + <input>
 + <argument id="gzip">
 + <name>z</name>
 + <description>gzip [y|n]</description>
 + </argument>
 + <argument id="ignore_derived">
 + <name>i</name>
 + <description>ignore derived [y|n]</description>
 + </argument>
 + <argument id="output_filename_format">
 + <name>f</name>
 + <description>Output filename format string. (%c=comments %f=folder name %i ID of patient %m=manufacturer %n=name of patient %p=protocol %s=series, %t=time; default 'N')</description>
 + </argument>
 + <argument id="output">
 + <name>o</name>
 + <description>Output Folder</description>
 + </argument>
 + <argument id="input"/>
 + </input>
 +</Resource>
 +</file>
 +++++
 +
 +==== Ejemplo: resource nuevo para llamar al programa tar ====
 +
 +En algunos pipelines puede interesar comprimir varios ficheros resultantes en un archivo tar.gz, usando el muy común programa tar de UNIX. Los //pipelines// de ejemplo no incluyen este programa como uno de los //resources// en commandlineTools, pero es muy fácil de escribirlo con las opciones básicas para comprimir archivos como
 +<code bash>
 +$ tar -z -cf archivo.tar.gz fichero1.ext fichero2.ext ...
 +</code>
 +
 +++++El código de tar.xml sería así |
 +<file xml tar.xml>
 +<?xml version="1.0" encoding="UTF-8"?>
 +<Resource xmlns="http://nrg.wustl.edu/pipeline">
 + <name>tar</name>
 + <type>Executable</type>
 + <description>TAR a dir/file</description>
 + <estimated_time>00:00:01</estimated_time>
 + <input>
 + <argument id="compress">
 + <name>z</name>
 + <description>apply gzip</description>
 + </argument>
 + <argument id="archive">
 + <name>cf</name>
 + <description>Archive name</description>
 + </argument>
 + <argument id="files">
 + <description>Dir/files to tar</description>
 + </argument>
 + </input>
 +</Resource>
 +</file>
 +++++
 +
 +==== Ejemplo: pipeline nuevo para limpieza de las series en una sesión DICOM ====
 +
 +Partiendo de un //pipeline// de ejemplo, creamos el pipeline ''CleanMRSession.xml'' que lleva a cabo la selección de los scans de una serie DICOM de forma análoga a la descrita en la página [[neuroimagen:xnat_api|Usar la API de XNAT]].
 +
 +Este //pipeline// consta de los siguientes archivos:
 +
 +  * ''CleanMRSession.xml'': la descripción de los pasos de procesamiento
 +  * ''resources/cleanMRSession.xml'': el //resource// que describe cómo se llama al script Bash siguiente
 +  * ''scripts/cleanMRSession.sh'': el script Bash
 +
 +
 +++++El código de CleanMRSession.xml es así |
 +<file xml CleanMRSession.xml>
  
 <?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
Line 268: Line 601:
 </Pipeline> </Pipeline>
  
-</code>+</file>
 ++++ ++++
  
-== cleanMRSession.xml (descripción de cleamMRSession.sh) == +++++ El código de cleanMRSession.xml (descripción de cleamMRSession.sh) es así | 
- +<file xml cleanMRSession.xml>
-++++ El código, completo, es así+
-<code xml>+
  
 <?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
Line 304: Line 635:
 </Resource> </Resource>
  
-</code>+</file>
 ++++ ++++
  
  
-== cleanMRSession.sh (script que realiza el borrado) == +++++ El código de cleanMRSession.sh (script que realiza el borrado) es así | 
- +<file bash cleanMRSession.sh>
-++++ El código, completo, es así+
-<code bash>+
  
 #!/bin/bash #!/bin/bash
Line 352: Line 681:
  
 #temporaries #temporaries
-TMP_PRO=$(tempfile)+TMP_PRO=$(mktemp)
  
 #Tipos de estudios #Tipos de estudios
Line 370: Line 699:
 dckey -k "AcquisitionDate" "$SERIES/$DCM" 2>&1 | grep -v Error &&\ dckey -k "AcquisitionDate" "$SERIES/$DCM" 2>&1 | grep -v Error &&\
 dckey -k "SeriesDescription" "$SERIES/$DCM" 2>&1 | grep -v Error | grep -v -f $TMP_PRO &&\ dckey -k "SeriesDescription" "$SERIES/$DCM" 2>&1 | grep -v Error | grep -v -f $TMP_PRO &&\
-/nas/data/xnat/pipeline/xnat-tools/XnatDataClient -u $USER -p $PASSWORD -r "$URL/$SERIES" -m DELETE+$HOME/pipeline/xnat-tools/XnatDataClient -u $USER -p $PASSWORD -r "$URL/$SERIES" -m DELETE
  
 #Dejar todo limpio #Dejar todo limpio
 rm -f  $TMP_PRO rm -f  $TMP_PRO
  
-</code>+</file>
 ++++ ++++
  
  
neuroimagen/xnat_pipelines.txt · Last modified: 2020/08/04 10:58 (external edit)