From c6c6df5c4b857af3a10b1f03ef734a11ee25f903 Mon Sep 17 00:00:00 2001 From: Anthony Galassi <28850131+bendhouseart@users.noreply.github.com> Date: Thu, 18 Jul 2024 16:42:59 -0400 Subject: [PATCH 01/27] added telemetry call --- pypet2bids/pypet2bids/dcm2niix4pet.py | 32 +++++++++ pypet2bids/pypet2bids/telemetry.py | 94 +++++++++++++++++++++++++++ 2 files changed, 126 insertions(+) create mode 100644 pypet2bids/pypet2bids/telemetry.py diff --git a/pypet2bids/pypet2bids/dcm2niix4pet.py b/pypet2bids/pypet2bids/dcm2niix4pet.py index a05380d..e1a1f77 100644 --- a/pypet2bids/pypet2bids/dcm2niix4pet.py +++ b/pypet2bids/pypet2bids/dcm2niix4pet.py @@ -42,6 +42,7 @@ metadata_dictionaries, get_metadata_from_spreadsheet, ) + from telemetry import send_telemetry, count_input_files, enable_disable_telemetry, count_output_files except ModuleNotFoundError: import pypet2bids.helper_functions as helper_functions import pypet2bids.is_pet as is_pet @@ -54,6 +55,7 @@ metadata_dictionaries, get_metadata_from_spreadsheet, ) + from pypet2bids.telemetry import send_telemetry, count_input_files, enable_disable_telemetry, count_output_files logger = helper_functions.logger("pypet2bids") @@ -319,6 +321,7 @@ def __init__( # next we use the loaded python script to extract the information we need self.load_spread_sheet_data() elif metadata_path and not metadata_translation_script or metadata_path == "": + self.metadata_path = Path(metadata_path) if not self.spreadsheet_metadata.get("nifti_json", None): self.spreadsheet_metadata["nifti_json"] = {} @@ -833,9 +836,38 @@ def post_dcm2niix(self): json.dump(blood_json_data, outfile, indent=4) def convert(self): + # check the size of out the output folder + before_output_files = {} + if self.destination_path.exists(): + before_output_files = count_output_files(self.destination_path) self.run_dcm2niix() self.post_dcm2niix() + # if telemetry isn't disabled we send a telemetry event to the pypet2bids server + if enable_disable_telemetry: + # count the number of files + data_out = count_input_files(self.image_folder) + # record if a blood tsv and json file were created + if self.spreadsheet_metadata.get("blood_tsv", {}): + data_out["blood_tsv"] = True + if self.spreadsheet_metadata.get("blood_json", {}): + data_out["blood_json"] = True + # record if a metadata spreadsheet was used + if self.metadata_path == "" or self.metadata_path is not None: + data_out["metadata_spreadsheet_used"] = True + + # count the output files + after_output_files = count_output_files(self.destination_path) + + if before_output_files != {}: + for key, value in after_output_files.items(): + data_out[key] = abs(after_output_files[key] - before_output_files[key]) + + send_telemetry(data_out) + + + + def match_dicom_header_to_file(self, destination_path=None): """ Matches a dicom header to a nifti or json file produced by dcm2niix, this is run after dcm2niix converts the diff --git a/pypet2bids/pypet2bids/telemetry.py b/pypet2bids/pypet2bids/telemetry.py new file mode 100644 index 0000000..8d132a3 --- /dev/null +++ b/pypet2bids/pypet2bids/telemetry.py @@ -0,0 +1,94 @@ +import requests +import os +import pathlib +from dotenv import load_dotenv +from typing import Union + + +# collect pet2bids version +from pypet2bids.helper_functions import get_version + + +def enable_disable_telemetry(config_path=None): + # load dcm2niix file + if not config_path: + config_file = pathlib.Path.home() / ".pet2bidsconfig" + else: + config_file = pathlib.Path(config_path) + + if config_file.exists(): + load_dotenv(dotenv_path=config_file) + + # check to see if telemetry is disabled + if os.getenv("PET2BIDS_TELEMETRY_ENABLED") == "False".upper(): + return False + else: + return True + + +def send_telemetry(json_data: dict, url: str = "http://52.87.154.236/telemetry/"): + if enable_disable_telemetry(): + # update data with version of pet2bids + json_data['pypet2bids_version'] = get_version() + # Send a POST request to the telemetry server + requests.post(url, json=json_data) + else: + pass + + +def count_input_files(input_file_path: Union[str, pathlib.Path]): + # Count the number of input files in the input file path + if isinstance(input_file_path, str): + input_file_path = pathlib.Path(input_file_path) + + if input_file_path.is_dir(): + # collect all files in the input dir + all_files = [f for f in input_file_path.iterdir()] + # count the number of dicom files + num_dicom_files = 0 + dicom_files_size = 0 + total_files = 0 + total_files_size = 0 + for file in all_files: + if file.is_file(): + total_files += 1 + total_files_size += file.stat().st_size + if file.suffix == ".dcm" or file.suffix == ".ima" or file.suffix == ".img" or file.suffix == "": + num_dicom_files += 1 + dicom_files_size += file.stat().st_size + return { + "TotalInputFiles": total_files, + "TotalInputFilesSize": total_files_size, + "DicomFiles": num_dicom_files, + "DicomFilesSize": dicom_files_size + } + + +def count_output_files(output_file_path: Union[str, pathlib.Path]): + if isinstance(output_file_path, str): + output_file_path = pathlib.Path(output_file_path) + + if output_file_path.is_file(): + output_file_path = output_file_path.parent + + if output_file_path.is_dir(): + # collect all files in the output dir + all_files = [f for f in output_file_path.iterdir()] + # count the number nifti files + num_nifti_files = 0 + nifti_files_size = 0 + total_files = 0 + total_files_size = 0 + for file in all_files: + if file.is_file(): + total_files += 1 + total_files_size += file.stat().st_size + if file.suffix == ".nii" or file.suffix == ".nii.gz": + num_nifti_files += 1 + nifti_files_size += file.stat().st_size + return { + "TotalOutputFiles": total_files, + "TotalOutputFilesSize": total_files_size, + "NiftiFiles": num_nifti_files, + "NiftiFilesSize": nifti_files_size + } \ No newline at end of file From 5a84ebbe5611ebaf07dd9e763f51703f76fa821e Mon Sep 17 00:00:00 2001 From: Anthony Galassi <28850131+bendhouseart@users.noreply.github.com> Date: Fri, 19 Jul 2024 17:59:07 -0400 Subject: [PATCH 02/27] added file count to telemetery tracking for dcm2niix --- pypet2bids/pypet2bids/dcm2niix4pet.py | 25 +++++++++++-------------- pypet2bids/pypet2bids/telemetry.py | 15 +++++---------- 2 files changed, 16 insertions(+), 24 deletions(-) diff --git a/pypet2bids/pypet2bids/dcm2niix4pet.py b/pypet2bids/pypet2bids/dcm2niix4pet.py index e1a1f77..7c43bc6 100644 --- a/pypet2bids/pypet2bids/dcm2niix4pet.py +++ b/pypet2bids/pypet2bids/dcm2niix4pet.py @@ -204,7 +204,7 @@ def __init__( # check to see if dcm2niix is installed self.blood_json = None self.blood_tsv = None - + self.telemetry_data = {} self.dcm2niix_path = self.check_for_dcm2niix() if not self.dcm2niix_path: logger.error( @@ -455,10 +455,15 @@ def run_dcm2niix(self): file_format_args = "" with TemporaryDirectory(dir=self.tempdir_location) as tempdir: tempdir_pathlike = Path(tempdir) + self.tempdir_location = tempdir_pathlike # people use screwy paths, we do this before running dcm2niix to account for that image_folder = helper_functions.sanitize_bad_path(self.image_folder) cmd = f"{self.dcm2niix_path} -b y -w 1 -z y {file_format_args} -o {tempdir_pathlike} {image_folder}" convert = subprocess.run(cmd, shell=True, capture_output=True) + self.telemetry_data['dcm2niix'] = { + "returncode": convert.returncode, + } + self.telemetry_data.update(count_output_files(self.tempdir_location)) if convert.returncode != 0: print( @@ -838,32 +843,24 @@ def post_dcm2niix(self): def convert(self): # check the size of out the output folder before_output_files = {} - if self.destination_path.exists(): - before_output_files = count_output_files(self.destination_path) self.run_dcm2niix() self.post_dcm2niix() # if telemetry isn't disabled we send a telemetry event to the pypet2bids server if enable_disable_telemetry: # count the number of files - data_out = count_input_files(self.image_folder) + self.telemetry_data.update(count_input_files(self.image_folder)) # record if a blood tsv and json file were created if self.spreadsheet_metadata.get("blood_tsv", {}): - data_out["blood_tsv"] = True + self.telemetry_data["blood_tsv"] = True if self.spreadsheet_metadata.get("blood_json", {}): - data_out["blood_json"] = True + self.telemetry_data["blood_json"] = True # record if a metadata spreadsheet was used if self.metadata_path == "" or self.metadata_path is not None: - data_out["metadata_spreadsheet_used"] = True - - # count the output files - after_output_files = count_output_files(self.destination_path) + self.telemetry_data["metadata_spreadsheet_used"] = True - if before_output_files != {}: - for key, value in after_output_files.items(): - data_out[key] = abs(after_output_files[key] - before_output_files[key]) - send_telemetry(data_out) + send_telemetry(self.telemetry_data) diff --git a/pypet2bids/pypet2bids/telemetry.py b/pypet2bids/pypet2bids/telemetry.py index 8d132a3..746a9b3 100644 --- a/pypet2bids/pypet2bids/telemetry.py +++ b/pypet2bids/pypet2bids/telemetry.py @@ -53,14 +53,9 @@ def count_input_files(input_file_path: Union[str, pathlib.Path]): if file.is_file(): total_files += 1 total_files_size += file.stat().st_size - if file.suffix == ".dcm" or file.suffix == ".ima" or file.suffix == ".img" or file.suffix == "": - num_dicom_files += 1 - dicom_files_size += file.stat().st_size return { "TotalInputFiles": total_files, "TotalInputFilesSize": total_files_size, - "DicomFiles": num_dicom_files, - "DicomFilesSize": dicom_files_size } @@ -79,13 +74,13 @@ def count_output_files(output_file_path: Union[str, pathlib.Path]): nifti_files_size = 0 total_files = 0 total_files_size = 0 - for file in all_files: - if file.is_file(): + for f in all_files: + if f.is_file(): total_files += 1 - total_files_size += file.stat().st_size - if file.suffix == ".nii" or file.suffix == ".nii.gz": + total_files_size += f.stat().st_size + if str(f).endswith('.nii') or str(f).endswith('.nii.gz'): num_nifti_files += 1 - nifti_files_size += file.stat().st_size + nifti_files_size += f.stat().st_size return { "TotalOutputFiles": total_files, "TotalOutputFilesSize": total_files_size, From 6b53ba4af4c14bb403322e9df2a39ebe0660423f Mon Sep 17 00:00:00 2001 From: Anthony Galassi <28850131+bendhouseart@users.noreply.github.com> Date: Wed, 24 Jul 2024 19:13:00 -0400 Subject: [PATCH 03/27] added python functionality --- pypet2bids/pypet2bids/dcm2niix4pet.py | 32 +++++++++++++++-------- pypet2bids/pypet2bids/ecat.py | 26 ++++++++++++++++++ pypet2bids/pypet2bids/helper_functions.py | 10 +++---- pypet2bids/pypet2bids/telemetry.py | 24 ++++++++++++----- 4 files changed, 69 insertions(+), 23 deletions(-) diff --git a/pypet2bids/pypet2bids/dcm2niix4pet.py b/pypet2bids/pypet2bids/dcm2niix4pet.py index 7c43bc6..bb2b0e9 100644 --- a/pypet2bids/pypet2bids/dcm2niix4pet.py +++ b/pypet2bids/pypet2bids/dcm2niix4pet.py @@ -42,7 +42,12 @@ metadata_dictionaries, get_metadata_from_spreadsheet, ) - from telemetry import send_telemetry, count_input_files, enable_disable_telemetry, count_output_files + from telemetry import ( + send_telemetry, + count_input_files, + telemetry_enabled, + count_output_files, + ) except ModuleNotFoundError: import pypet2bids.helper_functions as helper_functions import pypet2bids.is_pet as is_pet @@ -55,7 +60,12 @@ metadata_dictionaries, get_metadata_from_spreadsheet, ) - from pypet2bids.telemetry import send_telemetry, count_input_files, enable_disable_telemetry, count_output_files + from pypet2bids.telemetry import ( + send_telemetry, + count_input_files, + telemetry_enabled, + count_output_files, + ) logger = helper_functions.logger("pypet2bids") @@ -460,7 +470,7 @@ def run_dcm2niix(self): image_folder = helper_functions.sanitize_bad_path(self.image_folder) cmd = f"{self.dcm2niix_path} -b y -w 1 -z y {file_format_args} -o {tempdir_pathlike} {image_folder}" convert = subprocess.run(cmd, shell=True, capture_output=True) - self.telemetry_data['dcm2niix'] = { + self.telemetry_data["dcm2niix"] = { "returncode": convert.returncode, } self.telemetry_data.update(count_output_files(self.tempdir_location)) @@ -847,24 +857,24 @@ def convert(self): self.post_dcm2niix() # if telemetry isn't disabled we send a telemetry event to the pypet2bids server - if enable_disable_telemetry: + if telemetry_enabled: # count the number of files self.telemetry_data.update(count_input_files(self.image_folder)) # record if a blood tsv and json file were created - if self.spreadsheet_metadata.get("blood_tsv", {}): + if self.spreadsheet_metadata.get("blood_tsv", {}) != {}: self.telemetry_data["blood_tsv"] = True - if self.spreadsheet_metadata.get("blood_json", {}): - self.telemetry_data["blood_json"] = True + else: + self.telemetry_data["blood_tsv"] = False # record if a metadata spreadsheet was used - if self.metadata_path == "" or self.metadata_path is not None: + if helper_functions.collect_spreadsheets(self.metadata_path): self.telemetry_data["metadata_spreadsheet_used"] = True + else: + self.telemetry_data["metadata_spreadsheet_used"] = False + self.telemetry_data["InputType"] = "DICOM" send_telemetry(self.telemetry_data) - - - def match_dicom_header_to_file(self, destination_path=None): """ Matches a dicom header to a nifti or json file produced by dcm2niix, this is run after dcm2niix converts the diff --git a/pypet2bids/pypet2bids/ecat.py b/pypet2bids/pypet2bids/ecat.py index a900dbd..2b01c37 100644 --- a/pypet2bids/pypet2bids/ecat.py +++ b/pypet2bids/pypet2bids/ecat.py @@ -25,6 +25,7 @@ get_metadata_from_spreadsheet, check_meta_radio_inputs, ) + from telemetry import telemetry_enabled, send_telemetry except ModuleNotFoundError: import pypet2bids.helper_functions as helper_functions import pypet2bids.sidecar as sidecar @@ -35,6 +36,7 @@ get_metadata_from_spreadsheet, check_meta_radio_inputs, ) + from pypet2bids.telemetry import telemetry_enabled, send_telemetry from dateutil import parser @@ -107,6 +109,8 @@ def __init__( self.output_path = None self.metadata_path = metadata_path + self.telemetry_data = {} + # load config file default_json_path = helper_functions.check_pet2bids_config( "DEFAULT_METADATA_JSON" @@ -169,6 +173,12 @@ def __init__( else: self.nifti_file = nifti_file + self.telemetry_data["InputType"] = "ECAT" + str(self.ecat_header["SV_VERSION"]) + self.telemetry_data["TotalInputFiles"] = 1 + self.telemetry_data["TotalInputFilesSize"] = ( + pathlib.Path(self.ecat_file).stat().st_size + ) + # que up metadata path for spreadsheet loading later if self.metadata_path: if ( @@ -198,6 +208,16 @@ def __init__( load_spreadsheet_data["blood_json"] ) + if helper_functions.collect_spreadsheets(self.metadata_path): + self.telemetry_data.update({"metadata_spreadsheet_user": True}) + else: + self.telemetry_data.update({"metadata_spreadsheet_user": False}) + + if self.spreadsheet_metadata.get("blood_tsv", None): + self.telemetry_data.update({"blood_tsv": True}) + else: + self.telemetry_data.update({"blood_tsv": False}) + def make_nifti(self, output_path=None): """ Outputs a nifti from the read in ECAT file. @@ -221,6 +241,9 @@ def make_nifti(self, output_path=None): affine=self.affine, ) + self.telemetry_data["NiftiFiles"] = 1 + self.telemetry_data["NiftiFilesSize"] = pathlib.Path(output).stat().st_size + if "nii.gz" not in output: output = helper_functions.compress(output) @@ -653,3 +676,6 @@ def convert(self): self.prune_sidecar() self.show_sidecar(output_path=self.sidecar_path) self.write_out_blood_files() + + if telemetry_enabled: + send_telemetry(self.telemetry_data) diff --git a/pypet2bids/pypet2bids/helper_functions.py b/pypet2bids/pypet2bids/helper_functions.py index 2a28ec3..8a7d5c3 100644 --- a/pypet2bids/pypet2bids/helper_functions.py +++ b/pypet2bids/pypet2bids/helper_functions.py @@ -959,11 +959,11 @@ def ad_hoc_checks( if items_that_should_be_checked is None: items_that_should_be_checked = {} hardcoded_items = { - 'InjectedRadioactivityUnits': ['MBq', 'mCi'], - 'SpecificRadioactivityUnits': ['Bq/g', 'MBq/ug'], - 'InjectedMassUnits': 'ug', - 'MolarActivityUnits': 'GBq/umolug', - 'MolecularWeightUnits': 'g/mol' + "InjectedRadioactivityUnits": ["MBq", "mCi"], + "SpecificRadioactivityUnits": ["Bq/g", "MBq/ug"], + "InjectedMassUnits": "ug", + "MolarActivityUnits": "GBq/umolug", + "MolecularWeightUnits": "g/mol", } # if none are diff --git a/pypet2bids/pypet2bids/telemetry.py b/pypet2bids/pypet2bids/telemetry.py index 746a9b3..2913979 100644 --- a/pypet2bids/pypet2bids/telemetry.py +++ b/pypet2bids/pypet2bids/telemetry.py @@ -1,6 +1,7 @@ import requests import os import pathlib +import subprocess from dotenv import load_dotenv from typing import Union @@ -9,7 +10,7 @@ from pypet2bids.helper_functions import get_version -def enable_disable_telemetry(config_path=None): +def telemetry_enabled(config_path=None): # load dcm2niix file if not config_path: config_file = pathlib.Path.home() / ".pet2bidsconfig" @@ -20,16 +21,25 @@ def enable_disable_telemetry(config_path=None): load_dotenv(dotenv_path=config_file) # check to see if telemetry is disabled - if os.getenv("PET2BIDS_TELEMETRY_ENABLED") == "False".upper(): + if os.getenv("PET2BIDS_TELEMETRY_ENABLED", "").lower() == "false": return False else: return True def send_telemetry(json_data: dict, url: str = "http://52.87.154.236/telemetry/"): - if enable_disable_telemetry(): + if telemetry_enabled(): # update data with version of pet2bids - json_data['pypet2bids_version'] = get_version() + json_data["pypet2bids_version"] = get_version() + # check if it's one of the dev's running this + running_from_cloned_repository = subprocess.run( + ["git", "status"], stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL + ) + if running_from_cloned_repository.returncode == 0: + json_data["running_from_cloned_repository"] = True + + json_data["description"] = "pet2bids_python_telemetry" + # Send a POST request to the telemetry server requests.post(url, json=json_data) else: @@ -78,12 +88,12 @@ def count_output_files(output_file_path: Union[str, pathlib.Path]): if f.is_file(): total_files += 1 total_files_size += f.stat().st_size - if str(f).endswith('.nii') or str(f).endswith('.nii.gz'): + if str(f).endswith(".nii") or str(f).endswith(".nii.gz"): num_nifti_files += 1 nifti_files_size += f.stat().st_size return { "TotalOutputFiles": total_files, "TotalOutputFilesSize": total_files_size, "NiftiFiles": num_nifti_files, - "NiftiFilesSize": nifti_files_size - } \ No newline at end of file + "NiftiFilesSize": nifti_files_size, + } From b3bf9af43bcc929229f8816d2df4a5dfa1d00854 Mon Sep 17 00:00:00 2001 From: Anthony Galassi <28850131+bendhouseart@users.noreply.github.com> Date: Thu, 1 Aug 2024 17:44:20 -0400 Subject: [PATCH 04/27] matlab is being weird and not finding dcm2niix on path --- matlab/dcm2niix4pet.m | 31 +++++++++-- matlab/telemetry.m | 75 +++++++++++++++++++++++++++ pypet2bids/pypet2bids/dcm2niix4pet.py | 2 + 3 files changed, 103 insertions(+), 5 deletions(-) create mode 100644 matlab/telemetry.m diff --git a/matlab/dcm2niix4pet.m b/matlab/dcm2niix4pet.m index ebb7b9e..2baf951 100644 --- a/matlab/dcm2niix4pet.m +++ b/matlab/dcm2niix4pet.m @@ -50,11 +50,11 @@ function dcm2niix4pet(FolderList,MetaList,varargin) dcm2niixpath = 'D:\MRI\MRIcroGL12win\Resources\dcm2niix.exe'; % for windows machine indicate here, where is dcm2niix if ispc && ~exist(dcm2niixpath,'file') - error('for windows machine please edit the function line 42 and indicate the dcm2niix path') + error('for windows machine please edit the function line 51 and indicate the dcm2niix path') end if ~ispc % overwrite if not windowns (as it should be in the computer path) - dcm2niixpath = 'dcm2niix'; + dcm2niixpath = '/usr/local/bin/dcm2niix'; end % we rely on more recent version of dcm2niix, certain pet fields are unavailable in the sidecar jsons for versions @@ -62,9 +62,19 @@ function dcm2niix4pet(FolderList,MetaList,varargin) minimum_version = 'v1.0.20220720'; minimum_version_date = datetime(minimum_version(6:end), 'InputFormat', 'yyyyMMdd'); -version_cmd = ['dcm2niix', ' -v']; +%version_cmd = ['dcm2niix', ' -v']; % TODO fix this as it's not detecting dcm2niix running matlab on osx as of matlab v2023b. +version_cmd = ['/usr/local/bin/dcm2niix', ' -v']; + [status, version_output_string] = system(version_cmd); -version = regexp(version_output_string, 'v[0-9].[0-9].{8}[0-9]', 'match'); +version = regexp(version_output_string, 'v[0-9].[0-9].{8}[0-9]', 'match'); % TODO this returns an array with two of the same versions + +% initalize telemetry data fror later uploading +telemetry_data = {}; +dcm2niix_data = {}; +dcm2niix_data.version = version; +dcm2niix_data.returncode = 0; +telemetry_data.dcm2niix = dcm2niix_data; +telemetry_data.description = "Matlab_dcm2niix4pet.m" if length(version) >= 1 version_date = version{1}(6:end); @@ -249,10 +259,16 @@ function dcm2niix4pet(FolderList,MetaList,varargin) end out = system(command); + telemetry_data.dcm2niix.returncode = out; + % we still want to send telemetry even if this fails if out ~= 0 + telemetry_data.returncode = 1; + telemetry(telemetry_data, folder); error('%s did not run properly',command) + end - + + % deal with dcm files dcmfiles = dir(fullfile(FolderList{folder},'*.dcm')); if isempty(dcmfiles) % since sometimes they have no ext :-( @@ -318,4 +334,9 @@ function dcm2niix4pet(FolderList,MetaList,varargin) jsonfilename = newmetadata; end updatejsonpetfile(jsonfilename,MetaList,dcminfo); + + % if this all goes well update the telemetry data and send it with a positive return code of 0 + telemetry_data.returncode = 0; + telemetry(telemetry_data, FolderList{folder}) + end diff --git a/matlab/telemetry.m b/matlab/telemetry.m new file mode 100644 index 0000000..dd61758 --- /dev/null +++ b/matlab/telemetry.m @@ -0,0 +1,75 @@ +function telemetry(telemetry_data, input_path, output_path) + arguments + telemetry_data (1,:) struct + input_path (1,:) string = '' + output_path (1,:) string = '' + end + + if telemetry_enabled + % do all the things + + telemetry_data.description = "Matlab"; + + if strcmp(input_path, '') + % do nothing + else + input_file_count = count_input_files(input_path); + telemetry_data.TotalInputFiles = input_file_count.TotalInputFiles; + telemetry_data.TotalInputFileSize = input_file_count.TotalInputFileSize; + end + + url = 'http://52.87.154.236/telemetry/'; + options = weboptions('MediaType', 'application/json'); + response = webwrite(url, telemetry_data, options); + + else + % don't do anything + end +end + +function e = telemetry_enabled() + % checks to see if the telemetry is enabled or disabled + environment = getenv(); + home_dir = environment("HOME"); + loadenv(fullfile(home_dir, '.pet2bidsconfig'), FileType='env'); + % convert string to boolean/logical + disable_telemetry = strcmpi(getenv("PET2BIDS_TELEMETRY_ENABLED"), 'false'); + + if disable_telemetry + e = false; + else + e = true; + end + +end + + +function c = count_input_files(input_path) + % generate a list of all the files in the input directory + % count the number of files in the input directory + % count the total size of the files in the input directory + % return the count and the size + + % if the input path is a file then return 1 and the size of the file + if isfile(input_path) + input_file = dir(input_path); + c.TotalInputFiles = 1; + c.TotalInputFileSize = input_file.bytes; + return + elseif isfolder(input_path) + % get the list of files in the input directory + input_files = dir(input_path); + % count the number of files in the input directory + file_count = length(input_files); + % count the total size of the files in the input directory + total_size = 0; + for i = 1:file_count + total_size = total_size + input_files(i).bytes; + end + c.TotalInputFiles = file_count; + c.TotalInputFileSize = total_size; + return + else + error('Input path is not a file or a directory'); + end +end diff --git a/pypet2bids/pypet2bids/dcm2niix4pet.py b/pypet2bids/pypet2bids/dcm2niix4pet.py index bb2b0e9..e31bda0 100644 --- a/pypet2bids/pypet2bids/dcm2niix4pet.py +++ b/pypet2bids/pypet2bids/dcm2niix4pet.py @@ -873,6 +873,8 @@ def convert(self): self.telemetry_data["InputType"] = "DICOM" + self.telemetry_data["returncode"] = 0 + send_telemetry(self.telemetry_data) def match_dicom_header_to_file(self, destination_path=None): From 8550942db3bfe00641ed033e45c779a3c3b258e0 Mon Sep 17 00:00:00 2001 From: Anthony Galassi <28850131+bendhouseart@users.noreply.github.com> Date: Fri, 2 Aug 2024 15:13:57 -0400 Subject: [PATCH 05/27] added telemetry to matlab converters --- matlab/dcm2niix4pet.m | 10 +++++----- matlab/ecat2nii.m | 25 ++++++++++++++++++++----- 2 files changed, 25 insertions(+), 10 deletions(-) diff --git a/matlab/dcm2niix4pet.m b/matlab/dcm2niix4pet.m index 2baf951..08bad7f 100644 --- a/matlab/dcm2niix4pet.m +++ b/matlab/dcm2niix4pet.m @@ -54,7 +54,7 @@ function dcm2niix4pet(FolderList,MetaList,varargin) end if ~ispc % overwrite if not windowns (as it should be in the computer path) - dcm2niixpath = '/usr/local/bin/dcm2niix'; + dcm2niixpath = 'dcm2niix'; end % we rely on more recent version of dcm2niix, certain pet fields are unavailable in the sidecar jsons for versions @@ -62,16 +62,16 @@ function dcm2niix4pet(FolderList,MetaList,varargin) minimum_version = 'v1.0.20220720'; minimum_version_date = datetime(minimum_version(6:end), 'InputFormat', 'yyyyMMdd'); -%version_cmd = ['dcm2niix', ' -v']; % TODO fix this as it's not detecting dcm2niix running matlab on osx as of matlab v2023b. -version_cmd = ['/usr/local/bin/dcm2niix', ' -v']; +version_cmd = ['dcm2niix', ' -v']; [status, version_output_string] = system(version_cmd); -version = regexp(version_output_string, 'v[0-9].[0-9].{8}[0-9]', 'match'); % TODO this returns an array with two of the same versions +version = regexp(version_output_string, 'v[0-9].[0-9].{8}[0-9]', 'match'); + % initalize telemetry data fror later uploading telemetry_data = {}; dcm2niix_data = {}; -dcm2niix_data.version = version; +dcm2niix_data.version = version(1); dcm2niix_data.returncode = 0; telemetry_data.dcm2niix = dcm2niix_data; telemetry_data.description = "Matlab_dcm2niix4pet.m" diff --git a/matlab/ecat2nii.m b/matlab/ecat2nii.m index acfd52f..34222f7 100644 --- a/matlab/ecat2nii.m +++ b/matlab/ecat2nii.m @@ -58,6 +58,10 @@ parts = strsplit(ecat_save_steps_dir, filesep); ecat_save_steps_dir = strjoin([parts(1:end-2), 'ecat_testing', 'steps'], filesep); +%% initialize telemetry variable for reporting +telemetry_data = {}; +telemetry_data.description = "Matlab_ecat2nii"; + %% check inputs % ------------ @@ -131,14 +135,18 @@ %% Read and write data % -------------------- for j=1:length(FileListIn) - + try fprintf('Conversion of file: %s\n',FileListIn{j}); - + % quickly ensure we have the TimeZero - key to all analyzes! info = MetaList{1}; if ~isfield(info,'TimeZero') - error('Metadata TimeZero is missing - set to ScanStart or empty to use the scanning time as injection time') + error_text = 'Metadata TimeZero is missing - set to ScanStart or empty to use the scanning time as injection time'; + telemetry_data.returncode = 1; + telemetry_data.error = error_text; + telemetry(telemetry_data, FileListIn{j}) + error(error_text) end % Read ECAT file headers @@ -180,6 +188,9 @@ end end + % capture ecat version + telemetry_data.InputType = append("ECAT", string(mh.sw_version)); + % save debugging steps 6 and 7 if (ecat_save_steps == '1') first_middle_last_frames_to_text_cell(data,ecat_save_steps_dir, '6_ecat2nii_matlab'); @@ -206,8 +217,6 @@ fclose(fid); end - - % save debugging step 8 - rescale to 16 bits if (ecat_save_steps == '1') first_middle_last_frames_to_text(img_temp,ecat_save_steps_dir, '8_rescale_to_16_ecat2nii_matlab'); @@ -489,8 +498,14 @@ % FileListOut{j} = [filenameout '_pet.nii']; % niftiwrite(img_temp,FileListOut{j},info,'Endian','little','Compressed',false); % end + + telemetry_data.returncode = 0; + telemetry(telemetry_data, FileListIn{j}); catch conversionerr + telemetry_data.returncode = 1; + telemetry_data.error = conversionerr.message; + telemetry(telemetry_data, FileListIn{j}); FileListOut{j} = sprintf('%s failed to convert:%s',FileListIn{j},conversionerr.message, conversionerr.stack.line); end From 272780acb19681be7aae2cda7084d5865a094b80 Mon Sep 17 00:00:00 2001 From: Anthony Galassi <28850131+bendhouseart@users.noreply.github.com> Date: Fri, 2 Aug 2024 16:41:52 -0400 Subject: [PATCH 06/27] fixe typo, bump version --- pypet2bids/poetry.lock | 109 +++++++++++++++++----------------- pypet2bids/pypet2bids/ecat.py | 2 +- pypet2bids/pyproject.toml | 2 +- 3 files changed, 56 insertions(+), 57 deletions(-) diff --git a/pypet2bids/poetry.lock b/pypet2bids/poetry.lock index f0e7fba..c644a2c 100644 --- a/pypet2bids/poetry.lock +++ b/pypet2bids/poetry.lock @@ -24,13 +24,13 @@ files = [ [[package]] name = "babel" -version = "2.14.0" +version = "2.15.0" description = "Internationalization utilities" optional = false -python-versions = ">=3.7" +python-versions = ">=3.8" files = [ - {file = "Babel-2.14.0-py3-none-any.whl", hash = "sha256:efb1a25b7118e67ce3a259bed20545c29cb68be8ad2c784c83689981b7a57287"}, - {file = "Babel-2.14.0.tar.gz", hash = "sha256:6919867db036398ba21eb5c7a0f6b28ab8cbc3ae7a73a44ebe34ae74a4e7d363"}, + {file = "Babel-2.15.0-py3-none-any.whl", hash = "sha256:08706bdad8d0a3413266ab61bd6c34d0c28d6e1e7badf40a2cebe67644e2e1fb"}, + {file = "babel-2.15.0.tar.gz", hash = "sha256:8daf0e265d05768bc6c7a314cf1321e9a123afc328cc635c18622a2f30a04413"}, ] [package.dependencies] @@ -64,13 +64,13 @@ virtualenv = ["virtualenv (>=20.0.35)"] [[package]] name = "certifi" -version = "2024.2.2" +version = "2024.7.4" description = "Python package for providing Mozilla's CA Bundle." optional = false python-versions = ">=3.6" files = [ - {file = "certifi-2024.2.2-py3-none-any.whl", hash = "sha256:dc383c07b76109f368f6106eee2b593b04a011ea4d55f652c6ca24a754d1cdd1"}, - {file = "certifi-2024.2.2.tar.gz", hash = "sha256:0569859f95fc761b18b45ef421b1290a0f65f147e92a1e5eb3e635f9a5e4e66f"}, + {file = "certifi-2024.7.4-py3-none-any.whl", hash = "sha256:c198e21b1289c2ab85ee4e67bb4b4ef3ead0892059901a8d5b622f24a1101e90"}, + {file = "certifi-2024.7.4.tar.gz", hash = "sha256:5a1e7645bc0ec61a09e26c36f6106dd4cf40c6db3a1fb6352b0244e7fb057c7b"}, ] [[package]] @@ -207,13 +207,13 @@ files = [ [[package]] name = "exceptiongroup" -version = "1.2.1" +version = "1.2.2" description = "Backport of PEP 654 (exception groups)" optional = false python-versions = ">=3.7" files = [ - {file = "exceptiongroup-1.2.1-py3-none-any.whl", hash = "sha256:5258b9ed329c5bbdd31a309f53cbfb0b155341807f6ff7606a1e801a891b29ad"}, - {file = "exceptiongroup-1.2.1.tar.gz", hash = "sha256:a4785e48b045528f5bfe627b6ad554ff32def154f42372786903b7abcfe1aa16"}, + {file = "exceptiongroup-1.2.2-py3-none-any.whl", hash = "sha256:3111b9d131c238bec2f8f516e123e14ba243563fb135d3fe885990585aa7795b"}, + {file = "exceptiongroup-1.2.2.tar.gz", hash = "sha256:47c2edf7c6738fafb49fd34290706d1a1a2f4d1c6df275526b62cbb4aa5393cc"}, ] [package.extras] @@ -243,22 +243,22 @@ files = [ [[package]] name = "importlib-metadata" -version = "7.1.0" +version = "8.2.0" description = "Read metadata from Python packages" optional = false python-versions = ">=3.8" files = [ - {file = "importlib_metadata-7.1.0-py3-none-any.whl", hash = "sha256:30962b96c0c223483ed6cc7280e7f0199feb01a0e40cfae4d4450fc6fab1f570"}, - {file = "importlib_metadata-7.1.0.tar.gz", hash = "sha256:b78938b926ee8d5f020fc4772d487045805a55ddbad2ecf21c6d60938dc7fcd2"}, + {file = "importlib_metadata-8.2.0-py3-none-any.whl", hash = "sha256:11901fa0c2f97919b288679932bb64febaeacf289d18ac84dd68cb2e74213369"}, + {file = "importlib_metadata-8.2.0.tar.gz", hash = "sha256:72e8d4399996132204f9a16dcc751af254a48f8d1b20b9ff0f98d4a8f901e73d"}, ] [package.dependencies] zipp = ">=0.5" [package.extras] -docs = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-lint"] +doc = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-lint"] perf = ["ipython"] -testing = ["flufl.flake8", "importlib-resources (>=1.3)", "jaraco.test (>=5.4)", "packaging", "pyfakefs", "pytest (>=6)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=2.2)", "pytest-mypy", "pytest-perf (>=0.9.2)", "pytest-ruff (>=0.2.1)"] +test = ["flufl.flake8", "importlib-resources (>=1.3)", "jaraco.test (>=5.4)", "packaging", "pyfakefs", "pytest (>=6,!=8.1.*)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=2.2)", "pytest-mypy", "pytest-perf (>=0.9.2)", "pytest-ruff (>=0.2.1)"] [[package]] name = "importlib-resources" @@ -291,13 +291,13 @@ files = [ [[package]] name = "jinja2" -version = "3.1.3" +version = "3.1.4" description = "A very fast and expressive template engine." optional = false python-versions = ">=3.7" files = [ - {file = "Jinja2-3.1.3-py3-none-any.whl", hash = "sha256:7d6d50dd97d52cbc355597bd845fabfbac3f551e1f99619e39a35ce8c370b5fa"}, - {file = "Jinja2-3.1.3.tar.gz", hash = "sha256:ac8bd6544d4bb2c9792bf3a159e80bba8fda7f07e81bc3aed565432d5925ba90"}, + {file = "jinja2-3.1.4-py3-none-any.whl", hash = "sha256:bc5dd2abb727a5319567b7a813e6a2e7318c39f4f487cfe6c89c6f9c7d25197d"}, + {file = "jinja2-3.1.4.tar.gz", hash = "sha256:4a3aee7acbbe7303aede8e9648d13b8bf88a429282aa6122a993f0ac800cb369"}, ] [package.dependencies] @@ -308,13 +308,13 @@ i18n = ["Babel (>=2.7)"] [[package]] name = "joblib" -version = "1.4.0" +version = "1.4.2" description = "Lightweight pipelining with Python functions" optional = false python-versions = ">=3.8" files = [ - {file = "joblib-1.4.0-py3-none-any.whl", hash = "sha256:42942470d4062537be4d54c83511186da1fc14ba354961a2114da91efa9a4ed7"}, - {file = "joblib-1.4.0.tar.gz", hash = "sha256:1eb0dc091919cd384490de890cb5dfd538410a6d4b3b54eef09fb8c50b409b1c"}, + {file = "joblib-1.4.2-py3-none-any.whl", hash = "sha256:06d478d5674cbc267e7496a410ee875abd68e4340feff4490bcb7afb88060ae6"}, + {file = "joblib-1.4.2.tar.gz", hash = "sha256:2382c5816b2636fbd20a09e0f4e9dad4736765fdfb7dca582943b9c1366b3f0e"}, ] [[package]] @@ -480,13 +480,13 @@ files = [ [[package]] name = "openpyxl" -version = "3.1.2" +version = "3.1.5" description = "A Python library to read/write Excel 2010 xlsx/xlsm files" optional = false -python-versions = ">=3.6" +python-versions = ">=3.8" files = [ - {file = "openpyxl-3.1.2-py2.py3-none-any.whl", hash = "sha256:f91456ead12ab3c6c2e9491cf33ba6d08357d802192379bb482f1033ade496f5"}, - {file = "openpyxl-3.1.2.tar.gz", hash = "sha256:a6f5977418eff3b2d5500d54d9db50c8277a368436f4e4f8ddb1be3422870184"}, + {file = "openpyxl-3.1.5-py2.py3-none-any.whl", hash = "sha256:5282c12b107bffeef825f4617dc029afaf41d0ea60823bbb665ef3079dc79de2"}, + {file = "openpyxl-3.1.5.tar.gz", hash = "sha256:cf0e3cf56142039133628b5acffe8ef0c12bc902d2aadd3e0fe5878dc08d1050"}, ] [package.dependencies] @@ -494,13 +494,13 @@ et-xmlfile = "*" [[package]] name = "packaging" -version = "24.0" +version = "24.1" description = "Core utilities for Python packages" optional = false -python-versions = ">=3.7" +python-versions = ">=3.8" files = [ - {file = "packaging-24.0-py3-none-any.whl", hash = "sha256:2ddfb553fdf02fb784c234c7ba6ccc288296ceabec964ad2eae3777778130bc5"}, - {file = "packaging-24.0.tar.gz", hash = "sha256:eb82c5e3e56209074766e6885bb04b8c38a0c015d0a30036ebe7ece34c9989e9"}, + {file = "packaging-24.1-py3-none-any.whl", hash = "sha256:5b8f2217dbdbd2f7f384c41c628544e6d52f2d0f53c6d0c3ea61aa5d1d7ff124"}, + {file = "packaging-24.1.tar.gz", hash = "sha256:026ed72c8ed3fcce5bf8950572258698927fd1dbda10a5e981cdf0ac37f4f002"}, ] [[package]] @@ -607,17 +607,16 @@ docs = ["matplotlib", "numpy", "numpydoc", "pillow", "sphinx", "sphinx-copybutto [[package]] name = "pygments" -version = "2.17.2" +version = "2.18.0" description = "Pygments is a syntax highlighting package written in Python." optional = false -python-versions = ">=3.7" +python-versions = ">=3.8" files = [ - {file = "pygments-2.17.2-py3-none-any.whl", hash = "sha256:b27c2826c47d0f3219f29554824c30c5e8945175d888647acd804ddd04af846c"}, - {file = "pygments-2.17.2.tar.gz", hash = "sha256:da46cec9fd2de5be3a8a784f434e4c4ab670b4ff54d605c4c2717e9d49c4c367"}, + {file = "pygments-2.18.0-py3-none-any.whl", hash = "sha256:b8e6aca0523f3ab76fee51799c488e38782ac06eafcf95e7ba832985c8e7b13a"}, + {file = "pygments-2.18.0.tar.gz", hash = "sha256:786ff802f32e91311bff3889f6e9a86e81505fe99f2735bb6d60ae0c5004f199"}, ] [package.extras] -plugins = ["importlib-metadata"] windows-terminal = ["colorama (>=0.4.6)"] [[package]] @@ -655,13 +654,13 @@ hook-testing = ["execnet (>=1.5.0)", "psutil", "pytest (>=2.7.3)"] [[package]] name = "pyinstaller-hooks-contrib" -version = "2024.5" +version = "2024.7" description = "Community maintained hooks for PyInstaller" optional = false python-versions = ">=3.7" files = [ - {file = "pyinstaller_hooks_contrib-2024.5-py2.py3-none-any.whl", hash = "sha256:0852249b7fb1e9394f8f22af2c22fa5294c2c0366157969f98c96df62410c4c6"}, - {file = "pyinstaller_hooks_contrib-2024.5.tar.gz", hash = "sha256:aa5dee25ea7ca317ad46fa16b5afc8dba3b0e43f2847e498930138885efd3cab"}, + {file = "pyinstaller_hooks_contrib-2024.7-py2.py3-none-any.whl", hash = "sha256:8bf0775771fbaf96bcd2f4dfd6f7ae6c1dd1b1efe254c7e50477b3c08e7841d8"}, + {file = "pyinstaller_hooks_contrib-2024.7.tar.gz", hash = "sha256:fd5f37dcf99bece184e40642af88be16a9b89613ecb958a8bd1136634fc9fac5"}, ] [package.dependencies] @@ -768,13 +767,13 @@ files = [ [[package]] name = "requests" -version = "2.31.0" +version = "2.32.3" description = "Python HTTP for Humans." optional = false -python-versions = ">=3.7" +python-versions = ">=3.8" files = [ - {file = "requests-2.31.0-py3-none-any.whl", hash = "sha256:58cd2187c01e70e6e26505bca751777aa9f2ee0b7f4300988b709f44e013003f"}, - {file = "requests-2.31.0.tar.gz", hash = "sha256:942c5a758f98d790eaed1a29cb6eefc7ffb0d1cf7af05c3d2791656dbd6ad1e1"}, + {file = "requests-2.32.3-py3-none-any.whl", hash = "sha256:70761cfe03c773ceb22aa2f671b4757976145175cdfca038c02654d061d6dcc6"}, + {file = "requests-2.32.3.tar.gz", hash = "sha256:55365417734eb18255590a9ff9eb97e9e1da868d4ccd6402399eaf68af20a760"}, ] [package.dependencies] @@ -827,19 +826,19 @@ test = ["asv", "gmpy2", "mpmath", "pytest", "pytest-cov", "pytest-xdist", "sciki [[package]] name = "setuptools" -version = "69.5.1" +version = "72.1.0" description = "Easily download, build, install, upgrade, and uninstall Python packages" optional = false python-versions = ">=3.8" files = [ - {file = "setuptools-69.5.1-py3-none-any.whl", hash = "sha256:c636ac361bc47580504644275c9ad802c50415c7522212252c033bd15f301f32"}, - {file = "setuptools-69.5.1.tar.gz", hash = "sha256:6c1fccdac05a97e598fb0ae3bbed5904ccb317337a51139dcd51453611bbb987"}, + {file = "setuptools-72.1.0-py3-none-any.whl", hash = "sha256:5a03e1860cf56bb6ef48ce186b0e557fdba433237481a9a625176c2831be15d1"}, + {file = "setuptools-72.1.0.tar.gz", hash = "sha256:8d243eff56d095e5817f796ede6ae32941278f542e0f941867cc05ae52b162ec"}, ] [package.extras] -docs = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "pygments-github-lexers (==0.0.5)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-favicon", "sphinx-inline-tabs", "sphinx-lint", "sphinx-notfound-page (>=1,<2)", "sphinx-reredirects", "sphinxcontrib-towncrier"] -testing = ["build[virtualenv]", "filelock (>=3.4.0)", "importlib-metadata", "ini2toml[lite] (>=0.9)", "jaraco.develop (>=7.21)", "jaraco.envs (>=2.2)", "jaraco.path (>=3.2.0)", "mypy (==1.9)", "packaging (>=23.2)", "pip (>=19.1)", "pytest (>=6,!=8.1.1)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=2.2)", "pytest-home (>=0.5)", "pytest-mypy", "pytest-perf", "pytest-ruff (>=0.2.1)", "pytest-timeout", "pytest-xdist (>=3)", "tomli", "tomli-w (>=1.0.0)", "virtualenv (>=13.0.0)", "wheel"] -testing-integration = ["build[virtualenv] (>=1.0.3)", "filelock (>=3.4.0)", "jaraco.envs (>=2.2)", "jaraco.path (>=3.2.0)", "packaging (>=23.2)", "pytest", "pytest-enabler", "pytest-xdist", "tomli", "virtualenv (>=13.0.0)", "wheel"] +core = ["importlib-metadata (>=6)", "importlib-resources (>=5.10.2)", "jaraco.text (>=3.7)", "more-itertools (>=8.8)", "ordered-set (>=3.1.1)", "packaging (>=24)", "platformdirs (>=2.6.2)", "tomli (>=2.0.1)", "wheel (>=0.43.0)"] +doc = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "pygments-github-lexers (==0.0.5)", "pyproject-hooks (!=1.1)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-favicon", "sphinx-inline-tabs", "sphinx-lint", "sphinx-notfound-page (>=1,<2)", "sphinx-reredirects", "sphinxcontrib-towncrier"] +test = ["build[virtualenv] (>=1.0.3)", "filelock (>=3.4.0)", "importlib-metadata", "ini2toml[lite] (>=0.14)", "jaraco.develop (>=7.21)", "jaraco.envs (>=2.2)", "jaraco.path (>=3.2.0)", "jaraco.test", "mypy (==1.11.*)", "packaging (>=23.2)", "pip (>=19.1)", "pyproject-hooks (!=1.1)", "pytest (>=6,!=8.1.*)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=2.2)", "pytest-home (>=0.5)", "pytest-mypy", "pytest-perf", "pytest-ruff (<0.4)", "pytest-ruff (>=0.2.1)", "pytest-ruff (>=0.3.2)", "pytest-subprocess", "pytest-timeout", "pytest-xdist (>=3)", "tomli", "tomli-w (>=1.0.0)", "virtualenv (>=13.0.0)", "wheel"] [[package]] name = "six" @@ -1059,13 +1058,13 @@ files = [ [[package]] name = "urllib3" -version = "2.2.1" +version = "2.2.2" description = "HTTP library with thread-safe connection pooling, file post, and more." optional = false python-versions = ">=3.8" files = [ - {file = "urllib3-2.2.1-py3-none-any.whl", hash = "sha256:450b20ec296a467077128bff42b73080516e71b56ff59a60a02bef2232c4fa9d"}, - {file = "urllib3-2.2.1.tar.gz", hash = "sha256:d0570876c61ab9e520d776c38acbbb5b05a776d3f9ff98a5c8fd5162a444cf19"}, + {file = "urllib3-2.2.2-py3-none-any.whl", hash = "sha256:a448b2f64d686155468037e1ace9f2d2199776e17f0a46610480d311f73e3472"}, + {file = "urllib3-2.2.2.tar.gz", hash = "sha256:dd505485549a7a552833da5e6063639d0d177c04f23bc3864e41e5dc5f612168"}, ] [package.extras] @@ -1092,18 +1091,18 @@ test = ["pytest", "pytest-cov"] [[package]] name = "zipp" -version = "3.18.1" +version = "3.19.2" description = "Backport of pathlib-compatible object wrapper for zip files" optional = false python-versions = ">=3.8" files = [ - {file = "zipp-3.18.1-py3-none-any.whl", hash = "sha256:206f5a15f2af3dbaee80769fb7dc6f249695e940acca08dfb2a4769fe61e538b"}, - {file = "zipp-3.18.1.tar.gz", hash = "sha256:2884ed22e7d8961de1c9a05142eb69a247f120291bc0206a00a7642f09b5b715"}, + {file = "zipp-3.19.2-py3-none-any.whl", hash = "sha256:f091755f667055f2d02b32c53771a7a6c8b47e1fdbc4b72a8b9072b3eef8015c"}, + {file = "zipp-3.19.2.tar.gz", hash = "sha256:bf1dcf6450f873a13e952a29504887c89e6de7506209e5b1bcc3460135d4de19"}, ] [package.extras] -docs = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-lint"] -testing = ["big-O", "jaraco.functools", "jaraco.itertools", "more-itertools", "pytest (>=6)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=2.2)", "pytest-ignore-flaky", "pytest-mypy", "pytest-ruff (>=0.2.1)"] +doc = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-lint"] +test = ["big-O", "importlib-resources", "jaraco.functools", "jaraco.itertools", "jaraco.test", "more-itertools", "pytest (>=6,!=8.1.*)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=2.2)", "pytest-ignore-flaky", "pytest-mypy", "pytest-ruff (>=0.2.1)"] [metadata] lock-version = "2.0" diff --git a/pypet2bids/pypet2bids/ecat.py b/pypet2bids/pypet2bids/ecat.py index 2b01c37..efbc2ea 100644 --- a/pypet2bids/pypet2bids/ecat.py +++ b/pypet2bids/pypet2bids/ecat.py @@ -173,7 +173,7 @@ def __init__( else: self.nifti_file = nifti_file - self.telemetry_data["InputType"] = "ECAT" + str(self.ecat_header["SV_VERSION"]) + self.telemetry_data["InputType"] = "ECAT" + str(self.ecat_header["SW_VERSION"]) self.telemetry_data["TotalInputFiles"] = 1 self.telemetry_data["TotalInputFilesSize"] = ( pathlib.Path(self.ecat_file).stat().st_size diff --git a/pypet2bids/pyproject.toml b/pypet2bids/pyproject.toml index bc8e236..95760d0 100644 --- a/pypet2bids/pyproject.toml +++ b/pypet2bids/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "pypet2bids" -version = "1.3.12" +version = "1.3.13dev" description = "A python library for converting PET imaging and blood data to BIDS." authors = ["anthony galassi <28850131+bendhouseart@users.noreply.github.com>"] license = "MIT" From 62791ec61475b0722f35f1fac77c5ca193123c33 Mon Sep 17 00:00:00 2001 From: Anthony Galassi <28850131+bendhouseart@users.noreply.github.com> Date: Wed, 7 Aug 2024 19:40:20 -0400 Subject: [PATCH 07/27] added option to opt out of telemetry --- pypet2bids/pypet2bids/helper_functions.py | 3 +- pypet2bids/pypet2bids/telemetry.py | 90 ++++++++++++++++++++++- 2 files changed, 88 insertions(+), 5 deletions(-) diff --git a/pypet2bids/pypet2bids/helper_functions.py b/pypet2bids/pypet2bids/helper_functions.py index 8a7d5c3..46afbf5 100644 --- a/pypet2bids/pypet2bids/helper_functions.py +++ b/pypet2bids/pypet2bids/helper_functions.py @@ -15,6 +15,7 @@ | *Copyright OpenNeuroPET team* """ + import os import gzip import re @@ -285,7 +286,7 @@ def decompress(file_like_object, output_path: str = None): return output_path -def load_vars_from_config(path_to_config: str): +def load_vars_from_config(path_to_config: str=pathlib.Path.home() / ".pet2bidsconfig"): """ Loads values from a .env file given a path to said .env file. diff --git a/pypet2bids/pypet2bids/telemetry.py b/pypet2bids/pypet2bids/telemetry.py index 2913979..6bdd1c6 100644 --- a/pypet2bids/pypet2bids/telemetry.py +++ b/pypet2bids/pypet2bids/telemetry.py @@ -2,15 +2,65 @@ import os import pathlib import subprocess +import time +import sys +import select from dotenv import load_dotenv from typing import Union -# collect pet2bids version -from pypet2bids.helper_functions import get_version +try: + from helper_functions import get_version, load_vars_from_config, modify_config_file +except ModuleNotFoundError: + # collect pet2bids version + from pypet2bids.helper_functions import get_version, load_vars_from_config, modify_config_file + +pet2bids_config = load_vars_from_config() +telemetry_default_url = pet2bids_config.get("TELEMETRY_URL", "http://52.87.154.236/telemetry/") +telemetry_enabled = pet2bids_config.get("TELEMETRY_ENABLED", True) +telemetry_notify_user = pet2bids_config.get("NOTIFY_USER_OF_TELEMETRY", False) + + +def ask_user_to_opt_out(timeout=10): + """Waits for user input for a specified number of seconds. + + Args: + timeout: Number of seconds to wait for input. + + Returns: + The user input if provided within the timeout, otherwise None. + """ + + print("Do you want to opt out of telemetry? (yes/no): ".format(timeout), end="", flush=True) + sys.stdout.flush() + + ready, _, _ = select.select([sys.stdin], [], [], timeout) + if ready: + response = sys.stdin.readline().rstrip('\n') + if response.lower() == "yes": + return True + else: + return False + + +if telemetry_notify_user is False: + opt_out = ask_user_to_opt_out() + if opt_out: + # update the config file + modify_config_file("TELEMETRY_ENABLED", False) + + modify_config_file("NOTIFY_USER_OF_TELEMETRY", True) def telemetry_enabled(config_path=None): + """ + Check if telemetry is enabled, if it isn't disabled in the .pet2bidsconfig file + it will be considered enabled. One must opt out of tracking usage manually. + :param config_path: The path to the config file + :type config_path: Union[str, pathlib.Path] + :return: Whether telemetry is enabled or not + :rtype: bool + """ # load dcm2niix file if not config_path: config_file = pathlib.Path.home() / ".pet2bidsconfig" @@ -27,7 +77,17 @@ def telemetry_enabled(config_path=None): return True -def send_telemetry(json_data: dict, url: str = "http://52.87.154.236/telemetry/"): +def send_telemetry(json_data: dict, url: str = telemetry_default_url): + """ + Send telemetry data to the telemetry server, by default this will first try + to load the telemetry server url from the config file, if it's not found it will + default to the hardcoded value in this module. This will always send, unless a user + has disabled the pet2bids telemetry in the .pet2bidsconfig file. + :param json_data: The dat to be sent to the telemetry server + :type json_data: dict + :param url: The url of the telemetry server + :type url: str + """ if telemetry_enabled(): # update data with version of pet2bids json_data["pypet2bids_version"] = get_version() @@ -47,7 +107,13 @@ def send_telemetry(json_data: dict, url: str = "http://52.87.154.236/telemetry/" def count_input_files(input_file_path: Union[str, pathlib.Path]): - # Count the number of input files in the input file path + """ + Count the number of input files in the input file path + :param input_file_path: location of the input files + :type input_file_path: Union[str, pathlib.Path] + :return: The number of input files and their size + :rtype: dict + """ if isinstance(input_file_path, str): input_file_path = pathlib.Path(input_file_path) @@ -70,6 +136,20 @@ def count_input_files(input_file_path: Union[str, pathlib.Path]): def count_output_files(output_file_path: Union[str, pathlib.Path]): + """ + Count the number of output files in the output file path. This can be usefull + in determining whether any additional files were created during the conversion process. + However, this is only useful if the conversion process initially takes place from within + a temporary directory. + + # TODO check the last modified date of the files to determine if they were created during + # TODO the conversion process. That should make this usefull in all cases. + :param output_file_path: location of the output files + :type output_file_path: Union[str, pathlib.Path] + :return: The number of output files and their size and spefically the number of nifti files and + their size + :rtype: dict + """ if isinstance(output_file_path, str): output_file_path = pathlib.Path(output_file_path) @@ -97,3 +177,5 @@ def count_output_files(output_file_path: Union[str, pathlib.Path]): "NiftiFiles": num_nifti_files, "NiftiFilesSize": nifti_files_size, } + + From e60aa57db36adf9b361550129e375bab3d23c201 Mon Sep 17 00:00:00 2001 From: Anthony Galassi <28850131+bendhouseart@users.noreply.github.com> Date: Mon, 12 Aug 2024 11:13:43 -0400 Subject: [PATCH 08/27] added cli flag and environment variable disabling of telemetry --- matlab/telemetry.m | 9 +++++++- pypet2bids/pypet2bids/dcm2niix4pet.py | 11 ++++++++- pypet2bids/pypet2bids/ecat_cli.py | 11 +++++++++ pypet2bids/pypet2bids/helper_functions.py | 5 +++-- pypet2bids/pypet2bids/telemetry.py | 27 ++++++++++++++++++----- 5 files changed, 53 insertions(+), 10 deletions(-) diff --git a/matlab/telemetry.m b/matlab/telemetry.m index dd61758..baebd18 100644 --- a/matlab/telemetry.m +++ b/matlab/telemetry.m @@ -30,12 +30,19 @@ function telemetry(telemetry_data, input_path, output_path) function e = telemetry_enabled() % checks to see if the telemetry is enabled or disabled environment = getenv(); + % check environment too before loading the config file + if isfield(environment, 'PET2BIDS_TELEMETRY_ENABLED') + disable_telemetry_env = strcmpi(getenv("PET2BIDS_TELEMETRY_ENABLED"), 'false'); + else + disable_telemetry_env = false; + end + home_dir = environment("HOME"); loadenv(fullfile(home_dir, '.pet2bidsconfig'), FileType='env'); % convert string to boolean/logical disable_telemetry = strcmpi(getenv("PET2BIDS_TELEMETRY_ENABLED"), 'false'); - if disable_telemetry + if disable_telemetry | disable_telemetry_env e = false; else e = true; diff --git a/pypet2bids/pypet2bids/dcm2niix4pet.py b/pypet2bids/pypet2bids/dcm2niix4pet.py index e31bda0..4d6761c 100644 --- a/pypet2bids/pypet2bids/dcm2niix4pet.py +++ b/pypet2bids/pypet2bids/dcm2niix4pet.py @@ -1109,7 +1109,14 @@ def cli(): action="version", version=f"{helper_functions.get_version()}", ) - + parser.add_argument( + "--notrack", + action="store_true", + default=False, + help="Opt-out of sending tracking information of this run to the PET2BIDS developers. " + "This information helps to improve PET2BIDS and provides an indicator of real world " + "usage crucial for obtaining funding." + ) return parser @@ -1261,6 +1268,8 @@ def main(): "DEFAULT_METADATA_JSON", cli_args.set_default_metadata_json ) sys.exit(0) + if cli_args.notrack: + environ["PET2BIDS_TRACK"] = "False" elif cli_args.folder: # instantiate class diff --git a/pypet2bids/pypet2bids/ecat_cli.py b/pypet2bids/pypet2bids/ecat_cli.py index b1284f9..fa52584 100644 --- a/pypet2bids/pypet2bids/ecat_cli.py +++ b/pypet2bids/pypet2bids/ecat_cli.py @@ -190,6 +190,14 @@ def cli(): action="version", version=f"{helper_functions.get_version()}", ) + parser.add_argument( + "--notrack", + action="store_true", + default=False, + help="Opt-out of sending tracking information of this run to the PET2BIDS developers. " + "This information helps to improve PET2BIDS and provides an indicator of real world " + "usage crucial for obtaining funding." + ) return parser @@ -262,6 +270,9 @@ def main(): print(example1) sys.exit(0) + if cli_args.notrack: + os.environ["PET2BIDS_TELEMETRY_ENABLED"] = "False" + collect_pixel_data = False if cli_args.convert or cli_args.update: collect_pixel_data = True diff --git a/pypet2bids/pypet2bids/helper_functions.py b/pypet2bids/pypet2bids/helper_functions.py index 46afbf5..e95856a 100644 --- a/pypet2bids/pypet2bids/helper_functions.py +++ b/pypet2bids/pypet2bids/helper_functions.py @@ -15,7 +15,6 @@ | *Copyright OpenNeuroPET team* """ - import os import gzip import re @@ -286,7 +285,9 @@ def decompress(file_like_object, output_path: str = None): return output_path -def load_vars_from_config(path_to_config: str=pathlib.Path.home() / ".pet2bidsconfig"): +def load_vars_from_config( + path_to_config: str = pathlib.Path.home() / ".pet2bidsconfig", +): """ Loads values from a .env file given a path to said .env file. diff --git a/pypet2bids/pypet2bids/telemetry.py b/pypet2bids/pypet2bids/telemetry.py index 6bdd1c6..0ef9f19 100644 --- a/pypet2bids/pypet2bids/telemetry.py +++ b/pypet2bids/pypet2bids/telemetry.py @@ -13,11 +13,24 @@ from helper_functions import get_version, load_vars_from_config, modify_config_file except ModuleNotFoundError: # collect pet2bids version - from pypet2bids.helper_functions import get_version, load_vars_from_config, modify_config_file + from pypet2bids.helper_functions import ( + get_version, + load_vars_from_config, + modify_config_file, + ) pet2bids_config = load_vars_from_config() -telemetry_default_url = pet2bids_config.get("TELEMETRY_URL", "http://52.87.154.236/telemetry/") +telemetry_default_url = pet2bids_config.get( + "TELEMETRY_URL", "http://52.87.154.236/telemetry/" +) +# check environment variables as well as the config file +telemetry_enabled_env = os.getenv("PET2BIDS_TELEMETRY_ENABLED", True) telemetry_enabled = pet2bids_config.get("TELEMETRY_ENABLED", True) + +# if telemetry is disabled in the config file or the environment variable disable its use. +if telemetry_enabled_env is False or telemetry_enabled is False: + telemetry_enabled = False + telemetry_notify_user = pet2bids_config.get("NOTIFY_USER_OF_TELEMETRY", False) @@ -31,12 +44,16 @@ def ask_user_to_opt_out(timeout=10): The user input if provided within the timeout, otherwise None. """ - print("Do you want to opt out of telemetry? (yes/no): ".format(timeout), end="", flush=True) + print( + "Do you want to opt out of telemetry? (yes/no): ".format(timeout), + end="", + flush=True, + ) sys.stdout.flush() ready, _, _ = select.select([sys.stdin], [], [], timeout) if ready: - response = sys.stdin.readline().rstrip('\n') + response = sys.stdin.readline().rstrip("\n") if response.lower() == "yes": return True else: @@ -177,5 +194,3 @@ def count_output_files(output_file_path: Union[str, pathlib.Path]): "NiftiFiles": num_nifti_files, "NiftiFilesSize": nifti_files_size, } - - From ff3645d8c7198f8c4e52aacd98e1332a38ceb282 Mon Sep 17 00:00:00 2001 From: Anthony Galassi <28850131+bendhouseart@users.noreply.github.com> Date: Mon, 12 Aug 2024 11:14:21 -0400 Subject: [PATCH 09/27] updating matlab to suit passing of --notrack to conversion functions --- matlab/dcm2niix4pet.m | 26 ++++++++++++++++++++++++-- 1 file changed, 24 insertions(+), 2 deletions(-) diff --git a/matlab/dcm2niix4pet.m b/matlab/dcm2niix4pet.m index 08bad7f..6dc6ac1 100644 --- a/matlab/dcm2niix4pet.m +++ b/matlab/dcm2niix4pet.m @@ -1,4 +1,4 @@ -function dcm2niix4pet(FolderList,MetaList,varargin) +function dcm2niix4pet(FolderList,MetaList,varargin, notrack) % Converts dicom image file to nifti+json calling dcm2niix augmenting the % json file to be BIDS compliant. Note that you are always right when it @@ -12,7 +12,7 @@ function dcm2niix4pet(FolderList,MetaList,varargin) % % :param FolderList: Cell array of char strings with filenames and paths % :param MetaList: Cell array of structures for metadata -% :param options: +% :param varargin: % - *deletedcm* to be 'on' or 'off' % - *o* the output directory or cell arrays of directories % IF the folder is BIDS sub-xx files are renamed automatically @@ -30,6 +30,7 @@ function dcm2niix4pet(FolderList,MetaList,varargin) % - *w* = 2; % write behavior for name conflicts (0,1,2, default 2: 0=skip duplicates, 1=overwrite, 2=add suffix) % - *x* = 'n'; % crop 3D acquisitions (y/n/i, default n, use 'i'gnore to neither crop nor rotate 3D acquistions) % - *z* = 'n'; % gz compress images (y/o/i/n/3, default y) [y=pigz, o=optimal pigz, i=internal:miniz, n=no, 3=no,3D] +% :param notrack: boolean to Opt-out of sending tracking information of this run to the PET2BIDS developers. This information helps to improve PET2BIDS and provides an indicator of real world usage crucial for obtaining funding." % % .. code-block:: % @@ -220,6 +221,7 @@ function dcm2niix4pet(FolderList,MetaList,varargin) elseif strcmpi(varargin{var},'o') outputdir = varargin{var+1}; end + end if isempty(outputdir) @@ -235,6 +237,26 @@ function dcm2niix4pet(FolderList,MetaList,varargin) end end +% check to see if the user has disabled telemetry +no_track_string = lower(string(notrack)); +if strcmp(no_track_string, 'true') + tracking = false; +elseif strcmp(no_track_string, 'false') + tracking = true; +else + try + numeric_notrack = str2num(no_track_string); + tracking = logical(numeric_notrack); + catch + % don't do anything + end +end + +if ~tracking + setenv('PET2BIDS_TELEMETRY_ENABLED', 'false'); +end + + %% convert % ---------- for folder = 1:size(FolderList,1) From 400fec2649b4e951c2dae1a00aa615cddcd7f97b Mon Sep 17 00:00:00 2001 From: Anthony Galassi <28850131+bendhouseart@users.noreply.github.com> Date: Mon, 12 Aug 2024 12:05:14 -0400 Subject: [PATCH 10/27] update tracking on matlab to set env to not track if provided via arguments --- matlab/dcm2niix4pet.m | 25 ++++++------------------- matlab/ecat2nii.m | 3 +++ 2 files changed, 9 insertions(+), 19 deletions(-) diff --git a/matlab/dcm2niix4pet.m b/matlab/dcm2niix4pet.m index 6dc6ac1..e585a10 100644 --- a/matlab/dcm2niix4pet.m +++ b/matlab/dcm2niix4pet.m @@ -1,4 +1,4 @@ -function dcm2niix4pet(FolderList,MetaList,varargin, notrack) +function dcm2niix4pet(FolderList,MetaList,varargin) % Converts dicom image file to nifti+json calling dcm2niix augmenting the % json file to be BIDS compliant. Note that you are always right when it @@ -220,6 +220,11 @@ function dcm2niix4pet(FolderList,MetaList,varargin, notrack) end elseif strcmpi(varargin{var},'o') outputdir = varargin{var+1}; + elseif strcmpi(varargin{var},'notrack') + notrack = varargin{var+1}; + if notrack; setenv('TELEMETRY_ENABLED', 'False'); end + else + error('unknown option %s',varargin{var}) end end @@ -237,24 +242,6 @@ function dcm2niix4pet(FolderList,MetaList,varargin, notrack) end end -% check to see if the user has disabled telemetry -no_track_string = lower(string(notrack)); -if strcmp(no_track_string, 'true') - tracking = false; -elseif strcmp(no_track_string, 'false') - tracking = true; -else - try - numeric_notrack = str2num(no_track_string); - tracking = logical(numeric_notrack); - catch - % don't do anything - end -end - -if ~tracking - setenv('PET2BIDS_TELEMETRY_ENABLED', 'false'); -end %% convert diff --git a/matlab/ecat2nii.m b/matlab/ecat2nii.m index 34222f7..c364010 100644 --- a/matlab/ecat2nii.m +++ b/matlab/ecat2nii.m @@ -114,6 +114,9 @@ gz = varargin{v+1}; elseif strcmpi(varargin{v},'savemat') savemat = varargin{v+1}; + elseif strcmpi(varargin{v},'notrack') + notrack = varargin{v+1}; + if notrack; setenv('TELEMETRY_ENABLED', 'False'); end end end From 5903752ec9a444abd78ab292a1abd34f4a3cb702 Mon Sep 17 00:00:00 2001 From: Anthony Galassi <28850131+bendhouseart@users.noreply.github.com> Date: Mon, 12 Aug 2024 16:54:48 -0400 Subject: [PATCH 11/27] finished setting up matlab version --- matlab/dcm2niix4pet.m | 3 +-- matlab/ecat2nii.m | 3 +-- matlab/telemetry.m | 6 +++--- 3 files changed, 5 insertions(+), 7 deletions(-) diff --git a/matlab/dcm2niix4pet.m b/matlab/dcm2niix4pet.m index e585a10..da4399c 100644 --- a/matlab/dcm2niix4pet.m +++ b/matlab/dcm2niix4pet.m @@ -221,8 +221,7 @@ function dcm2niix4pet(FolderList,MetaList,varargin) elseif strcmpi(varargin{var},'o') outputdir = varargin{var+1}; elseif strcmpi(varargin{var},'notrack') - notrack = varargin{var+1}; - if notrack; setenv('TELEMETRY_ENABLED', 'False'); end + setenv('TELEMETRY_ENABLED', 'False') else error('unknown option %s',varargin{var}) end diff --git a/matlab/ecat2nii.m b/matlab/ecat2nii.m index c364010..52b54e4 100644 --- a/matlab/ecat2nii.m +++ b/matlab/ecat2nii.m @@ -115,8 +115,7 @@ elseif strcmpi(varargin{v},'savemat') savemat = varargin{v+1}; elseif strcmpi(varargin{v},'notrack') - notrack = varargin{v+1}; - if notrack; setenv('TELEMETRY_ENABLED', 'False'); end + setenv('TELEMETRY_ENABLED', 'False') end end diff --git a/matlab/telemetry.m b/matlab/telemetry.m index baebd18..06cd1e4 100644 --- a/matlab/telemetry.m +++ b/matlab/telemetry.m @@ -31,8 +31,8 @@ function telemetry(telemetry_data, input_path, output_path) % checks to see if the telemetry is enabled or disabled environment = getenv(); % check environment too before loading the config file - if isfield(environment, 'PET2BIDS_TELEMETRY_ENABLED') - disable_telemetry_env = strcmpi(getenv("PET2BIDS_TELEMETRY_ENABLED"), 'false'); + if isfield(environment, 'TELEMETRY_ENABLED') + disable_telemetry_env = strcmpi(getenv("TELEMETRY_ENABLED"), 'false'); else disable_telemetry_env = false; end @@ -40,7 +40,7 @@ function telemetry(telemetry_data, input_path, output_path) home_dir = environment("HOME"); loadenv(fullfile(home_dir, '.pet2bidsconfig'), FileType='env'); % convert string to boolean/logical - disable_telemetry = strcmpi(getenv("PET2BIDS_TELEMETRY_ENABLED"), 'false'); + disable_telemetry = strcmpi(getenv("TELEMETRY_ENABLED"), 'false'); if disable_telemetry | disable_telemetry_env e = false; From 4b4928a269fca0dd7e5d993f691cf94cf1fe72b9 Mon Sep 17 00:00:00 2001 From: Anthony Galassi <28850131+bendhouseart@users.noreply.github.com> Date: Wed, 14 Aug 2024 14:45:50 -0400 Subject: [PATCH 12/27] fix error with loading config --- pypet2bids/pypet2bids/helper_functions.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/pypet2bids/pypet2bids/helper_functions.py b/pypet2bids/pypet2bids/helper_functions.py index e95856a..73ae19f 100644 --- a/pypet2bids/pypet2bids/helper_functions.py +++ b/pypet2bids/pypet2bids/helper_functions.py @@ -297,7 +297,10 @@ def load_vars_from_config( if os.path.isfile(path_to_config): parameters = dotenv.main.dotenv_values(path_to_config) else: - raise FileNotFoundError(path_to_config) + log = logger("pypet2bids") + log.warning(f"Unable to locate {path_to_config}, returning empty dictionary.") + parameters = {} + #raise FileNotFoundError(path_to_config) for parameter, value in parameters.items(): try: From 9bc9e56bf3a250560d4f1c846dd33aeee491e893 Mon Sep 17 00:00:00 2001 From: Anthony Galassi <28850131+bendhouseart@users.noreply.github.com> Date: Wed, 14 Aug 2024 15:08:36 -0400 Subject: [PATCH 13/27] automated message was more errofr that it's worth --- pypet2bids/pypet2bids/telemetry.py | 35 ------------------------------ 1 file changed, 35 deletions(-) diff --git a/pypet2bids/pypet2bids/telemetry.py b/pypet2bids/pypet2bids/telemetry.py index 0ef9f19..bbc0683 100644 --- a/pypet2bids/pypet2bids/telemetry.py +++ b/pypet2bids/pypet2bids/telemetry.py @@ -34,41 +34,6 @@ telemetry_notify_user = pet2bids_config.get("NOTIFY_USER_OF_TELEMETRY", False) -def ask_user_to_opt_out(timeout=10): - """Waits for user input for a specified number of seconds. - - Args: - timeout: Number of seconds to wait for input. - - Returns: - The user input if provided within the timeout, otherwise None. - """ - - print( - "Do you want to opt out of telemetry? (yes/no): ".format(timeout), - end="", - flush=True, - ) - sys.stdout.flush() - - ready, _, _ = select.select([sys.stdin], [], [], timeout) - if ready: - response = sys.stdin.readline().rstrip("\n") - if response.lower() == "yes": - return True - else: - return False - - -if telemetry_notify_user is False: - opt_out = ask_user_to_opt_out() - if opt_out: - # update the config file - modify_config_file("TELEMETRY_ENABLED", False) - - modify_config_file("NOTIFY_USER_OF_TELEMETRY", True) - - def telemetry_enabled(config_path=None): """ Check if telemetry is enabled, if it isn't disabled in the .pet2bidsconfig file From b360317f3981b01b2f5dbf5748153b40a310e68d Mon Sep 17 00:00:00 2001 From: Anthony Galassi <28850131+bendhouseart@users.noreply.github.com> Date: Wed, 14 Aug 2024 16:34:04 -0400 Subject: [PATCH 14/27] formatted files --- pypet2bids/pypet2bids/dcm2niix4pet.py | 4 ++-- pypet2bids/pypet2bids/ecat_cli.py | 4 ++-- pypet2bids/pypet2bids/helper_functions.py | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/pypet2bids/pypet2bids/dcm2niix4pet.py b/pypet2bids/pypet2bids/dcm2niix4pet.py index 4d6761c..7d1bf3b 100644 --- a/pypet2bids/pypet2bids/dcm2niix4pet.py +++ b/pypet2bids/pypet2bids/dcm2niix4pet.py @@ -1114,8 +1114,8 @@ def cli(): action="store_true", default=False, help="Opt-out of sending tracking information of this run to the PET2BIDS developers. " - "This information helps to improve PET2BIDS and provides an indicator of real world " - "usage crucial for obtaining funding." + "This information helps to improve PET2BIDS and provides an indicator of real world " + "usage crucial for obtaining funding.", ) return parser diff --git a/pypet2bids/pypet2bids/ecat_cli.py b/pypet2bids/pypet2bids/ecat_cli.py index fa52584..d6a66f2 100644 --- a/pypet2bids/pypet2bids/ecat_cli.py +++ b/pypet2bids/pypet2bids/ecat_cli.py @@ -195,8 +195,8 @@ def cli(): action="store_true", default=False, help="Opt-out of sending tracking information of this run to the PET2BIDS developers. " - "This information helps to improve PET2BIDS and provides an indicator of real world " - "usage crucial for obtaining funding." + "This information helps to improve PET2BIDS and provides an indicator of real world " + "usage crucial for obtaining funding.", ) return parser diff --git a/pypet2bids/pypet2bids/helper_functions.py b/pypet2bids/pypet2bids/helper_functions.py index 73ae19f..420da04 100644 --- a/pypet2bids/pypet2bids/helper_functions.py +++ b/pypet2bids/pypet2bids/helper_functions.py @@ -300,7 +300,7 @@ def load_vars_from_config( log = logger("pypet2bids") log.warning(f"Unable to locate {path_to_config}, returning empty dictionary.") parameters = {} - #raise FileNotFoundError(path_to_config) + # raise FileNotFoundError(path_to_config) for parameter, value in parameters.items(): try: From 878d4acfaed53a7746316d690f56f617fb321c9a Mon Sep 17 00:00:00 2001 From: Anthony Galassi <28850131+bendhouseart@users.noreply.github.com> Date: Thu, 15 Aug 2024 14:33:17 -0400 Subject: [PATCH 15/27] add try catch for .env file check on telemetry.m --- matlab/telemetry.m | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/matlab/telemetry.m b/matlab/telemetry.m index 06cd1e4..baab2d0 100644 --- a/matlab/telemetry.m +++ b/matlab/telemetry.m @@ -38,8 +38,13 @@ function telemetry(telemetry_data, input_path, output_path) end home_dir = environment("HOME"); - loadenv(fullfile(home_dir, '.pet2bidsconfig'), FileType='env'); - % convert string to boolean/logical + try + loadenv(fullfile(home_dir, '.pet2bidsconfig'), FileType='env'); + % convert string to boolean/logical + catch ME + disable_telemetry = false; + end + disable_telemetry = strcmpi(getenv("TELEMETRY_ENABLED"), 'false'); if disable_telemetry | disable_telemetry_env From 29e32a4cc9dd457231ff366e04c6b60051001966 Mon Sep 17 00:00:00 2001 From: Anthony Galassi <28850131+bendhouseart@users.noreply.github.com> Date: Fri, 16 Aug 2024 14:01:01 -0400 Subject: [PATCH 16/27] update poetry lock file --- pypet2bids/poetry.lock | 44 +++++++++++++++++++++--------------------- 1 file changed, 22 insertions(+), 22 deletions(-) diff --git a/pypet2bids/poetry.lock b/pypet2bids/poetry.lock index c644a2c..890a072 100644 --- a/pypet2bids/poetry.lock +++ b/pypet2bids/poetry.lock @@ -24,13 +24,13 @@ files = [ [[package]] name = "babel" -version = "2.15.0" +version = "2.16.0" description = "Internationalization utilities" optional = false python-versions = ">=3.8" files = [ - {file = "Babel-2.15.0-py3-none-any.whl", hash = "sha256:08706bdad8d0a3413266ab61bd6c34d0c28d6e1e7badf40a2cebe67644e2e1fb"}, - {file = "babel-2.15.0.tar.gz", hash = "sha256:8daf0e265d05768bc6c7a314cf1321e9a123afc328cc635c18622a2f30a04413"}, + {file = "babel-2.16.0-py3-none-any.whl", hash = "sha256:368b5b98b37c06b7daf6696391c3240c938b37767d4584413e8438c5c435fa8b"}, + {file = "babel-2.16.0.tar.gz", hash = "sha256:d1f3554ca26605fe173f3de0c65f750f5a42f924499bf134de6423582298e316"}, ] [package.dependencies] @@ -262,21 +262,21 @@ test = ["flufl.flake8", "importlib-resources (>=1.3)", "jaraco.test (>=5.4)", "p [[package]] name = "importlib-resources" -version = "6.4.0" +version = "6.4.2" description = "Read resources from Python packages" optional = false python-versions = ">=3.8" files = [ - {file = "importlib_resources-6.4.0-py3-none-any.whl", hash = "sha256:50d10f043df931902d4194ea07ec57960f66a80449ff867bfe782b4c486ba78c"}, - {file = "importlib_resources-6.4.0.tar.gz", hash = "sha256:cdb2b453b8046ca4e3798eb1d84f3cce1446a0e8e7b5ef4efb600f19fc398145"}, + {file = "importlib_resources-6.4.2-py3-none-any.whl", hash = "sha256:8bba8c54a8a3afaa1419910845fa26ebd706dc716dd208d9b158b4b6966f5c5c"}, + {file = "importlib_resources-6.4.2.tar.gz", hash = "sha256:6cbfbefc449cc6e2095dd184691b7a12a04f40bc75dd4c55d31c34f174cdf57a"}, ] [package.dependencies] zipp = {version = ">=3.1.0", markers = "python_version < \"3.10\""} [package.extras] -docs = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "rst.linker (>=1.9)", "sphinx (<7.2.5)", "sphinx (>=3.5)", "sphinx-lint"] -testing = ["jaraco.test (>=5.4)", "pytest (>=6)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=2.2)", "pytest-mypy", "pytest-ruff (>=0.2.1)", "zipp (>=3.17)"] +doc = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-lint"] +test = ["jaraco.test (>=5.4)", "pytest (>=6,!=8.1.*)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=2.2)", "pytest-mypy", "pytest-ruff (>=0.2.1)", "zipp (>=3.17)"] [[package]] name = "iniconfig" @@ -654,13 +654,13 @@ hook-testing = ["execnet (>=1.5.0)", "psutil", "pytest (>=2.7.3)"] [[package]] name = "pyinstaller-hooks-contrib" -version = "2024.7" +version = "2024.8" description = "Community maintained hooks for PyInstaller" optional = false -python-versions = ">=3.7" +python-versions = ">=3.8" files = [ - {file = "pyinstaller_hooks_contrib-2024.7-py2.py3-none-any.whl", hash = "sha256:8bf0775771fbaf96bcd2f4dfd6f7ae6c1dd1b1efe254c7e50477b3c08e7841d8"}, - {file = "pyinstaller_hooks_contrib-2024.7.tar.gz", hash = "sha256:fd5f37dcf99bece184e40642af88be16a9b89613ecb958a8bd1136634fc9fac5"}, + {file = "pyinstaller_hooks_contrib-2024.8-py3-none-any.whl", hash = "sha256:0057fe9a5c398d3f580e73e58793a1d4a8315ca91c3df01efea1c14ed557825a"}, + {file = "pyinstaller_hooks_contrib-2024.8.tar.gz", hash = "sha256:29b68d878ab739e967055b56a93eb9b58e529d5b054fbab7a2f2bacf80cef3e2"}, ] [package.dependencies] @@ -745,13 +745,13 @@ files = [ [[package]] name = "pywin32-ctypes" -version = "0.2.2" +version = "0.2.3" description = "A (partial) reimplementation of pywin32 using ctypes/cffi" optional = false python-versions = ">=3.6" files = [ - {file = "pywin32-ctypes-0.2.2.tar.gz", hash = "sha256:3426e063bdd5fd4df74a14fa3cf80a0b42845a87e1d1e81f6549f9daec593a60"}, - {file = "pywin32_ctypes-0.2.2-py3-none-any.whl", hash = "sha256:bf490a1a709baf35d688fe0ecf980ed4de11d2b3e37b51e5442587a75d9957e7"}, + {file = "pywin32-ctypes-0.2.3.tar.gz", hash = "sha256:d162dc04946d704503b2edc4d55f3dba5c1d539ead017afa00142c38b9885755"}, + {file = "pywin32_ctypes-0.2.3-py3-none-any.whl", hash = "sha256:8a1513379d709975552d202d942d9837758905c8d01eb82b8bcc30918929e7b8"}, ] [[package]] @@ -826,18 +826,18 @@ test = ["asv", "gmpy2", "mpmath", "pytest", "pytest-cov", "pytest-xdist", "sciki [[package]] name = "setuptools" -version = "72.1.0" +version = "72.2.0" description = "Easily download, build, install, upgrade, and uninstall Python packages" optional = false python-versions = ">=3.8" files = [ - {file = "setuptools-72.1.0-py3-none-any.whl", hash = "sha256:5a03e1860cf56bb6ef48ce186b0e557fdba433237481a9a625176c2831be15d1"}, - {file = "setuptools-72.1.0.tar.gz", hash = "sha256:8d243eff56d095e5817f796ede6ae32941278f542e0f941867cc05ae52b162ec"}, + {file = "setuptools-72.2.0-py3-none-any.whl", hash = "sha256:f11dd94b7bae3a156a95ec151f24e4637fb4fa19c878e4d191bfb8b2d82728c4"}, + {file = "setuptools-72.2.0.tar.gz", hash = "sha256:80aacbf633704e9c8bfa1d99fa5dd4dc59573efcf9e4042c13d3bcef91ac2ef9"}, ] [package.extras] core = ["importlib-metadata (>=6)", "importlib-resources (>=5.10.2)", "jaraco.text (>=3.7)", "more-itertools (>=8.8)", "ordered-set (>=3.1.1)", "packaging (>=24)", "platformdirs (>=2.6.2)", "tomli (>=2.0.1)", "wheel (>=0.43.0)"] -doc = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "pygments-github-lexers (==0.0.5)", "pyproject-hooks (!=1.1)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-favicon", "sphinx-inline-tabs", "sphinx-lint", "sphinx-notfound-page (>=1,<2)", "sphinx-reredirects", "sphinxcontrib-towncrier"] +doc = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "pygments-github-lexers (==0.0.5)", "pyproject-hooks (!=1.1)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-favicon", "sphinx-inline-tabs", "sphinx-lint", "sphinx-notfound-page (>=1,<2)", "sphinx-reredirects", "sphinxcontrib-towncrier", "towncrier (<24.7)"] test = ["build[virtualenv] (>=1.0.3)", "filelock (>=3.4.0)", "importlib-metadata", "ini2toml[lite] (>=0.14)", "jaraco.develop (>=7.21)", "jaraco.envs (>=2.2)", "jaraco.path (>=3.2.0)", "jaraco.test", "mypy (==1.11.*)", "packaging (>=23.2)", "pip (>=19.1)", "pyproject-hooks (!=1.1)", "pytest (>=6,!=8.1.*)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=2.2)", "pytest-home (>=0.5)", "pytest-mypy", "pytest-perf", "pytest-ruff (<0.4)", "pytest-ruff (>=0.2.1)", "pytest-ruff (>=0.3.2)", "pytest-subprocess", "pytest-timeout", "pytest-xdist (>=3)", "tomli", "tomli-w (>=1.0.0)", "virtualenv (>=13.0.0)", "wheel"] [[package]] @@ -1091,13 +1091,13 @@ test = ["pytest", "pytest-cov"] [[package]] name = "zipp" -version = "3.19.2" +version = "3.20.0" description = "Backport of pathlib-compatible object wrapper for zip files" optional = false python-versions = ">=3.8" files = [ - {file = "zipp-3.19.2-py3-none-any.whl", hash = "sha256:f091755f667055f2d02b32c53771a7a6c8b47e1fdbc4b72a8b9072b3eef8015c"}, - {file = "zipp-3.19.2.tar.gz", hash = "sha256:bf1dcf6450f873a13e952a29504887c89e6de7506209e5b1bcc3460135d4de19"}, + {file = "zipp-3.20.0-py3-none-any.whl", hash = "sha256:58da6168be89f0be59beb194da1250516fdaa062ccebd30127ac65d30045e10d"}, + {file = "zipp-3.20.0.tar.gz", hash = "sha256:0145e43d89664cfe1a2e533adc75adafed82fe2da404b4bbb6b026c0157bdb31"}, ] [package.extras] From 349ef31fa2560a612e0cead0b874a65220a60bdc Mon Sep 17 00:00:00 2001 From: Anthony Galassi <28850131+bendhouseart@users.noreply.github.com> Date: Thu, 12 Sep 2024 11:06:55 -0400 Subject: [PATCH 17/27] bump version, update url for telemetry --- pypet2bids/pypet2bids/telemetry.py | 9 ++++++--- pypet2bids/pyproject.toml | 2 +- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/pypet2bids/pypet2bids/telemetry.py b/pypet2bids/pypet2bids/telemetry.py index bbc0683..2233088 100644 --- a/pypet2bids/pypet2bids/telemetry.py +++ b/pypet2bids/pypet2bids/telemetry.py @@ -21,7 +21,7 @@ pet2bids_config = load_vars_from_config() telemetry_default_url = pet2bids_config.get( - "TELEMETRY_URL", "http://52.87.154.236/telemetry/" + "TELEMETRY_URL", "http://openneuropet.org/pet2bids/" ) # check environment variables as well as the config file telemetry_enabled_env = os.getenv("PET2BIDS_TELEMETRY_ENABLED", True) @@ -82,8 +82,11 @@ def send_telemetry(json_data: dict, url: str = telemetry_default_url): json_data["description"] = "pet2bids_python_telemetry" - # Send a POST request to the telemetry server - requests.post(url, json=json_data) + try: + # Send a POST request to the telemetry server + requests.post(url, json=json_data) + except requests.exceptions.RequestException as e: + pass else: pass diff --git a/pypet2bids/pyproject.toml b/pypet2bids/pyproject.toml index 95760d0..f7117d9 100644 --- a/pypet2bids/pyproject.toml +++ b/pypet2bids/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "pypet2bids" -version = "1.3.13dev" +version = "1.3.13" description = "A python library for converting PET imaging and blood data to BIDS." authors = ["anthony galassi <28850131+bendhouseart@users.noreply.github.com>"] license = "MIT" From b3d4127a33773bae51fae38b85e8794c269fd652 Mon Sep 17 00:00:00 2001 From: Anthony Galassi <28850131+bendhouseart@users.noreply.github.com> Date: Thu, 12 Sep 2024 11:21:38 -0400 Subject: [PATCH 18/27] 319 standardize radiochemistry metadata case order (#321) * Bump Pandas Version (#317) * fix spelling errors to appease codespell * added reordering for Isotope Number --- ecat_validation/Readme.md | 2 +- matlab/dcm2niix4pet.m | 4 +- metadata/PET_Radionuclide.mkd | 76 ++++---- pypet2bids/poetry.lock | 184 +++++++++++------- pypet2bids/pypet2bids/ecat_cli.py | 4 +- pypet2bids/pypet2bids/helper_functions.py | 34 ++++ pypet2bids/pyproject.toml | 2 +- pypet2bids/tests/test_helper_functions.py | 15 ++ .../blood/pmod/convert_pmod_to_blood.m | 2 +- .../many_subjects_sheet/README.mkd | 2 +- .../single_subject_sheet/README.mkd | 2 +- 11 files changed, 211 insertions(+), 116 deletions(-) diff --git a/ecat_validation/Readme.md b/ecat_validation/Readme.md index f061b06..8677237 100644 --- a/ecat_validation/Readme.md +++ b/ecat_validation/Readme.md @@ -116,4 +116,4 @@ pip install pypet2bids ecatpet2bids ECAT7_multiframe.v.gz --convert ``` -This illustrates [what metadata are extracted from the ecat file](https://github.com/openneuropet/PET2BIDS/blob/main/ecat_validation/ECAT7_multiframe.json) - which does not comform with BIDS because radiochemistry and pharmaceutical metadata are missing. +This illustrates [what metadata are extracted from the ecat file](https://github.com/openneuropet/PET2BIDS/blob/main/ecat_validation/ECAT7_multiframe.json) - which does not conform with BIDS because radiochemistry and pharmaceutical metadata are missing. diff --git a/matlab/dcm2niix4pet.m b/matlab/dcm2niix4pet.m index da4399c..08e319d 100644 --- a/matlab/dcm2niix4pet.m +++ b/matlab/dcm2niix4pet.m @@ -28,7 +28,7 @@ function dcm2niix4pet(FolderList,MetaList,varargin) % - *p* = 'y'; % Philips precise float (not display) scaling (y/n, default y) % - *v* = 1; % verbose (n/y or 0/1/2, default 0) [no, yes, logorrheic] % - *w* = 2; % write behavior for name conflicts (0,1,2, default 2: 0=skip duplicates, 1=overwrite, 2=add suffix) -% - *x* = 'n'; % crop 3D acquisitions (y/n/i, default n, use 'i'gnore to neither crop nor rotate 3D acquistions) +% - *x* = 'n'; % crop 3D acquisitions (y/n/i, default n, use 'i'gnore to neither crop nor rotate 3D acquisitions) % - *z* = 'n'; % gz compress images (y/o/i/n/3, default y) [y=pigz, o=optimal pigz, i=internal:miniz, n=no, 3=no,3D] % :param notrack: boolean to Opt-out of sending tracking information of this run to the PET2BIDS developers. This information helps to improve PET2BIDS and provides an indicator of real world usage crucial for obtaining funding." % @@ -102,7 +102,7 @@ function dcm2niix4pet(FolderList,MetaList,varargin) p = 'y'; % Philips precise float (not display) scaling (y/n, default y) v = 1; % verbose (n/y or 0/1/2, default 0) [no, yes, logorrheic] w = 2; % write behavior for name conflicts (0,1,2, default 2: 0=skip duplicates, 1=overwrite, 2=add suffix) -x = 'n'; % crop 3D acquisitions (y/n/i, default n, use 'i'gnore to neither crop nor rotate 3D acquistions) +x = 'n'; % crop 3D acquisitions (y/n/i, default n, use 'i'gnore to neither crop nor rotate 3D acquisitions) z = 'y'; % gz compress images (y/o/i/n/3, default y) [y=pigz, o=optimal pigz, i=internal:miniz, n=no, 3=no,3D] %% check dcm2nii inputs diff --git a/metadata/PET_Radionuclide.mkd b/metadata/PET_Radionuclide.mkd index d0dfb4a..adda3d8 100644 --- a/metadata/PET_Radionuclide.mkd +++ b/metadata/PET_Radionuclide.mkd @@ -2,41 +2,41 @@ Table taken from https://dicom.nema.org/medical/Dicom/2016b/output/chtml/part16/sect_CID_4020.html -| Code Value | Code Meaning | -|:----------:|:---------------:| -| C-105A1 | ^11^Carbon | -| C-107A1 | ^13^Nitrogen | -| C-1018C | ^14^Oxygen | -| C-B1038 | ^15^Oxygen | -| C-111A1 | ^18^Fluorine | -| C-155A1 | ^22^Sodium | -| C-135A4 | ^38^Potassium | -| 126605 | ^43^Scandium | -| 126600 | ^44^Scandium | -| C-166A2 | ^45^Titanium | -| 126601 | ^51^Manganese | -| C-130A1 | ^52^Iron | -| C-149A1 | ^52^Manganese | -| 126607 | ^52m^Manganese | -| C-127A4 | ^60^Copper | -| C-127A1 | ^61^Copper | -| C-127A5 | ^62^Copper | -| C-141A1 | ^62^Zinc | -| C-127A | ^64^Copper | -| C-131A1 | ^66^Gallium | -| C-131A3 | ^68^Gallium | -| C-128A2 | ^68^Germanium | -| 126602 | ^70^Arsenic | -| C-115A2 | ^72^Arsenic | -| C-116A2 | ^73^Selenium | -| C-113A1 | ^75^Bromine | -| C-113A2 | ^76^Bromine | -| C-113A3 | ^77^Bromine | -| C-159A2 | ^82^Rubidium | -| C-162A3 | ^86^Yttrium | -| C-168A4 | ^89^Zirconium | -| 126603 | ^90^Niobium | -| C-162A7 | ^90^Yttrium | -| C-163AA | ^94m^Technetium | -| C-114A5 | ^124^Iodine | -| 126606 | ^152^Terbium | +| Code Value | Code Meaning | Isotope Abbreviation | +|:----------:|:---------------:|:--------------------:| +| C-105A1 | ^11^Carbon | 11C | +| C-107A1 | ^13^Nitrogen | 13N | +| C-1018C | ^14^Oxygen | 14O | +| C-B1038 | ^15^Oxygen | 150 | +| C-111A1 | ^18^Fluorine | 18F | +| C-155A1 | ^22^Sodium | 22Na | +| C-135A4 | ^38^Potassium | 38K | +| 126605 | ^43^Scandium | 43Sc | +| 126600 | ^44^Scandium | 44Sc | +| C-166A2 | ^45^Titanium | 45Ti | +| 126601 | ^51^Manganese | 51Mn | +| C-130A1 | ^52^Iron | 52Fe | +| C-149A1 | ^52^Manganese | 52Mn | +| 126607 | ^52m^Manganese | 52mMn | +| C-127A4 | ^60^Copper | 60Cu | +| C-127A1 | ^61^Copper | 61Cu | +| C-127A5 | ^62^Copper | 62Cu | +| C-141A1 | ^62^Zinc | 62Zn | +| C-127A | ^64^Copper | 64Cu | +| C-131A1 | ^66^Gallium | 66Ga | +| C-131A3 | ^68^Gallium | 68Ga | +| C-128A2 | ^68^Germanium | 68Ge | +| 126602 | ^70^Arsenic | 70As | +| C-115A2 | ^72^Arsenic | 72As | +| C-116A2 | ^73^Selenium | 73Se | +| C-113A1 | ^75^Bromine | 75Br | +| C-113A2 | ^76^Bromine | 76Br | +| C-113A3 | ^77^Bromine | 77Br | +| C-159A2 | ^82^Rubidium | 82Rb | +| C-162A3 | ^86^Yttrium | 86Y | +| C-168A4 | ^89^Zirconium | 89Zr | +| 126603 | ^90^Niobium | 90Nb | +| C-162A7 | ^90^Yttrium | 90Y | +| C-163AA | ^94m^Technetium | 94mTc | +| C-114A5 | ^124^Iodine | 124I | +| 126606 | ^152^Terbium | 152Tb | diff --git a/pypet2bids/poetry.lock b/pypet2bids/poetry.lock index 890a072..87ecc2a 100644 --- a/pypet2bids/poetry.lock +++ b/pypet2bids/poetry.lock @@ -64,13 +64,13 @@ virtualenv = ["virtualenv (>=20.0.35)"] [[package]] name = "certifi" -version = "2024.7.4" +version = "2024.8.30" description = "Python package for providing Mozilla's CA Bundle." optional = false python-versions = ">=3.6" files = [ - {file = "certifi-2024.7.4-py3-none-any.whl", hash = "sha256:c198e21b1289c2ab85ee4e67bb4b4ef3ead0892059901a8d5b622f24a1101e90"}, - {file = "certifi-2024.7.4.tar.gz", hash = "sha256:5a1e7645bc0ec61a09e26c36f6106dd4cf40c6db3a1fb6352b0244e7fb057c7b"}, + {file = "certifi-2024.8.30-py3-none-any.whl", hash = "sha256:922820b53db7a7257ffbda3f597266d435245903d80737e34f8a45ff3e3230d8"}, + {file = "certifi-2024.8.30.tar.gz", hash = "sha256:bec941d2aa8195e248a60b31ff9f0558284cf01a52591ceda73ea9afffd69fd9"}, ] [[package]] @@ -221,13 +221,13 @@ test = ["pytest (>=6)"] [[package]] name = "idna" -version = "3.7" +version = "3.8" description = "Internationalized Domain Names in Applications (IDNA)" optional = false -python-versions = ">=3.5" +python-versions = ">=3.6" files = [ - {file = "idna-3.7-py3-none-any.whl", hash = "sha256:82fee1fc78add43492d3a1898bfa6d8a904cc97d8427f683ed8e798d07761aa0"}, - {file = "idna-3.7.tar.gz", hash = "sha256:028ff3aadf0609c1fd278d8ea3089299412a7a8b9bd005dd08b9f8285bcb5cfc"}, + {file = "idna-3.8-py3-none-any.whl", hash = "sha256:050b4e5baadcd44d760cedbd2b8e639f2ff89bbc7a5730fcc662954303377aac"}, + {file = "idna-3.8.tar.gz", hash = "sha256:d838c2c0ed6fced7693d5e8ab8e734d5f8fda53a039c0164afb0b82e771e3603"}, ] [[package]] @@ -243,40 +243,48 @@ files = [ [[package]] name = "importlib-metadata" -version = "8.2.0" +version = "8.5.0" description = "Read metadata from Python packages" optional = false python-versions = ">=3.8" files = [ - {file = "importlib_metadata-8.2.0-py3-none-any.whl", hash = "sha256:11901fa0c2f97919b288679932bb64febaeacf289d18ac84dd68cb2e74213369"}, - {file = "importlib_metadata-8.2.0.tar.gz", hash = "sha256:72e8d4399996132204f9a16dcc751af254a48f8d1b20b9ff0f98d4a8f901e73d"}, + {file = "importlib_metadata-8.5.0-py3-none-any.whl", hash = "sha256:45e54197d28b7a7f1559e60b95e7c567032b602131fbd588f1497f47880aa68b"}, + {file = "importlib_metadata-8.5.0.tar.gz", hash = "sha256:71522656f0abace1d072b9e5481a48f07c138e00f079c38c8f883823f9c26bd7"}, ] [package.dependencies] -zipp = ">=0.5" +zipp = ">=3.20" [package.extras] +check = ["pytest-checkdocs (>=2.4)", "pytest-ruff (>=0.2.1)"] +cover = ["pytest-cov"] doc = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-lint"] +enabler = ["pytest-enabler (>=2.2)"] perf = ["ipython"] -test = ["flufl.flake8", "importlib-resources (>=1.3)", "jaraco.test (>=5.4)", "packaging", "pyfakefs", "pytest (>=6,!=8.1.*)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=2.2)", "pytest-mypy", "pytest-perf (>=0.9.2)", "pytest-ruff (>=0.2.1)"] +test = ["flufl.flake8", "importlib-resources (>=1.3)", "jaraco.test (>=5.4)", "packaging", "pyfakefs", "pytest (>=6,!=8.1.*)", "pytest-perf (>=0.9.2)"] +type = ["pytest-mypy"] [[package]] name = "importlib-resources" -version = "6.4.2" +version = "6.4.5" description = "Read resources from Python packages" optional = false python-versions = ">=3.8" files = [ - {file = "importlib_resources-6.4.2-py3-none-any.whl", hash = "sha256:8bba8c54a8a3afaa1419910845fa26ebd706dc716dd208d9b158b4b6966f5c5c"}, - {file = "importlib_resources-6.4.2.tar.gz", hash = "sha256:6cbfbefc449cc6e2095dd184691b7a12a04f40bc75dd4c55d31c34f174cdf57a"}, + {file = "importlib_resources-6.4.5-py3-none-any.whl", hash = "sha256:ac29d5f956f01d5e4bb63102a5a19957f1b9175e45649977264a1416783bb717"}, + {file = "importlib_resources-6.4.5.tar.gz", hash = "sha256:980862a1d16c9e147a59603677fa2aa5fd82b87f223b6cb870695bcfce830065"}, ] [package.dependencies] zipp = {version = ">=3.1.0", markers = "python_version < \"3.10\""} [package.extras] +check = ["pytest-checkdocs (>=2.4)", "pytest-ruff (>=0.2.1)"] +cover = ["pytest-cov"] doc = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-lint"] -test = ["jaraco.test (>=5.4)", "pytest (>=6,!=8.1.*)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=2.2)", "pytest-mypy", "pytest-ruff (>=0.2.1)", "zipp (>=3.17)"] +enabler = ["pytest-enabler (>=2.2)"] +test = ["jaraco.test (>=5.4)", "pytest (>=6,!=8.1.*)", "zipp (>=3.17)"] +type = ["pytest-mypy"] [[package]] name = "iniconfig" @@ -505,61 +513,80 @@ files = [ [[package]] name = "pandas" -version = "1.5.3" +version = "2.0.3" description = "Powerful data structures for data analysis, time series, and statistics" optional = false python-versions = ">=3.8" files = [ - {file = "pandas-1.5.3-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:3749077d86e3a2f0ed51367f30bf5b82e131cc0f14260c4d3e499186fccc4406"}, - {file = "pandas-1.5.3-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:972d8a45395f2a2d26733eb8d0f629b2f90bebe8e8eddbb8829b180c09639572"}, - {file = "pandas-1.5.3-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:50869a35cbb0f2e0cd5ec04b191e7b12ed688874bd05dd777c19b28cbea90996"}, - {file = "pandas-1.5.3-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c3ac844a0fe00bfaeb2c9b51ab1424e5c8744f89860b138434a363b1f620f354"}, - {file = "pandas-1.5.3-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7a0a56cef15fd1586726dace5616db75ebcfec9179a3a55e78f72c5639fa2a23"}, - {file = "pandas-1.5.3-cp310-cp310-win_amd64.whl", hash = "sha256:478ff646ca42b20376e4ed3fa2e8d7341e8a63105586efe54fa2508ee087f328"}, - {file = "pandas-1.5.3-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:6973549c01ca91ec96199e940495219c887ea815b2083722821f1d7abfa2b4dc"}, - {file = "pandas-1.5.3-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:c39a8da13cede5adcd3be1182883aea1c925476f4e84b2807a46e2775306305d"}, - {file = "pandas-1.5.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:f76d097d12c82a535fda9dfe5e8dd4127952b45fea9b0276cb30cca5ea313fbc"}, - {file = "pandas-1.5.3-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e474390e60ed609cec869b0da796ad94f420bb057d86784191eefc62b65819ae"}, - {file = "pandas-1.5.3-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5f2b952406a1588ad4cad5b3f55f520e82e902388a6d5a4a91baa8d38d23c7f6"}, - {file = "pandas-1.5.3-cp311-cp311-win_amd64.whl", hash = "sha256:bc4c368f42b551bf72fac35c5128963a171b40dce866fb066540eeaf46faa003"}, - {file = "pandas-1.5.3-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:14e45300521902689a81f3f41386dc86f19b8ba8dd5ac5a3c7010ef8d2932813"}, - {file = "pandas-1.5.3-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:9842b6f4b8479e41968eced654487258ed81df7d1c9b7b870ceea24ed9459b31"}, - {file = "pandas-1.5.3-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:26d9c71772c7afb9d5046e6e9cf42d83dd147b5cf5bcb9d97252077118543792"}, - {file = "pandas-1.5.3-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5fbcb19d6fceb9e946b3e23258757c7b225ba450990d9ed63ccceeb8cae609f7"}, - {file = "pandas-1.5.3-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:565fa34a5434d38e9d250af3c12ff931abaf88050551d9fbcdfafca50d62babf"}, - {file = "pandas-1.5.3-cp38-cp38-win32.whl", hash = "sha256:87bd9c03da1ac870a6d2c8902a0e1fd4267ca00f13bc494c9e5a9020920e1d51"}, - {file = "pandas-1.5.3-cp38-cp38-win_amd64.whl", hash = "sha256:41179ce559943d83a9b4bbacb736b04c928b095b5f25dd2b7389eda08f46f373"}, - {file = "pandas-1.5.3-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:c74a62747864ed568f5a82a49a23a8d7fe171d0c69038b38cedf0976831296fa"}, - {file = "pandas-1.5.3-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:c4c00e0b0597c8e4f59e8d461f797e5d70b4d025880516a8261b2817c47759ee"}, - {file = "pandas-1.5.3-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:a50d9a4336a9621cab7b8eb3fb11adb82de58f9b91d84c2cd526576b881a0c5a"}, - {file = "pandas-1.5.3-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:dd05f7783b3274aa206a1af06f0ceed3f9b412cf665b7247eacd83be41cf7bf0"}, - {file = "pandas-1.5.3-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9f69c4029613de47816b1bb30ff5ac778686688751a5e9c99ad8c7031f6508e5"}, - {file = "pandas-1.5.3-cp39-cp39-win32.whl", hash = "sha256:7cec0bee9f294e5de5bbfc14d0573f65526071029d036b753ee6507d2a21480a"}, - {file = "pandas-1.5.3-cp39-cp39-win_amd64.whl", hash = "sha256:dfd681c5dc216037e0b0a2c821f5ed99ba9f03ebcf119c7dac0e9a7b960b9ec9"}, - {file = "pandas-1.5.3.tar.gz", hash = "sha256:74a3fd7e5a7ec052f183273dc7b0acd3a863edf7520f5d3a1765c04ffdb3b0b1"}, + {file = "pandas-2.0.3-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:e4c7c9f27a4185304c7caf96dc7d91bc60bc162221152de697c98eb0b2648dd8"}, + {file = "pandas-2.0.3-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:f167beed68918d62bffb6ec64f2e1d8a7d297a038f86d4aed056b9493fca407f"}, + {file = "pandas-2.0.3-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ce0c6f76a0f1ba361551f3e6dceaff06bde7514a374aa43e33b588ec10420183"}, + {file = "pandas-2.0.3-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ba619e410a21d8c387a1ea6e8a0e49bb42216474436245718d7f2e88a2f8d7c0"}, + {file = "pandas-2.0.3-cp310-cp310-win32.whl", hash = "sha256:3ef285093b4fe5058eefd756100a367f27029913760773c8bf1d2d8bebe5d210"}, + {file = "pandas-2.0.3-cp310-cp310-win_amd64.whl", hash = "sha256:9ee1a69328d5c36c98d8e74db06f4ad518a1840e8ccb94a4ba86920986bb617e"}, + {file = "pandas-2.0.3-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:b084b91d8d66ab19f5bb3256cbd5ea661848338301940e17f4492b2ce0801fe8"}, + {file = "pandas-2.0.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:37673e3bdf1551b95bf5d4ce372b37770f9529743d2498032439371fc7b7eb26"}, + {file = "pandas-2.0.3-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b9cb1e14fdb546396b7e1b923ffaeeac24e4cedd14266c3497216dd4448e4f2d"}, + {file = "pandas-2.0.3-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d9cd88488cceb7635aebb84809d087468eb33551097d600c6dad13602029c2df"}, + {file = "pandas-2.0.3-cp311-cp311-win32.whl", hash = "sha256:694888a81198786f0e164ee3a581df7d505024fbb1f15202fc7db88a71d84ebd"}, + {file = "pandas-2.0.3-cp311-cp311-win_amd64.whl", hash = "sha256:6a21ab5c89dcbd57f78d0ae16630b090eec626360085a4148693def5452d8a6b"}, + {file = "pandas-2.0.3-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:9e4da0d45e7f34c069fe4d522359df7d23badf83abc1d1cef398895822d11061"}, + {file = "pandas-2.0.3-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:32fca2ee1b0d93dd71d979726b12b61faa06aeb93cf77468776287f41ff8fdc5"}, + {file = "pandas-2.0.3-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:258d3624b3ae734490e4d63c430256e716f488c4fcb7c8e9bde2d3aa46c29089"}, + {file = "pandas-2.0.3-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9eae3dc34fa1aa7772dd3fc60270d13ced7346fcbcfee017d3132ec625e23bb0"}, + {file = "pandas-2.0.3-cp38-cp38-win32.whl", hash = "sha256:f3421a7afb1a43f7e38e82e844e2bca9a6d793d66c1a7f9f0ff39a795bbc5e02"}, + {file = "pandas-2.0.3-cp38-cp38-win_amd64.whl", hash = "sha256:69d7f3884c95da3a31ef82b7618af5710dba95bb885ffab339aad925c3e8ce78"}, + {file = "pandas-2.0.3-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:5247fb1ba347c1261cbbf0fcfba4a3121fbb4029d95d9ef4dc45406620b25c8b"}, + {file = "pandas-2.0.3-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:81af086f4543c9d8bb128328b5d32e9986e0c84d3ee673a2ac6fb57fd14f755e"}, + {file = "pandas-2.0.3-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1994c789bf12a7c5098277fb43836ce090f1073858c10f9220998ac74f37c69b"}, + {file = "pandas-2.0.3-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5ec591c48e29226bcbb316e0c1e9423622bc7a4eaf1ef7c3c9fa1a3981f89641"}, + {file = "pandas-2.0.3-cp39-cp39-win32.whl", hash = "sha256:04dbdbaf2e4d46ca8da896e1805bc04eb85caa9a82e259e8eed00254d5e0c682"}, + {file = "pandas-2.0.3-cp39-cp39-win_amd64.whl", hash = "sha256:1168574b036cd8b93abc746171c9b4f1b83467438a5e45909fed645cf8692dbc"}, + {file = "pandas-2.0.3.tar.gz", hash = "sha256:c02f372a88e0d17f36d3093a644c73cfc1788e876a7c4bcb4020a77512e2043c"}, ] [package.dependencies] numpy = [ {version = ">=1.20.3", markers = "python_version < \"3.10\""}, - {version = ">=1.23.2", markers = "python_version >= \"3.11\""}, {version = ">=1.21.0", markers = "python_version >= \"3.10\" and python_version < \"3.11\""}, + {version = ">=1.23.2", markers = "python_version >= \"3.11\""}, ] -python-dateutil = ">=2.8.1" +python-dateutil = ">=2.8.2" pytz = ">=2020.1" +tzdata = ">=2022.1" [package.extras] -test = ["hypothesis (>=5.5.3)", "pytest (>=6.0)", "pytest-xdist (>=1.31)"] +all = ["PyQt5 (>=5.15.1)", "SQLAlchemy (>=1.4.16)", "beautifulsoup4 (>=4.9.3)", "bottleneck (>=1.3.2)", "brotlipy (>=0.7.0)", "fastparquet (>=0.6.3)", "fsspec (>=2021.07.0)", "gcsfs (>=2021.07.0)", "html5lib (>=1.1)", "hypothesis (>=6.34.2)", "jinja2 (>=3.0.0)", "lxml (>=4.6.3)", "matplotlib (>=3.6.1)", "numba (>=0.53.1)", "numexpr (>=2.7.3)", "odfpy (>=1.4.1)", "openpyxl (>=3.0.7)", "pandas-gbq (>=0.15.0)", "psycopg2 (>=2.8.6)", "pyarrow (>=7.0.0)", "pymysql (>=1.0.2)", "pyreadstat (>=1.1.2)", "pytest (>=7.3.2)", "pytest-asyncio (>=0.17.0)", "pytest-xdist (>=2.2.0)", "python-snappy (>=0.6.0)", "pyxlsb (>=1.0.8)", "qtpy (>=2.2.0)", "s3fs (>=2021.08.0)", "scipy (>=1.7.1)", "tables (>=3.6.1)", "tabulate (>=0.8.9)", "xarray (>=0.21.0)", "xlrd (>=2.0.1)", "xlsxwriter (>=1.4.3)", "zstandard (>=0.15.2)"] +aws = ["s3fs (>=2021.08.0)"] +clipboard = ["PyQt5 (>=5.15.1)", "qtpy (>=2.2.0)"] +compression = ["brotlipy (>=0.7.0)", "python-snappy (>=0.6.0)", "zstandard (>=0.15.2)"] +computation = ["scipy (>=1.7.1)", "xarray (>=0.21.0)"] +excel = ["odfpy (>=1.4.1)", "openpyxl (>=3.0.7)", "pyxlsb (>=1.0.8)", "xlrd (>=2.0.1)", "xlsxwriter (>=1.4.3)"] +feather = ["pyarrow (>=7.0.0)"] +fss = ["fsspec (>=2021.07.0)"] +gcp = ["gcsfs (>=2021.07.0)", "pandas-gbq (>=0.15.0)"] +hdf5 = ["tables (>=3.6.1)"] +html = ["beautifulsoup4 (>=4.9.3)", "html5lib (>=1.1)", "lxml (>=4.6.3)"] +mysql = ["SQLAlchemy (>=1.4.16)", "pymysql (>=1.0.2)"] +output-formatting = ["jinja2 (>=3.0.0)", "tabulate (>=0.8.9)"] +parquet = ["pyarrow (>=7.0.0)"] +performance = ["bottleneck (>=1.3.2)", "numba (>=0.53.1)", "numexpr (>=2.7.1)"] +plot = ["matplotlib (>=3.6.1)"] +postgresql = ["SQLAlchemy (>=1.4.16)", "psycopg2 (>=2.8.6)"] +spss = ["pyreadstat (>=1.1.2)"] +sql-other = ["SQLAlchemy (>=1.4.16)"] +test = ["hypothesis (>=6.34.2)", "pytest (>=7.3.2)", "pytest-asyncio (>=0.17.0)", "pytest-xdist (>=2.2.0)"] +xml = ["lxml (>=4.6.3)"] [[package]] name = "pefile" -version = "2023.2.7" +version = "2024.8.26" description = "Python PE parsing module" optional = false python-versions = ">=3.6.0" files = [ - {file = "pefile-2023.2.7-py3-none-any.whl", hash = "sha256:da185cd2af68c08a6cd4481f7325ed600a88f6a813bad9dea07ab3ef73d8d8d6"}, - {file = "pefile-2023.2.7.tar.gz", hash = "sha256:82e6114004b3d6911c77c3953e3838654b04511b8b66e8583db70c65998017dc"}, + {file = "pefile-2024.8.26-py3-none-any.whl", hash = "sha256:76f8b485dcd3b1bb8166f1128d395fa3d87af26360c2358fb75b80019b957c6f"}, + {file = "pefile-2024.8.26.tar.gz", hash = "sha256:3ff6c5d8b43e8c37bb6e6dd5085658d658a7a0bdcd20b6a07b1fcfc1c4e9d632"}, ] [[package]] @@ -670,13 +697,13 @@ setuptools = ">=42.0.0" [[package]] name = "pyparsing" -version = "3.1.2" +version = "3.1.4" description = "pyparsing module - Classes and methods to define and execute parsing grammars" optional = false python-versions = ">=3.6.8" files = [ - {file = "pyparsing-3.1.2-py3-none-any.whl", hash = "sha256:f9db75911801ed778fe61bb643079ff86601aca99fcae6345aa67292038fb742"}, - {file = "pyparsing-3.1.2.tar.gz", hash = "sha256:a1bac0ce561155ecc3ed78ca94d3c9378656ad4c94c1270de543f621420f94ad"}, + {file = "pyparsing-3.1.4-py3-none-any.whl", hash = "sha256:a6a7ee4235a3f944aa1fa2249307708f893fe5717dc603503c6c7969c070fb7c"}, + {file = "pyparsing-3.1.4.tar.gz", hash = "sha256:f86ec8d1a83f11977c9a6ea7598e8c27fc5cddfa5b07ea2241edbbde1d7bc032"}, ] [package.extras] @@ -734,13 +761,13 @@ cli = ["click (>=5.0)"] [[package]] name = "pytz" -version = "2024.1" +version = "2024.2" description = "World timezone definitions, modern and historical" optional = false python-versions = "*" files = [ - {file = "pytz-2024.1-py2.py3-none-any.whl", hash = "sha256:328171f4e3623139da4983451950b28e95ac706e13f3f2630a879749e7a8b319"}, - {file = "pytz-2024.1.tar.gz", hash = "sha256:2a29735ea9c18baf14b448846bde5a48030ed267578472d8955cd0e7443a9812"}, + {file = "pytz-2024.2-py2.py3-none-any.whl", hash = "sha256:31c7c1817eb7fae7ca4b8c7ee50c72f93aa2dd863de768e1ef4245d426aa0725"}, + {file = "pytz-2024.2.tar.gz", hash = "sha256:2aa355083c50a0f93fa581709deac0c9ad65cca8a9e9beac660adcbd493c798a"}, ] [[package]] @@ -826,19 +853,23 @@ test = ["asv", "gmpy2", "mpmath", "pytest", "pytest-cov", "pytest-xdist", "sciki [[package]] name = "setuptools" -version = "72.2.0" +version = "74.1.2" description = "Easily download, build, install, upgrade, and uninstall Python packages" optional = false python-versions = ">=3.8" files = [ - {file = "setuptools-72.2.0-py3-none-any.whl", hash = "sha256:f11dd94b7bae3a156a95ec151f24e4637fb4fa19c878e4d191bfb8b2d82728c4"}, - {file = "setuptools-72.2.0.tar.gz", hash = "sha256:80aacbf633704e9c8bfa1d99fa5dd4dc59573efcf9e4042c13d3bcef91ac2ef9"}, + {file = "setuptools-74.1.2-py3-none-any.whl", hash = "sha256:5f4c08aa4d3ebcb57a50c33b1b07e94315d7fc7230f7115e47fc99776c8ce308"}, + {file = "setuptools-74.1.2.tar.gz", hash = "sha256:95b40ed940a1c67eb70fc099094bd6e99c6ee7c23aa2306f4d2697ba7916f9c6"}, ] [package.extras] -core = ["importlib-metadata (>=6)", "importlib-resources (>=5.10.2)", "jaraco.text (>=3.7)", "more-itertools (>=8.8)", "ordered-set (>=3.1.1)", "packaging (>=24)", "platformdirs (>=2.6.2)", "tomli (>=2.0.1)", "wheel (>=0.43.0)"] +check = ["pytest-checkdocs (>=2.4)", "pytest-ruff (>=0.2.1)", "ruff (>=0.5.2)"] +core = ["importlib-metadata (>=6)", "importlib-resources (>=5.10.2)", "jaraco.text (>=3.7)", "more-itertools (>=8.8)", "packaging (>=24)", "platformdirs (>=2.6.2)", "tomli (>=2.0.1)", "wheel (>=0.43.0)"] +cover = ["pytest-cov"] doc = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "pygments-github-lexers (==0.0.5)", "pyproject-hooks (!=1.1)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-favicon", "sphinx-inline-tabs", "sphinx-lint", "sphinx-notfound-page (>=1,<2)", "sphinx-reredirects", "sphinxcontrib-towncrier", "towncrier (<24.7)"] -test = ["build[virtualenv] (>=1.0.3)", "filelock (>=3.4.0)", "importlib-metadata", "ini2toml[lite] (>=0.14)", "jaraco.develop (>=7.21)", "jaraco.envs (>=2.2)", "jaraco.path (>=3.2.0)", "jaraco.test", "mypy (==1.11.*)", "packaging (>=23.2)", "pip (>=19.1)", "pyproject-hooks (!=1.1)", "pytest (>=6,!=8.1.*)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=2.2)", "pytest-home (>=0.5)", "pytest-mypy", "pytest-perf", "pytest-ruff (<0.4)", "pytest-ruff (>=0.2.1)", "pytest-ruff (>=0.3.2)", "pytest-subprocess", "pytest-timeout", "pytest-xdist (>=3)", "tomli", "tomli-w (>=1.0.0)", "virtualenv (>=13.0.0)", "wheel"] +enabler = ["pytest-enabler (>=2.2)"] +test = ["build[virtualenv] (>=1.0.3)", "filelock (>=3.4.0)", "ini2toml[lite] (>=0.14)", "jaraco.develop (>=7.21)", "jaraco.envs (>=2.2)", "jaraco.path (>=3.2.0)", "jaraco.test", "packaging (>=23.2)", "pip (>=19.1)", "pyproject-hooks (!=1.1)", "pytest (>=6,!=8.1.*)", "pytest-home (>=0.5)", "pytest-perf", "pytest-subprocess", "pytest-timeout", "pytest-xdist (>=3)", "tomli-w (>=1.0.0)", "virtualenv (>=13.0.0)", "wheel (>=0.44.0)"] +type = ["importlib-metadata (>=7.0.2)", "jaraco.develop (>=7.21)", "mypy (==1.11.*)", "pytest-mypy"] [[package]] name = "six" @@ -1056,15 +1087,26 @@ files = [ {file = "tomli-2.0.1.tar.gz", hash = "sha256:de526c12914f0c550d15924c62d72abc48d6fe7364aa87328337a31007fe8a4f"}, ] +[[package]] +name = "tzdata" +version = "2024.1" +description = "Provider of IANA time zone data" +optional = false +python-versions = ">=2" +files = [ + {file = "tzdata-2024.1-py2.py3-none-any.whl", hash = "sha256:9068bc196136463f5245e51efda838afa15aaeca9903f49050dfa2679db4d252"}, + {file = "tzdata-2024.1.tar.gz", hash = "sha256:2674120f8d891909751c38abcdfd386ac0a5a1127954fbc332af6b5ceae07efd"}, +] + [[package]] name = "urllib3" -version = "2.2.2" +version = "2.2.3" description = "HTTP library with thread-safe connection pooling, file post, and more." optional = false python-versions = ">=3.8" files = [ - {file = "urllib3-2.2.2-py3-none-any.whl", hash = "sha256:a448b2f64d686155468037e1ace9f2d2199776e17f0a46610480d311f73e3472"}, - {file = "urllib3-2.2.2.tar.gz", hash = "sha256:dd505485549a7a552833da5e6063639d0d177c04f23bc3864e41e5dc5f612168"}, + {file = "urllib3-2.2.3-py3-none-any.whl", hash = "sha256:ca899ca043dcb1bafa3e262d73aa25c465bfb49e0bd9dd5d59f1d0acba2f8fac"}, + {file = "urllib3-2.2.3.tar.gz", hash = "sha256:e7d814a81dad81e6caf2ec9fdedb284ecc9c73076b62654547cc64ccdcae26e9"}, ] [package.extras] @@ -1091,20 +1133,24 @@ test = ["pytest", "pytest-cov"] [[package]] name = "zipp" -version = "3.20.0" +version = "3.20.1" description = "Backport of pathlib-compatible object wrapper for zip files" optional = false python-versions = ">=3.8" files = [ - {file = "zipp-3.20.0-py3-none-any.whl", hash = "sha256:58da6168be89f0be59beb194da1250516fdaa062ccebd30127ac65d30045e10d"}, - {file = "zipp-3.20.0.tar.gz", hash = "sha256:0145e43d89664cfe1a2e533adc75adafed82fe2da404b4bbb6b026c0157bdb31"}, + {file = "zipp-3.20.1-py3-none-any.whl", hash = "sha256:9960cd8967c8f85a56f920d5d507274e74f9ff813a0ab8889a5b5be2daf44064"}, + {file = "zipp-3.20.1.tar.gz", hash = "sha256:c22b14cc4763c5a5b04134207736c107db42e9d3ef2d9779d465f5f1bcba572b"}, ] [package.extras] +check = ["pytest-checkdocs (>=2.4)", "pytest-ruff (>=0.2.1)"] +cover = ["pytest-cov"] doc = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-lint"] -test = ["big-O", "importlib-resources", "jaraco.functools", "jaraco.itertools", "jaraco.test", "more-itertools", "pytest (>=6,!=8.1.*)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=2.2)", "pytest-ignore-flaky", "pytest-mypy", "pytest-ruff (>=0.2.1)"] +enabler = ["pytest-enabler (>=2.2)"] +test = ["big-O", "importlib-resources", "jaraco.functools", "jaraco.itertools", "jaraco.test", "more-itertools", "pytest (>=6,!=8.1.*)", "pytest-ignore-flaky"] +type = ["pytest-mypy"] [metadata] lock-version = "2.0" python-versions = ">=3.8,<=3.12" -content-hash = "d5e5bf221e17dd550fa3411f510dc5df546aac9dd2b97a40e98fd2cd8fe834c2" +content-hash = "b02777dd04e01a7b11ee992b28767525b36d9ae5b29ff37241bff88871cdc483" diff --git a/pypet2bids/pypet2bids/ecat_cli.py b/pypet2bids/pypet2bids/ecat_cli.py index d6a66f2..6a4067e 100644 --- a/pypet2bids/pypet2bids/ecat_cli.py +++ b/pypet2bids/pypet2bids/ecat_cli.py @@ -174,7 +174,7 @@ def cli(): help="Update/create a json sidecar file from an ECAT given a path to that each " "file,. e.g." "ecatpet2bids ecatfile.v --update path/to/sidecar.json " - "additionally one can pass metadat to the sidecar via inclusion of the " + "additionally one can pass metadata to the sidecar via inclusion of the " "--kwargs flag or" "the --metadata-path flag. If both are included the --kwargs flag will " "override any" @@ -209,7 +209,7 @@ def cli(): into the output from ecatpet2bids. Additional arguments/fields are passed via the kwargs flag in key value pairs. -example 1 (Passing PET metadat via the --kwargs argument): +example 1 (Passing PET metadata via the --kwargs argument): # Note `#` denotes a comment diff --git a/pypet2bids/pypet2bids/helper_functions.py b/pypet2bids/pypet2bids/helper_functions.py index 420da04..5f4cc0b 100644 --- a/pypet2bids/pypet2bids/helper_functions.py +++ b/pypet2bids/pypet2bids/helper_functions.py @@ -1154,3 +1154,37 @@ def first_middle_last_frames_to_text( delimiter="\t", fmt="%s", ) + +def reorder_isotope(isotope: str) -> str: + """ + Reorders the isotope string to be in the format of "isotope""element name" + :param isotope: isotope string + :type isotope: str + :return: reordered isotope string + :rtype: str + """ + # remove all non-alphanumeric characters from isotope + isotope = re.findall(r"[a-zA-Z0-9]+", isotope) + # combine all elements in isotope into one string + isotope = "".join(isotope) + # collect the isotope number from the isotope string + isotope_num = re.findall(r"\d+", isotope) + # collect the element name from the isotope string + element_name = re.findall(r"[a-zA-Z]+", isotope) + + # capitalize the first letter of the element name if the element name's length is <= 2 + if 1 < len(element_name[0]) <= 2: + e = element_name[0][0].capitalize() + if len(element_name[0]) == 2: + e += element_name[0][1].lower() + elif len(element_name[0]) == 1: + e = element_name[0].capitalize() + + # special case for 52mMn + if "".join(element_name).lower() == "mmn" or "".join(element_name).lower() == "mnm": + e = "mMn" + + # reorder to put the number before the element name + isotope = f"{isotope_num[0]}{e}" + + return isotope diff --git a/pypet2bids/pyproject.toml b/pypet2bids/pyproject.toml index f7117d9..67cf45d 100644 --- a/pypet2bids/pyproject.toml +++ b/pypet2bids/pyproject.toml @@ -26,7 +26,7 @@ pydicom = "^2.2.2" openpyxl = "^3.0.9" xlrd = "^2.0.1" json-maj = "^0.0.8" -pandas = "^1.4.4" +pandas = ">=1.4.4" pyxlsb = "^1.0.9" joblib = "^1.2.0" toml = ">=0.10.2" diff --git a/pypet2bids/tests/test_helper_functions.py b/pypet2bids/tests/test_helper_functions.py index 52ba136..5a2d39a 100644 --- a/pypet2bids/tests/test_helper_functions.py +++ b/pypet2bids/tests/test_helper_functions.py @@ -343,5 +343,20 @@ def test_collect_pet_spreadsheets(): assert len(pet_spreadsheets) == 3 +def test_reorder_isotope(): + # tests whether the isotope is reordered correctly with the numerical part appearing before the string part + # and if any non-alphanumeric characters are present + isotopes = { + "11C": ["C11", "^11^C", "C-11", "11-C", "11C", "c11", "c-11", "11c"], + "18F": ["F18", "^18^F", "F-18", "18-F", "18F"], + "68Ga": ["Ga68", "^68^Ga", "Ga-68", "68-Ga", "68Ga"], + "52mMn": ["Mn52m", "Mn-52m", "52m-Mn", "52mMn"] + } + + for isotope, isotope_variants in isotopes.items(): + for isotope_variant in isotope_variants: + assert helper_functions.reorder_isotope(isotope_variant) == isotope + + if __name__ == "__main__": unittest.main() diff --git a/spreadsheet_conversion/blood/pmod/convert_pmod_to_blood.m b/spreadsheet_conversion/blood/pmod/convert_pmod_to_blood.m index d58d8f5..d51353c 100644 --- a/spreadsheet_conversion/blood/pmod/convert_pmod_to_blood.m +++ b/spreadsheet_conversion/blood/pmod/convert_pmod_to_blood.m @@ -79,7 +79,7 @@ function convert_pmod_to_blood(varargin) %% deal with input file if nargin == 0 - [filenames, pathnames] = uigetfile({'*.bld','speadsheet';'*.txt','text'}, 'Pick the pmod files (N=2 or 3)', 'multiselect','on'); + [filenames, pathnames] = uigetfile({'*.bld','spreadsheet';'*.txt','text'}, 'Pick the pmod files (N=2 or 3)', 'multiselect','on'); if isequal(filenames, 0) || isequal(pathnames, 0) disp('Selection cancelled'); return diff --git a/spreadsheet_conversion/many_subjects_sheet/README.mkd b/spreadsheet_conversion/many_subjects_sheet/README.mkd index 51645f5..efa5eec 100644 --- a/spreadsheet_conversion/many_subjects_sheet/README.mkd +++ b/spreadsheet_conversion/many_subjects_sheet/README.mkd @@ -30,4 +30,4 @@ From the 2nd row, values are entered. When multiple values are required, these a # format -While the current templates and examples are in .xlsx (microsoft excel), other speadsheet formats can be used. \ No newline at end of file +While the current templates and examples are in .xlsx (microsoft excel), other spreadsheet formats can be used. \ No newline at end of file diff --git a/spreadsheet_conversion/single_subject_sheet/README.mkd b/spreadsheet_conversion/single_subject_sheet/README.mkd index 11681cd..3c6647d 100644 --- a/spreadsheet_conversion/single_subject_sheet/README.mkd +++ b/spreadsheet_conversion/single_subject_sheet/README.mkd @@ -10,4 +10,4 @@ From the 2nd row, values are entered. When multiple values are required, these a # format -While the current template and example are in .xlsx (microsoft excel), other speadsheet formats can be used. \ No newline at end of file +While the current template and example are in .xlsx (microsoft excel), other spreadsheet formats can be used. \ No newline at end of file From 1418a3f0de9b52e77487339fe6c614d32fb920b7 Mon Sep 17 00:00:00 2001 From: Anthony Galassi <28850131+bendhouseart@users.noreply.github.com> Date: Thu, 12 Sep 2024 12:25:19 -0400 Subject: [PATCH 19/27] update url for matlab --- matlab/telemetry.m | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/matlab/telemetry.m b/matlab/telemetry.m index baab2d0..8be466b 100644 --- a/matlab/telemetry.m +++ b/matlab/telemetry.m @@ -18,7 +18,7 @@ function telemetry(telemetry_data, input_path, output_path) telemetry_data.TotalInputFileSize = input_file_count.TotalInputFileSize; end - url = 'http://52.87.154.236/telemetry/'; + url = 'http://openneuropet.org/pet2bids/'; options = weboptions('MediaType', 'application/json'); response = webwrite(url, telemetry_data, options); From a9291cf2d54d1a98ce960a07732e1f2f57506d3a Mon Sep 17 00:00:00 2001 From: Anthony Galassi <28850131+bendhouseart@users.noreply.github.com> Date: Thu, 12 Sep 2024 13:34:34 -0400 Subject: [PATCH 20/27] fix spelling errors --- matlab/dcm2niix4pet.m | 2 +- pypet2bids/pypet2bids/telemetry.py | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/matlab/dcm2niix4pet.m b/matlab/dcm2niix4pet.m index 08e319d..355b815 100644 --- a/matlab/dcm2niix4pet.m +++ b/matlab/dcm2niix4pet.m @@ -69,7 +69,7 @@ function dcm2niix4pet(FolderList,MetaList,varargin) version = regexp(version_output_string, 'v[0-9].[0-9].{8}[0-9]', 'match'); -% initalize telemetry data fror later uploading +% initialize telemetry data fror later uploading telemetry_data = {}; dcm2niix_data = {}; dcm2niix_data.version = version(1); diff --git a/pypet2bids/pypet2bids/telemetry.py b/pypet2bids/pypet2bids/telemetry.py index 2233088..f83d92d 100644 --- a/pypet2bids/pypet2bids/telemetry.py +++ b/pypet2bids/pypet2bids/telemetry.py @@ -122,16 +122,16 @@ def count_input_files(input_file_path: Union[str, pathlib.Path]): def count_output_files(output_file_path: Union[str, pathlib.Path]): """ - Count the number of output files in the output file path. This can be usefull + Count the number of output files in the output file path. This can be useful in determining whether any additional files were created during the conversion process. However, this is only useful if the conversion process initially takes place from within a temporary directory. # TODO check the last modified date of the files to determine if they were created during - # TODO the conversion process. That should make this usefull in all cases. + # TODO the conversion process. That should make this useful in all cases. :param output_file_path: location of the output files :type output_file_path: Union[str, pathlib.Path] - :return: The number of output files and their size and spefically the number of nifti files and + :return: The number of output files and their size and specifically the number of nifti files and their size :rtype: dict """ From 0ab848fce63616b1cfbc31fd676cd41697c14252 Mon Sep 17 00:00:00 2001 From: Anthony Galassi <28850131+bendhouseart@users.noreply.github.com> Date: Thu, 12 Sep 2024 17:11:28 -0400 Subject: [PATCH 21/27] run black and bump node version in actions --- .github/workflows/phantoms.yaml | 2 +- pypet2bids/pypet2bids/helper_functions.py | 1 + pypet2bids/tests/test_helper_functions.py | 2 +- 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/.github/workflows/phantoms.yaml b/.github/workflows/phantoms.yaml index 8e63166..a84dc27 100644 --- a/.github/workflows/phantoms.yaml +++ b/.github/workflows/phantoms.yaml @@ -106,7 +106,7 @@ jobs: dcm2niix4pet -h - name: Set Up Node - uses: actions/setup-node@v3 + uses: actions/setup-node@v4 - name: Install BIDS Validator run: npm install -g bids-validator diff --git a/pypet2bids/pypet2bids/helper_functions.py b/pypet2bids/pypet2bids/helper_functions.py index 5f4cc0b..4edb0a3 100644 --- a/pypet2bids/pypet2bids/helper_functions.py +++ b/pypet2bids/pypet2bids/helper_functions.py @@ -1155,6 +1155,7 @@ def first_middle_last_frames_to_text( fmt="%s", ) + def reorder_isotope(isotope: str) -> str: """ Reorders the isotope string to be in the format of "isotope""element name" diff --git a/pypet2bids/tests/test_helper_functions.py b/pypet2bids/tests/test_helper_functions.py index 5a2d39a..8c9f177 100644 --- a/pypet2bids/tests/test_helper_functions.py +++ b/pypet2bids/tests/test_helper_functions.py @@ -350,7 +350,7 @@ def test_reorder_isotope(): "11C": ["C11", "^11^C", "C-11", "11-C", "11C", "c11", "c-11", "11c"], "18F": ["F18", "^18^F", "F-18", "18-F", "18F"], "68Ga": ["Ga68", "^68^Ga", "Ga-68", "68-Ga", "68Ga"], - "52mMn": ["Mn52m", "Mn-52m", "52m-Mn", "52mMn"] + "52mMn": ["Mn52m", "Mn-52m", "52m-Mn", "52mMn"], } for isotope, isotope_variants in isotopes.items(): From 7a0c7d72c78fd122d4e87943a44d5b75f6b35408 Mon Sep 17 00:00:00 2001 From: Anthony Galassi <28850131+bendhouseart@users.noreply.github.com> Date: Thu, 12 Sep 2024 17:16:58 -0400 Subject: [PATCH 22/27] roll back validator version --- .github/workflows/phantoms.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/phantoms.yaml b/.github/workflows/phantoms.yaml index a84dc27..79211a9 100644 --- a/.github/workflows/phantoms.yaml +++ b/.github/workflows/phantoms.yaml @@ -109,7 +109,7 @@ jobs: uses: actions/setup-node@v4 - name: Install BIDS Validator - run: npm install -g bids-validator + run: npm install -g bids-validator@1.14.6 - name: Collect Phantoms if: ${{ steps.cache-phantoms.outputs.cache-hit != 'true' }} && ${{ !env.ACT }} From d901bc0b1e5a42b82b1a32b1a5d4102d6283af14 Mon Sep 17 00:00:00 2001 From: Anthony Galassi <28850131+bendhouseart@users.noreply.github.com> Date: Thu, 12 Sep 2024 17:22:17 -0400 Subject: [PATCH 23/27] fixed python not validating, now it's matlab... --- .github/workflows/phantoms.yaml | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/.github/workflows/phantoms.yaml b/.github/workflows/phantoms.yaml index 79211a9..f657665 100644 --- a/.github/workflows/phantoms.yaml +++ b/.github/workflows/phantoms.yaml @@ -67,12 +67,6 @@ jobs: brew install dcm2niix fi - - name: Debug - uses: mxschmitt/action-tmate@v3 - if: ${{ github.event_name == 'workflow_dispatch' && inputs.debug_enabled }} - timeout-minutes: 15 - with: - limit-access-to-actor: true - name: Check dcm2niix is installed and on path if: runner.os != 'Windows' @@ -170,6 +164,13 @@ jobs: run: | bids-validator OpenNeuroPET-Phantoms/python + - name: Debug + uses: mxschmitt/action-tmate@v3 + if: ${{ github.event_name == 'workflow_dispatch' && inputs.debug_enabled }} + timeout-minutes: 15 + with: + limit-access-to-actor: true + - name: Validate Matlab Conversion run: | bids-validator OpenNeuroPET-Phantoms/matlab From 73f3ac100204595160b0a655dc9141c001e8dc71 Mon Sep 17 00:00:00 2001 From: Anthony Galassi <28850131+bendhouseart@users.noreply.github.com> Date: Fri, 13 Sep 2024 09:33:37 -0400 Subject: [PATCH 24/27] Update matlab/dcm2niix4pet.m --- matlab/dcm2niix4pet.m | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/matlab/dcm2niix4pet.m b/matlab/dcm2niix4pet.m index 355b815..aee527d 100644 --- a/matlab/dcm2niix4pet.m +++ b/matlab/dcm2niix4pet.m @@ -30,7 +30,7 @@ function dcm2niix4pet(FolderList,MetaList,varargin) % - *w* = 2; % write behavior for name conflicts (0,1,2, default 2: 0=skip duplicates, 1=overwrite, 2=add suffix) % - *x* = 'n'; % crop 3D acquisitions (y/n/i, default n, use 'i'gnore to neither crop nor rotate 3D acquisitions) % - *z* = 'n'; % gz compress images (y/o/i/n/3, default y) [y=pigz, o=optimal pigz, i=internal:miniz, n=no, 3=no,3D] -% :param notrack: boolean to Opt-out of sending tracking information of this run to the PET2BIDS developers. This information helps to improve PET2BIDS and provides an indicator of real world usage crucial for obtaining funding." +% - *notrack* Opt-out of sending tracking information of this run to the PET2BIDS developers. This information helps to improve PET2BIDS and provides an indicator of real world usage crucial for obtaining funding." % % .. code-block:: % From 4fa18a5165f945c5de3925331fdfb60010692d14 Mon Sep 17 00:00:00 2001 From: Anthony Galassi <28850131+bendhouseart@users.noreply.github.com> Date: Fri, 13 Sep 2024 09:34:13 -0400 Subject: [PATCH 25/27] Apply suggestions from code review --- matlab/dcm2niix4pet.m | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/matlab/dcm2niix4pet.m b/matlab/dcm2niix4pet.m index aee527d..c85de28 100644 --- a/matlab/dcm2niix4pet.m +++ b/matlab/dcm2niix4pet.m @@ -30,7 +30,7 @@ function dcm2niix4pet(FolderList,MetaList,varargin) % - *w* = 2; % write behavior for name conflicts (0,1,2, default 2: 0=skip duplicates, 1=overwrite, 2=add suffix) % - *x* = 'n'; % crop 3D acquisitions (y/n/i, default n, use 'i'gnore to neither crop nor rotate 3D acquisitions) % - *z* = 'n'; % gz compress images (y/o/i/n/3, default y) [y=pigz, o=optimal pigz, i=internal:miniz, n=no, 3=no,3D] -% - *notrack* Opt-out of sending tracking information of this run to the PET2BIDS developers. This information helps to improve PET2BIDS and provides an indicator of real world usage crucial for obtaining funding." +% - *notrack* Opt-out of sending tracking information of this run to the PET2BIDS developers. This information helps to improve PET2BIDS and provides an indicator of real world usage crucial for obtaining funding." % % .. code-block:: % From d270d956198e924f2024f34999e4e7796e174248 Mon Sep 17 00:00:00 2001 From: Anthony Galassi <28850131+bendhouseart@users.noreply.github.com> Date: Fri, 13 Sep 2024 09:49:20 -0400 Subject: [PATCH 26/27] fixed bug w/ dcm2niix args --- matlab/dcm2niix4pet.m | 4 +--- matlab/telemetry.m | 9 ++++++--- scripts/matlab_conversions.m | 2 +- 3 files changed, 8 insertions(+), 7 deletions(-) diff --git a/matlab/dcm2niix4pet.m b/matlab/dcm2niix4pet.m index 355b815..b5fa951 100644 --- a/matlab/dcm2niix4pet.m +++ b/matlab/dcm2niix4pet.m @@ -75,7 +75,7 @@ function dcm2niix4pet(FolderList,MetaList,varargin) dcm2niix_data.version = version(1); dcm2niix_data.returncode = 0; telemetry_data.dcm2niix = dcm2niix_data; -telemetry_data.description = "Matlab_dcm2niix4pet.m" +telemetry_data.description = "Matlab_dcm2niix4pet.m"; if length(version) >= 1 version_date = version{1}(6:end); @@ -222,8 +222,6 @@ function dcm2niix4pet(FolderList,MetaList,varargin) outputdir = varargin{var+1}; elseif strcmpi(varargin{var},'notrack') setenv('TELEMETRY_ENABLED', 'False') - else - error('unknown option %s',varargin{var}) end end diff --git a/matlab/telemetry.m b/matlab/telemetry.m index 8be466b..a17f270 100644 --- a/matlab/telemetry.m +++ b/matlab/telemetry.m @@ -19,9 +19,12 @@ function telemetry(telemetry_data, input_path, output_path) end url = 'http://openneuropet.org/pet2bids/'; - options = weboptions('MediaType', 'application/json'); - response = webwrite(url, telemetry_data, options); - + options = weboptions('MediaType', 'application/json', 'Timeout', 5); + try + response = webwrite(url, telemetry_data, options); + catch ME + % do nothing + end else % don't do anything end diff --git a/scripts/matlab_conversions.m b/scripts/matlab_conversions.m index 76c8c14..12703d8 100644 --- a/scripts/matlab_conversions.m +++ b/scripts/matlab_conversions.m @@ -31,7 +31,7 @@ [status, results] = system('which dcm2niix'); if status == 0 dcm2niix_path = results; - system([dcm2niix_path, ' -h']) + system(dcm2niix_path, ' -h') else print_me = ['This script expects to find dcm2niix at /opt/homebrew/bin, for a default brew installed dcm2niix.']; disp(print_me) From 5b80e5ab607bfcfa48ff871f85e7174b658be22c Mon Sep 17 00:00:00 2001 From: Anthony Galassi <28850131+bendhouseart@users.noreply.github.com> Date: Fri, 13 Sep 2024 11:05:46 -0400 Subject: [PATCH 27/27] disable telemetry if running in CI --- matlab/telemetry.m | 5 ++++- pypet2bids/pypet2bids/telemetry.py | 2 +- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/matlab/telemetry.m b/matlab/telemetry.m index a17f270..650837c 100644 --- a/matlab/telemetry.m +++ b/matlab/telemetry.m @@ -49,8 +49,11 @@ function telemetry(telemetry_data, input_path, output_path) end disable_telemetry = strcmpi(getenv("TELEMETRY_ENABLED"), 'false'); + + % if running in CI don't run telemetry + running_in_ci = strcmpi(getenv("CI"), 'true'); - if disable_telemetry | disable_telemetry_env + if disable_telemetry | disable_telemetry_env | running_in_ci e = false; else e = true; diff --git a/pypet2bids/pypet2bids/telemetry.py b/pypet2bids/pypet2bids/telemetry.py index f83d92d..6ae54a9 100644 --- a/pypet2bids/pypet2bids/telemetry.py +++ b/pypet2bids/pypet2bids/telemetry.py @@ -53,7 +53,7 @@ def telemetry_enabled(config_path=None): load_dotenv(dotenv_path=config_file) # check to see if telemetry is disabled - if os.getenv("PET2BIDS_TELEMETRY_ENABLED", "").lower() == "false": + if os.getenv("PET2BIDS_TELEMETRY_ENABLED", "").lower() == "false" or os.getenv("CI", "false") == "true": return False else: return True