source: trunk/FACT++/src/makeschedule.cc@ 18428

Last change on this file since 18428 was 18418, checked in by tbretz, 9 years ago
Fixed a bug which was introduced with the simplification of the code, the threshold wasn't calculated anymore at all.
File size: 23.2 KB
Line 
1#include "externals/Prediction.h"
2
3//#include <unordered_map>
4#include <boost/algorithm/string/join.hpp>
5
6#include "Database.h"
7
8#include "tools.h"
9#include "Time.h"
10#include "Configuration.h"
11
12/*
13#include <TROOT.h>
14#include <TH1.h>
15#include <TGraph.h>
16#include <TCanvas.h>
17#include <TLegend.h>
18*/
19
20using namespace std;
21using namespace Nova;
22
23// -----------------------------------------------------------------------
24
25/*
26void CheckForGap(TCanvas &c, TGraph &g, double axis)
27{
28 if (g.GetN()==0 || axis-g.GetX()[g.GetN()-1]<450)
29 return;
30
31 c.cd();
32 ((TGraph*)g.DrawClone("C"))->SetBit(kCanDelete);
33 while (g.GetN())
34 g.RemovePoint(0);
35}
36
37void DrawClone(TCanvas &c, TGraph &g)
38{
39 if (g.GetN()==0)
40 return;
41
42 c.cd();
43 ((TGraph*)g.DrawClone("C"))->SetBit(kCanDelete);
44}
45*/
46
47// ========================================================================
48// ========================================================================
49// ========================================================================
50
51void SetupConfiguration(Configuration &conf)
52{
53 po::options_description control("Makeschedule");
54 control.add_options()
55 ("date", var<string>(), "SQL time (UTC), e.g. '2016-12-24'")
56 ("source-database", var<string>(""), "Database link as in\n\tuser:password@server[:port]/database.")
57 ("max-current", var<double>(90), "Global maximum current limit in uA")
58 ("max-zd", var<double>(75), "Global zenith distance limit in degree")
59 ("source", vars<string>(), "List of all TeV sources to be included, names according to the database")
60 ("setup.*", var<double>(), "Setup for the sources to be observed")
61 ("preobs.*", vars<string>(), "Prescheduled observations")
62 ("startup.offset", var<double>(15), "Determines how many minutes the startup is scheduled before data-taking.start [0;120]")
63 ("data-taking.start", var<double>(-12), "Begin of data-taking in degree of sun below horizon")
64 ("data-taking.end", var<double>(-13.75), "End of data-taking in degree of sun below horizon")
65 ;
66
67 po::positional_options_description p;
68 p.add("date", 1); // The first positional options
69
70 conf.AddOptions(control);
71 conf.SetArgumentPositions(p);
72}
73
74void PrintUsage()
75{
76 cout <<
77 "makeschedule - Creates an automatic schedule\n"
78 "\n"
79 "Usage: makeschedule [yyyy-mm-dd]\n";
80 cout << endl;
81}
82
83void PrintHelp()
84{
85#ifdef HAVE_ROOT
86 cout <<
87 "\n"
88 "Examples:\n"
89 "\n"
90 " makeschedule 2016-12-24\n"
91 "\n"
92 "Calculate the Christmas schedule for 2016 using all TeV sources from the\n"
93 "database. If the date is omitted the current date is used.\n"
94 "\n"
95 " makeschedule --source='Mrk 421' --source='Mrk 501' --source='Crab'\n"
96 "\n"
97 "Use only the mentioned sources to calculate the schedule.\n"
98 "\n"
99 " makeschedule --source=Crab --setup.Crab.max-zd=30\n"
100 "\n"
101 "Limit the zenith distance of Crab into the range [0;30]deg.\n"
102 "\n"
103 " makeschedule --source=Crab --setup.Crab.max-current=50\n"
104 "\n"
105 "Limit the maximum estimated current of Crab at 50uA.\n"
106 "\n"
107 " makeschedule --source='IC 310' '--setup.IC 310.penalty=1.2'\n"
108 "\n"
109 "Multiply IC310's estimated relative threshold by a factor 1.2\n"
110 "\n";
111 cout << endl;
112#endif
113}
114
115
116struct MyDouble
117{
118 double val;
119 bool valid;
120 MyDouble(Configuration &conf, const string &str) : val(0)
121 {
122 valid = conf.Has(str);
123 if (valid)
124 val = conf.Get<double>(str);
125 }
126 MyDouble() : val(0), valid(false) {}
127};
128
129/*
130struct MinMax
131{
132 MyDouble min;
133 MyDouble max;
134 MinMax(Configuration &conf, const string &str)
135 {
136 min = MyDouble(conf, str+".min");
137 max = MyDouble(conf, str+".max");
138 }
139 MinMax() {}
140};
141*/
142
143struct Source
144{
145 // Global limits
146 static double max_current;
147 static double max_zd;
148
149 // Source descrition
150 string name;
151 EquPosn equ;
152
153 // Source specific limits
154 MyDouble maxzd;
155 MyDouble maxcurrent;
156 double penalty;
157
158 // Possible observation time
159 double begin;
160 double end;
161
162 // Threshold (sorting reference)
163 double threshold;
164
165 double duration() const { return end-begin; };
166
167 // Pre-observations (e.g. ratescan)
168 vector<string> preobs;
169
170 Source(const string &n="") : name(n), begin(0), threshold(std::numeric_limits<double>::max()) { }
171
172 //bool IsSpecial() const { return threshold==std::numeric_limits<double>::max(); }
173
174 double zd(const double &jd) const
175 {
176 return 90-GetHrzFromEqu(equ, jd).alt;
177 }
178
179 bool valid(const SolarObjects &so) const
180 {
181 const HrzPosn hrz = GetHrzFromEqu(equ, so.fJD);
182 const double current = FACT::PredictI(so, equ);
183
184 if (current>max_current)
185 return false;
186
187 if (hrz.alt<=0 || 90-hrz.alt>max_zd)
188 return false;
189
190 if (maxzd.valid && 90-hrz.alt>maxzd.val)
191 return false;
192
193 if (maxcurrent.valid && current>maxcurrent.val)
194 return false;
195
196 return true;
197 }
198
199 bool IsRangeValid(const double &jd_begin, const double &jd_end) const
200 {
201 const double step = 1./24/60;
202 for (double jd=jd_begin; jd<jd_end+step/2; jd++)
203 if (!valid(SolarObjects(jd)))
204 return false;
205
206 return true;
207 }
208
209 double getThreshold(const SolarObjects &so) const
210 {
211 const HrzPosn hrz = GetHrzFromEqu(equ, so.fJD);
212 const double current = FACT::PredictI(so, equ);
213
214 const double ratio = pow(cos((90-hrz.alt)*M_PI/180), -2.664);
215
216 return penalty*ratio*pow(current/6.2, 0.394);
217 }
218
219 bool calcThreshold(const SolarObjects &so)
220 {
221 const HrzPosn hrz = GetHrzFromEqu(equ, so.fJD);
222 const double current = FACT::PredictI(so, equ);
223
224 if (current>max_current)
225 return false;
226
227 if (hrz.alt<=0 || 90-hrz.alt>max_zd)
228 return false;
229
230 if (maxzd.valid && 90-hrz.alt>maxzd.val)
231 return false;
232
233 if (maxcurrent.valid && current>maxcurrent.val)
234 return false;
235
236 const double ratio = pow(cos((90-hrz.alt)*M_PI/180), -2.664);
237 threshold = penalty*ratio*pow(current/6.2, 0.394);
238
239 return true;
240 }
241};
242
243double Source::max_zd;
244double Source::max_current;
245
246bool SortByThreshold(const Source &i, const Source &j) { return i.threshold<j.threshold; }
247
248bool RescheduleFirstSources(vector<Source> &obs)
249{
250 if (obs.size()<2 || obs[0].duration()>=40./24/60 || obs[0].name=="SLEEP" || obs[1].name=="SLEEP")
251 return false;
252
253 cout << "First source [" << obs[0].name << "] detected < 40min" << endl;
254
255 const double obs1_duration = obs[1].end - obs[0].begin - 40./24/60;
256 const double obs0_end = obs[0].begin + 40./24/60;
257
258 // Check that:
259 // - the duration for the shrunken source obs[1] is still above 40min
260 // - obs[0] does not exceed 60deg at the end of its new window
261 // - obs[0] does not exceed any limit within the new window
262
263 if (obs1_duration>=40./24/60 && obs[0].IsRangeValid(obs[0].end, obs0_end))
264 {
265 obs[0].end = obs0_end;
266 obs[1].begin = obs0_end;
267
268 cout << "First source [" << obs[0].name << "] extended to 40min" << endl;
269
270 return false;
271 }
272
273 // Try to remove the first source, check if second source fullfills all limits
274 if (obs[1].IsRangeValid(obs[0].begin, obs[0].end))
275 {
276 cout << "First source [" << obs[0].name << "] removed" << endl;
277
278 obs[1].begin = obs[0].begin;
279 obs.erase(obs.begin());
280
281 return true;
282 }
283
284 // Try to remove the second source, check if the first source fullfills all limits
285 if (obs[0].IsRangeValid(obs[1].begin, obs[1].end))
286 {
287 cout << "Second source [" << obs[1].name << "] removed" << endl;
288
289 obs[0].end = obs[1].end;
290 obs.erase(obs.begin()+1);
291
292 if (obs.size()==0 || obs[0].name!=obs[1].name)
293 return true;
294
295 obs[0].end = obs[1].end;
296 obs.erase(obs.begin()+1);
297
298 cout << "Combined first two indentical sources [" << obs[0].name << "] into one observation" << endl;
299
300 return true;
301 }
302
303 cout << "No reschedule possible within limit." << endl;
304
305 return false;
306}
307
308bool RescheduleLastSources(vector<Source> &obs)
309{
310 // If observation time is smaller than 40min for the first source
311 // extend it to 40min if zenith angle will not go above 60deg.
312 const int last = obs.size()-1;
313 if (obs.size()<2 || obs[last].duration()>=40./24/60 || obs[last].name=="SLEEP" || obs[last-1].name=="SLEEP")
314 return false;
315
316 cout << "Last source [" << obs[last].name << "] detected < 40min" << endl;
317
318 const double obs1_duration = obs[last].end - 40./24/60 - obs[last-1].begin;
319 const double obs0_begin = obs[last].end - 40./24/60;
320
321 // Check that:
322 // - the duration for the shrunken source obs[1] is still above 40min
323 // - obs[0] does not exceed 60deg at the end of its new window
324 // - obs[0] does not exceed any limit within the new window
325
326 if (obs1_duration>=40./24/60 && obs[last].IsRangeValid(obs0_begin, obs[last].begin))
327 {
328 obs[last].begin = obs0_begin;
329 obs[last-1].end = obs0_begin;
330
331 cout << "Last source [" << obs[last].name << "] extended to 40min" << endl;
332
333 return false;
334 }
335
336 // Try to remove the last source, check if second source fullfills all limits
337 if (obs[last-1].IsRangeValid(obs[last].begin, obs[last].end))
338 {
339 cout << "Last source [" << obs[last].name << "] removed" << endl;
340
341 obs[last-1].end = obs[last].end;
342 obs.pop_back();
343
344 return true;
345 }
346
347 // Try to remove the second last source, check if the first source fullfills all limits
348 if (obs[last].IsRangeValid(obs[last-1].begin, obs[last-1].end))
349 {
350 cout << "Second last source [" << obs[last-1].name << "] removed" << endl;
351
352 obs[last].begin = obs[last-1].begin;
353 obs.erase(obs.begin()+obs.size()-2);
354
355 if (obs.size()==0 || obs[last-1].name!=obs[last-2].name)
356 return true;
357
358 obs[last-2].end = obs[last-1].end;
359 obs.pop_back();
360
361 cout << "Combined last two indentical sources [" << obs[last-1].name << "] into one observation" << endl;
362
363 return true;
364 }
365
366 cout << "No reschedule possible within limit." << endl;
367
368 return false;
369}
370
371bool RescheduleIntermediateSources(vector<Source> &obs)
372{
373 for (size_t i=1; i<obs.size()-1; i++)
374 {
375 if (obs[i].duration()>=40./24/60)
376 continue;
377
378 if (obs[i-1].name=="SLEEP" && obs[i+1].name=="SLEEP")
379 continue;
380
381 cout << "Intermediate source [" << obs[i].name << "] detected < 40min" << endl;
382
383 double intersection = -1;
384
385 if (obs[i-1].name=="SLEEP")
386 intersection = obs[i].begin;
387
388 if (obs[i+1].name=="SLEEP")
389 intersection = obs[i].end;
390
391 if (obs[i-1].name==obs[i+1].name)
392 intersection = obs[i].begin;
393
394 if (intersection<0)
395 {
396 const double step = 1./24/60;
397 for (double jd=obs[i].begin; jd<obs[i].end-step/2; jd+=step)
398 {
399 const SolarObjects so(jd);
400 if (obs[i-1].getThreshold(so)>=obs[i+1].getThreshold(so))
401 {
402 intersection = jd;
403 break;
404 }
405 }
406 }
407
408 if ((obs[i-1].name!="SLEEP" && !obs[i-1].IsRangeValid(obs[i-1].end, intersection)) ||
409 (obs[i+1].name!="SLEEP" && !obs[i+1].IsRangeValid(intersection, obs[i+1].begin)))
410 {
411 cout << "No reschedule possible within limits." << endl;
412 continue;
413 }
414
415 cout << "Intermediate source [" << obs[i].name << "] removed" << endl;
416
417 const bool underflow = obs[i-1].duration()*24*60<40 || obs[i+1].duration()*24*60<40;
418
419 obs[i-1].end = intersection;
420 obs[i+1].begin = intersection;
421 obs.erase(obs.begin()+i);
422
423 i--;
424
425 if (obs.size()>1 && obs[i].name==obs[i+1].name)
426 {
427 obs[i].end = obs[i+1].end;
428 obs.erase(obs.begin()+i+1);
429
430 cout << "Combined two surrounding indentical sources [" << obs[i].name << "] into one observation" << endl;
431
432 i--;
433
434 continue;
435 }
436
437 if (underflow)
438 cout << "WARNING - Neighbor source < 40min as well." << endl;
439 }
440 return false;
441}
442
443void Print(const vector<Source> &obs, double startup_offset)
444{
445 cout << Time(obs[0].begin-startup_offset).GetAsStr() << " STARTUP\n";
446 for (const auto& src: obs)
447 {
448 string tm = Time(src.begin).GetAsStr();
449
450 if (src.preobs.size()>0)
451 {
452 for (const auto& pre: src.preobs)
453 {
454 cout << tm << " " << pre << "\n";
455 tm = " ";
456 }
457 }
458
459 cout << tm << " " << src.name << " [";
460 cout << src.duration()*24*60 << "'";
461 if (src.name!="SLEEP")
462 cout << Tools::Form("; %.1f/%.1f", src.zd(src.begin), src.zd(src.end));
463 cout << "]";
464
465 if (src.duration()*24*60<40)
466 cout << " (!)";
467
468 cout << "\n";
469 }
470 cout << Time(obs.back().end).GetAsStr() << " SHUTDOWN" << endl;
471}
472
473int main(int argc, const char* argv[])
474{
475// gROOT->SetBatch();
476
477 Configuration conf(argv[0]);
478 conf.SetPrintUsage(PrintUsage);
479 SetupConfiguration(conf);
480
481 if (!conf.DoParse(argc, argv, PrintHelp))
482 return 127;
483
484 // ------------------ Eval config ---------------------
485
486 Time time;
487 if (conf.Has("date"))
488 time.SetFromStr(conf.Get<string>("date")+" 12:00:00");
489
490 Source::max_current = conf.Get<double>("max-current");
491 Source::max_zd = conf.Get<double>("max-zd");
492
493 const double startup_offset = conf.Get<double>("startup.offset")/60/24;
494
495 const double angle_sun_set = conf.Get<double>("data-taking.start");
496 const double angle_sun_rise = conf.Get<double>("data-taking.end");
497
498 if (startup_offset<0 || startup_offset>120)
499 throw runtime_error("Only values [0;120] are allowed for startup.offset");
500
501 if (angle_sun_set>-6)
502 throw runtime_error("datataking.start not allowed before sun at -6deg");
503
504 if (angle_sun_rise>-6)
505 throw runtime_error("datataking.end not allowed after sun at -6deg");
506
507 // -12: nautical
508 // Sun set with the same date than th provided date
509 // Sun rise on the following day
510 const RstTime sun_set = GetSolarRst(time.JD()-0.5, angle_sun_set);
511 const RstTime sun_rise = GetSolarRst(time.JD()+0.5, angle_sun_rise);
512
513 const double sunset = ceil(sun_set.set*24*60)/24/60;
514 const double sunrise = floor(sun_rise.rise*24*60)/24/60;
515
516 cout << "\n";
517 cout << "Date: " << Time(floor(sunset)) << "\n";
518 cout << "Set: " << Time(sun_set.set) << "\n";
519 cout << "Rise: " << Time(sun_rise.rise) << "\n";
520 cout << endl;
521
522 // ------------- Get Sources from databasse ---------------------
523
524 const vector<string> ourcenames = conf.Vec<string>("source");
525 const vector<string> sourcenames = conf.Vec<string>("source");
526 cout << "Nsources = " << sourcenames.size() << "\n";
527
528 string query = "SELECT fSourceName, fRightAscension, fDeclination FROM Source WHERE fSourceTypeKEY=1";
529 if (sourcenames.size()>0)
530 query += " AND fSourceName IN ('" + boost::algorithm::join(sourcenames, "', '")+"')";
531
532 const string fDatabase = conf.Get<string>("source-database");
533 const mysqlpp::StoreQueryResult res =
534 Database(fDatabase).query(query).store();
535
536 // ------------------ Eval config ---------------------
537
538 vector<Source> sources;
539 for (const auto &row: res)
540 {
541 const string name = string(row[0]);
542
543 Source src(name);
544
545 src.equ.ra = double(row[1])*15;
546 src.equ.dec = double(row[2]);
547
548 src.maxzd = MyDouble(conf, "setup."+name+".max-zd");
549 src.maxcurrent = MyDouble(conf, "setup."+name+".max-current");
550 src.penalty = conf.Has("setup."+name+".penalty") ?
551 conf.Get<double>("setup."+name+".penalty") : 1;
552
553 src.preobs = conf.Vec<string>("preobs."+name);
554
555
556 cout << "[" << name << "]";
557
558 if (src.maxzd.valid)
559 cout << " Zd<" << src.maxzd.val;
560 if (src.penalty!=1)
561 cout << " Penalty=" << src.penalty;
562
563 cout << " " << boost::algorithm::join(src.preobs, "+") << endl;
564
565 /*
566 RstTime t1 = GetObjectRst(floor(sunset)-1, src.equ);
567 RstTime t2 = GetObjectRst(floor(sunset), src.equ);
568
569 src.rst.transit = t1.transit<floor(sunset) ? t2.transit : t1.transit;
570 src.rst.rise = t1.rise>src.rst.transit ? t2.rise : t1.rise;
571 src.rst.set = t1.set <src.rst.transit ? t2.set : t1.set;
572 */
573
574 sources.emplace_back(src);
575 }
576 cout << endl;
577
578 // -------------------------------------------------------------------------
579
580 vector<Source> obs;
581
582 const double step = 1./24/60;
583 for (double jd=sunset; jd<sunrise-step/2; jd+=step)
584 {
585 const SolarObjects so(jd);
586
587 vector<Source> vis;
588 for (auto& src: sources)
589 {
590 if (src.calcThreshold(so))
591 vis.emplace_back(src);
592 }
593
594 // In case no source was found, add a sleep source
595 Source src("SLEEP");
596 vis.emplace_back(src);
597
598 // Source has higher priority if minimum observation time not yet fullfilled
599 sort(vis.begin(), vis.end(), SortByThreshold);
600
601 if (obs.size()>0 && obs.back().name==vis[0].name)
602 continue;
603
604 vis[0].begin = jd;
605 obs.emplace_back(vis[0]);
606 }
607
608 if (obs.size()==0)
609 {
610 cout << "No source found." << endl;
611 return 0;
612 }
613
614 // -------------------------------------------------------------------------
615
616 for (auto it=obs.begin(); it<obs.end()-1; it++)
617 it[0].end = it[1].begin;
618 obs.back().end = sunrise;
619
620 // -------------------------------------------------------------------------
621
622 Print(obs, startup_offset);
623 cout << endl;
624
625 // -------------------------------------------------------------------------
626
627 while (RescheduleFirstSources(obs));
628 while (RescheduleLastSources(obs));
629 while (RescheduleIntermediateSources(obs));
630
631 // ---------------------------------------------------------------------
632
633 cout << endl;
634 Print(obs, startup_offset);
635 cout << endl;
636
637 // ---------------------------------------------------------------------
638
639 return 1;
640
641 // ------------- Create canvases and frames ---------------------
642/*
643 // It is important to use an offset which is larger than
644 // 1970-01-01 00:00:00. This one will not work if your
645 // local time zone is positive!
646 TH1S hframe("", "", 1, Time(sunset).Mjd()*24*3600, Time(sunrise).Mjd()*24*3600);
647 hframe.SetStats(kFALSE);
648 hframe.GetXaxis()->SetTimeFormat("%Hh%M%F1995-01-01 00:00:00 GMT");
649 hframe.GetXaxis()->SetTitle((Time(jd).GetAsStr("%d/%m/%Y")+" - "+Time(jd+1).GetAsStr("%d/%m/%Y")+" [UTC]").c_str());
650 hframe.GetXaxis()->CenterTitle();
651 hframe.GetYaxis()->CenterTitle();
652 hframe.GetXaxis()->SetTimeDisplay(true);
653 hframe.GetYaxis()->SetTitleSize(0.040);
654 hframe.GetXaxis()->SetTitleSize(0.040);
655 hframe.GetXaxis()->SetTitleOffset(1.1);
656 hframe.GetYaxis()->SetLabelSize(0.040);
657 hframe.GetXaxis()->SetLabelSize(0.040);
658
659 TCanvas c1;
660 c1.SetFillColor(kWhite);
661 c1.SetBorderMode(0);
662 c1.SetFrameBorderMode(0);
663 c1.SetLeftMargin(0.085);
664 c1.SetRightMargin(0.01);
665 c1.SetTopMargin(0.03);
666 c1.SetGrid();
667 hframe.GetYaxis()->SetTitle("Altitude [deg]");
668 hframe.SetMinimum(15);
669 hframe.SetMaximum(90);
670 hframe.DrawCopy();
671
672 TCanvas c2;
673 c2.SetFillColor(kWhite);
674 c2.SetBorderMode(0);
675 c2.SetFrameBorderMode(0);
676 c2.SetLeftMargin(0.085);
677 c2.SetRightMargin(0.01);
678 c2.SetTopMargin(0.03);
679 c2.SetGrid();
680 hframe.GetYaxis()->SetTitle("Predicted Current [#muA]");
681 hframe.SetMinimum(0);
682 hframe.SetMaximum(100);
683 hframe.DrawCopy();
684
685 TCanvas c3;
686 c3.SetFillColor(kWhite);
687 c3.SetBorderMode(0);
688 c3.SetFrameBorderMode(0);
689 c3.SetLeftMargin(0.085);
690 c3.SetRightMargin(0.01);
691 c3.SetTopMargin(0.03);
692 c3.SetGrid();
693 c3.SetLogy();
694 hframe.GetYaxis()->SetTitle("Estimated relative threshold");
695 hframe.GetYaxis()->SetMoreLogLabels();
696 hframe.SetMinimum(0.9);
697 hframe.SetMaximum(11);
698 hframe.DrawCopy();
699
700 TCanvas c4;
701 c4.SetFillColor(kWhite);
702 c4.SetBorderMode(0);
703 c4.SetFrameBorderMode(0);
704 c4.SetLeftMargin(0.085);
705 c4.SetRightMargin(0.01);
706 c4.SetTopMargin(0.03);
707 c4.SetGrid();
708 hframe.GetYaxis()->SetTitle("Distance to moon [deg]");
709 hframe.SetMinimum(0);
710 hframe.SetMaximum(180);
711 hframe.DrawCopy();
712 Int_t color[] = { kBlack, kRed, kBlue, kGreen, kCyan, kMagenta };
713 Int_t style[] = { kSolid, kDashed, kDotted };
714
715 // TLegend leg(0, 0, 1, 1);
716
717 // ------------- Loop over sources ---------------------
718
719 for (vector<mysqlpp::Row>::const_iterator v=res.begin(); v<res.end(); v++, cnt++)
720 {
721 // Eval row
722 const string name = (*v)[0].c_str();
723
724 EquPosn pos;
725 pos.ra = double((*v)[1])*15;
726 pos.dec = double((*v)[2]);
727
728 // Loop over 24 hours
729 for (double h=0; h<1; h+=1./(24*12))
730 {
731 const SolarObjects so(jd+h);
732
733 // get local position of source
734 const HrzPosn hrz = GetHrzFromEqu(pos, so.fJD);
735
736 if (v==res.begin())
737 cout << Time(so.fJD) <<" " << 90-so.fMoonHrz.alt << endl;
738
739 const double cur = FACT::PredictI(so, pos);
740
741 // Relative energy threshold prediction
742 const double ratio = pow(cos((90-hrz.alt)*M_PI/180), -2.664);
743
744 // Add points to curve
745 const double axis = Time(so.fJD).Mjd()*24*3600;
746
747 // If there is a gap of more than one bin, start a new curve
748
749 // Add data
750 if (no_limits || cur<max_current)
751 g1.SetPoint(g1.GetN(), axis, hrz.alt);
752
753 if (no_limits || 90-hrz.alt<max_zd)
754 g2.SetPoint(g2.GetN(), axis, cur);
755
756 if (no_limits || (cur<max_current && 90-hrz.alt<max_zd))
757 g3.SetPoint(g3.GetN(), axis, ratio*pow(cur/6.2, 0.394));
758
759 if (no_limits || (cur<max_current && 90-hrz.alt<max_zd))
760 {
761 const double angle = GetAngularSeparation(so.fMoonEqu, pos);
762 g4.SetPoint(g4.GetN(), axis, angle);
763 }
764
765 if (cnt==0)
766 gm.SetPoint(gm.GetN(), axis, so.fMoonHrz.alt);
767 }
768 }
769
770 // Save three plots
771 TCanvas c5;
772 c5.SetFillColor(kWhite);
773 c5.SetBorderMode(0);
774 c5.SetFrameBorderMode(0);
775 leg.Draw();
776
777 const string t = Time(jd).GetAsStr("%Y%m%d");
778
779 c1.SaveAs((t+"-ZenithDistance.eps").c_str());
780 c2.SaveAs((t+"-PredictedCurrent.eps").c_str());
781 c3.SaveAs((t+"-RelativeThreshold.eps").c_str());
782 c4.SaveAs((t+"-MoonDist.eps").c_str());
783 c5.SaveAs((t+"-Legend.eps").c_str());
784
785 c1.SaveAs((t+"-ZenithDistance.root").c_str());
786 c2.SaveAs((t+"-PredictedCurrent.root").c_str());
787 c3.SaveAs((t+"-RelativeThreshold.root").c_str());
788 c4.SaveAs((t+"-MoonDist.root").c_str());
789
790 c1.Print((t+".pdf(").c_str(), "pdf");
791 c2.Print((t+".pdf" ).c_str(), "pdf");
792 c3.Print((t+".pdf" ).c_str(), "pdf");
793 c4.Print((t+".pdf" ).c_str(), "pdf");
794 c5.Print((t+".pdf)").c_str(), "pdf");
795*/
796}
Note: See TracBrowser for help on using the repository browser.