def plot_plane(planecolor=0.5, coord_system='gal', plane='SGP', **kwargs): """ Plot a the supergalactic plane onto skymap. :param planecolor: color of plane :param coord_system: default galactic ('gal') / equatorial ('eq') :param plane: plots 'SGP' or 'GAL' or both (list) into plot :param kwargs: additional named keyword arguments passed to plt.plot() """ phi0 = np.linspace(0, 2 * np.pi, 100) if coord_system.upper() == 'GAL': # only plotting the SGP makes sense phi, theta = coord.vec2ang( coord.sgal2gal(coord.ang2vec(phi0, np.zeros_like(phi0)))) kwargs.setdefault('color', planecolor) plt.plot(-np.sort(phi), theta[np.argsort(phi)], **kwargs) elif coord_system.upper() == 'EQ': if 'SGP' in plane: phi, theta = coord.vec2ang( coord.gal2eq( coord.sgal2gal(coord.ang2vec(phi0, np.zeros_like(phi0))))) kwargs.setdefault('color', planecolor) plt.plot(-np.sort(phi), theta[np.argsort(phi)], **kwargs) if 'GAL' in plane: phi, theta = coord.vec2ang( coord.gal2eq(coord.ang2vec(phi0, np.zeros_like(phi0)))) kwargs.setdefault('color', '0.5') plt.plot(-np.sort(phi), theta[np.argsort(phi)], **kwargs) else: raise Exception( "plane type not understood, use GP or SGP or list!") else: raise Exception("coord system not understood, use eq or gal!")
def test_02_gal2eq(self): vec_gal = -0.5 + np.random.random((3, stat)) vec_gal /= np.sqrt(np.sum(vec_gal**2, axis=0)) vec_eq = coord.gal2eq(vec_gal) bool_eq_gal_same = np.allclose(vec_gal, vec_eq) bool_normed = np.allclose(np.sum(vec_eq**2, axis=0), np.ones(stat)) self.assertTrue(bool_normed and not bool_eq_gal_same)
def test_20_exposure_issue(self): sim = ObservedBound(nside=4, nsets=nsets, ncrs=ncrs) sim.apply_exposure(a0=-35.25, zmax=60) sim.arrival_setup(0.) crs = sim.get_data(convert_all=True) _, dec = coord.vec2ang(coord.gal2eq(crs['vecs'].reshape(3, -1))) self.assertTrue(np.sum(coord.exposure_equatorial(dec, a0=-35.25, zmax=60) <= 0) == 0)
def sensitivity_2pt(self, set_idx=None, niso=1000, bins=180, **kwargs): """ Function to calculate the sensitivity by the 2pt-auto-correlation over a scrambling of the right ascension coordinates. :param set_idx: If set, only this set number will be evaluated :param niso: Number of isotropic sets to calculate :param bins: Number of angular bins, 180 correspond to 1 degree binning (np.linspace(0, np.pi, bins+1). :param kwargs: additional named arguments passed to obs.two_pt_auto() :return: pvalues in the shape (self.nsets, bins) """ kwargs.setdefault('cumulative', True) vec_crs = self.get('vecs') _, dec = coord.vec2ang(coord.gal2eq(np.reshape(vec_crs, (3, -1)))) # calculate auto correlation for isotropic scrambled data _ac_iso = np.zeros((niso, bins)) for i in range(niso): _vecs = coord.ang2vec(coord.rand_phi(self.ncrs), np.random.choice(dec, size=self.ncrs)) _ac_iso[i] = obs.two_pt_auto(_vecs, bins, **kwargs) # calculate p-value by comparing the true sets with the isotropic ones set_idx = np.arange(self.nsets) if set_idx is None else [set_idx] pvals = np.zeros((len(set_idx), bins)) for i, idx in enumerate(set_idx): _ac_crs = obs.two_pt_auto(vec_crs[:, idx], bins, **kwargs) pvals[i] = np.sum(_ac_iso >= _ac_crs[np.newaxis], axis=0) / float(niso) return pvals
def test_09_exposure(self): sim = ObservedBound(self.nside, self.nsets, self.ncrs) sim.apply_exposure() sim.arrival_setup(0.) crs = sim.get_data(convert_all=True) vecs_eq = coord.gal2eq(coord.ang2vec(np.hstack(crs['lon']), np.hstack(crs['lat']))) lon_eq, lat_eq = coord.vec2ang(vecs_eq) self.assertTrue(np.abs(np.mean(lon_eq)) < 0.05) self.assertTrue((np.mean(lat_eq) < -0.5) & (np.mean(lat_eq) > - 0.55))
def test_15_exposure(self): nsets = 100 sim = ObservedBound(self.nside, nsets, self.ncrs) sim.apply_exposure(a0=-35.25, zmax=60) sim.arrival_setup(0.2) crs = sim.get_data(convert_all=True) lon, lat = np.hstack(crs['lon']), np.hstack(crs['lat']) ra, dec = coord.vec2ang(coord.gal2eq(coord.ang2vec(lon, lat))) exp = coord.exposure_equatorial(dec, a0=-35.25, zmax=60) self.assertTrue((exp > 0).all())
def test_11_test_vecs_galactic(self): lon, lat = coord.rand_phi(stat), coord.rand_theta(stat) v = coord.ang2vec(lon, lat) self.assertTrue( np.allclose(lon, coord.get_longitude(v, coord_system='gal'))) self.assertTrue( np.allclose(lat, coord.get_latitude(v, coord_system='gal'))) v_eq = coord.gal2eq(v) self.assertTrue( np.allclose(lon, coord.get_longitude(v_eq, coord_system='eq'))) self.assertTrue( np.allclose(lat, coord.get_latitude(v_eq, coord_system='eq')))
def test_05_inariant_rotation(self): ac = obs.two_pt_auto(self.vecs, bins=self.nbins, cumulative=True, normalized=True) vecs_rotated = coord.gal2eq(self.vecs) self.assertTrue(np.mean(coord.angle(self.vecs, vecs_rotated)) > 0.1) ac_rotated = obs.two_pt_auto(vecs_rotated, bins=self.nbins, cumulative=True, normalized=True) self.assertTrue(np.allclose(ac, ac_rotated))
def test_06_scrambling(self): n = 5 vecs = coord.rand_exposure_vec(a0=-45, zmax=45, n=stat, coord_system='gal') ra, dec = coord.vec2ang(coord.gal2eq(vecs)) vecs_new = coord.equatorial_scrambling(vecs, n, coord_system='gal') self.assertTrue(vecs_new.shape == (3, n, stat)) for i in range(n): ra_s, dec_s = coord.vec2ang(coord.gal2eq(vecs_new[:, i])) self.assertTrue(np.allclose(dec, dec_s)) self.assertTrue(not np.allclose(ra, ra_s)) vecs = coord.rand_exposure_vec(a0=-80, zmax=60, n=stat, coord_system='eq') ra, dec = coord.vec2ang(vecs) vecs_new = coord.equatorial_scrambling(vecs, n, coord_system='eq') for i in range(n): ra_s, dec_s = coord.vec2ang(vecs_new[:, i]) self.assertTrue(np.allclose(dec, dec_s)) self.assertTrue(not np.allclose(ra, ra_s))
def sensitivity_2pt(self, niso=1000, bins=180, **kwargs): """ Function to calculate the sensitivity by the 2pt-auto-correlation over a scrambling of the right ascension coordinates. :param niso: Number of isotropic sets to calculate. :param bins: Number of angular bins, 180 correspond to 1 degree binning (np.linspace(0, np.pi, bins+1). :param kwargs: additional named arguments passed to obs.two_pt_auto() :return: pvalues in the shape (bins) """ kwargs.setdefault('cumulative', True) vec_crs = self.get('vecs') _, dec = coord.vec2ang(coord.gal2eq(vec_crs)) # calculate auto correlation for isotropic scrambled data _ac_iso = np.zeros((niso, bins)) for i in range(niso): _vecs = coord.ang2vec(coord.rand_phi(self.ncrs), dec) _ac_iso[i] = obs.two_pt_auto(_vecs, bins, **kwargs) # calculate p-value by comparing the true sets with the isotropic ones _ac_crs = obs.two_pt_auto(vec_crs, bins, **kwargs) pvals = np.sum(_ac_iso >= _ac_crs[np.newaxis], axis=0) / float(niso) return pvals
def scatter(v, c=None, cblabel='log$_{10}$(Energy / eV)', opath=None, fig=None, **kwargs): """ Scatter plot of events with arrival directions x,y,z and colorcoded energies. :param v: array of shape (3, n) pointing into directions of the events :param c: quantity that is supposed to occur in colorbar, e.g. energy of the cosmic rays :param cblabel: colorbar label :param opath: if not None, saves the figure to the given opath (no returns) :param fig: figure to plot in, creates new figure if None :param kwargs: additional named keyword arguments - figsize: figure size as input for plt.figure() - cmap: colormap - cbar: if True includes a colobar - cticks: sets ticks of colormap - mask_alpha: alpha value for maskcolor - fontsize: scale the general fontsize - dark_grid: if True paints a dark grid (useful for bright maps) - gridcolor: Color of the grid. - gridalpha: Transparency value of the gridcolor. - tickcolor: Color of the ticks. - tickalpha: Transparency of the longitude ticks. - plane: plots 'SGP' or 'GP' or both (list) into plot - planecolor: color of plane - coord_system: default galactic ('gal') / equatorial ('eq') :return: figure, axis of the scatter plot """ lons, lats = coord.vec2ang(v) fontsize = kwargs.pop('fontsize', 26) kwargs.setdefault('s', 8) if 'marker' not in kwargs: kwargs.setdefault('lw', 0) cbar = kwargs.pop('cbar', True) and isinstance(c, (list, tuple, np.ndarray)) if cbar: vmin = kwargs.pop( 'vmin', smart_round(np.min(c[np.isfinite(c)]), upper_border=False)) vmax = kwargs.pop( 'vmax', smart_round(np.max(c[np.isfinite(c)]), upper_border=True)) step = smart_round((vmax - vmin) / 5., order=1) cticks = kwargs.pop( 'cticks', np.round(np.arange(vmin, vmax, step), int(np.round(-np.log10(step), 0)))) clabels = kwargs.pop('clabels', cticks) # read keyword arguments for the grid dark_grid = kwargs.pop('dark_grid', True) gridcolor = kwargs.pop('gridcolor', 'lightgray' if dark_grid is None else 'black') gridalpha = kwargs.pop('gridalpha', 0.5 if dark_grid is None else 0.4) tickcolor = kwargs.pop('tickcolor', 'lightgray' if dark_grid is None else 'black') tickalpha = kwargs.pop('tickalpha', 0.5 if dark_grid is None else 1) planecolor = kwargs.pop('planecolor', 'darkgray') plane = kwargs.pop('plane', None) coord_system = kwargs.pop('coord_system', 'gal') if coord_system == 'eq': lons, lats = coord.vec2ang(coord.gal2eq(coord.ang2vec(lons, lats))) # mimic astronomy convention: positive longitudes evolving to the left with respect to GC lons = -lons # plot the events fig = plt.figure( figsize=kwargs.pop('figsize', [12, 6])) if fig is None else fig ax = fig.add_axes([0.1, 0.1, 0.85, 0.9], projection="hammer") events = ax.scatter(lons, lats, c=c, **kwargs) if cbar: cbar = plt.colorbar(events, orientation='horizontal', shrink=0.85, pad=0.05, aspect=30, ticks=cticks) cbar.set_label(cblabel, fontsize=fontsize) events.set_clim(vmin, vmax) cbar.ax.tick_params(labelsize=fontsize - 4) cbar.set_ticklabels(clabels) cbar.draw_all() # Setup the grid plt.xticks(fontsize=fontsize) plt.yticks(fontsize=fontsize) plot_grid(gridcolor=gridcolor, gridalpha=gridalpha, tickalpha=tickalpha, tickcolor=tickcolor, fontsize=fontsize) if plane is not None: plot_plane(planecolor, coord_system, plane) if opath is not None: plt.savefig(opath, bbox_inches='tight') plt.clf() return fig, ax