| 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, ×ync, &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 |
pam-rm2 |
1.4 |
float br, btheta, bphi; |
| 350 |
pam-rm2 |
1.1 |
|
| 351 |
|
|
// I can now compute the magnetic dipole moment at the actual date, |
| 352 |
|
|
// using the cJulian date. I don't to recompute it for every event |
| 353 |
|
|
// beacause changes are not relevant at all. |
| 354 |
|
|
Int_t y = tledate.GetYear(); |
| 355 |
|
|
Int_t m = tledate.GetMonth(); |
| 356 |
|
|
Int_t d = tledate.GetDay(); |
| 357 |
|
|
float year = (float) y + (m*31+d)/365; |
| 358 |
|
|
|
| 359 |
pam-rm2 |
1.4 |
// Initialize common data for geopack |
| 360 |
|
|
recalc_(y, m*31+d, 0, 0, 0); |
| 361 |
pam-rm2 |
1.1 |
/********** Magnetic Field **************/ |
| 362 |
|
|
|
| 363 |
|
|
tr = (TTree*)rootFile->Get("Physics"); |
| 364 |
|
|
TBranch *headBr = tr->GetBranch("Header"); |
| 365 |
|
|
tr->SetBranchAddress("Header", &eh); |
| 366 |
|
|
|
| 367 |
|
|
/********** Anticounter **************/ |
| 368 |
|
|
pamela::anticounter::AnticounterEvent *antiev = 0; |
| 369 |
|
|
tr->SetBranchAddress("Anticounter", &antiev); |
| 370 |
|
|
|
| 371 |
|
|
Int_t oldCAS4 = 0; |
| 372 |
|
|
Int_t diffCAS4 = 0; |
| 373 |
|
|
Int_t oldCAS3 = 0; |
| 374 |
|
|
Int_t diffCAS3 = 0; |
| 375 |
|
|
/********** Anticounter **************/ |
| 376 |
|
|
|
| 377 |
|
|
/********** Trigger **************/ |
| 378 |
|
|
pamela::trigger::TriggerEvent *trigger = 0; |
| 379 |
|
|
tr->SetBranchAddress("Trigger", &trigger); |
| 380 |
|
|
|
| 381 |
|
|
Int_t oldtrigAndOr = 0; |
| 382 |
|
|
Int_t oldtrigAndAnd = 0; |
| 383 |
|
|
Int_t oldtrigS11andS12 = 0; |
| 384 |
|
|
Int_t oldtrigS12andS21andS22 = 0; |
| 385 |
|
|
Int_t oldtrigS111A = 0; |
| 386 |
|
|
/********** Trigger **************/ |
| 387 |
|
|
|
| 388 |
|
|
/********** ND **************/ |
| 389 |
|
|
Int_t tmpSize=0; |
| 390 |
|
|
Int_t sumTrig=0; |
| 391 |
|
|
Int_t sumUpperBackground=0; |
| 392 |
|
|
Int_t sumBottomBackground=0; |
| 393 |
|
|
|
| 394 |
|
|
pamela::neutron::NeutronRecord *nr = 0; |
| 395 |
|
|
pamela::neutron::NeutronEvent *ne = 0; |
| 396 |
|
|
tr->SetBranchAddress("Neutron", &ne); |
| 397 |
|
|
/********** ND **************/ |
| 398 |
|
|
|
| 399 |
|
|
nevents = tr->GetEntries(); |
| 400 |
|
|
|
| 401 |
|
|
for(UInt_t i = 0; i < nevents; i++) //Fill variables from root-ple |
| 402 |
|
|
{ |
| 403 |
|
|
tr->GetEntry(i); |
| 404 |
|
|
ph = eh->GetPscuHeader(); |
| 405 |
|
|
|
| 406 |
|
|
// obt in ms |
| 407 |
|
|
ULong64_t obt = ph->GetOrbitalTime(); |
| 408 |
|
|
|
| 409 |
|
|
// timeElapsedFromTLE is the difference, in seconds, between the |
| 410 |
|
|
// event and the tle date. I use seconds and not milliseconds |
| 411 |
|
|
// because the indetermination on the timesync is about 1s. |
| 412 |
|
|
timeElapsedFromTLE = offsetTime + obt/1000; |
| 413 |
|
|
|
| 414 |
|
|
// I also need the abstime in seconds rounded to the lower |
| 415 |
|
|
// value. Every second, we set a_second_is_over to true. Only |
| 416 |
|
|
// in this case histograms with triggers are filled. |
| 417 |
|
|
a_second_is_over = (timeElapsedFromTLE > oldtimeElapsedFromTLE) ? 1 : 0; |
| 418 |
|
|
oldtimeElapsedFromTLE = timeElapsedFromTLE; |
| 419 |
|
|
|
| 420 |
|
|
// I need the acquisition time between two triggers to fill the |
| 421 |
|
|
// obtBinTime (histo of time spent in the bin). The time is in |
| 422 |
|
|
// second. |
| 423 |
|
|
deltaTime = timeElapsedFromTLE - oldtimeElapsedFromTLE; |
| 424 |
|
|
oldtimeElapsedFromTLE = timeElapsedFromTLE; |
| 425 |
|
|
|
| 426 |
|
|
// Finally, we get coordinates from absolute time the orbit |
| 427 |
|
|
// object initialised with the TLE data. cOrbit::getPosition() |
| 428 |
|
|
// requires the elapased time from the tle in minutes. |
| 429 |
|
|
// Coordinates are stored in the structure eci. |
| 430 |
|
|
orbit.getPosition(((double) timeElapsedFromTLE)/60., &eci); |
| 431 |
|
|
coo = eci.toGeo(); |
| 432 |
|
|
|
| 433 |
|
|
/********** ND **************/ |
| 434 |
|
|
// Summing over all stored pamela::neutron::NeutronRecords in |
| 435 |
|
|
// this event *ne. |
| 436 |
|
|
for(Int_t j = 0; j < ne->Records->GetEntries(); j++) { |
| 437 |
|
|
nr = (pamela::neutron::NeutronRecord*)ne->Records->At(j); |
| 438 |
|
|
sumTrig += (int)nr->trigPhysics; |
| 439 |
|
|
sumUpperBackground += (int)nr->upperBack; |
| 440 |
|
|
sumBottomBackground += (int)nr->bottomBack; |
| 441 |
|
|
} |
| 442 |
|
|
/********** ND **************/ |
| 443 |
|
|
|
| 444 |
|
|
/********** Anticounter **************/ |
| 445 |
|
|
// Get the difference between the actual counter and the |
| 446 |
|
|
// previous counter for anticoincidence, dealing with the |
| 447 |
|
|
// overflow with solve_ac_overflow(). |
| 448 |
|
|
diffCAS4 = solve_ac_overflow(oldCAS4, antiev->counters[0][6]); |
| 449 |
|
|
diffCAS3 = solve_ac_overflow(oldCAS3, antiev->counters[0][10]); |
| 450 |
|
|
/********** Anticounter **************/ |
| 451 |
|
|
|
| 452 |
|
|
// Build coordinates in the right range. We want to convert, |
| 453 |
|
|
// just for aesthetic, longitude from (0, 2*pi) to (-pi, pi). |
| 454 |
|
|
// We also want to convert from radians to degrees. |
| 455 |
|
|
lon = (coo.m_Lon > PI) ? rad2deg(coo.m_Lon - 2*PI) : rad2deg(coo.m_Lon); |
| 456 |
|
|
lat = rad2deg(coo.m_Lat); |
| 457 |
|
|
alt = coo.m_Alt; |
| 458 |
|
|
|
| 459 |
|
|
/********** Magnetic Field **************/ |
| 460 |
pam-rm2 |
1.4 |
igrf_geo__((coo.m_Alt+6371.2)/6371.2, M_PI/2.-coo.m_Lat, coo.m_Lon, br, btheta, bphi); |
| 461 |
|
|
// cout<<"("<<(coo.m_Alt+6371.2)/6371.2<<", "<<M_PI/2.-coo.m_Lat<<", "<<coo.m_Lon<<")"<<endl; |
| 462 |
pam-rm2 |
1.1 |
/********** Magnetic Field **************/ |
| 463 |
|
|
|
| 464 |
|
|
// serve fare il controllo deltatime < 1? |
| 465 |
|
|
if (deltaTime > 1) cout << endl << "******** deltaTime<1 ********" << endl; |
| 466 |
|
|
// Does nothing for the first two events or if acquisition time if more |
| 467 |
|
|
// than 1s. |
| 468 |
pam-rm2 |
1.3 |
if(i<1 || (deltaTime > 1)) continue; |
| 469 |
pam-rm2 |
1.1 |
|
| 470 |
|
|
// CAS3 and CAS4 are not rates but only counters. So I fill |
| 471 |
|
|
// with the bin with the difference beetween the actual counter |
| 472 |
|
|
// and the previous one and then divide with the time (see |
| 473 |
|
|
// below) to have rates. |
| 474 |
|
|
if(diffCAS3>1e3) // additional cut to avoid the peaks after dead time |
| 475 |
|
|
diffCAS3 = (Int_t) antiCAS3_counter->GetBinContent((Int_t)antiCAS3_counter->GetEntries()-1); |
| 476 |
|
|
antiCAS3_counter->Fill(lon , lat, diffCAS3); |
| 477 |
|
|
|
| 478 |
|
|
if(diffCAS4>1e3) // additional cut to avoid the peaks after dead time |
| 479 |
|
|
diffCAS4 = (Int_t) antiCAS4_counter->GetBinContent((Int_t) antiCAS4_counter->GetEntries()-1); |
| 480 |
|
|
antiCAS4_counter->Fill(lon, lat, diffCAS4); |
| 481 |
|
|
|
| 482 |
|
|
// Magnetic field values should be handled a bit carefully. |
| 483 |
|
|
// For every event I get a position and the related magnetic |
| 484 |
|
|
// field values. I can fill the histograms lon x lat with |
| 485 |
|
|
// this values but I need to count how many times I fill |
| 486 |
|
|
// each bin. This is done by the histogram event_counter. |
| 487 |
|
|
// I will normalize later. |
| 488 |
pam-rm2 |
1.4 |
hbabs_counter->Fill(lon, lat, sqrt(br*br+btheta*btheta+bphi*bphi)*1e-5); |
| 489 |
|
|
hbnorth_counter->Fill(lon, lat, -btheta*1e-5); |
| 490 |
|
|
hbdown_counter->Fill(lon, lat, -br*1e-5); |
| 491 |
|
|
hbeast_counter->Fill(lon, lat, bphi*1e-5); |
| 492 |
pam-rm2 |
1.1 |
|
| 493 |
|
|
// This histograms is now filled with the number of entries. |
| 494 |
|
|
// Below we will divide with the time (in seconds) to get |
| 495 |
|
|
// event rate per bin. |
| 496 |
|
|
event_counter->Fill(lon, lat); |
| 497 |
|
|
|
| 498 |
|
|
// counters about triggers are already rates (Hz). Only |
| 499 |
|
|
// every second we fill fill with the mean over all values. |
| 500 |
|
|
if(a_second_is_over) { |
| 501 |
|
|
// This histograms will hold the time, in seconds, spent |
| 502 |
|
|
// in the bin. |
| 503 |
|
|
obtBinTime->Fill(lon, lat, 1); |
| 504 |
|
|
|
| 505 |
|
|
// get the means |
| 506 |
|
|
mean_trigAndOr = getMean(vector_trigAndOr); |
| 507 |
|
|
mean_trigAndAnd = getMean(vector_trigAndAnd); |
| 508 |
|
|
mean_trigS11andS12 = getMean(vector_trigS11andS12); |
| 509 |
|
|
mean_trigS12andS21andS22 = getMean(vector_trigS12andS21andS22); |
| 510 |
|
|
mean_trigS111A = getMean(vector_trigS111A); |
| 511 |
|
|
|
| 512 |
|
|
// clear data about the last second |
| 513 |
|
|
vector_trigAndOr.clear(); |
| 514 |
|
|
vector_trigAndAnd.clear(); |
| 515 |
|
|
vector_trigS11andS12.clear(); |
| 516 |
|
|
vector_trigS12andS21andS22.clear(); |
| 517 |
|
|
vector_trigS111A.clear(); |
| 518 |
|
|
|
| 519 |
|
|
// Fill with the mean rate value |
| 520 |
|
|
trigAndOr_counter->Fill(lon , lat, mean_trigAndOr); |
| 521 |
|
|
trigAndAnd_counter->Fill(lon , lat, mean_trigAndAnd); |
| 522 |
|
|
trigS11andS12_counter->Fill(lon , lat, mean_trigS11andS12); |
| 523 |
|
|
trigS12andS21andS22_counter->Fill(lon , lat, mean_trigS12andS21andS22); |
| 524 |
|
|
trigS111A_counter->Fill(lon, lat, mean_trigS111A); |
| 525 |
|
|
} |
| 526 |
|
|
else { // Collect values for all the second |
| 527 |
|
|
vector_trigAndOr.push_back((1/4.)*trigger->trigrate[0]); |
| 528 |
|
|
vector_trigAndAnd.push_back((1/4.)*trigger->trigrate[1]); |
| 529 |
|
|
// pmtpl[0] is the rate every 60ms but I want Hz. |
| 530 |
|
|
vector_trigS11andS12.push_back((1000./60.)*trigger->pmtpl[0]); |
| 531 |
|
|
vector_trigS12andS21andS22.push_back((1/4.)*trigger->trigrate[4]); |
| 532 |
|
|
vector_trigS111A.push_back(1.*trigger->pmtcount1[0]); |
| 533 |
|
|
} |
| 534 |
|
|
|
| 535 |
|
|
// Now we discard ND data if: |
| 536 |
|
|
// - NeutronEvent is corrupted. |
| 537 |
|
|
if((ne->unpackError != 1)) |
| 538 |
|
|
nd_counter->Fill(lon, lat, 1.*(sumUpperBackground+sumTrig)); |
| 539 |
|
|
|
| 540 |
|
|
// Reset counters for ND. |
| 541 |
|
|
sumTrig = 0; |
| 542 |
|
|
sumUpperBackground = 0; |
| 543 |
|
|
sumBottomBackground = 0; |
| 544 |
|
|
} |
| 545 |
|
|
|
| 546 |
|
|
// We now need to normalize the histograms to print something |
| 547 |
|
|
// meaningful. I create similar histograms with the suffix _rate or |
| 548 |
|
|
// _norm. |
| 549 |
|
|
TH2F *event_rate = (TH2F*) event_counter->Clone("event_rate"); |
| 550 |
|
|
TH2F *trigS111A_rate = (TH2F*) trigS111A_counter->Clone("trigS111A_rate"); |
| 551 |
|
|
TH2F *antiCAS4_rate = (TH2F*) antiCAS4_counter->Clone("antiCAS4_rate"); |
| 552 |
|
|
TH2F *antiCAS3_rate = (TH2F*) antiCAS3_counter->Clone("antiCAS3_rate"); |
| 553 |
|
|
TH2F *trigS11andS12_rate = (TH2F*) trigS11andS12_counter->Clone("trigS11andS12_rate"); |
| 554 |
|
|
TH2F *trigS12andS21andS22_rate = (TH2F*) trigS12andS21andS22_counter->Clone("trigS12andS21andS22_rate"); |
| 555 |
|
|
TH2F *trigAndOr_rate = (TH2F*) trigAndOr_counter->Clone("trigAndOr_rate"); |
| 556 |
|
|
TH2F *trigAndAnd_rate = (TH2F*) trigAndAnd_counter->Clone("trigAndAnd_rate"); |
| 557 |
|
|
TH2F *nd_rate = (TH2F*) nd_counter->Clone("nd_rate"); |
| 558 |
|
|
TH2F *hbabs_norm = (TH2F*) hbabs_counter->Clone("hbabs_norm"); |
| 559 |
|
|
TH2F *hbnorth_norm = (TH2F*) hbnorth_counter->Clone("hbnorth_norm"); |
| 560 |
|
|
TH2F *hbdown_norm = (TH2F*) hbabs_counter->Clone("hbdown_norm"); |
| 561 |
|
|
TH2F *hbeast_norm = (TH2F*) hbabs_counter->Clone("hbeast_norm"); |
| 562 |
|
|
|
| 563 |
|
|
// Now we divide each histogram _counter with the time histogram |
| 564 |
|
|
// obtBinTime to have an histogram _rate. Note that, when a second |
| 565 |
|
|
// is passed in the above cycle, we fill the histogram obtBinTime |
| 566 |
|
|
// with 1 (second) together with all the other histograms. So |
| 567 |
|
|
// dividing here does make sense. |
| 568 |
|
|
// |
| 569 |
|
|
// Then we call printHist() for each filled TH2F. These are |
| 570 |
|
|
// refered to the root file we're now reading. We also build up a |
| 571 |
|
|
// filename to be passed to the function. Pay attention that the |
| 572 |
|
|
// filename must end with a file format (such as .png or .pdf) |
| 573 |
|
|
// recognised by TPad::SaveAs(). |
| 574 |
|
|
trigS111A_rate->Divide(trigS111A_counter, obtBinTime, 1, 1, ""); |
| 575 |
|
|
oss.str(""); |
| 576 |
|
|
oss << basename.Data() << "_orbit_trigS111A.png"; |
| 577 |
pam-rm2 |
1.3 |
trigS111A_rate->SetMinimum(9); |
| 578 |
pam-rm2 |
1.1 |
printHist(trigS111A_rate, mapFile, outDirectory, oss.str().c_str(), "S111A (Hz)", -width, height, true, 0); |
| 579 |
|
|
|
| 580 |
|
|
antiCAS4_rate->Divide(antiCAS4_counter, obtBinTime, 1, 1, ""); |
| 581 |
|
|
oss.str(""); |
| 582 |
|
|
oss << basename.Data() << "_orbit_CAS4.png"; |
| 583 |
pam-rm2 |
1.3 |
antiCAS4_rate->SetMinimum(99); |
| 584 |
pam-rm2 |
1.1 |
printHist(antiCAS4_rate, mapFile, outDirectory, oss.str().c_str(), "CAS4 (Hz)", -width, height, true, 0); |
| 585 |
|
|
|
| 586 |
|
|
antiCAS3_rate->Divide(antiCAS3_counter, obtBinTime, 1, 1, ""); |
| 587 |
|
|
oss.str(""); |
| 588 |
|
|
oss << basename.Data() << "_orbit_CAS3.png"; |
| 589 |
pam-rm2 |
1.3 |
antiCAS3_rate->SetMinimum(99); |
| 590 |
pam-rm2 |
1.1 |
printHist(antiCAS3_rate, mapFile, outDirectory, oss.str().c_str(), "CAS3 (Hz)", -width, height, true, 0); |
| 591 |
|
|
|
| 592 |
|
|
event_rate->Divide(event_counter, obtBinTime, 1, 1, ""); |
| 593 |
|
|
oss.str(""); |
| 594 |
|
|
oss << basename.Data() << "_orbit_EventRate.png"; |
| 595 |
|
|
printHist(event_rate, mapFile, outDirectory, oss.str().c_str(), "Event rate (Hz)", -width, height, 0, 0); |
| 596 |
|
|
|
| 597 |
|
|
trigS11andS12_rate->Divide(trigS11andS12_counter, obtBinTime, 1, 1, ""); |
| 598 |
|
|
oss.str(""); |
| 599 |
|
|
oss << basename.Data() << "_orbit_trigS11andS12.png"; |
| 600 |
pam-rm2 |
1.3 |
trigS11andS12_rate->SetMinimum(99); |
| 601 |
pam-rm2 |
1.1 |
printHist(trigS11andS12_rate, mapFile, outDirectory, oss.str().c_str(), "(S11*S12) (Hz)", -width, height, 1, 0); |
| 602 |
|
|
|
| 603 |
|
|
trigS12andS21andS22_rate->Divide(trigS12andS21andS22_counter, obtBinTime, 1, 1, ""); |
| 604 |
|
|
oss.str(""); |
| 605 |
|
|
oss << basename.Data() << "_orbit_trigS12andS21andS22.png"; |
| 606 |
pam-rm2 |
1.3 |
trigS12andS21andS22_rate->SetMinimum(9); |
| 607 |
pam-rm2 |
1.1 |
printHist(trigS12andS21andS22_rate, mapFile, outDirectory, oss.str().c_str(), "(S12*S12*S21) (Hz)", -width, height, true, 0); |
| 608 |
|
|
|
| 609 |
|
|
trigAndOr_rate->Divide(trigAndOr_counter, obtBinTime, 1, 1, ""); |
| 610 |
|
|
oss.str(""); |
| 611 |
|
|
oss << basename.Data() << "_orbit_trigANDofOR.png"; |
| 612 |
|
|
printHist(trigAndOr_rate, mapFile, outDirectory, oss.str().c_str(), "(S11+S12)*(S21+S22)*(S31+S32) (Hz)", -width, height, 0, 0); |
| 613 |
|
|
|
| 614 |
|
|
trigAndAnd_rate->Divide(trigAndAnd_counter, obtBinTime, 1, 1, ""); |
| 615 |
|
|
oss.str(""); |
| 616 |
|
|
oss << basename.Data() << "_orbit_trigANDofAND.png"; |
| 617 |
|
|
printHist(trigAndAnd_rate, mapFile, outDirectory, oss.str().c_str(), "(S11*S12)*(S21*S22)*(S31*S32) (Hz)", -width, height, 0, 0); |
| 618 |
|
|
|
| 619 |
|
|
nd_rate->Divide(nd_counter, obtBinTime, 1, 1, ""); |
| 620 |
|
|
oss.str(""); |
| 621 |
|
|
oss << basename.Data() << "_orbit_ND.png"; |
| 622 |
|
|
printHist(nd_rate, mapFile, outDirectory, oss.str().c_str(), "Neutron rate (Hz)", -width, height, 0, 0); |
| 623 |
|
|
|
| 624 |
|
|
// Also normalize histograms about magnetic fields. Beacause we |
| 625 |
|
|
// fill the bins with the values of the magnetic field for each |
| 626 |
|
|
// event, we need to divide with the number of fills done, that is |
| 627 |
|
|
// event_counter. |
| 628 |
|
|
hbabs_norm->Divide(hbabs_counter, event_counter, 1, 1, ""); |
| 629 |
|
|
oss.str(""); |
| 630 |
|
|
oss << basename.Data() << "_orbit_Babs.png"; |
| 631 |
|
|
printHist(hbabs_norm, mapFile, outDirectory, oss.str().c_str(), "B abs (G)", -width, height, 0, 0); |
| 632 |
|
|
|
| 633 |
|
|
hbnorth_norm->Divide(hbnorth_counter, event_counter, 1, 1, ""); |
| 634 |
|
|
oss.str(""); |
| 635 |
|
|
oss << basename.Data() << "_orbit_Bnorth.png"; |
| 636 |
|
|
printHist(hbnorth_norm, mapFile, outDirectory, oss.str().c_str(), "B north (G)", -width, height, 0, 1); |
| 637 |
|
|
|
| 638 |
|
|
hbdown_norm->Divide(hbdown_counter, event_counter, 1, 1, ""); |
| 639 |
|
|
oss.str(""); |
| 640 |
|
|
oss << basename.Data() << "_orbit_Bdown.png"; |
| 641 |
|
|
printHist(hbdown_norm, mapFile, outDirectory, oss.str().c_str(), "B down (G)", -width, height, 0, 1); |
| 642 |
|
|
|
| 643 |
|
|
hbeast_norm->Divide(hbeast_counter, event_counter, 1, 1, ""); |
| 644 |
|
|
oss.str(""); |
| 645 |
|
|
oss << basename.Data() << "_orbit_Beast.png"; |
| 646 |
|
|
printHist(hbeast_norm, mapFile, outDirectory, oss.str().c_str(), "B east (G)", -width, height, 0, 1); |
| 647 |
|
|
|
| 648 |
|
|
|
| 649 |
|
|
delete obtBinTime; |
| 650 |
|
|
delete event_counter; |
| 651 |
|
|
|
| 652 |
|
|
delete nd_counter; |
| 653 |
|
|
delete antiCAS4_counter; |
| 654 |
|
|
delete antiCAS3_counter; |
| 655 |
|
|
delete trigAndOr_counter; |
| 656 |
|
|
delete trigAndAnd_counter; |
| 657 |
|
|
delete trigS11andS12_counter; |
| 658 |
|
|
delete trigS111A_counter; |
| 659 |
|
|
delete trigS12andS21andS22_counter; |
| 660 |
|
|
|
| 661 |
|
|
delete event_rate; |
| 662 |
|
|
delete nd_rate; |
| 663 |
|
|
delete antiCAS4_rate; |
| 664 |
|
|
delete antiCAS3_rate; |
| 665 |
|
|
delete trigAndOr_rate; |
| 666 |
|
|
delete trigAndAnd_rate; |
| 667 |
|
|
delete trigS11andS12_rate; |
| 668 |
|
|
delete trigS111A_rate; |
| 669 |
|
|
delete trigS12andS21andS22_rate; |
| 670 |
|
|
|
| 671 |
|
|
delete hbabs_counter; |
| 672 |
|
|
delete hbnorth_counter; |
| 673 |
|
|
delete hbdown_counter; |
| 674 |
|
|
delete hbeast_counter; |
| 675 |
|
|
delete hbabs_norm; |
| 676 |
|
|
delete hbnorth_norm; |
| 677 |
|
|
delete hbdown_norm; |
| 678 |
|
|
delete hbeast_norm; |
| 679 |
|
|
|
| 680 |
|
|
rootFile->Close(); |
| 681 |
|
|
} |
| 682 |
|
|
|
| 683 |
|
|
|
| 684 |
|
|
// Print the istogram *h on the file outputfilename in the direcotry |
| 685 |
|
|
// outDirectory, using mapFile as background image, sizing the image |
| 686 |
|
|
// width per height. Log scale will be used if use_log is true. |
| 687 |
|
|
// |
| 688 |
|
|
// If bool_shift is true a further process is performed to solve a |
| 689 |
|
|
// problem with actual root version (5.12). This should be used when |
| 690 |
|
|
// the histrogram is filled also with negative values, because root |
| 691 |
|
|
// draws zero filled bins (so I have all the pad colorized and this is |
| 692 |
|
|
// really weird!). To avoid this problem I shift all the values in a |
| 693 |
|
|
// positive range and draw again using colz. Now I will not have zero |
| 694 |
|
|
// filled bins painted but the scale will be wrong. This is why I |
| 695 |
|
|
// need to draw a new axis along the palette. |
| 696 |
|
|
// |
| 697 |
|
|
// Pay attention: you cannot use a mapFile different from the provided |
| 698 |
|
|
// one without adjusting the scaling and position of the image (see |
| 699 |
|
|
// Scale() and Merge()). |
| 700 |
|
|
// |
| 701 |
|
|
// This function depends on InitStyle(); |
| 702 |
|
|
int printHist(TH2F *h, TString mapFile, TString outDirectory, TString outputFilename, char *title, int width, int height, bool use_log, bool bool_shift) |
| 703 |
|
|
{ |
| 704 |
|
|
InitStyle(); |
| 705 |
|
|
|
| 706 |
|
|
// Create a canvas and draw the TH2F with a nice colormap for z |
| 707 |
|
|
// values, using log scale for z values, if requested, and setting |
| 708 |
|
|
// some title. |
| 709 |
pam-rm2 |
1.3 |
TCanvas *canvas = new TCanvas("h", "h histogram", width*2, height*2); |
| 710 |
pam-rm2 |
1.1 |
|
| 711 |
pam-rm2 |
1.3 |
if(use_log) canvas->SetLogz(); |
| 712 |
pam-rm2 |
1.1 |
|
| 713 |
|
|
h->SetTitle(title); |
| 714 |
|
|
h->SetXTitle("Longitude (deg)"); |
| 715 |
|
|
h->SetYTitle("Latitude (deg)"); |
| 716 |
|
|
h->SetLabelColor(0, "X"); |
| 717 |
|
|
h->SetAxisColor(0, "X"); |
| 718 |
|
|
h->SetLabelColor(0, "Y"); |
| 719 |
|
|
h->SetAxisColor(0, "Y"); |
| 720 |
|
|
h->SetLabelColor(0, "Z"); |
| 721 |
|
|
h->SetAxisColor(0, "Z"); |
| 722 |
|
|
|
| 723 |
|
|
h->Draw("colz"); |
| 724 |
|
|
canvas->Update(); // Update! Otherwise we can't get any palette. |
| 725 |
|
|
|
| 726 |
|
|
// If shift in a positive range required (see comment above). |
| 727 |
|
|
if(bool_shift) { |
| 728 |
|
|
// Remember the minimum and maximum in this graph. |
| 729 |
|
|
Float_t min = h->GetMinimum(); |
| 730 |
|
|
Float_t max = h->GetMaximum(); |
| 731 |
|
|
|
| 732 |
|
|
// Shift the graph up by 100. Increase the value if you still get |
| 733 |
|
|
// negative filled bins. |
| 734 |
|
|
h = shiftHist(h, 100.0); |
| 735 |
|
|
h->SetMinimum(min+100.0); |
| 736 |
|
|
h->SetMaximum(max+100.0); |
| 737 |
|
|
|
| 738 |
|
|
// Hide the current axis of the palette |
| 739 |
|
|
TPaletteAxis *palette = (TPaletteAxis*) h->GetListOfFunctions()->FindObject("palette"); |
| 740 |
|
|
if(!palette) cout << "palette is null" << endl; |
| 741 |
|
|
TGaxis *ax = (TGaxis*) palette->GetAxis(); |
| 742 |
|
|
if(!ax) cout << "ax is null" << endl; |
| 743 |
|
|
ax->SetLabelOffset(999); |
| 744 |
|
|
ax->SetTickSize(0); |
| 745 |
|
|
|
| 746 |
|
|
// Create a new axis of the palette using the right min and max and draw it. |
| 747 |
|
|
TGaxis *gaxis = new TGaxis(palette->GetX2(), palette->GetY1(), palette->GetX2(), palette->GetY2(), min, max, 510,"+L"); |
| 748 |
|
|
gaxis->SetLabelColor(0); |
| 749 |
|
|
gaxis->Draw(); |
| 750 |
|
|
|
| 751 |
|
|
// Update again. |
| 752 |
|
|
canvas->Update(); |
| 753 |
|
|
} |
| 754 |
|
|
|
| 755 |
|
|
// We merge two images: the image of the earth read from a file on |
| 756 |
|
|
// that one of the TPad of canvas (the histogram). The first one is |
| 757 |
|
|
// scaled and adjusted to fit well inside the frame of the second |
| 758 |
|
|
// one. Finally we draw them both. |
| 759 |
|
|
// |
| 760 |
|
|
// Here there's a trick to avoid blurring during the merging |
| 761 |
|
|
// operation. We get the image from a canvas sized (width*2 x |
| 762 |
|
|
// height*2) and draw it on a canvas sized (width x height). |
| 763 |
|
|
|
| 764 |
|
|
TCanvas *mergeCanvas = new TCanvas("", "", width, height); |
| 765 |
|
|
TImage *img = TImage::Create(); |
| 766 |
|
|
TImage *terra = TImage::Create(); |
| 767 |
|
|
img->FromPad(canvas); // get the TCanvas canvas as TImage |
| 768 |
|
|
terra->ReadImage(mapFile, TImage::kPng); // get the png file as TImage |
| 769 |
|
|
terra->Scale(1304,830); |
| 770 |
|
|
img->Merge(terra, "add", 166, 112); // add image terra to image img |
| 771 |
|
|
img->Draw("X"); // see what we get, eXpanding img all over mergeCanvas. |
| 772 |
|
|
|
| 773 |
|
|
stringstream oss; |
| 774 |
|
|
oss << outDirectory.Data() << "/" << outputFilename.Data(); |
| 775 |
|
|
|
| 776 |
|
|
mergeCanvas->SaveAs(oss.str().c_str()); |
| 777 |
|
|
mergeCanvas->Close(); |
| 778 |
|
|
canvas->Close(); |
| 779 |
|
|
|
| 780 |
|
|
return EXIT_SUCCESS; |
| 781 |
|
|
} |
| 782 |
|
|
|
| 783 |
|
|
void saveHist(TH1 *h, TString savetorootfile) |
| 784 |
|
|
{ |
| 785 |
|
|
TFile *file = new TFile(savetorootfile.Data(), "update"); |
| 786 |
|
|
|
| 787 |
|
|
h->Write(); |
| 788 |
|
|
file->Close(); |
| 789 |
|
|
} |
| 790 |
|
|
|
| 791 |
|
|
|
| 792 |
|
|
// Get the TLE from tleFile. The right TLE is that one with the |
| 793 |
|
|
// closest previous date to offRes, that is the date at the time of |
| 794 |
|
|
// the first timesync found in the root file. |
| 795 |
|
|
// |
| 796 |
|
|
// Warning: you must use a tle file obtained by space-track.org |
| 797 |
|
|
// querying the database with the RESURS DK-1 id number 29228, |
| 798 |
|
|
// selecting the widest timespan, including the satellite name in the |
| 799 |
|
|
// results. |
| 800 |
|
|
cTle *getTle(TString tleFile, TDatime offRes) |
| 801 |
|
|
{ |
| 802 |
|
|
Float_t tledatefromfile, tledatefromroot; |
| 803 |
|
|
fstream tlefile(tleFile.Data(), ios::in); |
| 804 |
|
|
vector<cTle*> ctles; |
| 805 |
|
|
vector<cTle*>::iterator iter; |
| 806 |
|
|
|
| 807 |
|
|
|
| 808 |
|
|
// Build a vector of *cTle |
| 809 |
|
|
while(1) { |
| 810 |
|
|
cTle *tlef; |
| 811 |
|
|
string str1, str2, str3; |
| 812 |
|
|
|
| 813 |
|
|
getline(tlefile, str1); |
| 814 |
|
|
if(tlefile.eof()) break; |
| 815 |
|
|
|
| 816 |
|
|
getline(tlefile, str2); |
| 817 |
|
|
if(tlefile.eof()) break; |
| 818 |
|
|
|
| 819 |
|
|
getline(tlefile, str3); |
| 820 |
|
|
if(tlefile.eof()) break; |
| 821 |
|
|
|
| 822 |
|
|
// We now have three good lines for a cTle. |
| 823 |
|
|
tlef = new cTle(str1, str2, str3); |
| 824 |
|
|
ctles.push_back(tlef); |
| 825 |
|
|
} |
| 826 |
|
|
|
| 827 |
|
|
// Sort by date |
| 828 |
|
|
sort(ctles.begin(), ctles.end(), compTLE); |
| 829 |
|
|
|
| 830 |
|
|
tledatefromroot = (offRes.GetYear()-2000)*1e3 + (offRes.Convert() - (TDatime(offRes.GetYear(), 1, 1, 0, 0, 0)).Convert())/ (24.*3600.); |
| 831 |
|
|
|
| 832 |
|
|
for(iter = ctles.begin(); iter != ctles.end(); iter++) { |
| 833 |
|
|
cTle *tle = *iter; |
| 834 |
|
|
|
| 835 |
|
|
tledatefromfile = getTleJulian(tle); |
| 836 |
|
|
|
| 837 |
|
|
if(tledatefromroot > tledatefromfile) { |
| 838 |
|
|
tlefile.close(); |
| 839 |
|
|
cTle *thisTle = tle; |
| 840 |
|
|
ctles.clear(); |
| 841 |
|
|
|
| 842 |
|
|
return thisTle; |
| 843 |
|
|
} |
| 844 |
|
|
} |
| 845 |
|
|
|
| 846 |
|
|
// File ended withoud founding a TLE with a date after offRes. We'll use the last aviable date. |
| 847 |
|
|
cerr << "Warning: using last available TLE in " << tleFile.Data() << ". Consider updating your tle file." << endl; |
| 848 |
|
|
|
| 849 |
|
|
tlefile.close(); |
| 850 |
|
|
cTle *thisTle = ctles[ctles.size()-1]; |
| 851 |
|
|
ctles.clear(); |
| 852 |
|
|
|
| 853 |
|
|
return thisTle; |
| 854 |
|
|
} |
| 855 |
|
|
|
| 856 |
|
|
|
| 857 |
|
|
// Return whether the first TLE is older than the second |
| 858 |
|
|
bool compTLE (cTle *tle1, cTle *tle2) |
| 859 |
|
|
{ |
| 860 |
|
|
return getTleJulian(tle1) > getTleJulian(tle2); |
| 861 |
|
|
} |
| 862 |
|
|
|
| 863 |
|
|
|
| 864 |
|
|
// Return the date of the tle using the format (year-2000)*1e3 + |
| 865 |
|
|
// julian day. e.g. 6364.5 is the 31th Dec 2006 12:00:00. |
| 866 |
|
|
// It does *not* return a cJulian date. |
| 867 |
|
|
float getTleJulian(cTle *tle) { |
| 868 |
|
|
return tle->getField(cTle::FLD_EPOCHYEAR)*1e3 + tle->getField(cTle::FLD_EPOCHDAY); |
| 869 |
|
|
} |
| 870 |
|
|
|
| 871 |
|
|
|
| 872 |
|
|
// Look for a timesync in the TFile rootFile. Set timesync and |
| 873 |
|
|
// obt_timesync. Returns 1 if timesync is found, 0 otherwise. |
| 874 |
|
|
int lookforTimesync(TFile *rootFile, Float_t *timesync, Float_t *obt_timesync) { |
| 875 |
|
|
*timesync = -1; // will be != -1 if found |
| 876 |
|
|
|
| 877 |
|
|
ULong64_t nevents = 0; |
| 878 |
|
|
pamela::McmdRecord *mcmdrc = 0; |
| 879 |
|
|
pamela::McmdEvent *mcmdev = 0; |
| 880 |
|
|
TArrayC *mcmddata; |
| 881 |
|
|
TTree *tr = (TTree*) rootFile->Get("Mcmd"); |
| 882 |
|
|
|
| 883 |
|
|
tr->SetBranchAddress("Mcmd", &mcmdev); |
| 884 |
|
|
|
| 885 |
|
|
nevents = tr->GetEntries(); |
| 886 |
|
|
|
| 887 |
|
|
// Looking for a timesync. We stop at the first one found. |
| 888 |
|
|
long int recEntries; |
| 889 |
|
|
|
| 890 |
|
|
for(UInt_t i = 0; i < nevents; i++) { |
| 891 |
|
|
tr->GetEntry(i); |
| 892 |
|
|
recEntries = mcmdev->Records->GetEntries(); |
| 893 |
|
|
|
| 894 |
|
|
for(UInt_t j = 0; j < recEntries; j++) { |
| 895 |
|
|
mcmdrc = (pamela::McmdRecord*)mcmdev->Records->At(j); |
| 896 |
|
|
|
| 897 |
|
|
if ((mcmdrc != 0) && (mcmdrc->ID1 == 0xE0)) //Is it a TimeSync? |
| 898 |
|
|
{ |
| 899 |
|
|
mcmddata = mcmdrc->McmdData; |
| 900 |
|
|
*timesync = (((unsigned int)mcmddata->At(0)<<24)&0xFF000000) |
| 901 |
|
|
+ (((unsigned int)mcmddata->At(1)<<16)&0x00FF0000) |
| 902 |
|
|
+ (((unsigned int)mcmddata->At(2)<<8)&0x0000FF00) |
| 903 |
|
|
+ (((unsigned int)mcmddata->At(3))&0x000000FF); |
| 904 |
|
|
*obt_timesync = (mcmdrc->MCMD_RECORD_OBT)*(1./1000.); |
| 905 |
|
|
|
| 906 |
|
|
goto out; // a timesync is found |
| 907 |
|
|
} |
| 908 |
|
|
} |
| 909 |
|
|
} |
| 910 |
|
|
|
| 911 |
|
|
out: |
| 912 |
|
|
|
| 913 |
|
|
if (*timesync == -1) |
| 914 |
|
|
return 0; |
| 915 |
|
|
else |
| 916 |
|
|
return 1; |
| 917 |
|
|
} |
| 918 |
|
|
|
| 919 |
|
|
|
| 920 |
|
|
// Returns the mean value of the elements stored in the vector v. |
| 921 |
|
|
double getMean(vector<Double_t> v) |
| 922 |
|
|
{ |
| 923 |
|
|
double mean = 0; |
| 924 |
|
|
|
| 925 |
|
|
for(int i=0; i < v.size(); i++) |
| 926 |
|
|
mean += v.at(i); |
| 927 |
|
|
|
| 928 |
|
|
return mean/v.size(); |
| 929 |
|
|
} |
| 930 |
|
|
|
| 931 |
|
|
|
| 932 |
|
|
// Shift all non zero bins by shift. |
| 933 |
|
|
TH2F* shiftHist(TH2F* h, Float_t shift) |
| 934 |
|
|
{ |
| 935 |
|
|
// Global bin number. |
| 936 |
|
|
Int_t nBins = h->GetBin(h->GetNbinsX(), h->GetNbinsY()); |
| 937 |
|
|
|
| 938 |
|
|
for(int i = 0; i < nBins; i++) |
| 939 |
|
|
if(h->GetBinContent(i)) h->AddBinContent(i, shift); |
| 940 |
|
|
|
| 941 |
|
|
return h; |
| 942 |
|
|
} |
| 943 |
|
|
|
| 944 |
|
|
|
| 945 |
|
|
// Return a string like YYYY-MM-DD hh:mm:ss, a datetime format. |
| 946 |
|
|
string getTleDatetime(cTle *tle) |
| 947 |
|
|
{ |
| 948 |
|
|
int year, mon, day, hh, mm, ss; |
| 949 |
|
|
double dom; // day of month (is double!) |
| 950 |
|
|
stringstream date; // date in datetime format |
| 951 |
|
|
|
| 952 |
|
|
// create a cJulian from the date in tle |
| 953 |
|
|
cJulian jdate = cJulian( 2000 + (int) tle->getField(cTle::FLD_EPOCHYEAR), tle->getField(cTle::FLD_EPOCHDAY)); |
| 954 |
|
|
|
| 955 |
|
|
// get year, month, day of month |
| 956 |
|
|
jdate.getComponent(&year, &mon, &dom); |
| 957 |
|
|
|
| 958 |
|
|
// build a datetime YYYY-MM-DD hh:mm:ss |
| 959 |
|
|
date.str(""); |
| 960 |
|
|
day = (int) floor(dom); |
| 961 |
|
|
hh = (int) floor( (dom - day) * 24); |
| 962 |
|
|
mm = (int) floor( ((dom - day) * 24 - hh) * 60); |
| 963 |
|
|
ss = (int) floor( ((((dom - day) * 24 - hh) * 60 - mm) * 60)); |
| 964 |
|
|
// ms = (int) floor( (((((dom - day) * 24 - hh) * 60 - mm) * 60) - ss) * 1000); |
| 965 |
|
|
|
| 966 |
|
|
date << year << "-" << mon << "-" << day << " " << hh << ":" << mm << ":" << ss; |
| 967 |
|
|
|
| 968 |
|
|
return date.str(); |
| 969 |
|
|
} |
| 970 |
|
|
|
| 971 |
|
|
// |
| 972 |
|
|
// Solve the overflow for anticoincidence because this counter is |
| 973 |
|
|
// stored in 2 bytes so counts from 0 to 65535. |
| 974 |
|
|
// |
| 975 |
|
|
// counter is the actual value. |
| 976 |
|
|
// oldValue is meant to be the previous value of counter. |
| 977 |
|
|
// |
| 978 |
|
|
// Example: |
| 979 |
|
|
// for(...) { |
| 980 |
|
|
// ... |
| 981 |
|
|
// corrected_diff = solve_ac_overflow(oldValueOfTheCounter, actualValue); |
| 982 |
|
|
// ... |
| 983 |
|
|
// } |
| 984 |
|
|
// |
| 985 |
|
|
// |
| 986 |
|
|
// Returns the corrected difference between counter and oldValue and |
| 987 |
|
|
// set oldValue to the value of counter. |
| 988 |
|
|
// Attention: oldValue is a reference. |
| 989 |
|
|
Int_t solve_ac_overflow(Int_t& oldValue, Int_t counter) |
| 990 |
|
|
{ |
| 991 |
|
|
Int_t truediff = 0; |
| 992 |
|
|
|
| 993 |
|
|
if (counter < oldValue) // overflow! |
| 994 |
|
|
truediff = 0xFFFF - oldValue + counter; |
| 995 |
|
|
else |
| 996 |
|
|
truediff = counter - oldValue; |
| 997 |
|
|
|
| 998 |
|
|
oldValue = counter; |
| 999 |
|
|
|
| 1000 |
|
|
return truediff; |
| 1001 |
|
|
} |