icecube-skyreader 1.3.2__tar.gz → 1.3.3__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (20) hide show
  1. {icecube-skyreader-1.3.2 → icecube-skyreader-1.3.3}/PKG-INFO +1 -1
  2. {icecube-skyreader-1.3.2 → icecube-skyreader-1.3.3}/icecube_skyreader.egg-info/PKG-INFO +1 -1
  3. {icecube-skyreader-1.3.2 → icecube-skyreader-1.3.3}/skyreader/__init__.py +1 -1
  4. {icecube-skyreader-1.3.2 → icecube-skyreader-1.3.3}/skyreader/plot/plot.py +28 -153
  5. {icecube-skyreader-1.3.2 → icecube-skyreader-1.3.3}/skyreader/plot/plotting_tools.py +5 -1
  6. {icecube-skyreader-1.3.2 → icecube-skyreader-1.3.3}/skyreader/utils/handle_map_data.py +10 -6
  7. {icecube-skyreader-1.3.2 → icecube-skyreader-1.3.3}/LICENSE +0 -0
  8. {icecube-skyreader-1.3.2 → icecube-skyreader-1.3.3}/README.md +0 -0
  9. {icecube-skyreader-1.3.2 → icecube-skyreader-1.3.3}/icecube_skyreader.egg-info/SOURCES.txt +0 -0
  10. {icecube-skyreader-1.3.2 → icecube-skyreader-1.3.3}/icecube_skyreader.egg-info/dependency_links.txt +0 -0
  11. {icecube-skyreader-1.3.2 → icecube-skyreader-1.3.3}/icecube_skyreader.egg-info/requires.txt +0 -0
  12. {icecube-skyreader-1.3.2 → icecube-skyreader-1.3.3}/icecube_skyreader.egg-info/top_level.txt +0 -0
  13. {icecube-skyreader-1.3.2 → icecube-skyreader-1.3.3}/setup.cfg +0 -0
  14. {icecube-skyreader-1.3.2 → icecube-skyreader-1.3.3}/setup.py +0 -0
  15. {icecube-skyreader-1.3.2 → icecube-skyreader-1.3.3}/skyreader/event_metadata.py +0 -0
  16. {icecube-skyreader-1.3.2 → icecube-skyreader-1.3.3}/skyreader/plot/__init__.py +0 -0
  17. {icecube-skyreader-1.3.2 → icecube-skyreader-1.3.3}/skyreader/py.typed +0 -0
  18. {icecube-skyreader-1.3.2 → icecube-skyreader-1.3.3}/skyreader/result.py +0 -0
  19. {icecube-skyreader-1.3.2 → icecube-skyreader-1.3.3}/skyreader/utils/__init__.py +0 -0
  20. {icecube-skyreader-1.3.2 → icecube-skyreader-1.3.3}/skyreader/utils/areas.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: icecube-skyreader
3
- Version: 1.3.2
3
+ Version: 1.3.3
4
4
  Summary: An API for Results Produced by SkyDriver & the Skymap Scanner
5
5
  Home-page: https://github.com/icecube/skyreader
6
6
  Download-URL: https://pypi.org/project/icecube-skyreader/
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: icecube-skyreader
3
- Version: 1.3.2
3
+ Version: 1.3.3
4
4
  Summary: An API for Results Produced by SkyDriver & the Skymap Scanner
5
5
  Home-page: https://github.com/icecube/skyreader
6
6
  Download-URL: https://pypi.org/project/icecube-skyreader/
@@ -17,7 +17,7 @@ __all__ = [
17
17
  # is zero for an official release, positive for a development branch,
18
18
  # or negative for a release candidate or beta (after the base version
19
19
  # number has been incremented)
20
- __version__ = "1.3.2"
20
+ __version__ = "1.3.3"
21
21
  version_info = (
22
22
  int(__version__.split(".")[0]),
23
23
  int(__version__.split(".")[1]),
@@ -21,7 +21,6 @@ from matplotlib.projections import projection_registry # type: ignore[import]
21
21
 
22
22
  from .plotting_tools import (
23
23
  AstroMollweideAxes,
24
- DecFormatter,
25
24
  format_fits_header,
26
25
  hp_ticklabels,
27
26
  plot_catalog
@@ -42,7 +41,7 @@ LOGGER = logging.getLogger("skyreader.plot")
42
41
  class SkyScanPlotter:
43
42
  PLOT_SIZE_Y_IN: float = 3.85
44
43
  PLOT_SIZE_X_IN: float = 6
45
- PLOT_DPI_STANDARD = 150
44
+ PLOT_DPI_STANDARD = 300
46
45
  PLOT_DPI_ZOOMED = 1200
47
46
  PLOT_COLORMAP = matplotlib.colormaps['plasma_r']
48
47
 
@@ -55,7 +54,6 @@ class SkyScanPlotter:
55
54
  def create_plot(
56
55
  self,
57
56
  result: SkyScanResult,
58
- dozoom: bool = False,
59
57
  systematics: bool = False,
60
58
  llh_map: bool = True,
61
59
  angular_error_floor: Union[None, float] = None,
@@ -65,7 +63,7 @@ class SkyScanPlotter:
65
63
  PLOT_DPI_STANDARD and PLOT_DPI_ZOOMED. Zoomed mode is very inefficient
66
64
  as the meshgrid is created for the full sky.
67
65
  """
68
- dpi = self.PLOT_DPI_STANDARD if not dozoom else self.PLOT_DPI_ZOOMED
66
+ dpi = self.PLOT_DPI_STANDARD
69
67
 
70
68
  # number of grid points along RA coordinate
71
69
  xsize = int(self.PLOT_SIZE_X_IN * dpi)
@@ -90,11 +88,7 @@ class SkyScanPlotter:
90
88
  mjd_str = f"MJD: {event_metadata.mjd}"
91
89
  plot_title = f"{run_str} {evt_str} {typ_str} {mjd_str}"
92
90
 
93
- if dozoom:
94
- addition_to_filename = 'plot_zoomed_legacy.'
95
- else:
96
- addition_to_filename = ''
97
- plot_filename = f"{unique_id}.{addition_to_filename}pdf"
91
+ plot_filename = f"{unique_id}.pdf"
98
92
  LOGGER.info(f"saving plot to {plot_filename}")
99
93
 
100
94
  grid_value, grid_ra, grid_dec, equatorial_map, _ = extract_map(
@@ -107,8 +101,6 @@ class SkyScanPlotter:
107
101
  grid_pix = healpy.ang2pix(max(nsides), np.pi/2. - DEC, RA)
108
102
  plotting_map = equatorial_map[grid_pix]
109
103
 
110
- min_value = grid_value[0] # for probability map, this is actually
111
- # the max_value
112
104
  min_dec = grid_dec[0]
113
105
  min_ra = grid_ra[0]
114
106
 
@@ -118,12 +110,6 @@ class SkyScanPlotter:
118
110
  LOGGER.info(f"min Dec: {min_dec * 180./np.pi} deg")
119
111
 
120
112
  # renormalize
121
- if dozoom:
122
- plotting_map = plotting_map - min_value
123
- equatorial_map = equatorial_map - min_value
124
- vmin = 0.
125
- vmax = 50
126
- map_to_plot = plotting_map
127
113
  if llh_map:
128
114
  cmap = self.PLOT_COLORMAP
129
115
  text_colorbar = r"$-2 \ln(L)$"
@@ -162,11 +148,8 @@ class SkyScanPlotter:
162
148
 
163
149
  ax = None
164
150
 
165
- if dozoom:
166
- ax = fig.add_subplot(111) # ,projection='cartesian')
167
- else:
168
- cmap.set_over(alpha=0.) # make underflows transparent
169
- ax = fig.add_subplot(111, projection='astro mollweide')
151
+ cmap.set_over(alpha=0.) # make underflows transparent
152
+ ax = fig.add_subplot(111, projection='astro mollweide')
170
153
 
171
154
  # rasterized makes the map bitmap while the labels remain vectorial
172
155
  # flip longitude to the astro convention
@@ -185,124 +168,26 @@ class SkyScanPlotter:
185
168
  contour_levels, contour_labels, contour_colors
186
169
  ) = get_contour_levels(equatorial_map, llh_map, systematics)
187
170
 
188
- leg_element = []
189
- cs_collections = []
190
171
  for level, color in zip(contour_levels, contour_colors):
191
172
  if not llh_map:
192
173
  level = np.log10(level)
193
- contour_set = ax.contour(
174
+ ax.contour(
194
175
  ra, dec, map_to_plot, levels=[level], colors=[color]
195
176
  )
196
- cs_collections.append(contour_set.collections[0])
197
- e, _ = contour_set.legend_elements()
198
- leg_element.append(e[0])
199
-
200
- if not dozoom:
201
- # graticule
202
- if isinstance(ax, AstroMollweideAxes):
203
- # mypy guard
204
- ax.set_longitude_grid(30)
205
- ax.set_latitude_grid(30)
206
- cb = fig.colorbar(
207
- image,
208
- orientation='horizontal',
209
- shrink=.6,
210
- pad=0.05,
211
- ticks=[vmin, vmax],
212
- )
213
- cb.ax.xaxis.set_label_text(text_colorbar)
214
- else:
215
- ax.set_xlabel('right ascension')
216
- ax.set_ylabel('declination')
217
- cb = fig.colorbar(
218
- image, orientation='horizontal', shrink=.6, pad=0.13
219
- )
220
- cb.ax.xaxis.set_label_text(r"$-2 \Delta \ln (L)$")
221
-
222
- leg_labels = []
223
- for i in range(len(contour_labels)):
224
- vs = cs_collections[i].get_paths()[0].vertices
225
- # Compute area enclosed by vertices.
226
- # Take absolute values to be independent of orientation of
227
- # the boundary integral.
228
- contour_area = abs(calculate_area(vs)) # in square-radians
229
- # convert to square-degrees
230
- contour_area_sqdeg = contour_area*(180.*180.)/(np.pi*np.pi)
231
-
232
- area_string = f"area: {contour_area_sqdeg:.2f}sqdeg"
233
- leg_labels.append(
234
- f'{contour_labels[i]} - {area_string}'
235
- )
236
-
237
- ax.scatter(
238
- min_ra,
239
- min_dec,
240
- s=20,
241
- marker='*',
242
- color='black',
243
- label=r'scan best-fit',
244
- zorder=2
245
- )
246
- ax.legend(
247
- leg_element,
248
- leg_labels,
249
- loc='lower right',
250
- fontsize=8,
251
- scatterpoints=1,
252
- ncol=2
253
- )
254
-
255
- LOGGER.info(f"Contour Area (90%): {contour_area_sqdeg} "
256
- f"degrees (cartesian) "
257
- f"{contour_area_sqdeg * np.cos(min_dec)**2} "
258
- "degrees (scaled)")
259
- x_width = 1.6 * np.sqrt(contour_area_sqdeg)
260
- LOGGER.info(f"x width is {x_width}")
261
- if np.isnan(x_width):
262
- # this get called only when contour_area / x_width is
263
- # NaN so possibly never invoked in typical situations
264
- raise RuntimeError(
265
- "Estimated area / width is NaN and the fallback logic "
266
- "for this scenario is no longer supported. If you "
267
- "encounter this error raise an issue to SkyReader."
268
- )
269
- # mypy error: "QuadContourSet" has no attribute "allsegs"
270
- # [attr-defined]. This attribute is likely deprecated but
271
- # this scenario is rarely (if ever) hit original code is
272
- # kept commented for the time being
273
-
274
- # note: contour_set is re-assigned at every iteration of
275
- # the loop on contour_levels, contour_colors, so this
276
- # effectively corresponds to the last contour_set
277
- # x_width = 1.6*(max(contour_set.allsegs[i][0][:,0]) -
278
- # min(contour_set.allsegs[i][0][:,0]))
279
-
280
- y_width = 0.5 * x_width
281
-
282
- lower_x = max(min_ra - x_width*np.pi/180., 0.)
283
- upper_x = min(min_ra + x_width*np.pi/180., 2 * np.pi)
284
- lower_y = max(min_dec - y_width*np.pi/180., -np.pi/2.)
285
- upper_y = min(min_dec + y_width*np.pi/180., np.pi/2.)
286
177
 
287
- ax.set_xlim(upper_x, lower_x)
288
- ax.set_ylim(lower_y, upper_y)
289
-
290
- # why not RAFormatter?
291
- ax.xaxis.set_major_formatter(DecFormatter())
292
-
293
- ax.yaxis.set_major_formatter(DecFormatter())
294
-
295
- factor = 0.25*(np.pi/180.)
296
- while (upper_x - lower_x)/factor > 6:
297
- factor *= 2.
298
- tick_label_grid = factor
299
-
300
- ax.xaxis.set_major_locator(
301
- matplotlib.ticker.MultipleLocator(base=tick_label_grid)
302
- )
303
- ax.yaxis.set_major_locator(
304
- matplotlib.ticker.MultipleLocator(base=tick_label_grid)
305
- )
178
+ # graticule
179
+ if isinstance(ax, AstroMollweideAxes):
180
+ # mypy guard
181
+ ax.set_longitude_grid(30)
182
+ ax.set_latitude_grid(30)
183
+ cb = fig.colorbar(
184
+ image,
185
+ orientation='horizontal',
186
+ shrink=.6,
187
+ pad=0.05,
188
+ ticks=[vmin, vmax],
189
+ )
190
+ cb.ax.xaxis.set_label_text(text_colorbar)
306
191
 
307
192
  # cb.ax.xaxis.labelpad = -8
308
193
  # workaround for issue with viewers, see colorbar docstring
@@ -311,9 +196,6 @@ class SkyScanPlotter:
311
196
  if isinstance(cb.solids, matplotlib.collections.QuadMesh):
312
197
  cb.solids.set_edgecolor("face")
313
198
 
314
- if dozoom:
315
- ax.set_aspect('equal')
316
-
317
199
  ax.tick_params(axis='x', labelsize=10)
318
200
  ax.tick_params(axis='y', labelsize=10)
319
201
 
@@ -333,20 +215,12 @@ class SkyScanPlotter:
333
215
 
334
216
  # remove white space around figure
335
217
  spacing = 0.01
336
- if not dozoom:
337
- fig.subplots_adjust(
338
- bottom=spacing,
339
- top=1.-spacing,
340
- left=spacing+0.04,
341
- right=1.-spacing
342
- )
343
- else:
344
- fig.subplots_adjust(
345
- bottom=spacing,
346
- top=0.92-spacing,
347
- left=spacing+0.1,
348
- right=1.-spacing
349
- )
218
+ fig.subplots_adjust(
219
+ bottom=spacing,
220
+ top=1.-spacing,
221
+ left=spacing+0.04,
222
+ right=1.-spacing
223
+ )
350
224
 
351
225
  # set the title
352
226
  fig.suptitle(plot_title)
@@ -812,7 +686,7 @@ class SkyScanPlotter:
812
686
  plt.legend(fontsize=6, loc="lower left")
813
687
 
814
688
  # save flattened map
815
- equatorial_map, column_names = prepare_flattened_map(
689
+ equatorial_map, column_names, column_units = prepare_flattened_map(
816
690
  equatorial_map, llh_map
817
691
  )
818
692
  if llh_map:
@@ -825,8 +699,9 @@ class SkyScanPlotter:
825
699
  equatorial_map,
826
700
  coord='C',
827
701
  column_names=column_names,
702
+ column_units=column_units,
828
703
  extra_header=fits_header,
829
- overwrite=True
704
+ overwrite=True,
830
705
  )
831
706
  multiorder_map, column_names = prepare_multiorder_map(
832
707
  grid_value, uniq_array, llh_map, column_names
@@ -4,6 +4,7 @@
4
4
  # flake8: noqa
5
5
 
6
6
  import astropy.io.fits as pyfits # type: ignore[import]
7
+ from astropy.time import Time # type: ignore[import]
7
8
  import healpy # type: ignore[import]
8
9
  import matplotlib # type: ignore[import]
9
10
  import matplotlib.patheffects as path_effects # type: ignore[import]
@@ -28,11 +29,14 @@ def format_fits_header(
28
29
  else:
29
30
  uncertainty_comment = 'Highest posterior density 90% credible region'
30
31
 
32
+ t = Time(mjd, format="mjd")
33
+
31
34
  header = [
32
35
  ('RUNID', run_id),
33
36
  ('EVENTID', event_id),
34
37
  ('SENDER', 'IceCube Collaboration'),
35
- ('EventMJD', mjd),
38
+ ('DATE-OBS', t.isot, 'UTC date of the observation'),
39
+ ('MJD-OBS', mjd, 'modified Julian date of the observation'),
36
40
  ('I3TYPE', f'{event_type}','Alert Type'),
37
41
  ('RA', np.round(ra,2),'Degree'),
38
42
  ('DEC', np.round(dec,2),'Degree'),
@@ -362,20 +362,22 @@ def clean_data_multiorder_map(
362
362
  def prepare_flattened_map(
363
363
  equatorial_map: np.ndarray,
364
364
  llh_map: bool,
365
- ) -> Tuple[np.ndarray, List[str]]:
365
+ ) -> Tuple[np.ndarray, List[str], Union[List[str], None]]:
366
366
  """
367
367
  Create the healpix map that needs to be saved keeping
368
368
  into account if it is a probability or a llh map
369
369
  """
370
370
  if llh_map:
371
371
  column_names = ['2DLLH']
372
+ column_units = None
372
373
  else:
373
374
  # avoid excessively heavy data format for the flattened map
374
375
  equatorial_map[equatorial_map < 1e-16] = np.nanmean(
375
376
  equatorial_map[equatorial_map < 1e-16]
376
377
  )
377
- column_names = ["PROBABILITY"]
378
- return equatorial_map, column_names
378
+ column_names = ["PROB"]
379
+ column_units = ["pix-1"]
380
+ return equatorial_map, column_names, column_units
379
381
 
380
382
 
381
383
  def prepare_multiorder_map(
@@ -400,8 +402,10 @@ def prepare_multiorder_map(
400
402
  max_nside = np.max(all_nsides)
401
403
  multiorder_map = mhealpy.HealpixMap(
402
404
  grid_value / healpy.nside2pixarea(
403
- max_nside, degrees=True,
404
- ), uniq_array
405
+ max_nside, degrees=False,
406
+ ),
407
+ uniq_array,
408
+ unit="sr-1"
405
409
  )
406
- column_names = [f"{column_names[0]} DENSITY [deg-2]"]
410
+ column_names = ["PROBDENSITY"]
407
411
  return multiorder_map, column_names