212 """Test for making APDB schema."""
214 apdb = Apdb.from_config(config)
216 self.assertIsNotNone(apdb.tableDef(ApdbTables.DiaObject))
217 self.assertIsNotNone(apdb.tableDef(ApdbTables.DiaObjectLast))
218 self.assertIsNotNone(apdb.tableDef(ApdbTables.DiaSource))
219 self.assertIsNotNone(apdb.tableDef(ApdbTables.DiaForcedSource))
220 self.assertIsNotNone(apdb.tableDef(ApdbTables.metadata))
221 self.assertIsNotNone(apdb.tableDef(ApdbTables.SSObject))
222 self.assertIsNotNone(apdb.tableDef(ApdbTables.SSSource))
223 self.assertIsNotNone(apdb.tableDef(ApdbTables.DiaObject_To_Object_Match))
226 with tempfile.NamedTemporaryFile()
as tmpfile:
227 config.save(tmpfile.name)
228 apdb = Apdb.from_uri(tmpfile.name)
230 self.assertIsNotNone(apdb.tableDef(ApdbTables.DiaObject))
231 self.assertIsNotNone(apdb.tableDef(ApdbTables.DiaObjectLast))
232 self.assertIsNotNone(apdb.tableDef(ApdbTables.DiaSource))
233 self.assertIsNotNone(apdb.tableDef(ApdbTables.DiaForcedSource))
234 self.assertIsNotNone(apdb.tableDef(ApdbTables.metadata))
235 self.assertIsNotNone(apdb.tableDef(ApdbTables.SSObject))
236 self.assertIsNotNone(apdb.tableDef(ApdbTables.SSSource))
237 self.assertIsNotNone(apdb.tableDef(ApdbTables.DiaObject_To_Object_Match))
240 """Test for getting data from empty database.
242 All get() methods should return empty results, only useful for
243 checking that code is not broken.
247 apdb = Apdb.from_config(config)
252 res: pandas.DataFrame |
None
255 res = apdb.getDiaObjects(region)
259 res = apdb.getDiaSources(region,
None, visit_time)
262 res = apdb.getDiaSources(region, [], visit_time)
266 res = apdb.getDiaSources(region, [1, 2, 3], visit_time)
270 res = apdb.getDiaForcedSources(region, [], visit_time)
274 res = apdb.getDiaForcedSources(region, [1, 2, 3], visit_time)
278 res = apdb.containsVisitDetector(visit=1, detector=1, region=region, visit_time=visit_time)
279 self.assertFalse(res)
283 with self.assertRaises(NotImplementedError):
284 apdb.getDiaForcedSources(region,
None, visit_time)
286 res = apdb.getDiaForcedSources(region,
None, visit_time)
358 """Store and retrieve DiaObject which changes its position."""
361 apdb = Apdb.from_config(config)
364 lon_deg, lat_deg = 0.0, 0.0
365 lonlat1 = LonLat.fromDegrees(lon_deg - 1.0, lat_deg)
366 lonlat2 = LonLat.fromDegrees(lon_deg + 1.0, lat_deg)
371 self.assertNotEqual(pixelization.pixel(uv1), pixelization.pixel(uv2))
375 catalog1 = makeObjectCatalog(lonlat1, 1, visit_time1)
376 apdb.store(visit_time1, catalog1)
378 visit_time2 = visit_time1 + astropy.time.TimeDelta(120.0, format=
"sec")
379 catalog1 = makeObjectCatalog(lonlat2, 1, visit_time2)
380 apdb.store(visit_time2, catalog1)
383 region =
Circle(
UnitVector3d(LonLat.fromDegrees(lon_deg, lat_deg)), Angle.fromDegrees(1.1))
384 self.assertTrue(region.contains(uv1))
385 self.assertTrue(region.contains(uv2))
388 res = apdb.getDiaObjects(region)
392 """Store and retrieve DiaSources."""
394 apdb = Apdb.from_config(config)
400 objects = makeObjectCatalog(region, 100, visit_time)
401 oids = list(objects[
"diaObjectId"])
402 sources = makeSourceCatalog(objects, visit_time, use_mjd=self.
use_mjd)
405 apdb.store(visit_time, objects, sources)
408 res = apdb.getDiaSources(region,
None, visit_time)
412 res = apdb.getDiaSources(region, oids, visit_time)
416 res = apdb.getDiaSources(region, [], visit_time)
421 res = apdb.containsVisitDetector(visit=1, detector=1, region=region, visit_time=visit_time)
424 res = apdb.containsVisitDetector(visit=2, detector=42, region=region, visit_time=visit_time)
425 self.assertFalse(res)
428 """Store and retrieve DiaForcedSources."""
430 apdb = Apdb.from_config(config)
436 objects = makeObjectCatalog(region, 100, visit_time)
437 oids = list(objects[
"diaObjectId"])
438 catalog = makeForcedSourceCatalog(objects, visit_time, use_mjd=self.
use_mjd)
440 apdb.store(visit_time, objects, forced_sources=catalog)
443 res = apdb.getDiaForcedSources(region, oids, visit_time)
444 self.
assert_catalog(res, len(catalog), ApdbTables.DiaForcedSource)
447 res = apdb.getDiaForcedSources(region, [], visit_time)
451 res = apdb.containsVisitDetector(visit=1, detector=1, region=region, visit_time=visit_time)
454 res = apdb.containsVisitDetector(visit=2, detector=42, region=region, visit_time=visit_time)
455 self.assertFalse(res)
458 """Check that timestamp return type is as expected."""
460 apdb = Apdb.from_config(config)
467 time_before = makeTimestampNow(self.
use_mjd, -1)
468 objects = makeObjectCatalog(region, 100, visit_time)
469 oids = list(objects[
"diaObjectId"])
470 catalog = makeForcedSourceCatalog(objects, visit_time, use_mjd=self.
use_mjd)
471 time_after = makeTimestampNow(self.
use_mjd)
473 apdb.store(visit_time, objects, forced_sources=catalog)
476 res = apdb.getDiaForcedSources(region, oids, visit_time)
477 assert res
is not None
478 self.
assert_catalog(res, len(catalog), ApdbTables.DiaForcedSource)
480 time_processed_column =
"timeProcessedMjdTai" if self.
use_mjd else "time_processed"
481 self.assertIn(time_processed_column, res.dtypes)
482 dtype = res.dtypes[time_processed_column]
483 timestamp_type_name =
"float64" if self.
use_mjd else "datetime64[ns]"
484 self.assertEqual(dtype.name, timestamp_type_name)
486 self.assertTrue(all(time_before <= dt <= time_after
for dt
in res[time_processed_column]))
489 """Store and retrieve replica chunks."""
492 apdb = Apdb.from_config(config)
493 apdb_replica = ApdbReplica.from_config(config)
499 objects1 = makeObjectCatalog(region1, nobj, visit_time)
500 objects2 = makeObjectCatalog(region2, nobj, visit_time, start_id=nobj * 2)
505 (astropy.time.Time(
"2021-01-01T00:01:00", format=
"isot", scale=
"tai"), objects1),
506 (astropy.time.Time(
"2021-01-01T00:02:00", format=
"isot", scale=
"tai"), objects2),
507 (astropy.time.Time(
"2021-01-01T00:11:00", format=
"isot", scale=
"tai"), objects1),
508 (astropy.time.Time(
"2021-01-01T00:12:00", format=
"isot", scale=
"tai"), objects2),
509 (astropy.time.Time(
"2021-01-01T00:45:00", format=
"isot", scale=
"tai"), objects1),
510 (astropy.time.Time(
"2021-01-01T00:46:00", format=
"isot", scale=
"tai"), objects2),
511 (astropy.time.Time(
"2021-03-01T00:01:00", format=
"isot", scale=
"tai"), objects1),
512 (astropy.time.Time(
"2021-03-01T00:02:00", format=
"isot", scale=
"tai"), objects2),
516 for visit_time, objects
in visits:
517 sources = makeSourceCatalog(objects, visit_time, start_id=start_id, use_mjd=self.
use_mjd)
518 fsources = makeForcedSourceCatalog(objects, visit_time, visit=start_id, use_mjd=self.
use_mjd)
519 apdb.store(visit_time, objects, sources, fsources)
522 replica_chunks = apdb_replica.getReplicaChunks()
524 self.assertIsNone(replica_chunks)
526 with self.assertRaisesRegex(ValueError,
"APDB is not configured for replication"):
527 apdb_replica.getTableDataChunks(ApdbTables.DiaObject, [])
530 assert replica_chunks
is not None
531 self.assertEqual(len(replica_chunks), 4)
533 with self.assertRaisesRegex(ValueError,
"does not support replica chunks"):
534 apdb_replica.getTableDataChunks(ApdbTables.SSObject, [])
536 def _check_chunks(replica_chunks: list[ReplicaChunk], n_records: int |
None =
None) ->
None:
537 if n_records
is None:
538 n_records = len(replica_chunks) * nobj
539 res = apdb_replica.getTableDataChunks(
540 ApdbTables.DiaObject, (chunk.id
for chunk
in replica_chunks)
543 validityStartColumn =
"validityStartMjdTai" if self.
use_mjd else "validityStart"
544 validityStartType = (
545 felis.datamodel.DataType.double
if self.
use_mjd else felis.datamodel.DataType.timestamp
550 "apdb_replica_chunk": felis.datamodel.DataType.long,
551 "diaObjectId": felis.datamodel.DataType.long,
552 validityStartColumn: validityStartType,
553 "ra": felis.datamodel.DataType.double,
554 "dec": felis.datamodel.DataType.double,
555 "parallax": felis.datamodel.DataType.float,
556 "nDiaSources": felis.datamodel.DataType.int,
560 res = apdb_replica.getTableDataChunks(
561 ApdbTables.DiaSource, (chunk.id
for chunk
in replica_chunks)
567 "apdb_replica_chunk": felis.datamodel.DataType.long,
568 "diaSourceId": felis.datamodel.DataType.long,
569 "visit": felis.datamodel.DataType.long,
570 "detector": felis.datamodel.DataType.short,
574 res = apdb_replica.getTableDataChunks(
575 ApdbTables.DiaForcedSource, (chunk.id
for chunk
in replica_chunks)
581 "apdb_replica_chunk": felis.datamodel.DataType.long,
582 "diaObjectId": felis.datamodel.DataType.long,
583 "visit": felis.datamodel.DataType.long,
584 "detector": felis.datamodel.DataType.short,
589 _check_chunks(replica_chunks, 800)
590 _check_chunks(replica_chunks[1:], 600)
591 _check_chunks(replica_chunks[1:-1], 400)
592 _check_chunks(replica_chunks[2:3], 200)
596 deleted_chunks = replica_chunks[:1]
597 apdb_replica.deleteReplicaChunks(chunk.id
for chunk
in deleted_chunks)
600 _check_chunks(deleted_chunks, 0)
602 replica_chunks = apdb_replica.getReplicaChunks()
603 assert replica_chunks
is not None
604 self.assertEqual(len(replica_chunks), 3)
606 _check_chunks(replica_chunks, 600)
609 """Store and retrieve SSObjects."""
612 apdb = Apdb.from_config(config)
615 catalog = makeSSObjectCatalog(100, flags=1)
618 apdb.storeSSObjects(catalog)
621 res = apdb.getSSObjects()
625 catalog = makeSSObjectCatalog(100, 51, flags=2)
626 apdb.storeSSObjects(catalog)
627 res = apdb.getSSObjects()
629 self.assertEqual(len(res[res[
"flags"] == 1]), 50)
630 self.assertEqual(len(res[res[
"flags"] == 2]), 100)
633 """Reassign DiaObjects."""
636 apdb = Apdb.from_config(config)
640 objects = makeObjectCatalog(region, 100, visit_time)
641 oids = list(objects[
"diaObjectId"])
642 sources = makeSourceCatalog(objects, visit_time, use_mjd=self.
use_mjd)
643 apdb.store(visit_time, objects, sources)
645 catalog = makeSSObjectCatalog(100)
646 apdb.storeSSObjects(catalog)
649 res = apdb.getDiaSources(region, oids, visit_time)
652 apdb.reassignDiaSources({1: 1, 2: 2, 5: 5})
653 res = apdb.getDiaSources(region, oids, visit_time)
656 with self.assertRaisesRegex(ValueError,
r"do not exist.*\D1000"):
657 apdb.reassignDiaSources(
666 """Test for time filtering of DiaSources."""
668 apdb = Apdb.from_config(config)
672 src_time1 = astropy.time.Time(
"2021-01-01T00:00:00", format=
"isot", scale=
"tai")
673 src_time2 = astropy.time.Time(
"2021-01-01T00:00:02", format=
"isot", scale=
"tai")
674 visit_time0 = astropy.time.Time(
"2021-12-26T23:59:59", format=
"isot", scale=
"tai")
675 visit_time1 = astropy.time.Time(
"2021-12-27T00:00:01", format=
"isot", scale=
"tai")
676 visit_time2 = astropy.time.Time(
"2021-12-27T00:00:03", format=
"isot", scale=
"tai")
678 objects = makeObjectCatalog(region, 100, visit_time0)
679 oids = list(objects[
"diaObjectId"])
680 sources = makeSourceCatalog(objects, src_time1, 0, use_mjd=self.
use_mjd)
681 apdb.store(src_time1, objects, sources)
683 sources = makeSourceCatalog(objects, src_time2, 100, use_mjd=self.
use_mjd)
684 apdb.store(src_time2, objects, sources)
687 res = apdb.getDiaSources(region, oids, src_time2)
691 res = apdb.getDiaSources(region, oids, visit_time0)
695 res = apdb.getDiaSources(region, oids, visit_time1)
699 res = apdb.getDiaSources(region, oids, visit_time2)
703 """Test for time filtering of DiaForcedSources."""
705 apdb = Apdb.from_config(config)
708 src_time1 = astropy.time.Time(
"2021-01-01T00:00:00", format=
"isot", scale=
"tai")
709 src_time2 = astropy.time.Time(
"2021-01-01T00:00:02", format=
"isot", scale=
"tai")
710 visit_time0 = astropy.time.Time(
"2021-12-26T23:59:59", format=
"isot", scale=
"tai")
711 visit_time1 = astropy.time.Time(
"2021-12-27T00:00:01", format=
"isot", scale=
"tai")
712 visit_time2 = astropy.time.Time(
"2021-12-27T00:00:03", format=
"isot", scale=
"tai")
714 objects = makeObjectCatalog(region, 100, visit_time0)
715 oids = list(objects[
"diaObjectId"])
716 sources = makeForcedSourceCatalog(objects, src_time1, 1, use_mjd=self.
use_mjd)
717 apdb.store(src_time1, objects, forced_sources=sources)
719 sources = makeForcedSourceCatalog(objects, src_time2, 2, use_mjd=self.
use_mjd)
720 apdb.store(src_time2, objects, forced_sources=sources)
723 res = apdb.getDiaForcedSources(region, oids, src_time2)
727 res = apdb.getDiaForcedSources(region, oids, visit_time0)
731 res = apdb.getDiaForcedSources(region, oids, visit_time1)
735 res = apdb.getDiaForcedSources(region, oids, visit_time2)
739 """Simple test for writing/reading metadata table"""
741 apdb = Apdb.from_config(config)
742 metadata = apdb.metadata
746 self.assertFalse(metadata.empty())
747 self.assertEqual(len(list(metadata.items())), self.
meta_row_count)
749 metadata.set(
"meta",
"data")
750 metadata.set(
"data",
"meta")
752 self.assertFalse(metadata.empty())
753 self.assertTrue(set(metadata.items()) >= {(
"meta",
"data"), (
"data",
"meta")})
755 with self.assertRaisesRegex(KeyError,
"Metadata key 'meta' already exists"):
756 metadata.set(
"meta",
"data1")
758 metadata.set(
"meta",
"data2", force=
True)
759 self.assertTrue(set(metadata.items()) >= {(
"meta",
"data2"), (
"data",
"meta")})
761 self.assertTrue(metadata.delete(
"meta"))
762 self.assertIsNone(metadata.get(
"meta"))
763 self.assertFalse(metadata.delete(
"meta"))
765 self.assertEqual(metadata.get(
"data"),
"meta")
766 self.assertEqual(metadata.get(
"meta",
"meta"),
"meta")