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

Annotation of /quicklook/OrbitalRate/src/OrbitalRate.cpp

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.2 - (hide annotations) (download)
Wed Dec 6 15:52:13 2006 UTC (18 years ago) by pam-rm2
Branch: MAIN
Changes since 1.1: +6 -2 lines
Set some minimum for graphs.

1 pam-rm2 1.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 pam-rm2 1.2 if(i<2 || (deltaTime > 1)) continue;
482 pam-rm2 1.1
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 pam-rm2 1.2 trigS111A_rate->SetMinimum(10);
595 pam-rm2 1.1 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 pam-rm2 1.2 antiCAS4_rate->SetMinimum(100);
601 pam-rm2 1.1 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 pam-rm2 1.2 antiCAS3_rate->SetMinimum(100);
607 pam-rm2 1.1 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 pam-rm2 1.2 antiCAS3_rate->SetMinimum(100);
618 pam-rm2 1.1 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 pam-rm2 1.2 antiCAS3_rate->SetMinimum(10);
624 pam-rm2 1.1 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", "passed histogram", width*2, height*2);
741    
742     if(use_log) {
743     canvas->SetLogz();
744     }
745    
746     h->SetTitle(title);
747     h->SetXTitle("Longitude (deg)");
748     h->SetYTitle("Latitude (deg)");
749     h->SetLabelColor(0, "X");
750     h->SetAxisColor(0, "X");
751     h->SetLabelColor(0, "Y");
752     h->SetAxisColor(0, "Y");
753     h->SetLabelColor(0, "Z");
754     h->SetAxisColor(0, "Z");
755    
756     h->Draw("colz");
757     canvas->Update(); // Update! Otherwise we can't get any palette.
758    
759     // If shift in a positive range required (see comment above).
760     if(bool_shift) {
761     // Remember the minimum and maximum in this graph.
762     Float_t min = h->GetMinimum();
763     Float_t max = h->GetMaximum();
764    
765     // Shift the graph up by 100. Increase the value if you still get
766     // negative filled bins.
767     h = shiftHist(h, 100.0);
768     h->SetMinimum(min+100.0);
769     h->SetMaximum(max+100.0);
770    
771     // Hide the current axis of the palette
772     TPaletteAxis *palette = (TPaletteAxis*) h->GetListOfFunctions()->FindObject("palette");
773     if(!palette) cout << "palette is null" << endl;
774     TGaxis *ax = (TGaxis*) palette->GetAxis();
775     if(!ax) cout << "ax is null" << endl;
776     ax->SetLabelOffset(999);
777     ax->SetTickSize(0);
778    
779     // Create a new axis of the palette using the right min and max and draw it.
780     TGaxis *gaxis = new TGaxis(palette->GetX2(), palette->GetY1(), palette->GetX2(), palette->GetY2(), min, max, 510,"+L");
781     gaxis->SetLabelColor(0);
782     gaxis->Draw();
783    
784     // Update again.
785     canvas->Update();
786     }
787    
788     // We merge two images: the image of the earth read from a file on
789     // that one of the TPad of canvas (the histogram). The first one is
790     // scaled and adjusted to fit well inside the frame of the second
791     // one. Finally we draw them both.
792     //
793     // Here there's a trick to avoid blurring during the merging
794     // operation. We get the image from a canvas sized (width*2 x
795     // height*2) and draw it on a canvas sized (width x height).
796    
797     TCanvas *mergeCanvas = new TCanvas("", "", width, height);
798     TImage *img = TImage::Create();
799     TImage *terra = TImage::Create();
800     img->FromPad(canvas); // get the TCanvas canvas as TImage
801     terra->ReadImage(mapFile, TImage::kPng); // get the png file as TImage
802     terra->Scale(1304,830);
803     img->Merge(terra, "add", 166, 112); // add image terra to image img
804     img->Draw("X"); // see what we get, eXpanding img all over mergeCanvas.
805    
806     stringstream oss;
807     oss << outDirectory.Data() << "/" << outputFilename.Data();
808    
809     mergeCanvas->SaveAs(oss.str().c_str());
810     mergeCanvas->Close();
811     canvas->Close();
812    
813     return EXIT_SUCCESS;
814     }
815    
816     void saveHist(TH1 *h, TString savetorootfile)
817     {
818     TFile *file = new TFile(savetorootfile.Data(), "update");
819    
820     h->Write();
821     file->Close();
822     }
823    
824    
825     // Get the TLE from tleFile. The right TLE is that one with the
826     // closest previous date to offRes, that is the date at the time of
827     // the first timesync found in the root file.
828     //
829     // Warning: you must use a tle file obtained by space-track.org
830     // querying the database with the RESURS DK-1 id number 29228,
831     // selecting the widest timespan, including the satellite name in the
832     // results.
833     cTle *getTle(TString tleFile, TDatime offRes)
834     {
835     Float_t tledatefromfile, tledatefromroot;
836     fstream tlefile(tleFile.Data(), ios::in);
837     vector<cTle*> ctles;
838     vector<cTle*>::iterator iter;
839    
840    
841     // Build a vector of *cTle
842     while(1) {
843     cTle *tlef;
844     string str1, str2, str3;
845    
846     getline(tlefile, str1);
847     if(tlefile.eof()) break;
848    
849     getline(tlefile, str2);
850     if(tlefile.eof()) break;
851    
852     getline(tlefile, str3);
853     if(tlefile.eof()) break;
854    
855     // We now have three good lines for a cTle.
856     tlef = new cTle(str1, str2, str3);
857     ctles.push_back(tlef);
858     }
859    
860     // Sort by date
861     sort(ctles.begin(), ctles.end(), compTLE);
862    
863     tledatefromroot = (offRes.GetYear()-2000)*1e3 + (offRes.Convert() - (TDatime(offRes.GetYear(), 1, 1, 0, 0, 0)).Convert())/ (24.*3600.);
864    
865     for(iter = ctles.begin(); iter != ctles.end(); iter++) {
866     cTle *tle = *iter;
867    
868     tledatefromfile = getTleJulian(tle);
869    
870     if(tledatefromroot > tledatefromfile) {
871     tlefile.close();
872     cTle *thisTle = tle;
873     ctles.clear();
874    
875     return thisTle;
876     }
877     }
878    
879     // File ended withoud founding a TLE with a date after offRes. We'll use the last aviable date.
880     cerr << "Warning: using last available TLE in " << tleFile.Data() << ". Consider updating your tle file." << endl;
881    
882     tlefile.close();
883     cTle *thisTle = ctles[ctles.size()-1];
884     ctles.clear();
885    
886     return thisTle;
887     }
888    
889    
890     // Return whether the first TLE is older than the second
891     bool compTLE (cTle *tle1, cTle *tle2)
892     {
893     return getTleJulian(tle1) > getTleJulian(tle2);
894     }
895    
896    
897     // Return the date of the tle using the format (year-2000)*1e3 +
898     // julian day. e.g. 6364.5 is the 31th Dec 2006 12:00:00.
899     // It does *not* return a cJulian date.
900     float getTleJulian(cTle *tle) {
901     return tle->getField(cTle::FLD_EPOCHYEAR)*1e3 + tle->getField(cTle::FLD_EPOCHDAY);
902     }
903    
904    
905     // Look for a timesync in the TFile rootFile. Set timesync and
906     // obt_timesync. Returns 1 if timesync is found, 0 otherwise.
907     int lookforTimesync(TFile *rootFile, Float_t *timesync, Float_t *obt_timesync) {
908     *timesync = -1; // will be != -1 if found
909    
910     ULong64_t nevents = 0;
911     pamela::McmdRecord *mcmdrc = 0;
912     pamela::McmdEvent *mcmdev = 0;
913     TArrayC *mcmddata;
914     TTree *tr = (TTree*) rootFile->Get("Mcmd");
915    
916     tr->SetBranchAddress("Mcmd", &mcmdev);
917    
918     nevents = tr->GetEntries();
919    
920     // Looking for a timesync. We stop at the first one found.
921     long int recEntries;
922    
923     for(UInt_t i = 0; i < nevents; i++) {
924     tr->GetEntry(i);
925     recEntries = mcmdev->Records->GetEntries();
926    
927     for(UInt_t j = 0; j < recEntries; j++) {
928     mcmdrc = (pamela::McmdRecord*)mcmdev->Records->At(j);
929    
930     if ((mcmdrc != 0) && (mcmdrc->ID1 == 0xE0)) //Is it a TimeSync?
931     {
932     mcmddata = mcmdrc->McmdData;
933     *timesync = (((unsigned int)mcmddata->At(0)<<24)&0xFF000000)
934     + (((unsigned int)mcmddata->At(1)<<16)&0x00FF0000)
935     + (((unsigned int)mcmddata->At(2)<<8)&0x0000FF00)
936     + (((unsigned int)mcmddata->At(3))&0x000000FF);
937     *obt_timesync = (mcmdrc->MCMD_RECORD_OBT)*(1./1000.);
938    
939     goto out; // a timesync is found
940     }
941     }
942     }
943    
944     out:
945    
946     if (*timesync == -1)
947     return 0;
948     else
949     return 1;
950     }
951    
952    
953     // Returns the mean value of the elements stored in the vector v.
954     double getMean(vector<Double_t> v)
955     {
956     double mean = 0;
957    
958     for(int i=0; i < v.size(); i++)
959     mean += v.at(i);
960    
961     return mean/v.size();
962     }
963    
964    
965     // Shift all non zero bins by shift.
966     TH2F* shiftHist(TH2F* h, Float_t shift)
967     {
968     // Global bin number.
969     Int_t nBins = h->GetBin(h->GetNbinsX(), h->GetNbinsY());
970    
971     for(int i = 0; i < nBins; i++)
972     if(h->GetBinContent(i)) h->AddBinContent(i, shift);
973    
974     return h;
975     }
976    
977    
978     // Return a string like YYYY-MM-DD hh:mm:ss, a datetime format.
979     string getTleDatetime(cTle *tle)
980     {
981     int year, mon, day, hh, mm, ss;
982     double dom; // day of month (is double!)
983     stringstream date; // date in datetime format
984    
985     // create a cJulian from the date in tle
986     cJulian jdate = cJulian( 2000 + (int) tle->getField(cTle::FLD_EPOCHYEAR), tle->getField(cTle::FLD_EPOCHDAY));
987    
988     // get year, month, day of month
989     jdate.getComponent(&year, &mon, &dom);
990    
991     // build a datetime YYYY-MM-DD hh:mm:ss
992     date.str("");
993     day = (int) floor(dom);
994     hh = (int) floor( (dom - day) * 24);
995     mm = (int) floor( ((dom - day) * 24 - hh) * 60);
996     ss = (int) floor( ((((dom - day) * 24 - hh) * 60 - mm) * 60));
997     // ms = (int) floor( (((((dom - day) * 24 - hh) * 60 - mm) * 60) - ss) * 1000);
998    
999     date << year << "-" << mon << "-" << day << " " << hh << ":" << mm << ":" << ss;
1000    
1001     return date.str();
1002     }
1003    
1004     //
1005     // Solve the overflow for anticoincidence because this counter is
1006     // stored in 2 bytes so counts from 0 to 65535.
1007     //
1008     // counter is the actual value.
1009     // oldValue is meant to be the previous value of counter.
1010     //
1011     // Example:
1012     // for(...) {
1013     // ...
1014     // corrected_diff = solve_ac_overflow(oldValueOfTheCounter, actualValue);
1015     // ...
1016     // }
1017     //
1018     //
1019     // Returns the corrected difference between counter and oldValue and
1020     // set oldValue to the value of counter.
1021     // Attention: oldValue is a reference.
1022     Int_t solve_ac_overflow(Int_t& oldValue, Int_t counter)
1023     {
1024     Int_t truediff = 0;
1025    
1026     if (counter < oldValue) // overflow!
1027     truediff = 0xFFFF - oldValue + counter;
1028     else
1029     truediff = counter - oldValue;
1030    
1031     oldValue = counter;
1032    
1033     return truediff;
1034     }

  ViewVC Help
Powered by ViewVC 1.1.23