New class Data subclasses numpy.ndarray for faster data handling.
Changes:
* hooke.libhookecurve.PlotObject -> hooke.ui.gui.plot.PlotObject
* hooke.libhookecurve.Driver -> hooke.driver.Driver
* Raise new exception hooke.driver.NotRecognized if no driver
matches (vs. old print message and return false).
* Curve stores data in a list (vs. old dict). Often data order
is important. The names that used to key the data dict can
now go into Data.info['name'].
* HookeCurve.fits -> Curve.info['fits']
* HookeCurve.plots is GUI data, but if the UI needs it, it should be
stored in Curve.info['plots']
* Since Curve.data is an array,
HookeCurve.add_data() -> Curve.data.append(),
HookeCurve.delete_data() -> Curve.data.remove(), and
HookeCurve.set_data() -> Curve.data[i] = data
--- /dev/null
+import os.path
+import numpy
+
+from .driver import NotRecognized
+
+class Data (numpy.ndarray):
+ """Stores a single, continuous data set.
+
+ Adds :attr:`info` :class:`dict` to the standard :class:`numpy.ndarray`.
+
+ See :mod:`numpy.doc.subclassing` for the peculiarities of
+ subclassing :class:`numpy.ndarray`.
+ """
+ def __new__(self, subtype, shape, dtype=numpy.float, buffer=None, offset=0,
+ strides=None, order=None, info=None):
+ """Create the ndarray instance of our type, given the usual
+ input arguments. This will call the standard ndarray
+ constructor, but return an object of our type.
+ """
+ obj = np.ndarray.__new__(subtype=subtype, shape=shape, dtype=dtype,
+ buffer=buffer, offset=offset, strides=strides,
+ order=order)
+ # add the new attribute to the created instance
+ if info == None:
+ info = {}
+ obj.info = info
+ # Finally, we must return the newly created object:
+ return obj
+
+ def __array_finalize__(self, obj):
+ """Set any extra attributes from the original object when
+ creating a new view object."""
+ # reset the attribute from passed original object
+ self.info = getattr(obj, 'info', {})
+ # We do not need to return anything
+
+
+class Curve (object):
+ """A grouped set of :class:`Data` runs from the same file with metadata.
+
+ For an approach/retract force spectroscopy experiment, the group
+ would consist of the approach data and the retract data. Metadata
+ would be the temperature, cantilever spring constant, etc.
+ """
+ def __init__(self, path):
+ #the data dictionary contains: {name of data: list of data sets [{[x], [y]}]
+ self.path = path
+ self.driver = None
+ self.data = []
+ self.info = None
+ self.name = os.path.basename(path)
+ self.notes = ''
+
+ def identify(self, drivers):
+ """Identify the appropriate :class:`hooke.driver.Driver` for
+ the curve file (`.path`).
+ """
+ for driver in drivers:
+ current_driver = driver(self.path)
+ if current_driver.is_me():
+ self.driver = current_driver # remember the working driver
+ return
+ raise NotRecognized(self.path)
+
+ def load(self):
+ """Use the driver to read the curve into memory.
+ """
+ pass
+class NotRecognized (ValueError):
+ def __init__(self, path):
+ msg = 'Not a recognizable curve format: %s' % self.path
+ ValueError.__init__(self, msg)
+ self.path = path
+
+class Driver(object):
+ '''
+ Base class for file format drivers.
+
+ To be overridden
+ '''
+ def __init__(self):
+ self.experiment = ''
+ self.filetype = ''
+
+ def is_me(self):
+ '''
+ This method must read the file and return True if the filetype can be managed by the driver, False if not.
+ '''
+ return False
+
+ def close_all(self):
+ '''
+ This method must close all the open files of the driver, explicitly.
+ '''
+ return None
+
+ def default_plots(self):
+ dummy_default = PlotObject()
+ dummy_default.vectors.append([[[0]],[[0]]])
+ return [dummy_default]
(c)Massimo Sandal, 2008
'''
-from .. import libhookecurve as lhc
+from .. import curve as lhc
from .. import libhooke as lh
import csv
Massimo Sandal (c) 2009
'''
-from .. import libhookecurve as lhc
+from .. import curve as lhc
from .. import libhooke as lh
class hdf5Driver(lhc.Driver):
2007_02_07: Initial implementation
'''
import string
-from .. import libhookecurve as lhc
+from .. import curve as lhc
class DataChunk(list):
'''Dummy class to provide ext and ret methods to the data list.
import string
-from .. import libhookecurve as lhc
+from .. import curve as lhc
class DataChunk(list):
#Dummy class to provide ext and ret methods to the data list.
Massimo Sandal, Allen Chen (c) 2009
'''
-from .. import libhookecurve as lhc
+from .. import curve as lhc
from .. import libhooke as lh
import struct
import os
from .. import libhooke as lh
-from .. import libhookecurve as lhc
+from .. import curve as lhc
__version__='0.0.0.20090923'
import os.path
import struct
-from .. import libhookecurve as lhc
+from .. import curve as lhc
__version__='0.0.0.20100310'
from scipy import arange
#from .. import libhooke as lh
-from .. import libhookecurve as lhc
+from .. import curve as lhc
__version__='0.0.0.20090923'
import re, struct
from scipy import arange
-from .. import libhookecurve as lhc
+from .. import curve as lhc
__version__='0.0.0.20081706'
that is, two plots with two datasets each.
'''
-from .. import libhookecurve as lhc #We need to import this library to define some essential data types
+from .. import curve as lhc #We need to import this library to define some essential data types
class tutorialdriverDriver(lhc.Driver):
'''
This is the method that returns the plots to Hooke.
It must return a list with *one* or *two* PlotObjects.
- See the libhookecurve.py source code to see how PlotObjects are defined and work in detail.
+ See the curve.py source code to see how PlotObjects are defined and work in detail.
'''
gen_vectors=self._generate_vectors()
- title: string , the plot title.
for each plot.
- Again, see libhookecurve.py comments for details.
+ Again, see curve.py comments for details.
'''
main_plot.units=['unit of x','unit of y']
main_plot.destination=0
from matplotlib.ticker import ScalarFormatter
-from . import libhookecurve as lhc
+from . import curve as lhc
class EngrFormatter(ScalarFormatter):
import platform
from .libhooke import PlaylistXML
-from . import libhookecurve as lhc
+from . import curve as lhc
from . import libinput as linp
from . import liboutlet as lout
+++ /dev/null
-import os.path
-
-class HookeCurve(object):
-
- def __init__(self, path):
- #the data dictionary contains: {name of data: list of data sets [{[x], [y]}]
- self.data = {}
- self.driver = Driver()
- self.path = path
- self.fits = {}
- self.name = os.path.basename(path)
- self.notes = ''
- self.plots = None
-
- def add_data(self, name, x, y, color=None, result=None, style=None, visible=True):
- data = {'x': x, 'y': y, 'color': color, 'result': result, 'style': style, 'visible': visible}
- if self.data.has_key(name):
- #get the existing list of xydata
- list_data = self.data[name]
- else:
- #we need a new list of xydata
- list_data = []
- #append the xydata to the list
- list_data.append(data)
- #append or change the corresponding dictionary entry
- self.data[name] = list_data
-
- #def add_result(self, name, index, result):
- #if self.data.has_key(name):
- ##get the existing list of xydata
- #list_data = self.data[name][index]
- #list_data['result'] = result
-
- def delete_data(self, name):
- if self.data.has_key(name):
- del self.data[name]
-
- def identify(self, drivers):
- '''
- identifies a curve and returns the corresponding object
- '''
- for driver in drivers:
- current_driver = driver(self.filename)
- if current_driver.is_me():
- #bring on all the driver, with its load of methods etc.
- #so we can access the whole of it.
- self.driver = current_driver
- return True
- print 'Not a recognizable curve format: ', self.path
- return False
-
- def set_data(self, name, x, y, color=None, result=None, style=None, visible=True):
- data = {'x': x, 'y': y, 'color': color, 'result': result, 'style': style, 'visible': visible}
- #append the xydata to the list
- list_data = [data]
- #append or change the corresponding dictionary entry
- self.data[name] = list_data
-
-
-class Driver(object):
- '''
- Base class for file format drivers.
-
- To be overridden
- '''
- def __init__(self):
- self.experiment = ''
- self.filetype = ''
-
- def is_me(self):
- '''
- This method must read the file and return True if the filetype can be managed by the driver, False if not.
- '''
- return False
-
- def close_all(self):
- '''
- This method must close all the open files of the driver, explicitly.
- '''
- return None
-
- def default_plots(self):
- dummy_default = PlotObject()
- dummy_default.vectors.append([[[0]],[[0]]])
- return [dummy_default]
-
-
-class PlotObject(object):
-
- def __init__(self):
-
- '''
- the plot destination
- 0=top
- 1=bottom
- '''
- self.destination=0
-
- '''
- self.vectors is a multidimensional array:
- self.vectors[0]=plot1
- self.vectors[1]=plot2
- self.vectors[2]=plot3
- etc.
-
- 2 curves in a x,y plot are:
- [[[x1],[y1]],[[x2],[y2]]]
- for example:
- x1 y1 x2 y2
- [[[1,2,3,4],[10,20,30,40]],[[3,6,9,12],[30,60,90,120]]]
- x1 = self.vectors[0][0]
- y1 = self.vectors[0][1]
- x2 = self.vectors[1][0]
- y2 = self.vectors[1][1]
- '''
- self.vectors=[]
-
- '''
- self.units is simpler. for each plot with N axes (x,y,z...) only N labels
- can be made, regardless of the number of superimposed plots
- so units for the double plot above is: [unitx, unity]
-
- units are strings
- '''
- self.units=['', '']
-
- '''
- xaxes and yaxes directions. 0, 0 means the common +X=right, +Y=top directions
- '''
- self.xaxes = 0
- self.yaxes = 0
-
- self.filename = ''
- self.title = '' #title
-
- '''
- styles: defines what is the style of the current plots. If undefined or None, it is line plot.
- If an element of the list is 'scatter', the corresponding dataset
- is drawn with scattered points and not a continuous line.
- '''
- self.styles = []
-
- '''
- colors: define what is the colour of the current plots
- '''
- self.colors = []
-
- def add_set(self, x, y):
- '''
- Adds an x, y data set to the vectors.
- '''
- self.vectors.append([])
- self.vectors[-1].append(x)
- self.vectors[-1].append(y)
-
- def remove_set(self, whichset):
- '''
- Removes a set
- '''
- #TODO: do we need 'waste' here?
- waste = self.vectors.pop(whichset)
-
- def normalize_vectors(self):
- '''
- Trims the vector lengths as to be equal in a plot.
- '''
- for index in range(0,len(self.vectors)):
- vectors_to_plot=self.vectors[index]
- lengths=[len(vector) for vector in vectors_to_plot]
- if min(lengths) != max(lengths):
- for indexplot in range(0,len(vectors_to_plot)):
- self.vectors[index][indexplot] = self.vectors[index][indexplot][0:min(lengths)]
-
import xml.dom.minidom
from . import hooke as hooke
-from . import libhookecurve as lhc
+from . import curve as lhc
from . import libhooke as lh
class Playlist(object):
name='cut',
arguments=[
Argument(name='curve', type='curve', optional=False, help="""
-:class:``hooke.Curve`` to cut from.
+:class:``hooke.curve.Curve`` to cut from.
""".strip()),
Argument(name='block', aliases=['set'], type='int', default=0,
help="""
#import pickle
import libpeakspot as lps
-#import libhookecurve as lhc
+#import curve as lhc
import hookecurve as lhc
import libhooke as lh
import wxversion
#import pickle
from .. import libpeakspot as lps
-from .. import libhookecurve as lhc
+from .. import curve as lhc
class flatfiltsCommands(object):
wxversion.select(WX_GOOD)
from wx import PostEvent
-from .. import libhookecurve as lhc
+from .. import curve as lhc
class generalclampCommands(object):
import os.path
import string
-from .. import libhookecurve as lhc
+from .. import curve as lhc
from .. import libinput as linput
class macroCommands(object):
import csv
from .. import libpeakspot as lps
-from .. import libhookecurve as lhc
+from .. import curve as lhc
from .. import libhooke as lh
class massanalysisCommands(object):
import time
import pylab as pyl
-from .. import libhookecurve as lhc
+from .. import curve as lhc
import warnings
import scipy.signal
import copy
-from .. import libhookecurve as lhc
+from .. import curve as lhc
class procplotsCommands(object):
from wx import PostEvent
from numpy import arange, mean
-from .. import libhookecurve as lhc
+from .. import curve as lhc
class superimposeCommands(object):
import numpy as np
-from .. import libhookecurve as lhc
+from .. import curve as lhc
'''
SYNTAX OF DATA TYPE DECLARATION:
'''
'''self.current_list
- TYPE: [ libhookecurve.HookeCurve ], len=variable
+ TYPE: [ curve.HookeCurve ], len=variable
contains the actual playlist of Hooke curve objects.
Each HookeCurve object represents a reference to a data file.
We will see later in detail how do they work.
print 'pointer: ',self.pointer
'''self.current
- TYPE: libhookecurve.HookeCurve
+ TYPE: curve.HookeCurve
contains the current curve displayed.
We will see later how it works.
'''
print 'current:',self.current
'''self.plots
- TYPE: [ libhookecurve.PlotObject ], len=1,2
+ TYPE: [ curve.PlotObject ], len=1,2
contains the current default plots.
Each PlotObject contains all info needed to display
the plot: apart from the data vectors, the title, destination
def do_myfirstplot(self,args):
'''
In this function, we see how to create a PlotObject and send it to the screen.
- ***Read the code of PlotObject in libhookecurve.py before!***.
+ ***Read the code of PlotObject in curve.py before!***.
'''
#We generate some interesting data to plot for this example.
ydata2=[item**3 for item in xdata2]
#Create the object.
- #The PlotObject class lives in the libhookecurve library.
+ #The PlotObject class lives in the curve library.
myplot=lhc.PlotObject()
'''
The *data* of the plot live in the .vectors list.
self.current
---
- Contains the current libhookecurve.HookeCurve container object.
+ Contains the current curve.HookeCurve container object.
A HookeCurve object defines only two default attributes:
* self.current.path = string
The path of the current displayed curve
- * self.current.curve = libhookecurve.Driver
+ * self.current.curve = curve.Driver
The curve object. This is not only generated by the driver,
this IS a driver instance in itself.
This means that in self.current.curve you can access the
--- /dev/null
+class PlotObject(object):
+
+ def __init__(self):
+
+ '''
+ the plot destination
+ 0=top
+ 1=bottom
+ '''
+ self.destination=0
+
+ '''
+ self.vectors is a multidimensional array:
+ self.vectors[0]=plot1
+ self.vectors[1]=plot2
+ self.vectors[2]=plot3
+ etc.
+
+ 2 curves in a x,y plot are:
+ [[[x1],[y1]],[[x2],[y2]]]
+ for example:
+ x1 y1 x2 y2
+ [[[1,2,3,4],[10,20,30,40]],[[3,6,9,12],[30,60,90,120]]]
+ x1 = self.vectors[0][0]
+ y1 = self.vectors[0][1]
+ x2 = self.vectors[1][0]
+ y2 = self.vectors[1][1]
+ '''
+ self.vectors=[]
+
+ '''
+ self.units is simpler. for each plot with N axes (x,y,z...) only N labels
+ can be made, regardless of the number of superimposed plots
+ so units for the double plot above is: [unitx, unity]
+
+ units are strings
+ '''
+ self.units=['', '']
+
+ '''
+ xaxes and yaxes directions. 0, 0 means the common +X=right, +Y=top directions
+ '''
+ self.xaxes = 0
+ self.yaxes = 0
+
+ self.filename = ''
+ self.title = '' #title
+
+ '''
+ styles: defines what is the style of the current plots. If undefined or None, it is line plot.
+ If an element of the list is 'scatter', the corresponding dataset
+ is drawn with scattered points and not a continuous line.
+ '''
+ self.styles = []
+
+ '''
+ colors: define what is the colour of the current plots
+ '''
+ self.colors = []
+
+ def add_set(self, x, y):
+ '''
+ Adds an x, y data set to the vectors.
+ '''
+ self.vectors.append([])
+ self.vectors[-1].append(x)
+ self.vectors[-1].append(y)
+
+ def remove_set(self, whichset):
+ '''
+ Removes a set
+ '''
+ #TODO: do we need 'waste' here?
+ waste = self.vectors.pop(whichset)
+
+ def normalize_vectors(self):
+ '''
+ Trims the vector lengths as to be equal in a plot.
+ '''
+ for index in range(0,len(self.vectors)):
+ vectors_to_plot=self.vectors[index]
+ lengths=[len(vector) for vector in vectors_to_plot]
+ if min(lengths) != max(lengths):
+ for indexplot in range(0,len(vectors_to_plot)):
+ self.vectors[index][indexplot] = self.vectors[index][indexplot][0:min(lengths)]
+