66import sys
77import shutil
88from bids import BIDSLayout
9+ import importlib
910import glob
1011from platform import system
1112
5152for place in places_to_look :
5253 for root , folders , files in os .walk (place ):
5354 for file in files :
54- if file .endswith ("pyproject.toml" ):
55+ if file .endswith ("pyproject.toml" ) and "petdeface" in os . path . join ( root , file ) :
5556 toml_file = os .path .join (root , file )
5657
5758 with open (toml_file , "r" ) as f :
6667 __bids_version__ = (
6768 line .split ("=" )[1 ].strip ().replace ('"' , "" )
6869 )
69- break
70+ # if the version number is found and is formatted with major.minor.patch formating we can break
71+ # we check the version with a regex expression to see if all of the parts are there
72+ if re .match (r"\d+\.\d+\.\d+" , __version__ ):
73+ break
74+
75+ if __version__ != "unable to locate version number in pyproject.toml" :
76+ # we try to load the version using import lib
77+ __version__ = importlib .metadata .version ("petdeface" )
78+ if re .match (r"\d+\.\d+\.\d+" , __version__ ):
79+ break
7080
7181
7282def locate_freesurfer_license ():
@@ -79,20 +89,32 @@ def locate_freesurfer_license():
7989 :return: full path to Freesurfer license file
8090 :rtype: pathlib.Path
8191 """
82- # collect freesurfer home environment variable
83- fs_home = pathlib .Path (os .environ .get ("FREESURFER_HOME" , "" ))
84- if not fs_home :
85- raise ValueError (
86- "FREESURFER_HOME environment variable is not set, unable to determine location of license file"
87- )
92+
93+ # check to see if FREESURFER_LICENSE variable is set, if so we can skip the rest of this function
94+ if os .environ .get ("FREESURFER_LICENSE" , "" ):
95+ fs_license_env_var = pathlib .Path (os .environ .get ("FREESURFER_LICENSE" , "" ))
96+ if not fs_license_env_var .exists ():
97+ raise ValueError (
98+ f"Freesurfer license file does not exist at { fs_license_env_var } , but is set under $FREESURFER_LICENSE variable."
99+ f"Update or unset this varible to use the license.txt at $FREESURFER_HOME"
100+ )
101+ else :
102+ return fs_license_env_var
88103 else :
89- fs_license = fs_home / pathlib .Path ("license.txt" )
90- if not fs_license .exists ():
104+ # collect freesurfer home environment variable and look there instead
105+ fs_home = pathlib .Path (os .environ .get ("FREESURFER_HOME" , "" ))
106+ if not fs_home :
91107 raise ValueError (
92- "Freesurfer license file does not exist at {}" . format ( fs_license )
108+ "FREESURFER_HOME environment variable is not set, unable to determine location of license file"
93109 )
94110 else :
95- return fs_license
111+ fs_license = fs_home / pathlib .Path ("license.txt" )
112+ if not fs_license .exists ():
113+ raise ValueError (
114+ "Freesurfer license file does not exist at {}" .format (fs_license )
115+ )
116+ else :
117+ return fs_license
96118
97119
98120def check_docker_installed ():
@@ -198,7 +220,7 @@ def deface(args: Union[dict, argparse.Namespace]) -> None:
198220 else :
199221 args = args
200222
201- if not check_valid_fs_license ():
223+ if not check_valid_fs_license () and not locate_freesurfer_license (). exists () :
202224 raise Exception ("You need a valid FreeSurfer license to proceed!" )
203225
204226 if args .subject :
@@ -721,7 +743,11 @@ def __init__(
721743 # check if freesurfer license is valid
722744 self .fs_license = check_valid_fs_license ()
723745 if not self .fs_license :
724- raise ValueError ("Freesurfer license is not valid" )
746+ self .fs_license = locate_freesurfer_license ()
747+ if not self .fs_license .exists ():
748+ raise ValueError ("Freesurfer license is not valid" )
749+ else :
750+ print (f"Using freesurfer license at { self .fs_license } found in system env at $FREESURFER_LICENSE" )
725751
726752 def run (self ):
727753 """
@@ -800,6 +826,13 @@ def cli():
800826 default = False ,
801827 help = "Run in docker container" ,
802828 ),
829+ parser .add_argument (
830+ "--singularity" ,
831+ "-si" ,
832+ action = "store_true" ,
833+ default = False ,
834+ help = "Run in singularity container" ,
835+ ),
803836 parser .add_argument (
804837 "--n_procs" ,
805838 help = "Number of processors to use when running the workflow" ,
@@ -943,8 +976,16 @@ def main(): # noqa: max-complexity: 12
943976 docker_command += f"-v { code_dir } :/petdeface "
944977
945978 # collect location of freesurfer license if it's installed and working
946- if check_valid_fs_license ():
947- license_location = locate_freesurfer_license ()
979+ try :
980+ check_valid_fs_license ()
981+ except :
982+ if locate_freesurfer_license ().exists ():
983+ license_location = locate_freesurfer_license ()
984+ else :
985+ raise FileNotFoundError (
986+ "Freesurfer license not found, please set FREESURFER_LICENSE environment variable or place license.txt in FREESURFER_HOME"
987+ )
988+
948989 if license_location :
949990 docker_command += f"-v { license_location } :/opt/freesurfer/license.txt "
950991
@@ -960,6 +1001,60 @@ def main(): # noqa: max-complexity: 12
9601001
9611002 subprocess .run (docker_command , shell = True )
9621003
1004+ elif args .singularity :
1005+ singularity_command = f"singularity exec -e"
1006+
1007+ if args .output_dir == "None" or args .output_dir is None or args .output_dir == "" :
1008+ args .output_dir = args .input_dir / "derivatives" / "petdeface"
1009+
1010+ # create output directory if it doesn't exist
1011+ if not args .output_dir .exists ():
1012+ args .output_dir .mkdir (parents = True , exist_ok = True )
1013+
1014+ # convert args to dictionary
1015+ args_dict = vars (args )
1016+ for key , value in args_dict .items ():
1017+ if isinstance (value , pathlib .PosixPath ):
1018+ args_dict [key ] = str (value )
1019+
1020+ args_dict .pop ("singularity" )
1021+
1022+ # remove False boolean keys and values, and set true boolean keys to empty string
1023+ args_dict = {key : value for key , value in args_dict .items () if value }
1024+ set_to_empty_str = [key for key , value in args_dict .items () if value == True ]
1025+ for key in set_to_empty_str :
1026+ args_dict [key ] = "empty_str"
1027+
1028+ args_string = " " .join (
1029+ ["--{} {}" .format (key , value ) for key , value in args_dict .items () if value ]
1030+ )
1031+ args_string = args_string .replace ("empty_str" , "" )
1032+
1033+ # remove --input_dir from args_string as input dir is positional, we
1034+ # we're simply removing an artifact of argparse
1035+ args_string = args_string .replace ("--input_dir" , "" )
1036+
1037+ # collect location of freesurfer license if it's installed and working
1038+ try :
1039+ check_valid_fs_license ()
1040+ except :
1041+ if locate_freesurfer_license ().exists ():
1042+ license_location = locate_freesurfer_license ()
1043+ else :
1044+ raise FileNotFoundError (
1045+ "Freesurfer license not found, please set FREESURFER_LICENSE environment variable or place license.txt in FREESURFER_HOME"
1046+ )
1047+
1048+ singularity_command += f" --bind { str (license_location )} :/opt/freesurfer/license.txt"
1049+ singularity_command += f" docker://openneuropet/petdeface:{ __version__ } "
1050+ singularity_command += f" petdeface"
1051+ singularity_command += args_string
1052+
1053+ print ("Running singularity command: \n {}" .format (singularity_command ))
1054+
1055+ subprocess .run (singularity_command , shell = True )
1056+
1057+
9631058 else :
9641059 petdeface = PetDeface (
9651060 bids_dir = args .input_dir ,
0 commit comments