25 #include "TApplication.h"
41 cout <<
"NOTE : This program is an example code providing guidance regarding how to generate a PET CASToR datafile from any system datafile " << endl;
42 cout <<
" It does NOT perform any conversion by itself and must be adjusted to the conversion of any system dataset !" << endl;
45 cout <<
"Usage: castor-datafileConversionEx -ih input_datafile : (if datafile is histogram mode)" << endl;
46 cout <<
" -il input_datafile : (if datafile is list-mode)" << endl;
47 cout <<
" -o output_datafile" << endl;
48 cout <<
" -s scanner_alias "<< endl;
49 cout <<
" [-nc norm_factors_file" << endl;
50 cout <<
" [-sc scat_factors_file" << endl;
51 cout <<
" [-rc rdm_factors_file" << endl;
52 cout <<
" [-ac atn_factors_file" << endl;
53 cout <<
" [-cf calibration factor" << endl;
54 cout <<
" [-ist isotope_alias" << endl;
57 cout <<
" [-vb verbosity]" << endl;
60 cout <<
"[Main settings]:" << endl;
61 cout <<
" -ih path_to_histo_datafile : provide an input histogram datafile to convert" << endl;
62 cout <<
" -il path_to_listm_datafile : provide an input list-mode datafile to convert" << endl;
63 cout <<
" -o path_to_cstr_file.cdh : provide the path to the output file will be created inside this folder (no default)" << endl;
64 cout <<
" -s scanner_alias : provide the name of the scanner used for to acquire the original data" << endl;
65 cout <<
" : Must correspond to a .geom or .hscan file in the config/scanner repository." << endl;
67 cout <<
"[Optional settings]:" << endl;
68 cout <<
" -nc norm_factors_file : provide a file containing normalization correction factors" << endl;
69 cout <<
" -sc scat_factors_file : provide a file containing scatter correction factors" << endl;
70 cout <<
" -rc rdm_factors_file : provide a file containing random correction factors" << endl;
71 cout <<
" -ac atn_factors_file : provide a file containing attenuation correction factors" << endl;
72 cout <<
" -cf calibration factor : provide a calibration factor" << endl;
73 cout <<
" -ist isotope_alias : provide alias of the isotope used in the input datafile"<< endl;
74 cout <<
" Supported PET isotopes and their parameters are listed in config/misc/isotopes_pet"<< endl;
75 cout <<
" Other isotopes can be added in the same file"<< endl;
77 cout <<
"[Miscellaneous settings]:" << endl;
78 cout <<
" -vb : give the verbosity level, from 0 (no verbose) to above 5 (at the event level) (default: 1)." << endl;
81 cout <<
" This program is part of the CASToR release version " <<
CASTOR_VERSION <<
"." << endl;
91 int main(
int argc,
char** argv)
101 string path_to_input_file =
"";
107 string path_to_out_file =
"";
108 string path_to_data_file =
"";
109 string path_to_header_file =
"";
110 string path_to_norm_file =
"";
111 string path_to_scat_file =
"";
112 string path_to_rdm_file =
"";
113 string path_to_acf_file =
"";
114 FLTNB calib_factor = 1.;
116 string scanner_alias =
"";
117 string istp_alias =
"";
123 bool is_histogram_flag = 0;
130 for (
int i=1; i<argc; i++)
132 string option = (string)argv[i];
137 if (!path_to_input_file.empty())
139 Cerr(
"***** castor-datafileConversionEx :: the following file names have already been provided (either -ih or -il option must be used): " << endl);
140 Cout(path_to_input_file << endl);
145 if (argv[i+1] == NULL)
147 Cerr(
"***** castor-datafileConversionEx :: argument missing for option: " << option << endl);
151 path_to_input_file = (string)argv[i+1];
161 if (!path_to_input_file.empty())
163 Cerr(
"***** castor-datafileConversionEx :: the following file names have already been provided (either -ih or -il option must be used): " << endl);
164 Cout(path_to_input_file << endl);
169 if (argv[i+1] == NULL)
171 Cerr(
"***** castor-datafileConversionEx :: argument missing for option: " << option << endl);
175 path_to_input_file = (string)argv[i+1];
183 else if (option==
"-o")
185 if (argv[i+1] == NULL)
187 Cerr(
"***** castor-datafileConversionEx :: argument missing for option: " << option << endl);
191 path_to_out_file = (string)argv[i+1];
196 else if (option==
"-s")
198 if (argv[i+1] == NULL)
200 Cerr(
"***** castor-datafileConversionEx :: argument missing for option: " << option << endl);
204 scanner_alias = (string)argv[i+1];
209 else if (option==
"-nc")
211 if (argv[i+1] == NULL)
213 Cerr(
"***** castor-datafileConversionEx :: argument missing for option: " << option << endl);
217 path_to_norm_file = (string)argv[i+1];
223 else if (option==
"-sc")
225 if (argv[i+1] == NULL)
227 Cerr(
"***** castor-datafileConversionEx :: argument missing for option: " << option << endl);
231 path_to_scat_file = (string)argv[i+1];
237 else if (option==
"-rc")
239 if (argv[i+1] == NULL)
241 Cerr(
"***** castor-datafileConversionEx :: argument missing for option: " << option << endl);
245 path_to_rdm_file = (string)argv[i+1];
251 else if (option==
"-ac")
253 if (argv[i+1] == NULL)
255 Cerr(
"***** castor-datafileConversionEx :: argument missing for option: " << option << endl);
259 path_to_acf_file = (string)argv[i+1];
265 else if (option==
"-cf")
267 if (argv[i+1] == NULL)
269 Cerr(
"***** castor-datafileConversionEx :: argument missing for option: " << option << endl);
274 string val_str = (string)argv[i+1];
277 Cerr(
"***** castor-datafileConversionEx :: Exception when trying to read'" << val_str <<
" for option: " << option << endl);
285 else if (option==
"-ist")
287 if (argv[i+1] == NULL)
289 Cerr(
"***** castor-datafileConversionEx :: argument missing for option: " << option << endl);
293 istp_alias = (string)argv[i+1];
299 else if (option==
"-vb")
303 Cerr(
"***** castor-datafileConversionEx :: Argument missing for option: " << option << endl);
306 vb = atoi(argv[i+1]);
312 Cerr(
"***** castor-datafileConversionEx :: Unknown option '" << option <<
"' !" << endl);
323 if (path_to_input_file.empty() )
325 Cerr(
"***** castor-datafileConversionEx :: Please provide at least one data filename (-ih for histogram, -il for list-mode)" << endl);
326 cout <<
" -input filename : give an input datafile (no default)." << endl;
331 if (path_to_out_file.empty() )
333 Cerr(
"***** castor-datafileConversionEx :: Please provide the output file name (-o)" << endl);
338 if (scanner_alias.empty())
340 Cerr(
"***** castor-datafileConversionEx :: Please provide a scanner alias (-s) :" << endl);
341 Cout(
" It must correspond to a .geom or .hscan (user-made LUT) file in the config/scanner directory." << endl);
366 Cerr(
"***** castor-datafileConversionEx :: A problem occured while checking for the config directory path !" << endl);
372 Cerr(
"***** castor-datafileConversionEx :: A problem occured while initializing output directory !" << endl);
379 Cerr(
"***** castor-datafileConversionEx :: A problem occured while logging command line arguments !" << endl);
385 cout << std::setprecision(2);
396 scanner_alias = (scanner_alias.find(
OS_SEP)) ?
397 scanner_alias.substr(scanner_alias.find_last_of(
OS_SEP)+1) :
402 Cerr(
"**** castor-datafileConversionEx :: A problem occurred while searching for scanner system !" << endl);
407 path_to_data_file = path_to_out_file +
".Cdf";
408 path_to_header_file = path_to_out_file +
".Cdh";
425 uint16_t max_nb_lines_per_event = 1;
455 if(!istp_alias.empty())
459 Cerr(
"**** castor-datafileConversionEx :: A problem occurred while checking isotope name !" << endl);
490 uint32_t nangles = 1;
492 uint32_t nb_cor_factors = nbins
501 bool norm_flag =
false;
503 if( !path_to_norm_file.empty() )
505 if(vb>=2)
Cout(
"--> Reading the norm correction factors file = " << path_to_norm_file <<
"..." << endl);
506 ifstream ifile(path_to_norm_file.c_str(), ios::binary | ios::in);
510 Cerr(
"***** castor-datafileConversionEx :: Error reading normalization factor file: "<< path_to_norm_file <<
" !" << endl);
517 ifile.read(reinterpret_cast < char* > (p_norm), nb_cor_factors *
sizeof(
FLTNBDATA));
529 bool scat_flag =
false;
531 if( !path_to_scat_file.empty() )
533 if(vb>=2)
Cout(
"--> Reading the scatter correction factors file = " << path_to_scat_file <<
"..." << endl);
534 ifstream ifile(path_to_scat_file.c_str(), ios::binary | ios::in);
538 Cerr(
"***** castor-datafileConversionEx :: Error reading scatter factor file: "<< path_to_scat_file <<
" !" << endl);
545 ifile.read(reinterpret_cast < char* > (p_scat), nb_cor_factors *
sizeof(
FLTNBDATA));
557 bool rdm_flag =
false;
559 if( !path_to_rdm_file.empty() )
561 if(vb>=2)
Cout(
"--> Reading the random correction factors file = " << path_to_rdm_file <<
"..." << endl);
562 ifstream ifile(path_to_rdm_file.c_str(), ios::binary | ios::in);
566 Cerr(
"***** castor-datafileConversionEx :: Error reading random correction factor file: "<< path_to_rdm_file <<
" !" << endl);
573 ifile.read(reinterpret_cast < char* > (p_rdm), nb_cor_factors *
sizeof(
FLTNBDATA));
585 bool acf_flag =
false;
587 if( !path_to_acf_file.empty() )
589 if(vb>=2)
Cout(
"--> Reading the attenuation correction factors file = " << path_to_acf_file <<
"..." << endl);
590 ifstream ifile(path_to_acf_file.c_str(), ios::binary | ios::in);
594 Cerr(
"***** castor-datafileConversionEx :: Error reading attenuation correction factor file: "<< path_to_acf_file <<
" !" << endl);
601 ifile.read(reinterpret_cast < char* > (p_acf), nb_cor_factors*
sizeof(
FLTNBDATA));
625 Cout(
" --- Start conversion of datafile : " << path_to_input_file << endl
626 <<
" CASToR output header datafile: " << path_to_header_file << endl
627 <<
" CASToR output binary datafile: " << path_to_data_file << endl << endl);
635 uint32_t printing_index = 0;
639 uint32_t nEvents = 0;
644 FLTNB start_time_sec = 0.;
645 FLTNB stop_time_sec = 1.;
646 FLTNB duration_sec = stop_time_sec - start_time_sec;
650 uint32_t nRsectorsPerRing = 70;
651 uint32_t nb_crystals_trs = 9,
653 uint32_t nb_crystals_per_ring = nRsectorsPerRing
658 uint32_t *castor_id1 =
new uint32_t[max_nb_lines_per_event];
659 uint32_t *castor_id2 =
new uint32_t[max_nb_lines_per_event];
667 int32_t rSectorID1, rSectorID2;
668 int32_t moduleID1, moduleID2;
669 int32_t crystalID1, crystalID2;
672 TApplication *Tapp =
new TApplication(
"tapp",0,0);
673 TTree* Coincidences =
new TTree;
674 TFile* Tfile_root =
new TFile(path_to_input_file.c_str(),
"READ",
"ROOT file with histograms");
675 Coincidences = (TTree*)Tfile_root->Get(
"Coincidences");
676 nEvents += Coincidences->GetEntries();
680 Coincidences->SetBranchAddress(
"time1",&time1);
681 Coincidences->SetBranchAddress(
"rsectorID1",&rSectorID1);
682 Coincidences->SetBranchAddress(
"moduleID1",&moduleID1);
683 Coincidences->SetBranchAddress(
"crystalID1",&crystalID1);
686 Coincidences->SetBranchAddress(
"time2",&time2);
687 Coincidences->SetBranchAddress(
"rsectorID2",&rSectorID2);
688 Coincidences->SetBranchAddress(
"moduleID2",&moduleID2);
689 Coincidences->SetBranchAddress(
"crystalID2",&crystalID2);
692 Coincidences->GetEntry(0);
697 uint32_t printing_ratio = (nEvents>1000) ? 1000 : nEvents/10;
700 for (uint32_t i=0; i<nEvents ; i++)
703 uint32_t time_ms = 0;
704 stop_time_sec = (
FLTNB)time_ms/1000;
707 int nb_lines_in_event = 1;
713 Coincidences->GetEntry(i);
721 uint32_t crystals_trs_id1 = (uint32_t)(crystalID1/nb_crystals_trs);
723 uint32_t ringID1 = moduleID1*nb_crystals_axl
726 uint32_t crystals_trs_id2 = (uint32_t)(crystalID2/nb_crystals_trs);
728 uint32_t ringID2 = moduleID2*nb_crystals_axl
732 for(
int l=0 ; l<nb_lines_in_event ; l++)
736 castor_id1[l] = ringID1*nb_crystals_per_ring
737 + rSectorID1*nb_crystals_trs
738 + crystalID1%nb_crystals_trs ;
740 castor_id2[l] = ringID2*nb_crystals_per_ring
741 + rSectorID2*nb_crystals_trs
742 + crystalID2%nb_crystals_trs ;
747 if(is_histogram_flag)
753 for(
int l=0 ; l<nb_lines_in_event ; l++)
755 Event->
SetID1(l, castor_id1[l]);
756 Event->
SetID2(l, castor_id2[l]);
761 for (
int b=0; b<nb_tof_bins; b++)
764 FLTNB event_value = 1.;
772 FLTNB scat_correction_coeff = 0.;
773 ((
iEventHistoPET*)Event)->SetScatterRate(b, scat_correction_coeff);
786 FLTNB rdm_correction_coeff = 0.;
787 ((
iEventPET*)Event)->SetRandomRate(rdm_correction_coeff);
795 FLTNB norm_correction_coeff = 0.;
796 ((
iEventPET*)Event)->SetNormalizationFactor(norm_correction_coeff);
804 FLTNB atn_correction_coeff = 0.;
805 ((
iEventPET*)Event)->SetAttenuationCorrectionFactor(atn_correction_coeff);
820 for(
int l=0 ; l<nb_lines_in_event ; l++)
822 Event->
SetID1(l, castor_id1[l]);
823 Event->
SetID2(l, castor_id2[l]);
831 FLTNB scat_correction_coeff = 0.;
833 ((
iEventListPET*)Event)->SetScatterRate(0, scat_correction_coeff);
844 FLTNB rdm_correction_coeff = 0.;
845 ((
iEventPET*)Event)->SetRandomRate(rdm_correction_coeff);
853 FLTNB norm_correction_coeff = 0.;
854 ((
iEventPET*)Event)->SetNormalizationFactor(norm_correction_coeff);
862 FLTNB atn_correction_coeff = 0.;
863 ((
iEventPET*)Event)->SetAttenuationCorrectionFactor(atn_correction_coeff);
872 if (printing_index%printing_ratio==0)
875 cout <<
"\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b "
876 << percent <<
" \% ";
881 Cout(
"The simulated dataset contained " << nEvents <<
" coincidences / bins" << endl);
913 if(p_acf != NULL)
delete[] p_acf;
914 if(p_rdm != NULL)
delete[] p_rdm;
915 if(p_scat != NULL)
delete[] p_scat;
916 if(p_norm != NULL)
delete[] p_norm;
921 if (is_histogram_flag)
927 delete Out_data_file;
void SetDataMode(int a_dataMode)
set the data mode
This header file is mainly used to declare some macro definitions and all includes needed from the st...
int SetPETIsotope(int a_bed, const string &a_isotope)
Set the PET isotope for the provided bed.
static sScannerManager * GetInstance()
Instanciate the singleton object and Initialize member variables if not already done, return a pointer to this object otherwise.
void SetNbLines(uint16_t a_value)
Set the number of lines of the Event.
void SetVerbose(int a_verbose)
set verbosity
void SetAtnCorrectionFlagOn()
set to true the flag indicating the presence of attenuation correction factors in the datafile ...
int FindScannerSystem(string a_scannerName)
Look for a file matching with the scanner name in parameter inside the scanner repository.
void SetScatterCorrectionFlagOn()
set to true the flag indicating the presence of scatter correction factors in the datafile ...
void SetVerbose(int a_verboseLevel)
set verbosity
void SetDuration(FLTNB a_value)
virtual void SetEventValue(int a_bin, FLTNBDATA a_value)=0
This function is implemented by child classes.
static sOutputManager * GetInstance()
Instanciate the singleton object and Initialize member variables if not already done, return a pointer to this object otherwise.
int ComputeSizeEvent()
Computation of the size of each event according to the mandatory/optional correction fields...
Declaration of class iDataFilePET.
int LogCommandLine(int argc, char **argv)
Write log file header with the provided command line options and different informations.
void SetIsotope(string a_value)
initialize the isotope string value
int PROJ_WriteData()
Write/Merge chunk of data in a general data file.
int ConvertFromString(const string &a_str, string *a_result)
Copy the 'a_str' string in the position pointed by 'a_result'.
int CheckConfigDir(const string &a_path)
Set the path to the CASTOR config directory from the given path if not empty or through the existence...
Inherit from iEventPET. Class for PET list-mode events.
Inherit from iEventPET. Class for PET histogram mode events.
int PROJ_WriteEvent(vEvent *ap_Event, int a_th)
Write event according to the chosen type of data.
void SetStartTime(FLTNB a_value)
Singleton class that manages output writing on disk (images, sinograms, etc). It also manages loggi...
void SetDataType(int a_dataType)
set the data type
Singleton class that Instantiate and initialize the scanner object.
void SetCalibrationFactor(FLTNB a_value)
initialize the global calibration factor with a FLTNB value
void SetRandomCorrectionFlagOn()
set to true the flag indicating the presence of random correction factors in the datafile ...
Declaration of class sScannerManager.
void ShowHelp(int a_returnCode)
void SetHeaderDataFileName(const string &a_headerFileName)
set the data header file name
void SetMPIRank(int a_mpiRank)
Initialize the machine index for MPI.
int AllocateID()
Instantiate the mp_ID1 and mp_ID2 indices arrays.
int PROJ_InitFile()
Initialize the fstream objets for output writing as well as some other variables specific to the Proj...
int PROJ_DeleteTmpDatafile()
Delete temporary datafile used for multithreaded output writing if needed.
int PROJ_WriteHeader()
Generate a header file according to the projection and data output informations. Used by Projection...
int main(int argc, char **argv)
Inherit from vEvent. Main PET class for the Event objects.
void SetNbEvents(int64_t a_value)
initialize the number of events with a int64_t value
int PrepareDataFile()
Store different kind of information inside arrays (data relative to specific correction as well as ba...
void SetID2(int a_line, uint32_t a_value)
Set the indice associated with the line index for the 2nd ID of the Event.
void SetTimeInMs(uint32_t a_value)
Set the timestamp of the Event.
Declaration of class sOutputManager.
Mother class for the Event objects.
int InitOutputDirectory(const string &a_pathFout, const string &a_pathDout)
Create the output directory if any, extract the base name and create the log file.
void SetNormCorrectionFlagOn()
set to true the flag indicating the presence of normalization correction factors in the datafile ...
This class is designed to manage all dimensions and quantification related stuff. ...
This file is used for all kind of different functions designed for options parsing and ASCII file rea...
void SetVerbose(int a_verboseLevel)
set verbosity
void SetImageDimensionsAndQuantification(oImageDimensionsAndQuantification *ap_ImageDimensionsAndQuantification)
set the pointer to the oImageDimensionsAndQuantification object
Inherit from vDataFile. Class that manages the reading of a PET input file (header + data)...
void SetPercentageLoad(int a_percentageLoad)
Set the percentage of the data file that will be loaded in memory.
void SetMaxNumberOfLinesPerEvent(uint16_t a_value)
set the max number of line per event in the datafile
void SetID1(int a_line, uint32_t a_value)
Set the indice associated with the line index for the 1st ID of the Event.