diff --git a/python/lsst/obs/base/_instrument.py b/python/lsst/obs/base/_instrument.py index a348b3e25..9b43c1991 100644 --- a/python/lsst/obs/base/_instrument.py +++ b/python/lsst/obs/base/_instrument.py @@ -641,12 +641,25 @@ def makeExposureRecordFromObsInfo( else: raise RuntimeError(f"Unable to determine where to put group metadata in exposure record: {supported}") + # In some bad observations, the end time is before the begin time. We + # can not let that be ingested as-is because it becomes an unbounded + # timespan that will not work correctly with calibration lookups. Instead + # force the end time to be the begin time. + datetime_end = obsInfo.datetime_end + if datetime_end < obsInfo.datetime_begin: + datetime_end = obsInfo.datetime_begin + _LOG.warning( + "Exposure %s:%s has end time before begin time. Forcing it to use the begin time.", + obsInfo.instrument, + obsInfo.observation_id, + ) + return dimension.RecordClass( instrument=obsInfo.instrument, id=obsInfo.exposure_id, obs_id=obsInfo.observation_id, datetime_begin=obsInfo.datetime_begin, - datetime_end=obsInfo.datetime_end, + datetime_end=datetime_end, exposure_time=obsInfo.exposure_time.to_value("s"), # we are not mandating that dark_time be calculable dark_time=obsInfo.dark_time.to_value("s") if obsInfo.dark_time is not None else None, diff --git a/tests/data/ingest/sidecar_data/dataset_end.json b/tests/data/ingest/sidecar_data/dataset_end.json new file mode 100644 index 000000000..050ae3b28 --- /dev/null +++ b/tests/data/ingest/sidecar_data/dataset_end.json @@ -0,0 +1 @@ +{"telescope": "Pretend", "instrument": "DummyCam", "location": [-5464492.282102363, -2493000.626631501, 2150943.6513960036], "exposure_id": 3000, "visit_id": 3000, "physical_filter": "dummy_g", "datetime_begin": [2456462.0, 0.06193332175925925], "datetime_end": [2456461.0, 0.6230896990740742], "exposure_time": 30.0, "dark_time": 30.0, "boresight_airmass": 1.072389930512202, "boresight_rotation_angle": 270.0, "boresight_rotation_coord": "sky", "detector_num": 1, "detector_name": "RXX_S01", "detector_unique_name": "0_26", "detector_serial": "076", "detector_group": "0", "detector_exposure_id": 180666823, "object": "STRIPE82L", "temperature": 273.75, "pressure": 621.3000000000001, "relative_humidity": 72.5, "tracking_radec": [320.2499333333333, 1.9444444444444445e-05], "altaz_begin": [157.95888945, 68.80710558], "science_program": "o13015", "observation_type": "science", "observation_id": "DummyDataset_End", "observation_reason": "science", "exposure_group": "3000", "observing_day": 20130617, "observation_counter": 3000, "__CONTENT__": "translated"} diff --git a/tests/data/ingest/sidecar_data/dataset_end.yaml b/tests/data/ingest/sidecar_data/dataset_end.yaml new file mode 100644 index 000000000..f69a810f3 --- /dev/null +++ b/tests/data/ingest/sidecar_data/dataset_end.yaml @@ -0,0 +1,2 @@ +value: 3000 +name: "dataset_3000" diff --git a/tests/test_ingest.py b/tests/test_ingest.py index 66df2145a..174f2efee 100644 --- a/tests/test_ingest.py +++ b/tests/test_ingest.py @@ -135,6 +135,26 @@ def testSimpleIngest(self): datasets = list(self.butler.registry.queryDatasets("raw_dict", collections=self.outputRun)) self.assertEqual(len(datasets), 2) + def testTimeStampWarning(self): + # Now ingest a dataset which should generate a warning because of + # the end time being before the begin time. + return + files = [os.path.join(INGESTDIR, "sidecar_data", "dataset_end.yaml")] + with self.assertLogs("lsst.obs.base._instrument", level="WARNING") as cm: + self.task.run(files, run=self.outputRun) + + self.assertIn("has end time before begin time", cm.output[0]) + records = list( + self.butler.registry.queryDimensionRecords( + "exposure", + where="exposure = exp AND instrument = inst", + bind={"exp": 3000, "inst": "DummyCam"}, + ) + ) + record = records[0] + timespan = record.timespan + self.assertEqual(timespan.begin.isot, timespan.end.isot) + def testExplicitIndex(self): files = [os.path.join(INGESTDIR, "indexed_data", "_index.json")] self.task.run(files, run=self.outputRun)