HINEC Run Directory Organization System¶
Overview¶
Every pipeline invocation writes into its own timestamped directory under hinec_runs/,
carrying the config it ran with. Two properties follow from that: nothing lands in the project
root, and a finished run states its own parameters, so results stay attributable after the
fact.
The division of labour is worth stating up front, because it is easy to get backwards. The
processed nim, the preprocessed references and the CSD cache belong to the data layer
(next to the input, e.g. data/ismrm2015/). Run directories hold tractography outputs.
main.m writes the canonical nim to the data layer and a copy into the run directory for
that run's own provenance; never treat a run directory as the home of a nim.
Directory Structure¶
hinec_runs/
├── run_<timestamp>_<config>/ # e.g. run_20250118_143045_hinec_dti_cubic
│ ├── config.yml # Copy of the config used
│ ├── run_info.txt # Run metadata
│ ├── overrides.txt # --set overrides, when any were given
│ ├── logs/
│ │ └── pipeline.log # Live MATLAB stdout/stderr
│ ├── intermediate/
│ │ ├── sample.nii.gz # Preprocessed DWI
│ │ ├── sample_M.nii.gz # Brain mask
│ │ ├── sample_WM_mask.nii.gz # White matter mask
│ │ ├── sample_GM_mask.nii.gz # Gray matter mask
│ │ ├── sample_CSF_mask.nii.gz # CSF mask
│ │ ├── parcellation_mask.nii.gz # Parcellation
│ │ └── SOURCE.txt # (run_tractography.sh) frozen DWI reference
│ ├── output/
│ │ └── processed.mat # Copy of the processed nim, with run_info
│ ├── tractography/
│ │ ├── tracks_hinec_<timestamp>.mat
│ │ └── diagnostics/
│ │ └── track_statistics.txt
│ ├── scoring/ # (--score) Renauld-2023 scorer output
│ └── figures/ # (run_visualization.sh) exported figures
│
└── latest -> run_<timestamp>_<config>/ # Symlink to the most recent run
run_tractography.sh copies — rather than symlinks — the DWI reference into its own
intermediate/ and records where it came from in SOURCE.txt. Freezing the reference means
a later reprocess of the source data cannot silently change what an old run was scored
against.
Usage¶
Basic Usage¶
# Full pipeline; the run directory is created for you
./bin/run_hinec.sh data/parcellation_sample/sample sample_output.mat
# With a specific config
./bin/run_hinec.sh data/parcellation_sample/sample sample_output.mat config/hinec_dti_cubic.yml
# Tractography only, against an already-preprocessed nim
./bin/run_tractography.sh hinec_dti_cubic --score
Run Directory Contents¶
config.yml: Exact copy of configuration used for reproducibility
run_info.txt: Complete run metadata
- Run ID and timestamp
- Configuration used
- System information (MATLAB version, platform)
- Git commit hash (if available)
- Directory structure
logs/pipeline.log: the live MATLAB stdout/stderr for the run; tail it to watch progress
overrides.txt: the --set key=value overrides applied on the command line, one per line.
Written only when overrides were given, so its presence tells you the run's config.yml is
not the whole story.
intermediate/: preprocessing artifacts
- Preprocessed DWI
- Brain mask (improved)
- Tissue masks (WM, GM, CSF)
- Parcellation mask
output/: a copy of the processed nim, with nim.run_info embedded for traceability. The
canonical copy lives in the data directory.
tractography/: Tractography results
- Track files (
.matformat) - diagnostics/track_statistics.txt: Detailed statistics
- Track counts and lengths
- Seeding statistics
- Computation time
- Parameters used
Accessing Results¶
Latest run (via symlink):
List all runs:
Compare configs:
Compare track counts:
View run metadata:
File Naming Convention¶
Run Directory Names¶
Format: run_YYYYMMDD_HHMMSS_<config_preset>
For example, a run launched with config/hinec_dti_cubic.yml at 14:30:45 on 18 January 2025
becomes run_20250118_143045_hinec_dti_cubic. The preset name is the config file's basename.
run_tractography.sh additionally tags the name with any --set overrides, so a sweep
produces distinguishable directories rather than a row of identical timestamps.
Track Files¶
Format: tracks_<algorithm>_YYYY-MM-DD_HH_MM_SS.mat
One file per run, named for the tracker that produced it: tracks_standard_*,
tracks_hinec_* or tracks_mmf_*. For example,
tracks_hinec_2025-01-18_14_30_45.mat.
Cleanup and Management¶
Delete Old Runs¶
# Delete one run
rm -rf hinec_runs/run_<timestamp>_<config>/
# Delete every run from a given month
find hinec_runs/ -maxdepth 1 -name "run_202501*" -type d -exec rm -rf {} +
# Keep only the 5 most recent
ls -t hinec_runs/ | tail -n +6 | xargs -I {} rm -rf hinec_runs/{}
Archive Runs¶
# Archive a run for long-term storage
run=run_<timestamp>_<config>
tar -czf "${run}.tar.gz" "hinec_runs/${run}/"
# Extract it again
tar -xzf "${run}.tar.gz" -C hinec_runs/
Integration with MATLAB¶
Direct MATLAB Usage¶
You can also use the run directory system directly from MATLAB:
% Load configuration
config = load_config_yaml('config/hinec_dti_cubic.yml');
% Create run directory
run_info = create_run_directory('config/hinec_dti_cubic.yml');
% Run preprocessing with run directory
main('sample', 'processed.mat', config, run_info);
% Run tractography with run directory
output_mat = fullfile(run_info.output_dir, 'processed.mat');
runTractography(output_mat, config, run_info);
% Access run directory
fprintf('Results in: %s\n', run_info.run_dir);
Custom Run Names¶
% Create run with custom description
run_info = create_run_directory('config/irontract.yml', ...
'run_name', 'my_experiment_v2', ...
'description', 'Testing new seeding strategy');
Troubleshooting¶
Issue: Can't find latest results¶
Solution: Use the latest symlink
Issue: Run directory not created¶
Check: the MATLAB path includes src/nim_utils/, where create_run_directory lives.
Issue: Running without a run directory¶
Pass no run_info and both main and runTractography fall back to writing beside their
inputs — main next to the image path, runTractography into tractography_results/. Every
code path that touches outputs branches on whether a run_info was supplied.
Issue: latest is a file, not a symlink¶
On Windows, create_run_directory writes a text file containing the path instead of creating
a symlink. Read the file to get the path:
Best Practices¶
-
Keep Configs: Never delete the YAML config files - they're copied to run directories for reproducibility
-
Document Experiments: Use run_info.txt or create additional README files in run directories
-
Regular Cleanup: Periodically archive or delete old experimental runs to save disk space
-
Comparison Workflow:
-
Version Control:
hinec_runs/is already in.gitignore, so runs never enter git.
Technical Details¶
Run Directory Creation¶
create_run_directory.m:
- Builds a timestamped directory name from the config file's basename
- Creates the subdirectories (
mkdiris idempotent, so reusing a name is safe) - Copies the config file to
config.yml - Writes
run_info.txtwith the run ID, timestamp, MATLAB version, platform, working directory, and the git commit, branch and clean/modified status when git is available - Updates the
latestlink - Returns the
run_infostruct
The returned struct carries the paths every downstream stage writes through:
| Field | Contents |
|---|---|
.run_dir |
The run directory itself |
.config_file |
Path to the copied config.yml |
.logs_dir |
<run_dir>/logs |
.intermediate_dir |
<run_dir>/intermediate |
.output_dir |
<run_dir>/output |
.tractography_dir |
<run_dir>/tractography |
.diagnostics_dir |
<run_dir>/tractography/diagnostics |
.run_id |
The directory's own name |
.timestamp |
yyyymmdd_HHMMSS |
Optional name-value arguments: base_dir (default hinec_runs), run_name (overrides the
generated name entirely) and description (recorded in run_info.txt).
Integration Points¶
main.m takes run_info as its fourth positional argument, redirects intermediate files to
run_info.intermediate_dir, writes its output copy to run_info.output_dir, and stores
run_info on the nim.
runTractography.m takes run_info as its third positional argument, writes tracks to
run_info.tractography_dir and diagnostics to run_info.diagnostics_dir.
bin/run_hinec.sh creates the run directory before anything else, then passes the same
run_info to both main and runTractography in one matlab -batch process.
bin/run_tractography.sh creates its own run directory, freezes the DWI reference into it,
and passes run_info to runTractography only.
Backward Compatibility¶
Callers that pass no run_info still work: main and runTractography fall back to writing
beside their inputs. The YAML config system is independent of run directories and works either
way.