aptapy 0.1.1__tar.gz → 0.3.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (47) hide show
  1. {aptapy-0.1.1 → aptapy-0.3.0}/.gitignore +6 -2
  2. {aptapy-0.1.1 → aptapy-0.3.0}/PKG-INFO +10 -2
  3. aptapy-0.3.0/README.md +10 -0
  4. {aptapy-0.1.1 → aptapy-0.3.0}/docs/conf.py +15 -0
  5. aptapy-0.3.0/docs/examples/GALLERY_HEADER.rst +4 -0
  6. aptapy-0.3.0/docs/examples/composite_fit.py +28 -0
  7. aptapy-0.3.0/docs/examples/constrained_fit.py +29 -0
  8. aptapy-0.3.0/docs/examples/simple_fit.py +25 -0
  9. aptapy-0.3.0/docs/examples/simple_hist1d.py +20 -0
  10. aptapy-0.3.0/docs/examples/weighted_hist1d.py +25 -0
  11. aptapy-0.3.0/docs/hist.rst +45 -0
  12. aptapy-0.3.0/docs/index.rst +36 -0
  13. aptapy-0.3.0/docs/modeling.rst +185 -0
  14. aptapy-0.3.0/docs/release_notes.rst +41 -0
  15. aptapy-0.3.0/docs/strip.rst +44 -0
  16. {aptapy-0.1.1 → aptapy-0.3.0}/noxfile.py +3 -2
  17. {aptapy-0.1.1 → aptapy-0.3.0}/pyproject.toml +1 -0
  18. aptapy-0.3.0/src/aptapy/_version.py +1 -0
  19. aptapy-0.3.0/src/aptapy/hist.py +280 -0
  20. aptapy-0.3.0/src/aptapy/modeling.py +995 -0
  21. aptapy-0.3.0/src/aptapy/plotting.py +530 -0
  22. aptapy-0.3.0/src/aptapy/strip.py +92 -0
  23. aptapy-0.3.0/tests/test_hist.py +135 -0
  24. {aptapy-0.1.1 → aptapy-0.3.0}/tests/test_modeling.py +73 -45
  25. aptapy-0.3.0/tests/test_strip.py +53 -0
  26. aptapy-0.1.1/README.md +0 -3
  27. aptapy-0.1.1/docs/index.rst +0 -16
  28. aptapy-0.1.1/docs/modeling.rst +0 -10
  29. aptapy-0.1.1/docs/release_notes.rst +0 -12
  30. aptapy-0.1.1/src/aptapy/_version.py +0 -1
  31. aptapy-0.1.1/src/aptapy/modeling.py +0 -515
  32. aptapy-0.1.1/src/aptapy/plotting.py +0 -486
  33. {aptapy-0.1.1 → aptapy-0.3.0}/.github/workflows/ci.yml +0 -0
  34. {aptapy-0.1.1 → aptapy-0.3.0}/.github/workflows/docs.yml +0 -0
  35. {aptapy-0.1.1 → aptapy-0.3.0}/.github/workflows/pypi.yml +0 -0
  36. {aptapy-0.1.1 → aptapy-0.3.0}/CODE_OF_CONDUCT.md +0 -0
  37. {aptapy-0.1.1 → aptapy-0.3.0}/CONTRIBUTING.md +0 -0
  38. {aptapy-0.1.1 → aptapy-0.3.0}/LICENSE +0 -0
  39. {aptapy-0.1.1 → aptapy-0.3.0}/docs/Makefile +0 -0
  40. {aptapy-0.1.1 → aptapy-0.3.0}/docs/_static/favicon.ico +0 -0
  41. {aptapy-0.1.1 → aptapy-0.3.0}/docs/_static/logo.png +0 -0
  42. {aptapy-0.1.1 → aptapy-0.3.0}/docs/_static/logo_small.png +0 -0
  43. {aptapy-0.1.1 → aptapy-0.3.0}/docs/make.bat +0 -0
  44. {aptapy-0.1.1 → aptapy-0.3.0}/src/aptapy/__init__.py +0 -0
  45. {aptapy-0.1.1 → aptapy-0.3.0}/src/aptapy/py.typed +0 -0
  46. {aptapy-0.1.1 → aptapy-0.3.0}/src/aptapy/typing_.py +0 -0
  47. {aptapy-0.1.1 → aptapy-0.3.0}/tools/release.py +0 -0
@@ -1,3 +1,7 @@
1
+ # Custom files.
2
+ docs/sg_execution_times.rst
3
+ docs/auto_examples
4
+
1
5
  # Byte-compiled / optimized / DLL files
2
6
  __pycache__/
3
7
  *.py[codz]
@@ -182,9 +186,9 @@ cython_debug/
182
186
  .abstra/
183
187
 
184
188
  # Visual Studio Code
185
- # Visual Studio Code specific template is maintained in a separate VisualStudioCode.gitignore
189
+ # Visual Studio Code specific template is maintained in a separate VisualStudioCode.gitignore
186
190
  # that can be found at https://github.com/github/gitignore/blob/main/Global/VisualStudioCode.gitignore
187
- # and can be added to the global gitignore or merged into this file. However, if you prefer,
191
+ # and can be added to the global gitignore or merged into this file. However, if you prefer,
188
192
  # you could uncomment the following to ignore the entire vscode folder
189
193
  # .vscode/
190
194
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: aptapy
3
- Version: 0.1.1
3
+ Version: 0.3.0
4
4
  Summary: Statistical tools for online monitoring and analysis
5
5
  Project-URL: Homepage, https://github.com/lucabaldini/aptapy
6
6
  Project-URL: Issues, https://github.com/lucabaldini/aptapy/issues
@@ -694,9 +694,17 @@ Requires-Dist: pytest; extra == 'dev'
694
694
  Requires-Dist: ruff; extra == 'dev'
695
695
  Provides-Extra: docs
696
696
  Requires-Dist: sphinx; extra == 'docs'
697
+ Requires-Dist: sphinx-gallery; extra == 'docs'
697
698
  Requires-Dist: sphinxawesome-theme; extra == 'docs'
698
699
  Description-Content-Type: text/markdown
699
700
 
700
701
  <img src="docs/_static/logo.png" alt="logo" width="175"/>
701
702
 
702
- Statistical tools for online monitoring and analysis
703
+ ![License](https://img.shields.io/github/license/lucabaldini/aptapy.svg)
704
+ [![CI](https://github.com/lucabaldini/aptapy/actions/workflows/ci.yml/badge.svg)](https://github.com/lucabaldini/aptapy/actions/workflows/ci.yml)
705
+ [![Docs](https://github.com/lucabaldini/aptapy/actions/workflows/docs.yml/badge.svg)](https://github.com/lucabaldini/aptapy/actions/workflows/docs.yml)
706
+ [![Docs](https://img.shields.io/badge/docs-latest-blue.svg)](https://lucabaldini.github.io/aptapy/)
707
+ [![Ceasefire Now](https://badge.techforpalestine.org/default)](https://techforpalestine.org/learn-more)
708
+
709
+ Statistical tools for online monitoring and analysis.
710
+ [Read more](https://lucabaldini.github.io/aptapy/).
aptapy-0.3.0/README.md ADDED
@@ -0,0 +1,10 @@
1
+ <img src="docs/_static/logo.png" alt="logo" width="175"/>
2
+
3
+ ![License](https://img.shields.io/github/license/lucabaldini/aptapy.svg)
4
+ [![CI](https://github.com/lucabaldini/aptapy/actions/workflows/ci.yml/badge.svg)](https://github.com/lucabaldini/aptapy/actions/workflows/ci.yml)
5
+ [![Docs](https://github.com/lucabaldini/aptapy/actions/workflows/docs.yml/badge.svg)](https://github.com/lucabaldini/aptapy/actions/workflows/docs.yml)
6
+ [![Docs](https://img.shields.io/badge/docs-latest-blue.svg)](https://lucabaldini.github.io/aptapy/)
7
+ [![Ceasefire Now](https://badge.techforpalestine.org/default)](https://techforpalestine.org/learn-more)
8
+
9
+ Statistical tools for online monitoring and analysis.
10
+ [Read more](https://lucabaldini.github.io/aptapy/).
@@ -28,6 +28,7 @@ extensions = [
28
28
  "sphinx.ext.autodoc",
29
29
  "sphinx.ext.todo",
30
30
  "sphinx.ext.viewcode",
31
+ "sphinx_gallery.gen_gallery",
31
32
  ]
32
33
  autodoc_default_options = {
33
34
  "members": True,
@@ -37,6 +38,20 @@ autodoc_default_options = {
37
38
  }
38
39
  todo_include_todos = True
39
40
 
41
+
42
+ sphinx_gallery_conf = {
43
+ "examples_dirs": ["examples"], # source example scripts (relative to conf.py)
44
+ "gallery_dirs": ["auto_examples"], # generated output (reST + images)
45
+ "filename_pattern": r".*", # build all files in examples/
46
+ # Optional niceties:
47
+ "download_all_examples": False,
48
+ #"remove_config_comments": True,
49
+ # "backreferences_dir": "gen_modules/backreferences",
50
+ # "doc_module": ("yourpkg",), # populate backrefs for your package API
51
+ # "thumbnail_size": (320, 240),
52
+ "reset_modules": ("matplotlib", "aptapy.plotting.configure"),
53
+ }
54
+
40
55
  # Options for syntax highlighting.
41
56
  pygments_style = "default"
42
57
  pygments_dark_style = "default"
@@ -0,0 +1,4 @@
1
+ :orphan:
2
+
3
+ Example gallery
4
+ ===============
@@ -0,0 +1,28 @@
1
+ """
2
+ Composite fit example
3
+ =====================
4
+
5
+ Composite fit with a Gaussian plus a straight line.
6
+ """
7
+
8
+ # %%
9
+
10
+ import numpy as np
11
+
12
+ from aptapy.hist import Histogram1d
13
+ from aptapy.modeling import Gaussian, Line
14
+ from aptapy.plotting import plt
15
+
16
+ hist = Histogram1d(np.linspace(-5., 5., 100), label="Random data", xlabel="z")
17
+ # Fill with the sum of a gaussian...
18
+ hist.fill(np.random.default_rng().normal(size=100000))
19
+ # ... and a triangular distribution (this is done via the inverse transform method).
20
+ hist.fill(5. - 10. * np.sqrt(1 - np.random.default_rng().random(100000)))
21
+ hist.plot()
22
+
23
+ model = Gaussian() + Line()
24
+ model.fit_histogram(hist)
25
+ print(model)
26
+ model.plot()
27
+
28
+ plt.legend()
@@ -0,0 +1,29 @@
1
+ """
2
+ Constrained fit example
3
+ =======================
4
+
5
+ Gaussian fit to histogram data where the prefactor is frozen based on the
6
+ histogram normalization.
7
+ """
8
+
9
+ # %%
10
+
11
+ import numpy as np
12
+
13
+ from aptapy.hist import Histogram1d
14
+ from aptapy.modeling import Gaussian
15
+ from aptapy.plotting import plt
16
+
17
+ hist = Histogram1d(np.linspace(-5., 5., 100), label="Random data", xlabel="z")
18
+ hist.fill(np.random.default_rng().normal(size=100000))
19
+ hist.plot()
20
+
21
+ model = Gaussian()
22
+ # Fix the prefactor to the histogram area---note this only works because the
23
+ # Gaussian model is normalized to 1 over the full range when the prefactor is 1.
24
+ model.prefactor.freeze(hist.area())
25
+ model.fit_histogram(hist)
26
+ print(model)
27
+ model.plot()
28
+
29
+ plt.legend()
@@ -0,0 +1,25 @@
1
+ """
2
+ Simple fit example
3
+ ==================
4
+
5
+ Simple gaussian fit to histogram data.
6
+ """
7
+
8
+ # %%
9
+
10
+ import numpy as np
11
+
12
+ from aptapy.hist import Histogram1d
13
+ from aptapy.modeling import Gaussian
14
+ from aptapy.plotting import plt
15
+
16
+ hist = Histogram1d(np.linspace(-5., 5., 100), label="Random data", xlabel="z")
17
+ hist.fill(np.random.default_rng().normal(size=100000))
18
+ hist.plot()
19
+
20
+ model = Gaussian()
21
+ model.fit_histogram(hist)
22
+ print(model)
23
+ model.plot()
24
+
25
+ plt.legend()
@@ -0,0 +1,20 @@
1
+ """
2
+ Simple 1-D histogram
3
+ ====================
4
+
5
+ Simple one-dimensional histogram filled with random numbers from a normal
6
+ distribution.
7
+ """
8
+
9
+ # %%
10
+
11
+ import numpy as np
12
+
13
+ from aptapy.hist import Histogram1d
14
+ from aptapy.plotting import plt
15
+
16
+ hist = Histogram1d(np.linspace(-5., 5., 100), label="Random data", xlabel="z")
17
+ hist.fill(np.random.default_rng().normal(size=100000))
18
+ hist.plot()
19
+
20
+ plt.legend()
@@ -0,0 +1,25 @@
1
+ """
2
+ Weighted 1-D histogram
3
+ ======================
4
+
5
+ Weighted one-dimensional histogram to emulate a triangular distribution.
6
+ """
7
+
8
+ # %%
9
+
10
+ import numpy as np
11
+
12
+ from aptapy.hist import Histogram1d
13
+ from aptapy.plotting import plt
14
+
15
+ hist = Histogram1d(np.linspace(0., 1., 100), label="Random data", xlabel="u")
16
+ # Histogram sample: extract n random numbers uniformly distributed in [0, 1)
17
+ # and assign weights w = 1 - u (that is, w = 1 for u = 0 and 0 for u = 1).
18
+ # The result should be equivalent to sampling a triangular distribution.
19
+ n = 100000
20
+ sample = np.random.default_rng().random(size=n)
21
+ weights = 1. - sample
22
+ hist.fill(sample, weights=weights)
23
+ hist.plot()
24
+
25
+ plt.legend()
@@ -0,0 +1,45 @@
1
+ .. _hist:
2
+
3
+ :mod:`~aptapy.hist` --- Histograms
4
+ ==================================
5
+
6
+ The module provides an abstract base class for n-dimensional histograms along
7
+ with concrete implementations for 1D and 2D histograms:
8
+
9
+ * :class:`~aptapy.hist.AbstractHistogram`: Abstract base class for histograms;
10
+ * :class:`~aptapy.hist.Histogram1d`: 1D histogram implementation;
11
+ * :class:`~aptapy.hist.Histogram2d`: 2D histogram implementation.
12
+
13
+ Histograms are constructed with the bin edges (and, optionally, labels to be
14
+ used at the plotting stage) and are filled using the
15
+ :meth:`~aptapy.hist.AbstractHistogram.fill` method. The basic semantics is as
16
+ follows:
17
+
18
+ .. code-block:: python
19
+
20
+ import numpy as np
21
+ from aptapy.hist import Histogram1d, Histogram2d
22
+
23
+ rng = np.random.default_rng()
24
+ edges = np.linspace(-5., 5., 100)
25
+
26
+ hist = Histogram1d(edges, "x")
27
+ hist.fill(rng.normal(size=1000))
28
+ hist.plot()
29
+
30
+ hist = Histogram2d(edges, edges, 'x', 'y')
31
+ hist.fill(rng.normal(size=1000), rng.normal(size=1000))
32
+ hist.plot()
33
+
34
+ Histograms support weighted filling and basic arithmetic operations (addition
35
+ and subtraction) between histograms with identical binning.
36
+
37
+ .. warning::
38
+
39
+ Multiplication by a scalar is not yet supported.
40
+
41
+
42
+ Module documentation
43
+ --------------------
44
+
45
+ .. automodule:: aptapy.hist
@@ -0,0 +1,36 @@
1
+ .. aptapy documentation master file, created by
2
+ sphinx-quickstart on Sun Aug 24 11:47:57 2025.
3
+ You can adapt this file completely to your liking, but it should at least
4
+ contain the root `toctree` directive.
5
+
6
+ aptapy documentation
7
+ ====================
8
+
9
+ .. image:: _static/logo.png
10
+ :alt: Project logo
11
+ :width: 200px
12
+ :align: left
13
+
14
+ This is a small, pure-Python library providing statistical tools for online monitoring
15
+ and analysis of experimental data, with a focus on histogramming, time series, and
16
+ fitting. It is designed to be lightweight and easy to use, making it suitable for
17
+ integration into existing data processing pipelines.
18
+
19
+ The :doc:`examples Gallery <auto_examples/index>` is probably the best place to start.
20
+ Have fun!
21
+
22
+
23
+ .. toctree::
24
+ :maxdepth: 1
25
+ :caption: Contents:
26
+
27
+ auto_examples/index
28
+ release_notes
29
+
30
+ .. toctree::
31
+ :maxdepth: 1
32
+ :caption: API:
33
+
34
+ hist
35
+ modeling
36
+ strip
@@ -0,0 +1,185 @@
1
+ .. _modeling:
2
+
3
+ :mod:`~aptapy.modeling` --- Fitting models
4
+ ==========================================
5
+
6
+ The modeling module provides tools for fitting models to data, including parameter
7
+ estimation and uncertainty quantification.
8
+
9
+ Readily available simple models include
10
+
11
+ * :class:`~aptapy.modeling.Constant`: a constant value;
12
+ * :class:`~aptapy.modeling.Line`: a straight line;
13
+ * :class:`~aptapy.modeling.PowerLaw`: a power law;
14
+ * :class:`~aptapy.modeling.Gaussian`: a Gaussian function.
15
+
16
+ More complex models can be built by summing simple ones, e.g.,
17
+
18
+ >>> from aptapy.modeling import Line, Gaussian
19
+ >>>
20
+ >>> model = Line() + Gaussian()
21
+
22
+ The main fitting engine supports bounded fits and/or fits with fixed parameters.
23
+
24
+
25
+ Parameters
26
+ ----------
27
+
28
+ The first central concept in the modeling module is that of a fit parameter,
29
+ represented by the :class:`~aptapy.modeling.FitParameter` class. A fit parameter
30
+ is a named mutable object that holds a value, an optional uncertainty, and optional
31
+ bounds, along with a flag that indicate whether they should be varied or not in a fit.
32
+
33
+ :class:`~aptapy.modeling.FitParameter` objects provide all the facilities for
34
+ pretty-printing their value and uncertainty. The following example shows the basic
35
+ semantics of the class:
36
+
37
+ >>> from aptapy.modeling import FitParameter
38
+ >>>
39
+ >>> param = FitParameter(1.0, "amplitude", error=0.1)
40
+ >>> print(param)
41
+ Amplitude: 1.0 ± 0.1
42
+
43
+
44
+ Fit status
45
+ ----------
46
+
47
+ :class:`~aptapy.modeling.FitStatus` is a small bookkeeping class that holds all the
48
+ information about the status of a fit, such as the chisquare, the number of degrees of
49
+ freedom and the fit range.
50
+
51
+ .. warning::
52
+
53
+ At this point the implementation of the class is fairly minimal, and it is very
54
+ likely that we will be adding stuff along the way.
55
+
56
+
57
+ Simple models
58
+ -------------
59
+
60
+ Chances are you will not have to interact with :class:`~aptapy.modeling.FitParameter`
61
+ and :class:`~aptapy.modeling.FitStatus` objects a lot, but they are central to defining
62
+ and using simple fit models, and heavily used internally.
63
+
64
+ The easiest way to see how you would go about defining an actual fit model is to
65
+ look at the source code for a simple one.
66
+
67
+ .. literalinclude:: ../src/aptapy/modeling.py
68
+ :language: python
69
+ :pyobject: Line
70
+ :linenos:
71
+
72
+ All we really have to do is to subclass :class:`~aptapy.modeling.AbstractFitModel`,
73
+ listing all the fit parameters as class attributes (assigning them sensible default
74
+ values), and implement the :meth:`~aptapy.modeling.AbstractFitModel.evaluate` method,
75
+ which takes as first argument the independent variable and then the values of all the
76
+ fit parameters.
77
+
78
+ .. note::
79
+
80
+ It goes without saying that the order of the fit parameters in the argument
81
+ list of the :meth:`~aptapy.modeling.AbstractFitModel.evaluate` method must
82
+ match the order in which they are defined as class attributes.
83
+
84
+ In this particular case we are sayng that the ``Line`` model has two fit parameters,
85
+ ``intercept`` and ``slope``, and, well, the model itself evaluates as a straight line
86
+ as we would expect.
87
+
88
+ When we create an instance of a fitting model
89
+
90
+ >>> model = Line()
91
+
92
+ a few things happen under the hood:
93
+
94
+ * the class instance gets its own `copy` of each fit parameter, so that we can
95
+ change their values and settings without affecting the class definition, nor other
96
+ class instances;
97
+ * the class instance registers the fit parameters as attributes of the instance,
98
+ so that we can access them as, e.g., ``model.intercept``, ``model.slope``.
99
+
100
+ That it's pretty much it. The next thing that you proabably want to do is to fit
101
+ the model to a series of data points, which you do in pretty much the same fashion
102
+ as you would do with ``scipy.optimize.curve_fit`` using the
103
+ :meth:`~aptapy.modeling.AbstractFitModel.fit` method. This will return a
104
+ :meth:`~aptapy.modeling.FitStatus` object containing information about the fit.
105
+
106
+
107
+ Fitting primer
108
+ ~~~~~~~~~~~~~~
109
+
110
+ Assuming that you have a set of data points ``xdata``, ``ydata``, the latter with
111
+ associated uncertainties ``yerrors``, the simplest fit goes like
112
+
113
+ >>> from aptapy.modeling import Line
114
+ >>>
115
+ >>> model = Line()
116
+ >>> status = model.fit(xdata, ydata, sigma=yerrors)
117
+
118
+ You can fit within a subrange of the input data by specifying the ``min`` and/or
119
+ the ``max`` keyword arguments:
120
+
121
+ >>> from aptapy.modeling import Line
122
+ >>>
123
+ >>> model = Line()
124
+ >>> status = model.fit(xdata, ydata, sigma=yerrors, xmin=0., xmax=10.)
125
+
126
+ You can set bounds on the fit parameters, e.g., force the slope to be positive
127
+ by doing
128
+
129
+ >>> from aptapy.modeling import Line
130
+ >>>
131
+ >>> model = Line()
132
+ >>> model.slope.minimum = 0.
133
+ >>> status = model.fit(xdata, ydata, sigma=yerrors)
134
+
135
+ and you can freeze any of the parameters to a fixed value during the fit
136
+
137
+ >>> from aptapy.modeling import Line
138
+ >>>
139
+ >>> model = Line()
140
+ >>> model.intercept.freeze(0.)
141
+ >>> status = model.fit(xdata, ydata, sigma=yerrors)
142
+
143
+ Or, really, any linear combination of the above. The fit status is able to
144
+ pretty-print itself, and the fitted model can be plotted by just doing
145
+
146
+ >>> model.plot()
147
+ >>> plt.legend()
148
+
149
+ (The legend bit is put there on purpose, as by default the fitting model will
150
+ add a nice entry in the legend with all the relevant information.)
151
+
152
+ Fitting models interact nicely with one-dimensional histograms from the
153
+ :mod:`~aptapy.hist`, module so you can do
154
+
155
+ >>> import numpy as np
156
+ >>> from aptapy.hist import Histogram1D
157
+ >>> from aptapy.modeling import Line
158
+ >>>
159
+ >>> hist = Histogram1D(np.linspace(0., 1., 100))
160
+ >>> hist.fill(np.random.rand(1000))
161
+ >>> model = Line()
162
+ >>> status = model.fit_histogram(hist)
163
+
164
+
165
+ Composite models
166
+ ----------------
167
+
168
+ The modeling module also provides a way to build composite models by summing
169
+ simple ones. This is achieved by means of the :class:`~aptapy.modeling.FitModelSum`,
170
+ which is design to hold a list of components and interoperate with the rest
171
+ of the world in exactly the same fashion as simple models.
172
+
173
+ Chances are you will never have to instantiate a :class:`~aptapy.modeling.FitModelSum`
174
+ object directly, as the ``+`` operator will do the trick in most of the cases, e.g.,
175
+
176
+ >>> from aptapy.modeling import Line, Gaussian
177
+ >>> model = Line() + Gaussian()
178
+ >>> status = model.fit(xdata, ydata, sigma=yerrors)
179
+
180
+
181
+
182
+ Module documentation
183
+ --------------------
184
+
185
+ .. automodule:: aptapy.modeling
@@ -0,0 +1,41 @@
1
+ .. _release_notes:
2
+
3
+ Release notes
4
+ =============
5
+
6
+
7
+ Version 0.3.0 (2025-10-08)
8
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~
9
+
10
+ * New strip-chart facilities added.
11
+ * Introduction of model summation capability through operator overloading
12
+ * Refactored class hierarchy with new abstract base classes
13
+ * Enhanced parameter compatibility checking methods
14
+ * Improved histogram integration for fitting
15
+ * Adds sphinx-gallery integration with 5 example scripts demonstrating histogram
16
+ and fitting functionality
17
+ * Improves statistical analysis by adding p-value calculations and fixing degrees
18
+ of freedom calculations
19
+ * Updates test assertions to include p-value validation
20
+
21
+ * Pull requests merged:
22
+
23
+ - https://github.com/lucabaldini/aptapy/pull/3
24
+ - https://github.com/lucabaldini/aptapy/pull/4
25
+ - https://github.com/lucabaldini/aptapy/pull/5
26
+
27
+
28
+ Version 0.2.0 (2025-10-06)
29
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~
30
+
31
+ * New histogram facilities added.
32
+
33
+ * Pull requests merged:
34
+
35
+ - https://github.com/lucabaldini/aptapy/pull/2
36
+
37
+
38
+ Version 0.1.1 (2025-10-03)
39
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~
40
+
41
+ Initial release on PyPI.
@@ -0,0 +1,44 @@
1
+ .. _strip:
2
+
3
+ :mod:`~aptapy.strip` --- Strip charts
4
+ =====================================
5
+
6
+ This module provides a :class:`~aptapy.strip.StripChart` class representing a
7
+ sliding strip chart, that is, a scatter plot where the number of points is limited
8
+ to a maximum, so that the thing acts essentially as a sliding window, typically in time.
9
+ This is mainly meant to represent the time history of a signal over a reasonable
10
+ span---a long-term acquisition might go on for weeks, and it would not make sense
11
+ to try and plot on the screen millions of points, but the last segment of the
12
+ acquisition is the most important part when we want to monitor what is happening.
13
+
14
+ Internally the class uses two distinct :class:`collections.deque` objects to store
15
+ the data points, and the public interface is modeled after that of deques: you add
16
+ a single point with :meth:`~aptapy.strip.StripChart.append()`, and multiple points
17
+ with :meth:`~aptapy.strip.StripChart.extend()`.
18
+
19
+ .. code-block:: python
20
+
21
+ from aptapy.strip import StripChart
22
+
23
+ chart = StripChart(max_length=1000, label='Signal')
24
+
25
+ # add a single point
26
+ chart.append(0., 0.)
27
+
28
+ # add multiple points
29
+ chart.extend([1., 2., 3.], [4., 5., 6.])
30
+
31
+ # plot the current contents of the strip chart
32
+ chart.plot()
33
+
34
+ Strip chart objects can operate in two fundamentally different modes: if the
35
+ ``datetime`` flag is ``False``, the x-axis is treated as a simple numeric value
36
+ (e.g., time in seconds since the start of the acquisition, or a simple numeric
37
+ index), while if it is ``True``, the x-axis is treated as a series of
38
+ POSIX timestamps that are converted to datetime objects for plotting purposes.
39
+
40
+
41
+ Module documentation
42
+ --------------------
43
+
44
+ .. automodule:: aptapy.strip
@@ -43,8 +43,9 @@ def cleanup(session: nox.Session) -> None:
43
43
  if _path.exists():
44
44
  shutil.rmtree(_path)
45
45
  # Cleanup the docs.
46
- _path = _DOCS_DIR / "_build"
47
- if _path.exists():
46
+ for folder_name in ("_build", "auto_examples"):
47
+ _path = _DOCS_DIR / folder_name
48
+ if _path.exists():
48
49
  shutil.rmtree(_path)
49
50
 
50
51
 
@@ -35,6 +35,7 @@ dev = [
35
35
  docs = [
36
36
  "sphinx",
37
37
  "sphinxawesome-theme",
38
+ "sphinx-gallery",
38
39
  ]
39
40
 
40
41
  [project.urls]
@@ -0,0 +1 @@
1
+ __version__ = "0.3.0"