Skip to content

Commit

Permalink
Merge pull request #64 from lsst-sitcom/tickets/DM-41062
Browse files Browse the repository at this point in the history
DM-41062: Add topic finding to efdUtils
  • Loading branch information
mfisherlevine authored Oct 10, 2023
2 parents 273ad40 + e46e971 commit dddff91
Show file tree
Hide file tree
Showing 4 changed files with 74 additions and 18 deletions.
50 changes: 49 additions & 1 deletion python/lsst/summit/utils/efdUtils.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@
import datetime
import logging
import pandas as pd
import re
from deprecated.sphinx import deprecated

from .utils import getSite

Expand All @@ -46,7 +48,8 @@
'getDayObsStartTime',
'getDayObsEndTime',
'getDayObsForTime',
'getSubTopics',
'getSubTopics', # deprecated, being removed in w_2023_50
'getTopics',
]


Expand Down Expand Up @@ -530,6 +533,12 @@ def getDayObsForTime(time):
return int((time + offset).utc.isot[:10].replace('-', ''))


@deprecated(
reason="getSubTopics() has been replaced by getTopics() and using wildcards. "
"Will be removed after w_2023_50.",
version="w_2023_40",
category=FutureWarning,
)
def getSubTopics(client, topic):
"""Get all the sub topics within a given topic.
Expand All @@ -553,3 +562,42 @@ def getSubTopics(client, topic):
loop = asyncio.get_event_loop()
topics = loop.run_until_complete(client.get_topics())
return sorted([t for t in topics if t.startswith(topic)])


def getTopics(client, toFind, caseSensitive=False):
"""Return all the strings in topics which match the topic query string.
Supports wildcards, which are denoted as `*``, as per shell globs.
Example:
>>> # assume topics are ['apple', 'banana', 'grape']
>>> getTopics(, 'a*p*')
['apple', 'grape']
Parameters
----------
client : `lsst_efd_client.efd_helper.EfdClient`
The EFD client to use.
toFind : `str`
The query string, with optional wildcards denoted as *.
caseSensitive : `bool`, optional
If ``True``, the query is case sensitive. Defaults to ``False``.
Returns
-------
matches : `list` of `str`
The list of matching topics.
"""
loop = asyncio.get_event_loop()
topics = loop.run_until_complete(client.get_topics())

# Replace wildcard with regex equivalent
pattern = toFind.replace('*', '.*')
flags = re.IGNORECASE if not caseSensitive else 0

matches = []
for topic in topics:
if re.match(pattern, topic, flags):
matches.append(topic)

return matches
File renamed without changes.
14 changes: 6 additions & 8 deletions tests/test_butlerUtils.py
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@
)
from lsst.summit.utils.butlerUtils import removeDataProduct # noqa: F401
import lsst.daf.butler as dafButler
from lsst.daf.butler import DatasetRef, NamedKeyMapping
from lsst.resources import ResourcePath


Expand Down Expand Up @@ -108,10 +109,7 @@ def setUp(self):
self.dataCoordFullView = self.butler.registry.expandDataId(self.rawDataIdNoDayObSeqNum,
detector=0).full
self.assertIsInstance(self.dataCoordMinimal, dafButler.dimensions.DataCoordinate)
# NB the type check below is currently using a non-public API, but
# at present there isn't a good alternative
viewType = dafButler.core.dimensions._coordinate._DataCoordinateFullView
self.assertIsInstance(self.dataCoordFullView, viewType)
self.assertIsInstance(self.dataCoordFullView, NamedKeyMapping)

def test_getLatissDefaultCollections(self):
defaultCollections = getLatissDefaultCollections()
Expand Down Expand Up @@ -178,14 +176,14 @@ def test_getMostRecentDataId(self):

def test_getDatasetRefForDataId(self):
dRef = getDatasetRefForDataId(self.butler, 'raw', self.rawDataId)
self.assertIsInstance(dRef, lsst.daf.butler.core.datasets.ref.DatasetRef)
self.assertIsInstance(dRef, DatasetRef)

dRef = getDatasetRefForDataId(self.butler, 'raw', self.rawDataIdNoDayObSeqNum)
self.assertIsInstance(dRef, lsst.daf.butler.core.datasets.ref.DatasetRef)
self.assertIsInstance(dRef, DatasetRef)
dRef = getDatasetRefForDataId(self.butler, 'raw', self.dataCoordMinimal)
self.assertIsInstance(dRef, lsst.daf.butler.core.datasets.ref.DatasetRef)
self.assertIsInstance(dRef, DatasetRef)
dRef = getDatasetRefForDataId(self.butler, 'raw', self.dataCoordFullView)
self.assertIsInstance(dRef, lsst.daf.butler.core.datasets.ref.DatasetRef)
self.assertIsInstance(dRef, DatasetRef)

def test__dayobs_present(self):
goods = [{'day_obs': 123}, {'exposure.day_obs': 234}, {'day_obs': 345, 'otherkey': -1}]
Expand Down
28 changes: 19 additions & 9 deletions tests/test_efdUtils.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@
getDayObsStartTime,
getDayObsEndTime,
getDayObsForTime,
getSubTopics,
getTopics,
)

from utils import getVcr
Expand Down Expand Up @@ -118,14 +118,24 @@ def test_getDayObsAsTimes(self):
self.assertEqual(dayEnd.jd, dayStart.jd + 1)

@vcr.use_cassette()
def test_getSubTopics(self):
subTopics = getSubTopics(self.client, 'lsst.sal.MTMount')
self.assertIsInstance(subTopics, list)
self.assertGreater(len(subTopics), 0)

subTopics = getSubTopics(self.client, 'fake.topics.does.not.exist')
self.assertIsInstance(subTopics, list)
self.assertEqual(len(subTopics), 0)
def test_getTopics(self):
topics = getTopics(self.client, 'lsst.sal.MTMount*')
self.assertIsInstance(topics, list)
self.assertGreater(len(topics), 0)

topics = getTopics(self.client, '*fake.topics.does.not.exist*')
self.assertIsInstance(topics, list)
self.assertEqual(len(topics), 0)

# check we can find the mount with a preceding wildcard
topics = getTopics(self.client, '*mTmoUnt*')
self.assertIsInstance(topics, list)
self.assertGreater(len(topics), 0)

# check it fails if we don't allow case insensitivity
topics = getTopics(self.client, '*mTmoUnt*', caseSensitive=True)
self.assertIsInstance(topics, list)
self.assertEqual(len(topics), 0)

@vcr.use_cassette()
def test_getEfdData(self):
Expand Down

0 comments on commit dddff91

Please sign in to comment.