Commit fba90429514122919d7f376fa68aad2b308c2727

Authored by Jürgen Knödlseder
1 parent 20133af4

Integrate code (#3248)

cscripts/csphagen.par
@@ -43,8 +43,8 @@ glon, r, a, 184.56,0,360, "Galactic longitude of source region centre ( @@ -43,8 +43,8 @@ glon, r, a, 184.56,0,360, "Galactic longitude of source region centre (
43 glat, r, a, -5.79,-90,90, "Galactic latitude of source region centre (deg)" 43 glat, r, a, -5.79,-90,90, "Galactic latitude of source region centre (deg)"
44 rad, r, a, 0.2,0,180, "Radius of source region circle (deg)" 44 rad, r, a, 0.2,0,180, "Radius of source region circle (deg)"
45 width, r, a, 0.2,0,180, "Width of source region rectangle (deg)" 45 width, r, a, 0.2,0,180, "Width of source region rectangle (deg)"
46 -height, r, a, 0.2,0,180, "Width of source region rectangle (deg)"  
47 -posang, r, a, 0,-360,360, "Position angle of source region rectangle ccw from North (deg)" 46 +height, r, a, 0.2,0,180, "Height of source region rectangle (deg)"
  47 +posang, r, a, 0.0,-360,360, "Position angle of source region rectangle (deg)"
48 srcregfile, f, a, on.reg,,, "Source region file (ds9 or FITS WCS)" 48 srcregfile, f, a, on.reg,,, "Source region file (ds9 or FITS WCS)"
49 bkgmethod, s, a, REFLECTED,REFLECTED|CUSTOM,, "Method for background estimation" 49 bkgmethod, s, a, REFLECTED,REFLECTED|CUSTOM,, "Method for background estimation"
50 bkgregfile, f, a, bkg.reg,,, "Background regions file (ds9 or FITS WCS)" 50 bkgregfile, f, a, bkg.reg,,, "Background regions file (ds9 or FITS WCS)"
cscripts/csphagen.py
@@ -149,6 +149,34 @@ class csphagen(ctools.csobservation): @@ -149,6 +149,34 @@ class csphagen(ctools.csobservation):
149 # Return 149 # Return
150 return 150 return
151 151
  152 + def _compute_posang(self, pnt_dir, a, b):
  153 + """
  154 + Compute the difference in position angle wrt the pointing in degrees
  155 +
  156 + Parameters
  157 + ----------
  158 + pnt_dir : `~gammalib.GSkyDir`
  159 + Pointing direction
  160 + a : `~gammalib.GSkyDir`
  161 + First sky direction
  162 + a : `~gammalib.GSkyDir`
  163 + Second sky direction
  164 +
  165 + Returns
  166 + -------
  167 + posang : float
  168 + Position angle (degrees)
  169 + """
  170 + # Compute position angles
  171 + posang_a = pnt_dir.posang_deg(a) % 360
  172 + posang_b = pnt_dir.posang_deg(b) % 360
  173 +
  174 + # Compute difference
  175 + posang = abs(posang_a - posang_b)
  176 +
  177 + # Return position angle
  178 + return posang
  179 +
152 def _get_regions(self, filename): 180 def _get_regions(self, filename):
153 """ 181 """
154 Get regions from DS9 file or FITS file 182 Get regions from DS9 file or FITS file
@@ -192,26 +220,24 @@ class csphagen(ctools.csobservation): @@ -192,26 +220,24 @@ class csphagen(ctools.csobservation):
192 self['bkgregmin'].integer() 220 self['bkgregmin'].integer()
193 self['bkgregskip'].integer() 221 self['bkgregskip'].integer()
194 222
195 - # Set source region (so far only CIRCLE is supported) 223 + # If source shape is a circle the append GSkyRegionCircle
196 if self._srcshape == 'CIRCLE': 224 if self._srcshape == 'CIRCLE':
197 225
198 # Set circular source region 226 # Set circular source region
199 self._rad = self['rad'].real() 227 self._rad = self['rad'].real()
200 self._src_reg.append(gammalib.GSkyRegionCircle(self._src_dir, self._rad)) 228 self._src_reg.append(gammalib.GSkyRegionCircle(self._src_dir, self._rad))
201 229
  230 + # ... otherwise if source shape is a rectangle then append GSkyRegionRect
202 elif self._srcshape == 'RECT': 231 elif self._srcshape == 'RECT':
203 232
204 # Set rectangular source region 233 # Set rectangular source region
205 self._reg_width = self['width'].real() 234 self._reg_width = self['width'].real()
206 self._reg_height = self['height'].real() 235 self._reg_height = self['height'].real()
207 self._reg_posang = self['posang'].real() 236 self._reg_posang = self['posang'].real()
208 - self._src_reg.append(gammalib.GSkyRegionRect(self._src_dir  
209 - ,self._reg_width  
210 - ,self._reg_height  
211 - ,self._reg_posang  
212 - )  
213 - )  
214 - 237 + self._src_reg.append(gammalib.GSkyRegionRect(self._src_dir,
  238 + self._reg_width,
  239 + self._reg_height,
  240 + self._reg_posang))
215 241
216 # Query usage of background model 242 # Query usage of background model
217 self['use_model_bkg'].boolean() 243 self['use_model_bkg'].boolean()
@@ -357,118 +383,49 @@ class csphagen(ctools.csobservation): @@ -357,118 +383,49 @@ class csphagen(ctools.csobservation):
357 model = gammalib.GModelSky(spatial, spectral) 383 model = gammalib.GModelSky(spatial, spectral)
358 model.name('Dummy') 384 model.name('Dummy')
359 self._models.append(model) 385 self._models.append(model)
360 - self._srcname = 'Dummy' 386 + self._srcname = 'Dummy'
361 self['use_model_bkg'].boolean(False) 387 self['use_model_bkg'].boolean(False)
362 388
363 # Return 389 # Return
364 return 390 return
365 391
366 def _compute_region_separation(self, pnt_dir): 392 def _compute_region_separation(self, pnt_dir):
367 - """ Compute the separation angle for reflected off regions in radians. 393 + """
  394 + Compute the separation angle for reflected off regions in radians
368 395
369 Returns 396 Returns
370 ------- 397 -------
371 - angle : `float`  
372 - Separation angle of two off regions (rad) 398 + angle : float
  399 + Separation angle of two off regions (radians)
373 """ 400 """
374 # Initialise the result 401 # Initialise the result
375 - separation = -1 402 + separation = -1.0
376 403
377 # Compute offset of reflected regions to pointing position 404 # Compute offset of reflected regions to pointing position
378 offset = pnt_dir.dist_deg(self._src_dir) 405 offset = pnt_dir.dist_deg(self._src_dir)
379 406
  407 + # If shape is a circle then compute apparent diameter of the circle
  408 + # as separation
380 if self._srcshape == 'CIRCLE': 409 if self._srcshape == 'CIRCLE':
381 -  
382 - # Compute apparent diameter of the circle  
383 separation = 2.0 * self._rad / offset 410 separation = 2.0 * self._rad / offset
384 411
  412 + # ... otherwise if shape is a rectangle then compute the opening angle
  413 + # towards combinations of rectangle corners. This method overestimates
  414 + # the real need of space between the ectangles, so the method may be
  415 + # optimised to gain more off regions! Anyway, it is assured that the
  416 + # off regions will never overlap.
385 elif self._srcshape == 'RECT': 417 elif self._srcshape == 'RECT':
386 418
387 - # Compute the opening angle towards combinations of rectangle corners.  
388 - # This method overestimates the real need of space between the  
389 - # rectangles, so the method may be optimised to gain more off regions!  
390 - # Anyway, it is assured that the off regions will never overlap.  
391 -  
392 - # Get the corners 419 + # Get the sky directions of the corners of the rectangle
393 cs = [self._src_reg[0].get_corner(icorner) for icorner in range(4)] 420 cs = [self._src_reg[0].get_corner(icorner) for icorner in range(4)]
394 421
395 - # Auxillary, local method for opening angle computation  
396 - def __compute_posang(pnt_dir,a,b):  
397 - """ Compute the difference in position angle to the pointing in  
398 - degrees.  
399 - """  
400 - posang_a = pnt_dir.posang_deg(a) %360  
401 - posang_b = pnt_dir.posang_deg(b) %360  
402 - posang = abs(posang_a - posang_b)  
403 - return posang  
404 -  
405 # Compute the 6 opening angles 422 # Compute the 6 opening angles
406 combinations = [[0,1], [0,2], [0,3], [1,2], [1,3], [2,3]] 423 combinations = [[0,1], [0,2], [0,3], [1,2], [1,3], [2,3]]
407 - angles = [__compute_posang(pnt_dir, cs[i], cs[j]) for i,j in combinations] 424 + angles = [self._compute_posang(pnt_dir, cs[i], cs[j]) \
  425 + for i,j in combinations]
408 426
409 # The desired separation is the maximum opening angle 427 # The desired separation is the maximum opening angle
410 - separation = max(angles) *gammalib.deg2rad  
411 -  
412 -  
413 - ## Different approach:  
414 - ## Find the separation angle for which two rectangles to not overlap  
415 - ## Issue: Scanning not optimal.  
416 - # posang = pnt_dir.posang_deg(self._src_dir)  
417 - # dphi_incr = 0.1  
418 - # dphi = dphi_incr  
419 - # print("Src ctr direction: ra={} dec={}".format(self._src_dir.ra_deg(), self._src_dir.dec_deg()))  
420 - # print(self._src_reg)  
421 - # while dphi<360:  
422 -  
423 - # ctr_dir = pnt_dir.clone()  
424 - # ctr_dir.rotate_deg(posang + dphi, offset)  
425 - # print("Query ctr direction: ra={} dec={}".format(ctr_dir.ra_deg(), ctr_dir.dec_deg()))  
426 -  
427 - # # Create test rectangle  
428 - # reg = gammalib.GSkyRegionRect(ctr_dir  
429 - # ,self._reg_width  
430 - # ,self._reg_height  
431 - # ,self._reg_posang + dphi  
432 - # )  
433 - # print(reg)  
434 -  
435 - # # Check test rectangle corner containment in reference rectangle  
436 - # is_corner_contained = self._src_reg.overlaps(reg)  
437 - # # is_corner_contained = False  
438 - # # for icorner in range(4):  
439 - # # corner_dir = reg.get_corner(icorner)  
440 - # # is_corner_contained |= self._src_reg.contains(corner_dir)  
441 -  
442 - # # Check if any corner was contained  
443 - # if not is_corner_contained:  
444 - # diameter = dphi  
445 - # break  
446 -  
447 - # # Increment dphi  
448 - # dphi += dphi_incr  
449 -  
450 -  
451 - ## Very different approach: Compute the width along the circular  
452 - ## region placement path.  
453 - ## Issue: Long regions will overlap in the inner part.  
454 - # def l(w,h,phi):  
455 - # """ Super complicated method to compute the height along dec-axis  
456 - # of a rotated rectangle.  
457 - # """  
458 - # phi = np.deg2rad(phi) % (2*np.pi)  
459 - # phi_c = np.arctan2(w,h)  
460 - # if phi>=(0.5*np.pi) and (phi<np.pi):  
461 - # phi = np.pi-phi  
462 - # elif (phi>=np.pi) and (phi<(1.5*np.pi)):  
463 - # phi -=np.pi  
464 - # elif (phi>=(1.5*np.pi)) and (phi<(2*np.pi)):  
465 - # phi = 2*np.pi - phi  
466 -  
467 - # if (0<=phi) and (phi<phi_c):  
468 - # result = h/2/np.cos(phi)  
469 - # else:  
470 - # result = w/2/np.sin(phi)  
471 - # return 2*result 428 + separation = max(angles) * gammalib.deg2rad
472 429
473 # Return 430 # Return
474 return separation 431 return separation
@@ -551,11 +508,10 @@ class csphagen(ctools.csobservation): @@ -551,11 +508,10 @@ class csphagen(ctools.csobservation):
551 region = gammalib.GSkyRegionCircle(ctr_dir, self._rad) 508 region = gammalib.GSkyRegionCircle(ctr_dir, self._rad)
552 elif self._srcshape == 'RECT': 509 elif self._srcshape == 'RECT':
553 # Adjust the posang of the rectangle correspondingly 510 # Adjust the posang of the rectangle correspondingly
554 - region = gammalib.GSkyRegionRect(ctr_dir  
555 - ,self._reg_width  
556 - ,self._reg_height  
557 - ,self._reg_posang + dphi  
558 - ) 511 + region = gammalib.GSkyRegionRect(ctr_dir,
  512 + self._reg_width,
  513 + self._reg_height,
  514 + self._reg_posang + dphi)
559 if self._has_exclusion: 515 if self._has_exclusion:
560 if self._excl_reg.overlaps(region): 516 if self._excl_reg.overlaps(region):
561 517
doc/source/users/reference_manual/csphagen.rst
@@ -16,22 +16,27 @@ the OGIP format normally used in X-ray astronomy (PHA, ARF, RMF), @@ -16,22 +16,27 @@ the OGIP format normally used in X-ray astronomy (PHA, ARF, RMF),
16 16
17 If the ``bkgmethod`` parameter is ``REFLECTED``, the script will use an On region 17 If the ``bkgmethod`` parameter is ``REFLECTED``, the script will use an On region
18 shape defined by the ``srcshape`` parameter and generate reflected regions by 18 shape defined by the ``srcshape`` parameter and generate reflected regions by
19 -placing regions of the same shape that are reflected with respect to the pointing  
20 -direction. So far only circular regions are supported, with a center that is  
21 -specified by the ``ra`` and ``dec`` parameters if ``coordsys=CEL`` or the ``glon``  
22 -and ``glat`` parameters if ``coordsys=GAL``, and a radius that is specified by the  
23 -``rad`` parameter. Reflected regions are only generated for offset angles with  
24 -respect to the pointing direction that are smaller than the value specified by  
25 -the ``maxoffset`` parameter. If less than ``bkgregmin`` reflected regions can be  
26 -found because the offset angle between source and pointing direction is too small,  
27 -the observation will be skipped. Regions to be excluded for background  
28 -determination can be specified using a FITS mask file that is specified using the  
29 -``inexclusion`` parameter. A mask is a sky map where all pixel values that  
30 -differ from zero will be used as exclusion region. If the FITS file  
31 -contains multiple extensions and the user does not specify which one  
32 -to use, the extention ``EXCLUSION`` will be used if available (e.g.,  
33 -if you use a skymap generated by :ref:`ctskymap`).  
34 -Otherwise the primary extension will be used. 19 +placing regions of the same shape that are reflected with respect to the
  20 +pointing direction. So far circular and rectangular regions are supported.
  21 +Circular regions are defined by a center that is specified by the ``ra`` and
  22 +``dec`` parameters if ``coordsys=CEL`` or the ``glon`` and ``glat`` parameters if
  23 +``coordsys=GAL``, and a radius that is specified by the ``rad`` parameter.
  24 +Rectangular regions are defined by a center, again specified by either the
  25 +``ra`` and ``dec`` or the ``glon`` and ``glat`` parameters, a ``width`` parameter,
  26 +a ``height`` parameter and a ``posang`` parameter that specified the position
  27 +angle measured counter clockwise from celestial North. Note that the ``height``
  28 +axis is pointing in the direction of the position angle. Reflected regions are
  29 +only generated for offset angles with respect to the pointing direction that are
  30 +smaller than the value specified by the ``maxoffset`` parameter. If less than
  31 +``bkgregmin`` reflected regions can be found because the offset angle between
  32 +source and pointing direction is too small, the observation will be skipped.
  33 +Regions to be excluded for background determination can be specified using a
  34 +FITS mask file that is specified using the ``inexclusion`` parameter. A mask is
  35 +a sky map where all pixel values that differ from zero will be used as exclusion
  36 +region. If the FITS file contains multiple extensions and the user does not
  37 +specify which one to use, the extention ``EXCLUSION`` will be used if available
  38 +(e.g., if you use a skymap generated by :ref:`ctskymap`). Otherwise the primary
  39 +extension will be used.
35 40
36 Alternatively, if ``bkgmethod=CUSTOM`` is specified, the source and background 41 Alternatively, if ``bkgmethod=CUSTOM`` is specified, the source and background
37 regions will be specified using the ``srcregfile`` and ``bkgregfile`` parameters, 42 regions will be specified using the ``srcregfile`` and ``bkgregfile`` parameters,
@@ -132,9 +137,9 @@ General parameters @@ -132,9 +137,9 @@ General parameters
132 Exponent of the power law for ``POW`` energy binning. An exponent of 1.0 137 Exponent of the power law for ``POW`` energy binning. An exponent of 1.0
133 corresponds to a logarithmic energy binning. 138 corresponds to a logarithmic energy binning.
134 139
135 -``(srcshape = CIRCLE) <CIRCLE> [string]``  
136 - Shape of the source region. So far only ``CIRCLE`` exists which defines a  
137 - circular region around given position. 140 +``srcshape <CIRCLE|RECT> [string]``
  141 + Shape of the source region. ``CIRCLE`` defines a circular region around given
  142 + position, ``RECT`` defines a rectangle centred on a given position.
138 143
139 ``coordsys <CEL|GAL> [string]`` 144 ``coordsys <CEL|GAL> [string]``
140 Coordinate system (CEL - celestial, GAL - galactic). 145 Coordinate system (CEL - celestial, GAL - galactic).
@@ -154,6 +159,16 @@ General parameters @@ -154,6 +159,16 @@ General parameters
154 ``rad [real]`` 159 ``rad [real]``
155 Radius of source region circle (deg). 160 Radius of source region circle (deg).
156 161
  162 +``width [real]``
  163 + Width of source region rectangle (deg).
  164 +
  165 +``height [real]``
  166 + Height of source region rectangle (deg).
  167 +
  168 +``posang [real]``
  169 + Position angle of source region rectangle, counted counterclockwise from
  170 + celestial North (deg).
  171 +
157 ``srcregfile [file]`` 172 ``srcregfile [file]``
158 Source region file (ds9 or FITS WCS map). 173 Source region file (ds9 or FITS WCS map).
159 174