def _makePixelRanges(): """Generate pixel ID ranges for some envelope region""" pointing_v = UnitVector3d(1., 1., -1.) fov = 0.05 # radians region = Circle(pointing_v, Angle(fov / 2)) pixelator = HtmPixelization(HTM_LEVEL) indices = pixelator.envelope(region, 128) return indices.ranges()
def test_index_to_string(self): strings = ['S0', 'S1', 'S2', 'S3', 'N0', 'N1', 'N2', 'N3'] for i in range(8, 16): s0 = strings[i - 8] self.assertEqual(HtmPixelization.asString(i), s0) self.assertEqual(HtmPixelization(0).toString(i), s0) for j in range(4): s1 = s0 + str(j) self.assertEqual(HtmPixelization.asString(i * 4 + j), s1) self.assertEqual(HtmPixelization(1).asString(i * 4 + j), s1)
def _makeDiaObjects(self, sources, indices, dt): """Over-simplified implementation of source-to-object matching and new DiaObject generation. Currently matching is based on info passed along by source generator and does not even use DiaObjects from database. Parameters ---------- sources : `numpy.array` (x, y, z) coordinates of sources, array dimension is (N, 3) indices : `numpy.array` array of indices of sources, 1-dim ndarray, transient sources have negative indices dt : `datetime.datetime` Visit time. Returns ------- `afw.table.BaseCatalog` """ schema = self._makeDiaObjectSchema() catalog = afwTable.SourceCatalog(schema) n_trans = 0 for i in range(len(sources)): var_idx = int(indices[i]) if var_idx == _OUTSIDER: continue xyz = sources[i] if var_idx >= _TRANSIENT_START_ID: n_trans += 1 v3d = Vector3d(xyz[0], xyz[1], xyz[2]) sp = SpherePoint(v3d) dir_v = UnitVector3d(v3d) pixelator = HtmPixelization(self.config.htm_level) index = pixelator.index(dir_v) record = catalog.addNew() record.set("id", var_idx) # record.set("validityStart", _utc_seconds(dt)) # record.set("validityEnd", 0) # record.set("lastNonForcedSource", _utc_seconds(dt)) record.set("coord_ra", sp.getRa()) record.set("coord_dec", sp.getDec()) record.set("pixelId", index) _LOG.info('found %s matching objects and %s transients/noise', len(catalog) - n_trans, n_trans) return catalog
def _makeDiaSources(self, sources, indices, visit_id): """Generate catalog of DiaSources to store in a database Parameters ---------- sources : `numpy.ndarray` (x, y, z) coordinates of sources, array dimension is (N, 3) indices : `numpy.array` array of indices of sources, 1-dim ndarray, transient sources have negative indices visit_id : `int` ID of the visit Returns ------- `afw.table.BaseCatalog` """ schema = self._makeDiaSourceSchema() catalog = afwTable.BaseCatalog(schema) for i in range(len(sources)): var_idx = int(indices[i]) if var_idx == _OUTSIDER: continue xyz = sources[i] v3d = Vector3d(xyz[0], xyz[1], xyz[2]) sp = SpherePoint(v3d) dir_v = UnitVector3d(v3d) pixelator = HtmPixelization(self.config.htm_level) index = pixelator.index(dir_v) self.lastSourceId += 1 record = catalog.addNew() record.set("id", self.lastSourceId) record.set("ccdVisitId", visit_id) record.set("diaObjectId", var_idx) record.set("parent", 0) record.set("coord_ra", sp.getRa()) record.set("coord_dec", sp.getDec()) record.set("flags", 0) record.set("pixelId", index) return catalog
def _htm_indices(self, region): """Generate a set of HTM indices covering specified field of view. Parameters ---------- region: `sphgeom.Region` Region that needs to be indexed Returns ------- Sequence of ranges, range is a tuple (minHtmID, maxHtmID). """ _LOG.debug('region: %s', region) pixelator = HtmPixelization(self.config.htm_level) indices = pixelator.envelope(region, self.config.htm_max_ranges) for irange in indices.ranges(): _LOG.debug('range: %s %s', pixelator.toString(irange[0]), pixelator.toString(irange[1])) return indices.ranges()
def test_construction(self): with self.assertRaises(ValueError): HtmPixelization(-1) with self.assertRaises(ValueError): HtmPixelization(HtmPixelization.MAX_LEVEL + 1) h1 = HtmPixelization(0) self.assertEqual(h1.getLevel(), 0) h2 = HtmPixelization(1) h3 = HtmPixelization(h2) self.assertNotEqual(h1, h2) self.assertEqual(h2, h3)
def test_envelope_and_interior(self): pixelization = HtmPixelization(3) c = Circle(UnitVector3d(1, 1, 1), Angle.fromDegrees(0.1)) rs = pixelization.envelope(c) self.assertTrue(rs == RangeSet(0x3ff)) rs = pixelization.envelope(c, 1) self.assertTrue(rs == RangeSet(0x3ff)) self.assertTrue(rs.isWithin(pixelization.universe())) rs = pixelization.interior(c) self.assertTrue(rs.empty())
def test_pickle(self): a = HtmPixelization(20) b = pickle.loads(pickle.dumps(a)) self.assertEqual(a, b)
def test_string(self): p = HtmPixelization(3) self.assertEqual(str(p), 'HtmPixelization(3)') self.assertEqual(str(p), repr(p)) self.assertEqual(p, eval(repr(p), dict(HtmPixelization=HtmPixelization)))
def test_level(self): for index in (0, 16 * 4**HtmPixelization.MAX_LEVEL): self.assertEqual(HtmPixelization.level(index), -1) for level in range(HtmPixelization.MAX_LEVEL + 1): for root in range(8, 16): self.assertEqual(HtmPixelization.level(root * 4**level), level)
def test_pixel(self): h = HtmPixelization(1) self.assertIsInstance(h.pixel(10), ConvexPolygon)
def test_indexing(self): h = HtmPixelization(1) self.assertEqual(h.index(UnitVector3d(1, 1, 1)), 63)
def main(): descr = 'Quick and dirty simulation of sky partitioning and CCD overlaps.' parser = ArgumentParser(description=descr) parser.add_argument('-v', '--verbose', action='count', default=0, help='More verbose output, can use several times.') parser.add_argument('-m', '--mode', default='htm', choices=["htm", "q3c", "mq3c"], help='Partitioning mode, def: %(default)s') parser.add_argument('--level', type=int, default=8, help='Pixelization level, def: %(default)s') parser.add_argument('-n', '--counts', type=int, default=1000, help='Number of visits, def: %(default)s') parser.add_argument('--pixels-per-tile', default=None, help='Output file name for pixels-per-tile') parser.add_argument('--tiles-per-pixel', default=None, help='Output file name for pixels-per-tile') args = parser.parse_args() # configure logging _configLogger(args.verbose) if args.mode == 'htm': pixelator = HtmPixelization(args.level) lvlchk = pixelator.level poly = pixelator.triangle elif args.mode == 'q3c': pixelator = Q3cPixelization(args.level) lvlchk = None poly = pixelator.quad elif args.mode == 'mq3c': pixelator = Mq3cPixelization(args.level) lvlchk = pixelator.level poly = pixelator.quad pixels_per_tile = [] area_per_tile = [] tiles_per_pixel = [] for i in range(args.counts): pointing_xyz = generators.rand_sphere_xyz(1, -1)[0] pointing_v = UnitVector3d(pointing_xyz[0], pointing_xyz[1], pointing_xyz[2]) rot_ang = random.uniform(0., 2*math.pi) tiles = geom.make_square_tiles(FOV_rad, 15, 15, pointing_v, rot_rad=rot_ang) # for each tile find all pixels that overlap it pixel_tiles = dict() for ix, iy, tile in tiles: ranges = pixelator.envelope(tile, 1000000) tile_pixels = 0 tile_area = 0. for i0, i1 in ranges: for pixId in range(i0, i1): if lvlchk is not None and lvlchk(pixId) != args.level: logging.warning("tile %dx%d not fully pixelized: %d-%d", ix, iy, i0, i1) else: tile_pixels += 1 pixel_tiles.setdefault(pixId, 0) pixel_tiles[pixId] += 1 if poly: tile_area += geom.poly_area(poly(pixId)) * (180/math.pi)**2 pixels_per_tile.append(tile_pixels) area_per_tile.append(tile_area) for count in pixel_tiles.values(): tiles_per_pixel.append(count) avg_area = sum(area_per_tile) / len(area_per_tile) print("pixels_per_tile: {:.2f}".format(sum(pixels_per_tile)/len(pixels_per_tile))) print("area_per_tile: {:.6f} deg^2".format(avg_area)) print("tiles_per_pixel: {:.2f}".format(sum(tiles_per_pixel)/len(tiles_per_pixel))) if args.pixels_per_tile: with open(args.pixels_per_tile, 'w') as f: print("pixels,area_deg_sq", file=f) for pix, area in zip(pixels_per_tile, area_per_tile): print(f"{pix},{area}", file=f) if args.tiles_per_pixel: with open(args.tiles_per_pixel, 'w') as f: print("tiles", file=f) for num in tiles_per_pixel: print(num, file=f)
def getDatasetHandle(self, parq): df = parq._df lo, hi = HtmPixelization(7).universe().ranges()[0] value = np.random.randint(lo, hi) ref = self.butler.put(df, self.datasetType, dataId={'htm7': value}) return self.butler.getDeferred(ref)
def test_yaml(self): a = HtmPixelization(20) b = yaml.safe_load(yaml.dump(a)) self.assertEqual(a, b)