def __init__(self, geo_in, mask_in, C, zs, z_fine): """geo_in,mask_in: Geo objects""" self.geo_in = geo_in self.mask_in = mask_in assert (self.geo_in.angular_area() - self.mask_in.angular_area()) >= 0. Geo.__init__(self, zs, C, z_fine) l_max = np.min([geo_in._l_max, mask_in._l_max]) self.expand_alm_table(l_max)
def __init__(self, geo_in, C, zs, z_fine, angles, n_double): """geo_in Geo object""" self.geo_in = geo_in self.angles = angles self.n_double = n_double Geo.__init__(self, zs, C, z_fine) l_max = geo_in._l_max self.expand_alm_table(l_max)
def __init__(self, zs, C, z_fine): """create an analytic geo of the full sky inputs: zs: the tomographic z bins C: a CosmoPie object z_fine: the resolution z slices l_max: the maximum l to compute the alm table to res_healpix: 4 to 9, healpix resolution to use """ self.C = C self.z_fine = z_fine Geo.__init__(self, zs, C, z_fine)
def __init__(self,zs,pixels,C,z_fine,l_max,hard_l_max=np.inf): """pixelated geomtery inputs: zs: tomographic z bins pixels: pixels in format np.array([(theta,phi,area)]), area in steradians C: CosmoPie object z_fine: the fine z slices hard_l_max: absolute maximum possible l to resolve """ self.pixels = pixels self.hard_l_max = hard_l_max Geo.__init__(self,zs,C,z_fine) self._l_max = 0 self.alm_table[(0,0)] = np.sum(self.pixels[:,2])/np.sqrt(4.*np.pi) self.expand_alm_table(l_max)
def __init__(self, zs, thetas, phis, theta_in, phi_in, C, z_fine, l_max, poly_params): """ inputs: zs: the tomographic z bins thetas,phis: an array of theta values for the edges in radians, last value should be first for closure, edges will be clockwise theta_in,phi_in: a theta and phi known to be outside, needed for finding intersect for now C: a CosmoPie object z_fine: the resolution z slices l_max: the maximum l to compute the alm table to poly_params: a dict of parameters """ self.poly_params = poly_params self.n_double = poly_params['n_double'] self.l_max = l_max #maximum alm already available, only a00 available at start self._l_max = 0 self.n_v = thetas.size - 1 self.bounding_theta = thetas - np.pi / 2. #to radec self.bounding_phi = np.pi - phis self.bounding_xyz = np.asarray( sgv.radec_to_vector(self.bounding_phi, self.bounding_theta, degrees=False)).T self.theta_in = theta_in self.phi_in = phi_in self.thetas_orig = thetas self.phis_orig = phis #this gets correct internal angles with specified vertex order (copied from spherical_polygon clas) angle_body = gca.angle(self.bounding_xyz[:-2], self.bounding_xyz[1:-1], self.bounding_xyz[2:], degrees=False) angle_end = gca.angle(self.bounding_xyz[-2], self.bounding_xyz[0], self.bounding_xyz[1], degrees=False) self.internal_angles = 2. * np.pi - np.hstack([angle_body, angle_end]) Geo.__init__(self, zs, C, z_fine) self.sp_poly = get_poly(thetas, phis, theta_in, phi_in) print("PolygonGeo: area calculated by SphericalPolygon: " + str(self.sp_poly.area())) print("PolygonGeo: area calculated by PolygonGeo: " + str(self.angular_area()) + " sr or " + str(self.angular_area() * (180. / np.pi)**2) + " deg^2") self.alm_table = {(0, 0): self.angular_area() / np.sqrt(4. * np.pi)} self.z_hats = np.zeros((self.n_v, 3)) self.y_hats = np.zeros_like(self.z_hats) self.xps = np.zeros_like(self.z_hats) self.betas = np.zeros(self.n_v) self.theta_alphas = np.zeros(self.n_v) self.omega_alphas = np.zeros(self.n_v) self.gamma_alphas = np.zeros(self.n_v) for itr1 in range(0, self.n_v): itr2 = itr1 + 1 pa1 = self.bounding_xyz[itr1] #vertex 1 pa2 = self.bounding_xyz[itr2] #vertex 2 cos_beta12 = np.dot(pa2, pa1) #cos of angle between pa1 and pa2 cross_12 = np.cross(pa2, pa1) sin_beta12 = np.linalg.norm(cross_12) #magnitude of cross product self.betas[itr1] = np.arctan2( sin_beta12, cos_beta12) #angle between pa1 and pa2 #angle should be in quadrant expected by arccos because angle should be <pi beta_alt = np.arccos(cos_beta12) assert np.isclose(sin_beta12, np.sin(self.betas[itr1])) assert np.isclose(sin_beta12**2 + cos_beta12**2, 1.) assert np.isclose(beta_alt, self.betas[itr1]) #define z_hat if possible if np.isclose(self.betas[itr1], 0.): print( "PolygonGeo: side length 0, directions unconstrained, picking directions arbitrarily" ) #z_hat is not uniquely defined here so arbitrarily pick one orthogonal to pa1 arbitrary = np.zeros(3) if not np.isclose(np.abs(pa1[0]), 1.): arbitrary[0] = 1. elif not np.isclose(np.abs(pa1[1]), 1.): arbitrary[1] = 1. else: arbitrary[2] = 1. cross_12 = np.cross(arbitrary, pa1) self.z_hats[itr1] = cross_12 / np.linalg.norm(cross_12) elif np.isclose(self.betas[itr1], np.pi): raise RuntimeError( "PolygonGeo: Spherical polygons with sides of length pi are not uniquely determined" ) else: self.z_hats[ itr1] = cross_12 / sin_beta12 #direction of cross product #three euler rotation angles if not (np.isclose(self.z_hats[itr1, 1], 0.) and np.isclose(self.z_hats[itr1, 0], 0.)): self.theta_alphas[itr1] = -np.arccos(self.z_hats[itr1, 2]) y1 = np.cross(self.z_hats[itr1], pa1) self.y_hats[itr1] = y1 assert np.allclose( pa1 * np.cos(self.betas[itr1]) - y1 * np.sin(self.betas[itr1]), pa2) assert np.allclose(np.cross(pa1, y1), self.z_hats[itr1]) self.xps[itr1] = np.array([ self.z_hats[itr1][1] * pa1[0] - self.z_hats[itr1][0] * pa1[1], self.z_hats[itr1][1] * y1[0] - self.z_hats[itr1][0] * y1[1], 0. ]) self.gamma_alphas[itr1] = np.arctan2(-self.z_hats[itr1, 0], self.z_hats[itr1, 1]) gamma_alpha2 = np.arctan2(self.z_hats[itr1, 1], self.z_hats[itr1, 0]) - np.pi / 2. assert np.isclose(np.mod(self.gamma_alphas[itr1] + 0.000001, 2. * np.pi), np.mod(gamma_alpha2 + 0.000001, 2. * np.pi), atol=1.e-5) self.omega_alphas[itr1] = -np.arctan2(self.xps[itr1, 1], self.xps[itr1, 0]) else: self.omega_alphas[itr1] = 0. self.gamma_alphas[itr1] = np.arctan2(pa1[1], pa1[0]) #need to handle the case where z||z_hat separately (so don't divide by 0) if self.z_hats[itr1, 2] < 0: print("PolygonGeo: setting theta_alpha to pi at " + str(itr1)) self.theta_alphas[itr1] = np.pi else: print("PolygonGeo: setting theta_alpha to 0 at " + str(itr1)) self.theta_alphas[itr1] = 0. self.expand_alm_table(l_max) print("PolygonGeo: finished initialization")
def __init__(self, geos, masks, C=None, zs=None, z_fine=None, l_max=None, poly_params=None): """geo,masks: an array of PolygonGeo objects""" self.geos = geos self.masks = masks self.n_g = geos.size self.n_m = masks.size if zs is None: zs = geos[0].zs if z_fine is None: z_fine = geos[0].z_fine if C is None: C = geos[0].C if l_max is None: l_max = geos[0].l_max if poly_params is None: poly_params = geos[0].poly_params self.polys_pos = np.zeros(self.n_g, dtype=object) self.polys_mask = np.zeros(self.n_m, dtype=object) for itr in range(0, self.masks.size): if not isinstance(masks[itr], PolygonGeo): raise ValueError('unsupported type for mask') print(masks[itr].angular_area()) for itr in range(0, self.geos.size): if not isinstance(geos[itr], PolygonGeo): raise ValueError('unsupported type for geo') print(geos[itr].angular_area()) for itr in range(0, self.masks.size): self.polys_mask[itr] = masks[itr].sp_poly self.union_pos = self.geos[0].sp_poly for itr in range(1, self.n_g): self.union_pos = self.union_pos.union(self.polys_pos[itr]) self.union_xyz = list(self.union_pos.points) self.union_in = list(self.union_pos.inside) self.n_union = len(self.union_xyz) self.union_geos = np.zeros(self.n_union, dtype=object) if self.n_g == 1: self.union_geos[0] = self.geos[0] else: for itr in range(0, self.n_union): union_ra, union_dec = sgv.vector_to_radec( self.union_xyz[itr][:, 0], self.union_xyz[itr][:, 1], self.union_xyz[itr][:, 2], degrees=False) in_ra, in_dec = sgv.vector_to_radec(self.union_in[itr][0], self.union_in[itr][1], self.union_in[itr][2], degrees=False) self.union_geos[itr] = PolygonGeo(zs, union_dec + np.pi / 2., union_ra, in_dec + np.pi / 2., in_ra, C, z_fine, l_max, poly_params) if self.n_m > 0: #get union of all the masks with the union of the inside, ie the intersection, which is the mask to use self.union_mask = self.polys_mask[0] for itr1 in range(1, self.n_m): self.union_mask = self.union_mask.union(self.polys_mask[itr1]) #note union_mask can be several disjoint polygons #print("mask poly",self.union_mask) #print("union pos",self.union_pos) self.union_mask = self.union_pos.intersection(self.union_mask) self.mask_xyz = list(self.union_mask.points) in_point = list(self.union_mask.inside) self.n_mask = len(self.mask_xyz) self.mask_geos = np.zeros(self.n_mask, dtype=object) for itr in range(0, self.n_mask): mask_ra, mask_dec = sgv.vector_to_radec(self.mask_xyz[itr][:, 0], self.mask_xyz[itr][:, 1], self.mask_xyz[itr][:, 2], degrees=False) in_ra, in_dec = sgv.vector_to_radec(in_point[itr][0], in_point[itr][1], in_point[itr][2], degrees=False) self.mask_geos[itr] = PolygonGeo(zs, mask_dec + np.pi / 2., mask_ra, in_dec + np.pi / 2., in_ra, C, z_fine, l_max, poly_params) else: #TODO not right self.union_mask = None self.mask_geos = None #self.sp_poly = self.union_geo Geo.__init__(self, zs, C, z_fine) self.alm_table = {(0, 0): self.angular_area() / np.sqrt(4. * np.pi)} self._l_max = 0 self.expand_alm_table(l_max)