1
|
#include <algorithm>
|
2
|
#include <iomanip>
|
3
|
|
4
|
#define INFO_OUT_TAG "ReflectedBgMaker> "
|
5
|
#define DEBUG 0
|
6
|
#include <utilities/debugging.hh>
|
7
|
#include <utilities/ConfigHandler.hh>
|
8
|
#include <crash/RotatedSystem.hh>
|
9
|
#include <crash/EquatorSystem.hh>
|
10
|
#include <sash/RunHeader.hh>
|
11
|
|
12
|
#include "ReflectedBgMaker.hh"
|
13
|
|
14
|
using std::cout;
|
15
|
using std::endl;
|
16
|
|
17
|
|
18
|
|
19
|
|
20
|
|
21
|
Background::ReflectedBgMaker::
|
22
|
ReflectedBgMaker(std::string name, Utilities::ConfigHandler& conf,
|
23
|
std::string input, bool init_now) :
|
24
|
BgMaker(name.c_str(), conf, input, init_now)
|
25
|
{
|
26
|
ConstructMaker(conf);
|
27
|
}
|
28
|
Background::ReflectedBgMaker::
|
29
|
ReflectedBgMaker(Utilities::ConfigHandler& conf,
|
30
|
std::string input, bool init_now) :
|
31
|
BgMaker("ReflectedBgMaker", conf, input, init_now)
|
32
|
{
|
33
|
ConstructMaker(conf);
|
34
|
}
|
35
|
|
36
|
|
37
|
void Background::ReflectedBgMaker::ConstructMaker(Utilities::ConfigHandler& conf)
|
38
|
{
|
39
|
DEBUG_OUT << "Hello" << endl;
|
40
|
|
41
|
fMaxNumberOffRegions = 100;
|
42
|
fMinNumberOffRegions = 1;
|
43
|
fMinOnOffDist = 0.1;
|
44
|
fNumberOffRegions = 0;
|
45
|
fRotationAngleDeg = 0.;
|
46
|
fCurrentOffset = 0;
|
47
|
fMaxOffRegionDist = 10.;
|
48
|
fUseCircularOff = false;
|
49
|
|
50
|
std::string Name = "ReflectedBgMaker";
|
51
|
|
52
|
|
53
|
|
54
|
conf.SetSectionHelpText(Name, "Estimates background from a "
|
55
|
"series of on-region-shaped regions "
|
56
|
"that have the same offset from the observation "
|
57
|
"position as the test position. This BgMaker "
|
58
|
"is useful for making spectra, but is not well "
|
59
|
"suited for 2-D images." );
|
60
|
|
61
|
conf.GetValue(Name, "RotationAngle",
|
62
|
fRotationAngleDeg,
|
63
|
"Rotation angle of the initial OFF "
|
64
|
"region from the test position (deg)" );
|
65
|
|
66
|
conf.GetValue(Name, "MaxNumberOffRegions",
|
67
|
fMaxNumberOffRegions,
|
68
|
"Maximum allowed number of OFF regions");
|
69
|
|
70
|
conf.GetValue(Name, "MinNumberOffRegions",
|
71
|
fMinNumberOffRegions,
|
72
|
"Minimum required number of OFF regions");
|
73
|
|
74
|
conf.GetValue(Name, "MaxDistanceOffRegions",
|
75
|
fMaxOffRegionDist,
|
76
|
"Maximum allowed distance between OFF regions and target");
|
77
|
|
78
|
conf.GetValue(Name, "MinOnOffDistance",
|
79
|
fMinOnOffDist,
|
80
|
"Minimum angular distance between the on region and "
|
81
|
"any off region");
|
82
|
|
83
|
fUseCircularOff = conf.GetFlag(Name, "UseCircularOff",
|
84
|
"Use circular off regions "
|
85
|
"(for backwards compatibility)" );
|
86
|
|
87
|
|
88
|
ScaleExposureByRegionArea( true );
|
89
|
}
|
90
|
|
91
|
|
92
|
Background::ReflectedBgMaker::~ReflectedBgMaker() {
|
93
|
DEBUG_OUT << "Goodbye!" << endl;
|
94
|
}
|
95
|
|
96
|
|
97
|
|
98
|
|
99
|
|
100
|
|
101
|
void
|
102
|
Background::ReflectedBgMaker::
|
103
|
BeginRun() {
|
104
|
|
105
|
|
106
|
|
107
|
|
108
|
|
109
|
fNumberOffRegions = 0;
|
110
|
|
111
|
const Tools::Compound& onregion ( GetBgStats()->GetOnRegion() );
|
112
|
|
113
|
const Sash::RunHeader *runheader = fHess->Get<Sash::RunHeader>();
|
114
|
if (!runheader) {
|
115
|
WARN_OUT << "No runheader found" << endl;
|
116
|
throw std::runtime_error( "No runheader was found!" );
|
117
|
}
|
118
|
|
119
|
const Stash::Coordinate &obspos_radec = runheader->GetObservationPosition().
|
120
|
GetCoordinate(*(fHess->GetRADecJ2000System()));
|
121
|
const Stash::Coordinate &testpos_radec = onregion.GetCentre().
|
122
|
GetCoordinate(*(fHess->GetRADecJ2000System()));
|
123
|
|
124
|
DEBUG_OUT << "Obspos =" << obspos_radec <<endl;
|
125
|
DEBUG_OUT << "Testpos=" << testpos_radec <<endl;
|
126
|
|
127
|
fCurrentOffset = testpos_radec.GetAngularDistance( obspos_radec ).
|
128
|
GetDegrees();
|
129
|
|
130
|
|
131
|
Tools::Circle* circle = IsCircle(&onregion);
|
132
|
if (circle)
|
133
|
CreateOffRegionsForOnCircle(circle, obspos_radec);
|
134
|
else
|
135
|
CreateOffRegions(&onregion, obspos_radec);
|
136
|
|
137
|
|
138
|
if ( GetBgStats()->GetOffRegion().GetNumRegions() < fMinNumberOffRegions) {
|
139
|
WARN_OUT << "Run will be skipped: Too few off regions! (found "
|
140
|
<< GetBgStats()->GetOffRegion().GetNumRegions()
|
141
|
<< " / required " << fMinNumberOffRegions << " )" << std::endl;
|
142
|
GetBgStats()->GetSkippedFlag() = true;
|
143
|
}
|
144
|
|
145
|
}
|
146
|
|
147
|
|
148
|
|
149
|
|
150
|
|
151
|
|
152
|
void Background::ReflectedBgMaker::EndRun()
|
153
|
{
|
154
|
DEBUG_OUT << std::endl;
|
155
|
|
156
|
double alpha = GetBgStats()->GetOnRegion().GetArea()
|
157
|
/ GetBgStats()->GetOffRegion().GetArea();
|
158
|
double nOff = GetBgStats()->GetRateStats().nOff;
|
159
|
|
160
|
GetBgStats()->GetRateStats().exposureOff = nOff;
|
161
|
GetBgStats()->GetRateStats().exposureOn = alpha * nOff;
|
162
|
|
163
|
DEBUG_OUT << "on region area: " << GetBgStats()->GetOnRegion().GetArea() << endl;
|
164
|
DEBUG_OUT << "off region area: " << GetBgStats()->GetOffRegion().GetArea() << endl;
|
165
|
DEBUG_OUT << "-> alpha: " << alpha << endl;
|
166
|
DEBUG_OUT << "exposure off: " << GetBgStats()->GetRateStats().exposureOff << endl;
|
167
|
DEBUG_OUT << "-> exposure on: " << GetBgStats()->GetRateStats().exposureOn << endl;
|
168
|
}
|
169
|
|
170
|
|
171
|
|
172
|
|
173
|
bool Background::ReflectedBgMaker::IsOnMapEvent()
|
174
|
{
|
175
|
|
176
|
DEBUG_OUT << std::endl;
|
177
|
if(Background::BgMaker::IsOnEvent()) return true;
|
178
|
else return false;
|
179
|
|
180
|
}
|
181
|
|
182
|
|
183
|
|
184
|
|
185
|
bool Background::ReflectedBgMaker::IsOffMapEvent()
|
186
|
{
|
187
|
|
188
|
DEBUG_OUT << std::endl;
|
189
|
if(Background::BgMaker::IsOffEvent()) return true;
|
190
|
else return false;
|
191
|
|
192
|
}
|
193
|
|
194
|
|
195
|
|
196
|
|
197
|
void Background::ReflectedBgMaker::FillOnExposure()
|
198
|
{
|
199
|
|
200
|
DEBUG_OUT << std::endl;
|
201
|
|
202
|
}
|
203
|
|
204
|
|
205
|
|
206
|
|
207
|
void Background::ReflectedBgMaker::FillOffExposure()
|
208
|
{
|
209
|
|
210
|
DEBUG_OUT << std::endl;
|
211
|
|
212
|
}
|
213
|
|
214
|
|
215
|
|
216
|
|
217
|
|
218
|
|
219
|
|
220
|
|
221
|
|
222
|
|
223
|
Tools::Circle* Background::ReflectedBgMaker::IsCircle(const Tools::Region* region) {
|
224
|
|
225
|
DEBUG_OUT << "region type: " << typeid(*region).name() << endl;
|
226
|
if (typeid(*region) == typeid(Tools::Circle))
|
227
|
return (Tools::Circle*)region;
|
228
|
|
229
|
|
230
|
if (typeid(*region) == typeid(Tools::Compound)) {
|
231
|
Tools::Compound* compound = (Tools::Compound*)region;
|
232
|
DEBUG_OUT << "compound type: " << typeid(*compound).name() << endl;
|
233
|
DEBUG_OUT << "NumRegions: " << compound->GetNumRegions() << endl;
|
234
|
if (compound->GetNumRegions() == 1) {
|
235
|
const Tools::Region* first_region = compound->GetRegions()[0];
|
236
|
DEBUG_OUT << "First region type: " << typeid(*first_region).name() << endl;
|
237
|
if (typeid(*first_region) == typeid(Tools::Circle))
|
238
|
return (Tools::Circle*)first_region;
|
239
|
}
|
240
|
}
|
241
|
return 0;
|
242
|
}
|
243
|
|
244
|
|
245
|
|
246
|
|
247
|
|
248
|
|
249
|
|
250
|
|
251
|
|
252
|
|
253
|
|
254
|
|
255
|
|
256
|
|
257
|
|
258
|
|
259
|
|
260
|
|
261
|
|
262
|
|
263
|
|
264
|
|
265
|
|
266
|
bool
|
267
|
Background::ReflectedBgMaker::
|
268
|
CreateOffRegions(const Tools::Region* onregion,
|
269
|
const Stash::Coordinate &obspos_radec)
|
270
|
{
|
271
|
INFO_OUT << "On region is not a circle. "
|
272
|
"Creating off regions using the general algorithm." << endl;
|
273
|
|
274
|
fNumberOffRegions = 0;
|
275
|
|
276
|
|
277
|
if( onregion->Contains(obspos_radec) ) {
|
278
|
WARN_OUT << "ON region contains the observation position." << std::endl;
|
279
|
return false;
|
280
|
}
|
281
|
|
282
|
|
283
|
const Stash::Coordinate testpos_radec = onregion->GetCentre().
|
284
|
GetCoordinate(*fHess->GetRADecJ2000System());
|
285
|
|
286
|
|
287
|
|
288
|
|
289
|
Tools::Region *grownOn
|
290
|
= onregion->GrowBoundary(fMinOnOffDist);
|
291
|
|
292
|
DEBUG_OUT << "on region: " << *onregion << std::endl;
|
293
|
DEBUG_OUT << "grown on region: " << *grownOn << std::endl;
|
294
|
|
295
|
|
296
|
|
297
|
Tools::Region* tmpOff = 0;
|
298
|
|
299
|
if( fUseCircularOff ) {
|
300
|
double off_radius = onregion->GetEquivalentCircleRadius();
|
301
|
DEBUG_OUT << "using circular off regions with radius radius "
|
302
|
<< off_radius << " deg" << std::endl;
|
303
|
tmpOff = new Tools::Circle( testpos_radec, off_radius, "Off");
|
304
|
}
|
305
|
else {
|
306
|
DEBUG_OUT << "using on-shaped off regions" << std::endl;
|
307
|
tmpOff = (Tools::Region*)onregion->Clone("Off");
|
308
|
}
|
309
|
|
310
|
DEBUG_OUT << *tmpOff << std::endl;
|
311
|
|
312
|
|
313
|
|
314
|
|
315
|
|
316
|
|
317
|
|
318
|
double radius = onregion->GetEquivalentCircleRadius();
|
319
|
double offset = testpos_radec.GetAngularDistance(obspos_radec).GetDegrees();
|
320
|
double stepsize = asin(radius/offset) * 180.0 / M_PI / 5.;
|
321
|
|
322
|
DEBUG_OUT << "equivalent circle radius: " << radius << std::endl;
|
323
|
DEBUG_OUT << "offset: " << offset << std::endl;
|
324
|
DEBUG_OUT << "stepsize: " << stepsize << std::endl;
|
325
|
if( stepsize != stepsize ) {
|
326
|
WARN_OUT << "Offset too small (" << offset
|
327
|
<< "deg), no Off regions could be found." << std::endl;
|
328
|
return false;
|
329
|
}
|
330
|
|
331
|
Stash::Lambda rotAngle(fRotationAngleDeg, Stash::Angle::Degrees);
|
332
|
Stash::SmallAngle dRot(stepsize, Stash::Angle::Degrees);
|
333
|
int numSteps = 360. / stepsize;
|
334
|
|
335
|
do {
|
336
|
|
337
|
tmpOff->SetRotation( rotAngle, obspos_radec );
|
338
|
|
339
|
DEBUG_OUT << "Trying to find off region " << *tmpOff
|
340
|
<< " at rotation angle "
|
341
|
<< rotAngle << std::endl;
|
342
|
|
343
|
|
344
|
|
345
|
|
346
|
if( !(tmpOff->Overlaps(GetBgStats()->GetOffRegion()) )) {
|
347
|
if( !(tmpOff->Overlaps(GetBgStats()->GetOnExclusionRegion()) )) {
|
348
|
if( !tmpOff->Overlaps( *grownOn ) ) {
|
349
|
|
350
|
|
351
|
std::ostringstream offName;
|
352
|
offName << std::fixed << std::setprecision(1)
|
353
|
<< rotAngle.GetDegrees() << "deg";
|
354
|
|
355
|
Tools::Region* newOff
|
356
|
= (Tools::Region*)tmpOff->Clone( offName.str().c_str() );
|
357
|
GetBgStats()->GetOffRegion().AddRegion( newOff );
|
358
|
|
359
|
fNumberOffRegions++;
|
360
|
|
361
|
INFO_OUT << "Added new off region at "<< rotAngle.GetDegrees() << " deg from North at "
|
362
|
<< newOff->GetTrueCentre().GetCoordinate(*fHess->GetRADecJ2000System()) << std::endl;
|
363
|
DEBUG_OUT << "offset from observation position: "
|
364
|
<< newOff->GetTrueCentre().GetCoordinate(*fHess->GetRADecJ2000System())
|
365
|
.GetAngularDistance( obspos_radec ).GetDegrees() << " deg" << std::endl;
|
366
|
|
367
|
if( fNumberOffRegions == fMaxNumberOffRegions ) {
|
368
|
INFO_OUT << "Reached maximum allowed number of OFF regions ("
|
369
|
<< fMaxNumberOffRegions << "). Stopping creating new "
|
370
|
<< "ones at your request." << std::endl;
|
371
|
break;
|
372
|
}
|
373
|
}
|
374
|
}
|
375
|
}
|
376
|
rotAngle += dRot;
|
377
|
|
378
|
} while( --numSteps != 0 );
|
379
|
|
380
|
delete grownOn;
|
381
|
delete tmpOff;
|
382
|
|
383
|
if ( fNumberOffRegions == 0) {
|
384
|
WARN_OUT << "No Off regions found." << std::endl;
|
385
|
return false;
|
386
|
}
|
387
|
|
388
|
INFO_OUT << "Added "<< fNumberOffRegions
|
389
|
<< " OFF regions at offset " << fCurrentOffset << endl;
|
390
|
return true;
|
391
|
}
|
392
|
|
393
|
|
394
|
|
395
|
|
396
|
|
397
|
|
398
|
|
399
|
|
400
|
|
401
|
|
402
|
|
403
|
|
404
|
bool
|
405
|
Background::ReflectedBgMaker::
|
406
|
CreateOffRegionsForOnCircle(const Tools::Circle* onregion,
|
407
|
const Stash::Coordinate &obspos_radec)
|
408
|
{
|
409
|
INFO_OUT << "On region is a circle. "
|
410
|
"Creating off regions using the fast algorithm." << endl;
|
411
|
DEBUG_OUT << "on region: " << *onregion << std::endl;
|
412
|
|
413
|
fNumberOffRegions = 0;
|
414
|
|
415
|
|
416
|
if( onregion->Contains(obspos_radec) ) {
|
417
|
WARN_OUT << "ON region contains the observation position." << std::endl;
|
418
|
return false;
|
419
|
}
|
420
|
|
421
|
|
422
|
const Stash::Coordinate onpos_radec = onregion->GetCentre().
|
423
|
GetCoordinate(*fHess->GetRADecJ2000System());
|
424
|
DEBUG_OUT << "onpos_radec: " << onpos_radec << std::endl;
|
425
|
|
426
|
|
427
|
|
428
|
Tools::Region* tmpOff = (Tools::Circle*)onregion->Clone("Off");
|
429
|
DEBUG_OUT << "off region: " << *tmpOff << std::endl;
|
430
|
|
431
|
DEBUG_OUT << "--- OnExclusionRegion START --- " << endl
|
432
|
<< GetBgStats()->GetOnExclusionRegion() << endl
|
433
|
<< "--- OnExclusionRegion END --- " << endl;
|
434
|
|
435
|
|
436
|
|
437
|
|
438
|
double radius = onregion->GetR2();
|
439
|
double offset = onpos_radec.GetAngularDistance(obspos_radec).GetDegrees();
|
440
|
double segment = 2 * asin(radius/offset) * 180.0 / M_PI;
|
441
|
|
442
|
|
443
|
int steps_per_segment = 10;
|
444
|
double stepsize = segment / steps_per_segment;
|
445
|
int n_test_positions = 360 / segment * steps_per_segment;
|
446
|
DEBUG_OUT << "radius: " << radius << std::endl;
|
447
|
DEBUG_OUT << "offset: " << offset << std::endl;
|
448
|
DEBUG_OUT << "segment: " << segment << std::endl;
|
449
|
DEBUG_OUT << "steps_per_segment: " << steps_per_segment << std::endl;
|
450
|
DEBUG_OUT << "stepsize: " << stepsize << std::endl;
|
451
|
DEBUG_OUT << "n_test_positions: " << n_test_positions << std::endl;
|
452
|
|
453
|
|
454
|
double rot_angle = 0;
|
455
|
do {
|
456
|
|
457
|
|
458
|
Stash::Lambda rot_angle_lambda(rot_angle, Stash::Angle::Degrees);
|
459
|
tmpOff->SetRotation( rot_angle_lambda, obspos_radec );
|
460
|
|
461
|
const Stash::Coordinate tmpOffpos_radec = tmpOff->GetTrueCentre().
|
462
|
GetCoordinate(*fHess->GetRADecJ2000System());
|
463
|
double on_off_dist = tmpOffpos_radec.GetAngularDistance( onpos_radec ).GetDegrees();
|
464
|
double off_radius = tmpOff->GetEquivalentCircleRadius();
|
465
|
|
466
|
|
467
|
|
468
|
double allowed_dist = fMinOnOffDist + radius + off_radius;
|
469
|
|
470
|
DEBUG_OUT << "rot_angle " << rot_angle << std::endl;
|
471
|
DEBUG_OUT << "rot_angle_lambda " << rot_angle_lambda << std::endl;
|
472
|
DEBUG_OUT << "tmpOff " << *tmpOff << std::endl;
|
473
|
DEBUG_OUT << "tmpOff rotation " << tmpOff->GetRotationAngle() << std::endl;
|
474
|
DEBUG_OUT << "tmpOffpos_radec " << tmpOffpos_radec << std::endl;
|
475
|
DEBUG_OUT << "onpos_radec " << onpos_radec << std::endl;
|
476
|
DEBUG_OUT << "on_off_dist " << on_off_dist << std::endl;
|
477
|
DEBUG_OUT << "off_radius " << off_radius << std::endl;
|
478
|
DEBUG_OUT << "allowed_dist " << allowed_dist << std::endl;
|
479
|
|
480
|
|
481
|
if (on_off_dist < allowed_dist) {
|
482
|
DEBUG_OUT << "Skipping rot_angle " << rot_angle << " because on_off_dist " << on_off_dist
|
483
|
<< " is less than " << fMinOnOffDist << std::endl;
|
484
|
rot_angle += stepsize;
|
485
|
continue;
|
486
|
}
|
487
|
|
488
|
|
489
|
if (tmpOff->Overlaps(GetBgStats()->GetOnExclusionRegion())) {
|
490
|
DEBUG_OUT << "Skipping rot_angle " << rot_angle
|
491
|
<< " because it overlaps with the exclusion region." << std::endl;
|
492
|
rot_angle += stepsize;
|
493
|
continue;
|
494
|
}
|
495
|
|
496
|
|
497
|
|
498
|
|
499
|
DEBUG_OUT << "Accepting rot_angle " << rot_angle << std::endl;
|
500
|
|
501
|
|
502
|
std::ostringstream offName;
|
503
|
offName << std::fixed << std::setprecision(1) << rot_angle << "deg";
|
504
|
|
505
|
Tools::Region* newOff = (Tools::Region*)tmpOff->Clone( offName.str().c_str() );
|
506
|
GetBgStats()->GetOffRegion().AddRegion( newOff );
|
507
|
|
508
|
INFO_OUT << "Added new off region at "<< rot_angle << " deg from North at "
|
509
|
<< newOff->GetTrueCentre().GetCoordinate(*fHess->GetRADecJ2000System()) << std::endl;
|
510
|
DEBUG_OUT << "offset from observation position: "
|
511
|
<< newOff->GetTrueCentre().GetCoordinate(*fHess->GetRADecJ2000System())
|
512
|
.GetAngularDistance( obspos_radec ).GetDegrees() << " deg" << std::endl;
|
513
|
|
514
|
if( fNumberOffRegions == fMaxNumberOffRegions ) {
|
515
|
INFO_OUT << "Reached maximum allowed number of OFF regions ("
|
516
|
<< fMaxNumberOffRegions << "). Stopping creating new "
|
517
|
<< "ones at your request." << std::endl;
|
518
|
break;
|
519
|
}
|
520
|
|
521
|
fNumberOffRegions++;
|
522
|
rot_angle += segment;
|
523
|
} while( rot_angle < 360 );
|
524
|
|
525
|
delete tmpOff;
|
526
|
|
527
|
if (fNumberOffRegions == 0) {
|
528
|
WARN_OUT << "No Off regions found." << std::endl;
|
529
|
return false;
|
530
|
}
|
531
|
|
532
|
INFO_OUT << "Added "<< fNumberOffRegions << " OFF regions at offset " << fCurrentOffset << endl;
|
533
|
return true;
|
534
|
}
|