Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

263 telementry add tracking of code usage #316

Merged
merged 30 commits into from
Sep 13, 2024
Merged
Show file tree
Hide file tree
Changes from 26 commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
c6c6df5
added telemetry call
bendhouseart Jul 18, 2024
5a84ebb
added file count to telemetery tracking for dcm2niix
bendhouseart Jul 19, 2024
6b53ba4
added python functionality
bendhouseart Jul 24, 2024
b3bf9af
matlab is being weird and not finding dcm2niix on path
bendhouseart Aug 1, 2024
8550942
added telemetry to matlab converters
bendhouseart Aug 2, 2024
272780a
fixe typo, bump version
bendhouseart Aug 2, 2024
62791ec
added option to opt out of telemetry
bendhouseart Aug 7, 2024
e60aa57
added cli flag and environment variable disabling of telemetry
bendhouseart Aug 12, 2024
ff3645d
updating matlab to suit passing of --notrack to conversion functions
bendhouseart Aug 12, 2024
400fec2
update tracking on matlab to set env to not track if provided via arg…
bendhouseart Aug 12, 2024
5903752
finished setting up matlab version
bendhouseart Aug 12, 2024
4b4928a
fix error with loading config
bendhouseart Aug 14, 2024
9bc9e56
automated message was more errofr that it's worth
bendhouseart Aug 14, 2024
b360317
formatted files
bendhouseart Aug 14, 2024
878d4ac
add try catch for .env file check on telemetry.m
bendhouseart Aug 15, 2024
29e32a4
update poetry lock file
bendhouseart Aug 16, 2024
349ef31
bump version, update url for telemetry
bendhouseart Sep 12, 2024
b3d4127
319 standardize radiochemistry metadata case order (#321)
bendhouseart Sep 12, 2024
1418a3f
update url for matlab
bendhouseart Sep 12, 2024
0a7b744
Merge branch '263-telementry-add-tracking-of-code-usage' of github.co…
bendhouseart Sep 12, 2024
32f52d5
Merge branch 'main' of github.com:openneuropet/PET2BIDS into 263-tele…
bendhouseart Sep 12, 2024
a9291cf
fix spelling errors
bendhouseart Sep 12, 2024
0ab848f
run black and bump node version in actions
bendhouseart Sep 12, 2024
7a0c7d7
roll back validator version
bendhouseart Sep 12, 2024
d901bc0
fixed python not validating, now it's matlab...
bendhouseart Sep 12, 2024
73f3ac1
Update matlab/dcm2niix4pet.m
bendhouseart Sep 13, 2024
4fa18a5
Apply suggestions from code review
bendhouseart Sep 13, 2024
d270d95
fixed bug w/ dcm2niix args
bendhouseart Sep 13, 2024
78a3bcf
Merge branch '263-telementry-add-tracking-of-code-usage' of github.co…
bendhouseart Sep 13, 2024
5b80e5a
disable telemetry if running in CI
bendhouseart Sep 13, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 9 additions & 8 deletions .github/workflows/phantoms.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -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'
Expand Down Expand Up @@ -106,10 +100,10 @@ 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
run: npm install -g bids-validator@1.14.6

- name: Collect Phantoms
if: ${{ steps.cache-phantoms.outputs.cache-hit != 'true' }} && ${{ !env.ACT }}
Expand Down Expand Up @@ -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
35 changes: 32 additions & 3 deletions matlab/dcm2niix4pet.m
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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 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."
bendhouseart marked this conversation as resolved.
Show resolved Hide resolved
%
% .. code-block::
%
Expand All @@ -50,7 +51,7 @@ 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)
Expand All @@ -63,9 +64,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'];

[status, version_output_string] = system(version_cmd);
version = regexp(version_output_string, 'v[0-9].[0-9].{8}[0-9]', 'match');


% initialize telemetry data fror later uploading
telemetry_data = {};
dcm2niix_data = {};
dcm2niix_data.version = version(1);
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);
version_date = datetime(version_date, 'InputFormat', 'yyyyMMdd');
Expand Down Expand Up @@ -209,7 +220,12 @@ function dcm2niix4pet(FolderList,MetaList,varargin)
end
elseif strcmpi(varargin{var},'o')
outputdir = varargin{var+1};
elseif strcmpi(varargin{var},'notrack')
setenv('TELEMETRY_ENABLED', 'False')
else
error('unknown option %s',varargin{var})
end

end

if isempty(outputdir)
Expand All @@ -225,6 +241,8 @@ function dcm2niix4pet(FolderList,MetaList,varargin)
end
end



%% convert
% ----------
for folder = 1:size(FolderList,1)
Expand All @@ -249,10 +267,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 :-(
Expand Down Expand Up @@ -318,4 +342,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
27 changes: 22 additions & 5 deletions matlab/ecat2nii.m
Original file line number Diff line number Diff line change
Expand Up @@ -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
% ------------

Expand Down Expand Up @@ -110,6 +114,8 @@
gz = varargin{v+1};
elseif strcmpi(varargin{v},'savemat')
savemat = varargin{v+1};
elseif strcmpi(varargin{v},'notrack')
setenv('TELEMETRY_ENABLED', 'False')
end
end

Expand All @@ -131,14 +137,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
Expand Down Expand Up @@ -180,6 +190,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');
Expand All @@ -206,8 +219,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');
Expand Down Expand Up @@ -489,8 +500,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

Expand Down
87 changes: 87 additions & 0 deletions matlab/telemetry.m
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
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://openneuropet.org/pet2bids/';
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();
% check environment too before loading the config file
if isfield(environment, 'TELEMETRY_ENABLED')
disable_telemetry_env = strcmpi(getenv("TELEMETRY_ENABLED"), 'false');
else
disable_telemetry_env = false;
end

home_dir = environment("HOME");
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
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
76 changes: 38 additions & 38 deletions metadata/PET_Radionuclide.mkd
Original file line number Diff line number Diff line change
Expand Up @@ -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 |
Loading
Loading