Top

figure module

Figure creation subpackage.

This subpackage is in beta.

Use this subpackage to create publication quality figures with matplotlib from fits generated with scipy_data_fitting.

This subpackage works independently from scipy_data_fitting: it only assumes json fit files formatted according to scipy_data_fitting.Fit.to_json with meta=fit.metadata.

Use Fit to load fits saved as json files into a Fit object. Create a matplotlib.figure and manage subplots with Plot.

"""
**Figure creation subpackage.**

_This subpackage is in beta._

Use this subpackage to create publication quality figures
with [matplotlib][1] from fits generated with [`scipy_data_fitting`][2].

This subpackage works independently from [`scipy_data_fitting`][2]:
it only assumes json fit files formatted according to
[`scipy_data_fitting.Fit.to_json`][3] with [`meta=fit.metadata`][4].

Use `figure.Fit` to load fits saved as json files into a `figure.Fit` object.
Create a [`matplotlib.figure`][5] and manage subplots with `figure.Plot`.

[1]: http://matplotlib.org/
[2]: https://pythonhosted.org/scipy-data_fitting/
[3]: https://pythonhosted.org/scipy-data_fitting/#scipy_data_fitting.Fit.to_json
[4]: https://pythonhosted.org/scipy-data_fitting/#scipy_data_fitting.Fit.metadata
[5]: http://matplotlib.org/api/figure_api.html
"""

from .fit import Fit
from .plot import Plot

__all__ = ['Fit', 'Plot']

Classes

class Fit

Loads a fit from a json file into a Fit object.

class Fit:
    """
    Loads a fit from a json file into a `figure.Fit` object.
    """

    def __init__(self, path=None):
        self.path = path
        """
        Path to the json file containing fit to load.
        """

    @property
    def path(self):
        return self._path

    @path.setter
    def path(self, value):
        self._path = value

    @property
    def data(self):
        """
        Data points as a [`numpy.ndarray`][1] in the form

            #!python
            [
                [ x1, x2, x3, ... ],
                [ y1, y2, y3, ...]
            ]

        [1]: http://docs.scipy.org/doc/numpy/reference/generated/numpy.ndarray.html
        """
        if not hasattr(self, '_data'): self._load()
        return self._data

    @data.setter
    def data(self, value):
        self._data = value

    @property
    def fit(self):
        """
        Fit points as a [`numpy.ndarray`][1] in the form

            #!python
            [
                [ x1, x2, x3, ... ],
                [ y1, y2, y3, ...]
            ]

        [1]: http://docs.scipy.org/doc/numpy/reference/generated/numpy.ndarray.html
        """
        if not hasattr(self, '_fit'): self._load()
        return self._fit

    @fit.setter
    def fit(self, value):
        self._fit = value

    @property
    def meta(self):
        """
        A dictionary of metadata related to the fit.
        """
        if not hasattr(self, '_meta'): self._load()
        return self._meta

    @meta.setter
    def meta(self, value):
        self._meta = value

    @property
    def maps(self):
        """
        A dictionary of dictionaries.
        Each dictionary defines a map which is used to extend the metadata.

        The precise way maps interact with the metadata is defined by `figure.fit._extend_meta`.
        That method should be redefined or extended to suit specific use cases.
        """
        if not hasattr(self, '_maps'):
            maps = {}
            maps['tex_symbol'] = {}
            maps['siunitx'] = {}
            maps['value_transforms'] = {
                '__default__': lambda x: round(x, 2),
            }
            self._maps = maps
        return self._maps

    @maps.setter
    def maps(self, value):
        self._maps = value

    def _load(self):
        if not self.path: raise RuntimeError('Must specify path to load fit from file.')
        raw = json.load(open(self.path))

        self.data = numpy.array(raw['data']).T
        self.fit = numpy.array(raw['fit']).T

        if 'meta' in raw:
            self.meta = raw['meta']
        else:
            self.meta = {}
        for key in self.meta: self._extend_meta(self.meta[key])

    def _extend_meta(self, meta):
        if isinstance(meta, str): return None
        if isinstance(meta, dict): meta = [meta]
        for item in meta:
            if 'name' in item: key = item['name']
            if 'symbol' in item: key = item['symbol']

            if 'value' in item:
                item['disply_value'] = str(self._value_transform(key)(item['value']))

            item['tex_symbol'] = self._get_tex_symbol(key)

            if 'units' in item:
                item['siunitx'] = self._get_siunitx(item['units'])
            else:
                item['siunitx'] = ''

    def _get_siunitx(self, key):
        table = self.maps['siunitx']
        if key in table: return table[key]
        return ''

    def _get_tex_symbol(self, key):
        table = self.maps['tex_symbol']
        if key in table: return table[key]
        return key

    def _value_transform(self, key):
        table = self.maps['value_transforms']
        if key in table:
            return table[key]
        else:
            return table['__default__']

Ancestors (in MRO)

  • Fit
  • builtins.object

Static methods

def __init__(

self, path=None)

Initialize self. See help(type(self)) for accurate signature.

def __init__(self, path=None):
    self.path = path
    """
    Path to the json file containing fit to load.
    """

Instance variables

var data

Data points as a numpy.ndarray in the form

[
    [ x1, x2, x3, ... ],
    [ y1, y2, y3, ...]
]

var fit

Fit points as a numpy.ndarray in the form

[
    [ x1, x2, x3, ... ],
    [ y1, y2, y3, ...]
]

var maps

A dictionary of dictionaries. Each dictionary defines a map which is used to extend the metadata.

The precise way maps interact with the metadata is defined by figure.fit._extend_meta. That method should be redefined or extended to suit specific use cases.

var meta

A dictionary of metadata related to the fit.

var path

Path to the json file containing fit to load.

class Plot

Use a Plot object to create matplotlib plots from Fit objects.

Example:

>>> figure = Plot.new_figure()
>>> fit = Fit(path='fit.json')
>>> plot = Plot(fit=fit, plt=figure.add_subplot(111))
>>> plot.plot_data()
>>> plot.plot_fit()
>>> figure.savefig(figure.svg)
>>> Plot.close_figure(figure)
class Plot():
    """
    Use a `figure.Plot` object to create matplotlib plots
    from `figure.Fit` objects.

    Example:

        #!python
        >>> figure = Plot.new_figure()
        >>> fit = Fit(path='fit.json')
        >>> plot = Plot(fit=fit, plt=figure.add_subplot(111))
        >>> plot.plot_data()
        >>> plot.plot_fit()
        >>> figure.savefig(figure.svg)
        >>> Plot.close_figure(figure)
    """

    def __init__(self, fit=None, plt=None):
        self.fit = fit
        """
        The `figure.Fit` object to associate with this plot.
        """

        self.plt = plt
        """
        The matplotlib subplot associated with this plot.

        Assign the object returned by [`matplotlib.figure.Figure.add_subplot`][1] to this property.

        [1]: http://matplotlib.org/api/figure_api.html#matplotlib.figure.Figure.add_subplot
        """

    @property
    def fit(self):
        return self._fit

    @fit.setter
    def fit(self, value):
        self._fit = value

    @property
    def plt(self):
        return self._plt

    @plt.setter
    def plt(self, value):
        self._plt = value

    @property
    def options(self):
        """
        Dictionary of options which affect the plot style.

        Must contain the keys `data` and `fit` whose values are dictionaries.

        Options given in `data` and `fit` are passed as keyword arguments
        to [`matplotlib.pyplot.plot`][1] for the corresponding plot.

        Default:

            #!python
            {
                'data': {'marker': '.', 'linestyle': 'None'},
                'fit': {},
            }

        [1]: http://matplotlib.org/api/pyplot_api.html#matplotlib.pyplot.plot
        """
        if not hasattr(self, '_options'):
            self._options = {
                'data': {'marker': '.', 'linestyle': 'None'},
                'fit': {},
            }
        return self._options

    @options.setter
    def options(self, value):
        self._options = value

    def plot_data(self):
        """
        Add the data points to the plot.
        """
        self.plt.plot(*self.fit.data, **self.options['data'])

    def plot_fit(self):
        """
        Add the fit to the plot.
        """
        self.plt.plot(*self.fit.fit, **self.options['fit'])

    def add_xlabel(self, text=None):
        """
        Add a label to the x-axis.
        """
        x = self.fit.meta['independent']
        if not text:
            text = '$' + x['tex_symbol'] + r'$ $(\si{' + x['siunitx'] +  r'})$'
        self.plt.set_xlabel(text)

    def add_ylabel(self, text=None):
        """
        Add a label to the y-axis.
        """
        y = self.fit.meta['dependent']
        if not text:
            text = '$' + y['tex_symbol'] + r'$ $(\si{' + y['siunitx'] +  r'})$'
        self.plt.set_ylabel(text)

    def add_text_table(self, rows, r0, dr, **kwargs):
        """
        Add text to a plot in a grid fashion.

        `rows` is a list of lists (the rows).
        Each row contains the columns,
        each column is text to add to the plot.

        `r0` is a tuple `(x, y)` that positions the initial text.

        `dr` is a tuple `(dx, dy)` that determines the column and row spacing.

        Any keyword arguments will be passed to `matplotlib.pyplot.text`.

        Example:

            #!python
            >>> rows = [ ['a', '=', '1'], ['b', '=', '2'] ]
            >>> self.add_text_table(rows, (0.1, 0.9), (0.1, -0.1),
                    horizontalalignment='left',
                    verticalalignment='top')

        [1]: http://matplotlib.org/api/pyplot_api.html#matplotlib.pyplot.text
        """
        for m, row in enumerate(rows):
            for n, column in enumerate(row):
                self.plt.text(r0[0] + dr[0] * n, r0[1] + dr[1] * m, column,
                    transform=self.plt.axes.transAxes, **kwargs)

    @staticmethod
    def new_figure(**kwargs):
        """
        Returns a new [`matplotlib.figure.Figure`][1] object.
        Keyword arguments are passed to [`matplotlib.pyplot.figure`][2].

        [1]: http://matplotlib.org/api/figure_api.html#matplotlib.figure.Figure
        [2]: http://matplotlib.org/api/pyplot_api.html#matplotlib.pyplot.figure
        """
        return matplotlib.pyplot.figure(**kwargs)

    @staticmethod
    def close_figure(figure):
        """
        Closes a [`matplotlib.figure.Figure`][1] object
        with [`matplotlib.pyplot.close`][2].

        [1]: http://matplotlib.org/api/pyplot_api.html#matplotlib.pyplot.close
        """
        return matplotlib.pyplot.close(figure)

    @staticmethod
    def parameter_table(parameters):
        """
        Create
        """
        if not isinstance(parameters, list): parameters = [parameters]
        rows = []
        for param in parameters:
            row = []
            row.append('$' + param['tex_symbol'] + '$')
            row.append('$=$')
            row.append(r'$\SI{' + param['disply_value'] + '}{' + param['siunitx'] + '}$')
            rows.append(row)
        return rows

Ancestors (in MRO)

  • Plot
  • builtins.object

Static methods

def __init__(

self, fit=None, plt=None)

Initialize self. See help(type(self)) for accurate signature.

def __init__(self, fit=None, plt=None):
    self.fit = fit
    """
    The `figure.Fit` object to associate with this plot.
    """
    self.plt = plt
    """
    The matplotlib subplot associated with this plot.
    Assign the object returned by [`matplotlib.figure.Figure.add_subplot`][1] to this property.
    [1]: http://matplotlib.org/api/figure_api.html#matplotlib.figure.Figure.add_subplot
    """

def add_text_table(

self, rows, r0, dr, **kwargs)

Add text to a plot in a grid fashion.

rows is a list of lists (the rows). Each row contains the columns, each column is text to add to the plot.

r0 is a tuple (x, y) that positions the initial text.

dr is a tuple (dx, dy) that determines the column and row spacing.

Any keyword arguments will be passed to matplotlib.pyplot.text.

Example:

>>> rows = [ ['a', '=', '1'], ['b', '=', '2'] ]
>>> self.add_text_table(rows, (0.1, 0.9), (0.1, -0.1),
        horizontalalignment='left',
        verticalalignment='top')
def add_text_table(self, rows, r0, dr, **kwargs):
    """
    Add text to a plot in a grid fashion.
    `rows` is a list of lists (the rows).
    Each row contains the columns,
    each column is text to add to the plot.
    `r0` is a tuple `(x, y)` that positions the initial text.
    `dr` is a tuple `(dx, dy)` that determines the column and row spacing.
    Any keyword arguments will be passed to `matplotlib.pyplot.text`.
    Example:
        #!python
        >>> rows = [ ['a', '=', '1'], ['b', '=', '2'] ]
        >>> self.add_text_table(rows, (0.1, 0.9), (0.1, -0.1),
                horizontalalignment='left',
                verticalalignment='top')
    [1]: http://matplotlib.org/api/pyplot_api.html#matplotlib.pyplot.text
    """
    for m, row in enumerate(rows):
        for n, column in enumerate(row):
            self.plt.text(r0[0] + dr[0] * n, r0[1] + dr[1] * m, column,
                transform=self.plt.axes.transAxes, **kwargs)

def add_xlabel(

self, text=None)

Add a label to the x-axis.

def add_xlabel(self, text=None):
    """
    Add a label to the x-axis.
    """
    x = self.fit.meta['independent']
    if not text:
        text = '$' + x['tex_symbol'] + r'$ $(\si{' + x['siunitx'] +  r'})$'
    self.plt.set_xlabel(text)

def add_ylabel(

self, text=None)

Add a label to the y-axis.

def add_ylabel(self, text=None):
    """
    Add a label to the y-axis.
    """
    y = self.fit.meta['dependent']
    if not text:
        text = '$' + y['tex_symbol'] + r'$ $(\si{' + y['siunitx'] +  r'})$'
    self.plt.set_ylabel(text)

def close_figure(

figure)

Closes a matplotlib.figure.Figure object with [matplotlib.pyplot.close][2].

@staticmethod
def close_figure(figure):
    """
    Closes a [`matplotlib.figure.Figure`][1] object
    with [`matplotlib.pyplot.close`][2].
    [1]: http://matplotlib.org/api/pyplot_api.html#matplotlib.pyplot.close
    """
    return matplotlib.pyplot.close(figure)

def new_figure(

**kwargs)

Returns a new matplotlib.figure.Figure object. Keyword arguments are passed to matplotlib.pyplot.figure.

@staticmethod
def new_figure(**kwargs):
    """
    Returns a new [`matplotlib.figure.Figure`][1] object.
    Keyword arguments are passed to [`matplotlib.pyplot.figure`][2].
    [1]: http://matplotlib.org/api/figure_api.html#matplotlib.figure.Figure
    [2]: http://matplotlib.org/api/pyplot_api.html#matplotlib.pyplot.figure
    """
    return matplotlib.pyplot.figure(**kwargs)

def parameter_table(

parameters)

Create

@staticmethod
def parameter_table(parameters):
    """
    Create
    """
    if not isinstance(parameters, list): parameters = [parameters]
    rows = []
    for param in parameters:
        row = []
        row.append('$' + param['tex_symbol'] + '$')
        row.append('$=$')
        row.append(r'$\SI{' + param['disply_value'] + '}{' + param['siunitx'] + '}$')
        rows.append(row)
    return rows

def plot_data(

self)

Add the data points to the plot.

def plot_data(self):
    """
    Add the data points to the plot.
    """
    self.plt.plot(*self.fit.data, **self.options['data'])

def plot_fit(

self)

Add the fit to the plot.

def plot_fit(self):
    """
    Add the fit to the plot.
    """
    self.plt.plot(*self.fit.fit, **self.options['fit'])

Instance variables

var fit

The Fit object to associate with this plot.

var options

Dictionary of options which affect the plot style.

Must contain the keys data and fit whose values are dictionaries.

Options given in data and fit are passed as keyword arguments to matplotlib.pyplot.plot for the corresponding plot.

Default:

{
    'data': {'marker': '.', 'linestyle': 'None'},
    'fit': {},
}

var plt

The matplotlib subplot associated with this plot.

Assign the object returned by matplotlib.figure.Figure.add_subplot to this property.