source: trunk/FACT++/src/makeplots.cc@ 15184

Last change on this file since 15184 was 15178, checked in by tbretz, 12 years ago
Added some comments about time zone offsets in root plots.
File size: 11.7 KB
Line 
1#include <libnova/solar.h>
2#include <libnova/lunar.h>
3#include <libnova/rise_set.h>
4#include <libnova/transform.h>
5
6#include "Database.h"
7
8#include "Time.h"
9#include "Configuration.h"
10
11#include <TROOT.h>
12#include <TH1.h>
13#include <TGraph.h>
14#include <TCanvas.h>
15#include <TLegend.h>
16
17using namespace std;
18
19// ------------------------------------------------------------------------
20
21double Angle(double ra, double dec, double r, double d)
22{
23 const double theta0 = M_PI/2-d*M_PI/180;
24 const double phi0 = r*M_PI/12;
25
26 const double theta1 = M_PI/2-dec*M_PI/180;
27 const double phi1 = ra*M_PI/12;
28
29 const double x0 = sin(theta0) * cos(phi0);
30 const double y0 = sin(theta0) * sin(phi0);
31 const double z0 = cos(theta0);
32
33 const double x1 = sin(theta1) * cos(phi1);
34 const double y1 = sin(theta1) * sin(phi1);
35 const double z1 = cos(theta1);
36
37 double arg = x0*x1 + y0*y1 + z0*z1;
38 if(arg > 1.0) arg = 1.0;
39 if(arg < -1.0) arg = -1.0;
40
41 return acos(arg) * 180/M_PI;
42}
43
44void CheckForGap(TCanvas &c, TGraph &g, double axis)
45{
46 if (g.GetN()==0 || axis-g.GetX()[g.GetN()-1]<450)
47 return;
48
49 c.cd();
50 ((TGraph*)g.DrawClone("C"))->SetBit(kCanDelete);
51 while (g.GetN())
52 g.RemovePoint(0);
53}
54
55void DrawClone(TCanvas &c, TGraph &g)
56{
57 if (g.GetN()==0)
58 return;
59
60 c.cd();
61 ((TGraph*)g.DrawClone("C"))->SetBit(kCanDelete);
62}
63
64// ========================================================================
65// ========================================================================
66// ========================================================================
67
68void SetupConfiguration(Configuration &conf)
69{
70 po::options_description control("Smart FACT");
71 control.add_options()
72 ("ra", var<double>(), "Source right ascension")
73 ("dec", var<double>(), "Source declination")
74 ("date-time", var<string>(), "SQL time (UTC)")
75 ("source-database", var<string>(""), "Database link as in\n\tuser:password@server[:port]/database.")
76 ("max-current", var<double>(75), "Maximum current to display in other plots.")
77 ("max-zd", var<double>(75), "Maximum zenith distance to display in other plots")
78 ("no-limits", po_switch(), "Switch off limits in plots")
79 ;
80
81 po::positional_options_description p;
82 p.add("date-time", 1); // The first positional options
83
84 conf.AddOptions(control);
85 conf.SetArgumentPositions(p);
86}
87
88void PrintUsage()
89{
90 cout <<
91 "makeplots - The astronomy plotter\n"
92 "\n"
93 "Calculates several plots for the sources in the database\n"
94 "helpful or needed for scheduling. The Plot is always calculated\n"
95 "for the night which starts at the same so. So no matter if\n"
96 "you specify '1974-09-09 00:00:00' or '1974-09-09 21:56:00'\n"
97 "the plots will refer to the night 1974-09-09/1974-09-10.\n"
98 "The advantage is that specification of the date as in\n"
99 "1974-09-09 is enough. Time axis starts and ends at nautical\n"
100 "twilight which is 12deg below horizon.\n"
101 "\n"
102 "Usage: makeplots sql-datetime [--ra={ra} --dec={dec}]\n";
103 cout << endl;
104}
105
106int main(int argc, const char* argv[])
107{
108 gROOT->SetBatch();
109
110 Configuration conf(argv[0]);
111 conf.SetPrintUsage(PrintUsage);
112 SetupConfiguration(conf);
113
114 if (!conf.DoParse(argc, argv))
115 return 127;
116
117 if (conf.Has("ra")^conf.Has("dec"))
118 {
119 cout << "ERROR - Either --ra or --dec missing." << endl;
120 return 1;
121 }
122
123 // ------------------ Eval config ---------------------
124
125 const double lon = -(17.+53./60+26.525/3600);
126 const double lat = 28.+45./60+42.462/3600;
127
128 ln_lnlat_posn observer;
129 observer.lng = lon;
130 observer.lat = lat;
131
132 Time time;
133 if (conf.Has("date-time"))
134 time.SetFromStr(conf.Get<string>("date-time"));
135
136 const double max_current = conf.Get<double>("max-current");
137 const double max_zd = conf.Get<double>("max-zd");
138 const double no_limits = conf.Get<bool>("no-limits");
139
140 // -12: nautical
141 ln_rst_time sun_set; // Sun set with the same date than th provided date
142 ln_rst_time sun_rise; // Sun rise on the following day
143 ln_get_solar_rst_horizon(time.JD()-0.5, &observer, -12, &sun_set);
144 ln_get_solar_rst_horizon(time.JD()+0.5, &observer, -12, &sun_rise);
145
146 const double jd = floor(time.Mjd())+2400001;
147 const double mjd = floor(time.Mjd())+49718+0.5; // root time
148
149 cout << "Time: " << time << endl;
150 cout << "Base: " << Time(jd-0.5) << endl;
151 cout << "Set: " << Time(sun_set.set) << endl;
152 cout << "Rise: " << Time(sun_rise.rise) << endl;
153
154 const double jd0 = fmod(sun_set.set, 1); // ~0.3
155 const double jd1 = fmod(sun_rise.rise, 1); // ~0.8
156
157 const string fDatabase = conf.Get<string>("source-database");
158
159 // ------------------ Precalc moon coord ---------------------
160
161 vector<pair<ln_equ_posn, double>> fMoonCoords;
162
163 for (double h=0; h<1; h+=1./(24*12))
164 {
165 ln_equ_posn moon;
166 ln_get_lunar_equ_coords_prec(jd+h, &moon, 0.01);
167
168 const double disk = ln_get_lunar_disk(jd+h);
169
170 fMoonCoords.push_back(make_pair(moon, disk));
171 }
172
173 // ------------- Get Sources from databasse ---------------------
174
175 const mysqlpp::StoreQueryResult res =
176 Database(fDatabase).query("SELECT fSourceName, fRightAscension, fDeclination FROM source").store();
177
178 // ------------- Create canvases and frames ---------------------
179
180 // It is important to use an offset which is larger than
181 // 1970-01-01 00:00:00. This one will not work if your
182 // local time zone is positive!
183 TH1S hframe("", "", 1, (mjd+jd0)*24*3600, (mjd+jd1)*24*3600);
184 hframe.SetStats(kFALSE);
185 hframe.GetXaxis()->SetTimeFormat("%Hh%M%F1995-01-01 00:00:00 GMT");
186 hframe.GetXaxis()->SetTitle((Time(jd).GetAsStr("%d/%m/%Y")+" - "+Time(jd+1).GetAsStr("%d/%m/%Y")+" [UTC]").c_str());
187 hframe.GetXaxis()->CenterTitle();
188 hframe.GetYaxis()->CenterTitle();
189 hframe.GetXaxis()->SetTimeDisplay(true);
190 hframe.GetYaxis()->SetTitleSize(0.040);
191 hframe.GetXaxis()->SetTitleSize(0.040);
192 hframe.GetXaxis()->SetTitleOffset(1.1);
193 hframe.GetYaxis()->SetLabelSize(0.040);
194 hframe.GetXaxis()->SetLabelSize(0.040);
195
196 TCanvas c1;
197 c1.SetFillColor(kWhite);
198 c1.SetBorderMode(0);
199 c1.SetFrameBorderMode(0);
200 c1.SetLeftMargin(0.085);
201 c1.SetRightMargin(0.01);
202 c1.SetTopMargin(0.03);
203 c1.SetGrid();
204 hframe.GetYaxis()->SetTitle("Altitude [deg]");
205 hframe.SetMinimum(15);
206 hframe.SetMaximum(90);
207 hframe.DrawCopy();
208
209 TCanvas c2;
210 c2.SetFillColor(kWhite);
211 c2.SetBorderMode(0);
212 c2.SetFrameBorderMode(0);
213 c2.SetLeftMargin(0.085);
214 c2.SetRightMargin(0.01);
215 c2.SetTopMargin(0.03);
216 c2.SetGrid();
217 hframe.GetYaxis()->SetTitle("Predicted Current [\\muA]");
218 hframe.SetMinimum(0);
219 hframe.SetMaximum(100);
220 hframe.DrawCopy();
221
222 TCanvas c3;
223 c3.SetFillColor(kWhite);
224 c3.SetBorderMode(0);
225 c3.SetFrameBorderMode(0);
226 c3.SetLeftMargin(0.085);
227 c3.SetRightMargin(0.01);
228 c3.SetTopMargin(0.03);
229 c3.SetGrid();
230 c3.SetLogy();
231 hframe.GetYaxis()->SetTitle("Estimated relative threshold");
232 hframe.SetMinimum(0.9);
233 hframe.SetMaximum(180);
234 hframe.DrawCopy();
235
236 TCanvas c4;
237 c4.SetFillColor(kWhite);
238 c4.SetBorderMode(0);
239 c4.SetFrameBorderMode(0);
240 c4.SetLeftMargin(0.085);
241 c4.SetRightMargin(0.01);
242 c4.SetTopMargin(0.03);
243 c4.SetGrid();
244 hframe.GetYaxis()->SetTitle("Distance to moon [deg]");
245 hframe.SetMinimum(0);
246 hframe.SetMaximum(180);
247 hframe.DrawCopy();
248
249 Int_t color[] = { kBlack, kRed, kBlue, kGreen, kCyan, kMagenta };
250 Int_t style[] = { kSolid, kDashed, kDotted };
251
252 TLegend leg(0, 0, 1, 1);
253
254 // ------------- Loop over sources ---------------------
255
256 Int_t cnt=0;
257 for (vector<mysqlpp::Row>::const_iterator v=res.begin(); v<res.end(); v++, cnt++)
258 {
259 // Eval row
260 const string name = (*v)[0].c_str();
261
262 ln_equ_posn pos;
263 pos.ra = double((*v)[1])*15;
264 pos.dec = double((*v)[2]);
265
266 // Create graphs
267 TGraph g1, g2, g3, g4, gr, gm;
268 g1.SetName(name.data());
269 g2.SetName(name.data());
270 g3.SetName(name.data());
271 g4.SetName(name.data());
272 g1.SetLineWidth(2);
273 g2.SetLineWidth(2);
274 g3.SetLineWidth(2);
275 g4.SetLineWidth(2);
276 gm.SetLineWidth(1);
277 g1.SetLineStyle(style[cnt/6]);
278 g2.SetLineStyle(style[cnt/6]);
279 g3.SetLineStyle(style[cnt/6]);
280 g4.SetLineStyle(style[cnt/6]);
281 g1.SetLineColor(color[cnt%6]);
282 g2.SetLineColor(color[cnt%6]);
283 g3.SetLineColor(color[cnt%6]);
284 g4.SetLineColor(color[cnt%6]);
285 gm.SetLineColor(kYellow);
286
287 if (cnt==0)
288 leg.AddEntry(gm.Clone(), "Moon", "l");
289 leg.AddEntry(g1.Clone(), name.data(), "l");
290
291 // Loop over 24 hours
292 int i=0;
293 for (double h=0; h<1; h+=1./(24*12), i++)
294 {
295 // check if it is betwene sun-rise and sun-set
296 if (h<jd0 || h>jd1)
297 continue;
298
299 // get local position of source
300 ln_hrz_posn hrz;
301 ln_get_hrz_from_equ(&pos, &observer, jd+h, &hrz);
302
303 // Get moon properties and
304 ln_equ_posn moon = fMoonCoords[i].first;
305 const double disk = fMoonCoords[i].second;
306
307 ln_hrz_posn hrzm;
308 ln_get_hrz_from_equ(&moon, &observer, jd+h, &hrzm);
309
310 // Distance between source and moon
311 const double angle = Angle(moon.ra, moon.dec, pos.ra, pos.dec);
312
313 // Current prediction
314 const double cang = sin(angle *M_PI/180);
315 const double calt = sin(hrzm.alt*M_PI/180);
316
317 const double lc = cang==0 ? -1 : calt*pow(disk, 3)/sqrt(cang);
318 const double cur = lc>0 ? 8.1+94.6*lc : 8.1;
319
320 // Relative energy threshold prediction
321 const double cs = cos((90+hrz.alt)*M_PI/180);
322 const double ratio = (10.*sqrt(409600.*cs*cs+9009.) + 6400.*cs - 60.)/10.;
323
324 // Add points to curve
325 const double axis = (mjd+h)*24*3600;
326
327 // If there is a gap of more than one bin, start a new curve
328 CheckForGap(c1, g1, axis);
329 CheckForGap(c1, gm, axis);
330 CheckForGap(c2, g2, axis);
331 CheckForGap(c3, g3, axis);
332 CheckForGap(c4, g4, axis);
333
334 // Add data
335 if (no_limits || cur<max_current)
336 g1.SetPoint(g1.GetN(), axis, hrz.alt);
337
338 if (no_limits || 90-hrz.alt<max_zd)
339 g2.SetPoint(g2.GetN(), axis, cur);
340
341 if (no_limits || (cur<max_current && 90-hrz.alt<max_zd))
342 g3.SetPoint(g3.GetN(), axis, ratio*cur/8.1);
343
344 if (no_limits || (cur<max_current && 90-hrz.alt<max_zd))
345 g4.SetPoint(g4.GetN(), axis, angle);
346
347 if (cnt==0)
348 gm.SetPoint(gm.GetN(), axis, hrzm.alt);
349 }
350
351 if (cnt==0)
352 DrawClone(c1, gm);
353
354 DrawClone(c1, g1);
355 DrawClone(c2, g2);
356 DrawClone(c3, g3);
357 DrawClone(c4, g4);
358 }
359
360
361 // Save three plots
362 TCanvas c5;
363 c5.SetFillColor(kWhite);
364 c5.SetBorderMode(0);
365 c5.SetFrameBorderMode(0);
366 leg.Draw();
367
368 const string t = Time(jd).GetAsStr("%Y%m%d");
369
370 c1.SaveAs((t+"-ZenithDistance.eps").c_str());
371 c2.SaveAs((t+"-PredictedCurrent.eps").c_str());
372 c3.SaveAs((t+"-RelativeThreshold.eps").c_str());
373 c4.SaveAs((t+"-MoonDist.eps").c_str());
374 c5.SaveAs((t+"-Legend.eps").c_str());
375
376 c1.SaveAs((t+"-ZenithDistance.root").c_str());
377 c2.SaveAs((t+"-PredictedCurrent.root").c_str());
378 c3.SaveAs((t+"-RelativeThreshold.root").c_str());
379 c4.SaveAs((t+"-MoonDist.root").c_str());
380
381 return 0;
382}
Note: See TracBrowser for help on using the repository browser.