Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 7 additions & 1 deletion docs/_ext/custom_styles/example/example_experiment.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,13 @@ class DocumentedCurveAnalysis(CurveAnalysis):
In addition to above sections, analysis template provides following extra sections.

# section: fit_model
Here you can describe your fitting model.
Optional. Here you can describe your fitting model.
If you are documenting a CurveAnalysis subclass, Sphinx automatically generates
the fit model descriptions based on descriptions in the SeriesDef.
However you can still override this section.
If you want to provide the fit model description for other analysis classes,
please write this section.

Standard reStructuredText directives can be used. For example:

.. math::
Expand Down
3 changes: 1 addition & 2 deletions docs/_ext/custom_styles/formatter.py
Original file line number Diff line number Diff line change
Expand Up @@ -181,8 +181,7 @@ def format_fit_model(self, lines: List[str]) -> List[str]:
format_lines = [
".. rubric:: Fit Model",
"",
"This is the curve fitting analysis. ",
"Following equation(s) are used to represent curve(s).",
"Following fit models are used to represent the experimental result.",
"",
]
format_lines.extend(lines)
Expand Down
17 changes: 15 additions & 2 deletions docs/_ext/custom_styles/styles.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@

from qiskit_experiments.framework.base_analysis import BaseAnalysis
from qiskit_experiments.framework.base_experiment import BaseExperiment
from qiskit_experiments.curve_analysis import CurveAnalysis
from sphinx.config import Config as SphinxConfig

from .formatter import (
Expand All @@ -29,7 +30,11 @@
DocstringSectionFormatter,
)
from .section_parsers import load_standard_section, load_fit_parameters
from .utils import _generate_options_documentation, _format_default_options
from .utils import (
_generate_options_documentation,
_generate_fit_model_documentation,
_format_default_options,
)

section_regex = re.compile(r"# section: (?P<section_name>\S+)")

Expand Down Expand Up @@ -111,7 +116,8 @@ def add_new_section(section: str, lines: List[str]):
add_new_section(current_section, temp_lines)

for section, lines in self._extra_sections().items():
sectioned_docstrings[section] = lines
if section not in sectioned_docstrings:
sectioned_docstrings[section] = lines

return sectioned_docstrings

Expand Down Expand Up @@ -320,4 +326,11 @@ def _extra_sections(self) -> Dict[str, List[str]]:
if analysis_option:
parsed_sections["analysis_opts"] = analysis_option

# generate fit model from series definitions if curve analysis
if issubclass(self._target_cls, CurveAnalysis):
parsed_sections["fit_model"] = _generate_fit_model_documentation(
series_defs=self._target_cls.__series__,
indent=self._indent,
)

return parsed_sections
30 changes: 30 additions & 0 deletions docs/_ext/custom_styles/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@
from sphinx.ext.napoleon.docstring import GoogleDocstring
from sphinx.util.docstrings import prepare_docstring

from qiskit_experiments.curve_analysis import SeriesDef


def _trim_empty_lines(docstring_lines: List[str]) -> List[str]:
"""A helper function to remove redundant line feeds."""
Expand Down Expand Up @@ -123,6 +125,34 @@ def _generate_options_documentation(
return options_docstring_lines


def _generate_fit_model_documentation(series_defs: List[SeriesDef], indent: str = "") -> List[str]:
"""Automatically generate fit model documentation from the series definition."""
n_curves = len(series_defs)

fit_model_docstring_lines = []
for idx, series_def in enumerate(series_defs):
if series_def.model_description is None:
continue
if n_curves > 1:
fit_model_docstring_lines.extend([
f"- Fit model for the curve ``{series_def.name}``:",
""
])
math_block = [
".. math::",
"",
indent + f"F(x) = {series_def.model_description} \\tag{idx + 1}",
"",
]
fit_model_docstring_lines.extend(math_block)

fit_model_docstring_lines.append(
"The information about the fit model is also stored in the analysis result metadata."
)

return fit_model_docstring_lines


def _format_default_options(defaults: Dict[str, Any], indent: str = "") -> List[str]:
"""Format default options to docstring lines."""
docstring_lines = [
Expand Down
4 changes: 4 additions & 0 deletions docs/_static/gallery.css
Original file line number Diff line number Diff line change
Expand Up @@ -193,3 +193,7 @@ p.sphx-glr-signature a.reference.external {
a.sphx-glr-backref-instance {
text-decoration: none;
}

span.eqno {
float: right;
}
5 changes: 5 additions & 0 deletions qiskit_experiments/curve_analysis/curve_analysis.py
Original file line number Diff line number Diff line change
Expand Up @@ -867,6 +867,11 @@ def _run_analysis(
"""
result_data = CurveAnalysisResultData()
result_data["analysis_type"] = self.__class__.__name__

# add model description
result_data["fit_models"] = {
series_def.name: series_def.model_description for series_def in self.__series__
}
figures = list()

#
Expand Down
3 changes: 3 additions & 0 deletions qiskit_experiments/curve_analysis/curve_data.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,9 @@ class SeriesDef:
# Whether to plot fit uncertainty for this line.
plot_fit_uncertainty: bool = False

# Latex description of this fit model
model_description: str = "no description"


@dataclasses.dataclass(frozen=True)
class CurveData:
Expand Down
2 changes: 1 addition & 1 deletion qiskit_experiments/curve_analysis/fit_function.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ def sin(
.. math::
y = {\rm amp} \sin\left(2 \pi {\fm freq} x + {\rm phase}\right) + {\rm baseline}
"""
return amp * np.cos(2 * np.pi * freq * x + phase) + baseline
return amp * np.sin(2 * np.pi * freq * x + phase) + baseline


def exponential_decay(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ class DragCalAnalysis(CurveAnalysis):

.. math::

y = {\rm amp} \cos\left(2 \pi {\rm freq}_i x - 2 \pi {\rm beta}\right) + {\rm base}
y = {\rm amp} \cos\left(2 \pi {\rm freq}_i x - 2 \pi {\rm beta}\right) + b

Fit Parameters
- :math:`{\rm amp}`: Amplitude of all series.
Expand Down Expand Up @@ -65,6 +65,7 @@ class DragCalAnalysis(CurveAnalysis):
name="series-0",
filter_kwargs={"series": 0},
plot_symbol="o",
model_description=r"{\rm amp} \cos(2 \pi f_0 (x - beta)) + b",
),
SeriesDef(
fit_func=lambda x, amp, freq0, freq1, freq2, beta, base: cos(
Expand All @@ -74,6 +75,7 @@ class DragCalAnalysis(CurveAnalysis):
name="series-1",
filter_kwargs={"series": 1},
plot_symbol="^",
model_description=r"{\rm amp} \cos(2 \pi f_1 (x - beta)) + b",
),
SeriesDef(
fit_func=lambda x, amp, freq0, freq1, freq2, beta, base: cos(
Expand All @@ -83,6 +85,7 @@ class DragCalAnalysis(CurveAnalysis):
name="series-2",
filter_kwargs={"series": 2},
plot_symbol="v",
model_description=r"{\rm amp} \cos(2 \pi f_2 (x - beta)) + b",
),
]

Expand Down
Loading