|
21 | 21 | import numpy as np
|
22 | 22 | from nibabel import load
|
23 | 23 |
|
24 |
| -from ... import logging |
25 |
| -from ...utils.filemanip import fname_presuffix |
| 24 | +from ... import logging, LooseVersion |
| 25 | +from ...utils.filemanip import fname_presuffix, check_depends |
26 | 26 | from ..io import FreeSurferSource
|
27 | 27 | from ..base import (TraitedSpec, File, traits,
|
28 | 28 | Directory, InputMultiPath,
|
29 | 29 | OutputMultiPath, CommandLine,
|
30 | 30 | CommandLineInputSpec, isdefined)
|
31 | 31 | from .base import (FSCommand, FSTraitedSpec,
|
32 | 32 | FSTraitedSpecOpenMP,
|
33 |
| - FSCommandOpenMP) |
| 33 | + FSCommandOpenMP, Info) |
34 | 34 | from .utils import copy2subjdir
|
35 | 35 |
|
36 | 36 | __docformat__ = 'restructuredtext'
|
37 | 37 | iflogger = logging.getLogger('interface')
|
38 | 38 |
|
| 39 | +FSVersion = "0" |
| 40 | +_ver = Info.version() |
| 41 | +if _ver: |
| 42 | + if 'dev' in _ver: |
| 43 | + FSVersion = _ver.rstrip().split('-')[-1] + '.dev' |
| 44 | + else: |
| 45 | + FSVersion = _ver.rstrip().split('-v')[-1] |
| 46 | + |
39 | 47 |
|
40 | 48 | class ParseDICOMDirInputSpec(FSTraitedSpec):
|
41 | 49 | dicom_dir = Directory(exists=True, argstr='--d %s', mandatory=True,
|
@@ -622,6 +630,8 @@ class ReconAllInputSpec(CommandLineInputSpec):
|
622 | 630 | desc='Use converted T2 to refine the cortical surface')
|
623 | 631 | openmp = traits.Int(argstr="-openmp %d",
|
624 | 632 | desc="Number of processors to use in parallel")
|
| 633 | + parallel = traits.Bool(argstr="-parallel", |
| 634 | + desc="Enable parallel execution") |
625 | 635 | subjects_dir = Directory(exists=True, argstr='-sd %s', hash_files=False,
|
626 | 636 | desc='path to subjects directory', genfile=True)
|
627 | 637 | flags = traits.Str(argstr='%s', desc='additional parameters')
|
@@ -656,85 +666,173 @@ class ReconAll(CommandLine):
|
656 | 666 | output_spec = ReconAllOutputSpec
|
657 | 667 | _can_resume = True
|
658 | 668 |
|
659 |
| - _steps = [ |
660 |
| - # autorecon1 |
661 |
| - ('motioncor', ['mri/rawavg.mgz', 'mri/orig.mgz']), |
662 |
| - ('talairach', ['mri/transforms/talairach.auto.xfm', |
663 |
| - 'mri/transforms/talairach.xfm']), |
664 |
| - ('nuintensitycor', ['mri/nu.mgz']), |
665 |
| - ('normalization', ['mri/T1.mgz']), |
666 |
| - ('skullstrip', |
667 |
| - ['mri/brainmask.auto.mgz', |
668 |
| - 'mri/brainmask.mgz']), |
669 |
| - # autorecon2 |
670 |
| - ('gcareg', ['mri/transforms/talairach.lta']), |
671 |
| - ('canorm', ['mri/norm.mgz']), |
672 |
| - ('careg', ['mri/transforms/talairach.m3z']), |
673 |
| - ('careginv', ['mri/transforms/talairach.m3z.inv.x.mgz', |
674 |
| - 'mri/transforms/talairach.m3z.inv.y.mgz', |
675 |
| - 'mri/transforms/talairach.m3z.inv.z.mgz']), |
676 |
| - ('rmneck', ['mri/nu_noneck.mgz']), |
677 |
| - ('skull-lta', ['mri/transforms/talairach_with_skull_2.lta']), |
678 |
| - ('calabel', |
679 |
| - ['mri/aseg.auto_noCCseg.mgz', 'mri/aseg.auto.mgz', 'mri/aseg.mgz']), |
680 |
| - ('normalization2', ['mri/brain.mgz']), |
681 |
| - ('maskbfs', ['mri/brain.finalsurfs.mgz']), |
682 |
| - ('segmentation', ['mri/wm.asegedit.mgz', 'mri/wm.mgz']), |
683 |
| - ('fill', ['mri/filled.mgz']), |
684 |
| - ('tessellate', ['surf/lh.orig.nofix', 'surf/rh.orig.nofix']), |
685 |
| - ('smooth1', ['surf/lh.smoothwm.nofix', 'surf/rh.smoothwm.nofix']), |
686 |
| - ('inflate1', ['surf/lh.inflated.nofix', 'surf/rh.inflated.nofix']), |
687 |
| - ('qsphere', ['surf/lh.qsphere.nofix', 'surf/rh.qsphere.nofix']), |
688 |
| - ('fix', ['surf/lh.orig', 'surf/rh.orig']), |
689 |
| - ('white', |
690 |
| - ['surf/lh.white', |
691 |
| - 'surf/rh.white', |
692 |
| - 'surf/lh.curv', |
693 |
| - 'surf/rh.curv', |
694 |
| - 'surf/lh.area', |
695 |
| - 'surf/rh.area', |
696 |
| - 'label/lh.cortex.label', |
697 |
| - 'label/rh.cortex.label']), |
698 |
| - ('smooth2', ['surf/lh.smoothwm', 'surf/rh.smoothwm']), |
699 |
| - ('inflate2', |
700 |
| - ['surf/lh.inflated', |
701 |
| - 'surf/rh.inflated', |
702 |
| - 'surf/lh.sulc', |
703 |
| - 'surf/rh.sulc', |
704 |
| - 'surf/lh.inflated.H', |
705 |
| - 'surf/rh.inflated.H', |
706 |
| - 'surf/lh.inflated.K', |
707 |
| - 'surf/rh.inflated.K']), |
708 |
| - # autorecon3 |
709 |
| - ('sphere', ['surf/lh.sphere', 'surf/rh.sphere']), |
710 |
| - ('surfreg', ['surf/lh.sphere.reg', 'surf/rh.sphere.reg']), |
711 |
| - ('jacobian_white', ['surf/lh.jacobian_white', |
712 |
| - 'surf/rh.jacobian_white']), |
713 |
| - ('avgcurv', ['surf/lh.avg_curv', 'surf/rh.avg_curv']), |
714 |
| - ('cortparc', ['label/lh.aparc.annot', 'label/rh.aparc.annot']), |
715 |
| - ('pial', |
716 |
| - ['surf/lh.pial', |
717 |
| - 'surf/rh.pial', |
718 |
| - 'surf/lh.curv.pial', |
719 |
| - 'surf/rh.curv.pial', |
720 |
| - 'surf/lh.area.pial', |
721 |
| - 'surf/rh.area.pial', |
722 |
| - 'surf/lh.thickness', |
723 |
| - 'surf/rh.thickness']), |
724 |
| - ('cortparc2', ['label/lh.aparc.a2009s.annot', |
725 |
| - 'label/rh.aparc.a2009s.annot']), |
726 |
| - ('parcstats2', |
727 |
| - ['stats/lh.aparc.a2009s.stats', |
728 |
| - 'stats/rh.aparc.a2009s.stats', |
729 |
| - 'stats/aparc.annot.a2009s.ctab']), |
730 |
| - ('cortribbon', ['mri/lh.ribbon.mgz', 'mri/rh.ribbon.mgz', |
731 |
| - 'mri/ribbon.mgz']), |
732 |
| - ('segstats', ['stats/aseg.stats']), |
733 |
| - ('aparc2aseg', ['mri/aparc+aseg.mgz', 'mri/aparc.a2009s+aseg.mgz']), |
734 |
| - ('wmparc', ['mri/wmparc.mgz', 'stats/wmparc.stats']), |
735 |
| - ('balabels', ['BA.ctab', 'BA.thresh.ctab']), |
736 |
| - ('label-exvivo-ec', ['label/lh.entorhinal_exvivo.label', |
737 |
| - 'label/rh.entorhinal_exvivo.label'])] |
| 669 | + # Steps are based off of the recon-all tables [0,1] describing, inputs, |
| 670 | + # commands, and outputs of each step of the recon-all process, |
| 671 | + # controlled by flags. |
| 672 | + # |
| 673 | + # Each step is a 3-tuple containing (flag, [outputs], [inputs]) |
| 674 | + # A step is considered complete if all of its outputs exist and are newer |
| 675 | + # than the inputs. An empty input list indicates input mtimes will not |
| 676 | + # be checked. This may need updating, if users are working with manually |
| 677 | + # edited files. |
| 678 | + # |
| 679 | + # [0] https://surfer.nmr.mgh.harvard.edu/fswiki/ReconAllTableStableV5.3 |
| 680 | + # [1] https://surfer.nmr.mgh.harvard.edu/fswiki/ReconAllTableStableV6.0 |
| 681 | + _autorecon1_steps = [ |
| 682 | + ('motioncor', ['mri/rawavg.mgz', 'mri/orig.mgz'], []), |
| 683 | + ('talairach', ['mri/orig_nu.mgz', |
| 684 | + 'mri/transforms/talairach.auto.xfm', |
| 685 | + 'mri/transforms/talairach.xfm', |
| 686 | + # 'mri/transforms/talairach_avi.log', |
| 687 | + ], []), |
| 688 | + ('nuintensitycor', ['mri/nu.mgz'], []), |
| 689 | + ('normalization', ['mri/T1.mgz'], []), |
| 690 | + ('skullstrip', ['mri/talairach_with_skull.lta', |
| 691 | + 'mri/brainmask.auto.mgz', |
| 692 | + 'mri/brainmask.mgz'], []), |
| 693 | + ] |
| 694 | + if LooseVersion(FSVersion) < LooseVersion("6.0.0"): |
| 695 | + _autorecon2_steps = [ |
| 696 | + ('gcareg', ['mri/transforms/talairach.lta'], []), |
| 697 | + ('canorm', ['mri/norm.mgz'], []), |
| 698 | + ('careg', ['mri/transforms/talairach.m3z'], []), |
| 699 | + ('careginv', ['mri/transforms/talairach.m3z.inv.x.mgz', |
| 700 | + 'mri/transforms/talairach.m3z.inv.y.mgz', |
| 701 | + 'mri/transforms/talairach.m3z.inv.z.mgz', |
| 702 | + ], []), |
| 703 | + ('rmneck', ['mri/nu_noneck.mgz'], []), |
| 704 | + ('skull-lta', ['mri/transforms/talairach_with_skull_2.lta'], []), |
| 705 | + ('calabel', ['mri/aseg.auto_noCCseg.mgz', |
| 706 | + 'mri/aseg.auto.mgz', |
| 707 | + 'mri/aseg.mgz'], []), |
| 708 | + ('normalization2', ['mri/brain.mgz'], []), |
| 709 | + ('maskbfs', ['mri/brain.finalsurfs.mgz'], []), |
| 710 | + ('segmentation', ['mri/wm.seg.mgz', |
| 711 | + 'mri/wm.asegedit.mgz', |
| 712 | + 'mri/wm.mgz'], []), |
| 713 | + ('fill', ['mri/filled.mgz', |
| 714 | + # 'scripts/ponscc.cut.log', |
| 715 | + ], []), |
| 716 | + ('tessellate', ['surf/lh.orig.nofix', 'surf/rh.orig.nofix'], []), |
| 717 | + ('smooth1', ['surf/lh.smoothwm.nofix', 'surf/rh.smoothwm.nofix'], |
| 718 | + []), |
| 719 | + ('inflate1', ['surf/lh.inflated.nofix', 'surf/rh.inflated.nofix'], |
| 720 | + []), |
| 721 | + ('qsphere', ['surf/lh.qsphere.nofix', 'surf/rh.qsphere.nofix'], |
| 722 | + []), |
| 723 | + ('fix', ['surf/lh.orig', 'surf/rh.orig'], []), |
| 724 | + ('white', ['surf/lh.white', 'surf/rh.white', |
| 725 | + 'surf/lh.curv', 'surf/rh.curv', |
| 726 | + 'surf/lh.area', 'surf/rh.area', |
| 727 | + 'label/lh.cortex.label', 'label/rh.cortex.label'], []), |
| 728 | + ('smooth2', ['surf/lh.smoothwm', 'surf/rh.smoothwm'], []), |
| 729 | + ('inflate2', ['surf/lh.inflated', 'surf/rh.inflated', |
| 730 | + 'surf/lh.sulc', 'surf/rh.sulc', |
| 731 | + 'surf/lh.inflated.H', 'surf/rh.inflated.H', |
| 732 | + 'surf/lh.inflated.K', 'surf/rh.inflated.K'], []), |
| 733 | + ] |
| 734 | + _autorecon3_steps = [ |
| 735 | + ('sphere', ['surf/lh.sphere', 'surf/rh.sphere'], []), |
| 736 | + ('surfreg', ['surf/lh.sphere.reg', 'surf/rh.sphere.reg'], []), |
| 737 | + ('jacobian_white', ['surf/lh.jacobian_white', |
| 738 | + 'surf/rh.jacobian_white'], []), |
| 739 | + ('avgcurv', ['surf/lh.avg_curv', 'surf/rh.avg_curv'], []), |
| 740 | + ('cortparc', ['label/lh.aparc.annot', 'label/rh.aparc.annot'], []), |
| 741 | + ('pial', ['surf/lh.pial', 'surf/rh.pial', |
| 742 | + 'surf/lh.curv.pial', 'surf/rh.curv.pial', |
| 743 | + 'surf/lh.area.pial', 'surf/rh.area.pial', |
| 744 | + 'surf/lh.thickness', 'surf/rh.thickness'], []), |
| 745 | + ('cortparc2', ['label/lh.aparc.a2009s.annot', |
| 746 | + 'label/rh.aparc.a2009s.annot'], []), |
| 747 | + ('parcstats2', ['stats/lh.aparc.a2009s.stats', |
| 748 | + 'stats/rh.aparc.a2009s.stats', |
| 749 | + 'stats/aparc.annot.a2009s.ctab'], []), |
| 750 | + ('cortribbon', ['mri/lh.ribbon.mgz', 'mri/rh.ribbon.mgz', |
| 751 | + 'mri/ribbon.mgz'], []), |
| 752 | + ('segstats', ['stats/aseg.stats'], []), |
| 753 | + ('aparc2aseg', ['mri/aparc+aseg.mgz', |
| 754 | + 'mri/aparc.a2009s+aseg.mgz'], []), |
| 755 | + ('wmparc', ['mri/wmparc.mgz', 'stats/wmparc.stats'], []), |
| 756 | + ('balabels', ['BA.ctab', 'BA.thresh.ctab'], []), |
| 757 | + ('label-exvivo-ec', ['label/lh.entorhinal_exvivo.label', |
| 758 | + 'label/rh.entorhinal_exvivo.label'], []), |
| 759 | + ] |
| 760 | + else: |
| 761 | + _autorecon2_steps = [ |
| 762 | + ('gcareg', ['mri/transforms/talairach.lta'], []), |
| 763 | + ('canorm', ['mri/norm.mgz'], []), |
| 764 | + ('careg', ['mri/transforms/talairach.m3z'], []), |
| 765 | + ('calabel', ['mri/aseg.auto_noCCseg.mgz', |
| 766 | + 'mri/aseg.auto.mgz', |
| 767 | + 'mri/aseg.mgz'], []), |
| 768 | + ('normalization2', ['mri/brain.mgz'], []), |
| 769 | + ('maskbfs', ['mri/brain.finalsurfs.mgz'], []), |
| 770 | + ('segmentation', ['mri/wm.seg.mgz', |
| 771 | + 'mri/wm.asegedit.mgz', |
| 772 | + 'mri/wm.mgz'], []), |
| 773 | + ('fill', ['mri/filled.mgz', |
| 774 | + # 'scripts/ponscc.cut.log', |
| 775 | + ], []), |
| 776 | + ('tessellate', ['surf/lh.orig.nofix', 'surf/rh.orig.nofix'], []), |
| 777 | + ('smooth1', ['surf/lh.smoothwm.nofix', 'surf/rh.smoothwm.nofix'], |
| 778 | + []), |
| 779 | + ('inflate1', ['surf/lh.inflated.nofix', 'surf/rh.inflated.nofix'], |
| 780 | + []), |
| 781 | + ('qsphere', ['surf/lh.qsphere.nofix', 'surf/rh.qsphere.nofix'], |
| 782 | + []), |
| 783 | + ('fix', ['surf/lh.orig', 'surf/rh.orig'], []), |
| 784 | + ('white', ['surf/lh.white.preaparc', 'surf/rh.white.preaparc', |
| 785 | + 'surf/lh.curv', 'surf/rh.curv', |
| 786 | + 'surf/lh.area', 'surf/rh.area', |
| 787 | + 'label/lh.cortex.label', 'label/rh.cortex.label'], []), |
| 788 | + ('smooth2', ['surf/lh.smoothwm', 'surf/rh.smoothwm'], []), |
| 789 | + ('inflate2', ['surf/lh.inflated', 'surf/rh.inflated', |
| 790 | + 'surf/lh.sulc', 'surf/rh.sulc'], []), |
| 791 | + ('curvHK', ['surf/lh.white.H', 'surf/rh.white.H', |
| 792 | + 'surf/lh.white.K', 'surf/rh.white.K', |
| 793 | + 'surf/lh.inflated.H', 'surf/rh.inflated.H', |
| 794 | + 'surf/lh.inflated.K', 'surf/rh.inflated.K'], []), |
| 795 | + ('curvstats', ['stats/lh.curv.stats', 'stats/rh.curv.stats'], []), |
| 796 | + ] |
| 797 | + _autorecon3_steps = [ |
| 798 | + ('sphere', ['surf/lh.sphere', 'surf/rh.sphere'], []), |
| 799 | + ('surfreg', ['surf/lh.sphere.reg', 'surf/rh.sphere.reg'], []), |
| 800 | + ('jacobian_white', ['surf/lh.jacobian_white', |
| 801 | + 'surf/rh.jacobian_white'], []), |
| 802 | + ('avgcurv', ['surf/lh.avg_curv', 'surf/rh.avg_curv'], []), |
| 803 | + ('cortparc', ['label/lh.aparc.annot', 'label/rh.aparc.annot'], []), |
| 804 | + ('pial', ['surf/lh.pial', 'surf/rh.pial', |
| 805 | + 'surf/lh.curv.pial', 'surf/rh.curv.pial', |
| 806 | + 'surf/lh.area.pial', 'surf/rh.area.pial', |
| 807 | + 'surf/lh.thickness', 'surf/rh.thickness'], []), |
| 808 | + ('cortribbon', ['mri/lh.ribbon.mgz', 'mri/rh.ribbon.mgz', |
| 809 | + 'mri/ribbon.mgz'], []), |
| 810 | + ('parcstats', ['stats/lh.aparc.astats', 'stats/rh.aparc.stats', |
| 811 | + 'stats/aparc.annot.ctab'], []), |
| 812 | + ('cortparc2', ['label/lh.aparc.a2009s.annot', |
| 813 | + 'label/rh.aparc.a2009s.annot'], []), |
| 814 | + ('parcstats2', ['stats/lh.aparc.a2009s.stats', |
| 815 | + 'stats/rh.aparc.a2009s.stats', |
| 816 | + 'stats/aparc.annot.a2009s.ctab'], []), |
| 817 | + ('cortparc3', ['label/lh.aparc.DKTatlas.annot', |
| 818 | + 'label/rh.aparc.DKTatlas.annot'], []), |
| 819 | + ('parcstats3', ['stats/lh.aparc.DKTatlas.stats', |
| 820 | + 'stats/rh.aparc.DKTatlas.stats', |
| 821 | + 'stats/aparc.annot.DKTatlas.ctab'], []), |
| 822 | + ('pctsurfcon', ['surf/lh.w-g.pct.mgh', 'surf/rh.w-g.pct.mgh'], []), |
| 823 | + ('hyporelabel', ['mri/aseg.presurf.hypos.mgz'], []), |
| 824 | + ('aparc2aseg', ['mri/aparc+aseg.mgz', |
| 825 | + 'mri/aparc.a2009s+aseg.mgz', |
| 826 | + 'mri/aparc.DKTatlas+aseg.mgz'], []), |
| 827 | + ('apas2aseg', ['mri/aseg.mgz'], ['mri/aparc+aseg.mgz']), |
| 828 | + ('segstats', ['stats/aseg.stats'], []), |
| 829 | + ('wmparc', ['mri/wmparc.mgz', 'stats/wmparc.stats'], []), |
| 830 | + ('balabels', ['BA.ctab', 'BA.thresh.ctab', |
| 831 | + 'label/lh.entorhinal_exvivo.label', |
| 832 | + 'label/rh.entorhinal_exvivo.label'], []), |
| 833 | + ] |
| 834 | + |
| 835 | + _steps = _autorecon1_steps + _autorecon2_steps + _autorecon3_steps |
738 | 836 |
|
739 | 837 | def _gen_subjects_dir(self):
|
740 | 838 | return os.getcwd()
|
@@ -790,24 +888,21 @@ def cmdline(self):
|
790 | 888 | subjects_dir = self.inputs.subjects_dir
|
791 | 889 | if not isdefined(subjects_dir):
|
792 | 890 | subjects_dir = self._gen_subjects_dir()
|
793 |
| - # cmd = cmd.replace(' -all ', ' -make all ') |
794 |
| - iflogger.info('Overriding recon-all directive') |
| 891 | + |
795 | 892 | flags = []
|
796 |
| - directive = 'all' |
797 | 893 | for idx, step in enumerate(self._steps):
|
798 |
| - step, outfiles = step |
799 |
| - if all([os.path.exists(os.path.join(subjects_dir, |
800 |
| - self.inputs.subject_id, f)) for |
801 |
| - f in outfiles]): |
802 |
| - flags.append('-no%s' % step) |
803 |
| - if idx > 4: |
804 |
| - directive = 'autorecon2' |
805 |
| - elif idx > 23: |
806 |
| - directive = 'autorecon3' |
807 |
| - else: |
808 |
| - flags.append('-%s' % step) |
809 |
| - cmd = cmd.replace(' -%s ' % self.inputs.directive, ' -%s ' % directive) |
| 894 | + step, outfiles, infiles = step |
| 895 | + flag = '-{}'.format(step) |
| 896 | + noflag = '-no{}'.format(step) |
| 897 | + if flag in cmd or noflag in cmd: |
| 898 | + continue |
| 899 | + |
| 900 | + subj_dir = os.path.join(subjects_dir, self.inputs.subject_id) |
| 901 | + if check_depends([os.path.join(subj_dir, f) for f in outfiles], |
| 902 | + [os.path.join(subj_dir, f) for f in infiles]): |
| 903 | + flags.append(noflag) |
810 | 904 | cmd += ' ' + ' '.join(flags)
|
| 905 | + |
811 | 906 | iflogger.info('resume recon-all : %s' % cmd)
|
812 | 907 | return cmd
|
813 | 908 |
|
|
0 commit comments