Skip to content

Commit

Permalink
Fixed grammatical errors in docs (#1106)
Browse files Browse the repository at this point in the history
It will be nice if a native English speaker verifies that what I'm
indicating as errors are really errors, and spot additional ones that
I've missed.

---------

Co-authored-by: Helena Zhang <[email protected]>
  • Loading branch information
yaelbh and coruscating authored Mar 28, 2023
1 parent d04d99e commit ea3892b
Showing 1 changed file with 45 additions and 47 deletions.
92 changes: 45 additions & 47 deletions docs/tutorials/curve_analysis.rst
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,11 @@ Curve Analysis: Fitting your data
For most experiments, we are interested in fitting our results to a pre-defined
mathematical model.
The Curve Analysis module provides the analysis base class for a variety of experiments with
a single experimental parameter sweep. This analysis subclasses can override
a single experimental parameter sweep. Analysis subclasses can override
several class attributes to customize the behavior from data processing to post-processing,
including providing systematic initial guess for parameters tailored to the experiment.
including providing systematic initial guesses for parameters tailored to the experiment.
Here we describe how the Curve Analysis module works and how you can create new
analyses that inherits from the base class.
analyses that inherit from the base class.


.. _curve_analysis_overview:
Expand All @@ -23,7 +23,7 @@ different sets of experiment results. A single experiment can define sub-experim
consisting of multiple circuits which are tagged with common metadata,
and curve analysis sorts the experiment results based on the circuit metadata.

This is an example of showing the abstract data structure of typical curve analysis experiment:
This is an example of showing the abstract data structure of a typical curve analysis experiment:

.. jupyter-input::
:emphasize-lines: 1,10,19
Expand Down Expand Up @@ -51,7 +51,7 @@ This is an example of showing the abstract data structure of typical curve analy
- "series_B": y_B = f_B(x_B; p0, p1, p2)
- fixed parameters {p1: v}

Here the experiment runs two subset of experiments, namely, series A and series B.
Here the experiment runs two subsets of experiments, namely, series A and series B.
The analysis defines corresponding fit models :math:`f_A(x_A)` and :math:`f_B(x_B)`.
Data extraction function in the analysis creates two datasets, :math:`(x_A, y_A)`
for the series A and :math:`(x_B, y_B)` for the series B, from the experiment data.
Expand All @@ -74,22 +74,22 @@ This objective function can be described by two fit functions as follows.
The solver conducts the least square curve fitting against this objective function
and returns the estimated parameters :math:`\Theta_{\mbox{opt}}`
that minimizes the reduced chi-squared value.
that minimize the reduced chi-squared value.
The parameters to be evaluated are :math:`\Theta = \Theta_{\rm fit} \cup \Theta_{\rm fix}`,
where :math:`\Theta_{\rm fit} = \theta_A \cup \theta_B`.
Since series A and B share the parameters in this example, :math:`\Theta_{\rm fit} = \{p_0, p_2\}`,
and the fixed parameters are :math:`\Theta_{\rm fix} = \{ p_1 \}` as mentioned.
Thus, :math:`\Theta = \{ p_0, p_1, p_2 \}`.

Experiment for each series can perform individual parameter sweep for :math:`x_A` and
:math:`x_B`, and experiment data yield outcomes :math:`y_A` and :math:`y_B`, which might
be different size. Data processing function may also compute :math:`\sigma_A` and
:math:`\sigma_B` which are the uncertainty of outcomes arising from the sampling error
:math:`x_B`, and experiment data yields outcomes :math:`y_A` and :math:`y_B`, which might
be of different size. Data processing functions may also compute :math:`\sigma_A` and
:math:`\sigma_B`, which are the uncertainty of outcomes arising from the sampling error
or measurement error.

More specifically, the curve analysis defines following data model.
More specifically, the curve analysis defines the following data model.

- Model: Definition of a single curve that is a function of reserved parameter "x".
- Model: Definition of a single curve that is a function of a reserved parameter "x".

- Group: List of models. Fit functions defined under the same group must share the
fit parameters. Fit functions in the group are simultaneously fit to
Expand All @@ -98,11 +98,11 @@ More specifically, the curve analysis defines following data model.
Once the group is assigned, a curve analysis instance builds
a proper internal optimization routine.
Finally, the analysis outputs a set of :class:`.AnalysisResultData` entries
for important fit outcomes along with a single Matplotlib figure of the fit curves
for important fit outcomes along with a single figure of the fit curves
with the measured data points.

With this baseclass, a developer can avoid writing boilerplate code in
various curve analyses subclass and can quickly write up
With this base class, a developer can avoid writing boilerplate code in
various curve analyses subclasses and can quickly write up
the analysis code for a particular experiment.


Expand All @@ -112,7 +112,7 @@ Defining new models
-------------------

The fit model is defined by the `LMFIT`_ ``Model``. If you are familiar with this
package, you can skip this section. The LMFIT package manages complicated fit function
package, you can skip this section. The LMFIT package manages complicated fit functions
and offers several algorithms to solve non-linear least-square problems. Curve Analysis
delegates the core fitting functionality to this package.

Expand Down Expand Up @@ -147,13 +147,13 @@ Alternatively, you can take a callable to define the model object.

See the `LMFIT`_ documentation for detailed user guide. They also provide preset models.

If the :class:`.CurveAnalysis` is instantiated with multiple models,
If the :class:`.CurveAnalysis` object is instantiated with multiple models,
it internally builds a cost function to simultaneously minimize the residuals of
all fit functions.
The names of the parameters in the fit function are important since they are used
in the analysis result, and potentially in your experiment database as a fit result.

Here is another example how to implement multi-objective optimization task:
Here is another example on how to implement a multi-objective optimization task:

.. jupyter-input::

Expand Down Expand Up @@ -188,7 +188,7 @@ the exponential decay function.
Here one should expect the experiment data will have two classes of data with metadata
``"tag": 1`` and ``"tag": 2`` for ``my_experiment1`` and ``my_experiment2``, respectively.

By using this model, one can flexibly set up your fit model. Here is another example:
By using this model, you can flexibly set up your fit model. Here is another example:

.. jupyter-input::

Expand All @@ -205,7 +205,7 @@ By using this model, one can flexibly set up your fit model. Here is another exa
),
]

You have the same set of fit parameters in two models, but now you fit two datasets
You have the same set of fit parameters in the two models, but now you fit two datasets
with different trigonometric functions.

.. _LMFIT: https://lmfit.github.io/lmfit-py/intro.html
Expand Down Expand Up @@ -273,19 +273,19 @@ This workflow is defined in the method :meth:`CurveAnalysis._run_analysis`.
^^^^^^^^^^^^^^^^^

Curve analysis calls the :meth:`_initialization` method, where it initializes
some internal states and optionally populate analysis options
some internal states and optionally populates analysis options
with the input experiment data.
In some case it may train the data processor with fresh outcomes,
In some cases it may train the data processor with fresh outcomes,
or dynamically generate the fit models (``self._models``) with fresh analysis options.
A developer can override this method to perform initialization of analysis-specific variables.

2. Data processing
^^^^^^^^^^^^^^^^^^

Curve analysis calls :meth:`_run_data_processing` method where
Curve analysis calls the :meth:`_run_data_processing` method, where
the data processor in the analysis option is internally called.
This consumes input experiment results and creates :class:`.CurveData` dataclass.
Then :meth:`_format_data` method is called with the processed dataset to format it.
This consumes input experiment results and creates the :class:`.CurveData` dataclass.
Then the :meth:`_format_data` method is called with the processed dataset to format it.
By default, the formatter takes average of the outcomes in the processed dataset
over the same x values, followed by the sorting in the ascending order of x values.
This allows the analysis to easily estimate the slope of the curves to
Expand All @@ -296,50 +296,48 @@ or elimination of outliers for better fitting.
3. Fitting
^^^^^^^^^^

Curve analysis calls :meth:`_run_curve_fit` method which is the core functionality of the fitting.
The another method :meth:`_generate_fit_guesses` is internally called to
Curve analysis calls the :meth:`_run_curve_fit` method, which is the core functionality of the fitting.
Another method :meth:`_generate_fit_guesses` is internally called to
prepare the initial guess and parameter boundary with respect to the formatted data.
A developer usually override this method to provide better initial guess
Developers usually override this method to provide better initial guesses
tailored to the defined fit model or type of the associated experiment.
See :ref:`curve_analysis_init_guess` for more details.
A developer can also override the entire :meth:`_run_curve_fit` method to apply
custom fitting algorithms. This method must return :class:`.CurveFitResult` dataclass.
Developers can also override the entire :meth:`_run_curve_fit` method to apply
custom fitting algorithms. This method must return a :class:`.CurveFitResult` dataclass.

4. Post processing
^^^^^^^^^^^^^^^^^^

Curve analysis runs several postprocessing against to the fit outcome.
It calls :meth:`._create_analysis_results` to create :class:`.AnalysisResultData` class
for the fitting parameters of interest. A developer can inject a custom code to
Curve analysis runs several postprocessing against the fit outcome.
It calls :meth:`._create_analysis_results` to create the :class:`.AnalysisResultData` class
for the fitting parameters of interest. A developer can inject custom code to
compute custom quantities based on the raw fit parameters.
See :ref:`curve_analysis_results` for details.
Afterwards, the analysis draws several curves in the Matplotlib figure.
Users can set a custom plotter in :class:`.CurveAnalysis` classes, to customize
figures, by setting the :attr:`~.CurveAnalysis.plotter` attribute.
Finally, it returns the list of created analysis results and Matplotlib figure.
Afterwards, figure plotting is handed over to the :doc:`Visualization </tutorials/visualization>` module via
the :attr:`~.CurveAnalysis.plotter` attribute, and a list of created analysis results and the figure are returned.


.. _curve_analysis_init_guess:

Providing initial guesses
-------------------------

Fitting without initial guesses for parameters often results in a bad fit. User can
Fitting without initial guesses for parameters often results in a bad fit. Users can
provide initial guesses and boundaries for the fit parameters through analysis options
``p0`` and ``bounds``. These values are the dictionary keyed on the parameter name, and
one can get the list of parameters with the :attr:`CurveAnalysis.parameters`. Each
boundary value can be a tuple of float representing min and max value.
boundary value can be a tuple of floats representing minimum and maximum values.

Apart from user provided guesses, the analysis can systematically generate those values
with the method :meth:`_generate_fit_guesses` which is called with :class:`CurveData`
dataclass. If the analysis contains multiple models definitions, we can get the subset
of curve data with :meth:`.CurveData.get_subset_of` with the name of the series. A
with the method :meth:`_generate_fit_guesses`, which is called with the :class:`CurveData`
dataclass. If the analysis contains multiple model definitions, we can get the subset
of curve data with :meth:`.CurveData.get_subset_of` using the name of the series. A
developer can implement the algorithm to generate initial guesses and boundaries by
using this curve data object, which will be provided to the fitter. Note that there are
several common initial guess estimators available in :mod:`curve_analysis.guess`.

The :meth:`_generate_fit_guesses` also receives the :class:`.FitOptions` instance
``user_opt``, which contains user provided guesses and boundaries. This is
``user_opt``, which contains user provided guesses and boundaries. This is a
dictionary-like object consisting of sub-dictionaries for initial guess ``.p0``,
boundary ``.bounds``, and extra options for the fitter. See the API
documentation for available options.
Expand All @@ -366,7 +364,7 @@ Here you created two options with different ``p1`` values. If multiple options a
returned like this, the :meth:`_run_curve_fit` method attempts to fit with all provided
options and finds the best outcome with the minimum reduced chi-square value. When the
fit model contains some parameter that cannot be easily estimated from the curve data,
you can create multiple options with varying the initial guess to let the fitter find
you can create multiple options by varying the initial guess to let the fitter find
the most reasonable parameters to explain the model. This allows you to avoid analysis
failure with the poor initial guesses.

Expand Down Expand Up @@ -409,7 +407,7 @@ Here the first argument ``p0`` is the target parameter defined in the series def
``amp`` is the representation of ``p0`` in the result entry,
and ``Hz`` is the optional string for the unit of the value if available.

Not only returning the fit parameters, you can also compute new quantities
In addition to returning the fit parameters, you can also compute new quantities
by combining multiple fit parameters.
This can be done by overriding the :meth:`_create_analysis_results` method.

Expand All @@ -434,14 +432,14 @@ This can be done by overriding the :meth:`_create_analysis_results` method.

return outcomes

Note that both ``p0`` and ``p1`` are `UFloat`_ object consisting of
Note that both ``p0`` and ``p1`` are `UFloat`_ objects consisting of
a nominal value and an error value which assumes the standard deviation.
Since this object natively supports error propagation,
you don't need to manually recompute the error of new value.
you don't have to manually recompute the error of the new value.

.. _ufloat: https://pythonhosted.org/uncertainties/user_guide.html

See also
--------

API documentation: :doc:`Curve Analysis Module </apidocs/curve_analysis>`
API documentation: :doc:`Curve Analysis Module </apidocs/curve_analysis>`

0 comments on commit ea3892b

Please sign in to comment.