Skip to content

Commit f901ca4

Browse files
Merge pull request #121 from lsst-sitcom/tickets/DM-46086
DM-46086: Make EFD query raising on no schema entry an optional parameter
2 parents 0b3fd87 + 3a158cd commit f901ca4

File tree

11 files changed

+419
-16
lines changed

11 files changed

+419
-16
lines changed

python/lsst/summit/utils/auxtel/mount.py

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,13 @@ def hasTimebaseErrors(expRecord: dafButler.DimensionRecord, client: EfdClient, m
5656
`True` if the exposure has timebase errors, `False` otherwise.
5757
"""
5858
log = logging.getLogger(__name__)
59-
mountPosition = getEfdData(client, "lsst.sal.ATMCS.mount_AzEl_Encoders", expRecord=expRecord, warn=False)
59+
mountPosition = getEfdData(
60+
client,
61+
"lsst.sal.ATMCS.mount_AzEl_Encoders",
62+
expRecord=expRecord,
63+
warn=False,
64+
raiseIfTopicNotInSchema=False,
65+
)
6066

6167
if mountPosition.empty:
6268
log.warning(

python/lsst/summit/utils/blockUtils.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -204,7 +204,11 @@ def getDataForDayObs(self) -> None:
204204
# any blocks which might span the end of the day.
205205
padding = 1.5 * 60 * 60
206206
data = getEfdData(
207-
self.client, "lsst.sal.Script.logevent_state", dayObs=self.dayObs, postPadding=padding
207+
self.client,
208+
"lsst.sal.Script.logevent_state",
209+
dayObs=self.dayObs,
210+
postPadding=padding,
211+
raiseIfTopicNotInSchema=False,
208212
)
209213
self.data = data
210214

python/lsst/summit/utils/efdUtils.py

Lines changed: 46 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -180,6 +180,7 @@ def getEfdData(
180180
event: TMAEvent | None = None,
181181
expRecord: dafButler.DimensionRecord | None = None,
182182
warn: bool = True,
183+
raiseIfTopicNotInSchema: bool = True,
183184
) -> pd.DataFrame:
184185
"""Get one or more EFD topics over a time range, synchronously.
185186
@@ -194,6 +195,15 @@ def getEfdData(
194195
195196
The results from all topics are merged into a single dataframe.
196197
198+
`raiseIfTopicNotInSchema` should only be set to `False` when running on the
199+
summit or in utility code for topics which might have had no data taken
200+
within the last <data_retention_period> (nominally 30 days). Once a topic
201+
is in the schema at USDF it will always be there, and thus users there
202+
never need worry about this, always using `False` will be fine. However, at
203+
the summit things are a little less predictable, so something missing from
204+
the schema doesn't necessarily mean a typo, and utility code shouldn't
205+
raise when data has been expunged.
206+
197207
Parameters
198208
----------
199209
client : `lsst_efd_client.efd_helper.EfdClient`
@@ -230,6 +240,8 @@ def getEfdData(
230240
If ``True``, warn when no data is found. Exists so that utility code
231241
can disable warnings when checking for data, and therefore defaults to
232242
``True``.
243+
raiseIfTopicNotInSchema : `bool`, optional
244+
Whether to raise an error if the topic is not in the EFD schema.
233245
234246
Returns
235247
-------
@@ -263,14 +275,22 @@ def getEfdData(
263275
nest_asyncio.apply()
264276
loop = asyncio.get_event_loop()
265277
ret = loop.run_until_complete(
266-
_getEfdData(client=client, topic=topic, begin=begin, end=end, columns=columns)
278+
_getEfdData(
279+
client=client,
280+
topic=topic,
281+
begin=begin,
282+
end=end,
283+
columns=columns,
284+
raiseIfTopicNotInSchema=raiseIfTopicNotInSchema,
285+
)
267286
)
268287
if ret.empty and warn:
269288
log = logging.getLogger(__name__)
270-
log.warning(
271-
f"Topic {topic} is in the schema, but no data was returned by the query for the specified"
272-
" time range"
273-
)
289+
msg = ""
290+
if raiseIfTopicNotInSchema:
291+
f"Topic {topic} is in the schema, but "
292+
msg += "no data was returned by the query for the specified time range"
293+
log.warning(msg)
274294
return ret
275295

276296

@@ -280,6 +300,7 @@ async def _getEfdData(
280300
begin: astropy.Time,
281301
end: astropy.Time,
282302
columns: list[str] | None = None,
303+
raiseIfTopicNotInSchema: bool = True,
283304
) -> pd.DataFrame:
284305
"""Get data for a topic from the EFD over the specified time range.
285306
@@ -295,6 +316,8 @@ async def _getEfdData(
295316
The end time for the query.
296317
columns : `list` of `str`, optional
297318
The columns to query. If not specified, all columns are returned.
319+
raiseIfTopicNotInSchema : `bool`, optional
320+
Whether to raise an error if the topic is not in the EFD schema.
298321
299322
Returns
300323
-------
@@ -308,7 +331,12 @@ async def _getEfdData(
308331
availableTopics = await client.get_topics()
309332

310333
if topic not in availableTopics:
311-
raise ValueError(f"Topic {topic} not in EFD schema")
334+
if raiseIfTopicNotInSchema:
335+
raise ValueError(f"Topic {topic} not in EFD schema")
336+
else:
337+
log = logging.getLogger(__name__)
338+
log.debug(f"Topic {topic} not in EFD schema, returning empty DataFrame")
339+
return pd.DataFrame()
312340

313341
data = await client.select_time_series(topic, columns, begin.utc, end.utc)
314342

@@ -322,6 +350,7 @@ def getMostRecentRowWithDataBefore(
322350
warnStaleAfterNMinutes: float | int = 60 * 12,
323351
maxSearchNMinutes: float | int | None = None,
324352
where: Callable[[pd.DataFrame], list[bool]] | None = None,
353+
raiseIfTopicNotInSchema: bool = True,
325354
) -> pd.Series:
326355
"""Get the most recent row of data for a topic before a given time.
327356
@@ -341,6 +370,8 @@ def getMostRecentRowWithDataBefore(
341370
where: `Callable` or None, optional
342371
A callable taking a single pd.Dataframe argument and returning a
343372
boolean list indicating rows to consider.
373+
raiseIfTopicNotInSchema : `bool`, optional
374+
Whether to raise an error if the topic is not in the EFD schema.
344375
345376
Returns
346377
-------
@@ -366,7 +397,14 @@ def getMostRecentRowWithDataBefore(
366397
df = pd.DataFrame()
367398
beginTime = timeToLookBefore
368399
while df.empty and beginTime > earliest:
369-
df = getEfdData(client, topic, begin=beginTime, timespan=-TIME_CHUNKING, warn=False)
400+
df = getEfdData(
401+
client,
402+
topic,
403+
begin=beginTime,
404+
timespan=-TIME_CHUNKING,
405+
warn=False,
406+
raiseIfTopicNotInSchema=raiseIfTopicNotInSchema,
407+
)
370408
beginTime -= TIME_CHUNKING
371409
if where is not None and not df.empty:
372410
df = df[where(df)]
@@ -776,6 +814,7 @@ def getCommands(
776814
prePadding=prePadding,
777815
postPadding=postPadding,
778816
warn=False, # most commands will not be issue so we expect many empty queries
817+
raiseIfTopicNotInSchema=False,
779818
)
780819
for time, _ in data.iterrows():
781820
# this is much the most simple data structure, and the chance

python/lsst/summit/utils/m1m3/inertia_compensation_system.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -277,6 +277,7 @@ def query_efd_data(
277277
prePadding=self.outer_pad,
278278
postPadding=self.outer_pad,
279279
warn=False,
280+
raiseIfTopicNotInSchema=False,
280281
)
281282

282283
self.log.debug(f"Queried {df.index.size} rows from {topic}")

python/lsst/summit/utils/tmaUtils.py

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -182,10 +182,20 @@ def getAzimuthElevationDataForEvent(
182182
The elevation data for the specified event.
183183
"""
184184
azimuthData = getEfdData(
185-
client, "lsst.sal.MTMount.azimuth", event=event, prePadding=prePadding, postPadding=postPadding
185+
client,
186+
"lsst.sal.MTMount.azimuth",
187+
event=event,
188+
prePadding=prePadding,
189+
postPadding=postPadding,
190+
raiseIfTopicNotInSchema=False,
186191
)
187192
elevationData = getEfdData(
188-
client, "lsst.sal.MTMount.elevation", event=event, prePadding=prePadding, postPadding=postPadding
193+
client,
194+
"lsst.sal.MTMount.elevation",
195+
event=event,
196+
prePadding=prePadding,
197+
postPadding=postPadding,
198+
raiseIfTopicNotInSchema=False,
189199
)
190200

191201
azValues = azimuthData["actualPosition"].values
@@ -1498,7 +1508,13 @@ def _getEfdDataForDayObs(self, dayObs: int) -> None:
14981508
for component in itertools.chain(
14991509
self._movingComponents, self._inPositionComponents, self._stateComponents
15001510
):
1501-
data[component] = getEfdData(self.client, component, dayObs=dayObs, warn=False)
1511+
data[component] = getEfdData(
1512+
self.client,
1513+
component,
1514+
dayObs=dayObs,
1515+
warn=False,
1516+
raiseIfTopicNotInSchema=False,
1517+
)
15021518
self.log.debug(f"Found {len(data[component])} for {component}")
15031519

15041520
if all(dataframe.empty for dataframe in data.values()):

0 commit comments

Comments
 (0)