Skip to content

Commit 217f60f

Browse files
committed
Adds docstrings for improved code documentation
1 parent 9fd997d commit 217f60f

File tree

18 files changed

+246
-30
lines changed

18 files changed

+246
-30
lines changed

src/easydiffraction/analysis/calculators/pdffit.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,8 @@
1+
"""PDF calculation backend using diffpy.pdffit2 if available.
2+
3+
The class adapts the engine to EasyDiffraction calculator interface and
4+
silences stdio on import to avoid noisy output in notebooks and logs.
5+
"""
16
# SPDX-FileCopyrightText: 2021-2025 EasyDiffraction contributors <https://github.com/easyscience/diffraction>
27
# SPDX-License-Identifier: BSD-3-Clause
38

src/easydiffraction/analysis/categories/aliases.py

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,8 @@
1+
"""Alias category for mapping friendly names to parameter UIDs.
2+
3+
Defines a small record type used by analysis configuration to refer to
4+
parameters via readable labels instead of raw unique identifiers.
5+
"""
16
# SPDX-FileCopyrightText: 2021-2025 EasyDiffraction contributors <https://github.com/easyscience/diffraction>
27
# SPDX-License-Identifier: BSD-3-Clause
38

@@ -11,6 +16,17 @@
1116

1217

1318
class Alias(CategoryItem):
19+
"""Single alias entry.
20+
21+
Maps a human-readable ``label`` to a concrete ``param_uid`` used by
22+
the engine.
23+
24+
Args:
25+
label: Alias label. Must match ``^[A-Za-z_][A-Za-z0-9_]*$``.
26+
param_uid: Target parameter uid. Same identifier pattern as
27+
``label``.
28+
"""
29+
1430
def __init__(
1531
self,
1632
*,
@@ -57,21 +73,36 @@ def __init__(
5773

5874
@property
5975
def label(self):
76+
"""Alias label descriptor."""
6077
return self._label
6178

6279
@label.setter
6380
def label(self, value):
81+
"""Set alias label.
82+
83+
Args:
84+
value: New label.
85+
"""
6486
self._label.value = value
6587

6688
@property
6789
def param_uid(self):
90+
"""Parameter uid descriptor the alias points to."""
6891
return self._param_uid
6992

7093
@param_uid.setter
7194
def param_uid(self, value):
95+
"""Set the parameter uid.
96+
97+
Args:
98+
value: New uid.
99+
"""
72100
self._param_uid.value = value
73101

74102

75103
class Aliases(CategoryCollection):
104+
"""Collection of :class:`Alias` items."""
105+
76106
def __init__(self):
107+
"""Create an empty collection of aliases."""
77108
super().__init__(item_type=Alias)

src/easydiffraction/analysis/categories/constraints.py

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,8 @@
1+
"""Simple symbolic constraint between parameters.
2+
3+
Represents an equation of the form ``lhs_alias = rhs_expr`` where
4+
``rhs_expr`` is evaluated elsewhere by the analysis engine.
5+
"""
16
# SPDX-FileCopyrightText: 2021-2025 EasyDiffraction contributors <https://github.com/easyscience/diffraction>
27
# SPDX-License-Identifier: BSD-3-Clause
38

@@ -11,6 +16,13 @@
1116

1217

1318
class Constraint(CategoryItem):
19+
"""Single constraint item.
20+
21+
Args:
22+
lhs_alias: Left-hand side alias name being constrained.
23+
rhs_expr: Right-hand side expression as a string.
24+
"""
25+
1426
def __init__(
1527
self,
1628
*,
@@ -56,21 +68,36 @@ def __init__(
5668

5769
@property
5870
def lhs_alias(self):
71+
"""Alias name on the left-hand side of the equation."""
5972
return self._lhs_alias
6073

6174
@lhs_alias.setter
6275
def lhs_alias(self, value):
76+
"""Set the left-hand side alias.
77+
78+
Args:
79+
value: New alias string.
80+
"""
6381
self._lhs_alias.value = value
6482

6583
@property
6684
def rhs_expr(self):
85+
"""Right-hand side expression string."""
6786
return self._rhs_expr
6887

6988
@rhs_expr.setter
7089
def rhs_expr(self, value):
90+
"""Set the right-hand side expression.
91+
92+
Args:
93+
value: New expression string.
94+
"""
7195
self._rhs_expr.value = value
7296

7397

7498
class Constraints(CategoryCollection):
99+
"""Collection of :class:`Constraint` items."""
100+
75101
def __init__(self):
102+
"""Create an empty constraints collection."""
76103
super().__init__(item_type=Constraint)

src/easydiffraction/analysis/categories/joint_fit_experiments.py

Lines changed: 26 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,8 @@
1+
"""Joint-fit experiment weighting configuration.
2+
3+
Stores per-experiment weights to be used when multiple experiments are
4+
fitted simultaneously.
5+
"""
16
# SPDX-FileCopyrightText: 2021-2025 EasyDiffraction contributors <https://github.com/easyscience/diffraction>
27
# SPDX-License-Identifier: BSD-3-Clause
38

@@ -13,6 +18,13 @@
1318

1419

1520
class JointFitExperiment(CategoryItem):
21+
"""A single joint-fit entry.
22+
23+
Args:
24+
id: Experiment identifier used in the fit session.
25+
weight: Relative weight factor in the combined objective.
26+
"""
27+
1628
def __init__(
1729
self,
1830
*,
@@ -59,25 +71,36 @@ def __init__(
5971

6072
@property
6173
def id(self):
74+
"""Experiment identifier descriptor."""
6275
return self._id
6376

6477
@id.setter
6578
def id(self, value):
79+
"""Set the experiment identifier.
80+
81+
Args:
82+
value: New id string.
83+
"""
6684
self._id.value = value
6785

6886
@property
6987
def weight(self):
88+
"""Weight factor descriptor."""
7089
return self._weight
7190

7291
@weight.setter
7392
def weight(self, value):
93+
"""Set the weight factor.
94+
95+
Args:
96+
value: New weight value.
97+
"""
7498
self._weight.value = value
7599

76100

77101
class JointFitExperiments(CategoryCollection):
78-
"""Collection manager for experiments that are fitted together in a
79-
`joint` fit.
80-
"""
102+
"""Collection of :class:`JointFitExperiment` items."""
81103

82104
def __init__(self):
105+
"""Create an empty joint-fit experiments collection."""
83106
super().__init__(item_type=JointFitExperiment)

src/easydiffraction/analysis/minimizers/base.py

Lines changed: 47 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -16,9 +16,14 @@
1616

1717

1818
class MinimizerBase(ABC):
19-
"""Abstract base class for minimizer implementations.
20-
21-
Provides shared logic and structure for concrete minimizers.
19+
"""Abstract base for concrete minimizers.
20+
21+
Contract:
22+
- Subclasses must implement ``_prepare_solver_args``,
23+
``_run_solver``, ``_sync_result_to_parameters`` and
24+
``_check_success``.
25+
- The ``fit`` method orchestrates the full workflow and returns
26+
:class:`FitResults`.
2227
"""
2328

2429
def __init__(
@@ -39,18 +44,29 @@ def __init__(
3944
self.tracker: FitProgressTracker = FitProgressTracker()
4045

4146
def _start_tracking(self, minimizer_name: str) -> None:
47+
"""Initialize progress tracking and timer.
48+
49+
Args:
50+
minimizer_name: Human-readable name shown in progress.
51+
"""
4252
self.tracker.reset()
4353
self.tracker.start_tracking(minimizer_name)
4454
self.tracker.start_timer()
4555

4656
def _stop_tracking(self) -> None:
57+
"""Stop timer and finalize tracking."""
4758
self.tracker.stop_timer()
4859
self.tracker.finish_tracking()
4960

5061
@abstractmethod
5162
def _prepare_solver_args(self, parameters: List[Any]) -> Dict[str, Any]:
52-
"""Prepare the solver arguments directly from the list of free
53-
parameters.
63+
"""Prepare keyword-arguments for the underlying solver.
64+
65+
Args:
66+
parameters: List of free parameters to be fitted.
67+
68+
Returns:
69+
Mapping of keyword arguments to pass into ``_run_solver``.
5470
"""
5571
pass
5672

@@ -60,6 +76,7 @@ def _run_solver(
6076
objective_function: Callable[..., Any],
6177
engine_parameters: Dict[str, Any],
6278
) -> Any:
79+
"""Execute the concrete solver and return its raw result."""
6380
pass
6481

6582
@abstractmethod
@@ -68,13 +85,25 @@ def _sync_result_to_parameters(
6885
raw_result: Any,
6986
parameters: List[Any],
7087
) -> None:
88+
"""Copy values from ``raw_result`` back to ``parameters`` in-
89+
place.
90+
"""
7191
pass
7292

7393
def _finalize_fit(
7494
self,
7595
parameters: List[Any],
7696
raw_result: Any,
7797
) -> FitResults:
98+
"""Build :class:`FitResults` and store it on ``self.result``.
99+
100+
Args:
101+
parameters: Parameters after the solver finished.
102+
raw_result: Backend-specific solver output object.
103+
104+
Returns:
105+
FitResults: Aggregated outcome of the fit.
106+
"""
78107
self._sync_result_to_parameters(parameters, raw_result)
79108
success = self._check_success(raw_result)
80109
self.result = FitResults(
@@ -89,17 +118,24 @@ def _finalize_fit(
89118

90119
@abstractmethod
91120
def _check_success(self, raw_result: Any) -> bool:
92-
"""Determine whether the fit was successful.
93-
94-
This must be implemented by concrete minimizers.
95-
"""
121+
"""Determine whether the fit was successful."""
96122
pass
97123

98124
def fit(
99125
self,
100126
parameters: List[Any],
101127
objective_function: Callable[..., Any],
102128
) -> FitResults:
129+
"""Run the full minimization workflow.
130+
131+
Args:
132+
parameters: Free parameters to optimize.
133+
objective_function: Callable returning residuals for a given
134+
set of engine arguments.
135+
136+
Returns:
137+
FitResults with success flag, best chi2 and timing.
138+
"""
103139
minimizer_name = self.name or 'Unnamed Minimizer'
104140
if self.method is not None:
105141
minimizer_name += f' ({self.method})'
@@ -123,6 +159,7 @@ def _objective_function(
123159
experiments: Any,
124160
calculator: Any,
125161
) -> np.ndarray:
162+
"""Default objective helper computing residuals array."""
126163
return self._compute_residuals(
127164
engine_params,
128165
parameters,
@@ -138,6 +175,7 @@ def _create_objective_function(
138175
experiments: Any,
139176
calculator: Any,
140177
) -> Callable[[Dict[str, Any]], np.ndarray]:
178+
"""Return a closure capturing problem context for the solver."""
141179
return lambda engine_params: self._objective_function(
142180
engine_params,
143181
parameters,

src/easydiffraction/crystallography/space_groups.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,11 @@
11
# SPDX-FileCopyrightText: 2021-2025 EasyDiffraction contributors <https://github.com/easyscience/diffraction>
22
# SPDX-License-Identifier: BSD-3-Clause
3+
"""Space group reference data.
4+
5+
Loads a gzipped, packaged pickle with crystallographic space-group
6+
information. The file is part of the distribution; user input is not
7+
involved.
8+
"""
39

410
import gzip
511
import pickle # noqa: S403 - trusted internal pickle file (package data only)
@@ -18,6 +24,7 @@ def _restricted_pickle_load(file_obj) -> Any:
1824

1925

2026
def _load():
27+
"""Load space-group data from the packaged archive."""
2128
path = Path(__file__).with_name('space_groups.pkl.gz')
2229
with gzip.open(path, 'rb') as f:
2330
return _restricted_pickle_load(f)

src/easydiffraction/experiments/categories/excluded_regions.py

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
# SPDX-FileCopyrightText: 2021-2025 EasyDiffraction contributors <https://github.com/easyscience/diffraction>
22
# SPDX-License-Identifier: BSD-3-Clause
3+
"""Exclude ranges of x from fitting/plotting (masked regions)."""
34

45
from typing import List
56

@@ -15,6 +16,8 @@
1516

1617

1718
class ExcludedRegion(CategoryItem):
19+
"""Closed interval [start, end] to be excluded."""
20+
1821
def __init__(
1922
self,
2023
*,
@@ -83,8 +86,8 @@ def __init__(self):
8386
super().__init__(item_type=ExcludedRegion)
8487

8588
def add(self, item: ExcludedRegion) -> None:
86-
"""Mark excluded points in the experiment pattern when a new
87-
region is added.
89+
"""Mark excluded points in the pattern when a region is
90+
added.
8891
"""
8992
# 1. Call parent add first
9093

@@ -106,6 +109,7 @@ def add(self, item: ExcludedRegion) -> None:
106109
datastore.meas_su = datastore.full_meas_su[~datastore.excluded]
107110

108111
def show(self) -> None:
112+
"""Print a table of excluded [start, end] intervals."""
109113
# TODO: Consider moving this to the base class
110114
# to avoid code duplication with implementations in Background,
111115
# etc. Consider using parameter names as column headers

0 commit comments

Comments
 (0)