def test_moc_contains(): order = 4 size = 20 healpix_arr = np.random.randint(0, 12 * 4**order, size) all_healpix_arr = np.arange(12 * 4**order) healpix_outside_arr = np.setdiff1d(all_healpix_arr, healpix_arr) moc = MOC.from_json(json_moc={str(order): list(healpix_arr)}) #viz = Vizier(columns=['*', '_RAJ2000', '_DEJ2000']) #viz.ROW_LIMIT = -1 #table = viz.get_catalogs('I/293/npm2cros')[0] hp = HEALPix(nside=(1 << order), order='nested', frame=ICRS()) lon, lat = hp.healpix_to_lonlat(healpix_arr) lon_out, lat_out = hp.healpix_to_lonlat(healpix_outside_arr) should_be_inside_arr = moc.contains(ra=lon, dec=lat) assert should_be_inside_arr.all() should_be_outside_arr = moc.contains(ra=lon_out, dec=lat_out) assert not should_be_outside_arr.any() # test keep_inside field should_be_outside_arr = moc.contains(ra=lon, dec=lat, keep_inside=False) assert not should_be_outside_arr.any() should_be_inside_arr = moc.contains(ra=lon_out, dec=lat_out, keep_inside=False) assert should_be_inside_arr.all()
def DarkMap(self, nside, whichprofile, rs, rb, gamma, xmax, dx): #bvalues, lvalues, pixarea = self.toGcoordinate(nside) pixarea = hp.nside2pixarea(nside) npix = hp.nside2npix(nside) HP = HEALPix(nside=nside, order='ring') theta, phi = hp.pix2ang(nside, range(npix)) bvalues = np.array( [HP.healpix_to_lonlat([i])[1][0].value for i in range(len(theta))]) lvalues = np.array( [HP.healpix_to_lonlat([i])[0][0].value for i in range(len(phi))]) mappa_ary = np.array([ self.integratedDM(whichprofile, rs, rb, gamma, bvalues[p], lvalues[p], xmax, dx) for p in range(npix) ]) # Multiply by area of pixel to add sr unit mappa_ary *= pixarea return hp.ud_grade( np.array(mappa_ary), 128, power=-2 ) # See https://healpy.readthedocs.io/en/latest/generated/healpy.pixelfunc.ud_grade.html
def decomposition_IT20(sp_mass, sp_am_unit_vector): """ Perform disc/spheroid decomposition of simulated galaxies based on the method introduced in Irodotou and Thomas 2020 (hereafter IT20) (https://ui.adsabs.harvard.edu/abs/2020arXiv200908483I/abstract). This function takes as arguments the mass and angular momentum of stellar particles and returns two masks that contain disc and spheroid particles and the disc-to-total stellar mass ratio of the galaxy. # Step (i) in Section 2.2 Decomposition of IT20 # :param sp_mass: list of stellar particles's (sp) masses. :param sp_am_unit_vector: list of stellar particles's (sp) normalised angular momenta (am) unit vectors. :return: disc_mask_IT20, spheroid_mask_IT20, disc_fraction_IT20 """ # Step (ii) in Section 2.2 Decomposition of IT20 # # Calculate the azimuth (alpha) and elevation (delta) angle of the angular momentum of all stellar particles # alpha = np.degrees(np.arctan2(sp_am_unit_vector[:, 1], sp_am_unit_vector[:, 0])) # In degrees. delta = np.degrees(np.arcsin(sp_am_unit_vector[:, 2])) # In degrees. # Step (ii) in Section 2.2 Decomposition of IT20 # # Generate the pixelisation of the angular momentum map # nside = 2 ** 4 # Define the resolution of the grid (number of divisions along the side of a base-resolution grid cell). hp = HEALPix(nside=nside) # Initialise the HEALPix pixelisation class. indices = hp.lonlat_to_healpix(alpha * u.deg, delta * u.deg) # Create a list of HEALPix indices from particles's alpha and delta. densities = np.bincount(indices, minlength=hp.npix) # Count number of data points in each HEALPix grid cell. # Step (iii) in Section 2.2 Decomposition of IT20 # # Smooth the angular momentum map with a top-hat filter of angular radius 30 degrees # smoothed_densities = np.zeros(hp.npix) # Loop over all grid cells # for i in range(hp.npix): mask = hlp.query_disc(nside, hlp.pix2vec(nside, i), np.pi / 6.0) # Do a 30 degree cone search around each grid cell. smoothed_densities[i] = np.mean(densities[mask]) # Average the densities of the ones inside and assign this value to the grid cell. # Step (iii) in Section 2.2 Decomposition of IT20 # # Find the location of the density maximum # index_densest = np.argmax(smoothed_densities) alpha_densest = (hp.healpix_to_lonlat([index_densest])[0].value + np.pi) % (2 * np.pi) - np.pi # In radians. delta_densest = (hp.healpix_to_lonlat([index_densest])[1].value + np.pi / 2) % (2 * np.pi) - np.pi / 2 # In radians. # Step (iv) in Section 2.2 Decomposition of IT20 # # Calculate the angular separation of each stellar particle from the centre of the densest grid cell # Delta_theta = np.arccos(np.sin(delta_densest) * np.sin(np.radians(delta)) + np.cos(delta_densest) * np.cos(np.radians(delta)) * np.cos( alpha_densest - np.radians(alpha))) # In radians. # Step (v) in Section 2.2 Decomposition of IT20 # # Calculate the disc mass fraction as the mass within 30 degrees from the densest grid cell # disc_mask_IT20, = np.where(Delta_theta < (np.pi / 6.0)) spheroid_mask_IT20, = np.where(Delta_theta >= (np.pi / 6.0)) disc_fraction_IT20 = np.sum(sp_mass[disc_mask_IT20]) / np.sum(sp_mass) # Step (vi) in Section 2.2 Decomposition of IT20 # # Normalise the disc fractions # chi = 0.5 * (1 - np.cos(np.pi / 6)) disc_fraction_IT20 = np.divide(1, 1 - chi) * (disc_fraction_IT20 - chi) return disc_mask_IT20, spheroid_mask_IT20, disc_fraction_IT20
def test_moc_contains(): order = 4 size = 20 healpix_arr = np.random.randint(0, 12*4**order, size) all_healpix_arr = np.arange(12*4**order) healpix_outside_arr = np.setdiff1d(all_healpix_arr, healpix_arr) moc = MOC.from_json(json_moc={str(order): list(healpix_arr)}) hp = HEALPix(nside=(1 << order), order='nested', frame=ICRS()) lon, lat = hp.healpix_to_lonlat(healpix_arr) lon_out, lat_out = hp.healpix_to_lonlat(healpix_outside_arr) should_be_inside_arr = moc.contains(ra=lon, dec=lat) assert should_be_inside_arr.all() should_be_outside_arr = moc.contains(ra=lon_out, dec=lat_out) assert not should_be_outside_arr.any() # test keep_inside field should_be_outside_arr = moc.contains(ra=lon, dec=lat, keep_inside=False) assert not should_be_outside_arr.any() should_be_inside_arr = moc.contains(ra=lon_out, dec=lat_out, keep_inside=False) assert should_be_inside_arr.all()
while True: one_point_map = draw_map(nside, albedo_mean, albedo_std, whitenoise_relative_amp, length_scale) if min(one_point_map) > 0 and max(one_point_map) < 1: break bright_spot = 1 for i in range(0, one_point_map.size): if i == bright_spot: one_point_map[i] = 1.00 else: one_point_map[i] = 0.00 # Parameters p_rotation = 1 p_orbit = 365.256363 lat, lng = map.healpix_to_lonlat([bright_spot]) w_rot = 2 * np.pi / p_rotation w_orb = 2 * np.pi / p_orbit inclination = np.pi / 2 obliquity = 0 sol_phase = 1 p_rotation = 2 * np.pi / w_rot p_orb = 2 * np.pi / w_orb times = np.linspace(start=0.0, stop=1.0, num=1400) measurement_std = 0.001 # DO NOT CHANGE THIS. phi_orb = abs(5 * (np.pi / 3) + sol_phase) phi_rot = abs(2 * np.pi - sol_phase) # NUMERIC
def image_to_healpix(data, wcs_in, coord_system_out, nside, order='bilinear', nested=False): """ Convert image in a normal WCS projection to HEALPIX format. Parameters ---------- data : `numpy.ndarray` Input data array to reproject wcs_in : `~astropy.wcs.WCS` The WCS of the input array coord_system_out : str or `~astropy.coordinates.BaseCoordinateFrame` The target coordinate system for the HEALPIX projection, as an Astropy coordinate frame or corresponding string alias (e.g. ``'icrs'`` or ``'galactic'``) order : int or str, optional The order of the interpolation (if ``mode`` is set to ``'interpolation'``). This can be either one of the following strings: * 'nearest-neighbor' * 'bilinear' * 'biquadratic' * 'bicubic' or an integer. A value of ``0`` indicates nearest neighbor interpolation. nested : bool The order of the healpix_data, either nested or ring. Stored in FITS headers in the ORDERING keyword. Returns ------- reprojected_data : `numpy.ndarray` A HEALPIX array of values footprint : `~numpy.ndarray` Footprint of the input array in the output array. Values of 0 indicate no coverage or valid values in the input image, while values of 1 indicate valid values. """ from scipy.ndimage import map_coordinates hp = HEALPix(nside=nside, order='nested' if nested else 'ring') npix = hp.npix # Look up lon, lat of pixels in output system and convert colatitude theta # and longitude phi to longitude and latitude. lon_out, lat_out = hp.healpix_to_lonlat(np.arange(npix)) lon_out = lon_out.to(u.deg).value lat_out = lat_out.to(u.deg).value # Convert between celestial coordinates coord_system_out = parse_coord_system(coord_system_out) with np.errstate(invalid='ignore'): lon_in, lat_in = convert_world_coordinates( lon_out, lat_out, (coord_system_out, u.deg, u.deg), wcs_in) # Look up pixels in input system yinds, xinds = wcs_in.wcs_world2pix(lon_in, lat_in, 0) # Interpolate if isinstance(order, six.string_types): order = ORDER[order] healpix_data = map_coordinates(data, [xinds, yinds], order=order, mode='constant', cval=np.nan) return healpix_data, (~np.isnan(healpix_data)).astype(float)
whitenoise_relative_amp, length_scale) if min(simulated_map) > 0 and max(simulated_map) < 1: break # # # simulating a map that's all black everywhere except for one bright spot # for i in range(0, simulated_map.size): if i == 100: simulated_map[i] = 1.00 else: simulated_map[i] = 0.000 hp.mollview(simulated_map, title='albedo', cmap='gist_gray') # obtaining the lon and lat of this point map = HEALPix(nside=nside, order='nested') pt_lng, pt_lat = map.healpix_to_lonlat([100]) print("lng") print(pt_lng) print("lat") print(pt_lat) # Set orbital properties p_rotation = 23.934 p_orbit = 365.256363 * 24.0 phi_orb = np.pi # inclination = np.pi/2 # obliquity = 90. * np.pi/180.0 obliquity = np.pi / 4 inclination = np.pi / 2 phi_rot = np.pi
if min(one_point_map) > 0 and max(one_point_map) <1: break bright_spot = 12 for i in range(0, one_point_map.size): if i == bright_spot: one_point_map[i] = 1.00 else: one_point_map[i] = 0.00 map = HEALPix(nside=nside, order='ring') #Inputs p_rotation = 1 p_orbit = 365.256363 times = np.linspace(start=0.0, stop=10.0, num=1400) measurement_std = 0.001 lat, lng = map.healpix_to_lonlat([bright_spot]) a = Angle((np.pi/2)*u.rad) colat = a-lat w_rot = 2*np.pi/p_rotation w_orb = 2*np.pi/p_orbit inclination = 0 obliquity = 0 sol_phase = np.pi/6 # p_rotation = 2*np.pi/w_rot # p_orb = 2*np.pi/w_orb phi_orb = abs(1*(np.pi/2) + sol_phase) # Unknown parameter 1 phi_rot = abs(1*(np.pi/2) - sol_phase) # Unknown parameter 2 # Numeric lightcurve truth = IlluminationMapPosterior(times, np.zeros_like(times), measurement_std, nside=nside)
def generate_positions( min_positions: int, mount_model: MountModel, mount: TelescopeMount, min_altitude: Angle = 0.0 * u.deg, meridian_side: Optional[MeridianSide] = None, ) -> List[Position]: """Generate a list of equally spaced positions on the sky to search. The list of positions generated will be a subset of pixels generated by the HEALPix algorithm, which is a method of pixelization of a sphere where each "pixel" has equal area. In the context of mount alignment we not so much concerned with the equal area property, but we do want positions that are roughly evenly distributed over the sphere, and HEALPix does a reasonable job of this as well. The full set of HEALPix pixels is filtered to exclude pixels that are below a minimum altitude threshold and (optionally) those that are on the opposite side of the meridian. HEALPix is oriented with the top approximately at local zenith. Since these positions are used prior to alignment the mount may not point to the actual azimuth of each coordinate but this is not important. Args: min_positions: Minimum number of positions. The actual number of positions returned may be larger than requested. min_altitude: Restrict positions to be above this altitude. meridian_side: If specified, restricts positions to only be on this side of the meridian, where meridian is defined as the great circle passing through local zenith and the mount pole. Returns: A list of Position objects to use for alignment. """ level = 0 while True: healpix = HEALPix(nside=2**level) positions = [] for i in range(healpix.npix): # interpret each HEALPix as a topocentric (AzAlt) coordinate (az, alt) = healpix.healpix_to_lonlat(i) # skip points on wrong side of mount meridian if az > 180 * u.deg: # west of meridian if meridian_side == MeridianSide.EAST: continue side = MeridianSide.WEST if az <= 180 * u.deg: # east of meridian if meridian_side == MeridianSide.WEST: continue side = MeridianSide.EAST # skip points below min altitude threshold if alt < min_altitude: continue position_topo = SkyCoord(az, alt, frame='altaz') encoder_positions = mount_model.topocentric_to_encoders( position_topo, side) positions.append( Position( encoder_positions=encoder_positions, mount=mount, )) if len(positions) >= min_positions: break # not enough positions -- try again with a higher level HEALPix level += 1 return positions
def image_to_healpix(data, wcs_in, coord_system_out, nside, order='bilinear', nested=False): """ Convert image in a normal WCS projection to HEALPIX format. Parameters ---------- data : `numpy.ndarray` Input data array to reproject wcs_in : `~astropy.wcs.WCS` The WCS of the input array coord_system_out : str or `~astropy.coordinates.BaseCoordinateFrame` The target coordinate system for the HEALPIX projection, as an Astropy coordinate frame or corresponding string alias (e.g. ``'icrs'`` or ``'galactic'``) order : int or str, optional The order of the interpolation (if ``mode`` is set to ``'interpolation'``). This can be either one of the following strings: * 'nearest-neighbor' * 'bilinear' * 'biquadratic' * 'bicubic' or an integer. A value of ``0`` indicates nearest neighbor interpolation. nested : bool The order of the healpix_data, either nested or ring. Stored in FITS headers in the ORDERING keyword. Returns ------- reprojected_data : `numpy.ndarray` A HEALPIX array of values footprint : `~numpy.ndarray` Footprint of the input array in the output array. Values of 0 indicate no coverage or valid values in the input image, while values of 1 indicate valid values. """ from scipy.ndimage import map_coordinates hp = HEALPix(nside=nside, order='nested' if nested else 'ring') npix = hp.npix # Look up lon, lat of pixels in output system and convert colatitude theta # and longitude phi to longitude and latitude. lon_out, lat_out = hp.healpix_to_lonlat(np.arange(npix)) lon_out = lon_out.to(u.deg).value lat_out = lat_out.to(u.deg).value # Convert between celestial coordinates coord_system_out = parse_coord_system(coord_system_out) with np.errstate(invalid='ignore'): lon_in, lat_in = convert_world_coordinates(lon_out, lat_out, (coord_system_out, u.deg, u.deg), wcs_in) # Look up pixels in input system yinds, xinds = wcs_in.wcs_world2pix(lon_in, lat_in, 0) # Interpolate if isinstance(order, six.string_types): order = ORDER[order] healpix_data = map_coordinates(data, [xinds, yinds], order=order, mode='constant', cval=np.nan) return healpix_data, (~np.isnan(healpix_data)).astype(float)