How to use ========== PyASL supports two types of workflows based on the type of ASL data: - 🧠 **Human Data Processing** - 🐭 **Preclinical Data Processing** Each workflow consists of multiple modules for data conversion, preprocessing, and feature map generation. ----- Human Data Processing --------------------- Step 1: Import and Convert Raw Data ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Before processing, you need to convert your dataset into ASL-BIDS format using the ``load_data`` function. This step also generates a ``data_description.json`` file that stores key metadata for further processing. πŸ“ Prepare Your Dataset ^^^^^^^^^^^^^^^^^^^^^^^ Your raw data should follow this basic structure: :: ExampleStudy/ rawdata/ sub001/ ses1/ anat/ sub001_ses1_t1w.hdr sub001_ses1_t1w.img perf/ sub001_ses1_run1.hdr sub001_ses1_run1.img sub001_ses1_run2.hdr sub001_ses1_run2.img sub001_ses1_M0.hdr sub001_ses1_M0.img ses2/ ... sub002/ ... βœ… Notes: - Data can be in **Analyze** (``.hdr`` + ``.img``) or **NIfTI** (``.nii``) format - The directory **must** contain a ``rawdata/`` folder and ``perf/`` subfolders - The ``anat/`` folder is optional - The **M0 file name must contain "M0"** - You may rename subject/session folders as needed βš™οΈ Define ASL metadata ^^^^^^^^^^^^^^^^^^^^^^^ Create a JSON file containing acquisition parameters. This will be used to generate valid BIDS sidecar files. .. note:: For a full list of available fields, see :doc:`json_parameters`. .. code-block:: json { "anat": { "Manufacturer": "Siemens", "ManufacturersModelName": "Prisma", "MagneticFieldStrength": 3.0, "RepetitionTime": 4.38, "EchoTime": 0.0204, "FlipAngle": 90 }, "M0": { "Manufacturer": "Siemens", "ManufacturersModelName": "Prisma", "MagneticFieldStrength": 3.0, "RepetitionTime": 4.38, "EchoTime": 0.0204, "FlipAngle": 90 }, "ASL": { "Manufacturer": "Siemens", "ManufacturersModelName": "Prisma", "MagneticFieldStrength": 3.0, "RepetitionTime": 4.38, "EchoTime": 0.0204, "FlipAngle": 90, "ArterialSpinLabelingType": "PCASL", "PostLabelingDelay": 2, "LabelingDuration": 1.8, "M0Type": "Separate", "MRAcquisitionType": "3D", "BackgroundSuppression": true, "BackgroundSuppressionNumberPulses": 2, "BackgroundSuppressionPulseTime": [ 1, 1 ], "LabelingEfficiency": 0.85, } } πŸš€ Run the Conversion ^^^^^^^^^^^^^^^^^^^^^ Use the following command to convert your dataset into ASL-BIDS format: .. code-block:: python from pyasl import load_data load_data( "path-to-your-dataset/ExampleStudy", "path-to-your-jsonfile/example_parameters.json", convert=True, is_singledelay=True, is_labelcontrol=False ) After conversion, all images are converted to ``.nii`` format, with accompanying ``.json`` and ``.tsv`` sidecars. A ``data_description.json`` file is also generated at the root of the dataset. Example output structure: :: ExampleStudy/ rawdata/ sub001/ ses1/ anat/ sub001_ses1_t1w.nii sub001_ses1_t1w.json perf/ sub001_ses1_run1.nii sub001_ses1_run1.json sub001_ses1_run1_aslcontext.tsv sub001_ses1_run2.nii sub001_ses1_run2.json sub001_ses1_run2_aslcontext.tsv sub001_ses1_M0.nii sub001_ses1_M0.json ses2/ ... sub002/ ... πŸ—ƒοΈ Load Existing BIDS Dataset (Skip Conversion) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ If your dataset is already in ASL-BIDS format, you can skip the conversion step and simply generate the ``data_description.json`` file: .. code-block:: python load_data("path-to-your-dataset/ExampleStudy", None, convert=False) Step 2: Run processing functions ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ After converting your data to ASL-BIDS format (see Step 1), you can run any of the following processing functions. All outputs will be saved in the ``derivatives/`` folder under your dataset root. Data preparation Step 1: Import / Convert to ASL-BIDS Use load_data to convert (or validate) your dataset and to create a data_description.json used by most modules. πŸ“ Expected raw layout ------------------ :: ExampleStudy/ rawdata/ sub001/ ses1/ anat/ # optional but recommended sub001_ses1_T1w.hdr sub001_ses1_T1w.img perf/ sub001_ses1_run1.hdr sub001_ses1_run1.img sub001_ses1_run2.hdr sub001_ses1_run2.img sub001_ses1_M0.hdr # M0 filename must contain β€œM0” sub001_ses1_M0.img ses2/ ... sub002/ ... βœ… Notes - Images can be **Analyze** (``.hdr`` + ``.img``) or **NIfTI** (``.nii``/``.nii.gz``). - The tree **must** contain ``rawdata///perf``; ``anat`` is optional. - Subject/session folder names are free-form. βš™οΈ Minimal acquisition JSON ------------------ .. note:: See :doc:json_parameters for the full schema supported by PyASL modules. .. code-block:: json { "anat": { "Manufacturer": "Siemens", "ManufacturersModelName": "Prisma", "MagneticFieldStrength": 3.0, "RepetitionTime": 4.38, "EchoTime": 0.0204, "FlipAngle": 90 }, "M0": { "Manufacturer": "Siemens", "ManufacturersModelName": "Prisma", "MagneticFieldStrength": 3.0, "RepetitionTime": 4.38, "EchoTime": 0.0204, "FlipAngle": 90 }, "ASL": { "Manufacturer": "Siemens", "ManufacturersModelName": "Prisma", "MagneticFieldStrength": 3.0, "RepetitionTime": 4.38, "EchoTime": 0.0204, "FlipAngle": 90, "ArterialSpinLabelingType": "PCASL", "PostLabelingDelay": 2.0, "LabelingDuration": 1.8, "M0Type": "Separate", "MRAcquisitionType": "3D", "BackgroundSuppression": true, "BackgroundSuppressionNumberPulses": 2, "BackgroundSuppressionPulseTime": [1.0, 1.0], "LabelingEfficiency": 0.85 } } πŸš€ Run conversion / validation ------------------ .. code-block:: python from pyasl import load_data load_data( "path-to-your-dataset/ExampleStudy", "path-to-your-jsonfile/example_parameters.json", convert=True, is_singledelay=True, is_labelcontrol=False ) After conversion you will get NIfTI + sidecars and a top-level ``data_description.json``: :: ExampleStudy/ rawdata/ sub001/ ses1/ anat/ sub001_ses1_T1w.nii sub001_ses1_T1w.json perf/ sub001_ses1_run1.nii sub001_ses1_run1.json sub001_ses1_run1_aslcontext.tsv sub001_ses1_run2.nii sub001_ses1_run2.json sub001_ses1_run2_aslcontext.tsv sub001_ses1_M0.nii sub001_ses1_M0.json ses2/ ... sub002/ ... πŸ—ƒοΈ Use existing ASL-BIDS (skip conversion) .. code-block:: python load_data("path-to-your-dataset/ExampleStudy", None, convert=False) ------------------ YAML-driven modular pipelines ------------------ There is a unified dispatcher: Python: pyasl.pipelines.run_pipeline.run_pipeline(input_dir, config_path) CLI: python -m pyasl.pipelines.run_pipeline --input --config Each YAML sets type: ... and a list of ordered steps. Below are ready-to-run examples for each pipeline family. ASLtbx (human, single-delay) ------------------ Runner: pyasl.pipelines.asltbx_pipeline.run_pipeline .. code-block:: yaml type: asltbx steps: - name: ResetOrientation - name: Realign - name: Coregister - name: Smooth params: { fwhm: [6, 6, 6] } - name: CreateMask params: { thres: 0.1 } - name: PerfusionQuantify params: QuantFlag: 0 MaskFlag: true MeanFlag: true BOLDFlag: false PerfFlag: false SubtractionType: 0 SubtrationOrder: 1 Timeshift: 0.5 MRICloud (human, single- or multi-delay) ------------------ Runner: pyasl.pipelines.asl_mricloud_pipeline.run_mricloud_pipeline .. code-block:: yaml type: mricloud steps: - name: MRICloudRescale - name: Realign - name: MRICloudCalculateDiffmap - name: MRICloudCalculateM0 params: { t1_tissue: 1165, bgs_eff: 0.93 } - name: MRICloudCalculateCBF params: { t1_blood: 1650, part_coef: 0.9, bgs_eff: 0.93 } - name: MRICloudReadMPR - name: MRICloudCoregMPR - name: MRICloudT1ROICBFAverage Multidelay variant (fit CBF + ATT, or estimate M0 across PLDs): .. code-block:: yaml type: mricloud steps: - name: MRICloudRescale - name: Realign - name: MRICloudCalculateDiffmap - name: MRICloudMultidelayCalculateM0 - name: MRICloudMultidelayCalculateCBFATT - name: MRICloudReadMPR - name: MRICloudCoregMPR DeepASL / DLASL (denoising) ------------------ Runner: pyasl.pipelines.dlasl_pipeline.run_dlasl_pipeline .. code-block:: yaml type: dlasl steps: - name: DLASLBuildMask params: out_mask: "{root}/derivatives/sub-001/ses-001/perf/dlasl_mask.nii.gz" - name: DLASLDenoiseCBF params: model_selection: 1 # 0=model_068, 1=model_099 glob_patterns: ["*aCBF*.nii", "*CBF*.nii.gz"] Oxford ASL (FSL oxford_asl) ------------------ Runner: pyasl.pipelines.oxford_asl_pipeline.run_oxford_asl_pipeline .. code-block:: yaml type: oxford_asl steps: - name: OxfordASLSplitM0 # splits out embedded m0scan if present - name: OxfordASLRun params: useStructural: true useCalibration: false wp: true mc: true ibf: rpt # Optional physiology: # bat: 1.3 # t1: 1.3 # t1b: 1.65 # sliceband: 1 Preclinical: single-delay pCASL ------------------ Runner: pyasl.pipelines.preclinical_pcasl_pipeline.run_preclinical_pcasl_pipeline .. code-block:: yaml type: pcasl steps: - name: BrukerLoader params: { root: "{root}", expno: 18, procno: 1 } - name: SteadyStateTrim params: { trim: 2 } - name: ControlLabelSplit params: { control_first: true } - name: MotionCheck - name: DiffImage - name: ComputeM0 params: { TR: from_meta, T1t: 1900 } - name: SlicePLDAdjust params: { SGap: 31, T1blood: 2800 } - name: CBFRelative params: { vmax: 10 } - name: BrainMask params: { thres: 0.2, open_iter: 2, close_iter: 2 } - name: SaveOutputs params: { config_echo: "" } Preclinical: multi-TI PASL (absolute CBF via T1 fit) ------------------ Runner: pyasl.pipelines.preclinical_mti_pipeline.run_preclinical_mti_pipeline .. code-block:: yaml type: mti steps: - name: NIfTILoader params: path: "{root}/data/preclinical_MTI_PASL/FAIREPI.img" target: AbsData savedir: "{root}/results_mti" - name: AbsCBF_T1Fit params: sel_index: [0, 2, 4, 6] glo_index: [1, 3, 5, 7] TI_list: [300, 600, 900, 1200] save_curves_every: 200 - name: SaveOutputs β€œCustom” pipeline (advanced power-user) ------------------ Runner: pyasl.pipelines.custom_pipeline.run_custom_pipeline Accepts step names or fully-qualified class names. Automatically resolves relative paths against data_dir. Replaces any "from_meta" value with Context[key] if available. .. code-block:: yaml type: custom steps: - module: pyasl.modules.preclinical_loader_nifti.NIfTILoader params: { path: "{root}/data.nii.gz", target: AbsData } - module: AbsCBF_T1Fit params: { sel_index: [0,2], glo_index: [1,3], TI_list: [300, 800] } - module: SaveOutputs Running the pipelines ------------------ .. code-block:: python from pyasl.pipelines.run_pipeline import run_pipeline run_pipeline("path/to/ExampleStudy", "path/to/config.yaml") CLI ~~~ .. code-block:: bash python -m pyasl.pipelines.run_pipeline \ --input path/to/ExampleStudy \ --config path/to/config.yaml ------------ Troubleshoot ------------ - **YAML not rendering in docs**: in rST use ``.. code-block:: yaml`` followed by a **blank line** and then indent the YAML by **at least 4 spaces**. - **Relative paths**: You can use ``{root}`` placeholder; runners resolve it to the dataset root. - **Missing modules**: check the exact step names listed above; for the custom runner you may use a fully-qualified class name. - **Oxford ASL**: requires FSL/oxford_asl in ``PATH``. The runner injects a safe CLI environment; you can extend via ``params.env``.