OpenMPCD
LogicalEntityMeanSquareDisplacement.py
1 """
2 @package MPCDAnalysis.LogicalEntityMeanSquareDisplacement
3 
4 Analysis functionality for data on mean square displacement, as produced by
5 `OpenMPCD::CUDA::MPCFluid::Instrumentation::LogicalEntityMeanSquareDisplacement`.
6 """
7 
9  """
10  Analysis class for data on mean square displacement, as produced by
11  `OpenMPCD::CUDA::MPCFluid::Instrumentation::LogicalEntityMeanSquareDisplacement`.
12 
13  Unless specified otherwise, all times are measured in units of `measurement
14  time`, as defined in
15  `OpenMPCD::CUDA::MPCFluid::Instrumentation::LogicalEntityMeanSquareDisplacement`.
16 
17  @see OpenMPCD::CUDA::MPCFluid::Instrumentation::LogicalEntityMeanSquareDisplacement
18  """
19 
20  def __init__(self, rundirs):
21  """
22  The constructor.
23 
24  @throw TypeError
25  Throws if `rundir` is not a `str`, or a `list` of `str`.
26  @throw ValueError
27  Throws if the given `rundir` does not exist, or does not contain
28  a readable, valid data file.
29  @throw ValueError
30  Throws if `rundir` is an empty list.
31 
32  @param[in] rundirs
33  The run directory, as a `string`. From this directory, the
34  file `logicalEntityMeanSquareDisplacement.data` will be read
35  as input. If this file does not exist,
36  `logicalEntityMeanSquareDisplacement.data.xz` will be read
37  instead.
38  Alternatively, this can be a list of strings, each element
39  of which specifies a directory that is treated as described
40  above.
41  """
42 
43  if isinstance(rundirs, str):
44  rundirs = [rundirs]
45 
46  if not isinstance(rundirs, list):
47  raise TypeError()
48  for rundir in rundirs:
49  if not isinstance(rundir, str):
50  raise TypeError()
51  if len(rundirs) == 0:
52  raise ValueError()
53 
54 
55  self._measurements = []
56  self._statistics = {}
57  self._config = None
58 
59  from MPCDAnalysis.OnTheFlyStatisticsDDDA import OnTheFlyStatisticsDDDA
60 
61  for rundir in rundirs:
62  if not isinstance(rundir, str):
63  raise TypeError()
64 
65  filepath = rundir + "/" + "logicalEntityMeanSquareDisplacement.data"
66  filepathXZ = filepath + ".xz"
67 
68  import os.path
69  if not os.path.isfile(filepath) and not os.path.isfile(filepathXZ):
70  raise ValueError()
71 
72  from MPCDAnalysis.Configuration import Configuration
73  if self._config is None:
74  self._config = Configuration(rundir)
76  self._config[
77  "instrumentation." + \
78  "logicalEntityMeanSquareDisplacement." + \
79  "measurementArgumentCount"]
80 
81  for deltaT in range(1, self.getMaximumMeasurementTime() + 1):
82  self._statistics[deltaT] = OnTheFlyStatisticsDDDA()
83  else:
84  if not self._config.isEquivalent(Configuration(rundir)):
85  raise ValueError(
86  "Rundirs have incompatible configurations!")
87 
88  if os.path.isfile(filepath):
89  with open(filepath, "r") as f:
90  self._parse(f)
91  elif os.path.isfile(filepathXZ):
92  import lzma
93  f = lzma.LZMAFile(filepathXZ, "r")
94  self._parse(f)
95  else:
96  raise RuntimeError()
97 
98 
99  def getMaximumMeasurementTime(self):
100  """
101  Returns, in units of `measurement time`, the maximum correlation time
102  that was configured to be measured, i.e. \f$ N_A \f$.
103  """
104 
105  return self._measurementArgumentCount
106 
107 
108  def getMeanSquareDisplacement(self, deltaT):
109  """
110  Returns an `OnTheFlyStatisticsDDDA` object that holds information on the
111  sample of measured mean square displacements for time difference
112  `deltaT`.
113 
114  @throw TypeError
115  Throws if any of the arguments have invalid types.
116  @throw ValueError
117  Throws if any of the arguments have invalid values.
118 
119  @param[in] deltaT
120  The time difference to return results for, measured in
121  This argument is to be of type `int`, positive, and at
122  most `getMaximumMeasurementTime()`.
123  """
124 
125  if not isinstance(deltaT, int):
126  raise TypeError()
127  if deltaT <= 0:
128  raise ValueError()
129  if deltaT > self.getMaximumMeasurementTime():
130  raise ValueError()
131 
132  assert deltaT in self._statistics
133  return self._statistics[deltaT]
134 
135 
136  def fitToData(self, function = None, minTime = None, maxTime = None):
137  """
138  Fits the data to the given function, and returns the optimal function
139  parameters.
140 
141  @param[in] function
142  A function object suitable to be used as the first argument
143  to `scipy.optimize.curve_fit`, or `None`, in which case a
144  function of the form \f$ y\left(x\right) = p_1 x^{p_2} \f$
145  with parameters \f$ p_1 \f$ and \f$ p_2 \f$ is used.
146  @param[in] minTime
147  If not `None`, this value specifies the minimum value of the
148  measurement time that will be used for the fit.
149  @param[in] maxTime
150  If not `None`, this value specifies the maximum value of the
151  measurement time that will be used for the fit.
152  """
153 
154  import numpy
155  import scipy.optimize
156 
157  if minTime is None:
158  minTime = 1
159  if maxTime is None:
160  maxTime = self.getMaximumMeasurementTime() + 1
161 
162  times = []
163  values = []
164  for T in range(minTime, maxTime):
165  msd = self.getMeanSquareDisplacement(T)
166 
167  times.append(T)
168  values.append(msd.getSampleMean())
169 
170  if function is None:
171  function = lambda x, p1, p2: p1 * x ** p2
172 
173  times = numpy.array(times)
174  values = numpy.array(values)
175  fit = scipy.optimize.curve_fit(function, times, values)
176 
177  return fit[0]
178 
179 
180  def getMPLAxes(
181  self,
182  showEstimatedStandardDeviation = True,
183  lines = []):
184  """
185  Returns an `matplotlib.axes.Axes` object that plots the mean square
186  displacement against the diffusion time, in units of `measurement time`.
187 
188  @throw TypeError
189  Throws if any of the arguments have invalid types.
190  @throw ValueError
191  Throws if any of the arguments have invalid values.
192 
193  @param[in] showEstimatedStandardDeviation
194  Whether to show, for each data point, the estimated standard
195  deviation.
196  @param[in] lines
197  A list of lines to plot, in addition to the data. Each
198  element of this list represents a line and is a list
199  containing, in this order:
200  - A list containing `x` and `y` coordinates for the
201  starting point of the line,
202  - Likewise for the ending point.
203  """
204 
205  if not isinstance(showEstimatedStandardDeviation, bool):
206  raise TypeError()
207  if not isinstance(lines, list):
208  raise TypeError()
209 
210 
211  import matplotlib.figure
212 
213  figure = matplotlib.figure.Figure()
214  axes = figure.add_subplot(1, 1, 1)
215 
216  times = []
217  values = []
218  errorbars = []
219  for T in range(1, self.getMaximumMeasurementTime() + 1):
220  msd = self.getMeanSquareDisplacement(T)
221 
222  times.append(T)
223  values.append(msd.getSampleMean())
224  if showEstimatedStandardDeviation:
225  errorbars.append(
226  msd.getOptimalStandardErrorOfTheMean())
227 
228  if len(errorbars) == 0:
229  errorbars = None
230 
231 
232  axes.errorbar(times, values, yerr = errorbars)
233 
234  for line in lines:
235  x = [line[0][0], line[1][0]]
236  y = [line[0][1], line[1][1]]
237  axes.errorbar(x, y, yerr = None)
238 
239  axes.set_xlabel(r'Diffusion Time $ T $')
240  axes.set_ylabel(r'$ C(0, T) $')
241 
242  return axes
243 
244 
245  def _parse(self, f):
246  """
247  Parses the given file `f`.
248 
249  If a file has been parsed already, this new file is treated as if it
250  was a continuation of previously parsed runs. Hence, this file's first
251  measurement is treated as if it followed the last file's last
252  measurement.
253 
254  @param[in] f
255  The file to parse, of type `file` or `lzma.LZMAFile`.
256  """
257 
258  for line in f:
259  parts = line.split()
260  if len(parts) != 3:
261  raise ValueError()
262 
263  deltaT = int(parts[1])
264  msd = float(parts[2])
265 
266  self._statistics[deltaT].addDatum(msd)
MPCDAnalysis.LogicalEntityMeanSquareDisplacement.LogicalEntityMeanSquareDisplacement._statistics
_statistics
Definition: LogicalEntityMeanSquareDisplacement.py:59
MPCDAnalysis.LogicalEntityMeanSquareDisplacement.LogicalEntityMeanSquareDisplacement._parse
def _parse(self, f)
Definition: LogicalEntityMeanSquareDisplacement.py:264
MPCDAnalysis.LogicalEntityMeanSquareDisplacement.LogicalEntityMeanSquareDisplacement._config
_config
Definition: LogicalEntityMeanSquareDisplacement.py:60
MPCDAnalysis.LogicalEntityMeanSquareDisplacement.LogicalEntityMeanSquareDisplacement
Definition: LogicalEntityMeanSquareDisplacement.py:20
MPCDAnalysis.LogicalEntityMeanSquareDisplacement.LogicalEntityMeanSquareDisplacement.getMPLAxes
def getMPLAxes(self, showEstimatedStandardDeviation=True, lines=[])
Definition: LogicalEntityMeanSquareDisplacement.py:207
MPCDAnalysis.LogicalEntityMeanSquareDisplacement.LogicalEntityMeanSquareDisplacement.getMaximumMeasurementTime
def getMaximumMeasurementTime(self)
Definition: LogicalEntityMeanSquareDisplacement.py:107
MPCDAnalysis.LogicalEntityMeanSquareDisplacement.LogicalEntityMeanSquareDisplacement._measurementArgumentCount
_measurementArgumentCount
Definition: LogicalEntityMeanSquareDisplacement.py:78
MPCDAnalysis.LogicalEntityMeanSquareDisplacement.LogicalEntityMeanSquareDisplacement._measurements
_measurements
Definition: LogicalEntityMeanSquareDisplacement.py:58
MPCDAnalysis.LogicalEntityMeanSquareDisplacement.LogicalEntityMeanSquareDisplacement.fitToData
def fitToData(self, function=None, minTime=None, maxTime=None)
Definition: LogicalEntityMeanSquareDisplacement.py:158
MPCDAnalysis.LogicalEntityMeanSquareDisplacement.LogicalEntityMeanSquareDisplacement.__init__
def __init__(self, rundirs)
Definition: LogicalEntityMeanSquareDisplacement.py:44
MPCDAnalysis.LogicalEntityMeanSquareDisplacement.LogicalEntityMeanSquareDisplacement.getMeanSquareDisplacement
def getMeanSquareDisplacement(self, deltaT)
Definition: LogicalEntityMeanSquareDisplacement.py:128
MPCDAnalysis.Configuration
Definition: Configuration.py:1
MPCDAnalysis.OnTheFlyStatisticsDDDA
Definition: OnTheFlyStatisticsDDDA.py:1