# fit curve with x-values independent of the measurement data points
import numpy
import tables
from . import Drawable
[docs]
class FitResult(Drawable.Drawable):
"""
plottable fit curve belonging to a MeasurementResult
In contrast to MeasurementResult, the x-values are a plain array
and are independent of the measured data points, so a fit can be
sampled on a much denser x-grid for a smooth plot. The fit is
stored in the data pool under its own key, e.g. as a child of the
measurement ("Magnetization(tau)/fit"), and is drawn by the GUI
as an overlay on the measurement it belongs to.
"""
[docs]
def __init__(self, x, y, title=None, source=None, y_err=None, params=None):
"""
x: array-like of x-values (independent of the measurement)
y: array-like of y-values, same length as x
title: plot title of the fit
source: data pool key of the MeasurementResult this fit belongs to
y_err: optional array-like of y errors, same length as x
params: optional dictionary of fit parameters, shown in the plot
"""
Drawable.Drawable.__init__(self)
self.x = numpy.array(x, dtype="float64").reshape(-1)
self.y = [numpy.array(y, dtype="float64").reshape(-1)]
if y_err is not None:
self.y_err = numpy.array(y_err, dtype="float64").reshape(-1)
else:
self.y_err = None
self.title = title
self.source = source
self.params = dict(params) if params is not None else {}
def get_lineplotdata(self):
"""
x and y data for plotting the fit curve
"""
return [self.x, self.y[0]]
def uses_statistics(self):
"""
drawable interface method returns False
"""
return False
def write_to_hdf(self, hdffile, where, name, title, complib=None, complevel=None):
h5_table_format = {
"x": tables.Float64Col(),
"y": tables.Float64Col()
}
if self.y_err is not None:
h5_table_format["y_err"] = tables.Float64Col()
filter = None
if complib is not None:
if complevel is None:
complevel = 9
filter = tables.Filters(complevel=complevel, complib=complib, shuffle=1)
fit_table = hdffile.create_table(where=where, name=name,
description=h5_table_format,
title=title,
filters=filter,
expectedrows=self.x.shape[0])
fit_table.flavor = "numpy"
fit_table.attrs.damaris_type = "FitResult"
fit_table.attrs.quantity_name = self.get_title()
if self.xlabel is not None:
fit_table.attrs.xlabel = self.xlabel
if self.ylabel is not None:
fit_table.attrs.ylabel = self.ylabel
if self.source is not None:
fit_table.attrs.source = self.source
for (key, value) in self.params.items():
if isinstance(value, (int, float)) and not isinstance(value, bool):
fit_table.attrs.__setattr__("param_" + str(key), float(value))
else:
fit_table.attrs.__setattr__("param_" + str(key), str(value))
row = fit_table.row
has_y_err = self.y_err is not None
for i in range(self.x.shape[0]):
row["x"] = self.x[i]
row["y"] = self.y[0][i]
if has_y_err:
row["y_err"] = self.y_err[i]
row.append()
fit_table.flush()
def read_from_hdf(hdf_node):
"""
reads a FitResult object from the hdf_node
or None if the node is not suitable
"""
if not isinstance(hdf_node, tables.Table):
return None
if hdf_node._v_attrs.damaris_type != "FitResult":
return None
xdata = hdf_node.col("x")
ydata = hdf_node.col("y")
if "y_err" in hdf_node.colnames:
y_err = hdf_node.col("y_err")
else:
y_err = None
fr = FitResult(xdata, ydata,
title=getattr(hdf_node._v_attrs, "quantity_name", None),
source=getattr(hdf_node._v_attrs, "source", None),
y_err=y_err)
fr.xlabel = getattr(hdf_node._v_attrs, "xlabel", None)
fr.ylabel = getattr(hdf_node._v_attrs, "ylabel", None)
params = {}
for attr_name in hdf_node._v_attrs._f_list("all"):
if attr_name.startswith("param_"):
params[attr_name[6:]] = getattr(hdf_node._v_attrs, attr_name)
fr.params = params
return fr