/[PAMELA software]/quicklook/OrbitalRate/src/OrbitalRate.cpp
ViewVC logotype

Contents of /quicklook/OrbitalRate/src/OrbitalRate.cpp

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.3 - (show annotations) (download)
Wed Dec 6 16:25:52 2006 UTC (18 years ago) by pam-rm2
Branch: MAIN
Changes since 1.2: +8 -10 lines
*** empty log message ***

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

  ViewVC Help
Powered by ViewVC 1.1.23