Commit 844130f6ff66b7335f01dec9e40ca78d75c2e917
1 parent
2469a2e5
Add GC survey
Showing
1 changed file
with
204 additions
and
47 deletions
examples/make_pointings.py
| 1 | #! /usr/bin/env python | 1 | #! /usr/bin/env python |
| 2 | # ========================================================================== | 2 | # ========================================================================== |
| 3 | -# This script simulates pointing patterns for CTA surveys. | 3 | +# This script generated pointing patterns for CTA observations. |
| 4 | # | 4 | # |
| 5 | # Usage: | 5 | # Usage: |
| 6 | # ./make_pointings.py | 6 | # ./make_pointings.py |
| @@ -28,52 +28,133 @@ import sys | @@ -28,52 +28,133 @@ import sys | ||
| 28 | import math | 28 | import math |
| 29 | 29 | ||
| 30 | 30 | ||
| 31 | -# ======================= # | ||
| 32 | -# Setup double row scheme # | ||
| 33 | -# ======================= # | ||
| 34 | -def set_double_row(lmin=-30.0, lmax=30.0, separation=3.0, hours=100.0, site=None): | 31 | +# ============================================================ # |
| 32 | +# Get positions of pointings on sky for an interleaved pattern # | ||
| 33 | +# ============================================================ # | ||
| 34 | +def get_positions(xmin, xmax, ymin, ymax, step): | ||
| 35 | """ | 35 | """ |
| 36 | - Setup double row scheme. | 36 | + Get positions for a patch of interleaved pointings on the sky. |
| 37 | + The function does respect the latitude dependence of the | ||
| 38 | + pointing distance. The step parameter is for a latitude of | ||
| 39 | + zero. | ||
| 40 | + """ | ||
| 41 | + # Initialise positions | ||
| 42 | + positions = [] | ||
| 43 | + | ||
| 44 | + # Determine ystep and number of rows | ||
| 45 | + ystep = step * math.sqrt(0.75) | ||
| 46 | + ny = int((ymax-ymin)/ystep+1.5) | ||
| 47 | + rescale = (ymax-ymin)/(ystep*(ny-1)) | ||
| 48 | + ystep *= rescale | ||
| 49 | + print("Number of rows ....: %d" % (ny)) | ||
| 50 | + | ||
| 51 | + # Loop over rows | ||
| 52 | + y = ymin | ||
| 53 | + for row in range(ny): | ||
| 54 | + | ||
| 55 | + # Determine xstep and number of pointings in row | ||
| 56 | + xstep = step * math.cos(gammalib.deg2rad * y) | ||
| 57 | + nx = int((xmax-xmin)/xstep+1.5) | ||
| 58 | + rescale = (xmax-xmin)/(xstep*(nx-1)) | ||
| 59 | + xstep *= rescale | ||
| 60 | + | ||
| 61 | + # Set x offset | ||
| 62 | + if row % 2 == 0: | ||
| 63 | + x = xmin | ||
| 64 | + else: | ||
| 65 | + x = xmin + 0.5 * xstep | ||
| 66 | + #print(row, x) | ||
| 67 | + | ||
| 68 | + # Append pointings | ||
| 69 | + for pnt in range(nx): | ||
| 70 | + positions.append({'x': x, 'y': y}) | ||
| 71 | + x += xstep | ||
| 72 | + if x >= 360.0: | ||
| 73 | + x -= 360.0 | ||
| 74 | + | ||
| 75 | + # Increment y | ||
| 76 | + y += ystep | ||
| 77 | + | ||
| 78 | + # Return positions | ||
| 79 | + return positions | ||
| 80 | + | ||
| 81 | + | ||
| 82 | +# ====================== # | ||
| 83 | +# Setup patch on the sky # | ||
| 84 | +# ====================== # | ||
| 85 | +def set_patch(lmin=-30.0, lmax=30.0, bmin=-1.5, bmax=+1.5, \ | ||
| 86 | + separation=3.0, hours=100.0, \ | ||
| 87 | + site=None, lst=True, autodec=0.0): | ||
| 88 | + """ | ||
| 89 | + Setup pointing patch on the sky. | ||
| 37 | """ | 90 | """ |
| 38 | # Initialise observation definition | 91 | # Initialise observation definition |
| 39 | obsdef = [] | 92 | obsdef = [] |
| 40 | 93 | ||
| 41 | - # Compute number of pointings in row | ||
| 42 | - n_pnt_per_row = int((lmax-lmin)/separation+0.5) | ||
| 43 | - n_pnt = 2*n_pnt_per_row | 94 | + # Get pointing positions |
| 95 | + pointings = get_positions(lmin, lmax, bmin, bmax, separation) | ||
| 44 | 96 | ||
| 45 | - # Compute offset from Galactic plane (degrees) | ||
| 46 | - offset = separation * 0.5 * math.sqrt(0.75) | ||
| 47 | - | ||
| 48 | - # Compute duration per pointing (seconds) | 97 | + # Determine number of pointings and pointing duration |
| 98 | + n_pnt = len(pointings) | ||
| 49 | duration = hours*3600.0/float(n_pnt) | 99 | duration = hours*3600.0/float(n_pnt) |
| 50 | 100 | ||
| 51 | - # Set upper row | ||
| 52 | - lon = lmin | ||
| 53 | - for i in range(n_pnt_per_row): | ||
| 54 | - obs = {'lon': lon, 'lat': offset, 'duration': duration} | ||
| 55 | - obsdef.append(obs) | ||
| 56 | - lon += separation | 101 | + # Observing time collectors |
| 102 | + exposure_south = 0.0 | ||
| 103 | + exposure_north = 0.0 | ||
| 57 | 104 | ||
| 58 | - # Set lower row | ||
| 59 | - lon = lmin + 0.5*separation | ||
| 60 | - for i in range(n_pnt_per_row): | ||
| 61 | - obs = {'lon': lon, 'lat': -offset, 'duration': duration} | ||
| 62 | - obsdef.append(obs) | ||
| 63 | - lon += separation | 105 | + # Set observations |
| 106 | + for pnt in pointings: | ||
| 64 | 107 | ||
| 65 | - # Optionally add-in site dependent IRF | ||
| 66 | - if site != None: | ||
| 67 | - if site == "North": | ||
| 68 | - caldb = "tenerife" | ||
| 69 | - irf = "DESY20140105_50h" | ||
| 70 | - else: | ||
| 71 | - caldb = "aar" | ||
| 72 | - irf = "DESY20140105_50h" | ||
| 73 | - for obs in obsdef: | 108 | + # Set positions and duration |
| 109 | + obs = {'lon': pnt['x'], 'lat': pnt['y'], 'duration': duration} | ||
| 110 | + | ||
| 111 | + # Optionally add-in site dependent IRF | ||
| 112 | + if site != None: | ||
| 113 | + | ||
| 114 | + # Handle automatic site switching | ||
| 115 | + if site == "Automatic": | ||
| 116 | + pos = gammalib.GSkyDir() | ||
| 117 | + pos.lb_deg(pnt['x'], pnt['y']) | ||
| 118 | + dec = pos.dec_deg() | ||
| 119 | + if (dec >= autodec): | ||
| 120 | + obs_site = "North" | ||
| 121 | + else: | ||
| 122 | + obs_site = "South" | ||
| 123 | + else: | ||
| 124 | + obs_site = site | ||
| 125 | + | ||
| 126 | + # Set site IRF | ||
| 127 | + if obs_site == "North": | ||
| 128 | + caldb = "tenerife" | ||
| 129 | + if lst: | ||
| 130 | + irf = "DESY20140105_50h" | ||
| 131 | + else: | ||
| 132 | + irf = "DESY20140105_50h_noLST" | ||
| 133 | + exposure_north += duration | ||
| 134 | + else: | ||
| 135 | + caldb = "aar" | ||
| 136 | + if lst: | ||
| 137 | + irf = "DESY20140105_50h" | ||
| 138 | + else: | ||
| 139 | + irf = "DESY20140105_50h_noLST" | ||
| 140 | + exposure_south += duration | ||
| 141 | + | ||
| 142 | + # Set IRF information | ||
| 74 | obs['caldb'] = caldb | 143 | obs['caldb'] = caldb |
| 75 | obs['irf'] = irf | 144 | obs['irf'] = irf |
| 76 | 145 | ||
| 146 | + # Append observation | ||
| 147 | + obsdef.append(obs) | ||
| 148 | + | ||
| 149 | + # Dump statistics | ||
| 150 | + print("Number of pointings: %d (%.2f sec)" % (n_pnt,duration)) | ||
| 151 | + print("South array .......: %.2f hours (%.2f%%)" % \ | ||
| 152 | + (exposure_south/3600.0, \ | ||
| 153 | + 100.0*exposure_south/(exposure_south+exposure_north))) | ||
| 154 | + print("North array .......: %.2f hours (%.2f%%)" % \ | ||
| 155 | + (exposure_north/3600.0, \ | ||
| 156 | + 100.0*exposure_north/(exposure_south+exposure_north))) | ||
| 157 | + | ||
| 77 | # Return observation definition | 158 | # Return observation definition |
| 78 | return obsdef | 159 | return obsdef |
| 79 | 160 | ||
| @@ -81,7 +162,7 @@ def set_double_row(lmin=-30.0, lmax=30.0, separation=3.0, hours=100.0, site=None | @@ -81,7 +162,7 @@ def set_double_row(lmin=-30.0, lmax=30.0, separation=3.0, hours=100.0, site=None | ||
| 81 | # =========================== # | 162 | # =========================== # |
| 82 | # Setup Galactic plane survey # | 163 | # Setup Galactic plane survey # |
| 83 | # =========================== # | 164 | # =========================== # |
| 84 | -def set_gps(): | 165 | +def set_gps(separation=3.0, bmin=-1.3, bmax=1.3, lst=True): |
| 85 | """ | 166 | """ |
| 86 | Setup Galactic plane survey. | 167 | Setup Galactic plane survey. |
| 87 | """ | 168 | """ |
| @@ -89,19 +170,72 @@ def set_gps(): | @@ -89,19 +170,72 @@ def set_gps(): | ||
| 89 | obsdef = [] | 170 | obsdef = [] |
| 90 | 171 | ||
| 91 | # Add inner region South | 172 | # Add inner region South |
| 92 | - obsdef.extend(set_double_row(lmin=-60.0, lmax=60.0, hours=780, site="South")) | 173 | + obsdef.extend(set_patch(lmin=-60.0, lmax=60.0, bmin=bmin, bmax=bmax, \ |
| 174 | + separation=separation, hours=780, \ | ||
| 175 | + site="South", lst=lst)) | ||
| 93 | 176 | ||
| 94 | # Add Vela & Carina region | 177 | # Add Vela & Carina region |
| 95 | - obsdef.extend(set_double_row(lmin=240.0, lmax=300.0, hours=180, site="South")) | 178 | + obsdef.extend(set_patch(lmin=240.0, lmax=300.0, bmin=bmin, bmax=bmax, \ |
| 179 | + separation=separation, hours=180, \ | ||
| 180 | + site="South", lst=lst)) | ||
| 96 | 181 | ||
| 97 | # Add 210-240 region | 182 | # Add 210-240 region |
| 98 | - obsdef.extend(set_double_row(lmin=210.0, lmax=240.0, hours=60, site="South")) | 183 | + obsdef.extend(set_patch(lmin=210.0, lmax=240.0, bmin=bmin, bmax=bmax, \ |
| 184 | + separation=separation, hours=60, \ | ||
| 185 | + site="South", lst=lst)) | ||
| 99 | 186 | ||
| 100 | # Add Cygnus, Perseus | 187 | # Add Cygnus, Perseus |
| 101 | - obsdef.extend(set_double_row(lmin=60.0, lmax=150.0, hours=450, site="North")) | 188 | + obsdef.extend(set_patch(lmin=60.0, lmax=150.0, bmin=bmin, bmax=bmax, \ |
| 189 | + separation=separation, hours=450, \ | ||
| 190 | + site="North", lst=lst)) | ||
| 102 | 191 | ||
| 103 | # Add Anticentre | 192 | # Add Anticentre |
| 104 | - obsdef.extend(set_double_row(lmin=150.0, lmax=210.0, hours=150, site="North")) | 193 | + obsdef.extend(set_patch(lmin=150.0, lmax=210.0, bmin=bmin, bmax=bmax, \ |
| 194 | + separation=separation, hours=150, \ | ||
| 195 | + site="North", lst=lst)) | ||
| 196 | + | ||
| 197 | + # Return observation definition | ||
| 198 | + return obsdef | ||
| 199 | + | ||
| 200 | + | ||
| 201 | +# ========================== # | ||
| 202 | +# Setup Extragalactic survey # | ||
| 203 | +# ========================== # | ||
| 204 | +def set_extgal(separation=3.0, lst=True): | ||
| 205 | + """ | ||
| 206 | + Setup Extragalactic survey. | ||
| 207 | + """ | ||
| 208 | + # Initialise observation definition | ||
| 209 | + obsdef = [] | ||
| 210 | + | ||
| 211 | + # Set patch | ||
| 212 | + obsdef.extend(set_patch(lmin=-90.0, lmax=90.0, bmin=+5.0, bmax=+90.0, \ | ||
| 213 | + separation=separation, hours=1000, \ | ||
| 214 | + site="Automatic", lst=lst, autodec=25.0)) | ||
| 215 | + | ||
| 216 | + # Return observation definition | ||
| 217 | + return obsdef | ||
| 218 | + | ||
| 219 | + | ||
| 220 | +# ========================= # | ||
| 221 | +# Setup Galactic centre KSP # | ||
| 222 | +# ========================= # | ||
| 223 | +def set_gc(lst=True): | ||
| 224 | + """ | ||
| 225 | + Setup Galactic centre KSP. | ||
| 226 | + """ | ||
| 227 | + # Initialise observation definition | ||
| 228 | + obsdef = [] | ||
| 229 | + | ||
| 230 | + # Central wobble | ||
| 231 | + obsdef.extend(set_patch(lmin=-0.5, lmax=0.5, bmin=-0.5, bmax=0.5, \ | ||
| 232 | + separation=0.1, hours=525, \ | ||
| 233 | + site="South", lst=lst)) | ||
| 234 | + | ||
| 235 | + # Extended region | ||
| 236 | + obsdef.extend(set_patch(lmin=-10.0, lmax=10.0, bmin=-10.0, bmax=10.0, \ | ||
| 237 | + separation=1.5, hours=300, \ | ||
| 238 | + site="South", lst=lst)) | ||
| 105 | 239 | ||
| 106 | # Return observation definition | 240 | # Return observation definition |
| 107 | return obsdef | 241 | return obsdef |
| @@ -151,27 +285,50 @@ def write_obsdef(filename, obsdef): | @@ -151,27 +285,50 @@ def write_obsdef(filename, obsdef): | ||
| 151 | # ======================== # | 285 | # ======================== # |
| 152 | if __name__ == '__main__': | 286 | if __name__ == '__main__': |
| 153 | """ | 287 | """ |
| 154 | - CTA survey simulation. | 288 | + CTA pointing pattern generation. |
| 155 | """ | 289 | """ |
| 156 | # Initialise flags | 290 | # Initialise flags |
| 157 | need_help = False | 291 | need_help = False |
| 158 | 292 | ||
| 159 | # Test for command line arguments | 293 | # Test for command line arguments |
| 160 | - print(sys.argv[0]) | 294 | + #print(sys.argv[0]) |
| 161 | if (len(sys.argv) > 1): | 295 | if (len(sys.argv) > 1): |
| 162 | if sys.argv[1] == "-h": | 296 | if sys.argv[1] == "-h": |
| 163 | need_help = True | 297 | need_help = True |
| 164 | else: | 298 | else: |
| 165 | - need_help = True | 299 | + obsname = sys.argv[1] |
| 300 | + else: | ||
| 301 | + need_help = True | ||
| 166 | 302 | ||
| 167 | # Print help if needed and exit | 303 | # Print help if needed and exit |
| 168 | if need_help: | 304 | if need_help: |
| 169 | print("Usage: make_pointing.py [OPTIONS]") | 305 | print("Usage: make_pointing.py [OPTIONS]") |
| 170 | print(" -h Display this usage message") | 306 | print(" -h Display this usage message") |
| 307 | + print(" gps Galactic plane scan (2 row scheme)") | ||
| 308 | + print(" gps3 Galactic plane scan (3 row scheme)") | ||
| 309 | + print(" extgal Extragalactic survey") | ||
| 310 | + print(" gc Galactic centre") | ||
| 171 | sys.exit() | 311 | sys.exit() |
| 172 | 312 | ||
| 173 | - # Test | ||
| 174 | - obsdef = set_gps() | 313 | + # Galactic plane scan |
| 314 | + if obsname == "gps": | ||
| 315 | + obsdef = set_gps(lst=True) | ||
| 316 | + write_obsdef("gps.dat", obsdef) | ||
| 317 | + elif obsname == "gps3": | ||
| 318 | + obsdef = set_gps(separation=1.5, lst=True) | ||
| 319 | + write_obsdef("gps3.dat", obsdef) | ||
| 320 | + | ||
| 321 | + # Extragalactic survey | ||
| 322 | + elif obsname == "extgal": | ||
| 323 | + obsdef = set_extgal(lst=True) | ||
| 324 | + write_obsdef("extgal.dat", obsdef) | ||
| 325 | + | ||
| 326 | + # Galactic centre | ||
| 327 | + elif obsname == "gc": | ||
| 328 | + obsdef = set_gc(lst=True) | ||
| 329 | + write_obsdef("gc.dat", obsdef) | ||
| 175 | 330 | ||
| 176 | - # Write observation definition file | ||
| 177 | - write_obsdef("gps.dat", obsdef) | 331 | + # Invalid pattern |
| 332 | + else: | ||
| 333 | + print("Unknown option \""+obsname+"\"") | ||
| 334 | + |