16 #include "gVariables.hh" 17 #include "gOptions.hh" 18 #include "iDataFilePET.hh" 19 #include "sOutputManager.hh" 20 #include "sScannerManager.hh" 25 #include "Windows4Root.h" 28 #include "TApplication.h" 44 cout <<
"NOTE : This program is an example code providing guidance regarding how to generate a PET CASToR datafile from any system datafile " << endl;
45 cout <<
" It does NOT perform any conversion by itself and must be adjusted to the conversion of any system dataset !" << endl;
48 cout <<
"Usage: castor-datafileConversionEx -ih input_datafile : (if datafile is histogram mode)" << endl;
49 cout <<
" -il input_datafile : (if datafile is list-mode)" << endl;
50 cout <<
" -o output_datafile" << endl;
51 cout <<
" -s scanner_alias "<< endl;
52 cout <<
" [-nc norm_factors_file" << endl;
53 cout <<
" [-sc scat_factors_file" << endl;
54 cout <<
" [-rc rdm_factors_file" << endl;
55 cout <<
" [-ac atn_factors_file" << endl;
56 cout <<
" [-cf calibration factor" << endl;
57 cout <<
" [-ist isotope_alias" << endl;
60 cout <<
" [-vb verbosity]" << endl;
63 cout <<
"[Main settings]:" << endl;
64 cout <<
" -ih path_to_histo_datafile : provide an input histogram datafile to convert" << endl;
65 cout <<
" -il path_to_listm_datafile : provide an input list-mode datafile to convert" << endl;
66 cout <<
" -o path_to_cstr_file.cdh : provide the path to the output file will be created inside this folder (no default)" << endl;
67 cout <<
" -s scanner_alias : provide the name of the scanner used for to acquire the original data" << endl;
68 cout <<
" : Must correspond to a .geom or .hscan file in the config/scanner repository." << endl;
70 cout <<
"[Optional settings]:" << endl;
71 cout <<
" -nc norm_factors_file : provide a file containing normalization correction factors" << endl;
72 cout <<
" -sc scat_factors_file : provide a file containing scatter correction factors" << endl;
73 cout <<
" -rc rdm_factors_file : provide a file containing random correction factors" << endl;
74 cout <<
" -ac atn_factors_file : provide a file containing attenuation correction factors" << endl;
75 cout <<
" -cf calibration factor : provide a calibration factor" << endl;
76 cout <<
" -ist isotope_alias : provide alias of the isotope used in the input datafile"<< endl;
77 cout <<
" Supported PET isotopes and their parameters are listed in config/misc/isotopes_pet"<< endl;
78 cout <<
" Other isotopes can be added in the same file"<< endl;
80 cout <<
"[Miscellaneous settings]:" << endl;
81 cout <<
" -vb : give the verbosity level, from 0 (no verbose) to above 5 (at the event level) (default: 1)." << endl;
84 cout <<
" This program is part of the CASToR release version " <<
CASTOR_VERSION <<
"." << endl;
94 int main(
int argc,
char** argv)
102 MPI_Init(&argc, &argv);
103 MPI_Comm_rank(MPI_COMM_WORLD, &mpi_rank);
104 MPI_Comm_size(MPI_COMM_WORLD, &mpi_size);
105 if (mpi_rank!=0)
return 0;
116 string path_to_input_file =
"";
122 string path_to_out_file =
"";
123 string path_to_data_file =
"";
124 string path_to_header_file =
"";
125 string path_to_norm_file =
"";
126 string path_to_scat_file =
"";
127 string path_to_rdm_file =
"";
128 string path_to_acf_file =
"";
129 FLTNB calib_factor = 1.;
131 string scanner_alias =
"";
132 string istp_alias =
"";
138 bool is_histogram_flag = 0;
145 for (
int i=1; i<argc; i++)
147 string option = (string)argv[i];
152 if (!path_to_input_file.empty())
154 Cerr(
"***** castor-datafileConversionEx :: the following file names have already been provided (either -ih or -il option must be used): " << endl);
155 Cout(path_to_input_file << endl);
160 if (argv[i+1] == NULL)
162 Cerr(
"***** castor-datafileConversionEx :: argument missing for option: " << option << endl);
166 path_to_input_file = (string)argv[i+1];
176 if (!path_to_input_file.empty())
178 Cerr(
"***** castor-datafileConversionEx :: the following file names have already been provided (either -ih or -il option must be used): " << endl);
179 Cout(path_to_input_file << endl);
184 if (argv[i+1] == NULL)
186 Cerr(
"***** castor-datafileConversionEx :: argument missing for option: " << option << endl);
190 path_to_input_file = (string)argv[i+1];
198 else if (option==
"-o")
200 if (argv[i+1] == NULL)
202 Cerr(
"***** castor-datafileConversionEx :: argument missing for option: " << option << endl);
206 path_to_out_file = (string)argv[i+1];
211 else if (option==
"-s")
213 if (argv[i+1] == NULL)
215 Cerr(
"***** castor-datafileConversionEx :: argument missing for option: " << option << endl);
219 scanner_alias = (string)argv[i+1];
224 else if (option==
"-nc")
226 if (argv[i+1] == NULL)
228 Cerr(
"***** castor-datafileConversionEx :: argument missing for option: " << option << endl);
232 path_to_norm_file = (string)argv[i+1];
238 else if (option==
"-sc")
240 if (argv[i+1] == NULL)
242 Cerr(
"***** castor-datafileConversionEx :: argument missing for option: " << option << endl);
246 path_to_scat_file = (string)argv[i+1];
252 else if (option==
"-rc")
254 if (argv[i+1] == NULL)
256 Cerr(
"***** castor-datafileConversionEx :: argument missing for option: " << option << endl);
260 path_to_rdm_file = (string)argv[i+1];
266 else if (option==
"-ac")
268 if (argv[i+1] == NULL)
270 Cerr(
"***** castor-datafileConversionEx :: argument missing for option: " << option << endl);
274 path_to_acf_file = (string)argv[i+1];
280 else if (option==
"-cf")
282 if (argv[i+1] == NULL)
284 Cerr(
"***** castor-datafileConversionEx :: argument missing for option: " << option << endl);
289 string val_str = (string)argv[i+1];
292 Cerr(
"***** castor-datafileConversionEx :: Exception when trying to read'" << val_str <<
" for option: " << option << endl);
300 else if (option==
"-ist")
302 if (argv[i+1] == NULL)
304 Cerr(
"***** castor-datafileConversionEx :: argument missing for option: " << option << endl);
308 istp_alias = (string)argv[i+1];
314 else if (option==
"-vb")
318 Cerr(
"***** castor-datafileConversionEx :: Argument missing for option: " << option << endl);
321 vb = atoi(argv[i+1]);
327 Cerr(
"***** castor-datafileConversionEx :: Unknown option '" << option <<
"' !" << endl);
338 if (path_to_input_file.empty() )
340 Cerr(
"***** castor-datafileConversionEx :: Please provide at least one data filename (-ih for histogram, -il for list-mode)" << endl);
341 cout <<
" -input filename : give an input datafile (no default)." << endl;
346 if (path_to_out_file.empty() )
348 Cerr(
"***** castor-datafileConversionEx :: Please provide the output file name (-o)" << endl);
353 if (scanner_alias.empty())
355 Cerr(
"***** castor-datafileConversionEx :: Please provide a scanner alias (-s) :" << endl);
356 Cout(
" It must correspond to a .geom or .hscan (user-made LUT) file in the config/scanner directory." << endl);
381 Cerr(
"***** castor-datafileConversionEx :: A problem occurred while checking for the config directory path !" << endl);
387 Cerr(
"***** castor-datafileConversionEx :: A problem occurred while initializing output directory !" << endl);
394 Cerr(
"***** castor-datafileConversionEx :: A problem occurred while logging command line arguments !" << endl);
400 cout << std::setprecision(2);
411 scanner_alias = (scanner_alias.find(
OS_SEP)) ?
412 scanner_alias.substr(scanner_alias.find_last_of(
OS_SEP)+1) :
417 Cerr(
"**** castor-datafileConversionEx :: A problem occurred while searching for scanner system !" << endl);
422 path_to_data_file = path_to_out_file +
".Cdf";
423 path_to_header_file = path_to_out_file +
".Cdh";
440 uint16_t max_nb_lines_per_event = 1;
467 if(!istp_alias.empty())
471 Cerr(
"**** castor-datafileConversionEx :: A problem occurred while checking isotope name !" << endl);
502 uint32_t nangles = 1;
504 uint32_t nb_cor_factors = nbins
513 bool norm_flag =
false;
515 if( !path_to_norm_file.empty() )
517 if(vb>=2)
Cout(
"--> Reading the norm correction factors file = " << path_to_norm_file <<
"..." << endl);
518 ifstream ifile(path_to_norm_file.c_str(), ios::binary | ios::in);
522 Cerr(
"***** castor-datafileConversionEx :: Error reading normalization factor file: "<< path_to_norm_file <<
" !" << endl);
529 ifile.read(reinterpret_cast < char* > (p_norm), nb_cor_factors *
sizeof(
FLTNBDATA));
541 bool scat_flag =
false;
543 if( !path_to_scat_file.empty() )
545 if(vb>=2)
Cout(
"--> Reading the scatter correction factors file = " << path_to_scat_file <<
"..." << endl);
546 ifstream ifile(path_to_scat_file.c_str(), ios::binary | ios::in);
550 Cerr(
"***** castor-datafileConversionEx :: Error reading scatter factor file: "<< path_to_scat_file <<
" !" << endl);
557 ifile.read(reinterpret_cast < char* > (p_scat), nb_cor_factors *
sizeof(
FLTNBDATA));
569 bool rdm_flag =
false;
571 if( !path_to_rdm_file.empty() )
573 if(vb>=2)
Cout(
"--> Reading the random correction factors file = " << path_to_rdm_file <<
"..." << endl);
574 ifstream ifile(path_to_rdm_file.c_str(), ios::binary | ios::in);
578 Cerr(
"***** castor-datafileConversionEx :: Error reading random correction factor file: "<< path_to_rdm_file <<
" !" << endl);
585 ifile.read(reinterpret_cast < char* > (p_rdm), nb_cor_factors *
sizeof(
FLTNBDATA));
597 bool acf_flag =
false;
599 if( !path_to_acf_file.empty() )
601 if(vb>=2)
Cout(
"--> Reading the attenuation correction factors file = " << path_to_acf_file <<
"..." << endl);
602 ifstream ifile(path_to_acf_file.c_str(), ios::binary | ios::in);
606 Cerr(
"***** castor-datafileConversionEx :: Error reading attenuation correction factor file: "<< path_to_acf_file <<
" !" << endl);
613 ifile.read(reinterpret_cast < char* > (p_acf), nb_cor_factors*
sizeof(
FLTNBDATA));
637 Cout(
" --- Start conversion of datafile : " << path_to_input_file << endl
638 <<
" CASToR output header datafile: " << path_to_header_file << endl
639 <<
" CASToR output binary datafile: " << path_to_data_file << endl << endl);
647 uint32_t printing_index = 0;
651 uint32_t nEvents = 0;
656 FLTNB start_time_sec = 0.;
657 FLTNB stop_time_sec = 1.;
658 FLTNB duration_sec = stop_time_sec - start_time_sec;
662 uint32_t nRsectorsPerRing = 70;
663 uint32_t nb_crystals_trs = 9,
665 uint32_t nb_crystals_per_ring = nRsectorsPerRing
670 uint32_t *castor_id1 =
new uint32_t[max_nb_lines_per_event];
671 uint32_t *castor_id2 =
new uint32_t[max_nb_lines_per_event];
679 int32_t rSectorID1 = 0, rSectorID2 = 0;
680 int32_t moduleID1 = 0, moduleID2 = 0;
681 int32_t crystalID1 = 0, crystalID2 = 0;
684 TApplication *Tapp =
new TApplication(
"tapp",0,0);
685 TTree* Coincidences =
new TTree;
686 TFile* Tfile_root =
new TFile(path_to_input_file.c_str(),
"READ",
"ROOT file with histograms");
687 Coincidences = (TTree*)Tfile_root->Get(
"Coincidences");
688 nEvents += Coincidences->GetEntries();
692 Coincidences->SetBranchAddress(
"time1",&time1);
693 Coincidences->SetBranchAddress(
"rsectorID1",&rSectorID1);
694 Coincidences->SetBranchAddress(
"moduleID1",&moduleID1);
695 Coincidences->SetBranchAddress(
"crystalID1",&crystalID1);
698 Coincidences->SetBranchAddress(
"time2",&time2);
699 Coincidences->SetBranchAddress(
"rsectorID2",&rSectorID2);
700 Coincidences->SetBranchAddress(
"moduleID2",&moduleID2);
701 Coincidences->SetBranchAddress(
"crystalID2",&crystalID2);
704 Coincidences->GetEntry(0);
709 uint32_t printing_ratio = (nEvents>1000) ? 1000 : nEvents/10;
712 for (uint32_t i=0; i<nEvents ; i++)
715 uint32_t time_ms = 0;
716 stop_time_sec = (
FLTNB)time_ms/1000;
719 int nb_lines_in_event = 1;
725 Coincidences->GetEntry(i);
733 uint32_t crystals_trs_id1 = (uint32_t)(crystalID1/nb_crystals_trs);
735 uint32_t ringID1 = moduleID1*nb_crystals_axl
738 uint32_t crystals_trs_id2 = (uint32_t)(crystalID2/nb_crystals_trs);
740 uint32_t ringID2 = moduleID2*nb_crystals_axl
744 for(
int l=0 ; l<nb_lines_in_event ; l++)
748 castor_id1[l] = ringID1*nb_crystals_per_ring
749 + rSectorID1*nb_crystals_trs
750 + crystalID1%nb_crystals_trs ;
752 castor_id2[l] = ringID2*nb_crystals_per_ring
753 + rSectorID2*nb_crystals_trs
754 + crystalID2%nb_crystals_trs ;
759 if(is_histogram_flag)
765 for(
int l=0 ; l<nb_lines_in_event ; l++)
767 Event->
SetID1(l, castor_id1[l]);
768 Event->
SetID2(l, castor_id2[l]);
773 for (
int b=0; b<nb_tof_bins; b++)
776 FLTNB event_value = 1.;
784 FLTNB scat_correction_coeff = 0.;
785 ((
iEventHistoPET*)Event)->SetScatterRate(b, scat_correction_coeff);
798 FLTNB rdm_correction_coeff = 0.;
799 ((
iEventPET*)Event)->SetRandomRate(rdm_correction_coeff);
807 FLTNB norm_correction_coeff = 0.;
808 ((
iEventPET*)Event)->SetNormalizationFactor(norm_correction_coeff);
816 FLTNB atn_correction_coeff = 0.;
817 ((
iEventPET*)Event)->SetAttenuationCorrectionFactor(atn_correction_coeff);
832 for(
int l=0 ; l<nb_lines_in_event ; l++)
834 Event->
SetID1(l, castor_id1[l]);
835 Event->
SetID2(l, castor_id2[l]);
843 FLTNB scat_correction_coeff = 0.;
845 ((
iEventListPET*)Event)->SetScatterRate(0, scat_correction_coeff);
856 FLTNB rdm_correction_coeff = 0.;
857 ((
iEventPET*)Event)->SetRandomRate(rdm_correction_coeff);
865 FLTNB norm_correction_coeff = 0.;
866 ((
iEventPET*)Event)->SetNormalizationFactor(norm_correction_coeff);
874 FLTNB atn_correction_coeff = 0.;
875 ((
iEventPET*)Event)->SetAttenuationCorrectionFactor(atn_correction_coeff);
884 if (printing_index%printing_ratio==0)
887 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 " 893 Cout(
"The simulated dataset contained " << nEvents <<
" coincidences / bins" << endl);
925 if(p_acf != NULL)
delete[] p_acf;
926 if(p_rdm != NULL)
delete[] p_rdm;
927 if(p_scat != NULL)
delete[] p_scat;
928 if(p_norm != NULL)
delete[] p_norm;
933 if (is_histogram_flag)
939 delete Out_data_file;
int WriteEvent(vEvent *ap_Event, int a_th)
void SetDataMode(int a_dataMode)
int SetPETIsotope(int a_bed, const string &a_isotope)
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)
void SetVerbose(int a_verbose)
void SetAtnCorrectionFlagOn()
set to true the flag indicating the presence of attenuation correction factors in the datafile ...
int FindScannerSystem(string a_scannerName)
void SetIsotope(string a_value)
void SetScatterCorrectionFlagOn()
set to true the flag indicating the presence of scatter correction factors in the datafile ...
void SetVerbose(int a_verboseLevel)
void SetDuration(FLTNB a_value)
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...
int LogCommandLine(int argc, char **argv)
int PROJ_WriteData()
Write/Merge chunk of data in a general data file.
int CheckConfigDir(const string &a_path)
Inherit from iEventPET. Class for PET list-mode events.
Inherit from iEventPET. Class for PET histogram mode events.
void SetStartTime(FLTNB a_value)
Singleton class that manages output writing on disk (images, sinograms, etc). It also manages loggi...
void SetMaxNumberOfLinesPerEvent(uint16_t a_value)
void SetDataType(int a_dataType)
Singleton class that Instantiate and initialize the scanner object.
void SetCalibrationFactor(FLTNB a_value)
virtual void SetEventValue(int a_bin, FLTNBDATA a_value)=0
void SetRandomCorrectionFlagOn()
set to true the flag indicating the presence of random correction factors in the datafile ...
void SetHeaderDataFileName(const string &a_headerFileName)
int WriteHeader()
Generate a header file according to the data output information.
void SetMPIRank(int a_mpiRank)
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...
Inherit from vEvent. Main PET class for the Event objects.
void SetNbEvents(int64_t a_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)
void SetTimeInMs(uint32_t a_value)
Mother class for the Event objects.
int InitOutputDirectory(const string &a_pathFout, const string &a_pathDout)
int ConvertFromString(const string &a_str, string *a_result)
Copy the 'a_str' string in the position pointed by 'a_result'.
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. ...
void SetVerbose(int a_verboseLevel)
int PROJ_DeleteTmpDataFile()
Delete temporary datafile used for multithreaded output writing if needed.
void SetImageDimensionsAndQuantification(oImageDimensionsAndQuantification *ap_ImageDimensionsAndQuantification)
Inherit from vDataFile. Class that manages the reading of a PET input file (header + data)...
void SetID1(int a_line, uint32_t a_value)