1 # Copyright (C) 2010 W. Trevor King <wking@drexel.edu>
3 # This file is part of Hooke.
5 # Hooke is free software: you can redistribute it and/or
6 # modify it under the terms of the GNU Lesser General Public
7 # License as published by the Free Software Foundation, either
8 # version 3 of the License, or (at your option) any later version.
10 # Hooke is distributed in the hope that it will be useful,
11 # but WITHOUT ANY WARRANTY; without even the implied warranty of
12 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 # GNU Lesser General Public License for more details.
15 # You should have received a copy of the GNU Lesser General Public
16 # License along with Hooke. If not, see
17 # <http://www.gnu.org/licenses/>.
19 """The `curve` module provides :class:`Curve` and :class:`Data` for
27 class NotRecognized (ValueError):
28 def __init__(self, curve):
29 self.__setstate__(curve)
31 def __getstate__(self):
34 def __setstate__(self, data):
35 if isinstance(data, Curve):
36 msg = 'Not a recognizable curve format: %s' % data.path
37 super(NotRecognized, self).__init__(msg)
40 class Data (numpy.ndarray):
41 """Stores a single, continuous data set.
43 Adds :attr:`info` :class:`dict` to the standard :class:`numpy.ndarray`.
45 See :mod:`numpy.doc.subclassing` for the peculiarities of
46 subclassing :class:`numpy.ndarray`.
51 >>> d = Data(shape=(3,2), info={'columns':['distance (m)', 'force (N)']})
53 <class 'hooke.curve.Data'>
54 >>> for i in range(3): # initialize d
55 ... for j in range(2):
62 {'columns': ['distance (m)', 'force (N)']}
67 {'columns': ['distance (m)', 'force (N)']}
69 def __new__(subtype, shape, dtype=numpy.float, buffer=None, offset=0,
70 strides=None, order=None, info=None):
71 """Create the ndarray instance of our type, given the usual
72 input arguments. This will call the standard ndarray
73 constructor, but return an object of our type.
75 obj = numpy.ndarray.__new__(
76 subtype, shape, dtype, buffer, offset, strides, order)
77 # add the new attribute to the created instance
81 # Finally, we must return the newly created object:
84 def __array_finalize__(self, obj):
85 """Set any extra attributes from the original object when
86 creating a new view object."""
87 # reset the attribute from passed original object
88 self.info = getattr(obj, 'info', {})
89 # We do not need to return anything
93 """A grouped set of :class:`Data` runs from the same file with metadata.
95 For an approach/retract force spectroscopy experiment, the group
96 would consist of the approach data and the retract data. Metadata
97 would be the temperature, cantilever spring constant, etc.
99 Two important :attr:`info` settings are `filetype` and
100 `experiment`. These are two strings that can be used by Hooke
101 commands/plugins to understand what they are looking at.
103 * `.info['filetype']` should contain the name of the exact
104 filetype defined by the driver (so that filetype-speciofic
105 commands can know if they're dealing with the correct filetype).
106 * `.info['experiment']` should contain an instance of a
107 :class:`hooke.experiment.Experiment` subclass to identify the
108 experiment type. For example, various
109 :class:`hooke.driver.Driver`\s can read in force-clamp data, but
110 Hooke commands could like to know if they're looking at force
111 clamp data, regardless of their origin.
113 def __init__(self, path, info=None):
114 #the data dictionary contains: {name of data: list of data sets [{[x], [y]}]
121 self.name = os.path.basename(path)
123 def identify(self, drivers):
124 """Identify the appropriate :class:`hooke.driver.Driver` for
125 the curve file (`.path`).
127 for driver in drivers:
128 if driver.is_me(self.path):
129 self.driver = driver # remember the working driver
131 raise NotRecognized(self)
134 """Use the driver to read the curve into memory.
136 data,info = self.driver.read(self.path)
138 for key,value in info.items():
139 self.info[key] = value
142 """Release memory intensive :attr:`.data`.