1
|
|
2
|
#include <iostream>
|
3
|
#include <string>
|
4
|
|
5
|
#include <TPad.h>
|
6
|
#include <TBox.h>
|
7
|
#include <TLine.h>
|
8
|
#include <TPRegexp.h>
|
9
|
#include <TObjString.h>
|
10
|
|
11
|
#include <sash/HESSArray.hh>
|
12
|
#include <sash/TimeDiff.hh>
|
13
|
#include <sash/Time.hh>
|
14
|
#include <stash/constants.h>
|
15
|
#include <utilities/StringTools.hh>
|
16
|
#include <crash/EquatorSystem.hh>
|
17
|
#include <crash/RotatedSystem.hh>
|
18
|
#include <stdtools/strtools.hh>
|
19
|
|
20
|
|
21
|
#include "Region.hh"
|
22
|
#include "Polygon.hh"
|
23
|
#include "RegionTools.hh"
|
24
|
|
25
|
|
26
|
|
27
|
#define DEBUG 0
|
28
|
#include <utilities/debugging.hh>
|
29
|
|
30
|
using namespace std;
|
31
|
|
32
|
|
33
|
Tools::Region* Tools::StringToRegion (std::string input,
|
34
|
bool ds9, bool inverted){
|
35
|
Tools::Region* reg = 0;
|
36
|
if (ds9)
|
37
|
reg = Tools::DS9ToRegion(input, inverted);
|
38
|
else
|
39
|
reg = Tools::HESSToRegion(input);
|
40
|
|
41
|
return reg;
|
42
|
}
|
43
|
|
44
|
Tools::Region*
|
45
|
Tools::HESSToRegion (std::string input){
|
46
|
|
47
|
|
48
|
size_t i = input.find("#");
|
49
|
if (i != std::string::npos) input = input.substr(0,i);
|
50
|
|
51
|
|
52
|
if(input.empty()) return 0;
|
53
|
|
54
|
std::vector<std::string> info = split(input.c_str()," \t");
|
55
|
|
56
|
#ifdef DEBUG
|
57
|
if (DEBUG > 1) {
|
58
|
DEBUG_OUT_L(2) << " Read: ";
|
59
|
for (unsigned int i = 0; i < info.size(); i++)
|
60
|
std::cout << info[i] << " ; ";
|
61
|
std::cout << std::endl;
|
62
|
}
|
63
|
#endif
|
64
|
|
65
|
if (info.size() < 5) {
|
66
|
throw std::runtime_error("Parse error in regions file: "+input);
|
67
|
}
|
68
|
|
69
|
|
70
|
Tools::Region* reg = 0;
|
71
|
std::string type = info[0];
|
72
|
bool radec = (info[2] == "RADec" || info[2] == "RADEC");
|
73
|
double xpos = atof(info[3].c_str());
|
74
|
double ypos = atof(info[4].c_str());
|
75
|
std::string name = info[5];
|
76
|
|
77
|
const Stash::SystemRef *sys;
|
78
|
if (radec)
|
79
|
sys = &Crash::EquatorSystem::GetRADecJ2000System();
|
80
|
else
|
81
|
sys = &Crash::RotatedSystem::GetGalacticSystem();
|
82
|
|
83
|
Stash::Coordinate centre
|
84
|
= Stash::Coordinate (Stash::Lambda(xpos, Stash::Angle::Degrees),
|
85
|
Stash::Beta(ypos, Stash::Angle::Degrees), *sys);
|
86
|
|
87
|
if (type == "BOX") {
|
88
|
|
89
|
DEBUG_OUT_L(2) << "Found Box, columns: " << info.size() << std::endl;
|
90
|
|
91
|
if (info.size() < 8) return 0;
|
92
|
double boxX = atof(info[6].c_str());
|
93
|
double boxY = atof(info[7].c_str());
|
94
|
double phi = 0.0;
|
95
|
if (info.size() > 8) phi = atof(info[8].c_str());
|
96
|
|
97
|
reg = new Tools::Box(centre,boxX,boxY,
|
98
|
Stash::Lambda(phi,Stash::Angle::Degrees),name);
|
99
|
}
|
100
|
else if (type == "SEGMENT") {
|
101
|
|
102
|
DEBUG_OUT_L(2) << "Found Segment, columns: " << info.size() << std::endl;
|
103
|
|
104
|
if (info.size() < 10) return 0;
|
105
|
|
106
|
double r1 = atof(info[6].c_str());
|
107
|
double r2 = atof(info[7].c_str());
|
108
|
double phi1 = atof(info[8].c_str());
|
109
|
double phi2 = atof(info[9].c_str());
|
110
|
|
111
|
|
112
|
if (fabs(phi1)<1e-10 && fabs(phi2-360.0) <1e-10)
|
113
|
if (fabs(r1) < 1e-10)
|
114
|
reg = new Tools::Circle(centre,r2,name);
|
115
|
else
|
116
|
reg = new Tools::Ring(centre,r1,r2,name);
|
117
|
else
|
118
|
reg = new Tools::CircleSegment(centre,r1,r2,phi1,phi2,name);
|
119
|
|
120
|
}
|
121
|
else if (type == "POLYGON" || type == "POLYCORNERS") {
|
122
|
|
123
|
DEBUG_OUT_L(2) << "Found Polygon, columns: " << info.size() << std::endl;
|
124
|
|
125
|
if (info.size() < 13) return 0;
|
126
|
|
127
|
bool relative = (type == "POLYGON");
|
128
|
unsigned int ptNb = atoi(info[6].c_str());
|
129
|
std::vector<Stash::Coordinate> corners;
|
130
|
for (unsigned int c = 7; c < 7+2*ptNb; c+=2) {
|
131
|
Stash::Lambda lambda(info[c]);
|
132
|
Stash::Beta beta(info[c+1]);
|
133
|
Stash::Coordinate pos(lambda,
|
134
|
beta,
|
135
|
centre.GetSystem());
|
136
|
if (relative)
|
137
|
pos += centre;
|
138
|
|
139
|
corners.push_back(pos);
|
140
|
}
|
141
|
|
142
|
reg = new Tools::Polygon(corners, name);
|
143
|
|
144
|
}
|
145
|
else {
|
146
|
WARN_OUT << "Unknown region type: " << type << std::endl;
|
147
|
return 0;
|
148
|
}
|
149
|
|
150
|
return reg;
|
151
|
}
|
152
|
|
153
|
|
154
|
|
155
|
|
156
|
|
157
|
Tools::Region* Tools::DS9ToRegion (std::string input,
|
158
|
bool inverted)
|
159
|
{
|
160
|
|
161
|
if(input.empty()) return 0;
|
162
|
if(TString(input).BeginsWith("#")) return 0;
|
163
|
if(TString(input).BeginsWith("global")) return 0;
|
164
|
|
165
|
std::vector<std::string> infos = split(input.c_str(),"={}()#;, \t");
|
166
|
|
167
|
std::vector<std::string>::iterator info;
|
168
|
|
169
|
if (DEBUG) {
|
170
|
DEBUG_OUT << " Read: ";
|
171
|
for (unsigned int i = 0; i < infos.size(); i++)
|
172
|
std::cout << infos[i] << " ; ";
|
173
|
std::cout << std::endl;
|
174
|
}
|
175
|
|
176
|
|
177
|
bool system = false;
|
178
|
bool radec = true;
|
179
|
info = infos.begin();
|
180
|
while (info != infos.end()) {
|
181
|
if ( *info == "fk5" || *info == "FK5") {
|
182
|
system = true;
|
183
|
break;
|
184
|
}
|
185
|
if (*info == "galactic" || *info == "GALACTIC") {
|
186
|
system = true;
|
187
|
radec = false;
|
188
|
break;
|
189
|
}
|
190
|
info++;
|
191
|
}
|
192
|
|
193
|
if (system) {
|
194
|
info = infos.erase(info);
|
195
|
} else {
|
196
|
if (radec)
|
197
|
WARN_OUT << "No system found: assume RADec" << std::endl;
|
198
|
else
|
199
|
WARN_OUT << "No system found: assume galactic" << std::endl;
|
200
|
}
|
201
|
|
202
|
if (infos.size() == 0) return 0;
|
203
|
|
204
|
|
205
|
std::string name = "";
|
206
|
bool text = false;
|
207
|
info = infos.begin();
|
208
|
while (info != infos.end()) {
|
209
|
if ( *info == "text" || *info == "TEXT") {
|
210
|
text = true;
|
211
|
break;
|
212
|
}
|
213
|
info++;
|
214
|
}
|
215
|
if (text) {
|
216
|
info = infos.erase(info);
|
217
|
name = *info;
|
218
|
info = infos.erase(info);
|
219
|
text = true;
|
220
|
}
|
221
|
|
222
|
|
223
|
info = infos.begin();
|
224
|
bool fullCS = true;
|
225
|
bool disk = true;
|
226
|
unsigned int paramNb = 3;
|
227
|
std::string type = "SEGMENT";
|
228
|
if (*info == "circle" || *info == "CIRCLE") {
|
229
|
type = "SEGMENT";
|
230
|
fullCS = true;
|
231
|
paramNb = 3;
|
232
|
} else if (*info == "annulus" || *info == "ANNULUS") {
|
233
|
type = "SEGMENT";
|
234
|
fullCS = true;
|
235
|
disk = false;
|
236
|
paramNb = 4;
|
237
|
} else if (*info == "panda" || *info == "PANDA") {
|
238
|
type = "SEGMENT";
|
239
|
fullCS = false;
|
240
|
disk = false;
|
241
|
paramNb = 8;
|
242
|
} else if (*info == "box" || *info == "BOX") {
|
243
|
type = "BOX";
|
244
|
paramNb = 5;
|
245
|
} else if (*info == "polygon" || *info == "POLYGON") {
|
246
|
|
247
|
|
248
|
std::cout << "Polygon support not yet implemented" << std::endl;
|
249
|
return 0;
|
250
|
} else {
|
251
|
throw std::runtime_error("Parse error in regions file: "+input);
|
252
|
}
|
253
|
|
254
|
info = infos.erase(info);
|
255
|
|
256
|
if (infos.size() < paramNb) {
|
257
|
throw std::runtime_error("Parse error in regions file: "+input);
|
258
|
}
|
259
|
|
260
|
double xpos = atof((*info).c_str());
|
261
|
info = infos.erase(info);
|
262
|
double ypos = atof((*info).c_str());
|
263
|
info = infos.erase(info);
|
264
|
|
265
|
if (!text) {
|
266
|
name = "Reg_"+strtools::num2str(xpos)
|
267
|
+"_"+strtools::num2str(ypos);
|
268
|
WARN_OUT << "No name found: assume " << name << std::endl;
|
269
|
}
|
270
|
|
271
|
|
272
|
const Stash::SystemRef *sys;
|
273
|
if (radec)
|
274
|
sys = &Crash::EquatorSystem::GetRADecJ2000System();
|
275
|
else
|
276
|
sys = &Crash::RotatedSystem::GetGalacticSystem();
|
277
|
|
278
|
Stash::Coordinate centre
|
279
|
= Stash::Coordinate (Stash::Lambda(xpos, Stash::Angle::Degrees),
|
280
|
Stash::Beta(ypos, Stash::Angle::Degrees), *sys);
|
281
|
|
282
|
DEBUG_OUT << "Found Centre : " << xpos << " , " << ypos << std::endl;
|
283
|
|
284
|
Tools::Region* reg = 0;
|
285
|
if (type == "BOX") {
|
286
|
|
287
|
double boxX = atof((*info).c_str());
|
288
|
info = infos.erase(info);
|
289
|
double boxY = atof((*info).c_str());
|
290
|
info = infos.erase(info);
|
291
|
double phi = 0.;
|
292
|
if (infos.size() ) {
|
293
|
phi = atof((*info).c_str());
|
294
|
if (inverted) {
|
295
|
phi -= 180.;
|
296
|
phi *= -1;
|
297
|
}
|
298
|
info = infos.erase(info);
|
299
|
}
|
300
|
|
301
|
DEBUG_OUT << "Found Box : " << boxX
|
302
|
<< " , " << boxY
|
303
|
<< " , " << phi << std::endl;
|
304
|
|
305
|
reg = new Tools::Box(centre,boxX,boxY,
|
306
|
Stash::Lambda(phi,Stash::Angle::Degrees),name);
|
307
|
|
308
|
} else if (type == "SEGMENT") {
|
309
|
|
310
|
double phi1 = 0.;
|
311
|
double phi2 = 360.;
|
312
|
int Nphi = 1;
|
313
|
double r1 = 0.;
|
314
|
double r2 = 0.;
|
315
|
int Nr = 1;
|
316
|
|
317
|
if (!fullCS) {
|
318
|
phi1 = atof((*info).c_str());
|
319
|
info = infos.erase(info);
|
320
|
phi2 = atof((*info).c_str());
|
321
|
info = infos.erase(info);
|
322
|
Nphi = atoi((*info).c_str());
|
323
|
info = infos.erase(info);
|
324
|
r1 = Tools::ParseAngle((*info));
|
325
|
info = infos.erase(info);
|
326
|
r2 = Tools::ParseAngle((*info));
|
327
|
info = infos.erase(info);
|
328
|
Nr = atoi((*info).c_str());
|
329
|
info = infos.erase(info);
|
330
|
} else {
|
331
|
if (disk) {
|
332
|
r2 = Tools::ParseAngle((*info));
|
333
|
info = infos.erase(info);
|
334
|
} else {
|
335
|
r1 = Tools::ParseAngle((*info));
|
336
|
info = infos.erase(info);
|
337
|
r2 = Tools::ParseAngle((*info));
|
338
|
info = infos.erase(info);
|
339
|
Nr = atoi((*info).c_str());
|
340
|
info = infos.erase(info);
|
341
|
}
|
342
|
}
|
343
|
|
344
|
if(!fullCS){
|
345
|
if (inverted) {
|
346
|
double phi = phi2;
|
347
|
phi2 = 180. - phi1;
|
348
|
phi1 = 180. - phi;
|
349
|
}
|
350
|
}
|
351
|
|
352
|
DEBUG_OUT << "Found Segment: "
|
353
|
<< phi1 << " " << phi2 << " " << Nphi << " , "
|
354
|
<< r1 << " " << r2 << " " << Nr
|
355
|
<< std::endl;
|
356
|
Tools::CircleSegment *seg = new Tools::CircleSegment
|
357
|
(centre,r1,r2,phi1,phi2,name);
|
358
|
|
359
|
|
360
|
reg=seg;
|
361
|
|
362
|
|
363
|
|
364
|
|
365
|
|
366
|
|
367
|
|
368
|
|
369
|
|
370
|
|
371
|
|
372
|
|
373
|
|
374
|
|
375
|
|
376
|
|
377
|
|
378
|
|
379
|
|
380
|
|
381
|
|
382
|
|
383
|
|
384
|
|
385
|
|
386
|
|
387
|
|
388
|
|
389
|
|
390
|
|
391
|
|
392
|
|
393
|
}
|
394
|
else if (type == "POLYGON") {
|
395
|
|
396
|
WARN_OUT << "Polygon region not currently supported" << endl;
|
397
|
return NULL;
|
398
|
|
399
|
DEBUG_OUT << "Found Polygon: " << std::endl;
|
400
|
|
401
|
if (infos.size() < 13) return 0;
|
402
|
|
403
|
unsigned int ptNb = infos.size() / 2;
|
404
|
std::vector<Stash::Coordinate> corners;
|
405
|
for (unsigned int c = 0; c < 2*ptNb; c+=2) {
|
406
|
double x = atof((*info).c_str());
|
407
|
info = infos.erase(info);
|
408
|
double y = atof((*info).c_str());
|
409
|
info = infos.erase(info);
|
410
|
Stash::Coordinate pos( Stash::Lambda(x, Stash::Angle::Degrees),
|
411
|
Stash::Beta(y, Stash::Angle::Degrees),
|
412
|
centre.GetSystem() );
|
413
|
corners.push_back(pos);
|
414
|
}
|
415
|
|
416
|
reg = new Tools::Polygon (corners, name);
|
417
|
|
418
|
}
|
419
|
|
420
|
|
421
|
return reg;
|
422
|
}
|
423
|
|
424
|
|
425
|
|
426
|
|
427
|
|
428
|
|
429
|
|
430
|
|
431
|
|
432
|
|
433
|
|
434
|
|
435
|
|
436
|
|
437
|
|
438
|
Double_t Tools::ParseAngle(std::string input){
|
439
|
|
440
|
DEBUG_OUT << "Parsing \"" << input << "\"" << std::endl;
|
441
|
|
442
|
if( TPRegexp("[^\\.\\d\"'drpi]").Match(input.c_str()) > 0 ){
|
443
|
WARN_OUT << "ERROR: Illegal string \"" << input << "\"" << std::endl;
|
444
|
return 0.0;
|
445
|
|
446
|
}
|
447
|
|
448
|
TObjArray *subStrL = TPRegexp("([\\.\\d]*)([\"'drpi])").MatchS(input.c_str());
|
449
|
for (Int_t i = 0; i < subStrL->GetLast()+1; i++) {
|
450
|
const TString subStr = ((TObjString *)subStrL->At(i))->GetString();
|
451
|
DEBUG_OUT_L(2) << "substr " << i << ": \"" << subStr << "\"" << std::endl;
|
452
|
}
|
453
|
|
454
|
if( subStrL->GetLast() >= 3 ){
|
455
|
WARN_OUT << "ERROR parsing string \"" << input << "\"" << std::endl;
|
456
|
throw std::runtime_error("Parse error in ParseAngle, input: "+input);
|
457
|
}
|
458
|
|
459
|
if( subStrL->GetLast() < 1 ){
|
460
|
|
461
|
return TString(input).Atof();
|
462
|
}
|
463
|
|
464
|
TString numberStr = ((TObjString *)subStrL->At(1))->GetString();
|
465
|
Double_t number = numberStr.Atof();
|
466
|
|
467
|
if( subStrL->GetLast() == 2 ){
|
468
|
TString unitStr = ((TObjString *)subStrL->At(2))->GetString();
|
469
|
if( unitStr == "\"" ) number /= 3600.;
|
470
|
else if( unitStr == "'" ) number /= 60.;
|
471
|
else if( unitStr == "d" ) number /= 1.;
|
472
|
else if( unitStr == "r" ) number *= TMath::RadToDeg();
|
473
|
else{
|
474
|
WARN_OUT << "ERROR: illegal unit string \"" << unitStr << "\" in input \"" << input << "\"" << std::endl;
|
475
|
throw std::runtime_error("Parse error in ParseAngle, input: "+input);
|
476
|
}
|
477
|
}
|
478
|
|
479
|
return number;
|
480
|
}
|