Skip to content
Merged
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: 4 additions & 4 deletions docs/Parameters/Chromatogram.rst
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,10 @@ Chromatograms can be plotted using kind = chromatogram. In this plot, retention
Parameters
----------

.. csv-table::
:file: chromatogramPlot.tsv
:header-rows: 1
:delim: tab
.. docstring_to_table::
:docstring: pyopenms_viz._config.ChromatogramConfig
:parent_depth: 1
:default_docstring:

Example Usage
-------------
Expand Down
10 changes: 5 additions & 5 deletions docs/Parameters/Mobilogram.rst
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
Mobilogram
==========

Chromatograms can be plotted using kind = mobilogram. In this plot, ion mobility is on the x-axis and intensity is on the y-axis. The by parameter can be used to separate out different mass traces. Functionally these plots have very similar to chromatograms
Mobilograms are a type of plot used to visualize ion mobility data. In this plot, ion mobility is represented on the x-axis, while intensity is shown on the y-axis. The `by` parameter can be utilized to separate different mass traces. Functionally, mobilograms are similar to chromatograms.

Parameters
----------

.. csv-table::
:file: mobilogramPlot.tsv
:header-rows: 1
:delim: tab
.. docstring_to_table::
:docstring: pyopenms_viz._config.MobilogramConfig
:parent_depth: 1
:default_docstring:

Example Usage
-------------
Expand Down
10 changes: 6 additions & 4 deletions docs/Parameters/Parameters.rst
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,13 @@ Pyopenms-viz plotting occurs by calling the `.plot()` method on a pandas datafra

General Options include (mandatory fields are starred)

.. csv-table:: General Options
:file: basePlot.tsv
:header-rows: 1
:delim: tab
.. docstring_to_table::
:docstring: pyopenms_viz._config.BasePlotConfig
:title: Core Options

.. docstring_to_table::
:docstring: pyopenms_viz._config.LegendConfig
:title: Legend Options

Please click on a kind of plot below for more details on their specific parameters:

Expand Down
9 changes: 4 additions & 5 deletions docs/Parameters/PeakMap.rst
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,10 @@ Note: y_kind / x_kind is only relevant if add_marginals is set to True.
Parameters
----------

.. csv-table::
:file: peakMapPlot.tsv
:header-rows: 1
:delim: tab

.. docstring_to_table::
:docstring: pyopenms_viz._config.PeakMapConfig
:parent_depth: 1
:default_docstring:

Example Usage
-------------
Expand Down
9 changes: 4 additions & 5 deletions docs/Parameters/Spectrum.rst
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,10 @@ A spectrum can be plot using kind = "spectrum". In this plot, mass-to-charge rat
Parameters
----------

.. csv-table:: Chromatogram Options
:file: spectrumPlot.tsv
:header-rows: 1
:delim: tab

.. docstring_to_table::
:docstring: pyopenms_viz._config.SpectrumConfig
:parent_depth: 1
:default_docstring:

Example Usage
-------------
Expand Down
148 changes: 148 additions & 0 deletions docs/_ext/docstring_to_table.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,148 @@
from docutils.parsers.rst import Directive, directives
from docutils import nodes
import importlib
import inspect
import docstring_parser


DEFAULT_DOCSTRING = """
Default configuration for pyopenms_viz

Attributes:
x (str): The column name for the X-axis data. Required.
y (str): The column name for the Y-axis data. Required.
by (str): The column name for the grouping variable.
canvas (Any): Canvas for the plot. For Bokeh, this is a bokeh.plotting.Figure object. For Matplotlib, this is an Axes object, and for Plotly, this is a plotly.graph_objects.Figure object. If none, axis will be created Defaults to None.
show_plot (bool): Whether to display the plot. Defaults to True.
"""


class DocstringToTableDirective(Directive):
has_content = False
required_arguments = 0
optional_arguments = 0
option_spec = {
"docstring": str,
"title": str,
"parent_depth": int, # Number of parent classes to include
"default_docstring": directives.flag, # Flag, no argument required
}

def run(self):
docstring_path = self.options.get("docstring")
table_title = self.options.get("title")
# If parent_depth is not specified, only include the base class (depth=0)
parent_depth = self.options.get("parent_depth")
if parent_depth is None:
parent_depth = 0
else:
parent_depth = int(parent_depth)
if not docstring_path:
error = self.state_machine.reporter.error(
"No :docstring: option provided to docstring_to_table directive.",
line=self.lineno,
)
return [error]

# Split module and object
mod_name, _, obj_path = docstring_path.partition(".")
if not obj_path:
error = self.state_machine.reporter.error(
f"Invalid docstring path: {docstring_path}", line=self.lineno
)
return [error]

# Import module and get object
try:
mod = importlib.import_module(mod_name)
obj = mod
for attr in docstring_path.split(".")[1:]:
obj = getattr(obj, attr)
except Exception as e:
error = self.state_machine.reporter.error(
f"Could not import object '{docstring_path}': {e}", line=self.lineno
)
return [error]
Comment thread
jcharkow marked this conversation as resolved.

# Collect docstrings from parent classes up to parent_depth
docstrings = []
current_obj = obj
for i in range(parent_depth + 1):
docstring = inspect.getdoc(current_obj)
if docstring:
docstrings.append(docstring)
bases = getattr(current_obj, "__bases__", ())
if bases and i < parent_depth:
current_obj = bases[0]
else:
break

# Parse all collected docstrings
params = []
param_names = []
# If :default_docstring: is present (flag), prepend its params
if "default_docstring" in self.options:
default_parsed = docstring_parser.parse(DEFAULT_DOCSTRING)
for param in default_parsed.params:
name = param.arg_name or ""
default = param.default or ""
typ = param.type_name or ""
desc = param.description or ""
if not default:
name = f"{name}*"
params.append((name, typ, desc, default))
for docstring in reversed(docstrings): # Start from base class
parsed = docstring_parser.parse(docstring)
for param in parsed.params:
name = param.arg_name or ""
default = param.default or ""
typ = param.type_name or ""
desc = param.description or ""
# Mark required parameters (no default) with '*'
if not default:
name_out = f"{name}*"
else:
name_out = name
# Only keep the most "child" definition of each parameter
if name in param_names:
# Find and remove the old parameter from the list
# It could be with or without a star
for i, (p_name, _, _, _) in enumerate(params):
if p_name.strip("*") == name:
params.pop(i)
break
params.append((name_out, typ, desc, default))
if name not in param_names:
param_names.append(name)

# Build table
table = nodes.table()
if table_title:
title_node = nodes.title(text=table_title)
table += title_node
tgroup = nodes.tgroup(cols=4)
table += tgroup
for width in [1, 1, 3, 1]:
tgroup += nodes.colspec(colwidth=width)
thead = nodes.thead()
tgroup += thead
header_row = nodes.row()
for h in ["Parameter", "Type", "Description", "Default"]:
entry = nodes.entry()
entry += nodes.paragraph(text=h)
header_row += entry
thead += header_row
tbody = nodes.tbody()
tgroup += tbody
for param in params:
row = nodes.row()
for cell in param:
entry = nodes.entry()
entry += nodes.paragraph(text=cell)
row += entry
tbody += row
return [table]


def setup(app):
app.add_directive("docstring_to_table", DocstringToTableDirective)
2 changes: 2 additions & 0 deletions docs/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,7 @@ def find_git_directory(start_path):
# Add any Sphinx extension module names here, as strings. They can be
# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
# ones.
sys.path.insert(0, os.path.abspath(".")) # Add docs/ to path
extensions = [
"sphinx.ext.napoleon",
"sphinx.ext.autodoc",
Expand All @@ -99,6 +100,7 @@ def find_git_directory(start_path):
"sphinx_gallery.gen_gallery",
"bokeh.sphinxext.bokeh_plot",
"nbsphinx",
"docs._ext.docstring_to_table",
]

# Add any paths that contain templates here, relative to this directory.
Expand Down
2 changes: 2 additions & 0 deletions docs/requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,8 @@ defusedxml==0.7.1
# via
# cairosvg
# nbconvert
docstring-parser==0.17.0
# via pyopenms_viz (pyproject.toml)
docutils==0.21.2
# via
# nbsphinx
Expand Down
Loading
Loading