48 #include "Windows4Root.h"
51 #include "TApplication.h"
67 cout <<
"NOTE : This program is an example code providing guidance regarding how to generate a PET CASToR datafile from any system datafile " << endl;
68 cout <<
" It does NOT perform any conversion by itself and must be adjusted to the conversion of any system dataset !" << endl;
71 cout <<
"Usage: castor-datafileConversionEx -ih input_datafile : (if datafile is histogram mode)" << endl;
72 cout <<
" -il input_datafile : (if datafile is list-mode)" << endl;
73 cout <<
" -o output_datafile" << endl;
74 cout <<
" -s scanner_alias "<< endl;
75 cout <<
" [-nc norm_factors_file" << endl;
76 cout <<
" [-sc scat_factors_file" << endl;
77 cout <<
" [-rc rdm_factors_file" << endl;
78 cout <<
" [-ac atn_factors_file" << endl;
79 cout <<
" [-cf calibration factor" << endl;
80 cout <<
" [-ist isotope_alias" << endl;
83 cout <<
" [-vb verbosity]" << endl;
86 cout <<
"[Main settings]:" << endl;
87 cout <<
" -ih path_to_histo_datafile : provide an input histogram datafile to convert" << endl;
88 cout <<
" -il path_to_listm_datafile : provide an input list-mode datafile to convert" << endl;
89 cout <<
" -o path_to_cstr_file.cdh : provide the path to the output file will be created inside this folder (no default)" << endl;
90 cout <<
" -s scanner_alias : provide the name of the scanner used for to acquire the original data" << endl;
91 cout <<
" : Must correspond to a .geom or .hscan file in the config/scanner repository." << endl;
93 cout <<
"[Optional settings]:" << endl;
94 cout <<
" -nc norm_factors_file : provide a file containing normalization correction factors" << endl;
95 cout <<
" -sc scat_factors_file : provide a file containing scatter correction factors" << endl;
96 cout <<
" -rc rdm_factors_file : provide a file containing random correction factors" << endl;
97 cout <<
" -ac atn_factors_file : provide a file containing attenuation correction factors" << endl;
98 cout <<
" -cf calibration factor : provide a calibration factor" << endl;
99 cout <<
" -ist isotope_alias : provide alias of the isotope used in the input datafile"<< endl;
100 cout <<
" Supported PET isotopes and their parameters are listed in config/misc/isotopes_pet"<< endl;
101 cout <<
" Other isotopes can be added in the same file"<< endl;
103 cout <<
"[Miscellaneous settings]:" << endl;
104 cout <<
" -vb : give the verbosity level, from 0 (no verbose) to above 5 (at the event level) (default: 1)." << endl;
106 #ifdef CASTOR_VERSION
107 cout <<
" This program is part of the CASToR release version " <<
CASTOR_VERSION <<
"." << endl;
117 int main(
int argc,
char** argv)
127 string path_to_input_file =
"";
133 string path_to_out_file =
"";
134 string path_to_data_file =
"";
135 string path_to_header_file =
"";
136 string path_to_norm_file =
"";
137 string path_to_scat_file =
"";
138 string path_to_rdm_file =
"";
139 string path_to_acf_file =
"";
140 FLTNB calib_factor = 1.;
142 string scanner_alias =
"";
143 string istp_alias =
"";
149 bool is_histogram_flag = 0;
156 for (
int i=1; i<argc; i++)
158 string option = (string)argv[i];
163 if (!path_to_input_file.empty())
165 Cerr(
"***** castor-datafileConversionEx :: the following file names have already been provided (either -ih or -il option must be used): " << endl);
166 Cout(path_to_input_file << endl);
171 if (argv[i+1] == NULL)
173 Cerr(
"***** castor-datafileConversionEx :: argument missing for option: " << option << endl);
177 path_to_input_file = (string)argv[i+1];
187 if (!path_to_input_file.empty())
189 Cerr(
"***** castor-datafileConversionEx :: the following file names have already been provided (either -ih or -il option must be used): " << endl);
190 Cout(path_to_input_file << endl);
195 if (argv[i+1] == NULL)
197 Cerr(
"***** castor-datafileConversionEx :: argument missing for option: " << option << endl);
201 path_to_input_file = (string)argv[i+1];
209 else if (option==
"-o")
211 if (argv[i+1] == NULL)
213 Cerr(
"***** castor-datafileConversionEx :: argument missing for option: " << option << endl);
217 path_to_out_file = (string)argv[i+1];
222 else if (option==
"-s")
224 if (argv[i+1] == NULL)
226 Cerr(
"***** castor-datafileConversionEx :: argument missing for option: " << option << endl);
230 scanner_alias = (string)argv[i+1];
235 else if (option==
"-nc")
237 if (argv[i+1] == NULL)
239 Cerr(
"***** castor-datafileConversionEx :: argument missing for option: " << option << endl);
243 path_to_norm_file = (string)argv[i+1];
249 else if (option==
"-sc")
251 if (argv[i+1] == NULL)
253 Cerr(
"***** castor-datafileConversionEx :: argument missing for option: " << option << endl);
257 path_to_scat_file = (string)argv[i+1];
263 else if (option==
"-rc")
265 if (argv[i+1] == NULL)
267 Cerr(
"***** castor-datafileConversionEx :: argument missing for option: " << option << endl);
271 path_to_rdm_file = (string)argv[i+1];
277 else if (option==
"-ac")
279 if (argv[i+1] == NULL)
281 Cerr(
"***** castor-datafileConversionEx :: argument missing for option: " << option << endl);
285 path_to_acf_file = (string)argv[i+1];
291 else if (option==
"-cf")
293 if (argv[i+1] == NULL)
295 Cerr(
"***** castor-datafileConversionEx :: argument missing for option: " << option << endl);
300 string val_str = (string)argv[i+1];
303 Cerr(
"***** castor-datafileConversionEx :: Exception when trying to read'" << val_str <<
" for option: " << option << endl);
311 else if (option==
"-ist")
313 if (argv[i+1] == NULL)
315 Cerr(
"***** castor-datafileConversionEx :: argument missing for option: " << option << endl);
319 istp_alias = (string)argv[i+1];
325 else if (option==
"-vb")
329 Cerr(
"***** castor-datafileConversionEx :: Argument missing for option: " << option << endl);
332 vb = atoi(argv[i+1]);
338 Cerr(
"***** castor-datafileConversionEx :: Unknown option '" << option <<
"' !" << endl);
349 if (path_to_input_file.empty() )
351 Cerr(
"***** castor-datafileConversionEx :: Please provide at least one data filename (-ih for histogram, -il for list-mode)" << endl);
352 cout <<
" -input filename : give an input datafile (no default)." << endl;
357 if (path_to_out_file.empty() )
359 Cerr(
"***** castor-datafileConversionEx :: Please provide the output file name (-o)" << endl);
364 if (scanner_alias.empty())
366 Cerr(
"***** castor-datafileConversionEx :: Please provide a scanner alias (-s) :" << endl);
367 Cout(
" It must correspond to a .geom or .hscan (user-made LUT) file in the config/scanner directory." << endl);
392 Cerr(
"***** castor-datafileConversionEx :: A problem occured while checking for the config directory path !" << endl);
398 Cerr(
"***** castor-datafileConversionEx :: A problem occured while initializing output directory !" << endl);
405 Cerr(
"***** castor-datafileConversionEx :: A problem occured while logging command line arguments !" << endl);
411 cout << std::setprecision(2);
422 scanner_alias = (scanner_alias.find(
OS_SEP)) ?
423 scanner_alias.substr(scanner_alias.find_last_of(
OS_SEP)+1) :
428 Cerr(
"**** castor-datafileConversionEx :: A problem occurred while searching for scanner system !" << endl);
433 path_to_data_file = path_to_out_file +
".Cdf";
434 path_to_header_file = path_to_out_file +
".Cdh";
451 uint16_t max_nb_lines_per_event = 1;
478 if(!istp_alias.empty())
482 Cerr(
"**** castor-datafileConversionEx :: A problem occurred while checking isotope name !" << endl);
513 uint32_t nangles = 1;
515 uint32_t nb_cor_factors = nbins
524 bool norm_flag =
false;
526 if( !path_to_norm_file.empty() )
528 if(vb>=2)
Cout(
"--> Reading the norm correction factors file = " << path_to_norm_file <<
"..." << endl);
529 ifstream ifile(path_to_norm_file.c_str(), ios::binary | ios::in);
533 Cerr(
"***** castor-datafileConversionEx :: Error reading normalization factor file: "<< path_to_norm_file <<
" !" << endl);
540 ifile.read(reinterpret_cast < char* > (p_norm), nb_cor_factors *
sizeof(
FLTNBDATA));
552 bool scat_flag =
false;
554 if( !path_to_scat_file.empty() )
556 if(vb>=2)
Cout(
"--> Reading the scatter correction factors file = " << path_to_scat_file <<
"..." << endl);
557 ifstream ifile(path_to_scat_file.c_str(), ios::binary | ios::in);
561 Cerr(
"***** castor-datafileConversionEx :: Error reading scatter factor file: "<< path_to_scat_file <<
" !" << endl);
568 ifile.read(reinterpret_cast < char* > (p_scat), nb_cor_factors *
sizeof(
FLTNBDATA));
580 bool rdm_flag =
false;
582 if( !path_to_rdm_file.empty() )
584 if(vb>=2)
Cout(
"--> Reading the random correction factors file = " << path_to_rdm_file <<
"..." << endl);
585 ifstream ifile(path_to_rdm_file.c_str(), ios::binary | ios::in);
589 Cerr(
"***** castor-datafileConversionEx :: Error reading random correction factor file: "<< path_to_rdm_file <<
" !" << endl);
596 ifile.read(reinterpret_cast < char* > (p_rdm), nb_cor_factors *
sizeof(
FLTNBDATA));
608 bool acf_flag =
false;
610 if( !path_to_acf_file.empty() )
612 if(vb>=2)
Cout(
"--> Reading the attenuation correction factors file = " << path_to_acf_file <<
"..." << endl);
613 ifstream ifile(path_to_acf_file.c_str(), ios::binary | ios::in);
617 Cerr(
"***** castor-datafileConversionEx :: Error reading attenuation correction factor file: "<< path_to_acf_file <<
" !" << endl);
624 ifile.read(reinterpret_cast < char* > (p_acf), nb_cor_factors*
sizeof(
FLTNBDATA));
648 Cout(
" --- Start conversion of datafile : " << path_to_input_file << endl
649 <<
" CASToR output header datafile: " << path_to_header_file << endl
650 <<
" CASToR output binary datafile: " << path_to_data_file << endl << endl);
658 uint32_t printing_index = 0;
662 uint32_t nEvents = 0;
667 FLTNB start_time_sec = 0.;
668 FLTNB stop_time_sec = 1.;
669 FLTNB duration_sec = stop_time_sec - start_time_sec;
673 uint32_t nRsectorsPerRing = 70;
674 uint32_t nb_crystals_trs = 9,
676 uint32_t nb_crystals_per_ring = nRsectorsPerRing
681 uint32_t *castor_id1 =
new uint32_t[max_nb_lines_per_event];
682 uint32_t *castor_id2 =
new uint32_t[max_nb_lines_per_event];
690 int32_t rSectorID1 = 0, rSectorID2 = 0;
691 int32_t moduleID1 = 0, moduleID2 = 0;
692 int32_t crystalID1 = 0, crystalID2 = 0;
695 TApplication *Tapp =
new TApplication(
"tapp",0,0);
696 TTree* Coincidences =
new TTree;
697 TFile* Tfile_root =
new TFile(path_to_input_file.c_str(),
"READ",
"ROOT file with histograms");
698 Coincidences = (TTree*)Tfile_root->Get(
"Coincidences");
699 nEvents += Coincidences->GetEntries();
703 Coincidences->SetBranchAddress(
"time1",&time1);
704 Coincidences->SetBranchAddress(
"rsectorID1",&rSectorID1);
705 Coincidences->SetBranchAddress(
"moduleID1",&moduleID1);
706 Coincidences->SetBranchAddress(
"crystalID1",&crystalID1);
709 Coincidences->SetBranchAddress(
"time2",&time2);
710 Coincidences->SetBranchAddress(
"rsectorID2",&rSectorID2);
711 Coincidences->SetBranchAddress(
"moduleID2",&moduleID2);
712 Coincidences->SetBranchAddress(
"crystalID2",&crystalID2);
715 Coincidences->GetEntry(0);
720 uint32_t printing_ratio = (nEvents>1000) ? 1000 : nEvents/10;
723 for (uint32_t i=0; i<nEvents ; i++)
726 uint32_t time_ms = 0;
727 stop_time_sec = (
FLTNB)time_ms/1000;
730 int nb_lines_in_event = 1;
736 Coincidences->GetEntry(i);
744 uint32_t crystals_trs_id1 = (uint32_t)(crystalID1/nb_crystals_trs);
746 uint32_t ringID1 = moduleID1*nb_crystals_axl
749 uint32_t crystals_trs_id2 = (uint32_t)(crystalID2/nb_crystals_trs);
751 uint32_t ringID2 = moduleID2*nb_crystals_axl
755 for(
int l=0 ; l<nb_lines_in_event ; l++)
759 castor_id1[l] = ringID1*nb_crystals_per_ring
760 + rSectorID1*nb_crystals_trs
761 + crystalID1%nb_crystals_trs ;
763 castor_id2[l] = ringID2*nb_crystals_per_ring
764 + rSectorID2*nb_crystals_trs
765 + crystalID2%nb_crystals_trs ;
770 if(is_histogram_flag)
776 for(
int l=0 ; l<nb_lines_in_event ; l++)
778 Event->
SetID1(l, castor_id1[l]);
779 Event->
SetID2(l, castor_id2[l]);
784 for (
int b=0; b<nb_tof_bins; b++)
787 FLTNB event_value = 1.;
795 FLTNB scat_correction_coeff = 0.;
796 ((
iEventHistoPET*)Event)->SetScatterRate(b, scat_correction_coeff);
809 FLTNB rdm_correction_coeff = 0.;
810 ((
iEventPET*)Event)->SetRandomRate(rdm_correction_coeff);
818 FLTNB norm_correction_coeff = 0.;
819 ((
iEventPET*)Event)->SetNormalizationFactor(norm_correction_coeff);
827 FLTNB atn_correction_coeff = 0.;
828 ((
iEventPET*)Event)->SetAttenuationCorrectionFactor(atn_correction_coeff);
843 for(
int l=0 ; l<nb_lines_in_event ; l++)
845 Event->
SetID1(l, castor_id1[l]);
846 Event->
SetID2(l, castor_id2[l]);
854 FLTNB scat_correction_coeff = 0.;
856 ((
iEventListPET*)Event)->SetScatterRate(0, scat_correction_coeff);
867 FLTNB rdm_correction_coeff = 0.;
868 ((
iEventPET*)Event)->SetRandomRate(rdm_correction_coeff);
876 FLTNB norm_correction_coeff = 0.;
877 ((
iEventPET*)Event)->SetNormalizationFactor(norm_correction_coeff);
885 FLTNB atn_correction_coeff = 0.;
886 ((
iEventPET*)Event)->SetAttenuationCorrectionFactor(atn_correction_coeff);
895 if (printing_index%printing_ratio==0)
898 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 "
904 Cout(
"The simulated dataset contained " << nEvents <<
" coincidences / bins" << endl);
936 if(p_acf != NULL)
delete[] p_acf;
937 if(p_rdm != NULL)
delete[] p_rdm;
938 if(p_scat != NULL)
delete[] p_scat;
939 if(p_norm != NULL)
delete[] p_norm;
944 if (is_histogram_flag)
950 delete Out_data_file;
int WriteEvent(vEvent *ap_Event, int a_th)
Write event according to the chosen type of data.
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.
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
int WriteHeader()
Generate a header file according to the data output information.
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 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
int PROJ_DeleteTmpDataFile()
Delete temporary datafile used for multithreaded output writing if needed.
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 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.