neuroreg 0.2.0.dev0__tar.gz → 0.4.0.dev0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {neuroreg-0.2.0.dev0 → neuroreg-0.4.0.dev0}/PKG-INFO +162 -13
- {neuroreg-0.2.0.dev0 → neuroreg-0.4.0.dev0}/README.md +161 -12
- {neuroreg-0.2.0.dev0 → neuroreg-0.4.0.dev0}/neuroreg/__init__.py +2 -0
- {neuroreg-0.2.0.dev0 → neuroreg-0.4.0.dev0}/neuroreg/cli/coreg.py +1 -1
- {neuroreg-0.2.0.dev0 → neuroreg-0.4.0.dev0}/neuroreg/cli/lta.py +194 -6
- {neuroreg-0.2.0.dev0 → neuroreg-0.4.0.dev0}/neuroreg/cli/robreg.py +12 -21
- neuroreg-0.4.0.dev0/neuroreg/cli/segreg.py +264 -0
- {neuroreg-0.2.0.dev0 → neuroreg-0.4.0.dev0}/neuroreg/image/__init__.py +4 -1
- {neuroreg-0.2.0.dev0 → neuroreg-0.4.0.dev0}/neuroreg/image/map.py +136 -17
- {neuroreg-0.2.0.dev0 → neuroreg-0.4.0.dev0}/neuroreg/imreg/gd.py +11 -18
- {neuroreg-0.2.0.dev0 → neuroreg-0.4.0.dev0}/neuroreg/imreg/irls.py +3 -3
- {neuroreg-0.2.0.dev0 → neuroreg-0.4.0.dev0}/neuroreg/imreg/powell.py +7 -12
- {neuroreg-0.2.0.dev0 → neuroreg-0.4.0.dev0}/neuroreg/imreg/robreg.py +2 -2
- neuroreg-0.4.0.dev0/neuroreg/segreg/__init__.py +10 -0
- neuroreg-0.4.0.dev0/neuroreg/segreg/atlas.py +164 -0
- neuroreg-0.4.0.dev0/neuroreg/segreg/centroids.py +237 -0
- neuroreg-0.4.0.dev0/neuroreg/segreg/data/fsaverage_centroids.json +217 -0
- neuroreg-0.4.0.dev0/neuroreg/segreg/data/fsaverage_data.json +62 -0
- neuroreg-0.4.0.dev0/neuroreg/segreg/io.py +89 -0
- neuroreg-0.4.0.dev0/neuroreg/segreg/labels.py +105 -0
- neuroreg-0.4.0.dev0/neuroreg/segreg/points.py +368 -0
- neuroreg-0.4.0.dev0/neuroreg/segreg/register.py +442 -0
- {neuroreg-0.2.0.dev0 → neuroreg-0.4.0.dev0}/neuroreg/transforms/__init__.py +14 -0
- neuroreg-0.4.0.dev0/neuroreg/transforms/afni.py +150 -0
- neuroreg-0.4.0.dev0/neuroreg/transforms/antsmat.py +146 -0
- neuroreg-0.4.0.dev0/neuroreg/transforms/fsl.py +252 -0
- neuroreg-0.4.0.dev0/neuroreg/transforms/itk.py +203 -0
- {neuroreg-0.2.0.dev0 → neuroreg-0.4.0.dev0}/neuroreg/transforms/lta.py +98 -36
- neuroreg-0.4.0.dev0/neuroreg/transforms/niftyreg.py +118 -0
- neuroreg-0.4.0.dev0/neuroreg/transforms/regdat.py +206 -0
- neuroreg-0.4.0.dev0/neuroreg/transforms/xfm.py +226 -0
- {neuroreg-0.2.0.dev0 → neuroreg-0.4.0.dev0}/neuroreg.egg-info/PKG-INFO +162 -13
- {neuroreg-0.2.0.dev0 → neuroreg-0.4.0.dev0}/neuroreg.egg-info/SOURCES.txt +20 -2
- {neuroreg-0.2.0.dev0 → neuroreg-0.4.0.dev0}/neuroreg.egg-info/entry_points.txt +1 -0
- {neuroreg-0.2.0.dev0 → neuroreg-0.4.0.dev0}/pyproject.toml +5 -1
- {neuroreg-0.2.0.dev0 → neuroreg-0.4.0.dev0}/tests/test_coreg.py +2 -2
- neuroreg-0.4.0.dev0/tests/test_lta.py +861 -0
- neuroreg-0.4.0.dev0/tests/test_segreg.py +559 -0
- neuroreg-0.2.0.dev0/tests/test_lta_diff.py +0 -397
- {neuroreg-0.2.0.dev0 → neuroreg-0.4.0.dev0}/LICENSE +0 -0
- {neuroreg-0.2.0.dev0 → neuroreg-0.4.0.dev0}/neuroreg/_sys_info.py +0 -0
- {neuroreg-0.2.0.dev0 → neuroreg-0.4.0.dev0}/neuroreg/_version.py +0 -0
- {neuroreg-0.2.0.dev0 → neuroreg-0.4.0.dev0}/neuroreg/bbreg/__init__.py +0 -0
- {neuroreg-0.2.0.dev0 → neuroreg-0.4.0.dev0}/neuroreg/bbreg/cost.py +0 -0
- {neuroreg-0.2.0.dev0 → neuroreg-0.4.0.dev0}/neuroreg/bbreg/io.py +0 -0
- {neuroreg-0.2.0.dev0 → neuroreg-0.4.0.dev0}/neuroreg/bbreg/optimize.py +0 -0
- {neuroreg-0.2.0.dev0 → neuroreg-0.4.0.dev0}/neuroreg/bbreg/projection.py +0 -0
- {neuroreg-0.2.0.dev0 → neuroreg-0.4.0.dev0}/neuroreg/bbreg/register.py +0 -0
- {neuroreg-0.2.0.dev0 → neuroreg-0.4.0.dev0}/neuroreg/bbreg/sampling.py +0 -0
- {neuroreg-0.2.0.dev0 → neuroreg-0.4.0.dev0}/neuroreg/cli/__init__.py +0 -0
- {neuroreg-0.2.0.dev0 → neuroreg-0.4.0.dev0}/neuroreg/cli/bbreg.py +0 -0
- {neuroreg-0.2.0.dev0 → neuroreg-0.4.0.dev0}/neuroreg/cli/sys_info.py +0 -0
- {neuroreg-0.2.0.dev0 → neuroreg-0.4.0.dev0}/neuroreg/image/centroid.py +0 -0
- {neuroreg-0.2.0.dev0 → neuroreg-0.4.0.dev0}/neuroreg/image/pyramid.py +0 -0
- {neuroreg-0.2.0.dev0 → neuroreg-0.4.0.dev0}/neuroreg/image/segmentation.py +0 -0
- {neuroreg-0.2.0.dev0 → neuroreg-0.4.0.dev0}/neuroreg/image/smooth.py +0 -0
- {neuroreg-0.2.0.dev0 → neuroreg-0.4.0.dev0}/neuroreg/imreg/__init__.py +0 -0
- {neuroreg-0.2.0.dev0 → neuroreg-0.4.0.dev0}/neuroreg/imreg/coreg.py +0 -0
- {neuroreg-0.2.0.dev0 → neuroreg-0.4.0.dev0}/neuroreg/imreg/device.py +0 -0
- {neuroreg-0.2.0.dev0 → neuroreg-0.4.0.dev0}/neuroreg/imreg/init.py +0 -0
- {neuroreg-0.2.0.dev0 → neuroreg-0.4.0.dev0}/neuroreg/imreg/losses.py +0 -0
- {neuroreg-0.2.0.dev0 → neuroreg-0.4.0.dev0}/neuroreg/imreg/optimize.py +0 -0
- {neuroreg-0.2.0.dev0 → neuroreg-0.4.0.dev0}/neuroreg/imreg/reg_model.py +0 -0
- {neuroreg-0.2.0.dev0 → neuroreg-0.4.0.dev0}/neuroreg/imreg/robust.py +0 -0
- {neuroreg-0.2.0.dev0 → neuroreg-0.4.0.dev0}/neuroreg/transforms/matrices.py +0 -0
- {neuroreg-0.2.0.dev0 → neuroreg-0.4.0.dev0}/neuroreg/transforms/metrics.py +0 -0
- {neuroreg-0.2.0.dev0 → neuroreg-0.4.0.dev0}/neuroreg.egg-info/dependency_links.txt +0 -0
- {neuroreg-0.2.0.dev0 → neuroreg-0.4.0.dev0}/neuroreg.egg-info/requires.txt +0 -0
- {neuroreg-0.2.0.dev0 → neuroreg-0.4.0.dev0}/neuroreg.egg-info/top_level.txt +0 -0
- {neuroreg-0.2.0.dev0 → neuroreg-0.4.0.dev0}/setup.cfg +0 -0
- {neuroreg-0.2.0.dev0 → neuroreg-0.4.0.dev0}/tests/test_bbreg.py +0 -0
- {neuroreg-0.2.0.dev0 → neuroreg-0.4.0.dev0}/tests/test_cli.py +0 -0
- {neuroreg-0.2.0.dev0 → neuroreg-0.4.0.dev0}/tests/test_irls.py +0 -0
- {neuroreg-0.2.0.dev0 → neuroreg-0.4.0.dev0}/tests/test_robreg.py +0 -0
- {neuroreg-0.2.0.dev0 → neuroreg-0.4.0.dev0}/tests/test_robust_weights.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: neuroreg
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.4.0.dev0
|
|
4
4
|
Summary: A package for 3D neuroimaging registration with PyTorch.
|
|
5
5
|
Author: Martin Reuter
|
|
6
6
|
Maintainer: Martin Reuter
|
|
@@ -105,7 +105,9 @@ The main user-facing tools are:
|
|
|
105
105
|
(Powell-based by default, analogous to FreeSurfer/SPM `mri_coreg`)
|
|
106
106
|
- **`bbreg`** – boundary-based registration using cortical WM surfaces or segmentations
|
|
107
107
|
(extending FreeSurfer's `bbregister`)
|
|
108
|
-
- **`
|
|
108
|
+
- **`segreg`** – segmentation-based registration via label centroids
|
|
109
|
+
(rigid/affine, including atlas-centroid and upright/self-flip modes)
|
|
110
|
+
- **`lta`** – transform comparison, inversion, concatenation, and conversion utilities
|
|
109
111
|
|
|
110
112
|
This project is a work-in-progress in an early development stage. It is developed by
|
|
111
113
|
the creator of FreeSurfer's `mri_robust_register` as an efficient pure Python
|
|
@@ -312,15 +314,65 @@ Run `bbreg -h` for a full argument summary with defaults.
|
|
|
312
314
|
|
|
313
315
|
---
|
|
314
316
|
|
|
315
|
-
### `
|
|
317
|
+
### `segreg` — segmentation-based registration
|
|
316
318
|
|
|
317
|
-
|
|
318
|
-
|
|
319
|
+
Registers a moving segmentation by aligning label centroids to another
|
|
320
|
+
segmentation, to bundled atlas centroids such as `fsaverage`, or to a
|
|
321
|
+
left-right flipped self target for upright/midspace workflows. The centroid
|
|
322
|
+
fit now supports translation-only (`3`), rigid (`6`), similarity /
|
|
323
|
+
global-scale (`7`), anisotropic no-shear scaling (`9`), or full affine
|
|
324
|
+
(`12`) transforms.
|
|
325
|
+
|
|
326
|
+
`segreg` can also write mapped outputs while the package does not yet have a
|
|
327
|
+
separate transform-application CLI. If `--movimg` is provided, `--mapmov` and
|
|
328
|
+
`--mapmovhdr` map that intensity image with the recovered transform; otherwise
|
|
329
|
+
those outputs map the moving segmentation itself.
|
|
319
330
|
|
|
320
331
|
```
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
332
|
+
segreg --mov <moving_seg.mgz> (--ref <ref_seg.mgz> | --ref-centroids <centroids.json> | --atlas fsaverage | --flipped) [options]
|
|
333
|
+
```
|
|
334
|
+
|
|
335
|
+
**Common outputs**
|
|
336
|
+
|
|
337
|
+
- `--lta FILE` writes the recovered transform as an LTA.
|
|
338
|
+
- `--movimg FILE` provides a separate intensity image for `--mapmov` or `--mapmovhdr`.
|
|
339
|
+
- `--mapmov FILE` writes a resliced mapped output. It maps `--movimg` when provided; otherwise it reslices the moving segmentation itself.
|
|
340
|
+
- `--mapmovhdr FILE` writes a header-only mapped output. It maps `--movimg` when provided; otherwise it remaps the moving segmentation itself.
|
|
341
|
+
|
|
342
|
+
**Examples**
|
|
343
|
+
|
|
344
|
+
```bash
|
|
345
|
+
# Register a subject segmentation to another segmentation
|
|
346
|
+
segreg --mov sub-01/aparc+aseg.mgz --ref sub-02/aparc+aseg.mgz \
|
|
347
|
+
--lta sub01_to_sub02.lta
|
|
348
|
+
|
|
349
|
+
# Register a segmentation, then map a separate intensity image with the same transform
|
|
350
|
+
segreg --mov subj/mri/aparc+aseg.mgz --movimg subj/mri/orig.mgz --atlas fsaverage \
|
|
351
|
+
--lta subj_to_fsaverage.lta --mapmov orig_in_fsaverage_space.mgz
|
|
352
|
+
|
|
353
|
+
# If --movimg is omitted, --mapmov maps the segmentation itself
|
|
354
|
+
segreg --mov subj/mri/aparc+aseg.mgz --atlas fsaverage \
|
|
355
|
+
--mapmov aparc_aseg_in_fsaverage_space.mgz
|
|
356
|
+
|
|
357
|
+
# Export centroid JSON only
|
|
358
|
+
segreg --mov subj/mri/aparc+aseg.mgz --atlas fsaverage \
|
|
359
|
+
--write-mov-centroids subj_centroids.json --write-ref-centroids fsaverage_centroids.json
|
|
360
|
+
```
|
|
361
|
+
|
|
362
|
+
Run `segreg -h` for a full argument summary with defaults.
|
|
363
|
+
|
|
364
|
+
---
|
|
365
|
+
|
|
366
|
+
### `lta` — LTA and linear-transform utilities
|
|
367
|
+
|
|
368
|
+
Unified command for manipulating FreeSurfer-adjacent linear transforms with four
|
|
369
|
+
subcommands: `diff`, `invert`, `concat`, and `convert`.
|
|
370
|
+
|
|
371
|
+
```
|
|
372
|
+
lta diff LTA1 [LTA2] [options] # Compare transforms
|
|
373
|
+
lta invert INPUT OUTPUT # Invert a transform
|
|
374
|
+
lta concat LTA1 LTA2 OUTPUT # Concatenate two transforms
|
|
375
|
+
lta convert INPUT OUTPUT [--src-img SRC --dst-img DST] # Convert formats
|
|
324
376
|
```
|
|
325
377
|
|
|
326
378
|
---
|
|
@@ -418,8 +470,104 @@ lta concat fMRI_to_T1.lta T1_to_MNI.lta fMRI_to_MNI.lta
|
|
|
418
470
|
lta concat moving_to_intermediate.lta intermediate_to_fixed.lta moving_to_fixed.lta
|
|
419
471
|
```
|
|
420
472
|
|
|
473
|
+
---
|
|
474
|
+
|
|
475
|
+
#### `lta convert` — Convert between transform formats
|
|
476
|
+
|
|
477
|
+
Converts between `.lta`, `.xfm`, volumetric tkregister `.dat`/`.reg`, FSL `.mat`/`.fslmat`, ITK/ANTs 3D affine text transforms, experimental ANTs Matlab-format affine transforms, experimental AFNI affine text transforms, and NiftyReg affine text matrices by normalizing through an internal RAS-to-RAS `LTA`.
|
|
478
|
+
|
|
479
|
+
**Usage**
|
|
480
|
+
|
|
481
|
+
```
|
|
482
|
+
lta convert INPUT OUTPUT [--in-format {lta,xfm,fsl,regdat,itk,antsmat,afni,niftyreg}]
|
|
483
|
+
[--out-format {lta,xfm,fsl,regdat,itk,antsmat,afni,niftyreg}]
|
|
484
|
+
[--src-img SRC] [--dst-img DST]
|
|
485
|
+
[--out-type {ras2ras,vox2vox}]
|
|
486
|
+
[--subject SUBJECT] [--fscale FSCALE]
|
|
487
|
+
[--float2int {tkregister,round,floor}]
|
|
488
|
+
```
|
|
489
|
+
|
|
490
|
+
**Supported formats**
|
|
491
|
+
|
|
492
|
+
- `.lta` — FreeSurfer Linear Transform Array
|
|
493
|
+
- `.xfm` — MNI/MINC linear transform
|
|
494
|
+
- `.dat` — old tkregister volumetric `register.dat` format
|
|
495
|
+
- `.mat` / `.fslmat` — FSL FLIRT affine matrix
|
|
496
|
+
- `.tfm` — ITK/ANTs 3D affine text transform
|
|
497
|
+
- `*GenericAffine.mat` — experimental ANTs / ITK Matlab-format affine transform
|
|
498
|
+
- `.aff12.1D` — experimental AFNI affine text matrix
|
|
499
|
+
- `.niftyreg.txt` — NiftyReg 3D affine text matrix
|
|
500
|
+
|
|
421
501
|
**Notes**
|
|
422
502
|
|
|
503
|
+
- Reading `register.dat` requires both `--src-img` and `--dst-img`, because the
|
|
504
|
+
stored matrix is defined in tkregister coordinates rather than scanner RAS.
|
|
505
|
+
- Reading FSL `.mat` / `.fslmat` also requires both `--src-img` and `--dst-img`,
|
|
506
|
+
because the stored matrix is defined in FSL voxel conventions rather than
|
|
507
|
+
scanner RAS.
|
|
508
|
+
- Reading `.xfm`, ITK/ANTs text affines, experimental ANTs `.mat`, experimental
|
|
509
|
+
AFNI affine text, or NiftyReg text matrices without images still preserves the
|
|
510
|
+
transform matrix, but the resulting LTA geometry blocks stay marked as `valid=0`
|
|
511
|
+
unless you provide `--src-img` and `--dst-img`.
|
|
512
|
+
- Use `--in-format` / `--out-format` for ambiguous filenames such as `.txt`, `.1D`, or `.mat`.
|
|
513
|
+
- ITK/ANTs text support currently targets 3D affine transforms only, not binary or
|
|
514
|
+
composite transform files.
|
|
515
|
+
- Experimental ANTs `.mat` support is implemented via SciPy using ITK Matlab IO semantics.
|
|
516
|
+
- Experimental AFNI support targets affine text matrices in AFNI's DICOM/LPS convention.
|
|
517
|
+
- NiftyReg stores the inverse target-to-source RAS matrix in the file, matching
|
|
518
|
+
FreeSurfer's `lta_convert` handling.
|
|
519
|
+
- `--subject`, `--fscale`, and `--float2int` apply when writing `register.dat`.
|
|
520
|
+
- `--out-type` applies when writing `.lta` output.
|
|
521
|
+
|
|
522
|
+
**Examples**
|
|
523
|
+
|
|
524
|
+
```bash
|
|
525
|
+
# XFM -> LTA with explicit image geometry
|
|
526
|
+
lta convert talairach.xfm talairach.lta --src-img mov.mgz --dst-img ref.mgz
|
|
527
|
+
|
|
528
|
+
# LTA -> XFM
|
|
529
|
+
lta convert sub01_to_mni.lta sub01_to_mni.xfm
|
|
530
|
+
|
|
531
|
+
# LTA -> tkregister register.dat
|
|
532
|
+
lta convert bold_to_orig.lta bold_to_orig.dat --subject sub-01 --fscale 0.1
|
|
533
|
+
|
|
534
|
+
# tkregister register.dat -> LTA
|
|
535
|
+
lta convert bold_to_orig.dat bold_to_orig.lta --src-img bold.nii.gz --dst-img orig.mgz
|
|
536
|
+
|
|
537
|
+
# LTA -> FSL FLIRT matrix
|
|
538
|
+
lta convert bold_to_orig.lta bold_to_orig.mat
|
|
539
|
+
|
|
540
|
+
# FSL FLIRT matrix -> LTA
|
|
541
|
+
lta convert bold_to_orig.mat bold_to_orig_from_fsl.lta --src-img bold.nii.gz --dst-img orig.mgz
|
|
542
|
+
|
|
543
|
+
# LTA -> ITK/ANTs text affine
|
|
544
|
+
lta convert bold_to_orig.lta bold_to_orig.tfm
|
|
545
|
+
|
|
546
|
+
# ITK/ANTs text affine (.txt requires explicit format override)
|
|
547
|
+
lta convert bold_to_orig.txt bold_to_orig_from_itk.lta --in-format itk --src-img bold.nii.gz --dst-img orig.mgz
|
|
548
|
+
|
|
549
|
+
# LTA -> experimental ANTs GenericAffine .mat
|
|
550
|
+
lta convert bold_to_orig.lta bold_to_orig0GenericAffine.mat
|
|
551
|
+
|
|
552
|
+
# Experimental ANTs GenericAffine .mat -> LTA (.mat is otherwise assumed FSL)
|
|
553
|
+
lta convert bold_to_orig0GenericAffine.mat bold_to_orig_from_antsmat.lta
|
|
554
|
+
lta convert some_affine.mat bold_to_orig_from_antsmat.lta --in-format antsmat
|
|
555
|
+
|
|
556
|
+
# LTA -> experimental AFNI affine text
|
|
557
|
+
lta convert bold_to_orig.lta bold_to_orig.aff12.1D
|
|
558
|
+
|
|
559
|
+
# Experimental AFNI affine text -> LTA (.1D may need explicit format override)
|
|
560
|
+
lta convert bold_to_orig.aff12.1D bold_to_orig_from_afni.lta
|
|
561
|
+
|
|
562
|
+
# LTA -> NiftyReg affine text matrix (.txt requires explicit format override)
|
|
563
|
+
lta convert bold_to_orig.lta bold_to_orig.txt --out-format niftyreg
|
|
564
|
+
|
|
565
|
+
# NiftyReg affine text matrix -> LTA
|
|
566
|
+
lta convert bold_to_orig.txt bold_to_orig_from_niftyreg.lta --in-format niftyreg
|
|
567
|
+
```
|
|
568
|
+
|
|
569
|
+
**General notes**
|
|
570
|
+
|
|
423
571
|
- All metrics are numerically matched to FreeSurfer's `lta_diff` (except for a
|
|
424
572
|
known bug in the C++ single-transform corner metric, which is fixed here).
|
|
425
573
|
- When only one LTA is supplied to `diff`, the transform is compared against identity.
|
|
@@ -486,11 +634,12 @@ transform_bbreg, model_bbreg = bbreg(
|
|
|
486
634
|
|
|
487
635
|
Current DOF support is:
|
|
488
636
|
|
|
489
|
-
| Command / API path | Supported DOF
|
|
490
|
-
|
|
491
|
-
| `robreg` / public `robreg()` | `6` only
|
|
492
|
-
| `coreg` / public `coreg()` | `3`, `6`, `9`, `12`
|
|
493
|
-
| `bbreg` / public `bbreg()` | `6`, `9`, `12`
|
|
637
|
+
| Command / API path | Supported DOF |
|
|
638
|
+
|------------------------------|--------------------------|
|
|
639
|
+
| `robreg` / public `robreg()` | `6` only |
|
|
640
|
+
| `coreg` / public `coreg()` | `3`, `6`, `9`, `12` |
|
|
641
|
+
| `bbreg` / public `bbreg()` | `6`, `9`, `12` |
|
|
642
|
+
| `segreg` / public `segreg()` | `3`, `6`, `7`, `9`, `12` |
|
|
494
643
|
|
|
495
644
|
The public `robreg` path is intentionally rigid-only for now because it tracks
|
|
496
645
|
the current IRLS implementation.
|
|
@@ -15,7 +15,9 @@ The main user-facing tools are:
|
|
|
15
15
|
(Powell-based by default, analogous to FreeSurfer/SPM `mri_coreg`)
|
|
16
16
|
- **`bbreg`** – boundary-based registration using cortical WM surfaces or segmentations
|
|
17
17
|
(extending FreeSurfer's `bbregister`)
|
|
18
|
-
- **`
|
|
18
|
+
- **`segreg`** – segmentation-based registration via label centroids
|
|
19
|
+
(rigid/affine, including atlas-centroid and upright/self-flip modes)
|
|
20
|
+
- **`lta`** – transform comparison, inversion, concatenation, and conversion utilities
|
|
19
21
|
|
|
20
22
|
This project is a work-in-progress in an early development stage. It is developed by
|
|
21
23
|
the creator of FreeSurfer's `mri_robust_register` as an efficient pure Python
|
|
@@ -222,15 +224,65 @@ Run `bbreg -h` for a full argument summary with defaults.
|
|
|
222
224
|
|
|
223
225
|
---
|
|
224
226
|
|
|
225
|
-
### `
|
|
227
|
+
### `segreg` — segmentation-based registration
|
|
226
228
|
|
|
227
|
-
|
|
228
|
-
|
|
229
|
+
Registers a moving segmentation by aligning label centroids to another
|
|
230
|
+
segmentation, to bundled atlas centroids such as `fsaverage`, or to a
|
|
231
|
+
left-right flipped self target for upright/midspace workflows. The centroid
|
|
232
|
+
fit now supports translation-only (`3`), rigid (`6`), similarity /
|
|
233
|
+
global-scale (`7`), anisotropic no-shear scaling (`9`), or full affine
|
|
234
|
+
(`12`) transforms.
|
|
235
|
+
|
|
236
|
+
`segreg` can also write mapped outputs while the package does not yet have a
|
|
237
|
+
separate transform-application CLI. If `--movimg` is provided, `--mapmov` and
|
|
238
|
+
`--mapmovhdr` map that intensity image with the recovered transform; otherwise
|
|
239
|
+
those outputs map the moving segmentation itself.
|
|
229
240
|
|
|
230
241
|
```
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
242
|
+
segreg --mov <moving_seg.mgz> (--ref <ref_seg.mgz> | --ref-centroids <centroids.json> | --atlas fsaverage | --flipped) [options]
|
|
243
|
+
```
|
|
244
|
+
|
|
245
|
+
**Common outputs**
|
|
246
|
+
|
|
247
|
+
- `--lta FILE` writes the recovered transform as an LTA.
|
|
248
|
+
- `--movimg FILE` provides a separate intensity image for `--mapmov` or `--mapmovhdr`.
|
|
249
|
+
- `--mapmov FILE` writes a resliced mapped output. It maps `--movimg` when provided; otherwise it reslices the moving segmentation itself.
|
|
250
|
+
- `--mapmovhdr FILE` writes a header-only mapped output. It maps `--movimg` when provided; otherwise it remaps the moving segmentation itself.
|
|
251
|
+
|
|
252
|
+
**Examples**
|
|
253
|
+
|
|
254
|
+
```bash
|
|
255
|
+
# Register a subject segmentation to another segmentation
|
|
256
|
+
segreg --mov sub-01/aparc+aseg.mgz --ref sub-02/aparc+aseg.mgz \
|
|
257
|
+
--lta sub01_to_sub02.lta
|
|
258
|
+
|
|
259
|
+
# Register a segmentation, then map a separate intensity image with the same transform
|
|
260
|
+
segreg --mov subj/mri/aparc+aseg.mgz --movimg subj/mri/orig.mgz --atlas fsaverage \
|
|
261
|
+
--lta subj_to_fsaverage.lta --mapmov orig_in_fsaverage_space.mgz
|
|
262
|
+
|
|
263
|
+
# If --movimg is omitted, --mapmov maps the segmentation itself
|
|
264
|
+
segreg --mov subj/mri/aparc+aseg.mgz --atlas fsaverage \
|
|
265
|
+
--mapmov aparc_aseg_in_fsaverage_space.mgz
|
|
266
|
+
|
|
267
|
+
# Export centroid JSON only
|
|
268
|
+
segreg --mov subj/mri/aparc+aseg.mgz --atlas fsaverage \
|
|
269
|
+
--write-mov-centroids subj_centroids.json --write-ref-centroids fsaverage_centroids.json
|
|
270
|
+
```
|
|
271
|
+
|
|
272
|
+
Run `segreg -h` for a full argument summary with defaults.
|
|
273
|
+
|
|
274
|
+
---
|
|
275
|
+
|
|
276
|
+
### `lta` — LTA and linear-transform utilities
|
|
277
|
+
|
|
278
|
+
Unified command for manipulating FreeSurfer-adjacent linear transforms with four
|
|
279
|
+
subcommands: `diff`, `invert`, `concat`, and `convert`.
|
|
280
|
+
|
|
281
|
+
```
|
|
282
|
+
lta diff LTA1 [LTA2] [options] # Compare transforms
|
|
283
|
+
lta invert INPUT OUTPUT # Invert a transform
|
|
284
|
+
lta concat LTA1 LTA2 OUTPUT # Concatenate two transforms
|
|
285
|
+
lta convert INPUT OUTPUT [--src-img SRC --dst-img DST] # Convert formats
|
|
234
286
|
```
|
|
235
287
|
|
|
236
288
|
---
|
|
@@ -328,8 +380,104 @@ lta concat fMRI_to_T1.lta T1_to_MNI.lta fMRI_to_MNI.lta
|
|
|
328
380
|
lta concat moving_to_intermediate.lta intermediate_to_fixed.lta moving_to_fixed.lta
|
|
329
381
|
```
|
|
330
382
|
|
|
383
|
+
---
|
|
384
|
+
|
|
385
|
+
#### `lta convert` — Convert between transform formats
|
|
386
|
+
|
|
387
|
+
Converts between `.lta`, `.xfm`, volumetric tkregister `.dat`/`.reg`, FSL `.mat`/`.fslmat`, ITK/ANTs 3D affine text transforms, experimental ANTs Matlab-format affine transforms, experimental AFNI affine text transforms, and NiftyReg affine text matrices by normalizing through an internal RAS-to-RAS `LTA`.
|
|
388
|
+
|
|
389
|
+
**Usage**
|
|
390
|
+
|
|
391
|
+
```
|
|
392
|
+
lta convert INPUT OUTPUT [--in-format {lta,xfm,fsl,regdat,itk,antsmat,afni,niftyreg}]
|
|
393
|
+
[--out-format {lta,xfm,fsl,regdat,itk,antsmat,afni,niftyreg}]
|
|
394
|
+
[--src-img SRC] [--dst-img DST]
|
|
395
|
+
[--out-type {ras2ras,vox2vox}]
|
|
396
|
+
[--subject SUBJECT] [--fscale FSCALE]
|
|
397
|
+
[--float2int {tkregister,round,floor}]
|
|
398
|
+
```
|
|
399
|
+
|
|
400
|
+
**Supported formats**
|
|
401
|
+
|
|
402
|
+
- `.lta` — FreeSurfer Linear Transform Array
|
|
403
|
+
- `.xfm` — MNI/MINC linear transform
|
|
404
|
+
- `.dat` — old tkregister volumetric `register.dat` format
|
|
405
|
+
- `.mat` / `.fslmat` — FSL FLIRT affine matrix
|
|
406
|
+
- `.tfm` — ITK/ANTs 3D affine text transform
|
|
407
|
+
- `*GenericAffine.mat` — experimental ANTs / ITK Matlab-format affine transform
|
|
408
|
+
- `.aff12.1D` — experimental AFNI affine text matrix
|
|
409
|
+
- `.niftyreg.txt` — NiftyReg 3D affine text matrix
|
|
410
|
+
|
|
331
411
|
**Notes**
|
|
332
412
|
|
|
413
|
+
- Reading `register.dat` requires both `--src-img` and `--dst-img`, because the
|
|
414
|
+
stored matrix is defined in tkregister coordinates rather than scanner RAS.
|
|
415
|
+
- Reading FSL `.mat` / `.fslmat` also requires both `--src-img` and `--dst-img`,
|
|
416
|
+
because the stored matrix is defined in FSL voxel conventions rather than
|
|
417
|
+
scanner RAS.
|
|
418
|
+
- Reading `.xfm`, ITK/ANTs text affines, experimental ANTs `.mat`, experimental
|
|
419
|
+
AFNI affine text, or NiftyReg text matrices without images still preserves the
|
|
420
|
+
transform matrix, but the resulting LTA geometry blocks stay marked as `valid=0`
|
|
421
|
+
unless you provide `--src-img` and `--dst-img`.
|
|
422
|
+
- Use `--in-format` / `--out-format` for ambiguous filenames such as `.txt`, `.1D`, or `.mat`.
|
|
423
|
+
- ITK/ANTs text support currently targets 3D affine transforms only, not binary or
|
|
424
|
+
composite transform files.
|
|
425
|
+
- Experimental ANTs `.mat` support is implemented via SciPy using ITK Matlab IO semantics.
|
|
426
|
+
- Experimental AFNI support targets affine text matrices in AFNI's DICOM/LPS convention.
|
|
427
|
+
- NiftyReg stores the inverse target-to-source RAS matrix in the file, matching
|
|
428
|
+
FreeSurfer's `lta_convert` handling.
|
|
429
|
+
- `--subject`, `--fscale`, and `--float2int` apply when writing `register.dat`.
|
|
430
|
+
- `--out-type` applies when writing `.lta` output.
|
|
431
|
+
|
|
432
|
+
**Examples**
|
|
433
|
+
|
|
434
|
+
```bash
|
|
435
|
+
# XFM -> LTA with explicit image geometry
|
|
436
|
+
lta convert talairach.xfm talairach.lta --src-img mov.mgz --dst-img ref.mgz
|
|
437
|
+
|
|
438
|
+
# LTA -> XFM
|
|
439
|
+
lta convert sub01_to_mni.lta sub01_to_mni.xfm
|
|
440
|
+
|
|
441
|
+
# LTA -> tkregister register.dat
|
|
442
|
+
lta convert bold_to_orig.lta bold_to_orig.dat --subject sub-01 --fscale 0.1
|
|
443
|
+
|
|
444
|
+
# tkregister register.dat -> LTA
|
|
445
|
+
lta convert bold_to_orig.dat bold_to_orig.lta --src-img bold.nii.gz --dst-img orig.mgz
|
|
446
|
+
|
|
447
|
+
# LTA -> FSL FLIRT matrix
|
|
448
|
+
lta convert bold_to_orig.lta bold_to_orig.mat
|
|
449
|
+
|
|
450
|
+
# FSL FLIRT matrix -> LTA
|
|
451
|
+
lta convert bold_to_orig.mat bold_to_orig_from_fsl.lta --src-img bold.nii.gz --dst-img orig.mgz
|
|
452
|
+
|
|
453
|
+
# LTA -> ITK/ANTs text affine
|
|
454
|
+
lta convert bold_to_orig.lta bold_to_orig.tfm
|
|
455
|
+
|
|
456
|
+
# ITK/ANTs text affine (.txt requires explicit format override)
|
|
457
|
+
lta convert bold_to_orig.txt bold_to_orig_from_itk.lta --in-format itk --src-img bold.nii.gz --dst-img orig.mgz
|
|
458
|
+
|
|
459
|
+
# LTA -> experimental ANTs GenericAffine .mat
|
|
460
|
+
lta convert bold_to_orig.lta bold_to_orig0GenericAffine.mat
|
|
461
|
+
|
|
462
|
+
# Experimental ANTs GenericAffine .mat -> LTA (.mat is otherwise assumed FSL)
|
|
463
|
+
lta convert bold_to_orig0GenericAffine.mat bold_to_orig_from_antsmat.lta
|
|
464
|
+
lta convert some_affine.mat bold_to_orig_from_antsmat.lta --in-format antsmat
|
|
465
|
+
|
|
466
|
+
# LTA -> experimental AFNI affine text
|
|
467
|
+
lta convert bold_to_orig.lta bold_to_orig.aff12.1D
|
|
468
|
+
|
|
469
|
+
# Experimental AFNI affine text -> LTA (.1D may need explicit format override)
|
|
470
|
+
lta convert bold_to_orig.aff12.1D bold_to_orig_from_afni.lta
|
|
471
|
+
|
|
472
|
+
# LTA -> NiftyReg affine text matrix (.txt requires explicit format override)
|
|
473
|
+
lta convert bold_to_orig.lta bold_to_orig.txt --out-format niftyreg
|
|
474
|
+
|
|
475
|
+
# NiftyReg affine text matrix -> LTA
|
|
476
|
+
lta convert bold_to_orig.txt bold_to_orig_from_niftyreg.lta --in-format niftyreg
|
|
477
|
+
```
|
|
478
|
+
|
|
479
|
+
**General notes**
|
|
480
|
+
|
|
333
481
|
- All metrics are numerically matched to FreeSurfer's `lta_diff` (except for a
|
|
334
482
|
known bug in the C++ single-transform corner metric, which is fixed here).
|
|
335
483
|
- When only one LTA is supplied to `diff`, the transform is compared against identity.
|
|
@@ -396,11 +544,12 @@ transform_bbreg, model_bbreg = bbreg(
|
|
|
396
544
|
|
|
397
545
|
Current DOF support is:
|
|
398
546
|
|
|
399
|
-
| Command / API path | Supported DOF
|
|
400
|
-
|
|
401
|
-
| `robreg` / public `robreg()` | `6` only
|
|
402
|
-
| `coreg` / public `coreg()` | `3`, `6`, `9`, `12`
|
|
403
|
-
| `bbreg` / public `bbreg()` | `6`, `9`, `12`
|
|
547
|
+
| Command / API path | Supported DOF |
|
|
548
|
+
|------------------------------|--------------------------|
|
|
549
|
+
| `robreg` / public `robreg()` | `6` only |
|
|
550
|
+
| `coreg` / public `coreg()` | `3`, `6`, `9`, `12` |
|
|
551
|
+
| `bbreg` / public `bbreg()` | `6`, `9`, `12` |
|
|
552
|
+
| `segreg` / public `segreg()` | `3`, `6`, `7`, `9`, `12` |
|
|
404
553
|
|
|
405
554
|
The public `robreg` path is intentionally rigid-only for now because it tracks
|
|
406
555
|
the current IRLS implementation.
|
|
@@ -3,6 +3,7 @@ from neuroreg._sys_info import sys_info # noqa: F401
|
|
|
3
3
|
from neuroreg.bbreg.register import register_surface as bbreg # noqa: F401
|
|
4
4
|
from neuroreg.imreg.coreg import coreg # noqa: F401
|
|
5
5
|
from neuroreg.imreg.robreg import robreg # noqa: F401
|
|
6
|
+
from neuroreg.segreg import segreg # noqa: F401
|
|
6
7
|
from neuroreg.transforms import ( # noqa: F401
|
|
7
8
|
LINEAR_RAS_TO_RAS,
|
|
8
9
|
LINEAR_VOX_TO_VOX,
|
|
@@ -14,6 +15,7 @@ __all__ = [
|
|
|
14
15
|
"bbreg",
|
|
15
16
|
"coreg",
|
|
16
17
|
"robreg",
|
|
18
|
+
"segreg",
|
|
17
19
|
"sys_info",
|
|
18
20
|
"LINEAR_RAS_TO_RAS",
|
|
19
21
|
"LINEAR_VOX_TO_VOX",
|
|
@@ -229,7 +229,7 @@ def main(args=None) -> None:
|
|
|
229
229
|
v2v = coreg(mov_img, ref_img, **kwargs)
|
|
230
230
|
v2v_cpu = v2v.detach().cpu()
|
|
231
231
|
|
|
232
|
-
LTA.from_matrix(v2v_cpu.numpy(), ns.mov,
|
|
232
|
+
LTA.from_matrix(v2v_cpu.numpy(), ns.mov, mov_img, ns.ref, ref_img, lta_type=0).write(ns.out)
|
|
233
233
|
logger.info("Wrote LTA: %s", ns.out)
|
|
234
234
|
print(f"Output: {ns.out}")
|
|
235
235
|
|