Python fitter package for multiple computational back-ends
APACHE-2.0 License
Bot releases are visible (Hide)
See all documentation for this version here.
ParametrizedFunction
and its implementations (#522)jax
import error for JAX >=0.4.19 (#504)pycompwa
website (#513).html
from page URLs (#515)figure_formats = ["svg"]
statement (#507)docnblive
job in tox.ini
(#510)The full changelog as commits can be found here.
Published by release-drafter[bot] 12 months ago
See all documentation for this version here.
Abs
of mass (#482)Abs
of mass (#482)CITATION.cff
(#494)sphinx-build
output (#481)The full changelog as commits can be found here.
Published by github-actions[bot] over 1 year ago
See all documentation for this version here.
migrad_args
option to Minuit2
optimizer (#476)The full changelog as commits can be found here.
Published by release-drafter[bot] almost 2 years ago
See all documentation for this version here.
ChainedDataTransformer
(#470)UnbinnedNLL
(#466)Published by release-drafter[bot] about 2 years ago
See all documentation for this version here.
Published by release-drafter[bot] about 2 years ago
See all documentation for this version here.
logging
hierarchy so that logs can be enabled and disabled per module (#453)UnbinnedNLL
can now handle a phase space DataSample
that carries a "weights"
key (#458). This makes it possible to perform fits with importance-sampled phase space samples (#402).WeightedDataGenerator
into DataGenerator
interface (#458)black
's default 88 line width (#449)sphinx-panels
to sphinx-design
(#450)Published by redeboer over 2 years ago
See all documentation for this version here.
phasespace
(#447)Published by release-drafter[bot] over 2 years ago
See all documentation for this version here.
phasespace
has been removed (#445).phasespace
, TensorFlow is limited to below v2.7.
sphinx-build
only and cannot be built with make
anymore (#433)EXECUTE_NB
mode is now faster on second run due to MyST-NB caching (#433)Published by release-drafter[bot] over 2 years ago
See all documentation for this version here.
sympy.Indexed
can now be lambdified (#427)function
module (#428)Published by release-drafter[bot] over 2 years ago
See all documentation for this version here.
ChiSquared
are now computed from observed_values
(#421)
Published by release-drafter[bot] over 2 years ago
See all documentation for this version here.
Published by release-drafter[bot] over 2 years ago
See all documentation for this version here.
AmpForm v0.12.3 introduces a small change through https://github.com/ComPWA/ampform/pull/211: BoostZ
etc becomes BoostZMatrix
. This needs to be fixed in the TensorFlow printer.
Added TensorFlow printer instructions for _BoostZMatrixImplementation
etc. See release notes AmpForm v0.12.4.
See import attrs
and attrs
TNG.
Closes https://github.com/ComPWA/repo-maintenance/issues/43
Also fixes a small bug: callbacks that write to disk skip writing when computing the Hesse.
Preview here.
Improved the docstrings of both functions, preview here.
sphinx-codeautolink
. Closes https://github.com/ComPWA/compwa-org/issues/106
jupyterlab-myst
**
.Links to graphviz
's API are now also embedded correctly. Follow-up to #405.
Closes https://github.com/ComPWA/compwa-org/issues/109
Preview here.
Rewrote the installation page a bit so that it's clearer how to pin all dependencies with Conda. Preview here.
Added an example of how to use create_cached_function()
in combination with an Estimator
. Preview here.
Added an additional install example that shows how to install a specific branch or tag with pip
from Git with optional dependencies. Preview here.
Automated changes by create-pull-request GitHub action
Closes https://github.com/ComPWA/repo-maintenance/issues/43
See https://github.com/ComPWA/ampform/pull/207
Compare API v0.4.1 and preview of this PR.
See jupyterlab-myst
Adds a workflow_dispatch
with inputs that allows running all tests manually with the latest version of AmpForm installed.
Published by release-drafter[bot] almost 3 years ago
See all documentation for this version here.
Closes #358
Expression tree optimizations sketched here have been bundled in a new function create_cached_function()
. A usage notebook can be previewed here.
All computational backends are now optional dependencies (apart from NumPy). So for instance, to install TensorWaves with JAX, run:
pip install tensorwaves[jax]
To do amplitude analysis, install with:
pip install tensorwaves[jax,pwa]
Closes #395
import ampform
import qrules
from ampform.dynamics.builder import create_relativistic_breit_wigner_with_ff
from tensorwaves.data import (
IntensityDistributionGenerator,
TFPhaseSpaceGenerator,
TFUniformRealNumberGenerator,
)
from tensorwaves.data.transform import SympyDataTransformer
from tensorwaves.function.sympy import create_parametrized_function
reaction = qrules.generate_transitions(
initial_state="J/psi(1S)",
final_state=["gamma", "pi0", "pi0"],
allowed_intermediate_particles=["f(0)"],
allowed_interaction_types=["strong", "EM"],
)
builder = ampform.get_builder(reaction)
resonances = reaction.get_intermediate_particles()
for p in resonances:
builder.set_dynamics(p.name, create_relativistic_breit_wigner_with_ff)
model = builder.formulate()
intensity = create_parametrized_function(
model.expression.doit(),
parameters=model.parameter_defaults,
backend="jax",
)
helicity_transformer = SympyDataTransformer.from_sympy(
model.kinematic_variables, backend="jax"
)
phsp_generator = TFPhaseSpaceGenerator(
initial_state_mass=reaction.initial_state[-1].mass,
final_state_masses={i: p.mass for i, p in reaction.final_state.items()},
)
data_generator = IntensityDistributionGenerator(
function=intensity,
domain_generator=phsp_generator,
domain_transformer=helicity_transformer,
)
rng = TFUniformRealNumberGenerator(seed=0)
phsp_momenta = phsp_generator.generate(1_000_000, rng)
data_momenta = data_generator.generate(100_000, rng)
tensorwaves.function
moduleTYPE_CHECKING
is now ignored in test coveragePublished by release-drafter[bot] almost 3 years ago
See all documentation for this specific version here.
TensorWaves v0.4 has a more general interface than v0.3. Major changes are the removal of the Model
interface (#357) and generalization of the data
module (#392). This affects the way in which computational backend functions are created and the way in which hit-and-miss distributions are generated.
Some examples of syntax changes for an AmpForm HelicityModel
(model
):
v0.4.x (new)
# create function and data transformer
from tensorwaves.function.sympy import create_parametrized_function
intensity = create_parametrized_function(
expression=model.expression.doit(),
parameters=model.parameter_defaults,
backend="jax",
)
helicity_transformer = SympyDataTransformer.from_sympy(
model.kinematic_variables, backend="numpy"
)
# generate data
from tensorwaves.data import (
IntensityDistributionGenerator,
SympyDataTransformer,
TFPhaseSpaceGenerator,
TFUniformRealNumberGenerator,
)
phsp_generator = TFPhaseSpaceGenerator(
initial_state_mass=3.069,
final_state_masses={0: 0.0, 1: 0.135, 2: 0.135},
)
data_generator = IntensityDistributionGenerator(
domain_generator=phsp_generator,
function=intensity,
domain_transformer=helicity_transformer,
)
rng = TFUniformRealNumberGenerator(seed=0)
phsp = phsp_generator.generate(100_000, rng)
data = data_generator.generate(10_000, rng)
Note that this works for general SymPy expressions: there is no AmpForm dependency. See this page.
v0.3.x (old)
from tensorwaves.model import LambdifiedFunction, SympyModel
# create function and data transformer
sympy_model = SympyModel(
expression=model.expression.doit(),
parameters=model.parameter_defaults,
)
intensity = LambdifiedFunction(sympy_model, backend="jax")
helicity_transformer = HelicityTransformer(model.adapter)
# generate data
from tensorwaves.data import TFUniformRealNumberGenerator, generate_data, generate_phsp
from tensorwaves.data.transform import HelicityTransformer
rng = TFUniformRealNumberGenerator(seed=0)
phsp = generate_phsp(
size=100_000,
initial_state_mass=3.069,
final_state_masses={0: 0.0, 1: 0.135, 2: 0.135},
random_generator=rng,
)
data = generate_data(
size=10_000,
initial_state_mass=3.069,
final_state_masses={0: 0.0, 1: 0.135, 2: 0.135},
data_transformer=helicity_transformer,
intensity=intensity,
random_generator=rng,
)
Also includes improvements to the documentation of estimator
module.
Closes #323
tensorwaves.function.get_source_code()
function
and argument_order
to ParametrizedBackendFunction
(parallels attrs
-decorated PositionalArgumentFunction
class).PositionalArgumentFunction
is now used internally in ParametrizedBackendFunction
(simplifies its __call__()
method).use_cse=False
It's now possible to do
from tensorwaves.optimizer import Minuit2
instead of
from tensorwaves.optimizer.minuit import Minuit2
Adapts the data
module implementation so that it can work with AmpForm v0.12.x. Closes https://github.com/ComPWA/ampform/issues/182.
Some major changes:
DataSample
are now str
only, not int
. This means that momentum samples have keys "p0"
, "p1"
, etc. instead of 0
, 1
. This is in accordance with the Symbol
names used in AmpForm's HelicityModel.kinematic_variables
.create_function()
that creates a PositionalArgumentFunction
. This is a Function
without parameters (compare ParametrizedFunction
). The function and related class is used in the DataTransformer
implementation, which doesn't need parameters.This PR removes the Model
interface and related implementations. The interface was introduced with the idea to implement different types of expression trees later on (see ADR-001), but this seems to be a premature optimisation. For now, the Function
interface suffices: Function
instances can be created through specific functions.
Some major changes:
Model
interface and its implementation SympyModel
have been removedtensorwaves.model
has been renamed to tensorwaves.function
performance_optimize()
(for nowβsee #358)This means that the workflow becomes:
# helicity_model: ampform.helicity.HelicityModel
function = create_parametrized_function(
expression=helicity_model.expression.doit(),
parameters=helicity_model.parameter_defaults,
backend="numpy",
)
instead of
model = SympyModel(
expression=helicity_model.expression.doit(),
parameters=helicity_model.parameter_defaults,
max_complexity=max_complexity,
)
function = LambdifiedFunction(model, backend="numpy")
The existing Function
interface has too many responsibilities: it (1) converts a DataSample
to an array or tensor and (2) distinguishes parameter variables from domain variables. This worked fine so far, because Function
was only used when optimizing, where you need to tweak those parameters. In #345 though, we need to a Function
that only does (1), for the conversion of one DataSample
(four-momenta) to another DataSample
(kinematic variables) with different back-ends.
This PR creates a new ParametrizedFunction
interface that does (1) and (2) and a 'bare' Function
interface that does only (1). The input and output types of the Function
interface are generic, so that it can be used in different types of function-like interfaces.
Related changes:
LambdifiedFunction
to ParametrizedBackendFunction
.DataTransformer.transform()
has become a __call__
and DataTransformer
derives from Function
.Estimator
also derives from Function
: it computes an estimator value for a set of parameters.Large refactoring of the data
module with the aim to generalize its hit-and-miss mechanisms to general domain DataSample
types.
Removed generate_data()
and generate_phsp()
façade functions. The new way to generate phase space and hit-and-miss data samples is:
from tensorwaves.data import IntensityDistributionGenerator
from tensorwaves.data.phasespace import TFPhaseSpaceGenerator
from tensorwaves.data.rng import TFUniformRealNumberGenerator
# intensity: Function
# helicity_transformer: SympyDataTransformer
rng = TFUniformRealNumberGenerator(seed=0)
phsp_generator = TFPhaseSpaceGenerator(
initial_state_mass=3.0969,
final_state_masses={0: 0.0, 1: 0.135, 2: 0.135},
)
data_generator = IntensityDistributionGenerator(
domain_generator=phsp_generator,
domain_transformer=helicity_transformer,
function=intensity,
)
phsp = phsp_generator.generate(100_000, rng)
data = data_generator.generate(10_000, rng)
UniformRealNumberGenerator
-> RealNumberGenerator
PhaseSpaceGenerator
-> DataGenerator
PhaseSpaceGenerator.setup()
has been merged into the constructor (DataGenerator.__init__()
) and removed from the interface.
Split old TFPhaseSpaceGenerator
into an unweighted TFPhaseSpaceGenerator
(implements DataGenerator
) and a TFWeightedPhaseSpaceGenerator
(implements WeightedDataGenerator
). TFPhaseSpaceGenerator
can be used instead of the old generate_phsp()
function.
Collected RNGs under a new sub-module data.rng
DataGenerator
, which does not generate weights as opposed to FourMomentumGenerator
.IntensityDistributionGenerator
, which should be used instead of generate_data()
IdentityTransformer
, which is just the identity implementation of a DataTransformer
.NumpyUniformRNG
Only accepts a single str
now.
Fix-up to #374
Additional fixes:
use_cse
argument in hidden functions.**kwargs
from lambdify functions. This helps mypy/pyright identify whether functions calls miss certain arguments.sympy.lambdify()
doesn't work when SymPy is too old.
Preview here: https://tensorwaves--381.org.readthedocs.build/en/381/install.html
Additional improvements:
linkcheck_anchors = True
.typing-extensions
from requirements.Follow-up to #387. Generalizes the documentation with more non-PWA examples.
All example notebooks for amplitude analysis have been isolated under tensorwaves.rtfd.io/en/latest/amplitude-analysis. Examples under usage show more general expressions.
Note that resource-intensive examples like the Scipy fit on an amplitude model and the fit anination have been substituted with simpler examples, which should speed up CI on the docs.
Closes #379
The amplitude analysis notebook now shows how to optimize the expression tree with SymPy, so that the fit is much faster. This also allows showing a more complicated fit, with more free parameters and larger initial offset.
Closes #135
Adds a test under the tests/unit
folder that fits a small model with all back-ends and optimizers plus a unit test for generate_data
. This also helped fishing out some bugs (see commit history).
Closes #103
Large improvements to the testing suite:
tests/unit
moved one folder up.Published by redeboer almost 3 years ago
See all documentation for this version here.
CSVSummary
was writing "estimator_type"
incorrectly (it was writing the optimizer type). This PR fixes that and adds the optimizer type as an additional entry, also to YAMLSummary
.
See cse
argument in sympy.lambdify()
. This fixes https://github.com/ComPWA/tensorwaves/pull/345#commitcomment-61398587.
Note that lambdified source code becomes significantly smaller in larger expressions. Finding common sub-expressions has a small hit in performance when lambdifying, but in larger expressions, this is overcome by the fact that the output source code is smaller.
Extracted all SymPy functionality under tensorwaves.model
into a separate sub-module tensorwaves.model.sympy
.
Closes #280
This means that doit()
has to be called on the expression first.
CSVSummary
was writing "estimator_type"
incorrectly (it was writing the optimizer type). This PR fixes that and adds the optimizer type as an additional entry, also to YAMLSummary
.
JAX and TensorFlow printing is forwarded to the NumPy printer, but with jax.numpy
and tensorflow.experimental.numpy
as Printer._module
respectively.
Other improvements:
find_function
and wrote a test for lambdifying AmpForm's ComplexSqrt
tensorflow.Tensor
with find_function
_backend
module to function
, because function
is most related to back-ends.Closes #322
The role of _backend_lambdify
and _sympy_lambdify
is now swapped:
_backend_lambdify
is now purely a wrapper around sympy.lambdify
._sympy_lambdify
offers a switch between _backend_lambdify
and optimized_lambdify
.These functions will change further in #292, but this is PR focuses only on the problem describe din #322.
All tests that require AmpForm have been seperated from proper unit tests (that require no additional dependencies). The folder structure under tests
is now:
tests
βββ integration
βββ unit
Additional improvements:
qrules.ReactionInfo
is parametrized with the canonica-helicity and helicity formalism.SympyModel
is constructed with and without max_complexity
argument in the constructor, so that optimized_lambdify
is tested as well.LambdifiedFunction.update_parameters
: over-defined parameters were computed incorrectly. In addition, the error message now prints the expected parameters.pathlib.Path
(previously only str
). This makes it possible to convert the output_dir
fixture into a Path
as well.#344 created a module tensorwaves.model.backend
with the intention to collect functions that handle back-ends. This PR moves _find_function_in_backend
(which was under tensorwaves.estimator
) there as well, moves the module to the top, and hides it altogether, as these functions are implementation details.
Additional fixes:
%%time
statement in the cell makes the error code of that cell return 'success'. The error has been fixed and a hidden test cell has been added to prevent such failures in the future.optimized_lambdify
now directly calls _backend_lambdify
is max_complexity
is higher than the number of nodes in the expression.Integration tests have become unstable since #349, see e.g. https://github.com/ComPWA/tensorwaves/actions/runs/1504632721, because the callback output is written to the same file when using optimized_lambdify
/ _backend_lambdify
.
Closes #135
Adds a test under the tests/unit
folder that fits a small model with all back-ends and optimizers plus a unit test for generate_data
. This also helped fishing out some bugs (see commit history).
Other improvements:
tensorwaves.optimizer
module, e.g.:
from tensorwaves.optimizer import Minuit2
instead of
from tensorwaves.optimizer.minuit import Minuit2
Loadable
callbacks.Import expensive modules inline to speed up importing tensorwaves
. This makes import tensorwaves
(and collecting tests) about 8x as fast. Profiling done with tuna as follows (see stackoverflow):
python3 -X importtime -c "import tensorwaves" 2> tw.log && tuna tw.log
Previously, if no callback was specified in the optimizer constructor, an empty CallbackList would be created and on_optimize_end etc were always called. This is (theoretically) slower.
Some other improvements:
attrs
next-generation API (see also https://github.com/ComPWA/compwa-org/issues/90).Added links to the 'fit result' objects in the iminuit
and SciPy APIs.
Fix-up to #349
Writing with a callback in a pytest fixture and then loading it back in a test led to instable CI. This PR should fix that.
Switch from pytest-notebook
to nbmake
. Now it's again possible to run specific notebooks from the terminal with e.g.:
pytest --nbmake docs/usage/basics.ipynb
Other small fixes:
fast_lambdify()
in Jupyter notebooks to speed up docs workflow.tuple
in ParametrizedBackendFunction
.Reorganise GitHub Action workflow for pytest. Extracted from #366 in order to identify potential performance issues. Notebooks slow after the changes introduced in #366, which may be caused by the changes to the callbacks.
Other changes;
nb
.Should speed up pre-commit job.
Import expensive modules in the tests inline so that pytest --collect-only
is faster.
Published by release-drafter[bot] almost 3 years ago
See all documentation for this version here.
# type: ignore[error-code]
) with flake8-type-ignore.The .flake8
config file was using not using the same comment style as described in
https://flake8.pycqa.org/en/latest/user/configuration.html#project-configuration
Consequence not all errors were identified anymore.
Published by release-drafter[bot] about 3 years ago
See all documentation for this version here.
See ComPWA/ampform#104
Some platforms like Zenodo and conda-forge require the license file to be packaged.
Closes https://github.com/ComPWA/compwa-org/issues/61
Automated changes by create-pull-request GitHub action
See https://github.com/ComPWA/ampform/pull/147
See ComPWA/qrules#87
Note https://github.com/ComPWA/tensorwaves/pull/309#issuecomment-908152365. This comment is still relevant.
Published by release-drafter[bot] about 3 years ago
See all documentation for this version here.
Fix-up to #310
https://github.com/ComPWA/tensorwaves/blob/57f6ec0f04e0afc0cebcc955783d20cde2646be6/setup.cfg#L44
resulted in version conflicts downstream. AmpForm is now also correctly updated: 626abe1.
Published by release-drafter[bot] about 3 years ago
Published by release-drafter[bot] over 3 years ago
See all documentation for this version here.
Closes #290
Added a method FitResult.count_number_of_parameters()
FitResult(
minimum_valid=True,
execution_time=2.9841978549957275,
function_calls=166,
estimator_value=-7579.247627538372,
parameter_values={
'm_f(0)(980)': 0.989885368944097,
'Gamma_f(0)(980)': 0.060228379644260165,
},
parameter_errors={
'm_f(0)(980)': 0.0010628340144144574,
'Gamma_f(0)(980)': 0.0016523232241513362,
},
)
Removes AmpForm/QRules's ReactionInfo
from the main interface
. This makes generate_phsp
and generate_data
a bit more clumsy in usage, but the benefit is that ampform
is not imported into TensorWaves's interface
module.
Use HelicityModel.sum_components
instead.
Using type alias ParameterValue
where possible instead of Union[...]
.
Show how to generate a deterministic data and phase space sample in step 2 of the documentation.