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