Ejemplo n.º 1
0
 def testCodec(self):
     p = ConvexPolygon(
         [UnitVector3d.Z(),
          UnitVector3d.X(),
          UnitVector3d.Y()])
     s = p.encode()
     self.assertEqual(ConvexPolygon.decode(s), p)
     self.assertEqual(Region.decode(s), p)
Ejemplo n.º 2
0
def find_intersecting_exposures(database, region):
    """Find exposures that intersect a spherical region.

    Parameters
    ----------

    database : sqlite3.Connection or str
        A connection to (or filename of) a SQLite 3 database containing
        an exposure index.

    region : lsst.sphgeom.Region
        The spherical region of interest.

    Returns
    -------

        A list of :class:`.ExposureInfo` objects corresponding to the
        exposures intersecting `region`.  Their ``data_id`` attributes
        are data-id objects that can be passed to a butler to retrieve
        the corresponding exposure, and their ``boundary`` attributes
        are |polygon| objects.
    """
    if isinstance(database, sqlite3.Connection):
        conn = database
    else:
        conn = sqlite3.connect(database)
    query = ("SELECT pickled_data_id, encoded_polygon\n"
             "FROM exposure JOIN exposure_rtree USING (rowid)\n"
             "WHERE x_min < ? AND x_max > ? AND\n"
             "      y_min < ? AND y_max > ? AND\n"
             "      z_min < ? AND z_max > ?")
    bbox = region.getBoundingBox3d()
    params = (bbox.x().getB(), bbox.x().getA(),
              bbox.y().getB(), bbox.y().getA(),
              bbox.z().getB(), bbox.z().getA())
    results = []
    for row in conn.execute(query, params):
        # Note that in Python 2, BLOB columns are mapped to Python buffer
        # objects, and so a conversion to str is necessary. In Python 3,
        # BLOBs are mapped to bytes directly, and the str() calls must
        # be removed.
        poly = ConvexPolygon.decode(str(row[1]))
        if region.relate(poly) != DISJOINT:
            results.append(ExposureInfo(pickle.loads(str(row[0])), poly))
    return results
Ejemplo n.º 3
0
 def process_result_value(self, value, dialect):
     if value is None:
         return None
     return ConvexPolygon.decode(super().process_result_value(
         value, dialect))
 def testCodec(self):
     p = ConvexPolygon([UnitVector3d.Z(), UnitVector3d.X(), UnitVector3d.Y()])
     s = p.encode()
     self.assertEqual(ConvexPolygon.decode(s), p)
     self.assertEqual(ConvexPolygon.cast(Region.decode(s)), p)
Ejemplo n.º 5
0
def store_exposure_info(database, allow_replace, exposure_info):
    """Store exposure data-ids and bounding polygons in the given database.

    The database is assumed to have been initialized via
    :func:`.create_exposure_tables`.

    Parameters
    ----------

    database : sqlite3.Connection or str
        A connection to (or filename of) a SQLite 3 database.

    allow_replace : bool
        If ``True``, information for previously stored exposures with matching
        data-ids will be overwritten.

    exposure_info : iterable or lsst.daf.ingest.indexExposure.ExposureInfo
        One or more :class:`.ExposureInfo` objects to persist. Their
        ``data_id`` attributes must be pickled data-ids, and their
        ``boundary`` attributes must be |encoded| |polygon| objects.
    """
    if isinstance(database, sqlite3.Connection):
        conn = database
    else:
        conn = sqlite3.connect(database)
    with conn:
        cursor = conn.cursor()
        if isinstance(exposure_info, ExposureInfo):
            exposure_info = (exposure_info,)
        # Insert or update information in database
        for info in exposure_info:
            if info is None:
                continue
            # In Python 2, the sqlite3 module maps between Python buffer
            # objects and BLOBs. When migrating to Python 3, the buffer()
            # calls should be removed (sqlite3 maps bytes objects to BLOBs).
            pickled_data_id = buffer(info.data_id)
            encoded_polygon = buffer(info.boundary)
            bbox = ConvexPolygon.decode(info.boundary).getBoundingBox3d()
            if allow_replace:
                # See if there is already an entry for the given data id.
                cursor.execute(
                    'SELECT rowid FROM exposure WHERE pickled_data_id = ?',
                    (pickled_data_id,)
                )
                results = cursor.fetchall()
                if len(results) > 0:
                    # If so, update spatial information for the exposure.
                    row_id = results[0][0]
                    cursor.execute(
                        'UPDATE exposure\n'
                        '    SET encoded_polygon = ?\n'
                        '    WHERE rowid = ?',
                        (encoded_polygon, row_id)
                    )
                    cursor.execute(
                        'UPDATE exposure_rtree SET\n'
                        '    x_min = ?, x_max = ?,\n'
                        '    y_min = ?, y_max = ?,\n'
                        '    z_min = ?, z_max = ?\n'
                        'WHERE rowid = ?',
                        (bbox.x().getA(), bbox.x().getB(),
                         bbox.y().getA(), bbox.y().getB(),
                         bbox.z().getA(), bbox.z().getB(),
                         row_id)
                    )
                    return
            # Insert the data id and corresponding spatial information.
            cursor.execute(
                'INSERT INTO exposure\n'
                '    (pickled_data_id, encoded_polygon)\n'
                '    VALUES (?, ?)',
                (pickled_data_id, encoded_polygon)
            )
            row_id = cursor.lastrowid
            cursor.execute(
                'INSERT INTO exposure_rtree\n'
                '     (rowid, x_min, x_max, y_min, y_max, z_min, z_max)\n'
                '     VALUES (?, ?, ?, ?, ?, ?, ?)',
                (row_id,
                 bbox.x().getA(), bbox.x().getB(),
                 bbox.y().getA(), bbox.y().getB(),
                 bbox.z().getA(), bbox.z().getB())
            )
Ejemplo n.º 6
0
 def process_result_value(self, value: Optional[str], dialect: sqlalchemy.engine.Dialect
                          ) -> Optional[ConvexPolygon]:
     if value is None:
         return None
     return ConvexPolygon.decode(super().process_result_value(value, dialect))
Ejemplo n.º 7
0
 def process_result_value(self, value, dialect):
     return ConvexPolygon.decode(
         b64decode(value)) if value is not None else None