1 |
/** |
2 |
* OrbitalRate |
3 |
* author Nagni |
4 |
* version 1.0 - 27 April 2006 |
5 |
* |
6 |
* version 2.0 |
7 |
* author De Simone |
8 |
* - most of the code rewritten |
9 |
* - added graphs, magnetic field, new overflow resolution (AC), tle |
10 |
* stuff. |
11 |
* |
12 |
*/ |
13 |
#include <physics/anticounter/AnticounterEvent.h> |
14 |
#include <physics/trigger/TriggerEvent.h> |
15 |
#include <physics/neutronDetector/NeutronEvent.h> |
16 |
#include "physics/neutronDetector/NeutronRecord.h" |
17 |
#include <mcmd/McmdEvent.h> |
18 |
#include <mcmd/McmdRecord.h> |
19 |
#include <EventHeader.h> |
20 |
#include <PscuHeader.h> |
21 |
#include <TTree.h> |
22 |
#include "sgp4.h" |
23 |
#include "TH2F.h" |
24 |
#include "TFrame.h" |
25 |
#include "TGraph.h" |
26 |
#include "TCanvas.h" |
27 |
#include "TASImage.h" |
28 |
#include <TDatime.h> |
29 |
#include <TFile.h> |
30 |
|
31 |
#include <TTimeStamp.h> |
32 |
#include "TString.h" |
33 |
#include "TObjString.h" |
34 |
#include "TStyle.h" |
35 |
#include "TPaletteAxis.h" |
36 |
#include "TROOT.h" |
37 |
#include <sys/stat.h> |
38 |
#include <fstream> |
39 |
#include <iostream> |
40 |
|
41 |
#include <OrbitalRate.h> |
42 |
|
43 |
using namespace std; |
44 |
|
45 |
int main(int argc, char* argv[]){ |
46 |
TString *rootFile = NULL; |
47 |
TString outDir = "./"; |
48 |
TString mapFile = ""; |
49 |
TString tleFile = ""; |
50 |
int offDate = 20060928; |
51 |
// int offDate = 20060614; |
52 |
int offTime = 210000; |
53 |
bool field = false; |
54 |
|
55 |
if (argc < 2){ |
56 |
printf("You have to insert at least the file to analyze and the mapFile \n"); |
57 |
printf("Try '--help' for more information. \n"); |
58 |
exit(1); |
59 |
} |
60 |
|
61 |
if (!strcmp(argv[1], "--help")){ |
62 |
printf( "Usage: OrbitRate FILE -map mapFile [OPTION] \n"); |
63 |
printf( "mapFile have to be a mercator map image [gif|jpg|png] \n"); |
64 |
printf( "\t --help Print this help and exit \n"); |
65 |
printf( "\t -tle[File path] Path where to find the tle infos \n"); |
66 |
printf( "\t\tUse the script retrieve_TLE.sh to create the file.\n "); |
67 |
printf( "\t -outDir[path] Path where to put the output.\n"); |
68 |
printf( "\t -offDate Date of resetting of the Resource counter [format YYMMDD (UTC date) default 20060928] \n"); |
69 |
printf( "\t -offTime Time of resetting of the Resource counter [format HHMMSS (UTC date) default 210000] \n"); |
70 |
printf( "\t -field Produce maps of the magnetic field \n"); |
71 |
exit(1); |
72 |
} |
73 |
|
74 |
// Ok, here we should have at least one root file. We check that |
75 |
// the filename contains ".root". |
76 |
if(strstr(argv[1], ".root")) |
77 |
rootFile = new TString(argv[1]); |
78 |
else { |
79 |
cerr << "OrbitalRate: no root file." << endl << "See --help" << endl; |
80 |
exit(EXIT_FAILURE); |
81 |
} |
82 |
|
83 |
for (int i = 2; i < argc; i++){ |
84 |
if (!strcmp(argv[i], "-field")){ |
85 |
field = true; |
86 |
i++; |
87 |
continue; |
88 |
} |
89 |
|
90 |
if (!strcmp(argv[i], "-outDir")){ |
91 |
if (++i >= argc){ |
92 |
printf( "-outDir needs arguments. \n"); |
93 |
printf( "Try '--help' for more information. \n"); |
94 |
exit(1); |
95 |
} else { |
96 |
outDir = argv[i]; |
97 |
continue; |
98 |
} |
99 |
} |
100 |
|
101 |
if (!strcmp(argv[i], "-tle")){ |
102 |
if (++i >= argc){ |
103 |
printf( "-tle needs arguments. \n"); |
104 |
printf( "Try '--help' for more information. \n"); |
105 |
exit(1); |
106 |
} else { |
107 |
tleFile = argv[i]; |
108 |
continue; |
109 |
} |
110 |
} |
111 |
|
112 |
if (!strcmp(argv[i], "-offTime")){ |
113 |
if (++i >= argc){ |
114 |
printf( "-offTime needs arguments. \n"); |
115 |
printf( "Try '--help' for more information. \n"); |
116 |
exit(1); |
117 |
} |
118 |
else{ |
119 |
offTime = atol(argv[i]); |
120 |
continue; |
121 |
} |
122 |
} |
123 |
|
124 |
if (!strcmp(argv[i], "-offDate")){ |
125 |
if (++i >= argc){ |
126 |
printf( "-offDate needs arguments. \n"); |
127 |
printf( "Try '--help' for more information. \n"); |
128 |
exit(1); |
129 |
} |
130 |
else{ |
131 |
offDate = atol(argv[i]); |
132 |
continue; |
133 |
} |
134 |
} |
135 |
|
136 |
if (!strcmp(argv[i], "-map")){ |
137 |
if (++i >= argc){ |
138 |
printf( "-map needs arguments. \n"); |
139 |
printf( "Try '--help' for more information. \n"); |
140 |
exit(1); |
141 |
} else { |
142 |
mapFile = argv[i]; |
143 |
continue; |
144 |
} |
145 |
} |
146 |
} |
147 |
|
148 |
if (mapFile != ""){ |
149 |
Rate(rootFile, outDir, mapFile, tleFile, offDate, offTime, field); |
150 |
} else { |
151 |
printf("You have to insert at least the file to analyze and the mapFile \n"); |
152 |
printf("Try '--help' for more information. \n"); |
153 |
} |
154 |
} |
155 |
|
156 |
|
157 |
void InitStyle() { |
158 |
gROOT->SetStyle("Plain"); |
159 |
|
160 |
TStyle *myStyle[2], *tempo; |
161 |
myStyle[0]=new TStyle("StyleWhite", "white"); |
162 |
myStyle[1]=new TStyle("StyleBlack", "black"); |
163 |
|
164 |
tempo=gStyle; |
165 |
Int_t linecol, bkgndcol, histcol; |
166 |
|
167 |
for(Int_t style=0; style<2; style++) { |
168 |
|
169 |
linecol=kWhite*style+kBlack*(1-style); |
170 |
bkgndcol=kBlack*style+kWhite*(1-style); |
171 |
histcol=kYellow*style+kBlack*(1-style); // was 95 |
172 |
|
173 |
myStyle[style]->Copy(*tempo); |
174 |
|
175 |
myStyle[style]->SetCanvasBorderMode(0); |
176 |
myStyle[style]->SetCanvasBorderSize(1); |
177 |
myStyle[style]->SetFrameBorderSize(1); |
178 |
myStyle[style]->SetFrameBorderMode(0); |
179 |
myStyle[style]->SetPadBorderSize(1); |
180 |
myStyle[style]->SetStatBorderSize(1); |
181 |
myStyle[style]->SetTitleBorderSize(1); |
182 |
myStyle[style]->SetPadBorderMode(0); |
183 |
myStyle[style]->SetPalette(1,0); |
184 |
myStyle[style]->SetPaperSize(20,27); |
185 |
myStyle[style]->SetFuncColor(kRed); |
186 |
myStyle[style]->SetFuncWidth(1); |
187 |
myStyle[style]->SetLineScalePS(1); |
188 |
myStyle[style]->SetCanvasColor(bkgndcol); |
189 |
myStyle[style]->SetAxisColor(linecol,"XYZ"); |
190 |
myStyle[style]->SetFrameFillColor(bkgndcol); |
191 |
myStyle[style]->SetFrameLineColor(linecol); |
192 |
myStyle[style]->SetLabelColor(linecol,"XYZ"); |
193 |
myStyle[style]->SetPadColor(bkgndcol); |
194 |
myStyle[style]->SetStatColor(bkgndcol); |
195 |
myStyle[style]->SetStatTextColor(linecol); |
196 |
myStyle[style]->SetTitleColor(linecol,"XYZ"); |
197 |
myStyle[style]->SetTitleFillColor(bkgndcol); |
198 |
myStyle[style]->SetTitleTextColor(linecol); |
199 |
myStyle[style]->SetLineColor(linecol); |
200 |
myStyle[style]->SetMarkerColor(histcol); |
201 |
myStyle[style]->SetTextColor(linecol); |
202 |
|
203 |
myStyle[style]->SetGridColor((style)?13:kBlack); |
204 |
myStyle[style]->SetHistFillStyle(1001*(1-style)); |
205 |
myStyle[style]->SetHistLineColor(histcol); |
206 |
myStyle[style]->SetHistFillColor((style)?bkgndcol:kYellow); |
207 |
|
208 |
myStyle[style]->SetOptStat(0); // Remove statistic summary |
209 |
} |
210 |
|
211 |
myStyle[1]->cd(); |
212 |
|
213 |
gROOT->ForceStyle(); |
214 |
|
215 |
} |
216 |
|
217 |
|
218 |
void Rate(TString *filename, TString outDirectory = "", TString mapFile = "", TString tleFile = "", int offDate = 20060614, int offTime = 210000, bool field = false) |
219 |
{ |
220 |
// **** Offset to temporarily correct the TDatime bug ****/ |
221 |
// offTime += 10000; |
222 |
//********************************************************/ |
223 |
|
224 |
TTree *tr = 0; |
225 |
TFile *rootFile; |
226 |
FILE *f; |
227 |
|
228 |
pamela::McmdEvent *mcmdev = 0; |
229 |
pamela::McmdRecord *mcmdrc = 0; |
230 |
pamela::EventHeader *eh = 0; |
231 |
pamela::PscuHeader *ph = 0; |
232 |
TArrayC *mcmddata; |
233 |
ULong64_t nevents = 0; |
234 |
stringstream oss; |
235 |
|
236 |
Float_t timesync = 0, obt_timesync = 0; |
237 |
Long64_t offsetTime = 0; |
238 |
Long64_t timeElapsedFromTLE = 0; |
239 |
Long64_t deltaTime = 0, oldtimeElapsedFromTLE = 0; |
240 |
bool a_second_is_over; |
241 |
|
242 |
Float_t lon, lat, alt; |
243 |
|
244 |
vector<Double_t> vector_trigAndOr; |
245 |
vector<Double_t> vector_trigAndAnd; |
246 |
vector<Double_t> vector_trigS11andS12; |
247 |
vector<Double_t> vector_trigS12andS21andS22; |
248 |
vector<Double_t> vector_trigS111A; |
249 |
|
250 |
double mean_trigAndOr; |
251 |
double mean_trigAndAnd; |
252 |
double mean_trigS11andS12; |
253 |
double mean_trigS12andS21andS22; |
254 |
double mean_trigS111A; |
255 |
|
256 |
// We'll use this size for the generated images. |
257 |
TImage *tImage=TImage::Open(mapFile); |
258 |
int width=(int)(tImage->GetWidth()*0.80); |
259 |
int height=(int)(tImage->GetHeight()*0.80); |
260 |
delete tImage; |
261 |
|
262 |
// This histogram will store time (in seconds) spent in each bin. |
263 |
TH2F *obtBinTime = new TH2F("obtBinTime", "Time of acquisition of background data", 360, -180, 180, 180, -90, 90); |
264 |
|
265 |
// Now I create histograms longitude x latitude to hold values. I |
266 |
// use the suffix _counter to say that this values are what I read |
267 |
// from Pamela and they are not normalized in any way. |
268 |
|
269 |
// This historam will store the number of events occurred in each bin. |
270 |
TH2F *event_counter = new TH2F("event_counter", "Event rate", 360, -180, 180, 180, -90, 90); |
271 |
TH2F *nd_counter = new TH2F("nd_counter", "Upper background neutrons", 360, -180, 180, 180, -90, 90); |
272 |
TH2F *antiCAS4_counter = new TH2F("CAS4_counter", "CAS4 rate", 360, -180, 180, 180, -90, 90); |
273 |
TH2F *antiCAS3_counter = new TH2F("CAS3_counter", "CAS3 rate", 360, -180, 180, 180, -90, 90); |
274 |
TH2F *trigAndOr_counter = new TH2F("trigAndOr_counter", "Rate of triggering in (S11+S12)*(S21+S22)*(S31+S32) configuration", 360, -180, 180, 180, -90, 90); |
275 |
TH2F *trigAndAnd_counter = new TH2F("trigAndAnd_counter", "Rate of triggering in (S11*S12)*(S21*S22)*(S31*S32) configuration", 360, -180, 180, 180, -90, 90); |
276 |
TH2F *trigS11andS12_counter = new TH2F("trigS11andS12_counter", "Rate of S1 triggers", 360, -180, 180, 180, -90, 90); //(S11+S12) |
277 |
TH2F *trigS12andS21andS22_counter = new TH2F("trigS12andS21andS22_counter", "Rate of S11*S21*S21 triggers", 360, -180, 180, 180, -90, 90); //(S11*S12*S21) |
278 |
TH2F *trigS111A_counter = new TH2F("trigS111A_counter", "Rate of S111A counts", 360, -180, 180, 180, -90, 90); //(S111A) |
279 |
|
280 |
// Magnetic field histograms. I use always the suffix _counter |
281 |
// because they are not normalized. Imagine that an instrument |
282 |
// give us the value of the magnetic field for each event. |
283 |
TH2F *hbabs_counter; |
284 |
TH2F *hbnorth_counter; |
285 |
TH2F *hbdown_counter; |
286 |
TH2F *hbeast_counter; |
287 |
TH2F *hb0_counter; |
288 |
TH2F *hl_counter; |
289 |
|
290 |
if(field) { |
291 |
hbabs_counter = new TH2F("hbabs_counter", "B module", 360, -180, 180, 180, -90, 90); |
292 |
hbnorth_counter = new TH2F("hbnorth_counter", "B north", 360, -180, 180, 180, -90, 90); |
293 |
hbdown_counter = new TH2F("hbdown_counter", "B down", 360, -180, 180, 180, -90, 90); |
294 |
hbeast_counter = new TH2F("hbeast_counter", "B east", 360, -180, 180, 180, -90, 90); |
295 |
hb0_counter = new TH2F("hb0_counter", "B_0", 360, -180, 180, 180, -90, 90); |
296 |
hl_counter = new TH2F("hl_counter", "l", 360, -180, 180, 180, -90, 90); |
297 |
} |
298 |
|
299 |
// Get a char* to "file" from "/dir1/dir2/.../file.root" |
300 |
TString basename; |
301 |
basename = ((TObjString*) filename->Tokenize('/')->Last())->GetString(); // we get file.root |
302 |
basename = ((TObjString*)basename.Tokenize('.')->First())->GetString(); // we get file |
303 |
|
304 |
// Exit if the map file doesn't exist. |
305 |
if(! (f = fopen(mapFile.Data(), "r")) ) { |
306 |
cerr << "Error: the file " << mapFile.Data() << " does not exists." << endl; |
307 |
exit(EXIT_FAILURE); |
308 |
} |
309 |
|
310 |
// Open the root file. |
311 |
rootFile = new TFile(filename->Data()); |
312 |
if (rootFile->IsZombie()) { |
313 |
printf("The file %s does not exist\n", (filename->Data())); |
314 |
exit(EXIT_FAILURE); |
315 |
} |
316 |
|
317 |
// Look for a timesync in the TFile rootFile. We also get the obt |
318 |
// of the timesync mcmd. |
319 |
bool err; |
320 |
err = lookforTimesync(rootFile, ×ync, &obt_timesync); |
321 |
if(!err) { |
322 |
cerr << "Warning!!! No timesync info has been found in the file " |
323 |
<< filename->Data() << endl; |
324 |
exit(EXIT_FAILURE); |
325 |
} |
326 |
|
327 |
// Here I do: resurs offset + timesync |
328 |
TDatime offRes = TDatime(offDate, offTime); |
329 |
TTimeStamp offResTS = TTimeStamp(offRes.GetYear(), offRes.GetMonth(), offRes.GetDay(), offRes.GetHour(), offRes.GetMinute(), offRes.GetSecond(), 0, kTRUE, timesync); |
330 |
// cout<<"timesync="<<timesync<<" obt_timesync="<<obt_timesync<<endl; |
331 |
// cout<<"offResTS.GetSec()="<<offResTS.GetSec()<<endl; |
332 |
// cout<<"offResTS.AsString()="<<offResTS.AsString()<<endl<<endl; |
333 |
|
334 |
// Now I need a pointer to a cTle object. The class misses a |
335 |
// constructor without arguments, so we have to give it a dummy TLE. |
336 |
string str1 = "RESURS-DK 1"; |
337 |
string str2 = "1 29228U 06021A 06170.19643714 .00009962 00000-0 21000-3 0 196"; |
338 |
string str3 = "2 29228 069.9363 054.7893 0167576 127.4359 017.0674 15.31839265 604"; |
339 |
cTle *tle1 = new cTle(str1, str2, str3); |
340 |
|
341 |
// If we have to use a TLE file, call getTle(). |
342 |
if (tleFile != "") |
343 |
tle1 = getTle(tleFile, offResTS); // modify getTle() to use offResTS! |
344 |
else |
345 |
cout<<"OrbitalRate: Warning!!! No tle file supplied.\n"; |
346 |
|
347 |
// Here I do: resurs offset + timesync - obt of the timesync |
348 |
// cout<<"here0 "<<offResTS.GetSec()<<endl; |
349 |
// offResTS.Set(offResTS.GetSec() - obt_timesync, kTRUE, 0, kFALSE); |
350 |
offResTS.Set(offResTS.GetSec() - obt_timesync, kFALSE, 0, kFALSE); |
351 |
// cout<<"here1 "<<offResTS.GetSec()<<endl; |
352 |
|
353 |
cOrbit orbit(*tle1); |
354 |
cEci eci; |
355 |
cCoordGeo coo; |
356 |
|
357 |
// Here I do: resurs offset + timesync - obt of the timesync - tle time |
358 |
TTimeStamp tledate = getTleDatetime(tle1); |
359 |
cJulian jdatetime = cJulian((int) (tle1->getField(cTle::FLD_EPOCHYEAR)+2e3), tle1->getField(cTle::FLD_EPOCHDAY)); |
360 |
int pYear, pMon; double pDOM; |
361 |
jdatetime.getComponent(&pYear, &pMon, &pDOM); |
362 |
offsetTime = ((Long64_t) offResTS.GetSec() - (Long64_t) tledate.GetSec()); |
363 |
// cerr<<"offsetTime="<<offsetTime<<endl |
364 |
// <<"offResTS.GetSec()="<<offResTS.GetSec()<<endl |
365 |
// <<"tledate.GetSec()="<<tledate.GetSec()<<endl<<endl; |
366 |
|
367 |
/********** Magnetic Field **************/ |
368 |
// Check that all this is correct! |
369 |
float br, btheta, bphi; |
370 |
|
371 |
// I can now compute the magnetic dipole moment at the actual date, |
372 |
// using the cJulian date. I don't to recompute it for every event |
373 |
// beacause changes are not relevant at all. |
374 |
UInt_t y, m, d; |
375 |
tledate.GetDate(kTRUE, 0, &y, &m, &d); |
376 |
float year = (float) y + (m*31+d)/365; |
377 |
|
378 |
// Initialize common data for geopack |
379 |
if(field) |
380 |
recalc_(y, m*31+d, 0, 0, 0); |
381 |
/********** Magnetic Field **************/ |
382 |
|
383 |
tr = (TTree*)rootFile->Get("Physics"); |
384 |
TBranch *headBr = tr->GetBranch("Header"); |
385 |
tr->SetBranchAddress("Header", &eh); |
386 |
|
387 |
/********** Anticounter **************/ |
388 |
pamela::anticounter::AnticounterEvent *antiev = 0; |
389 |
tr->SetBranchAddress("Anticounter", &antiev); |
390 |
|
391 |
Int_t oldCAS4 = 0; |
392 |
Int_t diffCAS4 = 0; |
393 |
Int_t oldCAS3 = 0; |
394 |
Int_t diffCAS3 = 0; |
395 |
/********** Anticounter **************/ |
396 |
|
397 |
/********** Trigger **************/ |
398 |
pamela::trigger::TriggerEvent *trigger = 0; |
399 |
tr->SetBranchAddress("Trigger", &trigger); |
400 |
|
401 |
Int_t oldtrigAndOr = 0; |
402 |
Int_t oldtrigAndAnd = 0; |
403 |
Int_t oldtrigS11andS12 = 0; |
404 |
Int_t oldtrigS12andS21andS22 = 0; |
405 |
Int_t oldtrigS111A = 0; |
406 |
/********** Trigger **************/ |
407 |
|
408 |
/********** ND **************/ |
409 |
Int_t tmpSize=0; |
410 |
Int_t sumTrig=0; |
411 |
Int_t sumUpperBackground=0; |
412 |
Int_t sumBottomBackground=0; |
413 |
|
414 |
pamela::neutron::NeutronRecord *nr = 0; |
415 |
pamela::neutron::NeutronEvent *ne = 0; |
416 |
tr->SetBranchAddress("Neutron", &ne); |
417 |
/********** ND **************/ |
418 |
|
419 |
nevents = tr->GetEntries(); |
420 |
|
421 |
for(UInt_t i = 0; i < nevents; i++) //Fill variables from root-ple |
422 |
{ |
423 |
tr->GetEntry(i); |
424 |
ph = eh->GetPscuHeader(); |
425 |
|
426 |
// obt in ms |
427 |
UInt_t obt = (UInt_t) ph->GetOrbitalTime(); |
428 |
|
429 |
// timeElapsedFromTLE is the difference, in seconds, between the |
430 |
// event and the tle date. I use seconds and not milliseconds |
431 |
// because the indetermination on the timesync is about 1s. |
432 |
timeElapsedFromTLE = offsetTime + obt/1000; |
433 |
if(!i) cerr<<"1st event: timeElapsedFromTLE="<<timeElapsedFromTLE<<endl; |
434 |
|
435 |
// I also need the abstime in seconds rounded to the lower |
436 |
// value. Every second, we set a_second_is_over to true. Only |
437 |
// in this case histograms with triggers are filled. |
438 |
a_second_is_over = (timeElapsedFromTLE > oldtimeElapsedFromTLE) ? 1 : 0; |
439 |
oldtimeElapsedFromTLE = timeElapsedFromTLE; |
440 |
|
441 |
// I need the acquisition time between two triggers to fill the |
442 |
// obtBinTime (histo of time spent in the bin). The time is in |
443 |
// second. |
444 |
deltaTime = timeElapsedFromTLE - oldtimeElapsedFromTLE; |
445 |
oldtimeElapsedFromTLE = timeElapsedFromTLE; |
446 |
|
447 |
// Finally, we get coordinates from absolute time the orbit |
448 |
// object initialised with the TLE data. cOrbit::getPosition() |
449 |
// requires the elapased time from the tle in minutes. |
450 |
// Coordinates are stored in the structure eci. |
451 |
orbit.getPosition(((double) timeElapsedFromTLE)/60., &eci); |
452 |
coo = eci.toGeo(); |
453 |
|
454 |
/********** ND **************/ |
455 |
// Summing over all stored pamela::neutron::NeutronRecords in |
456 |
// this event *ne. |
457 |
for(Int_t j = 0; j < ne->Records->GetEntries(); j++) { |
458 |
nr = (pamela::neutron::NeutronRecord*)ne->Records->At(j); |
459 |
sumTrig += (int)nr->trigPhysics; |
460 |
sumUpperBackground += (int)nr->upperBack; |
461 |
sumBottomBackground += (int)nr->bottomBack; |
462 |
} |
463 |
/********** ND **************/ |
464 |
|
465 |
/********** Anticounter **************/ |
466 |
// Get the difference between the actual counter and the |
467 |
// previous counter for anticoincidence, dealing with the |
468 |
// overflow with solve_ac_overflow(). |
469 |
diffCAS4 = solve_ac_overflow(oldCAS4, antiev->counters[0][6]); |
470 |
diffCAS3 = solve_ac_overflow(oldCAS3, antiev->counters[0][10]); |
471 |
/********** Anticounter **************/ |
472 |
|
473 |
// Build coordinates in the right range. We want to convert, |
474 |
// just for aesthetic, longitude from (0, 2*pi) to (-pi, pi). |
475 |
// We also want to convert from radians to degrees. |
476 |
lon = (coo.m_Lon > PI) ? rad2deg(coo.m_Lon - 2*PI) : rad2deg(coo.m_Lon); |
477 |
lat = rad2deg(coo.m_Lat); |
478 |
alt = coo.m_Alt; |
479 |
|
480 |
/********** Magnetic Field **************/ |
481 |
if(field) |
482 |
igrf_geo__((coo.m_Alt+6371.2)/6371.2, M_PI/2.-coo.m_Lat, coo.m_Lon, br, btheta, bphi); |
483 |
// cout<<"("<<(coo.m_Alt+6371.2)/6371.2<<", "<<M_PI/2.-coo.m_Lat<<", "<<coo.m_Lon<<")"<<endl; |
484 |
/********** Magnetic Field **************/ |
485 |
|
486 |
// serve fare il controllo deltatime < 1? |
487 |
if (deltaTime > 1) cout << endl << "******** deltaTime<1 ********" << endl; |
488 |
// Does nothing for the first two events or if acquisition time if more |
489 |
// than 1s. |
490 |
if(i<1 || (deltaTime > 1)) continue; |
491 |
|
492 |
// CAS3 and CAS4 are not rates but only counters. So I fill |
493 |
// with the bin with the difference beetween the actual counter |
494 |
// and the previous one and then divide with the time (see |
495 |
// below) to have rates. |
496 |
if(diffCAS3>1e3) // additional cut to avoid the peaks after dead time |
497 |
diffCAS3 = (Int_t) antiCAS3_counter->GetBinContent((Int_t)antiCAS3_counter->GetEntries()-1); |
498 |
antiCAS3_counter->Fill(lon , lat, diffCAS3); |
499 |
|
500 |
if(diffCAS4>1e3) // additional cut to avoid the peaks after dead time |
501 |
diffCAS4 = (Int_t) antiCAS4_counter->GetBinContent((Int_t) antiCAS4_counter->GetEntries()-1); |
502 |
antiCAS4_counter->Fill(lon, lat, diffCAS4); |
503 |
|
504 |
// Magnetic field values should be handled a bit carefully. |
505 |
// For every event I get a position and the related magnetic |
506 |
// field values. I can fill the histograms lon x lat with |
507 |
// this values but I need to count how many times I fill |
508 |
// each bin. This is done by the histogram event_counter. |
509 |
// I will normalize later. |
510 |
if(field) { |
511 |
hbabs_counter->Fill(lon, lat, sqrt(br*br+btheta*btheta+bphi*bphi)*1e-5); |
512 |
hbnorth_counter->Fill(lon, lat, -btheta*1e-5); |
513 |
hbdown_counter->Fill(lon, lat, -br*1e-5); |
514 |
hbeast_counter->Fill(lon, lat, bphi*1e-5); |
515 |
} |
516 |
// This histograms is now filled with the number of entries. |
517 |
// Below we will divide with the time (in seconds) to get |
518 |
// event rate per bin. |
519 |
event_counter->Fill(lon, lat); |
520 |
|
521 |
// counters about triggers are already rates (Hz). Only |
522 |
// every second we fill fill with the mean over all values. |
523 |
if(a_second_is_over) { |
524 |
// This histograms will hold the time, in seconds, spent |
525 |
// in the bin. |
526 |
obtBinTime->Fill(lon, lat, 1); |
527 |
|
528 |
// get the means |
529 |
mean_trigAndOr = getMean(vector_trigAndOr); |
530 |
mean_trigAndAnd = getMean(vector_trigAndAnd); |
531 |
mean_trigS11andS12 = getMean(vector_trigS11andS12); |
532 |
mean_trigS12andS21andS22 = getMean(vector_trigS12andS21andS22); |
533 |
mean_trigS111A = getMean(vector_trigS111A); |
534 |
|
535 |
// clear data about the last second |
536 |
vector_trigAndOr.clear(); |
537 |
vector_trigAndAnd.clear(); |
538 |
vector_trigS11andS12.clear(); |
539 |
vector_trigS12andS21andS22.clear(); |
540 |
vector_trigS111A.clear(); |
541 |
|
542 |
// Fill with the mean rate value |
543 |
trigAndOr_counter->Fill(lon , lat, mean_trigAndOr); |
544 |
trigAndAnd_counter->Fill(lon , lat, mean_trigAndAnd); |
545 |
trigS11andS12_counter->Fill(lon , lat, mean_trigS11andS12); |
546 |
trigS12andS21andS22_counter->Fill(lon , lat, mean_trigS12andS21andS22); |
547 |
trigS111A_counter->Fill(lon, lat, mean_trigS111A); |
548 |
} |
549 |
else { // Collect values for all the second |
550 |
vector_trigAndOr.push_back((1/4.)*trigger->trigrate[0]); |
551 |
vector_trigAndAnd.push_back((1/4.)*trigger->trigrate[1]); |
552 |
// pmtpl[0] is the rate every 60ms but I want Hz. |
553 |
vector_trigS11andS12.push_back((1000./60.)*trigger->pmtpl[0]); |
554 |
vector_trigS12andS21andS22.push_back((1/4.)*trigger->trigrate[4]); |
555 |
vector_trigS111A.push_back(1.*trigger->pmtcount1[0]); |
556 |
} |
557 |
|
558 |
// Now we discard ND data if: |
559 |
// - NeutronEvent is corrupted. |
560 |
if((ne->unpackError != 1)) |
561 |
nd_counter->Fill(lon, lat, 1.*(sumUpperBackground+sumTrig)); |
562 |
|
563 |
// Reset counters for ND. |
564 |
sumTrig = 0; |
565 |
sumUpperBackground = 0; |
566 |
sumBottomBackground = 0; |
567 |
} |
568 |
|
569 |
// We now need to normalize the histograms to print something |
570 |
// meaningful. I create similar histograms with the suffix _rate or |
571 |
// _norm. |
572 |
TH2F *event_rate = (TH2F*) event_counter->Clone("event_rate"); |
573 |
TH2F *trigS111A_rate = (TH2F*) trigS111A_counter->Clone("trigS111A_rate"); |
574 |
TH2F *antiCAS4_rate = (TH2F*) antiCAS4_counter->Clone("antiCAS4_rate"); |
575 |
TH2F *antiCAS3_rate = (TH2F*) antiCAS3_counter->Clone("antiCAS3_rate"); |
576 |
TH2F *trigS11andS12_rate = (TH2F*) trigS11andS12_counter->Clone("trigS11andS12_rate"); |
577 |
TH2F *trigS12andS21andS22_rate = (TH2F*) trigS12andS21andS22_counter->Clone("trigS12andS21andS22_rate"); |
578 |
TH2F *trigAndOr_rate = (TH2F*) trigAndOr_counter->Clone("trigAndOr_rate"); |
579 |
TH2F *trigAndAnd_rate = (TH2F*) trigAndAnd_counter->Clone("trigAndAnd_rate"); |
580 |
TH2F *nd_rate = (TH2F*) nd_counter->Clone("nd_rate"); |
581 |
|
582 |
TH2F *hbabs_norm; |
583 |
TH2F *hbnorth_norm; |
584 |
TH2F *hbdown_norm; |
585 |
TH2F *hbeast_norm; |
586 |
|
587 |
if(field) { |
588 |
hbabs_norm = (TH2F*) hbabs_counter->Clone("hbabs_norm"); |
589 |
hbnorth_norm = (TH2F*) hbnorth_counter->Clone("hbnorth_norm"); |
590 |
hbdown_norm = (TH2F*) hbabs_counter->Clone("hbdown_norm"); |
591 |
hbeast_norm = (TH2F*) hbabs_counter->Clone("hbeast_norm"); |
592 |
} |
593 |
|
594 |
// Now we divide each histogram _counter with the time histogram |
595 |
// obtBinTime to have an histogram _rate. Note that, when a second |
596 |
// is passed in the above cycle, we fill the histogram obtBinTime |
597 |
// with 1 (second) together with all the other histograms. So |
598 |
// dividing here does make sense. |
599 |
// |
600 |
// Then we call printHist() for each filled TH2F. These are |
601 |
// refered to the root file we're now reading. We also build up a |
602 |
// filename to be passed to the function. Pay attention that the |
603 |
// filename must end with a file format (such as .png or .pdf) |
604 |
// recognised by TPad::SaveAs(). |
605 |
trigS111A_rate->Divide(trigS111A_counter, obtBinTime, 1, 1, ""); |
606 |
oss.str(""); |
607 |
oss << basename.Data() << "_orbit_trigS111A.png"; |
608 |
trigS111A_rate->SetMinimum(9); |
609 |
printHist(trigS111A_rate, mapFile, outDirectory, oss.str().c_str(), "S111A (Hz)", -width, height, true, 0); |
610 |
|
611 |
antiCAS4_rate->Divide(antiCAS4_counter, obtBinTime, 1, 1, ""); |
612 |
oss.str(""); |
613 |
oss << basename.Data() << "_orbit_CAS4.png"; |
614 |
antiCAS4_rate->SetMinimum(99); |
615 |
printHist(antiCAS4_rate, mapFile, outDirectory, oss.str().c_str(), "CAS4 (Hz)", -width, height, true, 0); |
616 |
|
617 |
antiCAS3_rate->Divide(antiCAS3_counter, obtBinTime, 1, 1, ""); |
618 |
oss.str(""); |
619 |
oss << basename.Data() << "_orbit_CAS3.png"; |
620 |
antiCAS3_rate->SetMinimum(99); |
621 |
printHist(antiCAS3_rate, mapFile, outDirectory, oss.str().c_str(), "CAS3 (Hz)", -width, height, true, 0); |
622 |
|
623 |
event_rate->Divide(event_counter, obtBinTime, 1, 1, ""); |
624 |
oss.str(""); |
625 |
oss << basename.Data() << "_orbit_EventRate.png"; |
626 |
printHist(event_rate, mapFile, outDirectory, oss.str().c_str(), "Event rate (Hz)", -width, height, 0, 0); |
627 |
|
628 |
trigS11andS12_rate->Divide(trigS11andS12_counter, obtBinTime, 1, 1, ""); |
629 |
oss.str(""); |
630 |
oss << basename.Data() << "_orbit_trigS11andS12.png"; |
631 |
trigS11andS12_rate->SetMinimum(99); |
632 |
printHist(trigS11andS12_rate, mapFile, outDirectory, oss.str().c_str(), "(S11*S12) (Hz)", -width, height, 1, 0); |
633 |
|
634 |
trigS12andS21andS22_rate->Divide(trigS12andS21andS22_counter, obtBinTime, 1, 1, ""); |
635 |
oss.str(""); |
636 |
oss << basename.Data() << "_orbit_trigS12andS21andS22.png"; |
637 |
trigS12andS21andS22_rate->SetMinimum(9); |
638 |
printHist(trigS12andS21andS22_rate, mapFile, outDirectory, oss.str().c_str(), "(S12*S12*S21) (Hz)", -width, height, true, 0); |
639 |
|
640 |
trigAndOr_rate->Divide(trigAndOr_counter, obtBinTime, 1, 1, ""); |
641 |
oss.str(""); |
642 |
oss << basename.Data() << "_orbit_trigANDofOR.png"; |
643 |
printHist(trigAndOr_rate, mapFile, outDirectory, oss.str().c_str(), "(S11+S12)*(S21+S22)*(S31+S32) (Hz)", -width, height, 0, 0); |
644 |
|
645 |
trigAndAnd_rate->Divide(trigAndAnd_counter, obtBinTime, 1, 1, ""); |
646 |
oss.str(""); |
647 |
oss << basename.Data() << "_orbit_trigANDofAND.png"; |
648 |
printHist(trigAndAnd_rate, mapFile, outDirectory, oss.str().c_str(), "(S11*S12)*(S21*S22)*(S31*S32) (Hz)", -width, height, 0, 0); |
649 |
|
650 |
nd_rate->Divide(nd_counter, obtBinTime, 1, 1, ""); |
651 |
oss.str(""); |
652 |
oss << basename.Data() << "_orbit_ND.png"; |
653 |
printHist(nd_rate, mapFile, outDirectory, oss.str().c_str(), "Neutron rate (Hz)", -width, height, 0, 0); |
654 |
|
655 |
// Also normalize histograms about magnetic fields. Beacause we |
656 |
// fill the bins with the values of the magnetic field for each |
657 |
// event, we need to divide with the number of fills done, that is |
658 |
// event_counter. |
659 |
if(field) { |
660 |
hbabs_norm->Divide(hbabs_counter, event_counter, 1, 1, ""); |
661 |
oss.str(""); |
662 |
oss << basename.Data() << "_orbit_Babs.png"; |
663 |
printHist(hbabs_norm, mapFile, outDirectory, oss.str().c_str(), "B abs (G)", -width, height, 0, 0); |
664 |
|
665 |
hbnorth_norm->Divide(hbnorth_counter, event_counter, 1, 1, ""); |
666 |
oss.str(""); |
667 |
oss << basename.Data() << "_orbit_Bnorth.png"; |
668 |
printHist(hbnorth_norm, mapFile, outDirectory, oss.str().c_str(), "B north (G)", -width, height, 0, 1); |
669 |
|
670 |
hbdown_norm->Divide(hbdown_counter, event_counter, 1, 1, ""); |
671 |
oss.str(""); |
672 |
oss << basename.Data() << "_orbit_Bdown.png"; |
673 |
printHist(hbdown_norm, mapFile, outDirectory, oss.str().c_str(), "B down (G)", -width, height, 0, 1); |
674 |
|
675 |
hbeast_norm->Divide(hbeast_counter, event_counter, 1, 1, ""); |
676 |
oss.str(""); |
677 |
oss << basename.Data() << "_orbit_Beast.png"; |
678 |
printHist(hbeast_norm, mapFile, outDirectory, oss.str().c_str(), "B east (G)", -width, height, 0, 1); |
679 |
} |
680 |
|
681 |
delete obtBinTime; |
682 |
delete event_counter; |
683 |
|
684 |
delete nd_counter; |
685 |
delete antiCAS4_counter; |
686 |
delete antiCAS3_counter; |
687 |
delete trigAndOr_counter; |
688 |
delete trigAndAnd_counter; |
689 |
delete trigS11andS12_counter; |
690 |
delete trigS111A_counter; |
691 |
delete trigS12andS21andS22_counter; |
692 |
|
693 |
delete event_rate; |
694 |
delete nd_rate; |
695 |
delete antiCAS4_rate; |
696 |
delete antiCAS3_rate; |
697 |
delete trigAndOr_rate; |
698 |
delete trigAndAnd_rate; |
699 |
delete trigS11andS12_rate; |
700 |
delete trigS111A_rate; |
701 |
delete trigS12andS21andS22_rate; |
702 |
|
703 |
if(field) { |
704 |
delete hbabs_counter; |
705 |
delete hbnorth_counter; |
706 |
delete hbdown_counter; |
707 |
delete hbeast_counter; |
708 |
delete hbabs_norm; |
709 |
delete hbnorth_norm; |
710 |
delete hbdown_norm; |
711 |
delete hbeast_norm; |
712 |
} |
713 |
|
714 |
rootFile->Close(); |
715 |
} |
716 |
|
717 |
|
718 |
// Print the istogram *h on the file outputfilename in the direcotry |
719 |
// outDirectory, using mapFile as background image, sizing the image |
720 |
// width per height. Log scale will be used if use_log is true. |
721 |
// |
722 |
// If bool_shift is true a further process is performed to solve a |
723 |
// problem with actual root version (5.12). This should be used when |
724 |
// the histrogram is filled also with negative values, because root |
725 |
// draws zero filled bins (so I have all the pad colorized and this is |
726 |
// really weird!). To avoid this problem I shift all the values in a |
727 |
// positive range and draw again using colz. Now I will not have zero |
728 |
// filled bins painted but the scale will be wrong. This is why I |
729 |
// need to draw a new axis along the palette. |
730 |
// |
731 |
// Pay attention: you cannot use a mapFile different from the provided |
732 |
// one without adjusting the scaling and position of the image (see |
733 |
// Scale() and Merge()). |
734 |
// |
735 |
// This function depends on InitStyle(); |
736 |
int printHist(TH2F *h, TString mapFile, TString outDirectory, TString outputFilename, const char *title, int width, int height, bool use_log, bool bool_shift) |
737 |
{ |
738 |
InitStyle(); |
739 |
|
740 |
// Create a canvas and draw the TH2F with a nice colormap for z |
741 |
// values, using log scale for z values, if requested, and setting |
742 |
// some title. |
743 |
TCanvas *canvas = new TCanvas("h", "h histogram", width*2, height*2); |
744 |
|
745 |
if(use_log) canvas->SetLogz(); |
746 |
|
747 |
h->SetTitle(title); |
748 |
h->SetXTitle("Longitude (deg)"); |
749 |
h->SetYTitle("Latitude (deg)"); |
750 |
h->SetLabelColor(0, "X"); |
751 |
h->SetAxisColor(0, "X"); |
752 |
h->SetLabelColor(0, "Y"); |
753 |
h->SetAxisColor(0, "Y"); |
754 |
h->SetLabelColor(0, "Z"); |
755 |
h->SetAxisColor(0, "Z"); |
756 |
|
757 |
h->Draw("colz"); |
758 |
canvas->Update(); // Update! Otherwise we can't get any palette. |
759 |
|
760 |
// If shift in a positive range required (see comment above). |
761 |
if(bool_shift) { |
762 |
// Remember the minimum and maximum in this graph. |
763 |
Float_t min = h->GetMinimum(); |
764 |
Float_t max = h->GetMaximum(); |
765 |
|
766 |
// Shift the graph up by 100. Increase the value if you still get |
767 |
// negative filled bins. |
768 |
h = shiftHist(h, 100.0); |
769 |
h->SetMinimum(min+100.0); |
770 |
h->SetMaximum(max+100.0); |
771 |
|
772 |
// Hide the current axis of the palette |
773 |
TPaletteAxis *palette = (TPaletteAxis*) h->GetListOfFunctions()->FindObject("palette"); |
774 |
if(!palette) cout << "palette is null" << endl; |
775 |
TGaxis *ax = (TGaxis*) palette->GetAxis(); |
776 |
if(!ax) cout << "ax is null" << endl; |
777 |
ax->SetLabelOffset(999); |
778 |
ax->SetTickSize(0); |
779 |
|
780 |
// Create a new axis of the palette using the right min and max and draw it. |
781 |
TGaxis *gaxis = new TGaxis(palette->GetX2(), palette->GetY1(), palette->GetX2(), palette->GetY2(), min, max, 510,"+L"); |
782 |
gaxis->SetLabelColor(0); |
783 |
gaxis->Draw(); |
784 |
|
785 |
// Update again. |
786 |
canvas->Update(); |
787 |
} |
788 |
|
789 |
// We merge two images: the image of the earth read from a file on |
790 |
// that one of the TPad of canvas (the histogram). The first one is |
791 |
// scaled and adjusted to fit well inside the frame of the second |
792 |
// one. Finally we draw them both. |
793 |
// |
794 |
// Here there's a trick to avoid blurring during the merging |
795 |
// operation. We get the image from a canvas sized (width*2 x |
796 |
// height*2) and draw it on a canvas sized (width x height). |
797 |
|
798 |
TCanvas *mergeCanvas = new TCanvas("", "", width, height); |
799 |
TImage *img = TImage::Create(); |
800 |
TImage *terra = TImage::Create(); |
801 |
img->FromPad(canvas); // get the TCanvas canvas as TImage |
802 |
terra->ReadImage(mapFile, TImage::kPng); // get the png file as TImage |
803 |
terra->Scale(1304,830); |
804 |
img->Merge(terra, "add", 166, 112); // add image terra to image img |
805 |
img->Draw("X"); // see what we get, eXpanding img all over mergeCanvas. |
806 |
|
807 |
stringstream oss; |
808 |
oss << outDirectory.Data() << "/" << outputFilename.Data(); |
809 |
|
810 |
mergeCanvas->SaveAs(oss.str().c_str()); |
811 |
mergeCanvas->Close(); |
812 |
canvas->Close(); |
813 |
|
814 |
return EXIT_SUCCESS; |
815 |
} |
816 |
|
817 |
void saveHist(TH1 *h, TString savetorootfile) |
818 |
{ |
819 |
TFile *file = new TFile(savetorootfile.Data(), "update"); |
820 |
|
821 |
h->Write(); |
822 |
file->Close(); |
823 |
} |
824 |
|
825 |
|
826 |
// Get the TLE from tleFile. The right TLE is that one with the |
827 |
// closest previous date to offRes, that is the date at the time of |
828 |
// the first timesync found in the root file. |
829 |
// |
830 |
// Warning: you must use a tle file obtained by space-track.org |
831 |
// querying the database with the RESURS DK-1 id number 29228, |
832 |
// selecting the widest timespan, including the satellite name in the |
833 |
// results. |
834 |
cTle *getTle(TString tleFile, TTimeStamp offResTS) |
835 |
{ |
836 |
Float_t tledatefromfile, tledatefromroot; |
837 |
fstream tlefile(tleFile.Data(), ios::in); |
838 |
vector<cTle*> ctles; |
839 |
vector<cTle*>::iterator iter; |
840 |
|
841 |
|
842 |
// Build a vector of *cTle |
843 |
while(1) { |
844 |
cTle *tlef; |
845 |
string str1, str2, str3; |
846 |
|
847 |
getline(tlefile, str1); |
848 |
if(tlefile.eof()) break; |
849 |
|
850 |
getline(tlefile, str2); |
851 |
if(tlefile.eof()) break; |
852 |
|
853 |
getline(tlefile, str3); |
854 |
if(tlefile.eof()) break; |
855 |
|
856 |
// We now have three good lines for a cTle. |
857 |
tlef = new cTle(str1, str2, str3); |
858 |
ctles.push_back(tlef); |
859 |
} |
860 |
|
861 |
// Sort by date |
862 |
sort(ctles.begin(), ctles.end(), compTLE); |
863 |
|
864 |
UInt_t year, month, day; |
865 |
offResTS.GetDate(kTRUE, 0, &year, &month, &day); |
866 |
TTimeStamp firstofjan = TTimeStamp(year, 1, 1, 0, 0, 0); |
867 |
tledatefromroot = (year-2000)*1e3 + (offResTS.GetSec() - firstofjan.GetSec())/(24.*3600.); |
868 |
|
869 |
for(iter = ctles.begin(); iter != ctles.end(); iter++) { |
870 |
cTle *tle = *iter; |
871 |
|
872 |
tledatefromfile = getTleJulian(tle); |
873 |
|
874 |
if(tledatefromroot > tledatefromfile) { |
875 |
tlefile.close(); |
876 |
cTle *thisTle = tle; |
877 |
ctles.clear(); |
878 |
|
879 |
return thisTle; |
880 |
} |
881 |
} |
882 |
|
883 |
// File ended withoud founding a TLE with a date after offRes. We'll use the last aviable date. |
884 |
cerr << "Warning: using last available TLE in " << tleFile.Data() << ". Consider updating your tle file." << endl; |
885 |
|
886 |
tlefile.close(); |
887 |
cTle *thisTle = ctles[ctles.size()-1]; |
888 |
ctles.clear(); |
889 |
|
890 |
return thisTle; |
891 |
} |
892 |
|
893 |
|
894 |
// Return whether the first TLE is older than the second |
895 |
bool compTLE (cTle *tle1, cTle *tle2) |
896 |
{ |
897 |
return getTleJulian(tle1) > getTleJulian(tle2); |
898 |
} |
899 |
|
900 |
|
901 |
// Return the date of the tle using the format (year-2000)*1e3 + |
902 |
// julian day. e.g. 6364.5 is the 31th Dec 2006 12:00:00. |
903 |
// It does *not* return a cJulian date. |
904 |
float getTleJulian(cTle *tle) { |
905 |
return tle->getField(cTle::FLD_EPOCHYEAR)*1e3 + tle->getField(cTle::FLD_EPOCHDAY); |
906 |
} |
907 |
|
908 |
|
909 |
// Look for a timesync in the TFile rootFile. Set timesync and |
910 |
// obt_timesync. Returns 1 if timesync is found, 0 otherwise. |
911 |
UInt_t lookforTimesync(TFile *rootFile, Float_t *timesync, Float_t *obt_timesync) { |
912 |
*timesync = -1; // will be != -1 if found |
913 |
|
914 |
ULong64_t nevents = 0; |
915 |
pamela::McmdRecord *mcmdrc = 0; |
916 |
pamela::McmdEvent *mcmdev = 0; |
917 |
TArrayC *mcmddata; |
918 |
TTree *tr = (TTree*) rootFile->Get("Mcmd"); |
919 |
|
920 |
tr->SetBranchAddress("Mcmd", &mcmdev); |
921 |
|
922 |
nevents = tr->GetEntries(); |
923 |
|
924 |
// Looking for a timesync. We stop at the first one found. |
925 |
long int recEntries; |
926 |
|
927 |
for(UInt_t i = 0; i < nevents; i++) { |
928 |
tr->GetEntry(i); |
929 |
recEntries = mcmdev->Records->GetEntries(); |
930 |
|
931 |
for(UInt_t j = 0; j < recEntries; j++) { |
932 |
mcmdrc = (pamela::McmdRecord*)mcmdev->Records->At(j); |
933 |
|
934 |
if ((mcmdrc != 0) && (mcmdrc->ID1 == 0xE0)) //Is it a TimeSync? |
935 |
{ |
936 |
mcmddata = mcmdrc->McmdData; |
937 |
*timesync = (((unsigned int)mcmddata->At(0)<<24)&0xFF000000) |
938 |
+ (((unsigned int)mcmddata->At(1)<<16)&0x00FF0000) |
939 |
+ (((unsigned int)mcmddata->At(2)<<8)&0x0000FF00) |
940 |
+ (((unsigned int)mcmddata->At(3))&0x000000FF); |
941 |
*obt_timesync = (mcmdrc->MCMD_RECORD_OBT)*(1./1000.); |
942 |
|
943 |
goto out; // a timesync is found |
944 |
} |
945 |
} |
946 |
} |
947 |
|
948 |
out: |
949 |
|
950 |
if (*timesync == -1) |
951 |
return 0; |
952 |
else |
953 |
return 1; |
954 |
} |
955 |
|
956 |
|
957 |
// Returns the mean value of the elements stored in the vector v. |
958 |
double getMean(vector<Double_t> v) |
959 |
{ |
960 |
double mean = 0; |
961 |
|
962 |
for(int i=0; i < v.size(); i++) |
963 |
mean += v.at(i); |
964 |
|
965 |
return mean/v.size(); |
966 |
} |
967 |
|
968 |
|
969 |
// Shift all non zero bins by shift. |
970 |
TH2F* shiftHist(TH2F* h, Float_t shift) |
971 |
{ |
972 |
// Global bin number. |
973 |
Int_t nBins = h->GetBin(h->GetNbinsX(), h->GetNbinsY()); |
974 |
|
975 |
for(int i = 0; i < nBins; i++) |
976 |
if(h->GetBinContent(i)) h->AddBinContent(i, shift); |
977 |
|
978 |
return h; |
979 |
} |
980 |
|
981 |
|
982 |
// |
983 |
// Returns the tle date as a TTimeStamp object. |
984 |
// |
985 |
TTimeStamp getTleDatetime(cTle *tle) |
986 |
{ |
987 |
int year, mon, day, hh, mm, ss; |
988 |
double dom; // day of month (is double!) |
989 |
stringstream date; // date in datetime format |
990 |
|
991 |
// create a cJulian from the date in tle |
992 |
cJulian jdate = cJulian( 2000 + (int) tle->getField(cTle::FLD_EPOCHYEAR), tle->getField(cTle::FLD_EPOCHDAY)); |
993 |
|
994 |
// get year, month, day of month |
995 |
jdate.getComponent(&year, &mon, &dom); |
996 |
|
997 |
// build a datetime YYYY-MM-DD hh:mm:ss |
998 |
date.str(""); |
999 |
day = (int) floor(dom); |
1000 |
hh = (int) floor( (dom - day) * 24); |
1001 |
mm = (int) floor( ((dom - day) * 24 - hh) * 60); |
1002 |
ss = (int) floor( ((((dom - day) * 24 - hh) * 60 - mm) * 60)); |
1003 |
// ms = (int) floor( (((((dom - day) * 24 - hh) * 60 - mm) * 60) - ss) * 1000); |
1004 |
|
1005 |
TTimeStamp t = TTimeStamp(year, mon, day, hh, mm, ss, 0, true); |
1006 |
|
1007 |
return t; |
1008 |
} |
1009 |
|
1010 |
// |
1011 |
// Solve the overflow for anticoincidence because this counter is |
1012 |
// stored in 2 bytes so counts from 0 to 65535. |
1013 |
// |
1014 |
// counter is the actual value. |
1015 |
// oldValue is meant to be the previous value of counter. |
1016 |
// |
1017 |
// Example: |
1018 |
// for(...) { |
1019 |
// ... |
1020 |
// corrected_diff = solve_ac_overflow(oldValueOfTheCounter, actualValue); |
1021 |
// ... |
1022 |
// } |
1023 |
// |
1024 |
// |
1025 |
// Returns the corrected difference between counter and oldValue and |
1026 |
// set oldValue to the value of counter. |
1027 |
// Attention: oldValue is a reference. |
1028 |
Int_t solve_ac_overflow(Int_t& oldValue, Int_t counter) |
1029 |
{ |
1030 |
Int_t truediff = 0; |
1031 |
|
1032 |
if (counter < oldValue) // overflow! |
1033 |
truediff = 0xFFFF - oldValue + counter; |
1034 |
else |
1035 |
truediff = counter - oldValue; |
1036 |
|
1037 |
oldValue = counter; |
1038 |
|
1039 |
return truediff; |
1040 |
} |