From 76866b33c7ab043e59600dab1ab30ab4245dd04b Mon Sep 17 00:00:00 2001 From: Romain Broucquart <romain.broucquart@synchrotron-soleil.fr> Date: Thu, 16 Mar 2023 17:33:59 +0100 Subject: [PATCH] feat:Date parser can now recognize time delta, auto init at start --- ArchiveExtractor.py | 85 +++++++++++++++++++++++++++++---------------- README.md | 25 ++++++------- 2 files changed, 66 insertions(+), 44 deletions(-) diff --git a/ArchiveExtractor.py b/ArchiveExtractor.py index 24f5cc3..2f3fa64 100755 --- a/ArchiveExtractor.py +++ b/ArchiveExtractor.py @@ -57,14 +57,16 @@ def _check_initialized(): ##----------------------------------------------------------------------## def _dateparse(datestr): """ - Convenient function to parse date strings. - Global format is %Y-%m-%d-%H:%M:%S and it can be reduced to be less precise. + Convenient function to parse date or duration strings. + Exact date format is %Y-%m-%d-%H:%M:%S and it can be reduced to be less precise. + Duration format is 'Xu' where X is a number and u is a unit in ('m':minutes, 'h':hours, 'd':days, 'M':months) If datstr is None, take the actual date and time. Parameters --------- datestr : string Date as a string, format %Y-%m-%d-%H:%M:%S or less precise. + Duration as a string, format 'Xu' where X is a number and u is a unit in ('m':minutes, 'h':hours, 'd':days, 'M':months) Exceptions ---------- @@ -73,35 +75,52 @@ def _dateparse(datestr): Returns ------- - date : datetime.datetime - Parsed date + date : datetime.datetime or datetime.timedelta + Parsed date or duration """ + logger.debug("Parsing date string '%s'"%datestr) + + # Determine date/duration by looking at the last char + if datestr[-1] in "mhdM": + # Duration + logger.debug("Assuming a duration") - if datestr is None: - return datetime.datetime.now() - - # This gives all format that will be tried, in order. - # Stop on first parse success. Raise error if none succeed. - fmt = [ - "%Y-%m-%d-%H:%M:%S", - "%Y-%m-%d-%H:%M", - "%Y-%m-%d-%H", - "%Y-%m-%d", - "%Y-%m", - ] - - date = None - for f in fmt: try: - date = datetime.datetime.strptime(datestr, f) - except ValueError: - continue - else: - break + q=float(datestr[:-1]) + except ValueError as e: + logger.error("Failed to parse date string. Given the last character, a duration was assumed.") + raise Exception("Could not parse argument to a date") from e + + # Convert all in minutes + minutes = q*{'m':1, 'h':60, 'd':60*24, 'm':30*60*24}[datestr[-1]] + + return datetime.timedelta(minutes=minutes) + else: - raise ValueError("Could not parse argument to a date") + # Probably a date string + + # This gives all format that will be tried, in order. + # Stop on first parse success. Raise error if none succeed. + fmt = [ + "%Y-%m-%d-%H:%M:%S", + "%Y-%m-%d-%H:%M", + "%Y-%m-%d-%H", + "%Y-%m-%d", + "%Y-%m", + ] + + date = None + for f in fmt: + try: + date = datetime.datetime.strptime(datestr, f) + except ValueError: + continue + else: + break + else: + raise ValueError("Could not parse argument to a date") - return date + return date ##----------------------------------------------------------------------## def _check_attribute(attribute, db): @@ -243,11 +262,13 @@ def init( Initialize the module. Instanciate tango.DeviceProxy for extractors (TDB and HDB) - HdbExtractorPath, TdbExtractorPath: string - Tango path to the extractors. + Parameters: + ----------- + HdbExtractorPath, TdbExtractorPath: string + Tango path to the extractors. - loglevel: string - loglevel to pass to logging.Logger + loglevel: string + loglevel to pass to logging.Logger """ global _extractors global _AttrTables @@ -641,3 +662,7 @@ def ExtrBetweenDates_MinMaxMean( "Max":value_max, },) +## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## +## Initialize on import +## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## +init() diff --git a/README.md b/README.md index 64b7954..4098332 100644 --- a/README.md +++ b/README.md @@ -13,12 +13,9 @@ Usage example, with an ipython prompt ```python In [1]: import pySoleilControl.ArchiveExtractor as AE -In [2]: # For now, we need manual initialization of the module - ...: AE.init() - -In [3]: # Looking for an attribute in HDB +In [2]: # Looking for an attribute in HDB ...: AE.findattr("ans/dg/*dcct*") -Out[3]: +Out[2]: ['ANS/DG/DCCT-CTRL/State', 'ANS/DG/DCCT-CTRL/Status', 'ANS/DG/DCCT-CTRL/current', @@ -26,10 +23,10 @@ Out[3]: 'ANS/DG/DCCT-CTRL/lifeTime', 'ANS/DG/DCCT-CTRL/lifeTimeErr'] -In [4]: # Get data between two dates, this return a pandas.Dataframe object +In [3]: # Get data between two dates, this return a pandas.Dataframe object ...: AE.ExtrBetweenDates('ANS/DG/DCCT-CTRL/current', '2021-12-13', '2021-12-13-12:00') INFO:Perform ExtractBetweenDates (ans/dg/dcct-ctrl/current, 2021-12-13 00:00:00, 2021-12-13 12:00:00) -Out[4]: +Out[3]: 2021-12-13 00:00:00 450.993568 2021-12-13 00:00:01 450.981979 2021-12-13 00:00:02 450.971455 @@ -43,11 +40,11 @@ Out[4]: 2021-12-13 12:00:00 15.005410 Length: 42725, dtype: float64 -In [5]: # Get min, max and mean with a 10 minute window +In [4]: # Get min, max and mean with a 10 minute window ...: d=AE.ExtrBetweenDates_MinMaxMean('ANS/DG/DCCT-CTRL/current', '2021-12-13', '2021-12-13-12:00', timeInterval='10m') -In [6]: d -Out[6]: +In [5]: d +Out[5]: Min Mean Max 2021-12-13 00:05:00 449.762286 450.619654 451.617095 2021-12-13 00:15:00 449.761171 450.676306 451.595391 @@ -64,14 +61,14 @@ Out[6]: [72 rows x 3 columns] -In [7]: # Activate inline matplotlib +In [6]: # Activate inline matplotlib ...: %matplotlib Using matplotlib backend: TkAgg -In [7]: # Simply plot +In [6]: # Simply plot ...: d.plot() -In [8]: # ipython prompt supports autocompletion. The doc of function can be quickly read by adding a '?' +In [7]: # ipython prompt supports autocompletion. The doc of function can be quickly read by adding a '?' ...: AE.ExtrBetweenDates? Signature: AE.ExtrBetweenDates(attribute, dateStart, dateStop=None, db='H') Docstring: @@ -114,4 +111,4 @@ Type: function -``` \ No newline at end of file +``` -- GitLab