Routine that outputs PET scanner metadata following BIDS. The metadata generated here are passed along imaging data to the converters, ecat2nii.m or dcm2niix4pet.m allowing to produce a .nii file with a BIDS compliant json file. :param Default: (aquisition and reconstruction parameters) can be stored in a *_parameters.txt seating on disk next to this function or passed as argument in. Replace * by the name of your scanner - for now we tested ‘SiemensBiograph’, ‘SiemensHRRT’, ‘GEAdvance’, ‘PhillipsVereos’, ‘PhillipsIngenuityPETMR’,’PhillipsIngenuityPETCT’. (see templates, as some info can be recovered from ecat or dcm - ie not all info is necessarily needed) :param inputs: a series of key/value pairs are expected :returns metadata: a structure with BIDS fields filled (such structure is ready to be writen as json file using e.g. the bids matlab jsonwrite function, typically associated with the _pet.nii file) :format: metadata = get_pet_metadata(key,value) .. note:: Mandatory inputs are as follows: - *Scanner name of scanner, map to a parameters.txt file e.g. ‘Scanner’, ‘SiemensBiograph’ - *TimeZero when was the tracer injected e.g. ‘TimeZero’,’11:05:01’ - ModeOfAdministration e.g. ‘ModeOfAdministration’, ‘bolus’ - TracerName which tracer was used e.g. ‘TracerName’,’DASB’ - TracerRadionuclide which nuclide was used e.g. ‘TracerRadionuclide’,’C11’ + at least 2 of those key/value arguments to infer others: - InjectedRadioactivity value in MBq e.g. ‘InjectedRadioactivity’, 605.3220 - InjectedMass Value in ug e.g. ‘InjectedMass’, 1.5934 - MolarActivity value in GBq/umol e.g. ‘MolarActivity’, 107.66 - MolecularWeight value in g/mol e.g. ‘MolecularWeight’, 15.02 - SpecificRadioactivity in Bq/g or Bq/mol e.g. ‘SpecificRadioactivity’, 3.7989e+14 Here is an example of such defaults, used at NRU for our SiemensBiograph_parameters.txt .. code-block:: InstitutionName = ‘Rigshospitalet, NRU, DK’; BodyPart = ‘Phantom’; AcquisitionMode = ‘list mode’; ImageDecayCorrected = ‘true’; ImageDecayCorrectionTime = 0; ReconFilterType = ‘none’; ReconFilterSize = 0; AttenuationCorrection = ‘10-min transmission scan’; FrameDuration = 1200; FrameTimesStart = 0; .. note:: TimeZero also can be [] or ‘ScanStart’ indicating that the scanning time should be used as TimeZero. If TimeZero is not the scan time, we strongly advice to input ScanStart and InjectionStart making sure timing is correct .. note:: OPTIONAL INPUTS ARE ALL OTHER BIDS FIELDS Example .. code-block:: meta = get_pet_metadata(‘Scanner’,’SiemensBiograph’,’TimeZero’,’ScanStart’,… ‘TracerName’,’CB36’,’TracerRadionuclide’,’C11’, … ‘ModeOfAdministration’,’infusion’,’SpecificRadioactivity’, … 605.3220,’InjectedMass’, 1.5934,’MolarActivity’, 107.66); –> will issue warnings without a SiemensBiographparameters.txt next to this function meta = get_pet_metadata(‘Scanner’,’SiemensBiograph’,’TimeZero’,’ScanStart’,… ‘TracerName’,’CB36’,’TracerRadionuclide’,’C11’, ‘ModeOfAdministration’,… ‘infusion’,’SpecificRadioactivity’, 605.3220,’InjectedMass’, 1.5934,… ‘MolarActivity’, 107.66, ‘InstitutionName’,’Rigshospitalet, NRU, DK’,… ‘AcquisitionMode’,’list mode’,’ImageDecayCorrected’,’true’,… ‘ImageDecayCorrectionTime’ ,0,’ReconMethodName’,’OP-OSEM’,… ‘ReconMethodParameterLabels’,{‘subsets’,’iterations’},… ‘ReconMethodParameterUnits’,{‘none’,’none’}, … ‘ReconMethodParameterValues’,[21 3], ‘ReconFilterType’,’XYZGAUSSIAN’,… ‘ReconFilterSize’,2, ‘AttenuationCorrection’,’MR-based attenuation correction’); –> works without txt file because all arguments are passed | Neurobiology Research Unit, Rigshospitalet | Martin Nørgaard & Cyril Pernet - 2021 | Copyright Open NeuroPET team

matlab.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 comes to metadata! DICOM values to be used in the json will be ignored, always using the meta data provided - BUT DICOM values are checked and the code tells you if there is inconsistency between your inputs and what DICOM says. :format: - fileout = dcm2bids4pet(FolderList,MetaList) - fileout = dcm2bids4pet(FolderList,MetaList,options) :param FolderList: Cell array of char strings with filenames and paths :param MetaList: Cell array of structures for metadata :param options: - 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 - gz = 6; % -1..-9 : gz compression level (1=fastest..9=smallest, default 6) - a = ‘n’; % -a : adjacent DICOMs (images from same series always in same folder) for faster conversion (n/y, default n) - ba = ‘y’; % -ba : anonymize BIDS (y/n, default y) - d = 5; % directory search depth. Convert DICOMs in sub-folders of in_folder? (0..9, default 5) - f = ‘%f_%p_%t_%s’; % filename (%a=antenna (coil) name, %b=basename, %c=comments, %d=description, %e=echo number, %f=folder name, %g=accession number, %i=ID of patient, %j=seriesInstanceUID, %k=studyInstanceUID, %m=manufacturer, %n=name of patient, %o=mediaObjectInstanceUID, %p=protocol, %r=instance number, %s=series number, %t=time, %u=acquisition number, %v=vendor, %x=study ID; %z=sequence name; default ‘%f_%p_%t_%s’) - g = ‘n’; % generate defaults file (y/n/o/i [o=only: reset and write defaults; i=ignore: reset defaults], default n) - i = ‘n’; % ignore derived, localizer and 2D images (y/n, default n) - l = ‘n’; % losslessly scale 16-bit integers to use dynamic range (y/n/o [yes=scale, no=no, but uint16->int16, o=original], default n) - m = ‘2’; % merge 2D slices from same series regardless of echo, exposure, etc. (n/y or 0/1/2, default 2) [no, yes, auto] - 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) - 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] .. code-block:: Example meta = get_pet_metadata(‘Scanner’,’SiemensBiograph’,’TimeZero’,’ScanStart’,’TracerName’,’CB36’,’TracerRadionuclide’,’C11’, … ‘ModeOfAdministration’,’infusion’,’SpecificRadioactivity’, 605.3220,’InjectedMass’, 1.5934,’MolarActivity’, 107.66); dcm2niix4pet(folder1,meta,’gz’,9,’o’,’mynewfolder’,’v’,1); % change dcm2nii default dcm2niix4pet({folder1,folder2,folder3},{meta}); % use the same PET meta for all subjects dcm2niix4pet({folder1,folder2,folder3},{meta1,meta2,meta3}); % each subject has specific metadata info.. note:: See also get_pet_metadata.m to generate the metadata structure updatejsonpetfile to see how the json file gets updated and checked agains DICOM tags | Cyril Pernet 2022 | Copyright Open NeuroPET team

matlab.ecat2nii(FileListIn, MetaList, varargin)

Converts ECAT 7 image file from hrrt pet scanner (ecat format) to nifti image files + json :format: - FileListOut = ecat2nii(FileListIn,MetaList) - FileListOut = ecat2nii(FileListIn,MetaList,options) :param FileListIn: a name or a Cell array of characters with paths and filenames :param MetaList: a structure or Cell array of structures for metadata (a single structure can be use other many FileListIn - see examples) options are name/value pairs :param FileListOut: a name or cell array of characters with filenames (with path if the path out is different) :param sifout: is true or false (default) to output a sif file, default = false, 0/1 to indicate SIF is a simple ascii file that contains the PET frame start and end times, and the numbers of observed events during each PET time frame. :param gz: is true (default) or false to output .nii.gz or .nii :param savemat: is true or false (default) to save the ecat data as .mat :returns FileListOut: is the name or a cell array of names of the nifti files created (should be the same as FileListOut entered as option with the added proper extension .nii or .nii.gz) .. code-block:: Example Meta = get_pet_metadata(‘Scanner’,’SiemensHRRT’,’TimeZero’,’ScanStart’,’TracerName’,’DASB’,’TracerRadionuclide’,’C11’, … ‘ModeOfAdministration’,’bolus’,’InjectedRadioactivity’, 605.3220,’InjectedMass’, 1.5934,’MolarActivity’, 107.66) FileListOut = ecat2nii(EcatFile,Meta,’FileListOut’,ConvertedRenamedFile1); FileListOut = ecat2nii({EcatFile1,EcatFile2},Meta,’gz’,false,’sifout’,true); FileListOut = ecat2nii({EcatFile1,EcatFile2},{Meta1,Meta2},’FileListOut’,{ConvertedRenamedFile1,ConvertedRenamedFile2}));`` .. note:: Uses: readECAT7.m (Raymond Muzic, 2002) jsonwrite.m (Guillaume Flandin, 2020) nii_tool.m (Xiangrui Li, 2016) See also get_pet_metadata.m to generate the metadata structure | Claus Svarer, Martin Nørgaard, Chris Rorden & Cyril Pernet - 2021 | Copyright Open NeuroPET team


Routine to check input consistency, possibly generate new ones from PET BIDS metadata - this only makes sense if you respect the input units as indicated :format: dataout = check_metaradioinputs(varargin) .. note:: arguments in are provided via the following params (key/value pairs) e.g. - ‘InjectedRadioctivity’,81.24 - ‘SpecificRadioactivity’,1.3019e+04 :param InjectedRadioactivity: in MBq :param InjectedMass: in ug :param SpecificRadioactivity: in Bq/g or MBq/ug :param MolarActivity: in GBq/umol :param MolecularWeight: in g/mol :return: a structure with the original and updated field, including expected units | Claus Svarer, Martin Nørgaard & Cyril Pernet - 2021 | Copyright Open NeuroPET team


from the dicom value of the PET reconstruction method, it returns the actual name of the method and the number of iterations and subsets if any :format: - [method,iteration,subset] = get_recon_method(headervalue) :param headervalue: the name in the ecat or dicom field of the reconstrusction method :returns method: the full name of the reconstrucrtion method or empty if no match found :returns iteration: the number of iterations or ‘none’ :returns subset: the number of subsets or ‘none’ | Cyril Pernet 2022 | Copyright Open NeuroPET team


routine that take a structure with nested subfileds and output all fields in a flat structure :format: - structout = flattenstruct(structin) :param structin: a structure with nested fields :returns structout: a flat sructure with all the fields .. note:: there is an exception handling for the fieldname ‘Item_1’ which is a DICOM name used by manufacturers to store various items | Cyril Pernet Novembre 2021 | Copyright Open NeuroPET team

matlab.readECAT7(fs, matrix, varargin)

Read the main header, subheaders, and image/sinogram data from ECAT v 7.x *.v, *.i, *.S, and *.a files. :format: [mh,sh,data] = readECAT(fs, [matrix], [‘Calibrated’, ‘on’]) :param fs: (optional) file specification (name/path) of file to read. if file specification is not given, then user is prompted to select a file. :param matrix: (optional) vector of matrix numbers to read. Default = all matrices in file. :param Calibrated’: ‘on’ or ‘off’, if on it calibrates to pixel values in units given in mh.data_units. When ‘Calibrated’ is ‘on’, pixel values are stored as doubles; otherwise, pixels are int16. Calibration is achieved by multiplication of pixels by ecat_calibration_factor (in mh) and the scale_factor (in sh). The default is uncalibrated in which case pixels are int16. :returns: - mh - main header - sh - cell array of subheaders. sh{i} is subheader for matrix(i). - data - cell array containing pixel data. data{i} is a [rows, cols, planes] or [proj, views, planes] array with the data of matrix i. The data are stored in the file as 2 byte signed integers. .. note:: To convert data from cell array of 3D arrays to a 4D array: d=double(cat(4,data{:})); This could be helpful to convert a time-sequence of image volumes to something that can be more easily manipulated. This should work for the entire line of ECAT scanners running 7.x of the software. Original version written by BT Christian, 12/10/98 Overhaul by RF Muzic, 20000726 Revised by RF Muzic, 20010916 Revised by RF Muzic, 20011221 add support for 3D sinogram files (prev only images supported) Revised by RF Muzic, 20021017 generalize support from multiple frames to multiple matrices. The distinction is that a matrix could correspond to different bed position or different frame. Revised by RF Muzic, 20021029 correct length of last fill block in image file subheader. It is actually 49 shorts (to make a 512 byte sh block) whereas CTI docs says 48. Add support for .a files. Copyright ? 2002 Raymond F. Muzic, Jr. Not intended for clinical/diagnostic use. User assumes all risk.


Serialize a JSON (JavaScript Object Notation) structure : format: - jsonwrite(filename,json,options) - S = jsonwrite(json) :param filename: the name of the JSON file to write :param json: the JSON structure :param options: - prettyPrint true or false to indent output [Default: true] - replacementStyle string to control how non-alphanumeric characters are replaced {‘underscore’,’hex’,’delete’,’nop’} [Default: ‘underscore’] - convertInfAndNaN encode NaN, Inf and -Inf as “null” [Default: true] :returns: S the serialized JSON structure (string) References: JSON Standard: jsonencode: .. note:: Guillaume Flandin $Id: spm_jsonwrite.m 8031 2020-12-10 13:37:00Z guillaume $