diff --git a/ArchiveExtractor.py b/ArchiveExtractor.py index 022b2262698fad845fb3abe54e984e0890263b87..195622551990edc2077ef939e4b7f19633a75161 100755 --- a/ArchiveExtractor.py +++ b/ArchiveExtractor.py @@ -11,7 +11,7 @@ import datetime import numpy as np import PyTango as tango -__version__ = 1.0 +__version__ = "1.0.1" ########################################################################## @@ -23,6 +23,7 @@ DBDFMT = "%Y-%m-%d %H:%M:%S" # Extractor date format for GetNearestValue DBDFMT2 = "%d-%m-%Y %H:%M:%S" +ArrayTimeStampToDatetime = np.vectorize(datetime.datetime.fromtimestamp) ##---------------------------------------------------------------------------## def dateparse(datestr): @@ -76,8 +77,7 @@ def query_ADB_BetweenDates(attr, extractor="archiving/TDBExtractor/4"): """ Query attribute data from an archiver database, get all points between dates. - Use GetAttDataBetweenDates. - Warning : if the time interval gives a huge set of data, it can stall. + Use ExtractBetweenDates. Parameters ---------- @@ -152,32 +152,22 @@ def query_ADB_BetweenDates(attr, # For each date chunk for i_d in range(len(cdates)-1): # Make retrieval request - logger.debug("Perform GetAttDataBetweenDates (%s, %s, %s)"%( + logger.debug("Perform ExtractBetweenDates (%s, %s, %s)"%( attr, cdates[i_d].strftime(DBDFMT), cdates[i_d+1].strftime(DBDFMT)) ) - [N,], [name,] = ADB.GetAttDataBetweenDates([ + _date, _value = ADB.ExtractBetweenDates([ attr, cdates[i_d].strftime(DBDFMT), cdates[i_d+1].strftime(DBDFMT) ]) - # Read the history - logger.debug("Retrieve hystory of %d values. Dynamic attribute named %s."%(N, name)) - attrHist = ADB.attribute_history(name, N) - # Transform to datetime - value arrays - _value = np.empty(N, dtype=float) - _date = np.empty(N, dtype=object) - for i_h in range(N): - _value[i_h]=attrHist[i_h].value - _date[i_h]=attrHist[i_h].time.todatetime() - - # Remove dynamic attribute - logger.debug("Remove dynamic attribute %s."%name) - ADB.RemoveDynamicAttribute(name) + _value = np.asarray(_value, dtype=float) + if len(_date) > 0: + _date = ArrayTimeStampToDatetime(_date/1000.0) value.append(_value) date.append(_date) @@ -272,7 +262,7 @@ if __name__ == "__main__": # Install argument parser import argparse - parser = argparse.ArgumentParser(description="Extract attributes from the extractor devices.") + parser = argparse.ArgumentParser(description="Extract attributes from the extractor devices.\nVersion %s"%__version__) parser.add_argument("--from", type=dateparse, dest="dateStart", help="Start date for extraction, format '1990-12-13-22:33:45'. "+ @@ -323,6 +313,8 @@ if __name__ == "__main__": logger.debug("Parsed arguments: %s"%args) + logger.info("Archive Extractor %s"%__version__) + ####################################################### # Filemode or not if args.filemode: diff --git a/ContextSaver.py b/ContextSaver.py new file mode 100644 index 0000000000000000000000000000000000000000..24b3e497f5569675c66433a75abc628b31e0c4ed --- /dev/null +++ b/ContextSaver.py @@ -0,0 +1,197 @@ +#!/usr/Local/pyroot/PyTangoRoot/bin/python +""" +Python module for scanning and saving configuration of devices. + +Includes a Command Line Interface. +Can be imported as is to use function in user script. +""" +import PyTango as tango +import logging +import argparse +import json + +__version__ = "1.0.0" + +##---------------------------------------------------------------------------## +def get_wattr(proxy): + """ + Get all writable attributes from a device and save their values in a python dict. + + Parameters + ---------- + proxy : PyTango.DeviceProxy + Proxy to the device. + + Returns + ------- + config : dict + Dictionnary, keys are attribute names and value their present values. + """ + logger.debug("Scanning write attribute of device %s"%proxy.name()) + config = dict() + + # Scan all attributes + for attr in proxy.get_attribute_list(): + if proxy.get_attribute_config(attr).writable in [ + tango.AttrWriteType.WRITE, + tango.AttrWriteType.READ_WRITE, + tango.AttrWriteType.READ_WITH_WRITE]: + config[attr]=proxy[attr].value + + logger.debug("Detect writtable attribute %s = %s"%( + attr, + proxy[attr].value)) + + return config + + +##---------------------------------------------------------------------------## +def get_properties(proxy): + """ + Get all properties from a device and save them in a python dict. + + Parameters + ---------- + proxy : PyTango.DeviceProxy + Proxy to the device. + + Returns + ------- + config : dict + Dictionnary, keys are attribute names and value their present values. + """ + logger.debug("Scanning properties of device %s"%proxy.name()) + + pl = proxy.get_property_list('*') + + _props = proxy.get_property(pl) + + props=dict() + + # Here we simply convert tango arrays to python arrays. + # For properties, each prop is an array, one element in + # the array is a line for the property. + # Maybe we need to convert in one single string. + for k in _props.keys(): + if k[:2] !="__": + # Change type + props[k] = list(_props[k]) + logger.debug("Detect property %s = %s"%( + k, props[k])) + + + return props + + +########################################################################## +""" Command Line Interface """ +if __name__ == "__main__": + + # Name the logger after the filename + logger = logging.getLogger("ContextSaver") + + ####################################################### + # Install argument parser + import argparse + + parser = argparse.ArgumentParser(description="Copy attributes and properties to a JSON structure.\n"+ + "Version %s"%__version__) + + parser.add_argument("--fileout", type=str, + help="Save the JSON structure to the specified file. Implicit set no output to stdout."), + + parser.add_argument('--log', type=str, default="INFO", + help="Log level. Default: %(default)s.") + + parser.add_argument('-v', action="store_true", + help="Print in stdout the context. Default is on if no fileout option specified.") + + parser.add_argument('--filemode', action="store_true", + help="Set devices to filemode."+ + " Instead of specifying devices, put a path to a file containing a list of devices."+ + " The file contains one device path per line.") + + parser.add_argument('devices', type=str, nargs='+', + help="List of devices to inspect. Full tango path.") + + args = parser.parse_args() + + + ####################################################### + # Configure logger + + # Add a stream handler + s_handler = logging.StreamHandler() + s_handler.setFormatter(logging.Formatter("%(levelname)s\t[%(funcName)s] \t%(message)s")) + + # Set level according to command line attribute + s_handler.setLevel(level=getattr(logging, args.log.upper())) + logger.setLevel(level=getattr(logging, args.log.upper())) + logger.addHandler(s_handler) + + logger.debug("Parsed arguments: %s"%args) + + logger.info("Context Saver %s"%__version__) + + ####################################################### + # Filemode or not + if args.filemode: + logger.info("Filemode, openning file %s"%args.devices[0]) + # Read the file. Each line is an device + with open(args.devices[0], "r") as fp: + devices = fp.readlines() + + logger.debug("Read lines : %s"%devices) + + # Clean end of line + for i_a in range(len(devices)): + devices[i_a] = devices[i_a].rstrip() + + else: + devices = args.devices + + ####################################################### + # Prepare array for result + results = [] + + ####################################################### + # Scan all devices + + for dev in devices: + logger.info("Scanning device %s..."%dev) + + # Declare proxy + prx = tango.DeviceProxy(dev) + + # Retrieve write attributes + wattr = get_wattr(prx) + + # Retrieve properties + props = get_properties(prx) + + # Build json dict + jdict = { + "tangopath":dev, + "wattributes":wattr, + "properties":props, + } + + # Add to results + results.append(jdict) + + logger.info("Done") + + if args.fileout is None: + print(json.dumps(results, indent=4)) + else: + with open(args.fileout, "w") as fp: + json.dump(results, fp, indent=4) + + # Additionnal dump to stdout + if args.v: + print(json.dumps(results, indent=4)) + + +else: + # Name the logger after the module name + logger = logging.getLogger(__name__) diff --git a/SoleilTools.py b/SoleilTools.py index 62e79f383ca07e827ac686d276950d1101d5319d..bd1f7e18eb3ecc8866fb41bca2f7a857eff0d555 100644 --- a/SoleilTools.py +++ b/SoleilTools.py @@ -263,9 +263,9 @@ def plot_meanstdmaxmin(ax, datax, datay, N, c=lines[0].get_color() # Add max, min and std area - lines.append(ax.plot(xmean, ymax, linestyle='-', color=mcol.to_rgba(c, 0.4))[0]) - lines.append(ax.plot(xmean, ymin, linestyle='-', color=mcol.to_rgba(c, 0.4))[0]) - lines.append(ax.fill_between(xmean, ymean-ystd, ymean+ystd, color=mcol.to_rgba(c, 0.4))) + lines.append(ax.plot(xmean, ymax, linestyle='-', color=mcol.to_rgba(c, 0.5))[0]) + lines.append(ax.plot(xmean, ymin, linestyle='-', color=mcol.to_rgba(c, 0.5))[0]) + lines.append(ax.fill_between(xmean, ymean-ystd, ymean+ystd, color=mcol.to_rgba(c, 0.1))) return lines