From 452cff08f36e0316ba4f292d33542c45431f2d1d Mon Sep 17 00:00:00 2001 From: Jim Pivarski Date: Wed, 18 Dec 2024 10:30:51 -0600 Subject: [PATCH 01/23] give the logo some margins --- docs/_images/LogoSrc.svg | 60 +++++++++++++++++------------------ docs/_images/vector-logo.png | Bin 12709 -> 10183 bytes 2 files changed, 30 insertions(+), 30 deletions(-) diff --git a/docs/_images/LogoSrc.svg b/docs/_images/LogoSrc.svg index 7d81c1e0..6c2e8ef4 100644 --- a/docs/_images/LogoSrc.svg +++ b/docs/_images/LogoSrc.svg @@ -1,22 +1,22 @@ + inkscape:export-filename="/home/jpivarski/irishep/vector/docs/_images/vector-logo.png" + inkscape:export-xdpi="86.150795" + inkscape:export-ydpi="86.150795" + xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" + xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" + xmlns="http://www.w3.org/2000/svg" + xmlns:svg="http://www.w3.org/2000/svg" + xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:cc="http://creativecommons.org/ns#" + xmlns:dc="http://purl.org/dc/elements/1.1/"> + inkscape:window-width="2554" + inkscape:window-height="1365" + inkscape:window-x="1920" + inkscape:window-y="32" + inkscape:window-maximized="1" + fit-margin-top="5" + fit-margin-left="5" + fit-margin-right="5" + fit-margin-bottom="5" + inkscape:pagecheckerboard="0"> @@ -66,7 +67,6 @@ image/svg+xml - @@ -74,7 +74,7 @@ inkscape:label="Layer 1" inkscape:groupmode="layer" id="layer1" - transform="translate(-7.011975,-108.12622)"> + transform="translate(-2.011975,-103.12622)"> uOiB2;pH0}` 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 C?EO9f literal 12709 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 Xrn+QrWIOdAG9X Date: Wed, 18 Dec 2024 11:02:58 -0600 Subject: [PATCH 02/23] remove the old; I'll use vector.readthedocs.io as a guide for refilling it --- README.md | 874 +--- docs/api/backends/vector.backends._numba.rst | 8 - .../vector.backends._numba_object.rst | 8 - docs/api/backends/vector.backends.awkward.rst | 8 - .../vector.backends.awkward_constructors.rst | 8 - .../backends/vector.backends.numba_numpy.rst | 8 - docs/api/backends/vector.backends.numpy.rst | 8 - docs/api/backends/vector.backends.object.rst | 8 - docs/api/backends/vector.backends.rst | 22 - .../lorentz/vector._compute.lorentz.Et.rst | 8 - .../lorentz/vector._compute.lorentz.Et2.rst | 8 - .../lorentz/vector._compute.lorentz.Mt.rst | 8 - .../lorentz/vector._compute.lorentz.Mt2.rst | 8 - .../lorentz/vector._compute.lorentz.add.rst | 8 - .../lorentz/vector._compute.lorentz.beta.rst | 8 - .../vector._compute.lorentz.boostX_beta.rst | 8 - .../vector._compute.lorentz.boostX_gamma.rst | 8 - .../vector._compute.lorentz.boostY_beta.rst | 8 - .../vector._compute.lorentz.boostY_gamma.rst | 8 - .../vector._compute.lorentz.boostZ_beta.rst | 8 - .../vector._compute.lorentz.boostZ_gamma.rst | 8 - .../vector._compute.lorentz.boost_beta3.rst | 8 - .../vector._compute.lorentz.boost_p4.rst | 8 - ...ctor._compute.lorentz.deltaRapidityPhi.rst | 8 - ...tor._compute.lorentz.deltaRapidityPhi2.rst | 8 - .../lorentz/vector._compute.lorentz.dot.rst | 8 - .../lorentz/vector._compute.lorentz.equal.rst | 8 - .../lorentz/vector._compute.lorentz.gamma.rst | 8 - .../vector._compute.lorentz.is_lightlike.rst | 8 - .../vector._compute.lorentz.is_spacelike.rst | 8 - .../vector._compute.lorentz.is_timelike.rst | 8 - .../vector._compute.lorentz.isclose.rst | 8 - .../vector._compute.lorentz.not_equal.rst | 8 - .../vector._compute.lorentz.rapidity.rst | 8 - .../lorentz/vector._compute.lorentz.rst | 49 - .../lorentz/vector._compute.lorentz.scale.rst | 8 - .../vector._compute.lorentz.subtract.rst | 8 - .../lorentz/vector._compute.lorentz.t.rst | 8 - .../lorentz/vector._compute.lorentz.t2.rst | 8 - .../lorentz/vector._compute.lorentz.tau.rst | 8 - .../lorentz/vector._compute.lorentz.tau2.rst | 8 - .../vector._compute.lorentz.to_beta3.rst | 8 - .../vector._compute.lorentz.transform4D.rst | 8 - .../lorentz/vector._compute.lorentz.unit.rst | 8 - .../planar/vector._compute.planar.add.rst | 8 - .../vector._compute.planar.deltaphi.rst | 8 - .../planar/vector._compute.planar.dot.rst | 8 - .../planar/vector._compute.planar.equal.rst | 8 - ...vector._compute.planar.is_antiparallel.rst | 8 - .../vector._compute.planar.is_parallel.rst | 8 - ...ector._compute.planar.is_perpendicular.rst | 8 - .../planar/vector._compute.planar.isclose.rst | 8 - .../vector._compute.planar.not_equal.rst | 8 - .../planar/vector._compute.planar.phi.rst | 8 - .../planar/vector._compute.planar.rho.rst | 8 - .../planar/vector._compute.planar.rho2.rst | 8 - .../planar/vector._compute.planar.rotateZ.rst | 8 - .../compute/planar/vector._compute.planar.rst | 34 - .../planar/vector._compute.planar.scale.rst | 8 - .../vector._compute.planar.subtract.rst | 8 - .../vector._compute.planar.transform2D.rst | 8 - .../planar/vector._compute.planar.unit.rst | 8 - .../planar/vector._compute.planar.x.rst | 8 - .../planar/vector._compute.planar.y.rst | 8 - .../spatial/vector._compute.spatial.add.rst | 8 - .../vector._compute.spatial.costheta.rst | 8 - .../vector._compute.spatial.cottheta.rst | 8 - .../spatial/vector._compute.spatial.cross.rst | 8 - .../vector._compute.spatial.deltaR.rst | 8 - .../vector._compute.spatial.deltaR2.rst | 8 - .../vector._compute.spatial.deltaangle.rst | 8 - .../vector._compute.spatial.deltaeta.rst | 8 - .../spatial/vector._compute.spatial.dot.rst | 8 - .../spatial/vector._compute.spatial.equal.rst | 8 - .../spatial/vector._compute.spatial.eta.rst | 8 - ...ector._compute.spatial.is_antiparallel.rst | 8 - .../vector._compute.spatial.is_parallel.rst | 8 - ...ctor._compute.spatial.is_perpendicular.rst | 8 - .../vector._compute.spatial.isclose.rst | 8 - .../spatial/vector._compute.spatial.mag.rst | 8 - .../spatial/vector._compute.spatial.mag2.rst | 8 - .../vector._compute.spatial.not_equal.rst | 8 - .../vector._compute.spatial.rotateX.rst | 8 - .../vector._compute.spatial.rotateY.rst | 8 - .../vector._compute.spatial.rotate_axis.rst | 8 - .../vector._compute.spatial.rotate_euler.rst | 8 - ...tor._compute.spatial.rotate_quaternion.rst | 8 - .../spatial/vector._compute.spatial.rst | 44 - .../spatial/vector._compute.spatial.scale.rst | 8 - .../vector._compute.spatial.subtract.rst | 8 - .../spatial/vector._compute.spatial.theta.rst | 8 - .../vector._compute.spatial.transform3D.rst | 8 - .../spatial/vector._compute.spatial.unit.rst | 8 - .../spatial/vector._compute.spatial.z.rst | 8 - docs/api/compute/vector._compute.rst | 18 - docs/api/inheritance.svg | 3413 -------------- docs/api/modules.rst | 7 - docs/api/vector._methods.rst | 8 - docs/api/vector._typeutils.rst | 8 - docs/api/vector.rst | 21 - docs/changelog.md | 475 -- docs/index.rst | 80 +- docs/usage/intro.ipynb | 4084 ----------------- docs/usage/structure.md | 11 - 104 files changed, 11 insertions(+), 9849 deletions(-) delete mode 100644 docs/api/backends/vector.backends._numba.rst delete mode 100644 docs/api/backends/vector.backends._numba_object.rst delete mode 100644 docs/api/backends/vector.backends.awkward.rst delete mode 100644 docs/api/backends/vector.backends.awkward_constructors.rst delete mode 100644 docs/api/backends/vector.backends.numba_numpy.rst delete mode 100644 docs/api/backends/vector.backends.numpy.rst delete mode 100644 docs/api/backends/vector.backends.object.rst delete mode 100644 docs/api/backends/vector.backends.rst delete mode 100644 docs/api/compute/lorentz/vector._compute.lorentz.Et.rst delete mode 100644 docs/api/compute/lorentz/vector._compute.lorentz.Et2.rst delete mode 100644 docs/api/compute/lorentz/vector._compute.lorentz.Mt.rst delete mode 100644 docs/api/compute/lorentz/vector._compute.lorentz.Mt2.rst delete mode 100644 docs/api/compute/lorentz/vector._compute.lorentz.add.rst delete mode 100644 docs/api/compute/lorentz/vector._compute.lorentz.beta.rst delete mode 100644 docs/api/compute/lorentz/vector._compute.lorentz.boostX_beta.rst delete mode 100644 docs/api/compute/lorentz/vector._compute.lorentz.boostX_gamma.rst delete mode 100644 docs/api/compute/lorentz/vector._compute.lorentz.boostY_beta.rst delete mode 100644 docs/api/compute/lorentz/vector._compute.lorentz.boostY_gamma.rst delete mode 100644 docs/api/compute/lorentz/vector._compute.lorentz.boostZ_beta.rst delete mode 100644 docs/api/compute/lorentz/vector._compute.lorentz.boostZ_gamma.rst delete mode 100644 docs/api/compute/lorentz/vector._compute.lorentz.boost_beta3.rst delete mode 100644 docs/api/compute/lorentz/vector._compute.lorentz.boost_p4.rst delete mode 100644 docs/api/compute/lorentz/vector._compute.lorentz.deltaRapidityPhi.rst delete mode 100644 docs/api/compute/lorentz/vector._compute.lorentz.deltaRapidityPhi2.rst delete mode 100644 docs/api/compute/lorentz/vector._compute.lorentz.dot.rst delete mode 100644 docs/api/compute/lorentz/vector._compute.lorentz.equal.rst delete mode 100644 docs/api/compute/lorentz/vector._compute.lorentz.gamma.rst delete mode 100644 docs/api/compute/lorentz/vector._compute.lorentz.is_lightlike.rst delete mode 100644 docs/api/compute/lorentz/vector._compute.lorentz.is_spacelike.rst delete mode 100644 docs/api/compute/lorentz/vector._compute.lorentz.is_timelike.rst delete mode 100644 docs/api/compute/lorentz/vector._compute.lorentz.isclose.rst delete mode 100644 docs/api/compute/lorentz/vector._compute.lorentz.not_equal.rst delete mode 100644 docs/api/compute/lorentz/vector._compute.lorentz.rapidity.rst delete mode 100644 docs/api/compute/lorentz/vector._compute.lorentz.rst delete mode 100644 docs/api/compute/lorentz/vector._compute.lorentz.scale.rst delete mode 100644 docs/api/compute/lorentz/vector._compute.lorentz.subtract.rst delete mode 100644 docs/api/compute/lorentz/vector._compute.lorentz.t.rst delete mode 100644 docs/api/compute/lorentz/vector._compute.lorentz.t2.rst delete mode 100644 docs/api/compute/lorentz/vector._compute.lorentz.tau.rst delete mode 100644 docs/api/compute/lorentz/vector._compute.lorentz.tau2.rst delete mode 100644 docs/api/compute/lorentz/vector._compute.lorentz.to_beta3.rst delete mode 100644 docs/api/compute/lorentz/vector._compute.lorentz.transform4D.rst delete mode 100644 docs/api/compute/lorentz/vector._compute.lorentz.unit.rst delete mode 100644 docs/api/compute/planar/vector._compute.planar.add.rst delete mode 100644 docs/api/compute/planar/vector._compute.planar.deltaphi.rst delete mode 100644 docs/api/compute/planar/vector._compute.planar.dot.rst delete mode 100644 docs/api/compute/planar/vector._compute.planar.equal.rst delete mode 100644 docs/api/compute/planar/vector._compute.planar.is_antiparallel.rst delete mode 100644 docs/api/compute/planar/vector._compute.planar.is_parallel.rst delete mode 100644 docs/api/compute/planar/vector._compute.planar.is_perpendicular.rst delete mode 100644 docs/api/compute/planar/vector._compute.planar.isclose.rst delete mode 100644 docs/api/compute/planar/vector._compute.planar.not_equal.rst delete mode 100644 docs/api/compute/planar/vector._compute.planar.phi.rst delete mode 100644 docs/api/compute/planar/vector._compute.planar.rho.rst delete mode 100644 docs/api/compute/planar/vector._compute.planar.rho2.rst delete mode 100644 docs/api/compute/planar/vector._compute.planar.rotateZ.rst delete mode 100644 docs/api/compute/planar/vector._compute.planar.rst delete mode 100644 docs/api/compute/planar/vector._compute.planar.scale.rst delete mode 100644 docs/api/compute/planar/vector._compute.planar.subtract.rst delete mode 100644 docs/api/compute/planar/vector._compute.planar.transform2D.rst delete mode 100644 docs/api/compute/planar/vector._compute.planar.unit.rst delete mode 100644 docs/api/compute/planar/vector._compute.planar.x.rst delete mode 100644 docs/api/compute/planar/vector._compute.planar.y.rst delete mode 100644 docs/api/compute/spatial/vector._compute.spatial.add.rst delete mode 100644 docs/api/compute/spatial/vector._compute.spatial.costheta.rst delete mode 100644 docs/api/compute/spatial/vector._compute.spatial.cottheta.rst delete mode 100644 docs/api/compute/spatial/vector._compute.spatial.cross.rst delete mode 100644 docs/api/compute/spatial/vector._compute.spatial.deltaR.rst delete mode 100644 docs/api/compute/spatial/vector._compute.spatial.deltaR2.rst delete mode 100644 docs/api/compute/spatial/vector._compute.spatial.deltaangle.rst delete mode 100644 docs/api/compute/spatial/vector._compute.spatial.deltaeta.rst delete mode 100644 docs/api/compute/spatial/vector._compute.spatial.dot.rst delete mode 100644 docs/api/compute/spatial/vector._compute.spatial.equal.rst delete mode 100644 docs/api/compute/spatial/vector._compute.spatial.eta.rst delete mode 100644 docs/api/compute/spatial/vector._compute.spatial.is_antiparallel.rst delete mode 100644 docs/api/compute/spatial/vector._compute.spatial.is_parallel.rst delete mode 100644 docs/api/compute/spatial/vector._compute.spatial.is_perpendicular.rst delete mode 100644 docs/api/compute/spatial/vector._compute.spatial.isclose.rst delete mode 100644 docs/api/compute/spatial/vector._compute.spatial.mag.rst delete mode 100644 docs/api/compute/spatial/vector._compute.spatial.mag2.rst delete mode 100644 docs/api/compute/spatial/vector._compute.spatial.not_equal.rst delete mode 100644 docs/api/compute/spatial/vector._compute.spatial.rotateX.rst delete mode 100644 docs/api/compute/spatial/vector._compute.spatial.rotateY.rst delete mode 100644 docs/api/compute/spatial/vector._compute.spatial.rotate_axis.rst delete mode 100644 docs/api/compute/spatial/vector._compute.spatial.rotate_euler.rst delete mode 100644 docs/api/compute/spatial/vector._compute.spatial.rotate_quaternion.rst delete mode 100644 docs/api/compute/spatial/vector._compute.spatial.rst delete mode 100644 docs/api/compute/spatial/vector._compute.spatial.scale.rst delete mode 100644 docs/api/compute/spatial/vector._compute.spatial.subtract.rst delete mode 100644 docs/api/compute/spatial/vector._compute.spatial.theta.rst delete mode 100644 docs/api/compute/spatial/vector._compute.spatial.transform3D.rst delete mode 100644 docs/api/compute/spatial/vector._compute.spatial.unit.rst delete mode 100644 docs/api/compute/spatial/vector._compute.spatial.z.rst delete mode 100644 docs/api/compute/vector._compute.rst delete mode 100644 docs/api/inheritance.svg delete mode 100644 docs/api/modules.rst delete mode 100644 docs/api/vector._methods.rst delete mode 100644 docs/api/vector._typeutils.rst delete mode 100644 docs/api/vector.rst delete mode 100644 docs/changelog.md delete mode 100644 docs/usage/intro.ipynb delete mode 100644 docs/usage/structure.md diff --git a/README.md b/README.md index 28b82fd3..ea7344f3 100644 --- a/README.md +++ b/README.md @@ -16,877 +16,15 @@ [![LICENSE][license-badge]][license-link] [![Scikit-HEP][sk-badge]][sk-link] -Vector is a Python 3.8+ library (Python 3.6 and 3.7 supported till `v0.9.0` and `v1.0.0`, respectively) for 2D, 3D, and [Lorentz vectors](https://en.wikipedia.org/wiki/Special_relativity#Physics_in_spacetime), especially _arrays of vectors_, to solve common physics problems in a NumPy-like way. - -Main features of Vector: - -- Pure Python with NumPy as its only dependency. This makes it easier to install. -- Vectors may be represented in a variety of coordinate systems: Cartesian, cylindrical, pseudorapidity, and any combination of these with time or proper time for Lorentz vectors. In all, there are 12 coordinate systems: {_x_-_y_ vs _ρ_-_φ_ in the azimuthal plane} × {_z_ vs _θ_ vs _η_ longitudinally} × {_t_ vs _τ_ temporally}. -- Uses names and conventions set by [ROOT](https://root.cern/)'s [TLorentzVector](https://root.cern.ch/doc/master/classTLorentzVector.html) and [Math::LorentzVector](https://root.cern.ch/doc/master/classROOT_1_1Math_1_1LorentzVector.html), as well as [scikit-hep/math](https://github.com/scikit-hep/scikit-hep/tree/master/skhep/math), [uproot-methods TLorentzVector](https://github.com/scikit-hep/uproot3-methods/blob/master/uproot3_methods/classes/TLorentzVector.py), [henryiii/hepvector](https://github.com/henryiii/hepvector), and [coffea.nanoevents.methods.vector](https://coffea-hep.readthedocs.io/en/latest/modules/coffea.nanoevents.methods.vector.html) (backed by Scikit-HEP/vector since `v2024.8`). -- Implemented on a variety of backends: - - pure Python objects - - [SymPy](https://www.sympy.org/en/index.html) vectors - - NumPy arrays of vectors (as a [structured array](https://numpy.org/doc/stable/user/basics.rec.html) subclass) - - [Awkward Arrays](https://awkward-array.org/) of vectors - - potential for more: CuPy, TensorFlow, Torch... -- Awkward backend also implemented in [Numba](https://numba.pydata.org/) for JIT-compiled calculations on vectors. -- [JAX](https://awkward-array.org/doc/main/user-guide/how-to-specialize-differentiate-jax.html) and [Dask](https://dask-awkward.readthedocs.io/en/stable/) support through Awkward Arrays. -- Distinction between geometrical vectors, which have a minimum of attribute and method names, and vectors representing momentum, which have synonyms like `pt` = `rho`, `energy` = `t`, `mass` = `tau`. - -## Installation - -To install, use `pip install vector` or your favorite way to install in an environment. - ## Overview -This overview is based on the [documentation here](https://vector.readthedocs.io/en/develop/usage/intro.html). - -```python -import vector -import numpy as np -import awkward as ak # at least v2.0.0 (vector v1.4.* supports awkward v1 and v2 both) -import numba as nb -``` - -## Constructing a vector or an array of vectors - -The easiest way to create one or many vectors is with a helper function: - -- `vector.obj` to make a pure Python vector object, -- `vector.arr` to make a NumPy array of vectors (or `array`, lowercase, like `np.array`), -- `vector.awk` to make an Awkward Array of vectors (or `Array`, uppercase, like `ak.Array`). -- `vector.zip` to make an Awkward Array of vectors (similar to `ak.zip`) - -### Pure Python vectors - -You can directly use the `VectorObject` and `MomentumObject` classes to construct object type vectors: - -```python -vector.VectorObject2D(x=1.1, y=2.2) -vector.MomentumObject3D(px=1.1, py=2.2, pz=3.3) -vector.VectorObject4D(x=1.1, y=2.2, eta=3.3, tau=4.4) -``` - -and so on for every class. - -Or, you can use a single wrapper function to construct all possible combinations of -object type vectors: - -```python -# Cartesian 2D vector -vector.obj(x=3, y=4) -# same in polar coordinates -vector.obj(rho=5, phi=0.9273) -# use "isclose" unless they are exactly equal -vector.obj(x=3, y=4).isclose(vector.obj(rho=5, phi=0.9273)) -# Cartesian 3D vector -vector.obj(x=3, y=4, z=-2) -# Cartesian 4D vector -vector.obj(x=3, y=4, z=-2, t=10) -# in rho-phi-eta-t cylindrical coordinates -vector.obj(rho=5, phi=0.9273, eta=-0.39, t=10) -# use momentum-synonyms to get a momentum vector -vector.obj(pt=5, phi=0.9273, eta=-0.39, E=10) -vector.obj(rho=5, phi=0.9273, eta=-0.39, t=10) == vector.obj( - pt=5, phi=0.9273, eta=-0.390035, E=10 -) -# geometrical vectors have to use geometrical names ("tau", not "mass") -vector.obj(rho=5, phi=0.9273, eta=-0.39, t=10).tau -# momentum vectors can use momentum names (as well as geometrical ones) -vector.obj(pt=5, phi=0.9273, eta=-0.39, E=10).mass -# any combination of azimuthal, longitudinal, and temporal coordinates is allowed -vector.obj(pt=5, phi=0.9273, theta=1.9513, mass=8.4262) -vector.obj(x=3, y=4, z=-2, t=10).isclose( - vector.obj(pt=5, phi=0.9273, theta=1.9513, mass=8.4262) -) - -# Test instance type for any level of granularity. -( - # is a vector or array of vectors - isinstance(vector.obj(x=1.1, y=2.2), vector.Vector), - # is 2D (not 3D or 4D) - isinstance(vector.obj(x=1.1, y=2.2), vector.Vector2D), - # is a vector object (not an array) - isinstance(vector.obj(x=1.1, y=2.2), vector.VectorObject), - # has momentum synonyms - isinstance(vector.obj(px=1.1, py=2.2), vector.Momentum), - # has transverse plane (2D, 3D, or 4D) - isinstance(vector.obj(x=1.1, y=2.2, z=3.3, t=4.4), vector.Planar), - # has all spatial coordinates (3D or 4D) - isinstance(vector.obj(x=1.1, y=2.2, z=3.3, t=4.4), vector.Spatial), - # has temporal coordinates (4D) - isinstance(vector.obj(x=1.1, y=2.2, z=3.3, t=4.4), vector.Lorentz), - # azimuthal coordinate type - isinstance(vector.obj(x=1.1, y=2.2, z=3.3, t=4.4).azimuthal, vector.AzimuthalXY), - # longitudinal coordinate type - isinstance( - vector.obj(x=1.1, y=2.2, z=3.3, t=4.4).longitudinal, vector.LongitudinalZ - ), - # temporal coordinate type - isinstance(vector.obj(x=1.1, y=2.2, z=3.3, t=4.4).temporal, vector.TemporalT), -) -``` - -The allowed keyword arguments for 2D vectors are: - -- `x` and `y` for Cartesian azimuthal coordinates, -- `px` and `py` for momentum, -- `rho` and `phi` for polar azimuthal coordinates, -- `pt` and `phi` for momentum. - -For 3D vectors, you need the above and: - -- `z` for the Cartesian longitudinal coordinate, -- `pz` for momentum, -- `theta` for the spherical polar angle (from $0$ to $\pi$, inclusive), -- `eta` for pseudorapidity, which is a kind of spherical polar angle. - -For 4D vectors, you need the above and: - -- `t` for the Cartesian temporal coordinate, -- `E` or `energy` to get four-momentum, -- `tau` for the "proper time" (temporal coordinate in the vector's rest coordinate system), -- `M` or `mass` to get four-momentum. - -Since momentum vectors have momentum-synonyms _in addition_ to the geometrical names, any momentum-synonym will make the whole vector a momentum vector. - -If you want to bypass the dimension and coordinate system inference through keyword arguments (e.g. for static typing), you can use specialized constructors: - -```python -vector.VectorObject2D.from_xy(1.1, 2.2) -vector.MomentumObject3D.from_rhophiz(1.1, 2.2, 3.3) -vector.VectorObject4D.from_xyetatau(1.1, 2.2, 3.3, 4.4) -``` - -and so on, for all combinations of azimuthal, longitudinal, and temporal coordinates, geometric and momentum-flavored. - -### SymPy vectors - -> **Note:** Operations on SymPy vectors are only 100% compatible with numeric vectors (Python, NumPy, and Awkward backends) if the vectors are positive time-like, that is, if `t**2 > x**2 + y**2 + z**2`. The space-like and negative time-like cases have different sign conventions. - -You can directly use the `VectorSympy` and `MomentumSympy` classes to construct object type vectors: - -```python -import sympy - -x, y, z, t, px, py, pz, eta, tau = sympy.symbols( - "x y z t px py pz eta tau", - real=True, # see sympy assumptions to add more restrictions on the symbols -) -vector.VectorSympy2D(x=x, y=y) -vector.MomentumSympy3D(px=px, py=py, pz=pz) -vector.VectorSympy4D(x=x, y=y, eta=eta, tau=tau) -``` - -and so on for every class. - -```python -# Test instance type for any level of granularity. -( - # is a vector or array of vectors - isinstance(vector.VectorSympy2D(x=x, y=y), vector.Vector), - # is 2D (not 3D or 4D) - isinstance(vector.VectorSympy2D(x=x, y=y), vector.Vector2D), - # is a sympy vector (not an array) - isinstance(vector.VectorSympy2D(x=x, y=y), vector.VectorSympy), - # has momentum synonyms - isinstance(vector.MomentumSympy2D(px=px, py=py), vector.Momentum), - # has transverse plane (2D, 3D, or 4D) - isinstance(vector.VectorSympy4D(x=x, y=y, z=z, t=t), vector.Planar), - # has all spatial coordinates (3D or 4D) - isinstance(vector.VectorSympy4D(x=x, y=y, z=z, t=t), vector.Spatial), - # has temporal coordinates (4D) - isinstance(vector.VectorSympy4D(x=x, y=y, z=z, t=t), vector.Lorentz), - # azimuthal coordinate type - isinstance(vector.VectorSympy4D(x=x, y=y, z=z, t=t).azimuthal, vector.AzimuthalXY), - # longitudinal coordinate type - isinstance( - vector.VectorSympy4D(x=x, y=y, z=z, t=t).longitudinal, vector.LongitudinalZ - ), - # temporal coordinate type - isinstance(vector.VectorSympy4D(x=x, y=y, z=z, t=t).temporal, vector.TemporalT), -) -``` - -Since `VectorSympy2D`, `VectorSympy3D`, `VectorSympy4D`, and their momentum equivalents operate on SymPy expressions, all of the normal SymPy methods and functions work on the results, coordinates, and the vectors. - -```python -sympy.init_session() # latex printing - -v1 = vector.VectorSympy2D(x=x, y=y) -sympy.Eq(v1.rho, sympy.sqrt(x**2 + y**2)) - -v2 = vector.VectorSympy4D(x=x, y=y, z=z, t=t) -v2.to_rhophithetatau().tau - -values = {x: 3, y: 2, z: 1, t: 10} # t**2 > x**2 + y**2 + z**2 -v2.is_timelike() -v2.is_timelike().subs(values) - -v2.to_rhophithetatau().tau.subs(values).evalf() - -v2.boost(v2.to_beta3()) -v2.boost(v2.to_beta3()).t -v2.boost(v2.to_beta3()).t.simplify() -v2.boost(v2.to_beta3()).t.subs(values) -v2.boost(v2.to_beta3()).t.subs(values).evalf() -``` - -All of the keyword arguments and rules that apply to `vector.obj` construction apply to `vector.VectorSympyND` and `vector.MomentumObjectND` objects. - -### NumPy arrays of vectors - -You can directly use the `VectorNumpy` classes to construct object type vectors: - -```python -# NumPy-like arguments (literally passed through to NumPy) -vector.VectorNumpy2D( - [(1.1, 2.1), (1.2, 2.2), (1.3, 2.3), (1.4, 2.4), (1.5, 2.5)], - dtype=[("x", float), ("y", float)], -) - -# Pandas-like arguments (dict from names to column arrays) -vector.VectorNumpy2D({"x": [1.1, 1.2, 1.3, 1.4, 1.5], "y": [2.1, 2.2, 2.3, 2.4, 2.5]}) - -# As with objects, the coordinate system and dimension is taken from the names of the fields. -vector.VectorNumpy4D( - { - "x": [1.1, 1.2, 1.3, 1.4, 1.5], - "y": [2.1, 2.2, 2.3, 2.4, 2.5], - "z": [3.1, 3.2, 3.3, 3.4, 3.5], - "t": [4.1, 4.2, 4.3, 4.4, 4.5], - } -) -``` - -and so on for every class. - -Or, you can use a single wrapper function to construct all possible combinations of -NumPy type vectors: - -```python -# NumPy-like arguments (literally passed through to NumPy) -vector.array( - [(1.1, 2.1), (1.2, 2.2), (1.3, 2.3), (1.4, 2.4), (1.5, 2.5)], - dtype=[("x", float), ("y", float)], -) - -# Pandas-like arguments (dict from names to column arrays) -vector.array({"x": [1.1, 1.2, 1.3, 1.4, 1.5], "y": [2.1, 2.2, 2.3, 2.4, 2.5]}) - -# As with objects, the coordinate system and dimension is taken from the names of the fields. -vector.array( - { - "x": [1.1, 1.2, 1.3, 1.4, 1.5], - "y": [2.1, 2.2, 2.3, 2.4, 2.5], - "z": [3.1, 3.2, 3.3, 3.4, 3.5], - "t": [4.1, 4.2, 4.3, 4.4, 4.5], - } -) - -vector.array( - { - "pt": [1.1, 1.2, 1.3, 1.4, 1.5], - "phi": [2.1, 2.2, 2.3, 2.4, 2.5], - "eta": [3.1, 3.2, 3.3, 3.4, 3.5], - "M": [4.1, 4.2, 4.3, 4.4, 4.5], - } -) -``` - -Existing NumPy arrays can be viewed as arrays of vectors, but it needs to be a [structured array](https://numpy.org/doc/stable/user/basics.rec.html) with recognized field names. - -```python -np.arange(0, 24, 0.1).view( # NumPy array - [ - ("x", float), - ("y", float), - ("z", float), - ("t", float), - ] # interpret groups of four values as named fields -).view( - vector.VectorNumpy4D -) # give it vector properties and methods -``` - -Since `VectorNumpy2D`, `VectorNumpy3D`, `VectorNumpy4D`, and their momentum equivalents are NumPy array subclasses, all of the normal NumPy methods and functions work on them. - -```python -np.arange(0, 24, 0.1).view( - [("x", float), ("y", float), ("z", float), ("t", float)] -).view(vector.VectorNumpy4D).reshape(6, 5, 2) -``` - -All of the keyword arguments and rules that apply to `vector.obj` construction apply to `vector.arr` dtypes. - -Geometrical names are used in the dtype, even if momentum-synonyms are used in construction. - -```python -vector.arr({"px": [1, 2, 3, 4], "py": [1.1, 2.2, 3.3, 4.4], "pz": [0.1, 0.2, 0.3, 0.4]}) -``` - -### Awkward Arrays of vectors - -[Awkward Arrays](https://awkward-array.org/) are arrays with more complex data structures than NumPy allows, such as variable-length lists, nested records, missing and even heterogeneous data (multiple data types: use sparingly). - -The `vector.awk` function behaves exactly like the [ak.Array](https://awkward-array.readthedocs.io/en/latest/_auto/ak.Array.html) constructor, except that it makes arrays of vectors. - -```python -vector.awk( - [ - [{"x": 1, "y": 1.1, "z": 0.1}, {"x": 2, "y": 2.2, "z": 0.2}], - [], - [{"x": 3, "y": 3.3, "z": 0.3}], - [ - {"x": 4, "y": 4.4, "z": 0.4}, - {"x": 5, "y": 5.5, "z": 0.5}, - {"x": 6, "y": 6.6, "z": 0.6}, - ], - ] -) -``` - -If you want _any_ records named "`Vector2D`", "`Vector3D`", "`Vector4D`", "`Momentum2D`", "`Momentum3D`", or "`Momentum4D`" to be interpreted as vectors, register the behaviors globally. - -```python -vector.register_awkward() - -ak.Array( - [ - [{"x": 1, "y": 1.1, "z": 0.1}, {"x": 2, "y": 2.2, "z": 0.2}], - [], - [{"x": 3, "y": 3.3, "z": 0.3}], - [ - {"x": 4, "y": 4.4, "z": 0.4}, - {"x": 5, "y": 5.5, "z": 0.5}, - {"x": 6, "y": 6.6, "z": 0.6}, - ], - ], - with_name="Vector3D", -) -``` - -All of the keyword arguments and rules that apply to `vector.obj` construction apply to `vector.awk` field names. - -Finally, the `VectorAwkward` mixins can be subclassed to create custom vector classes. The awkward behavior classes and projections must be named as `*Array`. For example, `coffea` uses the following names - `TwoVectorArray`, `ThreeVectorArray`, `PolarTwoVectorArray`, `SphericalThreeVectorArray`, ... - -## Vector properties - -Any geometrical coordinate can be computed from vectors in any coordinate system; they'll be provided or computed as needed. - -```python -vector.obj(x=3, y=4).rho -vector.obj(rho=5, phi=0.9273).x -vector.obj(rho=5, phi=0.9273).y -vector.obj(x=1, y=2, z=3).theta -vector.obj(x=1, y=2, z=3).eta -``` - -Some properties are not coordinates, but derived from them. - -```python -vector.obj(x=1, y=2, z=3).costheta -vector.obj(x=1, y=2, z=3).mag # spatial magnitude -vector.obj(x=1, y=2, z=3).mag2 # spatial magnitude squared -``` - -These properties are provided because they can be computed faster or with more numerical stability in different coordinate systems. For instance, the magnitude ignores `phi` in polar coordinates. - -```python -vector.obj(rho=3, phi=0.123456789, z=4).mag2 -``` - -Momentum vectors have geometrical properties as well as their momentum-synonyms. - -```python -vector.obj(px=3, py=4).rho -vector.obj(px=3, py=4).pt -vector.obj(x=1, y=2, z=3, E=4).tau -vector.obj(x=1, y=2, z=3, E=4).mass -``` - -Here's the key thing: _arrays of vectors return arrays of coordinates_. - -```python -vector.arr( - { - "x": [1.0, 2.0, 3.0, 4.0, 5.0], - "y": [1.1, 2.2, 3.3, 4.4, 5.5], - "z": [0.1, 0.2, 0.3, 0.4, 0.5], - } -).theta - -vector.awk( - [ - [{"x": 1, "y": 1.1, "z": 0.1}, {"x": 2, "y": 2.2, "z": 0.2}], - [], - [{"x": 3, "y": 3.3, "z": 0.3}], - [{"x": 4, "y": 4.4, "z": 0.4}, {"x": 5, "y": 5.5, "z": 0.5}], - ] -).theta - -# Make a large, random NumPy array of 3D momentum vectors. -array = ( - np.random.normal(0, 1, 150) - .view([(x, float) for x in ("x", "y", "z")]) - .view(vector.MomentumNumpy3D) - .reshape(5, 5, 2) -) - -# Get the transverse momentum of each one. -array.pt - -# The array and its components have the same shape. -array.shape -array.pt.shape - -# Make a large, random Awkward Array of 3D momentum vectors. -array = vector.awk( - [ - [ - {x: np.random.normal(0, 1) for x in ("px", "py", "pz")} - for inner in range(np.random.poisson(1.5)) - ] - for outer in range(50) - ] -) - -# Get the transverse momentum of each one, in the same nested structure. -array.pt - -# The array and its components have the same list lengths (and can therefore be used together in subsequent calculations). -ak.num(array) -ak.num(array.pt) -``` - -## Vector methods - -Vector methods require arguments (in parentheses), which may be scalars or other vectors, depending on the calculation. - -```python -vector.obj(x=3, y=4).rotateZ(0.1) -vector.obj(rho=5, phi=0.4).rotateZ(0.1) - -# Broadcasts a scalar rotation angle of 0.5 to all elements of the NumPy array. -print( - vector.arr({"rho": [1, 2, 3, 4, 5], "phi": [0.1, 0.2, 0.3, 0.4, 0.5]}).rotateZ(0.5) -) - -# Matches each rotation angle to an element of the NumPy array. -print( - vector.arr({"rho": [1, 2, 3, 4, 5], "phi": [0.1, 0.2, 0.3, 0.4, 0.5]}).rotateZ( - np.array([0.1, 0.2, 0.3, 0.4, 0.5]) - ) -) - -# Broadcasts a scalar rotation angle of 0.5 to all elements of the Awkward Array. -print( - vector.awk( - [[{"rho": 1, "phi": 0.1}, {"rho": 2, "phi": 0.2}], [], [{"rho": 3, "phi": 0.3}]] - ).rotateZ(0.5) -) - -# Broadcasts a rotation angle of 0.1 to both elements of the first list, 0.2 to the empty list, and 0.3 to the only element of the last list. -print( - vector.awk( - [[{"rho": 1, "phi": 0.1}, {"rho": 2, "phi": 0.2}], [], [{"rho": 3, "phi": 0.3}]] - ).rotateZ([0.1, 0.2, 0.3]) -) - -# Matches each rotation angle to an element of the Awkward Array. -print( - vector.awk( - [[{"rho": 1, "phi": 0.1}, {"rho": 2, "phi": 0.2}], [], [{"rho": 3, "phi": 0.3}]] - ).rotateZ([[0.1, 0.2], [], [0.3]]) -) -``` - -Some methods are equivalent to binary operators. - -```python -vector.obj(x=3, y=4).scale(10) -vector.obj(x=3, y=4) * 10 -10 * vector.obj(x=3, y=4) -vector.obj(rho=5, phi=0.5) * 10 -``` - -Some methods involve more than one vector. - -```python -vector.obj(x=1, y=2).add(vector.obj(x=5, y=5)) -vector.obj(x=1, y=2) + vector.obj(x=5, y=5) -vector.obj(x=1, y=2).dot(vector.obj(x=5, y=5)) -vector.obj(x=1, y=2) @ vector.obj(x=5, y=5) -``` - -The vectors can use different coordinate systems. Conversions are necessary, but minimized for speed and numeric stability. - -```python -# both are Cartesian, dot product is exact -vector.obj(x=3, y=4) @ vector.obj(x=6, y=8) -# one is polar, dot product is approximate -vector.obj(rho=5, phi=0.9273) @ vector.obj(x=6, y=8) -# one is polar, dot product is approximate -vector.obj(x=3, y=4) @ vector.obj(rho=10, phi=0.9273) -# both are polar, a formula that depends on phi differences is used -vector.obj(rho=5, phi=0.9273) @ vector.obj(rho=10, phi=0.9273) -``` - -In Python, some "operators" are actually built-in functions, such as `abs`. - -```python -abs(vector.obj(x=3, y=4)) -``` - -Note that `abs` returns - -- `rho` for 2D vectors -- `mag` for 3D vectors -- `tau` (`mass`) for 4D vectors - -Use the named properties when you want magnitude in a specific number of dimensions; use `abs` when you want the magnitude for any number of dimensions. - -The vectors can be from different backends. Normal rules for broadcasting Python numbers, NumPy arrays, and Awkward Arrays apply. - -```python -vector.arr({"x": [1, 2, 3, 4, 5], "y": [0.1, 0.2, 0.3, 0.4, 0.5]}) + vector.obj( - x=10, y=5 -) - -( - vector.awk( - [ # an Awkward Array of vectors - [{"x": 1, "y": 1.1}, {"x": 2, "y": 2.2}], - [], - [{"x": 3, "y": 3.3}], - [{"x": 4, "y": 4.4}, {"x": 5, "y": 5.5}], - ] - ) - + vector.obj(x=10, y=5) # and a single vector object -) - -( - vector.awk( - [ # an Awkward Array of vectors - [{"x": 1, "y": 1.1}, {"x": 2, "y": 2.2}], - [], - [{"x": 3, "y": 3.3}], - [{"x": 4, "y": 4.4}, {"x": 5, "y": 5.5}], - ] - ) - + vector.arr( - {"x": [4, 3, 2, 1], "y": [0.1, 0.1, 0.1, 0.1]} - ) # and a NumPy array of vectors -) -``` - -Some operations are defined for 2D or 3D vectors, but are usable on higher-dimensional vectors because the additional components can be ignored or are passed through unaffected. - -```python -# deltaphi is a planar operation (defined on the transverse plane) -vector.obj(rho=1, phi=0.5).deltaphi(vector.obj(rho=2, phi=0.3)) -# but we can use it on 3D vectors -vector.obj(rho=1, phi=0.5, z=10).deltaphi(vector.obj(rho=2, phi=0.3, theta=1.4)) -# and 4D vectors -vector.obj(rho=1, phi=0.5, z=10, t=100).deltaphi( - vector.obj(rho=2, phi=0.3, theta=1.4, tau=1000) -) -# and mixed dimensionality -vector.obj(rho=1, phi=0.5).deltaphi(vector.obj(rho=2, phi=0.3, theta=1.4, tau=1000)) -``` - -This is especially useful for giving 4D vectors all the capabilities of 3D vectors. - -```python -vector.obj(x=1, y=2, z=3).rotateX(np.pi / 4) -vector.obj(x=1, y=2, z=3, tau=10).rotateX(np.pi / 4) -vector.obj(pt=1, phi=1.3, eta=2).deltaR(vector.obj(pt=2, phi=0.3, eta=1)) -vector.obj(pt=1, phi=1.3, eta=2, mass=5).deltaR( - vector.obj(pt=2, phi=0.3, eta=1, mass=10) -) -``` - -For a few operations - `+`, `-`, `==`, `!=`, ... - the dimension of the vectors should be equal. This can be achieved by using the `like` method, `to_{coordinate_name}` methods, `to_Vector*D` methods. The `to_Vector*D` methods provide more flexibility to the users, that is, new coordinate values can be passed into the methods as named arguments. - -```python -v1 = vector.obj(x=1, y=2, z=3) -v2 = vector.obj(x=1, y=2) - -v1 - v2.like(v1) # transforms v2 to v1's coordinate system (imputes z=0) -v1.like(v2) - v2 # transforms v1 to v2's coordinate system (removes z) -v1 - v2.to_xyz() # transforms v2 to xyz coordinates (imputes z=0) -v1.to_xy() - v2 # transforms v1 to xy coordinates (removes z) -v1 - v2.to_Vector3D(z=3) # transforms v2 to 3D (imputes z=3) -v1.to_Vector2D() - v2 # transforms v1 to 2D (removes z) -``` - -Similarly, for a few vector methods, the dimension of the input vectors are type checked strictly. - -For instance, a cross-product is only defined for 3D and 7D vectors; hence, running the method on a 4D vector will error out. - -```python -vector.obj(x=0.1, y=0.2, z=0.3).cross(vector.obj(x=0.4, y=0.5, z=0.6)) -``` - -The (current) list of properties and methods is: - -**Planar (2D, 3D, 4D):** - -- `x` (`px`) -- `y` (`py`) -- `rho` (`pt`): two-dimensional magnitude -- `rho2` (`pt2`): two-dimensional magnitude squared -- `phi` -- `deltaphi(vector)`: difference in `phi` (signed and rectified to $-\pi$ through $\pi$) -- `rotateZ(angle)` -- `transform2D(obj)`: the `obj` must supply components through `obj["xx"]`, `obj["xy"]`, `obj["yx"]`, `obj["yy"]` -- `is_parallel(vector, tolerance=1e-5)`: only true _if they're pointing in the same direction_ -- `is_antiparallel(vector, tolerance=1e-5)`: only true _if they're pointing in opposite directions_ -- `is_perpendicular(vector, tolerance=1e-5)` - -**Spatial (3D, 4D):** - -- `z` (`pz`) -- `theta` -- `eta` -- `costheta` -- `cottheta` -- `mag` (`p`): three-dimensional magnitude, does not include temporal component -- `mag2` (`p2`): three-dimensional magnitude squared -- `cross`: cross-product (strictly 3D) -- `deltaangle(vector)`: difference in angle (always non-negative) -- `deltaeta(vector)`: difference in `eta` (signed) -- `deltaR(vector)`: $\Delta R = \sqrt{\Delta\phi^2 + \Delta\eta^2}$ -- `deltaR2(vector)`: the above, squared -- `rotateX(angle)` -- `rotateY(angle)` -- `rotate_axis(axis, angle)`: the magnitude of `axis` is ignored, but it must be at least 3D -- `rotate_euler(phi, theta, psi, order="zxz")`: the arguments are in the same order as [ROOT::Math::EulerAngles](https://root.cern.ch/doc/master/classROOT_1_1Math_1_1EulerAngles.html), and `order="zxz"` agrees with ROOT's choice of conventions -- `rotate_nautical(yaw, pitch, roll)` -- `rotate_quaternion(u, i, j, k)`: again, the conventions match [ROOT::Math::Quaternion](https://root.cern.ch/doc/master/classROOT_1_1Math_1_1Quaternion.html). -- `transform3D(obj)`: the `obj` must supply components through `obj["xx"]`, `obj["xy"]`, etc. -- `is_parallel(vector, tolerance=1e-5)`: only true _if they're pointing in the same direction_ -- `is_antiparallel(vector, tolerance=1e-5)`: only true _if they're pointing in opposite directions_ -- `is_perpendicular(vector, tolerance=1e-5)` - -**Lorentz (4D only):** - -- `t` (`E`, `energy`): follows the [ROOT::Math::LorentzVector](https://root.cern/doc/master/LorentzVectorPage.html) behavior of treating spacelike vectors as negative `t` and negative `tau` and truncating wrong-direction timelike vectors -- `t2` (`E2`, `energy2`) -- `tau` (`M`, `mass`): see note above -- `tau2` (`M2`, `mass2`) -- `beta`: scalar(s) between $0$ (inclusive) and $1$ (exclusive, unless the vector components are infinite) -- `deltaRapidityPhi`: $\Delta R_{\mbox{rapidity}} = \Delta\phi^2 + \Delta \mbox{rapidity}^2$ -- `deltaRapidityPhi2`: the above, squared -- `gamma`: scalar(s) between $1$ (inclusive) and $\infty$ -- `rapidity`: scalar(s) between $0$ (inclusive) and $\infty$ -- `boost_p4(four_vector)`: change coordinate system using another 4D vector as the difference -- `boost_beta(three_vector)`: change coordinate system using a 3D beta vector (all components between $-1$ and $+1$) -- `boost(vector)`: uses the dimension of the given `vector` to determine behavior -- `boostX(beta=None, gamma=None)`: supply `beta` xor `gamma`, but not both -- `boostY(beta=None, gamma=None)`: supply `beta` xor `gamma`, but not both -- `boostZ(beta=None, gamma=None)`: supply `beta` xor `gamma`, but not both -- `transform4D(obj)`: the `obj` must supply components through `obj["xx"]`, `obj["xy"]`, etc. -- `to_beta3()`: turns a `four_vector` (for `boost_p4`) into a `three_vector` (for `boost_beta3`) -- `is_timelike(tolerance=0)` -- `is_spacelike(tolerance=0)` -- `is_lightlike(tolerance=1e-5)`: note the different tolerance - -**All numbers of dimensions:** - -- `unit()`: note the parentheses -- `dot(vector)`: can also use the `@` operator -- `add(vector)`: can also use the `+` operator -- `subtract(vector)`: can also use the `-` operator -- `scale(factor)`: can also use the `*` operator -- `equal(vector)`: can also use the `==` operator, but consider `isclose` instead -- `not_equal(vector)`: can also use the `!=` operator, but consider `isclose` instead -- `sum()`: can also use the `numpy.sum` or `awkward.sum`, only for NumPy and Awkward vectors -- `count_nonzero()`: can also use `numpy.count_nonzero` or `awkward.count_nonzero`, only for NumPy and Awkward vectors -- `count()`: can also use `awkward.count`, only for Awkward vectors -- `isclose(vector, rtol=1e-5, atol=1e-8, equal_nan=False)`: works like [np.isclose](https://numpy.org/doc/stable/reference/generated/numpy.isclose.html); arrays also have an [allclose](https://numpy.org/doc/stable/reference/generated/numpy.allclose.html) method -- `to_VectorND(coordinates)`/`to_ND(coordinates)`: replace `N` with the required vector dimension -- `to_{coordinate-names}`: for example - `to_rhophietatau` -- `like(other)`: projects the vector into the dimensions of `other`, for example - `two_d_vector.like(three_d_vector)` - -## Compiling your Python with Numba - -[Numba](https://numba.pydata.org/) is a just-in-time (JIT) compiler for a mathematically relevant subset of NumPy and Python. It allows you to write fast code without leaving the Python environment. The drawback of Numba is that it can only compile code blocks involving objects and functions that it recognizes. - -The Vector library includes extensions to inform Numba about vector objects, vector NumPy arrays, and vector Awkward Arrays. At the time of writing, the implementation of vector NumPy arrays is incomplete due to [numba/numba#6148](https://github.com/numba/numba/pull/6148). - -For instance, consider the following function: - -```python -@nb.njit -def compute_mass(v1, v2): - return (v1 + v2).mass - - -compute_mass(vector.obj(px=1, py=2, pz=3, E=4), vector.obj(px=-1, py=-2, pz=-3, E=4)) -``` - -When the two `MomentumObject4D` objects are passed as arguments, Numba recognizes them and replaces the Python objects with low-level structs. When it compiles the function, it recognizes `+` as the 4D `add` function and recognizes `.mass` as the `tau` component of the result. - -Although this demonstrates that Numba can manipulate vector objects, there is no performance advantage (and a likely disadvantage) to compiling a calculation on just a few vectors. The advantage comes when many vectors are involved, in arrays. - -```python -# This is still not a large number. You want millions. -array = vector.awk( - [ - [ - dict( - {x: np.random.normal(0, 1) for x in ("px", "py", "pz")}, - E=np.random.normal(10, 1), - ) - for inner in range(np.random.poisson(1.5)) - ] - for outer in range(50) - ] -) - - -@nb.njit -def compute_masses(array): - out = np.empty(len(array), np.float64) - for i, event in enumerate(array): - total = vector.obj(px=0.0, py=0.0, pz=0.0, E=0.0) - for vec in event: - total = total + vec - out[i] = total.mass - return out - - -compute_masses(array) -``` - -## Sub-classing Awkward mixins - -At the moment, it is possible to sub-class vector awkward mixins to extend the vector functionalities. Although the mechanism in place works well, it is still being improved. - -For instance, the `MomentumAwkward` classes can be extended in the following way: - -```py -behavior = vector.backends.awkward.behavior - - -@ak.mixin_class(behavior) -class TwoVector(vector.backends.awkward.MomentumAwkward2D): - pass - - -@ak.mixin_class(behavior) -class ThreeVector(vector.backends.awkward.MomentumAwkward3D): - pass - - -# required for transforming vectors -# the class names must always end with "Array" -TwoVectorArray.ProjectionClass2D = TwoVectorArray # noqa: F821 -TwoVectorArray.ProjectionClass3D = ThreeVectorArray # noqa: F821 -TwoVectorArray.MomentumClass = TwoVectorArray # noqa: F821 - -ThreeVectorArray.ProjectionClass2D = TwoVectorArray # noqa: F821 -ThreeVectorArray.ProjectionClass3D = ThreeVectorArray # noqa: F821 -ThreeVectorArray.MomentumClass = ThreeVectorArray # noqa: F821 - -vec = ak.zip( - { - "pt": [[1, 2], [], [3], [4]], - "phi": [[1.2, 1.4], [], [1.6], [3.4]], - }, - with_name="TwoVector", - behavior=behavior, -) - -vec -``` - -The binary operators are not automatically registered by awkward, but vector methods can be used to perform operations on sub-classed vectors. - -```py -vec.add(vec) -``` - -Similarly, other vector methods can be used by the new methods internally. - -```py -@ak.mixin_class(behavior) -class LorentzVector(vector.backends.awkward.MomentumAwkward4D): - @ak.mixin_class_method(np.divide, {numbers.Number}) - def divide(self, factor): - return self.scale(1 / factor) - - -# required for transforming vectors -# the class names must always end with "Array" -LorentzVectorArray.ProjectionClass2D = TwoVectorArray # noqa: F821 -LorentzVectorArray.ProjectionClass3D = ThreeVectorArray # noqa: F821 -LorentzVectorArray.ProjectionClass4D = LorentzVectorArray # noqa: F821 -LorentzVectorArray.MomentumClass = LorentzVectorArray # noqa: F821 - -vec = ak.zip( - { - "pt": [[1, 2], [], [3], [4]], - "eta": [[1.2, 1.4], [], [1.6], [3.4]], - "phi": [[0.3, 0.4], [], [0.5], [0.6]], - "energy": [[50, 51], [], [52], [60]], - }, - with_name="LorentzVector", - behavior=behavior, -) - -vec / 2 -vec.like(vector.obj(x=1, y=2)) -vec.like(vector.obj(x=1, y=2, z=3)) -``` - -It is also possible to manually add binary operations in vector's behavior dict to enable binary operations. - -```py -_binary_dispatch_cls = { - "TwoVector": TwoVector, - "ThreeVector": ThreeVector, - "LorentzVector": LorentzVector, -} -_rank = [TwoVector, ThreeVector, LorentzVector] - -for lhs, lhs_to in _binary_dispatch_cls.items(): - for rhs, rhs_to in _binary_dispatch_cls.items(): - out_to = min(lhs_to, rhs_to, key=_rank.index) - behavior[(np.add, lhs, rhs)] = out_to.add - behavior[(np.subtract, lhs, rhs)] = out_to.subtract - -vec + vec -vec.to_2D() + vec.to_2D() -``` - -Finally, instead of manually registering the superclass ufuncs, one can use the utility `copy_behaviors` function to copy behavior items for a new subclass - - -```py -behavior.update(ak._util.copy_behaviors("Vector2D", "TwoVector", behavior)) -behavior.update(ak._util.copy_behaviors("Vector3D", "ThreeVector", behavior)) -behavior.update(ak._util.copy_behaviors("Momentum4D", "LorentzVector", behavior)) - -vec + vec -vec.to_2D() + vec.to_2D() -``` - -## Talks about vector - -- 21st October 2024 - [A new SymPy backend for vector: uniting experimental and theoretical physicists](https://indi.to/zTs5b) - [CHEP 2024](https://indico.cern.ch/event/1338689/) -- 3rd July 2024 - [A new SymPy backend for vector: uniting experimental and theoretical physicists](https://indi.to/pfTC6) - [PyHEP 2024 (virtual)](https://indico.cern.ch/event/1384010/) [🎥](https://www.youtube.com/watch?v=aVPhP_APhqw) -- 9th October 2023 - [What’s new with Vector? First major release is out!](https://indi.to/35ym5) - [PyHEP 2023 (virtual)](https://indico.cern.ch/event/1252095/) [🎥](https://www.youtube.com/watch?v=JHEAb2R3xzE&list=PLKZ9c4ONm-VlAorAG8kR09ZqhMfHiH2LJ&index=10) -- 13th September 2022 - [Constructing HEP vectors and analyzing HEP data using Vector](https://indi.to/bPmMc) - [PyHEP 2022 (virtual)](https://indico.cern.ch/event/1150631/) [🎥](https://www.youtube.com/watch?v=4iveMzrbe7s&list=PLKZ9c4ONm-VkohKG-skzEG_gklMaSgaO7&index=15) -- 20th July 2022 - [Analysis Grand Challenge / HEP Scientific Python Ecosystem](https://indico.cern.ch/event/1151329/timetable/#3-analysis-grand-challenge-hep) - [DANCE/CoDaS@Snowmass 2022 computational and data science software training](https://indico.cern.ch/event/1151329/) -- 25th April 2022 - [Foundation libraries (uproot, awkward, hist, mplhep)](https://indico.cern.ch/event/1126109/contributions/4780138/) - [IRIS-HEP AGC Tools 2022 Workshop](https://indico.cern.ch/event/1126109/) [🎥](https://www.youtube.com/watch?v=O9KvsDMKOmY) -- 3rd November 2021 - [Data handling: uproot, awkward & vector](https://indico.cern.ch/event/1076231/contributions/4560398/) - [IRIS-HEP AGC Tools 2021 Workshop](https://indico.cern.ch/event/1076231/) [🎥](https://indico.cern.ch/event/1076231/contributions/4560398/attachments/2338579/4017718/agc_uproot_awk.mp4) +## Installation -### Status as of November 17, 2023 +## Getting help -First major release of vector is out and the package has reached a stable position. The work is spearheaded by bug reports and feature requests created on GitHub. It can only be improved by your feedback! +## Contributing to Vector -## Contributors ✨ +## Contributors Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/docs/en/emoji-key)): @@ -921,9 +59,9 @@ development environment. ## Acknowledgements -This library was primarily developed by Jim Pivarski, Henry Schreiner, Saransh Chopra, and Eduardo Rodrigues. +This library was primarily developed by Saransh Chopra, Jim Pivarski, Henry Schreiner, and Eduardo Rodrigues. -Support for this work was provided by the National Science Foundation cooperative agreement OAC-1836650 and PHY-2323298 (IRIS-HEP) and OAC-1450377 (DIANA/HEP). Any opinions, findings, conclusions or recommendations expressed in this material are those of the authors and do not necessarily reflect the views of the National Science Foundation. +Support for this work was provided by the National Science Foundation cooperative agreement [OAC-1836650](https://www.nsf.gov/awardsearch/showAward?AWD_ID=1836650) and [PHY-2323298](https://www.nsf.gov/awardsearch/showAward?AWD_ID=2323298) (IRIS-HEP) and [OAC-1450377](https://www.nsf.gov/awardsearch/showAward?AWD_ID=1450377) (DIANA/HEP). Any opinions, findings, conclusions or recommendations expressed in this material are those of the authors and do not necessarily reflect the views of the National Science Foundation. [actions-badge]: https://github.com/scikit-hep/vector/actions/workflows/ci.yml/badge.svg [actions-link]: https://github.com/scikit-hep/vector/actions diff --git a/docs/api/backends/vector.backends._numba.rst b/docs/api/backends/vector.backends._numba.rst deleted file mode 100644 index 97138875..00000000 --- a/docs/api/backends/vector.backends._numba.rst +++ /dev/null @@ -1,8 +0,0 @@ -vector.backends.\_numba module -================================ - -.. automodule:: vector.backends._numba - :members: - :undoc-members: - :show-inheritance: - :private-members: \ No newline at end of file diff --git a/docs/api/backends/vector.backends._numba_object.rst b/docs/api/backends/vector.backends._numba_object.rst deleted file mode 100644 index aa98c501..00000000 --- a/docs/api/backends/vector.backends._numba_object.rst +++ /dev/null @@ -1,8 +0,0 @@ -vector.backends.\_numba\_object module -====================================== - -.. automodule:: vector.backends._numba_object - :members: - :undoc-members: - :show-inheritance: - :private-members: \ No newline at end of file diff --git a/docs/api/backends/vector.backends.awkward.rst b/docs/api/backends/vector.backends.awkward.rst deleted file mode 100644 index 884a2fb4..00000000 --- a/docs/api/backends/vector.backends.awkward.rst +++ /dev/null @@ -1,8 +0,0 @@ -vector.backends.awkward module -================================== - -.. automodule:: vector.backends.awkward - :members: - :undoc-members: - :show-inheritance: - :private-members: diff --git a/docs/api/backends/vector.backends.awkward_constructors.rst b/docs/api/backends/vector.backends.awkward_constructors.rst deleted file mode 100644 index e27d4682..00000000 --- a/docs/api/backends/vector.backends.awkward_constructors.rst +++ /dev/null @@ -1,8 +0,0 @@ -vector.backends.awkward_constructors module -=========================================== - -.. automodule:: vector.backends.awkward_constructors - :members: - :undoc-members: - :show-inheritance: - :private-members: diff --git a/docs/api/backends/vector.backends.numba_numpy.rst b/docs/api/backends/vector.backends.numba_numpy.rst deleted file mode 100644 index f4f074b5..00000000 --- a/docs/api/backends/vector.backends.numba_numpy.rst +++ /dev/null @@ -1,8 +0,0 @@ -vector.backends.numba\_numpy module -===================================== - -.. automodule:: vector.backends.numba_numpy - :members: - :undoc-members: - :show-inheritance: - :private-members: diff --git a/docs/api/backends/vector.backends.numpy.rst b/docs/api/backends/vector.backends.numpy.rst deleted file mode 100644 index 0528cd32..00000000 --- a/docs/api/backends/vector.backends.numpy.rst +++ /dev/null @@ -1,8 +0,0 @@ -vector.backends.numpy module -================================ - -.. automodule:: vector.backends.numpy - :members: - :undoc-members: - :show-inheritance: - :private-members: diff --git a/docs/api/backends/vector.backends.object.rst b/docs/api/backends/vector.backends.object.rst deleted file mode 100644 index e689d1e0..00000000 --- a/docs/api/backends/vector.backends.object.rst +++ /dev/null @@ -1,8 +0,0 @@ -vector.backends.object module -================================= - -.. automodule:: vector.backends.object - :members: - :undoc-members: - :show-inheritance: - :private-members: \ No newline at end of file diff --git a/docs/api/backends/vector.backends.rst b/docs/api/backends/vector.backends.rst deleted file mode 100644 index 4b506913..00000000 --- a/docs/api/backends/vector.backends.rst +++ /dev/null @@ -1,22 +0,0 @@ -vector.backends package -========================= - -.. automodule:: vector.backends - :members: - :undoc-members: - :show-inheritance: - :private-members: - -Submodules ----------- - -.. toctree:: - :maxdepth: 1 - - vector.backends.object - vector.backends.numpy - vector.backends.awkward - vector.backends.awkward_constructors - vector.backends._numba - vector.backends.numba_numpy - vector.backends._numba_object diff --git a/docs/api/compute/lorentz/vector._compute.lorentz.Et.rst b/docs/api/compute/lorentz/vector._compute.lorentz.Et.rst deleted file mode 100644 index 4b874530..00000000 --- a/docs/api/compute/lorentz/vector._compute.lorentz.Et.rst +++ /dev/null @@ -1,8 +0,0 @@ -vector._compute.lorentz.Et module -================================= - -.. automodule:: vector._compute.lorentz.Et - :members: - :undoc-members: - :show-inheritance: - :private-members: diff --git a/docs/api/compute/lorentz/vector._compute.lorentz.Et2.rst b/docs/api/compute/lorentz/vector._compute.lorentz.Et2.rst deleted file mode 100644 index 6947ccfa..00000000 --- a/docs/api/compute/lorentz/vector._compute.lorentz.Et2.rst +++ /dev/null @@ -1,8 +0,0 @@ -vector._compute.lorentz.Et2 module -================================== - -.. automodule:: vector._compute.lorentz.Et2 - :members: - :undoc-members: - :show-inheritance: - :private-members: diff --git a/docs/api/compute/lorentz/vector._compute.lorentz.Mt.rst b/docs/api/compute/lorentz/vector._compute.lorentz.Mt.rst deleted file mode 100644 index d7c88339..00000000 --- a/docs/api/compute/lorentz/vector._compute.lorentz.Mt.rst +++ /dev/null @@ -1,8 +0,0 @@ -vector._compute.lorentz.Mt module -================================= - -.. automodule:: vector._compute.lorentz.Mt - :members: - :undoc-members: - :show-inheritance: - :private-members: diff --git a/docs/api/compute/lorentz/vector._compute.lorentz.Mt2.rst b/docs/api/compute/lorentz/vector._compute.lorentz.Mt2.rst deleted file mode 100644 index 04726768..00000000 --- a/docs/api/compute/lorentz/vector._compute.lorentz.Mt2.rst +++ /dev/null @@ -1,8 +0,0 @@ -vector._compute.lorentz.Mt2 module -================================== - -.. automodule:: vector._compute.lorentz.Mt2 - :members: - :undoc-members: - :show-inheritance: - :private-members: diff --git a/docs/api/compute/lorentz/vector._compute.lorentz.add.rst b/docs/api/compute/lorentz/vector._compute.lorentz.add.rst deleted file mode 100644 index 06c98c34..00000000 --- a/docs/api/compute/lorentz/vector._compute.lorentz.add.rst +++ /dev/null @@ -1,8 +0,0 @@ -vector._compute.lorentz.add module -================================== - -.. automodule:: vector._compute.lorentz.add - :members: - :undoc-members: - :show-inheritance: - :private-members: diff --git a/docs/api/compute/lorentz/vector._compute.lorentz.beta.rst b/docs/api/compute/lorentz/vector._compute.lorentz.beta.rst deleted file mode 100644 index 6dd1618f..00000000 --- a/docs/api/compute/lorentz/vector._compute.lorentz.beta.rst +++ /dev/null @@ -1,8 +0,0 @@ -vector._compute.lorentz.beta module -=================================== - -.. automodule:: vector._compute.lorentz.beta - :members: - :undoc-members: - :show-inheritance: - :private-members: diff --git a/docs/api/compute/lorentz/vector._compute.lorentz.boostX_beta.rst b/docs/api/compute/lorentz/vector._compute.lorentz.boostX_beta.rst deleted file mode 100644 index 084118a6..00000000 --- a/docs/api/compute/lorentz/vector._compute.lorentz.boostX_beta.rst +++ /dev/null @@ -1,8 +0,0 @@ -vector._compute.lorentz.boostX_beta module -========================================== - -.. automodule:: vector._compute.lorentz.boostX_beta - :members: - :undoc-members: - :show-inheritance: - :private-members: diff --git a/docs/api/compute/lorentz/vector._compute.lorentz.boostX_gamma.rst b/docs/api/compute/lorentz/vector._compute.lorentz.boostX_gamma.rst deleted file mode 100644 index 3ce1d974..00000000 --- a/docs/api/compute/lorentz/vector._compute.lorentz.boostX_gamma.rst +++ /dev/null @@ -1,8 +0,0 @@ -vector._compute.lorentz.boostX_gamma module -=========================================== - -.. automodule:: vector._compute.lorentz.boostX_gamma - :members: - :undoc-members: - :show-inheritance: - :private-members: diff --git a/docs/api/compute/lorentz/vector._compute.lorentz.boostY_beta.rst b/docs/api/compute/lorentz/vector._compute.lorentz.boostY_beta.rst deleted file mode 100644 index 4c28dd95..00000000 --- a/docs/api/compute/lorentz/vector._compute.lorentz.boostY_beta.rst +++ /dev/null @@ -1,8 +0,0 @@ -vector._compute.lorentz.boostY_beta module -========================================== - -.. automodule:: vector._compute.lorentz.boostY_beta - :members: - :undoc-members: - :show-inheritance: - :private-members: diff --git a/docs/api/compute/lorentz/vector._compute.lorentz.boostY_gamma.rst b/docs/api/compute/lorentz/vector._compute.lorentz.boostY_gamma.rst deleted file mode 100644 index 25491f77..00000000 --- a/docs/api/compute/lorentz/vector._compute.lorentz.boostY_gamma.rst +++ /dev/null @@ -1,8 +0,0 @@ -vector._compute.lorentz.boostY_gamma module -=========================================== - -.. automodule:: vector._compute.lorentz.boostY_gamma - :members: - :undoc-members: - :show-inheritance: - :private-members: diff --git a/docs/api/compute/lorentz/vector._compute.lorentz.boostZ_beta.rst b/docs/api/compute/lorentz/vector._compute.lorentz.boostZ_beta.rst deleted file mode 100644 index 1190f043..00000000 --- a/docs/api/compute/lorentz/vector._compute.lorentz.boostZ_beta.rst +++ /dev/null @@ -1,8 +0,0 @@ -vector._compute.lorentz.boostZ_beta module -========================================== - -.. automodule:: vector._compute.lorentz.boostZ_beta - :members: - :undoc-members: - :show-inheritance: - :private-members: diff --git a/docs/api/compute/lorentz/vector._compute.lorentz.boostZ_gamma.rst b/docs/api/compute/lorentz/vector._compute.lorentz.boostZ_gamma.rst deleted file mode 100644 index 85492a60..00000000 --- a/docs/api/compute/lorentz/vector._compute.lorentz.boostZ_gamma.rst +++ /dev/null @@ -1,8 +0,0 @@ -vector._compute.lorentz.boostZ_gamma module -=========================================== - -.. automodule:: vector._compute.lorentz.boostZ_gamma - :members: - :undoc-members: - :show-inheritance: - :private-members: diff --git a/docs/api/compute/lorentz/vector._compute.lorentz.boost_beta3.rst b/docs/api/compute/lorentz/vector._compute.lorentz.boost_beta3.rst deleted file mode 100644 index 3b938c1b..00000000 --- a/docs/api/compute/lorentz/vector._compute.lorentz.boost_beta3.rst +++ /dev/null @@ -1,8 +0,0 @@ -vector._compute.lorentz.boost_beta3 module -========================================== - -.. automodule:: vector._compute.lorentz.boost_beta3 - :members: - :undoc-members: - :show-inheritance: - :private-members: diff --git a/docs/api/compute/lorentz/vector._compute.lorentz.boost_p4.rst b/docs/api/compute/lorentz/vector._compute.lorentz.boost_p4.rst deleted file mode 100644 index 3dc0be1d..00000000 --- a/docs/api/compute/lorentz/vector._compute.lorentz.boost_p4.rst +++ /dev/null @@ -1,8 +0,0 @@ -vector._compute.lorentz.boost_p4 module -======================================= - -.. automodule:: vector._compute.lorentz.boost_p4 - :members: - :undoc-members: - :show-inheritance: - :private-members: diff --git a/docs/api/compute/lorentz/vector._compute.lorentz.deltaRapidityPhi.rst b/docs/api/compute/lorentz/vector._compute.lorentz.deltaRapidityPhi.rst deleted file mode 100644 index 4b784ecc..00000000 --- a/docs/api/compute/lorentz/vector._compute.lorentz.deltaRapidityPhi.rst +++ /dev/null @@ -1,8 +0,0 @@ -vector._compute.lorentz.deltaRapidityPhi module -=============================================== - -.. automodule:: vector._compute.lorentz.deltaRapidityPhi - :members: - :undoc-members: - :show-inheritance: - :private-members: diff --git a/docs/api/compute/lorentz/vector._compute.lorentz.deltaRapidityPhi2.rst b/docs/api/compute/lorentz/vector._compute.lorentz.deltaRapidityPhi2.rst deleted file mode 100644 index 7931d03c..00000000 --- a/docs/api/compute/lorentz/vector._compute.lorentz.deltaRapidityPhi2.rst +++ /dev/null @@ -1,8 +0,0 @@ -vector._compute.lorentz.deltaRapidityPhi2 module -================================================ - -.. automodule:: vector._compute.lorentz.deltaRapidityPhi2 - :members: - :undoc-members: - :show-inheritance: - :private-members: diff --git a/docs/api/compute/lorentz/vector._compute.lorentz.dot.rst b/docs/api/compute/lorentz/vector._compute.lorentz.dot.rst deleted file mode 100644 index 92172bb1..00000000 --- a/docs/api/compute/lorentz/vector._compute.lorentz.dot.rst +++ /dev/null @@ -1,8 +0,0 @@ -vector._compute.lorentz.dot module -================================== - -.. automodule:: vector._compute.lorentz.dot - :members: - :undoc-members: - :show-inheritance: - :private-members: diff --git a/docs/api/compute/lorentz/vector._compute.lorentz.equal.rst b/docs/api/compute/lorentz/vector._compute.lorentz.equal.rst deleted file mode 100644 index 4a8c247a..00000000 --- a/docs/api/compute/lorentz/vector._compute.lorentz.equal.rst +++ /dev/null @@ -1,8 +0,0 @@ -vector._compute.lorentz.equal module -==================================== - -.. automodule:: vector._compute.lorentz.equal - :members: - :undoc-members: - :show-inheritance: - :private-members: diff --git a/docs/api/compute/lorentz/vector._compute.lorentz.gamma.rst b/docs/api/compute/lorentz/vector._compute.lorentz.gamma.rst deleted file mode 100644 index 81189377..00000000 --- a/docs/api/compute/lorentz/vector._compute.lorentz.gamma.rst +++ /dev/null @@ -1,8 +0,0 @@ -vector._compute.lorentz.gamma module -==================================== - -.. automodule:: vector._compute.lorentz.gamma - :members: - :undoc-members: - :show-inheritance: - :private-members: diff --git a/docs/api/compute/lorentz/vector._compute.lorentz.is_lightlike.rst b/docs/api/compute/lorentz/vector._compute.lorentz.is_lightlike.rst deleted file mode 100644 index b22dbd8c..00000000 --- a/docs/api/compute/lorentz/vector._compute.lorentz.is_lightlike.rst +++ /dev/null @@ -1,8 +0,0 @@ -vector._compute.lorentz.is_lightlike module -=========================================== - -.. automodule:: vector._compute.lorentz.is_lightlike - :members: - :undoc-members: - :show-inheritance: - :private-members: diff --git a/docs/api/compute/lorentz/vector._compute.lorentz.is_spacelike.rst b/docs/api/compute/lorentz/vector._compute.lorentz.is_spacelike.rst deleted file mode 100644 index 0056c874..00000000 --- a/docs/api/compute/lorentz/vector._compute.lorentz.is_spacelike.rst +++ /dev/null @@ -1,8 +0,0 @@ -vector._compute.lorentz.is_spacelike module -=========================================== - -.. automodule:: vector._compute.lorentz.is_spacelike - :members: - :undoc-members: - :show-inheritance: - :private-members: diff --git a/docs/api/compute/lorentz/vector._compute.lorentz.is_timelike.rst b/docs/api/compute/lorentz/vector._compute.lorentz.is_timelike.rst deleted file mode 100644 index 5c52aafd..00000000 --- a/docs/api/compute/lorentz/vector._compute.lorentz.is_timelike.rst +++ /dev/null @@ -1,8 +0,0 @@ -vector._compute.lorentz.is_timelike module -========================================== - -.. automodule:: vector._compute.lorentz.is_timelike - :members: - :undoc-members: - :show-inheritance: - :private-members: diff --git a/docs/api/compute/lorentz/vector._compute.lorentz.isclose.rst b/docs/api/compute/lorentz/vector._compute.lorentz.isclose.rst deleted file mode 100644 index 2c859917..00000000 --- a/docs/api/compute/lorentz/vector._compute.lorentz.isclose.rst +++ /dev/null @@ -1,8 +0,0 @@ -vector._compute.lorentz.isclose module -====================================== - -.. automodule:: vector._compute.lorentz.isclose - :members: - :undoc-members: - :show-inheritance: - :private-members: diff --git a/docs/api/compute/lorentz/vector._compute.lorentz.not_equal.rst b/docs/api/compute/lorentz/vector._compute.lorentz.not_equal.rst deleted file mode 100644 index 5c2018b5..00000000 --- a/docs/api/compute/lorentz/vector._compute.lorentz.not_equal.rst +++ /dev/null @@ -1,8 +0,0 @@ -vector._compute.lorentz.not_equal module -======================================== - -.. automodule:: vector._compute.lorentz.not_equal - :members: - :undoc-members: - :show-inheritance: - :private-members: diff --git a/docs/api/compute/lorentz/vector._compute.lorentz.rapidity.rst b/docs/api/compute/lorentz/vector._compute.lorentz.rapidity.rst deleted file mode 100644 index b67afac4..00000000 --- a/docs/api/compute/lorentz/vector._compute.lorentz.rapidity.rst +++ /dev/null @@ -1,8 +0,0 @@ -vector._compute.lorentz.rapidity module -======================================= - -.. automodule:: vector._compute.lorentz.rapidity - :members: - :undoc-members: - :show-inheritance: - :private-members: diff --git a/docs/api/compute/lorentz/vector._compute.lorentz.rst b/docs/api/compute/lorentz/vector._compute.lorentz.rst deleted file mode 100644 index ad8a5d7c..00000000 --- a/docs/api/compute/lorentz/vector._compute.lorentz.rst +++ /dev/null @@ -1,49 +0,0 @@ -vector.\_compute.lorentz package -================================ - -.. automodule:: vector._compute.lorentz - :members: - :undoc-members: - :show-inheritance: - :private-members: - -Submodules ----------- - -.. toctree:: - :maxdepth: 1 - - vector._compute.lorentz.add - vector._compute.lorentz.beta - vector._compute.lorentz.boost_beta3 - vector._compute.lorentz.boost_p4 - vector._compute.lorentz.boostX_beta - vector._compute.lorentz.boostX_gamma - vector._compute.lorentz.boostY_beta - vector._compute.lorentz.boostY_gamma - vector._compute.lorentz.boostZ_beta - vector._compute.lorentz.boostZ_gamma - vector._compute.lorentz.deltaRapidityPhi - vector._compute.lorentz.deltaRapidityPhi2 - vector._compute.lorentz.dot - vector._compute.lorentz.equal - vector._compute.lorentz.Et - vector._compute.lorentz.Et2 - vector._compute.lorentz.gamma - vector._compute.lorentz.is_lightlike - vector._compute.lorentz.is_spacelike - vector._compute.lorentz.is_timelike - vector._compute.lorentz.isclose - vector._compute.lorentz.Mt - vector._compute.lorentz.Mt2 - vector._compute.lorentz.not_equal - vector._compute.lorentz.rapidity - vector._compute.lorentz.scale - vector._compute.lorentz.subtract - vector._compute.lorentz.t - vector._compute.lorentz.t2 - vector._compute.lorentz.tau - vector._compute.lorentz.tau2 - vector._compute.lorentz.to_beta3 - vector._compute.lorentz.transform4D - vector._compute.lorentz.unit diff --git a/docs/api/compute/lorentz/vector._compute.lorentz.scale.rst b/docs/api/compute/lorentz/vector._compute.lorentz.scale.rst deleted file mode 100644 index 3ba5ae9d..00000000 --- a/docs/api/compute/lorentz/vector._compute.lorentz.scale.rst +++ /dev/null @@ -1,8 +0,0 @@ -vector._compute.lorentz.scale module -==================================== - -.. automodule:: vector._compute.lorentz.scale - :members: - :undoc-members: - :show-inheritance: - :private-members: diff --git a/docs/api/compute/lorentz/vector._compute.lorentz.subtract.rst b/docs/api/compute/lorentz/vector._compute.lorentz.subtract.rst deleted file mode 100644 index 4797def6..00000000 --- a/docs/api/compute/lorentz/vector._compute.lorentz.subtract.rst +++ /dev/null @@ -1,8 +0,0 @@ -vector._compute.lorentz.subtract module -======================================= - -.. automodule:: vector._compute.lorentz.subtract - :members: - :undoc-members: - :show-inheritance: - :private-members: diff --git a/docs/api/compute/lorentz/vector._compute.lorentz.t.rst b/docs/api/compute/lorentz/vector._compute.lorentz.t.rst deleted file mode 100644 index 0f035c2e..00000000 --- a/docs/api/compute/lorentz/vector._compute.lorentz.t.rst +++ /dev/null @@ -1,8 +0,0 @@ -vector._compute.lorentz.t module -================================ - -.. automodule:: vector._compute.lorentz.t - :members: - :undoc-members: - :show-inheritance: - :private-members: diff --git a/docs/api/compute/lorentz/vector._compute.lorentz.t2.rst b/docs/api/compute/lorentz/vector._compute.lorentz.t2.rst deleted file mode 100644 index c878c815..00000000 --- a/docs/api/compute/lorentz/vector._compute.lorentz.t2.rst +++ /dev/null @@ -1,8 +0,0 @@ -vector._compute.lorentz.t2 module -================================= - -.. automodule:: vector._compute.lorentz.t2 - :members: - :undoc-members: - :show-inheritance: - :private-members: diff --git a/docs/api/compute/lorentz/vector._compute.lorentz.tau.rst b/docs/api/compute/lorentz/vector._compute.lorentz.tau.rst deleted file mode 100644 index a9c5281c..00000000 --- a/docs/api/compute/lorentz/vector._compute.lorentz.tau.rst +++ /dev/null @@ -1,8 +0,0 @@ -vector._compute.lorentz.tau module -================================== - -.. automodule:: vector._compute.lorentz.tau - :members: - :undoc-members: - :show-inheritance: - :private-members: diff --git a/docs/api/compute/lorentz/vector._compute.lorentz.tau2.rst b/docs/api/compute/lorentz/vector._compute.lorentz.tau2.rst deleted file mode 100644 index f4a888a7..00000000 --- a/docs/api/compute/lorentz/vector._compute.lorentz.tau2.rst +++ /dev/null @@ -1,8 +0,0 @@ -vector._compute.lorentz.tau2 module -=================================== - -.. automodule:: vector._compute.lorentz.tau2 - :members: - :undoc-members: - :show-inheritance: - :private-members: diff --git a/docs/api/compute/lorentz/vector._compute.lorentz.to_beta3.rst b/docs/api/compute/lorentz/vector._compute.lorentz.to_beta3.rst deleted file mode 100644 index 7cd16962..00000000 --- a/docs/api/compute/lorentz/vector._compute.lorentz.to_beta3.rst +++ /dev/null @@ -1,8 +0,0 @@ -vector._compute.lorentz.to_beta3 module -======================================= - -.. automodule:: vector._compute.lorentz.to_beta3 - :members: - :undoc-members: - :show-inheritance: - :private-members: diff --git a/docs/api/compute/lorentz/vector._compute.lorentz.transform4D.rst b/docs/api/compute/lorentz/vector._compute.lorentz.transform4D.rst deleted file mode 100644 index 307777c1..00000000 --- a/docs/api/compute/lorentz/vector._compute.lorentz.transform4D.rst +++ /dev/null @@ -1,8 +0,0 @@ -vector._compute.lorentz.transform4D module -========================================== - -.. automodule:: vector._compute.lorentz.transform4D - :members: - :undoc-members: - :show-inheritance: - :private-members: diff --git a/docs/api/compute/lorentz/vector._compute.lorentz.unit.rst b/docs/api/compute/lorentz/vector._compute.lorentz.unit.rst deleted file mode 100644 index 3efacdb1..00000000 --- a/docs/api/compute/lorentz/vector._compute.lorentz.unit.rst +++ /dev/null @@ -1,8 +0,0 @@ -vector._compute.lorentz.unit module -=================================== - -.. automodule:: vector._compute.lorentz.unit - :members: - :undoc-members: - :show-inheritance: - :private-members: diff --git a/docs/api/compute/planar/vector._compute.planar.add.rst b/docs/api/compute/planar/vector._compute.planar.add.rst deleted file mode 100644 index d6e998f5..00000000 --- a/docs/api/compute/planar/vector._compute.planar.add.rst +++ /dev/null @@ -1,8 +0,0 @@ -vector._compute.planar.add module -================================= - -.. automodule:: vector._compute.planar.add - :members: - :undoc-members: - :show-inheritance: - :private-members: diff --git a/docs/api/compute/planar/vector._compute.planar.deltaphi.rst b/docs/api/compute/planar/vector._compute.planar.deltaphi.rst deleted file mode 100644 index 3ef6cbc6..00000000 --- a/docs/api/compute/planar/vector._compute.planar.deltaphi.rst +++ /dev/null @@ -1,8 +0,0 @@ -vector._compute.planar.deltaphi module -====================================== - -.. automodule:: vector._compute.planar.deltaphi - :members: - :undoc-members: - :show-inheritance: - :private-members: diff --git a/docs/api/compute/planar/vector._compute.planar.dot.rst b/docs/api/compute/planar/vector._compute.planar.dot.rst deleted file mode 100644 index 8183e6c0..00000000 --- a/docs/api/compute/planar/vector._compute.planar.dot.rst +++ /dev/null @@ -1,8 +0,0 @@ -vector._compute.planar.dot module -================================= - -.. automodule:: vector._compute.planar.dot - :members: - :undoc-members: - :show-inheritance: - :private-members: diff --git a/docs/api/compute/planar/vector._compute.planar.equal.rst b/docs/api/compute/planar/vector._compute.planar.equal.rst deleted file mode 100644 index 4bb6c445..00000000 --- a/docs/api/compute/planar/vector._compute.planar.equal.rst +++ /dev/null @@ -1,8 +0,0 @@ -vector._compute.planar.equal module -=================================== - -.. automodule:: vector._compute.planar.equal - :members: - :undoc-members: - :show-inheritance: - :private-members: diff --git a/docs/api/compute/planar/vector._compute.planar.is_antiparallel.rst b/docs/api/compute/planar/vector._compute.planar.is_antiparallel.rst deleted file mode 100644 index 3a208ac2..00000000 --- a/docs/api/compute/planar/vector._compute.planar.is_antiparallel.rst +++ /dev/null @@ -1,8 +0,0 @@ -vector._compute.planar.is_antiparallel module -============================================= - -.. automodule:: vector._compute.planar.is_antiparallel - :members: - :undoc-members: - :show-inheritance: - :private-members: diff --git a/docs/api/compute/planar/vector._compute.planar.is_parallel.rst b/docs/api/compute/planar/vector._compute.planar.is_parallel.rst deleted file mode 100644 index f3cff1b5..00000000 --- a/docs/api/compute/planar/vector._compute.planar.is_parallel.rst +++ /dev/null @@ -1,8 +0,0 @@ -vector._compute.planar.is_parallel module -========================================= - -.. automodule:: vector._compute.planar.is_parallel - :members: - :undoc-members: - :show-inheritance: - :private-members: diff --git a/docs/api/compute/planar/vector._compute.planar.is_perpendicular.rst b/docs/api/compute/planar/vector._compute.planar.is_perpendicular.rst deleted file mode 100644 index 9d3ea543..00000000 --- a/docs/api/compute/planar/vector._compute.planar.is_perpendicular.rst +++ /dev/null @@ -1,8 +0,0 @@ -vector._compute.planar.is_perpendicular module -============================================== - -.. automodule:: vector._compute.planar.is_perpendicular - :members: - :undoc-members: - :show-inheritance: - :private-members: diff --git a/docs/api/compute/planar/vector._compute.planar.isclose.rst b/docs/api/compute/planar/vector._compute.planar.isclose.rst deleted file mode 100644 index 95cca66d..00000000 --- a/docs/api/compute/planar/vector._compute.planar.isclose.rst +++ /dev/null @@ -1,8 +0,0 @@ -vector._compute.planar.isclose module -===================================== - -.. automodule:: vector._compute.planar.isclose - :members: - :undoc-members: - :show-inheritance: - :private-members: diff --git a/docs/api/compute/planar/vector._compute.planar.not_equal.rst b/docs/api/compute/planar/vector._compute.planar.not_equal.rst deleted file mode 100644 index c407cc65..00000000 --- a/docs/api/compute/planar/vector._compute.planar.not_equal.rst +++ /dev/null @@ -1,8 +0,0 @@ -vector._compute.planar.not_equal module -======================================= - -.. automodule:: vector._compute.planar.not_equal - :members: - :undoc-members: - :show-inheritance: - :private-members: diff --git a/docs/api/compute/planar/vector._compute.planar.phi.rst b/docs/api/compute/planar/vector._compute.planar.phi.rst deleted file mode 100644 index 2782f0a0..00000000 --- a/docs/api/compute/planar/vector._compute.planar.phi.rst +++ /dev/null @@ -1,8 +0,0 @@ -vector._compute.planar.phi module -================================= - -.. automodule:: vector._compute.planar.phi - :members: - :undoc-members: - :show-inheritance: - :private-members: diff --git a/docs/api/compute/planar/vector._compute.planar.rho.rst b/docs/api/compute/planar/vector._compute.planar.rho.rst deleted file mode 100644 index bde020ab..00000000 --- a/docs/api/compute/planar/vector._compute.planar.rho.rst +++ /dev/null @@ -1,8 +0,0 @@ -vector._compute.planar.rho module -================================= - -.. automodule:: vector._compute.planar.rho - :members: - :undoc-members: - :show-inheritance: - :private-members: diff --git a/docs/api/compute/planar/vector._compute.planar.rho2.rst b/docs/api/compute/planar/vector._compute.planar.rho2.rst deleted file mode 100644 index 42addaba..00000000 --- a/docs/api/compute/planar/vector._compute.planar.rho2.rst +++ /dev/null @@ -1,8 +0,0 @@ -vector._compute.planar.rho2 module -================================== - -.. automodule:: vector._compute.planar.rho2 - :members: - :undoc-members: - :show-inheritance: - :private-members: diff --git a/docs/api/compute/planar/vector._compute.planar.rotateZ.rst b/docs/api/compute/planar/vector._compute.planar.rotateZ.rst deleted file mode 100644 index 9f46d3d2..00000000 --- a/docs/api/compute/planar/vector._compute.planar.rotateZ.rst +++ /dev/null @@ -1,8 +0,0 @@ -vector._compute.planar.rotateZ module -===================================== - -.. automodule:: vector._compute.planar.rotateZ - :members: - :undoc-members: - :show-inheritance: - :private-members: diff --git a/docs/api/compute/planar/vector._compute.planar.rst b/docs/api/compute/planar/vector._compute.planar.rst deleted file mode 100644 index b89254bd..00000000 --- a/docs/api/compute/planar/vector._compute.planar.rst +++ /dev/null @@ -1,34 +0,0 @@ -vector.\_compute.planar package -=============================== - -.. automodule:: vector._compute.planar - :members: - :undoc-members: - :show-inheritance: - :private-members: - -Submodules ----------- - -.. toctree:: - :maxdepth: 1 - - vector._compute.planar.add - vector._compute.planar.deltaphi - vector._compute.planar.dot - vector._compute.planar.equal - vector._compute.planar.is_antiparallel - vector._compute.planar.is_parallel - vector._compute.planar.is_perpendicular - vector._compute.planar.isclose - vector._compute.planar.not_equal - vector._compute.planar.phi - vector._compute.planar.rho - vector._compute.planar.rho2 - vector._compute.planar.rotateZ - vector._compute.planar.scale - vector._compute.planar.subtract - vector._compute.planar.transform2D - vector._compute.planar.unit - vector._compute.planar.x - vector._compute.planar.y \ No newline at end of file diff --git a/docs/api/compute/planar/vector._compute.planar.scale.rst b/docs/api/compute/planar/vector._compute.planar.scale.rst deleted file mode 100644 index 623ff94d..00000000 --- a/docs/api/compute/planar/vector._compute.planar.scale.rst +++ /dev/null @@ -1,8 +0,0 @@ -vector._compute.planar.scale module -=================================== - -.. automodule:: vector._compute.planar.scale - :members: - :undoc-members: - :show-inheritance: - :private-members: diff --git a/docs/api/compute/planar/vector._compute.planar.subtract.rst b/docs/api/compute/planar/vector._compute.planar.subtract.rst deleted file mode 100644 index 0e0a9c22..00000000 --- a/docs/api/compute/planar/vector._compute.planar.subtract.rst +++ /dev/null @@ -1,8 +0,0 @@ -vector._compute.planar.subtract module -====================================== - -.. automodule:: vector._compute.planar.subtract - :members: - :undoc-members: - :show-inheritance: - :private-members: diff --git a/docs/api/compute/planar/vector._compute.planar.transform2D.rst b/docs/api/compute/planar/vector._compute.planar.transform2D.rst deleted file mode 100644 index f8ca6d42..00000000 --- a/docs/api/compute/planar/vector._compute.planar.transform2D.rst +++ /dev/null @@ -1,8 +0,0 @@ -vector._compute.planar.transform2D module -========================================= - -.. automodule:: vector._compute.planar.transform2D - :members: - :undoc-members: - :show-inheritance: - :private-members: diff --git a/docs/api/compute/planar/vector._compute.planar.unit.rst b/docs/api/compute/planar/vector._compute.planar.unit.rst deleted file mode 100644 index 74cedaf5..00000000 --- a/docs/api/compute/planar/vector._compute.planar.unit.rst +++ /dev/null @@ -1,8 +0,0 @@ -vector._compute.planar.unit module -================================== - -.. automodule:: vector._compute.planar.unit - :members: - :undoc-members: - :show-inheritance: - :private-members: diff --git a/docs/api/compute/planar/vector._compute.planar.x.rst b/docs/api/compute/planar/vector._compute.planar.x.rst deleted file mode 100644 index 82dac956..00000000 --- a/docs/api/compute/planar/vector._compute.planar.x.rst +++ /dev/null @@ -1,8 +0,0 @@ -vector._compute.planar.x module -=============================== - -.. automodule:: vector._compute.planar.x - :members: - :undoc-members: - :show-inheritance: - :private-members: diff --git a/docs/api/compute/planar/vector._compute.planar.y.rst b/docs/api/compute/planar/vector._compute.planar.y.rst deleted file mode 100644 index 60345525..00000000 --- a/docs/api/compute/planar/vector._compute.planar.y.rst +++ /dev/null @@ -1,8 +0,0 @@ -vector._compute.planar.y module -=============================== - -.. automodule:: vector._compute.planar.y - :members: - :undoc-members: - :show-inheritance: - :private-members: diff --git a/docs/api/compute/spatial/vector._compute.spatial.add.rst b/docs/api/compute/spatial/vector._compute.spatial.add.rst deleted file mode 100644 index b1340164..00000000 --- a/docs/api/compute/spatial/vector._compute.spatial.add.rst +++ /dev/null @@ -1,8 +0,0 @@ -vector._compute.spatial.add module -================================== - -.. automodule:: vector._compute.spatial.add - :members: - :undoc-members: - :show-inheritance: - :private-members: diff --git a/docs/api/compute/spatial/vector._compute.spatial.costheta.rst b/docs/api/compute/spatial/vector._compute.spatial.costheta.rst deleted file mode 100644 index f4888b23..00000000 --- a/docs/api/compute/spatial/vector._compute.spatial.costheta.rst +++ /dev/null @@ -1,8 +0,0 @@ -vector._compute.spatial.costheta module -======================================= - -.. automodule:: vector._compute.spatial.costheta - :members: - :undoc-members: - :show-inheritance: - :private-members: diff --git a/docs/api/compute/spatial/vector._compute.spatial.cottheta.rst b/docs/api/compute/spatial/vector._compute.spatial.cottheta.rst deleted file mode 100644 index 2d33b327..00000000 --- a/docs/api/compute/spatial/vector._compute.spatial.cottheta.rst +++ /dev/null @@ -1,8 +0,0 @@ -vector._compute.spatial.cottheta module -======================================= - -.. automodule:: vector._compute.spatial.cottheta - :members: - :undoc-members: - :show-inheritance: - :private-members: diff --git a/docs/api/compute/spatial/vector._compute.spatial.cross.rst b/docs/api/compute/spatial/vector._compute.spatial.cross.rst deleted file mode 100644 index a95d106f..00000000 --- a/docs/api/compute/spatial/vector._compute.spatial.cross.rst +++ /dev/null @@ -1,8 +0,0 @@ -vector._compute.spatial.cross module -==================================== - -.. automodule:: vector._compute.spatial.cross - :members: - :undoc-members: - :show-inheritance: - :private-members: diff --git a/docs/api/compute/spatial/vector._compute.spatial.deltaR.rst b/docs/api/compute/spatial/vector._compute.spatial.deltaR.rst deleted file mode 100644 index 4e21d5cd..00000000 --- a/docs/api/compute/spatial/vector._compute.spatial.deltaR.rst +++ /dev/null @@ -1,8 +0,0 @@ -vector._compute.spatial.deltaR module -===================================== - -.. automodule:: vector._compute.spatial.deltaR - :members: - :undoc-members: - :show-inheritance: - :private-members: diff --git a/docs/api/compute/spatial/vector._compute.spatial.deltaR2.rst b/docs/api/compute/spatial/vector._compute.spatial.deltaR2.rst deleted file mode 100644 index 1e5f70af..00000000 --- a/docs/api/compute/spatial/vector._compute.spatial.deltaR2.rst +++ /dev/null @@ -1,8 +0,0 @@ -vector._compute.spatial.deltaR2 module -====================================== - -.. automodule:: vector._compute.spatial.deltaR2 - :members: - :undoc-members: - :show-inheritance: - :private-members: diff --git a/docs/api/compute/spatial/vector._compute.spatial.deltaangle.rst b/docs/api/compute/spatial/vector._compute.spatial.deltaangle.rst deleted file mode 100644 index 8cc43d96..00000000 --- a/docs/api/compute/spatial/vector._compute.spatial.deltaangle.rst +++ /dev/null @@ -1,8 +0,0 @@ -vector._compute.spatial.deltaangle module -========================================= - -.. automodule:: vector._compute.spatial.deltaangle - :members: - :undoc-members: - :show-inheritance: - :private-members: diff --git a/docs/api/compute/spatial/vector._compute.spatial.deltaeta.rst b/docs/api/compute/spatial/vector._compute.spatial.deltaeta.rst deleted file mode 100644 index 87688a1c..00000000 --- a/docs/api/compute/spatial/vector._compute.spatial.deltaeta.rst +++ /dev/null @@ -1,8 +0,0 @@ -vector._compute.spatial.deltaeta module -======================================= - -.. automodule:: vector._compute.spatial.deltaeta - :members: - :undoc-members: - :show-inheritance: - :private-members: diff --git a/docs/api/compute/spatial/vector._compute.spatial.dot.rst b/docs/api/compute/spatial/vector._compute.spatial.dot.rst deleted file mode 100644 index 5d81c1e1..00000000 --- a/docs/api/compute/spatial/vector._compute.spatial.dot.rst +++ /dev/null @@ -1,8 +0,0 @@ -vector._compute.spatial.dot module -================================== - -.. automodule:: vector._compute.spatial.dot - :members: - :undoc-members: - :show-inheritance: - :private-members: diff --git a/docs/api/compute/spatial/vector._compute.spatial.equal.rst b/docs/api/compute/spatial/vector._compute.spatial.equal.rst deleted file mode 100644 index a47e55b8..00000000 --- a/docs/api/compute/spatial/vector._compute.spatial.equal.rst +++ /dev/null @@ -1,8 +0,0 @@ -vector._compute.spatial.equal module -==================================== - -.. automodule:: vector._compute.spatial.equal - :members: - :undoc-members: - :show-inheritance: - :private-members: diff --git a/docs/api/compute/spatial/vector._compute.spatial.eta.rst b/docs/api/compute/spatial/vector._compute.spatial.eta.rst deleted file mode 100644 index 5da8df35..00000000 --- a/docs/api/compute/spatial/vector._compute.spatial.eta.rst +++ /dev/null @@ -1,8 +0,0 @@ -vector._compute.spatial.eta module -================================== - -.. automodule:: vector._compute.spatial.eta - :members: - :undoc-members: - :show-inheritance: - :private-members: diff --git a/docs/api/compute/spatial/vector._compute.spatial.is_antiparallel.rst b/docs/api/compute/spatial/vector._compute.spatial.is_antiparallel.rst deleted file mode 100644 index ffeb0977..00000000 --- a/docs/api/compute/spatial/vector._compute.spatial.is_antiparallel.rst +++ /dev/null @@ -1,8 +0,0 @@ -vector._compute.spatial.is_antiparallel module -============================================== - -.. automodule:: vector._compute.spatial.is_antiparallel - :members: - :undoc-members: - :show-inheritance: - :private-members: diff --git a/docs/api/compute/spatial/vector._compute.spatial.is_parallel.rst b/docs/api/compute/spatial/vector._compute.spatial.is_parallel.rst deleted file mode 100644 index 6bd9d884..00000000 --- a/docs/api/compute/spatial/vector._compute.spatial.is_parallel.rst +++ /dev/null @@ -1,8 +0,0 @@ -vector._compute.spatial.is_parallel module -========================================== - -.. automodule:: vector._compute.spatial.is_parallel - :members: - :undoc-members: - :show-inheritance: - :private-members: diff --git a/docs/api/compute/spatial/vector._compute.spatial.is_perpendicular.rst b/docs/api/compute/spatial/vector._compute.spatial.is_perpendicular.rst deleted file mode 100644 index 9cff7e49..00000000 --- a/docs/api/compute/spatial/vector._compute.spatial.is_perpendicular.rst +++ /dev/null @@ -1,8 +0,0 @@ -vector._compute.spatial.is_perpendicular module -=============================================== - -.. automodule:: vector._compute.spatial.is_perpendicular - :members: - :undoc-members: - :show-inheritance: - :private-members: diff --git a/docs/api/compute/spatial/vector._compute.spatial.isclose.rst b/docs/api/compute/spatial/vector._compute.spatial.isclose.rst deleted file mode 100644 index 861fce43..00000000 --- a/docs/api/compute/spatial/vector._compute.spatial.isclose.rst +++ /dev/null @@ -1,8 +0,0 @@ -vector._compute.spatial.isclose module -====================================== - -.. automodule:: vector._compute.spatial.isclose - :members: - :undoc-members: - :show-inheritance: - :private-members: diff --git a/docs/api/compute/spatial/vector._compute.spatial.mag.rst b/docs/api/compute/spatial/vector._compute.spatial.mag.rst deleted file mode 100644 index 1c7f638d..00000000 --- a/docs/api/compute/spatial/vector._compute.spatial.mag.rst +++ /dev/null @@ -1,8 +0,0 @@ -vector._compute.spatial.mag module -================================== - -.. automodule:: vector._compute.spatial.mag - :members: - :undoc-members: - :show-inheritance: - :private-members: diff --git a/docs/api/compute/spatial/vector._compute.spatial.mag2.rst b/docs/api/compute/spatial/vector._compute.spatial.mag2.rst deleted file mode 100644 index fdcbcf13..00000000 --- a/docs/api/compute/spatial/vector._compute.spatial.mag2.rst +++ /dev/null @@ -1,8 +0,0 @@ -vector._compute.spatial.mag2 module -=================================== - -.. automodule:: vector._compute.spatial.mag2 - :members: - :undoc-members: - :show-inheritance: - :private-members: diff --git a/docs/api/compute/spatial/vector._compute.spatial.not_equal.rst b/docs/api/compute/spatial/vector._compute.spatial.not_equal.rst deleted file mode 100644 index 303832b6..00000000 --- a/docs/api/compute/spatial/vector._compute.spatial.not_equal.rst +++ /dev/null @@ -1,8 +0,0 @@ -vector._compute.spatial.not_equal module -======================================== - -.. automodule:: vector._compute.spatial.not_equal - :members: - :undoc-members: - :show-inheritance: - :private-members: diff --git a/docs/api/compute/spatial/vector._compute.spatial.rotateX.rst b/docs/api/compute/spatial/vector._compute.spatial.rotateX.rst deleted file mode 100644 index eb75af92..00000000 --- a/docs/api/compute/spatial/vector._compute.spatial.rotateX.rst +++ /dev/null @@ -1,8 +0,0 @@ -vector._compute.spatial.rotateX module -====================================== - -.. automodule:: vector._compute.spatial.rotateX - :members: - :undoc-members: - :show-inheritance: - :private-members: diff --git a/docs/api/compute/spatial/vector._compute.spatial.rotateY.rst b/docs/api/compute/spatial/vector._compute.spatial.rotateY.rst deleted file mode 100644 index 9eb279be..00000000 --- a/docs/api/compute/spatial/vector._compute.spatial.rotateY.rst +++ /dev/null @@ -1,8 +0,0 @@ -vector._compute.spatial.rotateY module -====================================== - -.. automodule:: vector._compute.spatial.rotateY - :members: - :undoc-members: - :show-inheritance: - :private-members: diff --git a/docs/api/compute/spatial/vector._compute.spatial.rotate_axis.rst b/docs/api/compute/spatial/vector._compute.spatial.rotate_axis.rst deleted file mode 100644 index ffe10600..00000000 --- a/docs/api/compute/spatial/vector._compute.spatial.rotate_axis.rst +++ /dev/null @@ -1,8 +0,0 @@ -vector._compute.spatial.rotate_axis module -========================================== - -.. automodule:: vector._compute.spatial.rotate_axis - :members: - :undoc-members: - :show-inheritance: - :private-members: diff --git a/docs/api/compute/spatial/vector._compute.spatial.rotate_euler.rst b/docs/api/compute/spatial/vector._compute.spatial.rotate_euler.rst deleted file mode 100644 index 11be2f2a..00000000 --- a/docs/api/compute/spatial/vector._compute.spatial.rotate_euler.rst +++ /dev/null @@ -1,8 +0,0 @@ -vector._compute.spatial.rotate_euler module -=========================================== - -.. automodule:: vector._compute.spatial.rotate_euler - :members: - :undoc-members: - :show-inheritance: - :private-members: diff --git a/docs/api/compute/spatial/vector._compute.spatial.rotate_quaternion.rst b/docs/api/compute/spatial/vector._compute.spatial.rotate_quaternion.rst deleted file mode 100644 index ab982cd1..00000000 --- a/docs/api/compute/spatial/vector._compute.spatial.rotate_quaternion.rst +++ /dev/null @@ -1,8 +0,0 @@ -vector._compute.spatial.rotate_quaternion module -================================================ - -.. automodule:: vector._compute.spatial.rotate_quaternion - :members: - :undoc-members: - :show-inheritance: - :private-members: diff --git a/docs/api/compute/spatial/vector._compute.spatial.rst b/docs/api/compute/spatial/vector._compute.spatial.rst deleted file mode 100644 index 9fcab267..00000000 --- a/docs/api/compute/spatial/vector._compute.spatial.rst +++ /dev/null @@ -1,44 +0,0 @@ -vector.\_compute.spatial package -================================ - -.. automodule:: vector._compute.spatial - :members: - :undoc-members: - :show-inheritance: - :private-members: - -Submodules ----------- - -.. toctree:: - :maxdepth: 1 - - vector._compute.spatial.add - vector._compute.spatial.costheta - vector._compute.spatial.cottheta - vector._compute.spatial.cross - vector._compute.spatial.deltaangle - vector._compute.spatial.deltaeta - vector._compute.spatial.deltaR - vector._compute.spatial.deltaR2 - vector._compute.spatial.dot - vector._compute.spatial.equal - vector._compute.spatial.eta - vector._compute.spatial.is_antiparallel - vector._compute.spatial.is_parallel - vector._compute.spatial.is_perpendicular - vector._compute.spatial.isclose - vector._compute.spatial.mag - vector._compute.spatial.mag2 - vector._compute.spatial.not_equal - vector._compute.spatial.rotate_axis - vector._compute.spatial.rotate_euler - vector._compute.spatial.rotate_quaternion - vector._compute.spatial.rotateX - vector._compute.spatial.rotateY - vector._compute.spatial.scale - vector._compute.spatial.subtract - vector._compute.spatial.theta - vector._compute.spatial.transform3D - vector._compute.spatial.unit - vector._compute.spatial.z diff --git a/docs/api/compute/spatial/vector._compute.spatial.scale.rst b/docs/api/compute/spatial/vector._compute.spatial.scale.rst deleted file mode 100644 index 30f69b23..00000000 --- a/docs/api/compute/spatial/vector._compute.spatial.scale.rst +++ /dev/null @@ -1,8 +0,0 @@ -vector._compute.spatial.scale module -==================================== - -.. automodule:: vector._compute.spatial.scale - :members: - :undoc-members: - :show-inheritance: - :private-members: diff --git a/docs/api/compute/spatial/vector._compute.spatial.subtract.rst b/docs/api/compute/spatial/vector._compute.spatial.subtract.rst deleted file mode 100644 index d2c2b632..00000000 --- a/docs/api/compute/spatial/vector._compute.spatial.subtract.rst +++ /dev/null @@ -1,8 +0,0 @@ -vector._compute.spatial.subtract module -======================================= - -.. automodule:: vector._compute.spatial.subtract - :members: - :undoc-members: - :show-inheritance: - :private-members: diff --git a/docs/api/compute/spatial/vector._compute.spatial.theta.rst b/docs/api/compute/spatial/vector._compute.spatial.theta.rst deleted file mode 100644 index 6db025d2..00000000 --- a/docs/api/compute/spatial/vector._compute.spatial.theta.rst +++ /dev/null @@ -1,8 +0,0 @@ -vector._compute.spatial.theta module -==================================== - -.. automodule:: vector._compute.spatial.theta - :members: - :undoc-members: - :show-inheritance: - :private-members: diff --git a/docs/api/compute/spatial/vector._compute.spatial.transform3D.rst b/docs/api/compute/spatial/vector._compute.spatial.transform3D.rst deleted file mode 100644 index fdd00622..00000000 --- a/docs/api/compute/spatial/vector._compute.spatial.transform3D.rst +++ /dev/null @@ -1,8 +0,0 @@ -vector._compute.spatial.transform3D module -========================================== - -.. automodule:: vector._compute.spatial.transform3D - :members: - :undoc-members: - :show-inheritance: - :private-members: diff --git a/docs/api/compute/spatial/vector._compute.spatial.unit.rst b/docs/api/compute/spatial/vector._compute.spatial.unit.rst deleted file mode 100644 index 847f490e..00000000 --- a/docs/api/compute/spatial/vector._compute.spatial.unit.rst +++ /dev/null @@ -1,8 +0,0 @@ -vector._compute.spatial.unit module -=================================== - -.. automodule:: vector._compute.spatial.unit - :members: - :undoc-members: - :show-inheritance: - :private-members: diff --git a/docs/api/compute/spatial/vector._compute.spatial.z.rst b/docs/api/compute/spatial/vector._compute.spatial.z.rst deleted file mode 100644 index dab3159f..00000000 --- a/docs/api/compute/spatial/vector._compute.spatial.z.rst +++ /dev/null @@ -1,8 +0,0 @@ -vector._compute.spatial.z module -================================ - -.. automodule:: vector._compute.spatial.z - :members: - :undoc-members: - :show-inheritance: - :private-members: diff --git a/docs/api/compute/vector._compute.rst b/docs/api/compute/vector._compute.rst deleted file mode 100644 index 4da83134..00000000 --- a/docs/api/compute/vector._compute.rst +++ /dev/null @@ -1,18 +0,0 @@ -vector.\_compute package -======================== - -.. automodule:: vector._compute - :members: - :undoc-members: - :show-inheritance: - :private-members: - -Subpackages ------------ - -.. toctree:: - :maxdepth: 4 - - lorentz/vector._compute.lorentz - planar/vector._compute.planar - spatial/vector._compute.spatial diff --git a/docs/api/inheritance.svg b/docs/api/inheritance.svg deleted file mode 100644 index 7311a043..00000000 --- a/docs/api/inheritance.svg +++ /dev/null @@ -1,3413 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - image/svg+xml - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Azimuthal - Longitudinal - Temporal - AzimuthalXY - AzimuthalRhoPhi - TemporalT - TemporalTau - Planar - Spatial - Lorentz - AzimuthalObject - LongitudinalObject - TemporalObject - AzimuthalObjectXY - AzimuthalObjectRhoPhi - LongitudinalObjectZ - LongitudinalObjectTheta - LongitudinalObjectEta - TemporalObjectT - TemporalObjectTau - MomentumObject4D - - - - - - Vector - Vector3D - - - Vector2D - Vector4D - - Coordinates - - - - - - - - - VectorObject4D - - - VectorObject3D - MomentumObject3D - - - - - VectorObject2D - MomentumObject2D - - - user interface methods - - mix-in class or superclass - - has data members - - - - class inheritance - - - - - CoordinatesObject - - - - - - LongitudinalZ - LongitudinalTheta - LongitudinalEta - - - VectorObject - - contains object as member - "Object" is one backend.For other backends, replacewith "Numpy", "Awkward", etc. - - contains azimuthal, longitudinal, and temporal - - contains azimuthal - - contains azimuthal and longitudinal - - - - - - - - - - Generic vector mix-insreduce objects to numbersand call a flat-function inthe "compute" modulecorresponding to itscoordinate system. - Momentum mix-insprovide synonymsfor a momentuminterpretation(e.g. "rho" → "pt","tau" → "mass"). - - Momentum - - - - PlanarMomentum - SpatialMomentum - LorentzMomentum - - diff --git a/docs/api/modules.rst b/docs/api/modules.rst deleted file mode 100644 index abbbc901..00000000 --- a/docs/api/modules.rst +++ /dev/null @@ -1,7 +0,0 @@ -vector -====== - -.. toctree:: - :maxdepth: 7 - - vector diff --git a/docs/api/vector._methods.rst b/docs/api/vector._methods.rst deleted file mode 100644 index 28de3616..00000000 --- a/docs/api/vector._methods.rst +++ /dev/null @@ -1,8 +0,0 @@ -vector.\_methods module -======================= - -.. automodule:: vector._methods - :members: - :undoc-members: - :show-inheritance: - :private-members: \ No newline at end of file diff --git a/docs/api/vector._typeutils.rst b/docs/api/vector._typeutils.rst deleted file mode 100644 index 0fd7871e..00000000 --- a/docs/api/vector._typeutils.rst +++ /dev/null @@ -1,8 +0,0 @@ -vector.\_typeutils module -========================= - -.. automodule:: vector._typeutils - :members: - :undoc-members: - :show-inheritance: - :private-members: \ No newline at end of file diff --git a/docs/api/vector.rst b/docs/api/vector.rst deleted file mode 100644 index a0a54f73..00000000 --- a/docs/api/vector.rst +++ /dev/null @@ -1,21 +0,0 @@ -vector package -============== - -Subpackages ------------ - -.. toctree:: - :maxdepth: 7 - - backends/vector.backends - compute/vector._compute - -Submodules ----------- - -.. toctree:: - :maxdepth: 1 - - vector._methods - vector._typeutils - diff --git a/docs/changelog.md b/docs/changelog.md deleted file mode 100644 index a8aadecb..00000000 --- a/docs/changelog.md +++ /dev/null @@ -1,475 +0,0 @@ -# Changelog - -## Version 1.5 - -### Version 1.5.2 - -#### Maintenance - -- ci: 3.13, attestations, and some modernization [#511][] - -[#511]: https://github.com/scikit-hep/vector/pull/511 - -### Version 1.5.1 - -#### Fixes - -- fix: uncap numpy [#502][] - -[#502]: https://github.com/scikit-hep/vector/pull/502 - -### Version 1.5.0 - -#### Breaking - -- drop support for awkward v1 [#434][] - -[#434]: https://github.com/scikit-hep/vector/pull/434 - -## Version 1.4 - -### Version 1.4.3 - -#### Fixes - -- fix: uncap numpy [#502][] - -[#502]: https://github.com/scikit-hep/vector/pull/502 - -### Version 1.4.2 - -#### Fixes - -- fix: depend on numpy<2.1 to support numba [#476][] -- fix: fix ci for awkward v1.x (numpy v2 is out) [#479][] -- fix: sympy tests (sympy v1.13) [#485][] - -#### Documentation - -- docs: update intro notebook + readme [#489][] - -[#476]: https://github.com/scikit-hep/vector/pull/476 -[#479]: https://github.com/scikit-hep/vector/pull/479 -[#485]: https://github.com/scikit-hep/vector/pull/485 -[#489]: https://github.com/scikit-hep/vector/pull/489 - -### Version 1.4.1 - -#### Fixes - -- fix: sympy backend on numpy 2.0 (full numpy 2.0 support) [#473][] -- fix: add lower and upper bounds for deltaangle [#465][] -- fix: maximum for SymPy backend is the identity function now [#465][] -- fix: get coordinate classes to work for numpy [#466][] - -#### Documentation - -- docs: add basic docs for sub-classing awkward mixins [#468][] - -#### Maintenance - -- chore: add missing compute function tests [#454] -- ci: Add GitHub artifact attestations to package distribution [#470][] - -[#473]: https://github.com/scikit-hep/vector/pull/473 -[#465]: https://github.com/scikit-hep/vector/pull/465 -[#466]: https://github.com/scikit-hep/vector/pull/466 -[#468]: https://github.com/scikit-hep/vector/pull/468 -[#454]: https://github.com/scikit-hep/vector/pull/454 -[#470]: https://github.com/scikit-hep/vector/pull/470 - -### Version 1.4.0 - -#### Features - -- feat: allow coord values in to\_ methods [#446][] -- feat: a sympy backend [#442][] - -#### Bug fixes - -- fix: call the square implementation for power 2 on object vectors [#444][] -- fix: use negfactor in negfactor scale test [#456][] - -#### Maintenance - -- chore: test on numpy 2.0 [#451][] - -[#446]: https://github.com/scikit-hep/vector/pull/446 -[#442]: https://github.com/scikit-hep/vector/pull/442 -[#444]: https://github.com/scikit-hep/vector/pull/444 -[#456]: https://github.com/scikit-hep/vector/pull/456 -[#451]: https://github.com/scikit-hep/vector/pull/451 - -## Version 1.3 - -### Version 1.3.1 - -#### Features - -- feat: make momentum-ness infectious [#437][] - -#### Bug fixes - -- fix: support dask-awkward 2024.3.0 [#436][] -- fix: momentum coords should not be repeated with generic coords in subclasses [#438][] - -[#436]: https://github.com/scikit-hep/vector/pull/436 -[#438]: https://github.com/scikit-hep/vector/pull/438 -[#437]: https://github.com/scikit-hep/vector/pull/437 - -### Version 1.3.0 - -#### Features - -- feat: coordinate transformation functions with momentum names [#424][] -- feat: allow momentum coords in to_Vector\*D methods + cleanup [#423][] -- feat: add a lite nox session + add numba as optional dependency [#431][] -- feat: `like` method for projecting vector into the coordinate space of another vector + better type errors and hints [#426][] -- feat: add support for dask-awkward arrays in vector constructors [#429][] -- feat: short names for to_VectorND methods [#432][] - -[#424]: https://github.com/scikit-hep/vector/pull/424 -[#423]: https://github.com/scikit-hep/vector/pull/423 -[#431]: https://github.com/scikit-hep/vector/pull/431 -[#426]: https://github.com/scikit-hep/vector/pull/426 -[#429]: https://github.com/scikit-hep/vector/pull/429 -[#432]: https://github.com/scikit-hep/vector/pull/432 - -## Version 1.2 - -### Version 1.2.0 - -#### Bug fixes - -- fix: result of an infix operation should be demoted to the lowest possible dimension [#413][] -- fix: all infix operations should not depend on the order of arguments [#413][] -- fix: return the correct awkward record when performing an infix operation [#413][] -- fix: respect user defined awkward mixin subclasses and projection classes [#413][] - -#### Documentation - -- Update `README` and `intro.ipynb` to include the latest developments [#399][] -- docs: add docs for vector.zip [#390][] -- Fix Vector\* mixin's docstring [#404][] - -#### Maintenance - -- chore: repo review updates [#408][] -- black -> ruff format [#414][] -- chore: migrate to pytest-doctestplus [#416][] - -[#390]: https://github.com/scikit-hep/vector/pull/390 -[#404]: https://github.com/scikit-hep/vector/pull/404 -[#399]: https://github.com/scikit-hep/vector/pull/399 -[#408]: https://github.com/scikit-hep/vector/pull/408 -[#414]: https://github.com/scikit-hep/vector/pull/414 -[#416]: https://github.com/scikit-hep/vector/pull/416 -[#413]: https://github.com/scikit-hep/vector/pull/413 - -## Version 1.1 - -### Version 1.1.1.post1 - -#### Maintenance - -- chore: support Python 3.12 [#388][] -- Fix CI badge in README and docs [#386][] - -[#388]: https://github.com/scikit-hep/vector/pull/388 -[#386]: https://github.com/scikit-hep/vector/pull/386 - -### Version 1.1.1 - -#### Bug fixes - -- fix: `keepdims` in `numpy.sum` should not be `None` [#376][] - -#### Maintenance - -- chore: remove license string (not standard) [#371][] -- chore: blackend-docs moved [#370][] -- chore: use 2x faster black mirror [#367][] -- chore: clean up VCS versioning [#363][] -- chore: target-version no longer needed by Black or Ruff [#359][] -- chore: ruff moved to astral-sh [#358][] - -[#376]: https://github.com/scikit-hep/vector/pull/376 -[#371]: https://github.com/scikit-hep/vector/pull/371 -[#370]: https://github.com/scikit-hep/vector/pull/370 -[#367]: https://github.com/scikit-hep/vector/pull/367 -[#363]: https://github.com/scikit-hep/vector/pull/363 -[#359]: https://github.com/scikit-hep/vector/pull/359 -[#358]: https://github.com/scikit-hep/vector/pull/358 - -### Version 1.1.0 - -#### Features - -- feat: implement `sum`, `count`, and `count_nonzero` reductions [#347][] - -#### Maintenance - -- chore: remove Python `3.7` support [#355][] -- chore: use trusted publisher deployment [#354][] -- chore: replace custom definition of np.isclose with numba's np.isclose [#348][] - -[#355]: https://github.com/scikit-hep/vector/pull/355 -[#354]: https://github.com/scikit-hep/vector/pull/354 -[#347]: https://github.com/scikit-hep/vector/pull/347 -[#348]: https://github.com/scikit-hep/vector/pull/348 - -## Version 1.0 - -### Version 1.0.0 - -#### Features - -- feat: add constructors for `VectorObject3D` and `MomentumObject3D` [#231][] -- feat: add constructors for `VectorObject4D` and `MomentumObject4D` [#232][] -- feat: update `to_Vector3D` to pass new coordinate values [#278][] -- feat: allow passing coordinates to to_Vector-D [#319][] - -#### Bug fixes - -- fix: better elif conditions for obj \_\_init\_\_ methods [#316][] - -#### Documentation - -- docs: a readable changelog [#320][] - -#### Maintenance - -- ci: use numpy~=1.24.0 in pre-commit [#308][] -- fix: update discheck [#305][] -- ci: update number of builds for codecov bot [#314][] -- chore: move to using Ruff [#315][] -- chore: update copyright and license for 2022 and 2023 [#321][] - -[#231]: https://github.com/scikit-hep/vector/pull/231 -[#232]: https://github.com/scikit-hep/vector/pull/232 -[#278]: https://github.com/scikit-hep/vector/pull/278 -[#316]: https://github.com/scikit-hep/vector/pull/316 -[#308]: https://github.com/scikit-hep/vector/pull/308 -[#305]: https://github.com/scikit-hep/vector/pull/305 -[#314]: https://github.com/scikit-hep/vector/pull/314 -[#315]: https://github.com/scikit-hep/vector/pull/315 -[#319]: https://github.com/scikit-hep/vector/pull/319 -[#320]: https://github.com/scikit-hep/vector/pull/320 -[#321]: https://github.com/scikit-hep/vector/pull/321 - -## Version 0.11 - -### Version 0.11.0 - -#### Features - -- Add constructors for `VectorObject2D` and `MomentumObject2D`[#89][] -- Add support for awkward v2 (and keep supporting v1) [#284][] - -#### Bug fixes - -- `vector.arr` should construct `NumPy` vectors [#254][] -- Development dependency missing [#280][] - -#### Documentation - -- docs: add a section for talks [#264][] -- docs: fix missing backslash in latex for readme [#285][] -- docs: update changelog.md, PR template, and CONTRIBUTING.md [#275][] -- docs: add a developer guide [#233][] - -#### Maintenance - -- chore: add PyLint and additional pre-commit hooks [#260][] -- chore: pull request template-Priyadarshi [#271][] -- chore: add issue templates [#267][] -- chore: better and long term fix for flake8-bugbear [#298][] -- chore: bump mypy and revert python-version [#263][] -- chore: fix the failing mypy hook by pinning python-version [#261][] -- chore: ignore flake8 B905 + improve bug report template [#297][] -- chore: minor cleanups [#266][] -- chore: test on `awkward v1.10.0` and add cov to `noxfile` [#256][] -- chore: use Python 3.11! [#282][] -- chore: zenodo badge sync [#269][] -- ci: test notebooks on PRs [#272][] - -[#256]: https://github.com/scikit-hep/vector/pull/256 -[#254]: https://github.com/scikit-hep/vector/pull/254 -[#260]: https://github.com/scikit-hep/vector/pull/260 -[#261]: https://github.com/scikit-hep/vector/pull/261 -[#263]: https://github.com/scikit-hep/vector/pull/263 -[#264]: https://github.com/scikit-hep/vector/pull/264 -[#266]: https://github.com/scikit-hep/vector/pull/266 -[#267]: https://github.com/scikit-hep/vector/pull/267 -[#269]: https://github.com/scikit-hep/vector/pull/269 -[#271]: https://github.com/scikit-hep/vector/pull/271 -[#233]: https://github.com/scikit-hep/vector/pull/233 -[#272]: https://github.com/scikit-hep/vector/pull/272 -[#89]: https://github.com/scikit-hep/vector/pull/89 -[#275]: https://github.com/scikit-hep/vector/pull/275 -[#280]: https://github.com/scikit-hep/vector/pull/280 -[#282]: https://github.com/scikit-hep/vector/pull/282 -[#285]: https://github.com/scikit-hep/vector/pull/285 -[#297]: https://github.com/scikit-hep/vector/pull/297 -[#298]: https://github.com/scikit-hep/vector/pull/298 -[#284]: https://github.com/scikit-hep/vector/pull/284 - -## Version 0.10 - -### Version 0.10.0 - -#### Maintenance - -- Remove Python `3.6` support [#251][] - -[#251]: https://github.com/scikit-hep/vector/pull/251 - -## Version 0.9 - -### Version 0.9.0 - -#### Features - -- Implements deltaRapidityPhi and deltaRapidityPhi2. [#175][] -- Remove underscores [#192][] -- feat: add git archive support [#244][] - -#### Bug fixes - -- fix bad values for high (abs) eta [#172][] -- Add custom reprs to awkward coordinate classes [#212][] -- Explicitly set posinf and neginf in nan_to_num so they stay infinite. [#173][] -- Add type checks in constructors [#210][] - -#### Documentation - -- Add Conda and Zenodo badges to the README-rodrigues [#183][] -- Tests and docs for deltaRapidityPhi [#187][] -- docs: fix intro notebook, and submodule and subpackage index [#191][] -- docs: add codecov badge to README [#203][] -- docs: fix warnings [#193][] -- docs: add docstrings in the `backends.numpy` module [#195][] -- docs: add docstrings in the `backends.object` module [#201][] -- docs: improve the landing page and API docs structure [#204][] -- docs: add docstrings in the `backends.awkward` module [#207][] -- Implement doctests in CI [#211][] -- docs: Add CITATION.cff Citation File Format file [#243][] -- docs: update changelog [#248][] - -#### Maintenance - -- chore: wheel not required for setuptools PEP 517 (all-repos) [#176][] -- fix: bump black to 22.3.0 due to click 8.1 release [#181][] -- ci: fix a test and update CI to catch errors regularly [#199][] -- chore: fix conda badge and update dependabot [#213][] -- docs: render module level docstrings in documentation [#218][] -- chore: pass repo review [#219][] -- chore: migrate to hatchling [#223][] -- chore: add `codecov.yml` [#229][] -- chore: add `pyproject-fmt` pre-commit hook [#230][] -- chore: remove redundant `tool.check-manifest` from `pyproject.toml` [#235][] -- chore: support `awkward` `v1` and `v2` together [#226][] -- chore: build and test on Python `3.10` and `3.11-dev` [#252][] - -[#176]: https://github.com/scikit-hep/vector/pull/176 -[#172]: https://github.com/scikit-hep/vector/pull/172 -[#181]: https://github.com/scikit-hep/vector/pull/181 -[#175]: https://github.com/scikit-hep/vector/pull/175 -[#187]: https://github.com/scikit-hep/vector/pull/187 -[#191]: https://github.com/scikit-hep/vector/pull/191 -[#199]: https://github.com/scikit-hep/vector/pull/199 -[#192]: https://github.com/scikit-hep/vector/pull/192 -[#203]: https://github.com/scikit-hep/vector/pull/203 -[#193]: https://github.com/scikit-hep/vector/pull/193 -[#195]: https://github.com/scikit-hep/vector/pull/195 -[#201]: https://github.com/scikit-hep/vector/pull/201 -[#204]: https://github.com/scikit-hep/vector/pull/204 -[#207]: https://github.com/scikit-hep/vector/pull/207 -[#211]: https://github.com/scikit-hep/vector/pull/211 -[#212]: https://github.com/scikit-hep/vector/pull/212 -[#213]: https://github.com/scikit-hep/vector/pull/213 -[#218]: https://github.com/scikit-hep/vector/pull/218 -[#219]: https://github.com/scikit-hep/vector/pull/219 -[#173]: https://github.com/scikit-hep/vector/pull/173 -[#210]: https://github.com/scikit-hep/vector/pull/210 -[#223]: https://github.com/scikit-hep/vector/pull/223 -[#229]: https://github.com/scikit-hep/vector/pull/229 -[#230]: https://github.com/scikit-hep/vector/pull/230 -[#235]: https://github.com/scikit-hep/vector/pull/235 -[#244]: https://github.com/scikit-hep/vector/pull/244 -[#243]: https://github.com/scikit-hep/vector/pull/243 -[#226]: https://github.com/scikit-hep/vector/pull/226 -[#252]: https://github.com/scikit-hep/vector/pull/252 - -## Version 0.8 - -### Version 0.8.5 - -- Added boostCM_of to clarify #134, supported by scaleD and negD [#135][] -- Let 'eta' be NaN if 'z' is NaN [#139][] -- Defined dot product without absolute value [#148][] -- Fixed numpy array code examples in documentation [#151][] -- Vector components may be NumpyArrayType or IndexedArrayType in Numba [#162][] -- VectorNumpy pickle support to enable multiprocessing [#163][] -- pre-commit and style cleanup [#164][] - -[#135]: https://github.com/scikit-hep/vector/pull/135 -[#139]: https://github.com/scikit-hep/vector/pull/139 -[#148]: https://github.com/scikit-hep/vector/pull/148 -[#151]: https://github.com/scikit-hep/vector/pull/151 -[#162]: https://github.com/scikit-hep/vector/pull/162 -[#163]: https://github.com/scikit-hep/vector/pull/163 -[#164]: https://github.com/scikit-hep/vector/pull/164 - -### Version 0.8.4 - -- Allow VectorObject, VectorNumpy, and VectorAwkward to be subclassed by other projects [#128][] - -[#128]: https://github.com/scikit-hep/vector/pull/128 - -### Version 0.8.3 - -- Fixed Awkward Arrays of momentum vectors in Numba [#112] - -[#112]: https://github.com/scikit-hep/vector/pull/112 - -### Version 0.8.2 - -- Fixed missing momentum synonyms in CoordinatesAwkward [#84][] -- Added vector.zip [#94][] -- Allowed lowercase e and m for energy and mass [#95][] -- Fixed \_wrap_result for methods called on an ak.Record [#100][] -- Fixed error in calculation of deltaangle [#105][] -- Fixed Awkward version check [#82][] -- Pinned Python version for dis (in tests) [#90][] -- Using myst-parser (in docs) [#91][] - -[#82]: https://github.com/scikit-hep/vector/pull/82 -[#84]: https://github.com/scikit-hep/vector/pull/84 -[#90]: https://github.com/scikit-hep/vector/pull/90 -[#91]: https://github.com/scikit-hep/vector/pull/91 -[#94]: https://github.com/scikit-hep/vector/pull/94 -[#95]: https://github.com/scikit-hep/vector/pull/95 -[#100]: https://github.com/scikit-hep/vector/pull/100 -[#105]: https://github.com/scikit-hep/vector/pull/105 - -### Version 0.8.1 - -- Fix issue importing without Awkward installed [#76][] - -[#76]: https://github.com/scikit-hep/vector/pull/76 - -### Version 0.8.0 - -First release to PyPI. Initial implementation. Initial features: - -- 2D, 3D, and Lorentz vectors -- Single, Array, and Awkward forms -- Supports Numba / Awkward + Numba -- Multiple coordinate systems -- Geometric / momentum versions -- Statically typed - -You can currently construct vectors using `obj`/`arr`/`awk` (or -`obj`/`array`/`Array`) for single, NumPy, and Awkward vectors, respectively. -The next version is likely to improve the vector construction process. diff --git a/docs/index.rst b/docs/index.rst index d77aa9c8..4afa28b3 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -12,53 +12,16 @@ Overview -------- -Vector is a Python 3.8+ library (Python 3.6 and 3.7 supported till ``v0.9.0`` and ``v1.0.0``, respectively) for 2D, 3D, and `Lorentz vectors `_, especially *arrays of vectors*, to solve common physics problems in a NumPy-like way. - -Main features of Vector: - -* Pure Python with NumPy as its only dependency. This makes it easier to install. -* Vectors may be represented in a variety of coordinate systems: Cartesian, cylindrical, pseudorapidity, and any combination of these with time or proper time for Lorentz vectors. In all, there are 12 coordinate systems: {*x* - *y* vs *ρ* - *φ* in the azimuthal plane} × {*z* vs *θ* vs *η* longitudinally} × {*t* vs *τ* temporally}. -* Uses names and conventions set by `ROOT `_'s `TLorentzVector `_ and `Math::LorentzVector `_, as well as `scikit-hep/math `_, `uproot-methods TLorentzVector `_, `henryiii/hepvector `_, and `coffea.nanoevents.methods.vector `_ (backed by Scikit-HEP/vector since ``v2024.8``). -* Implemented on a variety of backends: - * pure Python objects - * `SymPy `_ vectors - * NumPy arrays of vectors (as a `structured array `_ subclass) - * `Awkward Arrays `_ of vectors - * potential for more: CuPy, TensorFlow, Torch... -* Awkward and Object backends also implemented in `Numba `_ for JIT-compiled calculations on vectors. -* `JAX `_ and `Dask `_ support through Awkward Arrays. -* Distinction between geometrical vectors, which have a minimum of attribute and method names, and vectors representing momentum, which have synonyms like ``pt`` = ``rho``, ``energy`` = ``t``, ``mass`` = ``tau``. - Installation ------------ -Vector is available on `PyPI `_ as well as on `conda `_. The library can be installed using ``pip`` - - -.. code-block:: - - pip install vector - -or using ``conda`` - - -.. code-block:: - conda install -c conda-forge vector - -Example gallery ---------------- -``Vector`` has several examples covering the basics as well as some advanced usage of the library. The example gallery -covers almost all the features offered by ``vector`` and any new additions to the gallery are welcomed. - -**Note**: Adding more examples and improving the existing examples for newcomers is still in progress. - -.. toctree:: - :maxdepth: 1 - :caption: Example gallery +Getting help +------------ - usage/intro - usage/structure - usage/vector_design_prototype +Contributing to Vector +---------------------- -Talks about vector +Talks about Vector ------------------ - 21st October 2024 - `A new SymPy backend for vector: uniting @@ -93,39 +56,6 @@ Talks about vector Workshop `__ `🎥 `__ - -Changes in vector's API ------------------------ -The ``changelog`` file describes the changes in ``vector``'s API and usage introduced in every new version. These changes can -be breaking changes or minor adjustments, hence one should go through this file and their existing codebase while updating ``vector``'s -version. - -.. toctree:: - :maxdepth: 3 - :caption: Changes in vector's API - - changelog - -Getting help ------------- -* ``Vector``'s code is hosted on `GitHub `_. -* If something is not working the way it should, or if you want to request a new feature, create a new `issue `_ on GitHub. -* To discuss something related to ``vector``, use the `discussions `_ tab on GitHub or ``vector``'s gitter (`Scikit-HEP/vector `_) chat room. - -Contributing to vector ----------------------- -If you are planning to develop ``vector`` (thank you!), or if you want to use the latest commit of ``vector`` on your local machine, you might want to install it from the source. Refer to our `Contributing Guidelines `_ for more information. - -API reference -------------- -The API reference details the functionality of each ``class`` and ``function`` present in ``vector``'s codebase. - -.. toctree:: - :maxdepth: 8 - :caption: API Reference - - api/modules.rst - .. |Action status| image:: https://github.com/scikit-hep/vector/actions/workflows/ci.yml/badge.svg :target: https://github.com/scikit-hep/vector/actions .. |Documentation Status| image:: https://readthedocs.org/projects/vector/badge/?version=latest diff --git a/docs/usage/intro.ipynb b/docs/usage/intro.ipynb deleted file mode 100644 index 8d22682d..00000000 --- a/docs/usage/intro.ipynb +++ /dev/null @@ -1,4084 +0,0 @@ -{ - "cells": [ - { - "cell_type": "markdown", - "id": "auburn-verification", - "metadata": {}, - "source": [ - "# Introduction to Vector\n", - "\n", - "Vector is a Python 3.8+ library (Python 3.6 and 3.7 supported till `v0.9.0` and `v1.0.0`, respectively) for 2D, 3D, and [Lorentz vectors](https://en.wikipedia.org/wiki/Special_relativity#Physics_in_spacetime), especially _arrays of vectors_, to solve common physics problems in a NumPy-like way.\n", - "\n", - "Main features of Vector:\n", - "\n", - " * Pure Python with NumPy as its only dependency. This makes it easier to install.\n", - " * Vectors may be represented in a variety of coordinate systems: Cartesian, cylindrical, spherical, and any combination of these with time or proper time for Lorentz vectors. In all, there are 12 coordinate systems: {$x$-$y$ vs $\\rho$-$\\phi$ in the azimuthal plane} × {$z$ vs $\\theta$ vs $\\eta$ longitudinally} × {$t$ vs $\\tau$ temporally}.\n", - " * Uses names and conventions set by [ROOT](https://root.cern/)'s [TLorentzVector](https://root.cern.ch/doc/master/classTLorentzVector.html) and [Math::LorentzVector](https://root.cern.ch/doc/master/classROOT_1_1Math_1_1LorentzVector.html), as well as [scikit-hep/math](https://github.com/scikit-hep/scikit-hep/tree/master/skhep/math), [uproot-methods TLorentzVector](https://github.com/scikit-hep/uproot3-methods/blob/master/uproot3_methods/classes/TLorentzVector.py), [henryiii/hepvector](https://github.com/henryiii/hepvector), and [coffea.nanoevents.methods.vector](https://coffeateam.github.io/coffea/modules/coffea.nanoevents.methods.vector.html).\n", - " * Implemented on a variety of backends:\n", - " - pure Python objects\n", - " - [SymPy](https://www.sympy.org/en/index.html) vectors\n", - " - NumPy arrays of vectors (as a [structured array](https://numpy.org/doc/stable/user/basics.rec.html) subclass)\n", - " - [Awkward Arrays](https://awkward-array.org/) of vectors\n", - " - potential for more: CuPy, TensorFlow, Torch...\n", - " * Awkward backend also implemented in [Numba](https://numba.pydata.org/) for JIT-compiled calculations on vectors.\n", - " * [JAX](https://awkward-array.org/doc/main/user-guide/how-to-specialize-differentiate-jax.html) and [Dask](https://dask-awkward.readthedocs.io/en/stable/) support through Awkward Arrays.\n", - " * Distinction between geometrical vectors, which have a minimum of attribute and method names, and vectors representing momentum, which have synonyms like `pt` = `rho`, `energy` = `t`, `mass` = `tau`.\n", - "\n", - "This notebook requires Vector, NumPy, Awkward Array, SymPy, and Numba to run." - ] - }, - { - "cell_type": "code", - "execution_count": 1, - "id": "careful-mandate", - "metadata": {}, - "outputs": [], - "source": [ - "from __future__ import annotations\n", - "\n", - "import numbers\n", - "\n", - "import awkward as ak # at least v2.0.0 (vector v1.4.* supports awkward v1 and v2 both)\n", - "import numba as nb\n", - "import numpy as np\n", - "import sympy\n", - "\n", - "import vector" - ] - }, - { - "cell_type": "markdown", - "id": "supposed-outreach", - "metadata": {}, - "source": [ - "## Constructing a vector or an array of vectors\n", - "\n", - "The easiest way to create one or many vectors is with a helper function:\n", - "\n", - " * `vector.obj` to make a pure Python vector object,\n", - " * `vector.arr` to make a NumPy array of vectors (lowercase, like `np.array`),\n", - " * `vector.awk` to make an Awkward Array of vectors (uppercase, like `ak.Array`).\n", - " * `vector.zip` to make an Awkward Array of vectors (similar to `ak.zip`)" - ] - }, - { - "cell_type": "markdown", - "id": "instant-phoenix", - "metadata": {}, - "source": [ - "### Pure Python vectors\n", - "\n", - "You can directly use the `VectorObject` classes to construct object type vectors:" - ] - }, - { - "cell_type": "code", - "execution_count": 2, - "id": "c133d634", - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "VectorObject2D(x=1.1, y=2.2)" - ] - }, - "execution_count": 2, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "vector.VectorObject2D(x=1.1, y=2.2)" - ] - }, - { - "cell_type": "code", - "execution_count": 3, - "id": "2e48bfd8", - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "MomentumObject3D(px=1.1, py=2.2, pz=3.3)" - ] - }, - "execution_count": 3, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "vector.MomentumObject3D(px=1.1, py=2.2, pz=3.3)" - ] - }, - { - "cell_type": "code", - "execution_count": 4, - "id": "73748719", - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "VectorObject4D(x=1.1, y=2.2, eta=3.3, tau=4.4)" - ] - }, - "execution_count": 4, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "vector.VectorObject4D(x=1.1, y=2.2, eta=3.3, tau=4.4)" - ] - }, - { - "cell_type": "markdown", - "id": "3dbe90b0", - "metadata": {}, - "source": [ - "and so on for every class.\n", - "\n", - "Or, you can use a single wrapper function to construct all possible combinations of\n", - "object type vectors:" - ] - }, - { - "cell_type": "code", - "execution_count": 5, - "id": "divided-control", - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "VectorObject2D(x=3, y=4)" - ] - }, - "execution_count": 5, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "vector.obj(x=3, y=4) # Cartesian 2D vector" - ] - }, - { - "cell_type": "code", - "execution_count": 6, - "id": "touched-reader", - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "VectorObject2D(rho=5, phi=0.9273)" - ] - }, - "execution_count": 6, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "vector.obj(rho=5, phi=0.9273) # same in polar coordinates" - ] - }, - { - "cell_type": "code", - "execution_count": 7, - "id": "coordinated-banner", - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "True" - ] - }, - "execution_count": 7, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "vector.obj(x=3, y=4).isclose(\n", - " vector.obj(rho=5, phi=0.9273)\n", - ") # use \"isclose\" unless they are exactly equal" - ] - }, - { - "cell_type": "code", - "execution_count": 8, - "id": "worse-depression", - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "VectorObject3D(x=3, y=4, z=-2)" - ] - }, - "execution_count": 8, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "vector.obj(x=3, y=4, z=-2) # Cartesian 3D vector" - ] - }, - { - "cell_type": "code", - "execution_count": 9, - "id": "copyrighted-answer", - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "VectorObject4D(x=3, y=4, z=-2, t=10)" - ] - }, - "execution_count": 9, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "vector.obj(x=3, y=4, z=-2, t=10) # Cartesian 4D vector" - ] - }, - { - "cell_type": "code", - "execution_count": 10, - "id": "recovered-platinum", - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "VectorObject4D(rho=5, phi=0.9273, eta=-0.39, t=10)" - ] - }, - "execution_count": 10, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "vector.obj(\n", - " rho=5, phi=0.9273, eta=-0.39, t=10\n", - ") # in rho-phi-eta-t cylindrical coordinates" - ] - }, - { - "cell_type": "code", - "execution_count": 11, - "id": "exempt-palestine", - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "MomentumObject4D(pt=5, phi=0.9273, eta=-0.39, E=10)" - ] - }, - "execution_count": 11, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "vector.obj(\n", - " pt=5, phi=0.9273, eta=-0.39, E=10\n", - ") # use momentum-synonyms to get a momentum vector" - ] - }, - { - "cell_type": "code", - "execution_count": 12, - "id": "better-responsibility", - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "False" - ] - }, - "execution_count": 12, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "vector.obj(rho=5, phi=0.9273, eta=-0.39, t=10) == vector.obj(\n", - " pt=5, phi=0.9273, eta=-0.390035, E=10\n", - ")" - ] - }, - { - "cell_type": "code", - "execution_count": 13, - "id": "adverse-lighting", - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "8.426194916448265" - ] - }, - "execution_count": 13, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "vector.obj(\n", - " rho=5, phi=0.9273, eta=-0.39, t=10\n", - ").tau # geometrical vectors have to use geometrical names (\"tau\", not \"mass\")" - ] - }, - { - "cell_type": "code", - "execution_count": 14, - "id": "broadband-budget", - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "8.426194916448265" - ] - }, - "execution_count": 14, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "vector.obj(\n", - " pt=5, phi=0.9273, eta=-0.39, E=10\n", - ").mass # momentum vectors can use momentum names (as well as geometrical ones)" - ] - }, - { - "cell_type": "code", - "execution_count": 15, - "id": "prompt-archive", - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "MomentumObject4D(pt=5, phi=0.9273, theta=1.9513, mass=8.4262)" - ] - }, - "execution_count": 15, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "vector.obj(\n", - " pt=5, phi=0.9273, theta=1.9513, mass=8.4262\n", - ") # any combination of azimuthal, longitudinal, and temporal coordinates is allowed" - ] - }, - { - "cell_type": "code", - "execution_count": 16, - "id": "southern-register", - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "True" - ] - }, - "execution_count": 16, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "vector.obj(x=3, y=4, z=-2, t=10).isclose(\n", - " vector.obj(pt=5, phi=0.9273, theta=1.9513, mass=8.4262)\n", - ")" - ] - }, - { - "cell_type": "code", - "execution_count": 17, - "id": "utility-cartridge", - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "(True, True, True, True, True, True, True, True, True, True)" - ] - }, - "execution_count": 17, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "# Test instance type for any level of granularity.\n", - "(\n", - " isinstance(\n", - " vector.obj(x=1.1, y=2.2), vector.Vector\n", - " ), # is a vector or array of vectors\n", - " isinstance(vector.obj(x=1.1, y=2.2), vector.Vector2D), # is 2D (not 3D or 4D)\n", - " isinstance(\n", - " vector.obj(x=1.1, y=2.2), vector.VectorObject\n", - " ), # is a vector object (not an array)\n", - " isinstance(vector.obj(px=1.1, py=2.2), vector.Momentum), # has momentum synonyms\n", - " isinstance(\n", - " vector.obj(x=1.1, y=2.2, z=3.3, t=4.4), vector.Planar\n", - " ), # has transverse plane (2D, 3D, or 4D)\n", - " isinstance(\n", - " vector.obj(x=1.1, y=2.2, z=3.3, t=4.4), vector.Spatial\n", - " ), # has all spatial coordinates (3D or 4D)\n", - " isinstance(\n", - " vector.obj(x=1.1, y=2.2, z=3.3, t=4.4), vector.Lorentz\n", - " ), # has temporal coordinates (4D)\n", - " isinstance(\n", - " vector.obj(x=1.1, y=2.2, z=3.3, t=4.4).azimuthal, vector.AzimuthalXY\n", - " ), # azimuthal coordinate type\n", - " isinstance(\n", - " vector.obj(x=1.1, y=2.2, z=3.3, t=4.4).longitudinal, vector.LongitudinalZ\n", - " ), # longitudinal coordinate type\n", - " isinstance(\n", - " vector.obj(x=1.1, y=2.2, z=3.3, t=4.4).temporal, vector.TemporalT\n", - " ), # temporal coordinate type\n", - ")" - ] - }, - { - "cell_type": "markdown", - "id": "mature-facial", - "metadata": {}, - "source": [ - "The allowed keyword arguments for 2D vectors are:\n", - "\n", - " * `x` and `y` for Cartesian azimuthal coordinates,\n", - " * `px` and `py` for momentum,\n", - " * `rho` and `phi` for polar azimuthal coordinates,\n", - " * `pt` and `phi` for momentum.\n", - "\n", - "For 3D vectors, you need the above and:\n", - "\n", - " * `z` for the Cartesian longitudinal coordinate,\n", - " * `pz` for momentum,\n", - " * `theta` for the spherical polar angle (from $0$ to $\\pi$, inclusive),\n", - " * `eta` for pseudorapidity, which is a kind of spherical polar angle.\n", - "\n", - "For 4D vectors, you need the above and:\n", - "\n", - " * `t` for the Cartesian temporal coordinate,\n", - " * `E` or `energy` to get four-momentum,\n", - " * `tau` for the \"proper time\" (temporal coordinate in the vector's rest coordinate system),\n", - " * `M` or `mass` to get four-momentum.\n", - "\n", - "Since momentum vectors have momentum-synonyms _in addition_ to the geometrical names, any momentum-synonym will make the whole vector a momentum vector." - ] - }, - { - "cell_type": "markdown", - "id": "handmade-tract", - "metadata": {}, - "source": [ - "If you want to bypass the dimension and coordinate system inference through keyword arguments (e.g. for static typing), you can use specialized constructors:" - ] - }, - { - "cell_type": "code", - "execution_count": 18, - "id": "center-beauty", - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "VectorObject2D(x=1.1, y=2.2)" - ] - }, - "execution_count": 18, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "vector.VectorObject2D.from_xy(1.1, 2.2)" - ] - }, - { - "cell_type": "code", - "execution_count": 19, - "id": "indoor-playing", - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "MomentumObject3D(pt=1.1, phi=2.2, pz=3.3)" - ] - }, - "execution_count": 19, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "vector.MomentumObject3D.from_rhophiz(1.1, 2.2, 3.3)" - ] - }, - { - "cell_type": "code", - "execution_count": 20, - "id": "documented-lyric", - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "VectorObject4D(x=1.1, y=2.2, eta=3.3, tau=4.4)" - ] - }, - "execution_count": 20, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "vector.VectorObject4D.from_xyetatau(1.1, 2.2, 3.3, 4.4)" - ] - }, - { - "cell_type": "markdown", - "id": "improved-coach", - "metadata": {}, - "source": [ - "and so on, for all combinations of azimuthal, longitudinal, and temporal coordinates, geometric and momentum-flavored." - ] - }, - { - "cell_type": "markdown", - "id": "54ede1c4-249e-4218-8563-4f29e2748213", - "metadata": {}, - "source": [ - "### SymPy vectors\n", - "\n", - "> **Note:** Operations on SymPy vectors are only 100% compatible with numeric vectors (Python, NumPy, and Awkward backends) if the vectors are positive time-like, that is, if `t**2 > x**2 + y**2 + z**2`. The space-like and negative time-like cases have different sign conventions.\n", - "\n", - "You can directly use the `VectorSympy` and `MomentumSympy` classes to construct object type vectors:" - ] - }, - { - "cell_type": "code", - "execution_count": 21, - "id": "2e184679-4fd9-4a5b-9705-1f060977e970", - "metadata": {}, - "outputs": [], - "source": [ - "x, y, z, t, px, py, pz, eta, tau = sympy.symbols(\n", - " \"x y z t px py pz eta tau\",\n", - " real=True, # see sympy assumptions to add more restrictions on the symbols\n", - ")" - ] - }, - { - "cell_type": "code", - "execution_count": 22, - "id": "e4e385f0-6b9a-4395-974f-ddcdff7416af", - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "VectorSympy2D(x=x, y=y)" - ] - }, - "execution_count": 22, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "vector.VectorSympy2D(x=x, y=y)" - ] - }, - { - "cell_type": "code", - "execution_count": 23, - "id": "a84770fa-8a8e-4e96-a95d-f4109f9ef876", - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "MomentumSympy3D(px=px, py=py, pz=pz)" - ] - }, - "execution_count": 23, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "vector.MomentumSympy3D(px=px, py=py, pz=pz)" - ] - }, - { - "cell_type": "code", - "execution_count": 24, - "id": "a7c741e0-ae25-46a5-8a53-8a713a7b837f", - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "VectorSympy4D(x=x, y=y, eta=eta, tau=tau)" - ] - }, - "execution_count": 24, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "vector.VectorSympy4D(x=x, y=y, eta=eta, tau=tau)" - ] - }, - { - "cell_type": "markdown", - "id": "fad8d0f2-04e4-47a2-978e-a146192bead2", - "metadata": {}, - "source": [ - "and so on for every class." - ] - }, - { - "cell_type": "code", - "execution_count": 25, - "id": "bbb22de8-32ca-44f5-9e55-d03a49f5e2fe", - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "(True, True, True, True, True, True, True, True, True, True)" - ] - }, - "execution_count": 25, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "# Test instance type for any level of granularity.\n", - "(\n", - " # is a vector or array of vectors\n", - " isinstance(vector.VectorSympy2D(x=x, y=y), vector.Vector),\n", - " # is 2D (not 3D or 4D)\n", - " isinstance(vector.VectorSympy2D(x=x, y=y), vector.Vector2D),\n", - " # is a sympy vector (not an array)\n", - " isinstance(vector.VectorSympy2D(x=x, y=y), vector.VectorSympy),\n", - " # has momentum synonyms\n", - " isinstance(vector.MomentumSympy2D(px=px, py=py), vector.Momentum),\n", - " # has transverse plane (2D, 3D, or 4D)\n", - " isinstance(vector.VectorSympy4D(x=x, y=y, z=z, t=t), vector.Planar),\n", - " # has all spatial coordinates (3D or 4D)\n", - " isinstance(vector.VectorSympy4D(x=x, y=y, z=z, t=t), vector.Spatial),\n", - " # has temporal coordinates (4D)\n", - " isinstance(vector.VectorSympy4D(x=x, y=y, z=z, t=t), vector.Lorentz),\n", - " # azimuthal coordinate type\n", - " isinstance(vector.VectorSympy4D(x=x, y=y, z=z, t=t).azimuthal, vector.AzimuthalXY),\n", - " # longitudinal coordinate type\n", - " isinstance(\n", - " vector.VectorSympy4D(x=x, y=y, z=z, t=t).longitudinal, vector.LongitudinalZ\n", - " ),\n", - " # temporal coordinate type\n", - " isinstance(vector.VectorSympy4D(x=x, y=y, z=z, t=t).temporal, vector.TemporalT),\n", - ")" - ] - }, - { - "cell_type": "markdown", - "id": "e7887274-a456-473e-a848-88a38ea594aa", - "metadata": {}, - "source": [ - "Since `VectorSympy2D`, `VectorSympy3D`, `VectorSympy4D`, and their momentum equivalents operate on SymPy expressions, all of the normal SymPy methods and functions work on the results, coordinates, and the vectors." - ] - }, - { - "cell_type": "code", - "execution_count": 26, - "id": "d1dfc115-ceee-4b47-a25d-5e57242aae23", - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "IPython console for SymPy 1.13.0 (Python 3.11.5-64-bit) (ground types: python)\n", - "\n", - "These commands were executed:\n", - ">>> from sympy import *\n", - ">>> x, y, z, t = symbols('x y z t')\n", - ">>> k, m, n = symbols('k m n', integer=True)\n", - ">>> f, g, h = symbols('f g h', cls=Function)\n", - ">>> init_printing()\n", - "\n", - "Documentation can be found at https://docs.sympy.org/1.13.0/\n", - "\n" - ] - } - ], - "source": [ - "sympy.init_session() # latex printing" - ] - }, - { - "cell_type": "code", - "execution_count": 27, - "id": "25b81776-1240-4e86-8b16-c3590470e502", - "metadata": {}, - "outputs": [ - { - "data": { - "image/png": "iVBORw0KGgoAAAANSUhEUgAAACoAAAAOCAYAAABZ/o57AAAACXBIWXMAAA7EAAAOxAGVKw4bAAAB0UlEQVRIDb2W7U0CQRCGD0IBqB1oBxAqEDuA2IF0oH/5Z6ADtAKFDqAEpAOxA0MH+Dzn7uVyhFNAb5JhZudj592vOWrb7TYZDodvSZI04Q38GWQLKWlbw/rPg1yTc4NeGTVCJUH1KT6LldHv0UfwAP0pZ++hP8dxVbIOCHdqlgdZVjzELcti/sNXZ1KPc37g5KuwwAPTjg8XqDvqHTyE3gl2gZVRg51ZHVHNhU3JvUQ+wo47cBfuwy7ee6x/QZy2BHmHGMBpHuOx9kiMtT/AbsQF3MRmfFL351Ai2eLtkHcV5ATpo+zi82rot4MIOiVsPsprOLN9e9JFmGv3GRE3hlPASG3HATUxkEAE5mN0V8+QWYdgvHOl8G9CblFMMbyGeVIfujveQvZieyom/XZs0QxMCYjS+chzNz32dPcKwV7NzqlAndNdPZUEKbUB7T3Ok1dq+RdA9x1lvthPejyVOUCzj04+qZ4fVKEDJO5eVg6bx+uCbzNjTsHfPRVok/nkfeSHpAjMFiYo20+e7AY+TP0ZMfYzvq75pyRSCLLn2cxNEISTLmDv4oQYW48++5vf/eh/wb5zbNi8Y5K90dhX+AOWlvizPzfoLsq2JMVeas31Fx2vogF49TMKAAAAAElFTkSuQmCC", - "text/latex": [ - "$\\displaystyle \\text{True}$" - ], - "text/plain": [ - "True" - ] - }, - "execution_count": 27, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "v1 = vector.VectorSympy2D(x=x, y=y)\n", - "sympy.Eq(v1.rho, sympy.sqrt(x**2 + y**2))" - ] - }, - { - "cell_type": "code", - "execution_count": 28, - "id": "405f6458-cc8c-4c15-ae82-264d133ca627", - "metadata": {}, - "outputs": [], - "source": [ - "v2 = vector.VectorSympy4D(x=x, y=y, z=z, t=t)" - ] - }, - { - "cell_type": "code", - "execution_count": 29, - "id": "9e7a68d7-33b6-4654-b0f0-4dda87f0ce58", - "metadata": {}, - "outputs": [ - { - "data": { - "image/png": "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", - "text/latex": [ - "$\\displaystyle \\sqrt{\\left|{- t^{2} + x^{2} + y^{2} + z^{2}}\\right|}$" - ], - "text/plain": [ - " _______________________\n", - " ╱ │ 2 2 2 2│ \n", - "╲╱ │- t + x + y + z │ " - ] - }, - "execution_count": 29, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "v2.to_rhophithetatau().tau" - ] - }, - { - "cell_type": "code", - "execution_count": 30, - "id": "56ca9dc1-f8f7-4774-b80b-5fc8f2e1be88", - "metadata": {}, - "outputs": [], - "source": [ - "values = {x: 3, y: 2, z: 1, t: 10} # t**2 > x**2 + y**2 + z**2" - ] - }, - { - "cell_type": "code", - "execution_count": 31, - "id": "e98893fa-511e-4380-8d1a-90aecf6a50c2", - "metadata": {}, - "outputs": [ - { - "data": { - "image/png": "iVBORw0KGgoAAAANSUhEUgAAAMAAAAAXCAYAAABd50CQAAAACXBIWXMAAA7EAAAOxAGVKw4bAAAFRUlEQVR4Ae2a3XEUORRG2y4HQC0ZQAZQRICdASwRgDOA8pP9RkEGQARbkAEmAgwZrDcCw2RgztFKKnXXMDP2aMbSrm+V5qrVavWnq/sn9excXl4Oi+jk5OQO949in3uRP6d9tui5Fu71ir1H3D1iVkf3VlDUN0zuMPWj/o76N8r91NYw7xV7j7h7xDzsrqC8L1D6/aLfG+r3aHtQtLVa7RV7j7h7xLySAej9z1rV8CW4esXeI+4eMQ87y/YAUwXD8xsBnsB7SIFG8HvF3iPuXjCvsgfISsSkTHueUB7mxk4qvWLvEXdrmMGj05YuKDpu9yvnNowiAI2e+LjBPUgd7CRx7QmQG+Cn1Js/ARJzol6x94i7NczgUZ9fwz+pD/CRjk8jgJtdFf2HnRPxkG2v4Ae2xWt5sKLUr0UesXaHvUfcrWEGzwt08g48KL/6SX0Wr3XmB1MDUMHP7WRniXry/CpROvlxw/MqdGj4p1fsPeJeBzPP6pW/UN5Rf19RpZ4y1vc5432l7aXvnRqAESBbS3zQEJLCRmwKhqERtE69Yu8R97Uxo4h65cco0xH8b7iG8LaCcqnP8wwqZS77O8fHx3ZSmVVy66cUI8DXSiAYqh6BSZyGNukR5TnFKPWMIol7asT/3rnB3wK3m7BvXOeFifc+wPVYzRG4jPwfIzD3gN8pynwfnudRCzhjvmQsddJ1NH9XH69EPKOe/KS8pz5y1lw7Hw32cJeLU4qCNycaqLsBdpI1LNAha5M7+LcRn6HsA8WFMCVz0mnHT7Up0rsp08+UKcY/afN0rTkCszJVxuqHCqn8xS+vrvyMOzCu66ujMBroLIwI4rgK/RE7zxY8NEqBzP/n5UsLnt/uLYSg5y+Vx8mpOEYByUmX90PjTf+AW4+jsUrKeXTIENuMvC2SMn3MHLIiUVfGSeYbw8x7NDA9uGv8BX4Gz0eYFV58d68YxPSnWuoAWC3WjY18VQrhdUHnM8ZN+Zvd/B5hOA6LA6+SQmwAuwcLybno7V8LviBlP20rbq9W3QDugTGzvOP4R2Klng1iNXTX78W71MtPcOX0ES6mZX/InDqZEkCKDhfBABhQJTWnMzxXIcZUQFU/mDFmUqKEcZ4ypXvX5rWxx/EGuAuorHPqQJvRwba1I0B8T1WZgysQY6sf/gOghdM/5bWQlAXFPvP6prbzYAB0cmEGHsiLQN3z05ntLRLYkjLlqCVmsTaM2wiVI1aUq/NwsabGHW/fPAObGP0DZN4XUt+afvAuUyAjj57fLCFHJa4Xkfqs4U4pRYDTvXhnlP/HF/qSZhZFgYPHkwhzQCfmzl7FKYXhRrMFDwW0ueRilHjtpOyz47GhJUKeYXMOz1Er4nNjXCXl/N18ead7PtdT+VxF8dOQQV/SRcFz6pwMQIsIC8NLVTStPXvW4sGbrOqFLH6QE+Mox6PNe2mjSbVJUsbJ+wwRs7hHx3StIAef6ZnYjFpyU+S7FI1iY8rPu8pj0Idcz3jflYnn3ECrL6ZuQZ/h6o6ps98dhj1/IK3Mo6Zwvg7PoS7cbeNHL6AXUmEGMB5SPlM8nvNM9wf11oxWqCUpZ8/7PUW5oHjUJ7UaAZ6B1Qg1wFV6vb5GrOyrZgeMp2Kqfxqauphkw+VapLc3a3gEV+ZyT7UC/tGf4bhxS1uUAIugIezDN7Jx3eJU1noV81f5dWIq6jTVWmvsZQ/fGsAyCVW6P1X2uOj/MLzHea1HrkpSaG+Y3fYg/WcRmUL8VczOdMIc9Vb5C6Fsu3obAbYkcRRdA3ADbLg3v/WDTqu5P/D+H/QLaapo0PNG2ZwAAAAASUVORK5CYII=", - "text/latex": [ - "$\\displaystyle t^{2} - x^{2} - y^{2} - z^{2} > 0$" - ], - "text/plain": [ - " 2 2 2 2 \n", - "t - x - y - z > 0" - ] - }, - "execution_count": 31, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "v2.is_timelike()" - ] - }, - { - "cell_type": "code", - "execution_count": 32, - "id": "da5af338-4554-4531-8db8-1f67be5be2b6", - "metadata": {}, - "outputs": [ - { - "data": { - "image/png": "iVBORw0KGgoAAAANSUhEUgAAACoAAAAOCAYAAABZ/o57AAAACXBIWXMAAA7EAAAOxAGVKw4bAAAB0UlEQVRIDb2W7U0CQRCGD0IBqB1oBxAqEDuA2IF0oH/5Z6ADtAKFDqAEpAOxA0MH+Dzn7uVyhFNAb5JhZudj592vOWrb7TYZDodvSZI04Q38GWQLKWlbw/rPg1yTc4NeGTVCJUH1KT6LldHv0UfwAP0pZ++hP8dxVbIOCHdqlgdZVjzELcti/sNXZ1KPc37g5KuwwAPTjg8XqDvqHTyE3gl2gZVRg51ZHVHNhU3JvUQ+wo47cBfuwy7ee6x/QZy2BHmHGMBpHuOx9kiMtT/AbsQF3MRmfFL351Ai2eLtkHcV5ATpo+zi82rot4MIOiVsPsprOLN9e9JFmGv3GRE3hlPASG3HATUxkEAE5mN0V8+QWYdgvHOl8G9CblFMMbyGeVIfujveQvZieyom/XZs0QxMCYjS+chzNz32dPcKwV7NzqlAndNdPZUEKbUB7T3Ok1dq+RdA9x1lvthPejyVOUCzj04+qZ4fVKEDJO5eVg6bx+uCbzNjTsHfPRVok/nkfeSHpAjMFiYo20+e7AY+TP0ZMfYzvq75pyRSCLLn2cxNEISTLmDv4oQYW48++5vf/eh/wb5zbNi8Y5K90dhX+AOWlvizPzfoLsq2JMVeas31Fx2vogF49TMKAAAAAElFTkSuQmCC", - "text/latex": [ - "$\\displaystyle \\text{True}$" - ], - "text/plain": [ - "True" - ] - }, - "execution_count": 32, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "v2.is_timelike().subs(values)" - ] - }, - { - "cell_type": "code", - "execution_count": 33, - "id": "0be2000d-4386-4ee0-8b78-1207045cc4c2", - "metadata": {}, - "outputs": [ - { - "data": { - "image/png": "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", - "text/latex": [ - "$\\displaystyle 9.2736184954957$" - ], - "text/plain": [ - "9.27361849549570" - ] - }, - "execution_count": 33, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "v2.to_rhophithetatau().tau.subs(values).evalf()" - ] - }, - { - "cell_type": "code", - "execution_count": 34, - "id": "d764bbca-2a30-4249-9caa-52642cb47e5d", - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "VectorSympy4D(x=x*(1 + x**2/(t**2*(1 + 1/sqrt(1 - x**2/t**2 - y**2/t**2 - z**2/t**2))*(1 - x**2/t**2 - y**2/t**2 - z**2/t**2))) + x/sqrt(1 - x**2/t**2 - y**2/t**2 - z**2/t**2) + x*y**2/(t**2*(1 + 1/sqrt(1 - x**2/t**2 - y**2/t**2 - z**2/t**2))*(1 - x**2/t**2 - y**2/t**2 - z**2/t**2)) + x*z**2/(t**2*(1 + 1/sqrt(1 - x**2/t**2 - y**2/t**2 - z**2/t**2))*(1 - x**2/t**2 - y**2/t**2 - z**2/t**2)), y=y*(1 + y**2/(t**2*(1 + 1/sqrt(1 - x**2/t**2 - y**2/t**2 - z**2/t**2))*(1 - x**2/t**2 - y**2/t**2 - z**2/t**2))) + y/sqrt(1 - x**2/t**2 - y**2/t**2 - z**2/t**2) + x**2*y/(t**2*(1 + 1/sqrt(1 - x**2/t**2 - y**2/t**2 - z**2/t**2))*(1 - x**2/t**2 - y**2/t**2 - z**2/t**2)) + y*z**2/(t**2*(1 + 1/sqrt(1 - x**2/t**2 - y**2/t**2 - z**2/t**2))*(1 - x**2/t**2 - y**2/t**2 - z**2/t**2)), z=z*(1 + z**2/(t**2*(1 + 1/sqrt(1 - x**2/t**2 - y**2/t**2 - z**2/t**2))*(1 - x**2/t**2 - y**2/t**2 - z**2/t**2))) + z/sqrt(1 - x**2/t**2 - y**2/t**2 - z**2/t**2) + x**2*z/(t**2*(1 + 1/sqrt(1 - x**2/t**2 - y**2/t**2 - z**2/t**2))*(1 - x**2/t**2 - y**2/t**2 - z**2/t**2)) + y**2*z/(t**2*(1 + 1/sqrt(1 - x**2/t**2 - y**2/t**2 - z**2/t**2))*(1 - x**2/t**2 - y**2/t**2 - z**2/t**2)), t=t/sqrt(1 - x**2/t**2 - y**2/t**2 - z**2/t**2) + x**2/(t*sqrt(1 - x**2/t**2 - y**2/t**2 - z**2/t**2)) + y**2/(t*sqrt(1 - x**2/t**2 - y**2/t**2 - z**2/t**2)) + z**2/(t*sqrt(1 - x**2/t**2 - y**2/t**2 - z**2/t**2)))" - ] - }, - "execution_count": 34, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "v2.boost(v2.to_beta3())" - ] - }, - { - "cell_type": "code", - "execution_count": 35, - "id": "11f06041-3f8d-418f-a4c2-c3378d0b930f", - "metadata": {}, - "outputs": [ - { - "data": { - "image/png": "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", - "text/latex": [ - "$\\displaystyle \\frac{t}{\\sqrt{1 - \\frac{x^{2}}{t^{2}} - \\frac{y^{2}}{t^{2}} - \\frac{z^{2}}{t^{2}}}} + \\frac{x^{2}}{t \\sqrt{1 - \\frac{x^{2}}{t^{2}} - \\frac{y^{2}}{t^{2}} - \\frac{z^{2}}{t^{2}}}} + \\frac{y^{2}}{t \\sqrt{1 - \\frac{x^{2}}{t^{2}} - \\frac{y^{2}}{t^{2}} - \\frac{z^{2}}{t^{2}}}} + \\frac{z^{2}}{t \\sqrt{1 - \\frac{x^{2}}{t^{2}} - \\frac{y^{2}}{t^{2}} - \\frac{z^{2}}{t^{2}}}}$" - ], - "text/plain": [ - " 2 2 ↪\n", - " t x y ↪\n", - "──────────────────────── + ────────────────────────── + ────────────────────── ↪\n", - " __________________ __________________ ______________ ↪\n", - " ╱ 2 2 2 ╱ 2 2 2 ╱ 2 2 ↪\n", - " ╱ x y z ╱ x y z ╱ x y ↪\n", - " ╱ 1 - ── - ── - ── t⋅ ╱ 1 - ── - ── - ── t⋅ ╱ 1 - ── - ── - ↪\n", - " ╱ 2 2 2 ╱ 2 2 2 ╱ 2 2 ↪\n", - "╲╱ t t t ╲╱ t t t ╲╱ t t ↪\n", - "\n", - "↪ 2 \n", - "↪ z \n", - "↪ ──── + ──────────────────────────\n", - "↪ ____ __________________\n", - "↪ 2 ╱ 2 2 2 \n", - "↪ z ╱ x y z \n", - "↪ ── t⋅ ╱ 1 - ── - ── - ── \n", - "↪ 2 ╱ 2 2 2 \n", - "↪ t ╲╱ t t t " - ] - }, - "execution_count": 35, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "v2.boost(v2.to_beta3()).t" - ] - }, - { - "cell_type": "code", - "execution_count": 36, - "id": "bf3b60b5-59a2-4cc7-ac40-ef759c062932", - "metadata": {}, - "outputs": [ - { - "data": { - "image/png": "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", - "text/latex": [ - "$\\displaystyle \\frac{t \\sqrt{\\frac{t^{2} - x^{2} - y^{2} - z^{2}}{t^{2}}} \\left(t^{2} + x^{2} + y^{2} + z^{2}\\right)}{t^{2} - x^{2} - y^{2} - z^{2}}$" - ], - "text/plain": [ - " ___________________ \n", - " ╱ 2 2 2 2 \n", - " ╱ t - x - y - z ⎛ 2 2 2 2⎞\n", - "t⋅ ╱ ───────────────── ⋅⎝t + x + y + z ⎠\n", - " ╱ 2 \n", - " ╲╱ t \n", - "───────────────────────────────────────────────\n", - " 2 2 2 2 \n", - " t - x - y - z " - ] - }, - "execution_count": 36, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "v2.boost(v2.to_beta3()).t.simplify()" - ] - }, - { - "cell_type": "code", - "execution_count": 37, - "id": "4cd7282c-f97d-45a0-bb03-acf5756cb383", - "metadata": {}, - "outputs": [ - { - "data": { - "image/png": "iVBORw0KGgoAAAANSUhEUgAAADwAAAAuCAYAAAB04nriAAAACXBIWXMAAA7EAAAOxAGVKw4bAAAFe0lEQVRoBe2Z7ZHUOBCGPRQBwJEBlwG3G8FBBnAbAZDBUfza/UdBBkAEfGQARMBBBkcGd7cZLM+jcatkje0xi+1ji+0qjaRWS+q3u9Uey5uzs7PmR6KTk5Nb6HNE/Ygyu3JXfySwrS5PqR/ZBvCm5c1WXZltpRkWAqDeFejnGZbrXSIDjs1KKXjXKDeDZ5vyQH7wZq4fs54eXozKkP7QAgnrBqjfit31wHMLsgU7N0/hX8+9b2gwT8Nq0Pf1NHjqojGC7L/pk1UAfm20V/ASrhLwv+1qgvpCeUt5guBpy7c6pKiQ4zXdhpHOXj0wse/coflP0eNhuQ59ARuB6pmItkZ7QzHhJcNR27f8SmlKwJ8ZvCdzjJC5U4/DS2FPnTevZcb6zNNjB9QdUM6B94Dqk+2K7tP/QCn3FJjeLKPEtbODSsDw99LHAQk9sNdYA3NlG4JPBsb1jAZ9MTCe2Ox/l4bR+XspB7/joCvl4L42k0trJnF4Y8ruW7Jhvh643bd2O1kj32X8XSsba7qv+STI6DCHlEcwxnK9iT8eCBoO7ygqcIOiVT3DkcTodokxZUxgHSt2pcZ7zFXxv6kHPciYuulByXOu1zVAdgDt/+AZuob6EeUfinKd5FZ6WKCvmfiMEgnkE22T0RCprKWXmKtnxuY7T5lBsAow7nEJGfdzzdoR6i+ZC0xa4tDrAg5jNRkwzDuUHA60tZaHvwwbultiXO8aimWCiOEG/p90XlLGDKJM7/p5IRqspcLqpsfcz72NigSEOsDeoh2GQSTRa35fhkwG3A7WlaB9NrpBTVovZ79yEHmThxtbVMJ+Hz1k7FnfQPAYN0vrDL32heLxiQSZgbTyffqY4TXIgTIJMIt4HvpSvzJSWHDb2/5q3Xh2l/yGtXzE6ZHIvOWfhiTLuED2ehcZI6TzfGauZ1dvq5dR5l5S1Nte9zc5LQGGL3on1/SLDBbsnBf6yrrA2AbOc1wve07ThrSDBFGHX4ylut3HPxc7+8DTmwJPOlIb6uo1RMn7AfgFC2ixmkwOfWc0hQdjvR6uFokznL3EXkbH2z4g5dx23EdNbawQE2DoZ7T0yfnX2DWSXAD20dIJL/omFCnOy7a3/Q1L7li+FLLNOlrWzcqXDkM8wp3mKLl/+htZSrGuR8KjmDxHrbffU4eBG9rq+QfFR1Wi8jmsdcILhoneM1HsgIKnrGf+Pu38LKTfS8gYKT7jXV8FTUImvUmErElPI5UR1Xm+xkLICjgcIo7Of4kMOCYsVaOIBtJQAr5HP3lmqf2G1o2QHhqfk28Ia3kfLf8LWMGsBhiQhr7ZPo6N+69Oq4X06sgGNlzNwwP7r86+BLy6yVfe8Kfz8Ob4+Hj22/2VnTZ5O54Um8ssPdlcF1TwpzvDl4AvaKROVvvqZMnvFCRD+ornHVbntZD+Tfnt8r5c2PdiP17s26F5qtUAo653y748ZAKUAH3nDsANbW9DfLH3FXLvu3ZebGJjlTOM4nF7UqvlrYU3IYIMCs/6wj87LQ4YMIbyaVtqAHq8M4a8/cVojZA+AkQnbAMNfL3Z+Z4ML7zduWOLOd9bL+phlJ/0ZSFAIO/dl3dSJrfRK9yY8631Yh5GYbOt16N7r3OQMewFe0gxzP+iLEKLAUZbvTTpOgc5QaYMTtuQ9iPexcnSKDv1M8qOF5nro8jEtXMXvSN8DsbsZxiFDWU/j0wKZeQM55oipA3zWWmJkBbwIUD8o1GSwPwSKd+rWsM9fcCjfZ2y6OMoFJkdMIr7qIk/D7FPA98v9H4KKT/dCFJeDfagnbizTl7wnI3ZAY/ocY0xS0k7SQ3wJi3lTHq1Icq552ovfuOB0v6BMMzjPJqUPsJPH8Kp5ZdeV3axl4eviiMGEw28sb8AAAAASUVORK5CYII=", - "text/latex": [ - "$\\displaystyle \\frac{57 \\sqrt{86}}{43}$" - ], - "text/plain": [ - "57⋅√86\n", - "──────\n", - " 43 " - ] - }, - "execution_count": 37, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "v2.boost(v2.to_beta3()).t.subs(values)" - ] - }, - { - "cell_type": "code", - "execution_count": 38, - "id": "a52b57a0-516f-4a14-b0dc-590c8d3b1017", - "metadata": {}, - "outputs": [ - { - "data": { - "image/png": "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", - "text/latex": [ - "$\\displaystyle 12.292936145192$" - ], - "text/plain": [ - "12.2929361451920" - ] - }, - "execution_count": 38, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "v2.boost(v2.to_beta3()).t.subs(values).evalf()" - ] - }, - { - "cell_type": "markdown", - "id": "0e7b9e31-5e43-4bf7-9de5-b8d3e95fd6d5", - "metadata": {}, - "source": [ - "All of the keyword arguments and rules that apply to `vector.obj` construction apply to `vector.VectorSympyND` and `vector.MomentumObjectND` objects." - ] - }, - { - "cell_type": "markdown", - "id": "sustained-object", - "metadata": {}, - "source": [ - "### NumPy arrays of vectors\n", - "\n", - "You can directly use the `VectorNumpy` classes to construct object type vectors:" - ] - }, - { - "cell_type": "code", - "execution_count": 39, - "id": "c88d6a0c", - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "VectorNumpy2D([(1.1, 2.1), (1.2, 2.2), (1.3, 2.3), (1.4, 2.4), (1.5, 2.5)],\n", - " dtype=[('x', '[[{x: 1, y: 1.1, z: 0.1}, {x: 2, y: 2.2, z: 0.2}],\n", - " [],\n", - " [{x: 3, y: 3.3, z: 0.3}],\n", - " [{x: 4, y: 4.4, z: 0.4}, {x: 5, y: 5.5, ...}, {x: 6, y: 6.6, z: 0.6}]]\n", - "-----------------------------------------------------------------------\n", - "type: 4 * var * Vector3D[\n", - " x: int64,\n", - " y: float64,\n", - " z: float64\n", - "]" - ], - "text/plain": [ - "" - ] - }, - "execution_count": 49, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "vector.Array(\n", - " [\n", - " [{\"x\": 1, \"y\": 1.1, \"z\": 0.1}, {\"x\": 2, \"y\": 2.2, \"z\": 0.2}],\n", - " [],\n", - " [{\"x\": 3, \"y\": 3.3, \"z\": 0.3}],\n", - " [\n", - " {\"x\": 4, \"y\": 4.4, \"z\": 0.4},\n", - " {\"x\": 5, \"y\": 5.5, \"z\": 0.5},\n", - " {\"x\": 6, \"y\": 6.6, \"z\": 0.6},\n", - " ],\n", - " ]\n", - ")" - ] - }, - { - "cell_type": "markdown", - "id": "hybrid-powell", - "metadata": {}, - "source": [ - "If you want _any_ records named \"`Vector2D`\", \"`Vector3D`\", \"`Vector4D`\", \"`Momentum2D`\", \"`Momentum3D`\", or \"`Momentum4D`\" to be interpreted as vectors, register the behaviors globally." - ] - }, - { - "cell_type": "code", - "execution_count": 50, - "id": "becoming-demand", - "metadata": {}, - "outputs": [], - "source": [ - "vector.register_awkward()" - ] - }, - { - "cell_type": "code", - "execution_count": 51, - "id": "bored-ribbon", - "metadata": {}, - "outputs": [ - { - "data": { - "text/html": [ - "
[[{x: 1, y: 1.1, z: 0.1}, {x: 2, y: 2.2, z: 0.2}],\n",
-       " [],\n",
-       " [{x: 3, y: 3.3, z: 0.3}],\n",
-       " [{x: 4, y: 4.4, z: 0.4}, {x: 5, y: 5.5, ...}, {x: 6, y: 6.6, z: 0.6}]]\n",
-       "-----------------------------------------------------------------------\n",
-       "type: 4 * var * Vector3D[\n",
-       "    x: int64,\n",
-       "    y: float64,\n",
-       "    z: float64\n",
-       "]
" - ], - "text/plain": [ - "" - ] - }, - "execution_count": 51, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "ak.Array(\n", - " [\n", - " [{\"x\": 1, \"y\": 1.1, \"z\": 0.1}, {\"x\": 2, \"y\": 2.2, \"z\": 0.2}],\n", - " [],\n", - " [{\"x\": 3, \"y\": 3.3, \"z\": 0.3}],\n", - " [\n", - " {\"x\": 4, \"y\": 4.4, \"z\": 0.4},\n", - " {\"x\": 5, \"y\": 5.5, \"z\": 0.5},\n", - " {\"x\": 6, \"y\": 6.6, \"z\": 0.6},\n", - " ],\n", - " ],\n", - " with_name=\"Vector3D\",\n", - ")" - ] - }, - { - "cell_type": "markdown", - "id": "beginning-expert", - "metadata": {}, - "source": [ - "All of the keyword arguments and rules that apply to `vector.obj` construction apply to `vector.Array` field names.\n", - "\n", - "Finally, the `VectorAwkward` mixins can be subclassed to create custom vector classes. The awkward behavior classes and projections must be named as `*Array`. For example, `coffea` uses the following names - `TwoVectorArray`, `ThreeVectorArray`, `PolarTwoVectorArray`, `SphericalThreeVectorArray`, ..." - ] - }, - { - "cell_type": "markdown", - "id": "documentary-skill", - "metadata": {}, - "source": [ - "## Vector properties\n", - "\n", - "Any geometrical coordinate can be computed from vectors in any coordinate system; they'll be provided or computed as needed." - ] - }, - { - "cell_type": "code", - "execution_count": 52, - "id": "colored-directory", - "metadata": {}, - "outputs": [ - { - "data": { - "image/png": "iVBORw0KGgoAAAANSUhEUgAAABkAAAAPCAYAAAARZmTlAAAACXBIWXMAAA7EAAAOxAGVKw4bAAABjElEQVQ4Ea2U723CQAzFU9QBItgg3QDaDdIN2m5QukH5mHyrwgYwQmED0gkQbAAbgNgg/b3kjEKUP1VUSy/ne2efz/blvCzLvCiKxhrLgPNBUOb66vdeIT9xHPuoezeXLpkUQ/cX/8RZnRgfQAJ3FDfQBzmDCxgDBViDCUbiOgW7HUZbxhmYo8/ABj3InVUCyrLqWwp8p+BQ9YdLwEa8ZZIH7Pl5xc/KXN5iyyQkG/8/goRspnJXJe8HZGiN94g4hVA/RkC1/IKrOyFLhbAu+y4ZWiYy/sZpDtQ0YYeuU7bJ0C22XZCiXGz2DK6G6Eo1BYu2CH9cG1kmdfYKFBBQpWuSul6YrWV5GrCJ7rPueZM01h0/y77OxrijMnkERpQD5Sdho9bm46Cy1mVrmaQKsmQjPQNVUdO1QZesMNBBq6Inaa9sFWSBctNg5p/OQz9aLnA+yMBNaZkvMTgzvjhTD12VeQPv4u7020MqXV1bidJUQ/UOXUSYMD+gp4wfxmlkrk31QMpeD+QTuP5nv4JEA14+QuryAAAAAElFTkSuQmCC", - "text/latex": [ - "$\\displaystyle 5.0$" - ], - "text/plain": [ - "5.0" - ] - }, - "execution_count": 52, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "vector.obj(x=3, y=4).rho" - ] - }, - { - "cell_type": "code", - "execution_count": 53, - "id": "passive-benchmark", - "metadata": {}, - "outputs": [ - { - "data": { - "image/png": "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", - "text/latex": [ - "$\\displaystyle 2.99998087197215$" - ], - "text/plain": [ - "2.9999808719721477" - ] - }, - "execution_count": 53, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "vector.obj(rho=5, phi=0.9273).x" - ] - }, - { - "cell_type": "code", - "execution_count": 54, - "id": "indoor-opportunity", - "metadata": {}, - "outputs": [ - { - "data": { - "image/png": "iVBORw0KGgoAAAANSUhEUgAAAKAAAAAPCAYAAABjhcQWAAAACXBIWXMAAA7EAAAOxAGVKw4bAAAFQUlEQVRoBe2a600dMRCFL4gCbkgFkA4CdJB0kEcFhA5A+cc/BB1AKsijA0gFPDpIUkEIHdycz3fH8nrttc2NtFGUkXxtj8fH9vF41ruwtlgsZv/l72Hg+Pj4udJdOCPV56pvKv8e6v+F8kZuERChtgPlBzmbWC/b0073U/kzpdMUaVPZ2Xw1Pmv7rLSj8oPpc3lnP+BC+m31MX5wEuqs+SqHZfocptq/qg0sc0LKyM4y6//K9jzQbKq8L93omkbGnj0Gj/FzmNKPcpR1QGGyQUYCY4yKBrqVwYnyLxgqh7hb5S+V/MlVeSo75vNB6V5pVwliamXARbe+I+XmgDOVXwnwUvlrJcfDyAADzM6W+SEcEngDB157TqW641dt5yqfKZ8pp88P5RwszzltkQzGlv0qeMDnMEc5Wo8m5qqazGFKn9PJ/p3a5so96SpDGHV/QqeyY97MRwnHwGE+oqsR2ee4YM3v1I7TmVjke2+KVD6Cifmd2p8orSk9U2IDe87XYXKYeCw750OnMgHjRslzjj4U2eTW8yg8sEcwixwNHFBgnCIWnFo046XktZSpaHkt/QthzrtOU9ml5lzUFbhgvT2eZF/krIBZnFNggOOnohzzCjn3XQpjN+MBXMAscjRwQGG+FeiFn3Vd4YXM7hOmRhDtyFR2y9Hbf7NciKMrJSKVRb2ZyhYNsxFIU8hi1k5P49iBTnHO/RvZXWa93+TYK+ABnsSkQbhFjnp3QHUgPI+RB25Pgsn39FGFR4WRFjX1qn/crofeUGnlQvYcLl7CeFlJHuBaTNm5K42wniptK3EHJJo4UZnrBGVeOmKhD0I/L7LP7u1j8AAew/QDBwXZDzjyDqhGJszCLGoFXUeLRsLY4wfnm8pudPKpxhYuZMuVBWL3lHAS7mADacCEq0+yd3x2/b4p52XOR1vZcL9m3FiYDwKOkw6jtLfVeIBWYtr4WY7CR3D25DqU1X7sVJZQprKL51XNhTaCl4YzJe63vNzw5m+P4hC3ClN9cTTnfHRWmYCA48VPpv2u3TuhbNlo6xsGkpqxW/AYugYTO9aQ5cg5oAwI+fECXeeKn9Q9xLptdgXuJVPZ2Vyq8lW4UF+iCA7wWeUwAq3CL/PGmbaF6R+rKjPOlhJv9odKPP5p58UPcQ4ofdXYtXgA12JiG4v69jjakIJJz5WHJybul62rn91HPOGBsem+T2UXzKVYbOFCtu5Rp9zfzboBbpQTlUhfGjEv1Yd78I7ylBifrk12OKH/DolSOhwRgfOmvS3hAdqCKdsiRxvCZJJ7MuZDYih05tShZzFHYWNU5hEBTiwWAe3uMpVdPK9cvYULPqjPxAtvwjhCTloweXNNPSkcjxondvbUmOwbb58EBvBW3VuP1w3Wsp4iR0RAnMIcpBvDEfsLvdq525QEJ7WTF9pyknn+2wZNZRfOKVtu5II1uY2OAO3zh+O0EfNC9qmDTjTt7ZHsuGfy8XhLZcev8rnq2LoIqnr13tbgCXfWginzIkfrgGaExZC8aHAe1Qsl59nWoDqfHe6VQ4oTlen7RsldblFOZcfYkdjLjkXoqHlQHXAhCxyFR6aXbv3YckF/8A3pQgqTP6v17uKq218u4kBAJIqjJQecsUuRMjX2KnisMIVZ5Ggt/m+YjgAmw0lCuDReS29/b/ymOic/vnswAaLggxIvHXyWOInJUH0SO81lprHZIIS1MQ82irsvf78dfLuTDmcY4wKc0DGwHf1nhApMMCwKckBwsiP1g9eeSGdPHdaC8PLTi5RL9fK3YuwmPFArMEc5+g0NearHmXz/ygAAAABJRU5ErkJggg==", - "text/latex": [ - "$\\displaystyle 4.00001434594943$" - ], - "text/plain": [ - "4.000014345949428" - ] - }, - "execution_count": 54, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "vector.obj(rho=5, phi=0.9273).y" - ] - }, - { - "cell_type": "code", - "execution_count": 55, - "id": "mature-clone", - "metadata": {}, - "outputs": [ - { - "data": { - "image/png": "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", - "text/latex": [ - "$\\displaystyle 0.640522312679424$" - ], - "text/plain": [ - "0.6405223126794245" - ] - }, - "execution_count": 55, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "vector.obj(x=1, y=2, z=3).theta" - ] - }, - { - "cell_type": "code", - "execution_count": 56, - "id": "peripheral-script", - "metadata": {}, - "outputs": [ - { - "data": { - "image/png": "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", - "text/latex": [ - "$\\displaystyle 1.10358684156015$" - ], - "text/plain": [ - "1.103586841560145" - ] - }, - "execution_count": 56, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "vector.obj(x=1, y=2, z=3).eta" - ] - }, - { - "cell_type": "markdown", - "id": "caroline-capability", - "metadata": {}, - "source": [ - "Some properties are not coordinates, but derived from them." - ] - }, - { - "cell_type": "code", - "execution_count": 57, - "id": "stretch-knife", - "metadata": {}, - "outputs": [ - { - "data": { - "image/png": "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", - "text/latex": [ - "$\\displaystyle 0.801783725737273$" - ], - "text/plain": [ - "0.8017837257372732" - ] - }, - "execution_count": 57, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "vector.obj(x=1, y=2, z=3).costheta" - ] - }, - { - "cell_type": "code", - "execution_count": 58, - "id": "bearing-protein", - "metadata": {}, - "outputs": [ - { - "data": { - "image/png": "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", - "text/latex": [ - "$\\displaystyle 3.74165738677394$" - ], - "text/plain": [ - "3.7416573867739413" - ] - }, - "execution_count": 58, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "vector.obj(x=1, y=2, z=3).mag # spatial magnitude" - ] - }, - { - "cell_type": "code", - "execution_count": 59, - "id": "green-crack", - "metadata": {}, - "outputs": [ - { - "data": { - "image/png": "iVBORw0KGgoAAAANSUhEUgAAABMAAAAOCAYAAADNGCeJAAAACXBIWXMAAA7EAAAOxAGVKw4bAAAA8klEQVQ4EaWT7Q2CQAyGxTAA0Q0YwY8NXMG4gWzgb9ZQR9ANZAMTR2AEZQN8XnJNPJBwaJOmvV7vufY+orquJyZ5ni/wL+gSv7J4n3X5GTZTToyTYM/oE12hKRoq2vhhyYKpgq0C+AeMqhsUl+vlTb1R4ACQNlQR3lH8BAOyA3hq7z0a5to7tkEaj4IBSllTYcu/YQD0DDrtGTi4MiB7Fn1tbxTMtZf0tWew2JwBq7NaA9Mj/RQ9kdTFyyAYyQWLpJ4QfxEosM2jb5/Z3GXPvFX9A31FaSORPjpkK39DVJP6b7r+G3Od2yOmi1Drypdc0fsbefVKjEhUk9oAAAAASUVORK5CYII=", - "text/latex": [ - "$\\displaystyle 14$" - ], - "text/plain": [ - "14" - ] - }, - "execution_count": 59, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "vector.obj(x=1, y=2, z=3).mag2 # spatial magnitude squared" - ] - }, - { - "cell_type": "markdown", - "id": "adjustable-serum", - "metadata": {}, - "source": [ - "These properties are provided because they can be computed faster or with more numerical stability in different coordinate systems. For instance, the magnitude ignores `phi` in polar coordinates." - ] - }, - { - "cell_type": "code", - "execution_count": 60, - "id": "amber-disco", - "metadata": {}, - "outputs": [ - { - "data": { - "image/png": "iVBORw0KGgoAAAANSUhEUgAAABMAAAAPCAYAAAAGRPQsAAAACXBIWXMAAA7EAAAOxAGVKw4bAAABjUlEQVQ4EY2TMVICQRBFF/UAK56AJTVCzQnwBmpmqjeQMoLM0htAaCiGZmgViSHcAI5gkRniewMDy7JW0VV/u/t3T09vz0yyWCySfdHpdBrFXLgUZPJHCdLtdjNUWxs5Bz+gDT+RyMkXXIofeW3lzM8hsFCPpJtms/kB+qPR6BTuFf2NP8MOgn+HUQE18AvewS1r5+jQ2TP6XicKQbty4QAcRx49gb/O+VvmAV4LTEmKLceET4wU3s73Eou5aMai0GrJquImJSlLquIplAnFp/AZ2hkFwfa3h8ANToBdP8GHA7GzHSHYgDQxnnDMscgb8RdgTIyxHVVSese4N1MwKN6pMp+8ofnGdjpjlx57OMN/Ty10sfl4dRxHtlUMwutQRV9ucpcW3BCMi3zOT9fFSLwiUEevO8IOO64W+DLKTrZqnNxJKIbhwC/QxYG7gU9L6ROvL82tr8P3eiUVhpehPe5ASOakFQugzfNlrF8L9gPcI6hhzy0W7lOuQN70+YRHLIkdCq4S/D27doO53B+ljuuToylupQAAAABJRU5ErkJggg==", - "text/latex": [ - "$\\displaystyle 25$" - ], - "text/plain": [ - "25" - ] - }, - "execution_count": 60, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "vector.obj(rho=3, phi=0.123456789, z=4).mag2" - ] - }, - { - "cell_type": "markdown", - "id": "interpreted-intensity", - "metadata": {}, - "source": [ - "Momentum vectors have geometrical properties as well as their momentum-synonyms." - ] - }, - { - "cell_type": "code", - "execution_count": 61, - "id": "latest-thunder", - "metadata": {}, - "outputs": [ - { - "data": { - "image/png": "iVBORw0KGgoAAAANSUhEUgAAABkAAAAPCAYAAAARZmTlAAAACXBIWXMAAA7EAAAOxAGVKw4bAAABjElEQVQ4Ea2U723CQAzFU9QBItgg3QDaDdIN2m5QukH5mHyrwgYwQmED0gkQbAAbgNgg/b3kjEKUP1VUSy/ne2efz/blvCzLvCiKxhrLgPNBUOb66vdeIT9xHPuoezeXLpkUQ/cX/8RZnRgfQAJ3FDfQBzmDCxgDBViDCUbiOgW7HUZbxhmYo8/ABj3InVUCyrLqWwp8p+BQ9YdLwEa8ZZIH7Pl5xc/KXN5iyyQkG/8/goRspnJXJe8HZGiN94g4hVA/RkC1/IKrOyFLhbAu+y4ZWiYy/sZpDtQ0YYeuU7bJ0C22XZCiXGz2DK6G6Eo1BYu2CH9cG1kmdfYKFBBQpWuSul6YrWV5GrCJ7rPueZM01h0/y77OxrijMnkERpQD5Sdho9bm46Cy1mVrmaQKsmQjPQNVUdO1QZesMNBBq6Inaa9sFWSBctNg5p/OQz9aLnA+yMBNaZkvMTgzvjhTD12VeQPv4u7020MqXV1bidJUQ/UOXUSYMD+gp4wfxmlkrk31QMpeD+QTuP5nv4JEA14+QuryAAAAAElFTkSuQmCC", - "text/latex": [ - "$\\displaystyle 5.0$" - ], - "text/plain": [ - "5.0" - ] - }, - "execution_count": 61, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "vector.obj(px=3, py=4).rho" - ] - }, - { - "cell_type": "code", - "execution_count": 62, - "id": "included-fireplace", - "metadata": {}, - "outputs": [ - { - "data": { - "image/png": "iVBORw0KGgoAAAANSUhEUgAAABkAAAAPCAYAAAARZmTlAAAACXBIWXMAAA7EAAAOxAGVKw4bAAABjElEQVQ4Ea2U723CQAzFU9QBItgg3QDaDdIN2m5QukH5mHyrwgYwQmED0gkQbAAbgNgg/b3kjEKUP1VUSy/ne2efz/blvCzLvCiKxhrLgPNBUOb66vdeIT9xHPuoezeXLpkUQ/cX/8RZnRgfQAJ3FDfQBzmDCxgDBViDCUbiOgW7HUZbxhmYo8/ABj3InVUCyrLqWwp8p+BQ9YdLwEa8ZZIH7Pl5xc/KXN5iyyQkG/8/goRspnJXJe8HZGiN94g4hVA/RkC1/IKrOyFLhbAu+y4ZWiYy/sZpDtQ0YYeuU7bJ0C22XZCiXGz2DK6G6Eo1BYu2CH9cG1kmdfYKFBBQpWuSul6YrWV5GrCJ7rPueZM01h0/y77OxrijMnkERpQD5Sdho9bm46Cy1mVrmaQKsmQjPQNVUdO1QZesMNBBq6Inaa9sFWSBctNg5p/OQz9aLnA+yMBNaZkvMTgzvjhTD12VeQPv4u7020MqXV1bidJUQ/UOXUSYMD+gp4wfxmlkrk31QMpeD+QTuP5nv4JEA14+QuryAAAAAElFTkSuQmCC", - "text/latex": [ - "$\\displaystyle 5.0$" - ], - "text/plain": [ - "5.0" - ] - }, - "execution_count": 62, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "vector.obj(px=3, py=4).pt" - ] - }, - { - "cell_type": "code", - "execution_count": 63, - "id": "analyzed-andrews", - "metadata": {}, - "outputs": [ - { - "data": { - "image/png": "iVBORw0KGgoAAAANSUhEUgAAAJQAAAAPCAYAAAACneZUAAAACXBIWXMAAA7EAAAOxAGVKw4bAAAFbUlEQVRoBe2a35XVNhCHDWcLWEgH0AGwHWw6CKECoIPk5G3fONBBoAL+dJCkAgIdQAeB7WDzfbqWIsuyr2TvCS/MObqSR6PfjDSjkezdG1dXV8N36l+Bi4uLe5SP+UieT3m+Tf0553+rNnbcQfc55Q3ty//DjpNcCUrv8fyWcn+PASPOU+qnOX5s9+pZwoPvgv064j6g/uIz/Imjx/5QHdM9Yka7DRB1PIf/Z45D+y949kddtqX7h2r+i/zzgvsaXhw/0G6ezyh7zE79+bsF+UJ1eLyEf8tWI94EgzGzeDmB6UK8ougMneKk9pJBmRZKsJ16anja6UL9KL5EW4d9kEdJAUC7aY6jnAEZHTXQ/gnMP6gfUt6pZyTXS3JRzUj2PUPmknpC8LTVOYgd7KL22XKXMowyPfNpsfMMaPXVMqaZK2xGdLs+LXjaubqWBpQL8JCi8C9ULtBmGjFm47fqWcJDgcGTHK9CZF2UJzR1VNh5I791jo59AoYBFIMnBuZv9EWesB+RCevmwxHSHrNRxFJcx+SObp4P45rtRGfacCqV4IWkQR3n04O3upY3Dyqu5xcDDUYVWnbTETx32CdkdExOOu0Ufli0vKOhbVad2A/Orrkw3gznurzM9cM3i+bO7plPq53vc51Z2yM834yteBlEvXlSZ2/mPsLQSercjHQYuIZn4HgxXnJ4GWhHTQFLzJTZHADPgJC8i2whHeddZcnOiNk8n1Y7kYsZKOoY4JkJnyUGDXjXNu9rCyiM8rjcuuj5/EL7GB79S8dNOLLpd9ftIjDMGuEooj3JMALD86gwcH+gmBG9Q5V6vZd+hq9djyj/ULw3vYWnIwPR3jwfxq7amenQRjdhfJGJXZO6FW8yaHy4loDCAA11F+Z3gpq+Jt5WPMbpNG1ZXbBjRow4OumMYoD8XRljIKXX8dFmj+DJCwEyMVM+oC/ZRfsr5TFllkWiLvpW5zP2H7Mzwlm7OSxV2oA3w7k542xj+IlgtoO3QYVRW/G8/L7Dlhc7dA+M98L9gmLWeE3xzTEefQGaZwMnHWO03UxmnJSl4cVgMiuU6/MG2VeZTMAtflbnw9ijdkY8ZN1o59QpK8a+WPfgxTFlvTugMMK0nxaxVND7vBWPcdrg0bJ0dPSaEuTBM4MYOB5RMUCWsAyqO8jpvJxqmfsDAuJ5JM4IjK75NNjpXa5mx0y3jAa86rhdAYVSF843qmZDq1aMzK14jDOo/UKdvzWtqar2Md5MEu5ghUA88jxeBmT8rGBALFEIPGQMRCnWh6fpbxl84q/Oh/4mO6dqBjPsl4IXHjfi1aCGvXcoF+MMg0zNOYWzf+SbNdLdIReqtLvxwHah7lKnzEQ7OIm6N9BDkDDuFmUtCMwqNefcdk6MzS/mHjGzoFFupImNjG2ZT6udQQWYBrg25HaN6kPVhZcPLNu7AgpDXazZmQz/q3zq5ORSce25Fw95A9eALgNWp5R3lprKkmcQaXcZTAaQFOf6sqLTfjNYlPFZ8ugqN5x8/0Tji0ySp906n1Y71SNF+2ubwP5ePMdUqQwoX38ld9pkUZnsKTwDxYvg4t+r6JeUtSzRop6FATM8bHDH6SgDoLzDncNbupiv6S4DcwDH4FS/LwqX1JJ/IrGkj4O0/WwiTTYRfF8StNGPiQGfWryfKY8dIMHrmU+rnQfw/3wR7Y/8WPfixXGztbzhfxswmbiD3GFO1tRoKvaukHY67U/wXJy0kDwngq9jXRhxJC+07+EH51I36Qkj+VnDo09b1FWjWdC36kZO2/OgUIfBkDKJCnmWHx3hBnT3+1G36jT4vq67tpLyk29W9PfOp8lOlYGtrR5ri58pkOnBW/Tjv+UeF7RHL5lRAAAAAElFTkSuQmCC", - "text/latex": [ - "$\\displaystyle 1.4142135623731$" - ], - "text/plain": [ - "1.4142135623730951" - ] - }, - "execution_count": 63, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "vector.obj(x=1, y=2, z=3, E=4).tau" - ] - }, - { - "cell_type": "code", - "execution_count": 64, - "id": "declared-yeast", - "metadata": {}, - "outputs": [ - { - "data": { - "image/png": "iVBORw0KGgoAAAANSUhEUgAAAJQAAAAPCAYAAAACneZUAAAACXBIWXMAAA7EAAAOxAGVKw4bAAAFbUlEQVRoBe2a35XVNhCHDWcLWEgH0AGwHWw6CKECoIPk5G3fONBBoAL+dJCkAgIdQAeB7WDzfbqWIsuyr2TvCS/MObqSR6PfjDSjkezdG1dXV8N36l+Bi4uLe5SP+UieT3m+Tf0553+rNnbcQfc55Q3ty//DjpNcCUrv8fyWcn+PASPOU+qnOX5s9+pZwoPvgv064j6g/uIz/Imjx/5QHdM9Yka7DRB1PIf/Z45D+y949kddtqX7h2r+i/zzgvsaXhw/0G6ezyh7zE79+bsF+UJ1eLyEf8tWI94EgzGzeDmB6UK8ougMneKk9pJBmRZKsJ16anja6UL9KL5EW4d9kEdJAUC7aY6jnAEZHTXQ/gnMP6gfUt6pZyTXS3JRzUj2PUPmknpC8LTVOYgd7KL22XKXMowyPfNpsfMMaPXVMqaZK2xGdLs+LXjaubqWBpQL8JCi8C9ULtBmGjFm47fqWcJDgcGTHK9CZF2UJzR1VNh5I791jo59AoYBFIMnBuZv9EWesB+RCevmwxHSHrNRxFJcx+SObp4P45rtRGfacCqV4IWkQR3n04O3upY3Dyqu5xcDDUYVWnbTETx32CdkdExOOu0Ufli0vKOhbVad2A/Orrkw3gznurzM9cM3i+bO7plPq53vc51Z2yM834yteBlEvXlSZ2/mPsLQSercjHQYuIZn4HgxXnJ4GWhHTQFLzJTZHADPgJC8i2whHeddZcnOiNk8n1Y7kYsZKOoY4JkJnyUGDXjXNu9rCyiM8rjcuuj5/EL7GB79S8dNOLLpd9ftIjDMGuEooj3JMALD86gwcH+gmBG9Q5V6vZd+hq9djyj/ULw3vYWnIwPR3jwfxq7amenQRjdhfJGJXZO6FW8yaHy4loDCAA11F+Z3gpq+Jt5WPMbpNG1ZXbBjRow4OumMYoD8XRljIKXX8dFmj+DJCwEyMVM+oC/ZRfsr5TFllkWiLvpW5zP2H7Mzwlm7OSxV2oA3w7k542xj+IlgtoO3QYVRW/G8/L7Dlhc7dA+M98L9gmLWeE3xzTEefQGaZwMnHWO03UxmnJSl4cVgMiuU6/MG2VeZTMAtflbnw9ijdkY8ZN1o59QpK8a+WPfgxTFlvTugMMK0nxaxVND7vBWPcdrg0bJ0dPSaEuTBM4MYOB5RMUCWsAyqO8jpvJxqmfsDAuJ5JM4IjK75NNjpXa5mx0y3jAa86rhdAYVSF843qmZDq1aMzK14jDOo/UKdvzWtqar2Md5MEu5ghUA88jxeBmT8rGBALFEIPGQMRCnWh6fpbxl84q/Oh/4mO6dqBjPsl4IXHjfi1aCGvXcoF+MMg0zNOYWzf+SbNdLdIReqtLvxwHah7lKnzEQ7OIm6N9BDkDDuFmUtCMwqNefcdk6MzS/mHjGzoFFupImNjG2ZT6udQQWYBrg25HaN6kPVhZcPLNu7AgpDXazZmQz/q3zq5ORSce25Fw95A9eALgNWp5R3lprKkmcQaXcZTAaQFOf6sqLTfjNYlPFZ8ugqN5x8/0Tji0ySp906n1Y71SNF+2ubwP5ePMdUqQwoX38ld9pkUZnsKTwDxYvg4t+r6JeUtSzRop6FATM8bHDH6SgDoLzDncNbupiv6S4DcwDH4FS/LwqX1JJ/IrGkj4O0/WwiTTYRfF8StNGPiQGfWryfKY8dIMHrmU+rnQfw/3wR7Y/8WPfixXGztbzhfxswmbiD3GFO1tRoKvaukHY67U/wXJy0kDwngq9jXRhxJC+07+EH51I36Qkj+VnDo09b1FWjWdC36kZO2/OgUIfBkDKJCnmWHx3hBnT3+1G36jT4vq67tpLyk29W9PfOp8lOlYGtrR5ri58pkOnBW/Tjv+UeF7RHL5lRAAAAAElFTkSuQmCC", - "text/latex": [ - "$\\displaystyle 1.4142135623731$" - ], - "text/plain": [ - "1.4142135623730951" - ] - }, - "execution_count": 64, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "vector.obj(x=1, y=2, z=3, E=4).mass" - ] - }, - { - "cell_type": "markdown", - "id": "alpine-investor", - "metadata": {}, - "source": [ - "Here's the key thing: _arrays of vectors return arrays of coordinates_." - ] - }, - { - "cell_type": "code", - "execution_count": 65, - "id": "attempted-country", - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "array([1.50363023, 1.50363023, 1.50363023, 1.50363023, 1.50363023])" - ] - }, - "execution_count": 65, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "vector.array(\n", - " {\n", - " \"x\": [1.0, 2.0, 3.0, 4.0, 5.0],\n", - " \"y\": [1.1, 2.2, 3.3, 4.4, 5.5],\n", - " \"z\": [0.1, 0.2, 0.3, 0.4, 0.5],\n", - " }\n", - ").theta" - ] - }, - { - "cell_type": "code", - "execution_count": 66, - "id": "consecutive-attempt", - "metadata": {}, - "outputs": [ - { - "data": { - "text/html": [ - "
[[1.5, 1.5],\n",
-       " [],\n",
-       " [1.5],\n",
-       " [1.5, 1.5]]\n",
-       "-----------------------\n",
-       "type: 4 * var * float64
" - ], - "text/plain": [ - "" - ] - }, - "execution_count": 66, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "vector.Array(\n", - " [\n", - " [{\"x\": 1, \"y\": 1.1, \"z\": 0.1}, {\"x\": 2, \"y\": 2.2, \"z\": 0.2}],\n", - " [],\n", - " [{\"x\": 3, \"y\": 3.3, \"z\": 0.3}],\n", - " [{\"x\": 4, \"y\": 4.4, \"z\": 0.4}, {\"x\": 5, \"y\": 5.5, \"z\": 0.5}],\n", - " ]\n", - ").theta" - ] - }, - { - "cell_type": "code", - "execution_count": 67, - "id": "latin-channels", - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "MomentumNumpy3D([[[( 0.13260391, 0.2601781 , 1.04694552),\n", - " (-0.26319529, -0.77320792, -0.99130649)],\n", - " [( 0.01667648, 0.29866905, 0.18466902),\n", - " ( 1.34383037, -0.10881989, -0.49760439)],\n", - " [( 2.03530493, 0.11366079, -0.82173533),\n", - " (-0.31129007, -1.84168638, -0.16826771)],\n", - " [( 1.58952081, 0.67672986, 0.39419798),\n", - " (-0.34309328, 1.22834158, -0.45125405)],\n", - " [(-0.39677479, 0.89203262, 0.62427518),\n", - " (-0.51305815, -1.06523853, 0.51476415)]],\n", - "\n", - " [[( 0.62534261, 2.19809954, -1.74075339),\n", - " (-0.5823244 , -0.29312602, -0.43676964)],\n", - " [(-3.15626856, 0.11091443, 1.59055725),\n", - " (-1.51497505, 0.73573103, 0.11611239)],\n", - " [(-1.10585758, -1.3744337 , -0.45652228),\n", - " ( 0.74772884, 0.33616902, 0.16559539)],\n", - " [( 1.68097067, -1.74999875, -0.09875288),\n", - " (-1.4415149 , 0.19554285, -0.41443723)],\n", - " [(-0.88453411, -0.43962161, -1.144978 ),\n", - " (-0.70646718, 1.0279956 , 0.15112694)]],\n", - "\n", - " [[(-0.167228 , -1.14624761, 0.37325173),\n", - " ( 0.03890062, -0.25074582, 0.75658396)],\n", - " [( 1.24646773, 0.84040834, 0.70366236),\n", - " (-0.93898028, -1.63633977, -0.82303599)],\n", - " [( 0.59744465, -0.56592375, 1.73794445),\n", - " ( 0.09641971, -0.58255055, 1.62074543)],\n", - " [(-0.28663052, 0.3644517 , 1.246621 ),\n", - " (-0.04809795, -0.50406828, 1.47166047)],\n", - " [(-0.34240645, 0.47174417, 0.87089676),\n", - " ( 1.66574864, 0.18921741, 0.39070562)]],\n", - "\n", - " [[( 0.00878644, -1.62536013, -0.42163486),\n", - " ( 0.46505462, 0.02231124, 1.01025727)],\n", - " [( 0.40799765, 1.03055286, -1.67387635),\n", - " (-0.6960781 , 1.34294937, -0.05646045)],\n", - " [( 0.7966022 , 0.8646252 , -0.37478019),\n", - " (-1.59930401, 0.34685381, -0.89294171)],\n", - " [( 0.59402505, 0.98172123, 0.78361029),\n", - " ( 0.8967682 , 0.75803473, -1.61971293)],\n", - " [(-0.00343387, 0.91582888, 1.00745774),\n", - " ( 0.38013935, 0.37748105, 0.61506312)]],\n", - "\n", - " [[( 0.86241151, -0.79418385, -1.46392439),\n", - " ( 0.12601623, -1.75780638, -0.53983752)],\n", - " [(-0.82900978, -1.19255499, -1.09695779),\n", - " ( 0.31537637, -0.78298955, 0.13288536)],\n", - " [( 1.51532109, -1.17606172, -1.21292931),\n", - " (-0.23002288, -0.20392714, -0.13550909)],\n", - " [(-1.41126192, 1.00526992, 1.16169235),\n", - " (-3.41913823, 0.75890305, -2.06607514)],\n", - " [(-1.09784888, 0.53826587, -1.09363904),\n", - " ( 0.47498744, 0.27155865, 0.87275119)]]],\n", - " dtype=[('x', '[[{x: 0.0952, y: 2.35, z: -0.225}, {x: 1.12, y: -0.0102, z: 0.648}],\n", - " [{x: 0.626, y: -0.231, z: -1.15}, {...}, {x: 0.232, y: 0.773, z: 0.321}],\n", - " [{x: 0.153, y: 0.854, z: 1.62}, {...}, ..., {x: -1.03, y: -0.0817, z: 1.32}],\n", - " [{x: -0.0757, y: -0.717, z: 0.0196}],\n", - " [{x: -0.0664, y: -0.5, z: -0.732}, ..., {x: -0.682, y: 0.555, z: -1.15}],\n", - " [{x: 0.231, y: -0.166, z: -0.19}],\n", - " [{x: -0.26, y: 0.0152, z: -0.469}, {x: -0.807, y: 1.39, z: 0.51}],\n", - " [{x: -0.982, y: 2.04, z: -0.788}],\n", - " [{x: -0.601, y: -1.39, z: -0.962}],\n", - " [{x: 0.365, y: -0.684, z: 0.384}],\n", - " ...,\n", - " [{x: 1.09, y: -0.864, z: 0.556}, {x: 0.166, y: -0.0708, z: 0.728}],\n", - " [{x: 1.47, y: 1.26, z: -2.5}, {x: 1.17, y: 0.418, z: 0.31}],\n", - " [],\n", - " [{x: 0.681, y: 0.755, z: 0.631}],\n", - " [{x: -0.795, y: -0.883, z: -0.861}, {x: 0.418, y: 1.04, z: 0.172}],\n", - " [{x: -0.176, y: 0.133, z: -0.34}],\n", - " [{x: -0.307, y: 0.661, z: 0.976}, {x: 0.911, y: -1.2, z: 1.2}],\n", - " [{x: 1.76, y: 0.317, z: -0.544}, {x: -0.691, y: -0.761, z: -0.992}],\n", - " [{x: -0.71, y: 0.624, z: -0.0189}, {...}, ..., {x: -1.11, y: 0.629, z: 1.26}]]\n", - "-------------------------------------------------------------------------------\n", - "type: 50 * var * Momentum3D[\n", - " x: float64,\n", - " y: float64,\n", - " z: float64\n", - "]" - ], - "text/plain": [ - "" - ] - }, - "execution_count": 71, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "# Make a large, random Awkward Array of 3D momentum vectors.\n", - "array = vector.Array(\n", - " [\n", - " [\n", - " {x: np.random.normal(0, 1) for x in (\"px\", \"py\", \"pz\")}\n", - " for inner in range(np.random.poisson(1.5))\n", - " ]\n", - " for outer in range(50)\n", - " ]\n", - ")\n", - "array" - ] - }, - { - "cell_type": "code", - "execution_count": 72, - "id": "conditional-modeling", - "metadata": {}, - "outputs": [ - { - "data": { - "text/html": [ - "
[[2.35, 1.12],\n",
-       " [0.668, 0.985, 0.807],\n",
-       " [0.868, 0.321, 0.209, 1.04],\n",
-       " [0.721],\n",
-       " [0.505, 0.661, 0.426, 0.879],\n",
-       " [0.285],\n",
-       " [0.26, 1.61],\n",
-       " [2.26],\n",
-       " [1.52],\n",
-       " [0.775],\n",
-       " ...,\n",
-       " [1.39, 0.181],\n",
-       " [1.94, 1.24],\n",
-       " [],\n",
-       " [1.02],\n",
-       " [1.19, 1.12],\n",
-       " [0.22],\n",
-       " [0.729, 1.51],\n",
-       " [1.78, 1.03],\n",
-       " [0.945, 0.514, 2.46, 1.27]]\n",
-       "------------------------------\n",
-       "type: 50 * var * float64
" - ], - "text/plain": [ - "" - ] - }, - "execution_count": 72, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "# Get the transverse momentum of each one, in the same nested structure.\n", - "array.pt" - ] - }, - { - "cell_type": "code", - "execution_count": 73, - "id": "general-october", - "metadata": {}, - "outputs": [ - { - "data": { - "text/html": [ - "
[2,\n",
-       " 3,\n",
-       " 4,\n",
-       " 1,\n",
-       " 4,\n",
-       " 1,\n",
-       " 2,\n",
-       " 1,\n",
-       " 1,\n",
-       " 1,\n",
-       " ...,\n",
-       " 2,\n",
-       " 2,\n",
-       " 0,\n",
-       " 1,\n",
-       " 2,\n",
-       " 1,\n",
-       " 2,\n",
-       " 2,\n",
-       " 4]\n",
-       "----------------\n",
-       "type: 50 * int64
" - ], - "text/plain": [ - "" - ] - }, - "execution_count": 73, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "# The array and its components have the same list lengths (and can therefore be used together in subsequent calculations).\n", - "ak.num(array)" - ] - }, - { - "cell_type": "code", - "execution_count": 74, - "id": "ongoing-rally", - "metadata": {}, - "outputs": [ - { - "data": { - "text/html": [ - "
[2,\n",
-       " 3,\n",
-       " 4,\n",
-       " 1,\n",
-       " 4,\n",
-       " 1,\n",
-       " 2,\n",
-       " 1,\n",
-       " 1,\n",
-       " 1,\n",
-       " ...,\n",
-       " 2,\n",
-       " 2,\n",
-       " 0,\n",
-       " 1,\n",
-       " 2,\n",
-       " 1,\n",
-       " 2,\n",
-       " 2,\n",
-       " 4]\n",
-       "----------------\n",
-       "type: 50 * int64
" - ], - "text/plain": [ - "" - ] - }, - "execution_count": 74, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "ak.num(array.pt)" - ] - }, - { - "cell_type": "markdown", - "id": "brown-blood", - "metadata": {}, - "source": [ - "## Vector methods\n", - "\n", - "Vector methods require arguments (in parentheses), which may be scalars or other vectors, depending on the calculation." - ] - }, - { - "cell_type": "code", - "execution_count": 75, - "id": "unique-trance", - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "VectorObject2D(x=2.585678829246765, y=4.279516911052588)" - ] - }, - "execution_count": 75, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "vector.obj(x=3, y=4).rotateZ(0.1)" - ] - }, - { - "cell_type": "code", - "execution_count": 76, - "id": "pharmaceutical-notebook", - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "VectorObject2D(rho=5, phi=0.5)" - ] - }, - "execution_count": 76, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "vector.obj(rho=5, phi=0.4).rotateZ(0.1)" - ] - }, - { - "cell_type": "code", - "execution_count": 77, - "id": "approved-ancient", - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "[(1., 0.6) (2., 0.7) (3., 0.8) (4., 0.9) (5., 1. )]\n" - ] - } - ], - "source": [ - "# Broadcasts a scalar rotation angle of 0.5 to all elements of the NumPy array.\n", - "print(\n", - " vector.array({\"rho\": [1, 2, 3, 4, 5], \"phi\": [0.1, 0.2, 0.3, 0.4, 0.5]}).rotateZ(\n", - " 0.5\n", - " )\n", - ")" - ] - }, - { - "cell_type": "code", - "execution_count": 78, - "id": "derived-lincoln", - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "[(1., 0.2) (2., 0.4) (3., 0.6) (4., 0.8) (5., 1. )]\n" - ] - } - ], - "source": [ - "# Matches each rotation angle to an element of the NumPy array.\n", - "print(\n", - " vector.array({\"rho\": [1, 2, 3, 4, 5], \"phi\": [0.1, 0.2, 0.3, 0.4, 0.5]}).rotateZ(\n", - " np.array([0.1, 0.2, 0.3, 0.4, 0.5])\n", - " )\n", - ")" - ] - }, - { - "cell_type": "code", - "execution_count": 79, - "id": "dangerous-effect", - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "[[{rho: 1, phi: 0.6}, {rho: 2, phi: 0.7}], [], [{rho: 3, phi: 0.8}]]\n" - ] - } - ], - "source": [ - "# Broadcasts a scalar rotation angle of 0.5 to all elements of the Awkward Array.\n", - "print(\n", - " vector.Array(\n", - " [[{\"rho\": 1, \"phi\": 0.1}, {\"rho\": 2, \"phi\": 0.2}], [], [{\"rho\": 3, \"phi\": 0.3}]]\n", - " ).rotateZ(0.5)\n", - ")" - ] - }, - { - "cell_type": "code", - "execution_count": 80, - "id": "weird-insert", - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "[[{rho: 1, phi: 0.2}, {rho: 2, phi: 0.3}], [], [{rho: 3, phi: 0.6}]]\n" - ] - } - ], - "source": [ - "# Broadcasts a rotation angle of 0.1 to both elements of the first list, 0.2 to the empty list, and 0.3 to the only element of the last list.\n", - "print(\n", - " vector.Array(\n", - " [[{\"rho\": 1, \"phi\": 0.1}, {\"rho\": 2, \"phi\": 0.2}], [], [{\"rho\": 3, \"phi\": 0.3}]]\n", - " ).rotateZ([0.1, 0.2, 0.3])\n", - ")" - ] - }, - { - "cell_type": "code", - "execution_count": 81, - "id": "satellite-southeast", - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "[[{rho: 1, phi: 0.2}, {rho: 2, phi: 0.4}], [], [{rho: 3, phi: 0.6}]]\n" - ] - } - ], - "source": [ - "# Matches each rotation angle to an element of the Awkward Array.\n", - "print(\n", - " vector.Array(\n", - " [[{\"rho\": 1, \"phi\": 0.1}, {\"rho\": 2, \"phi\": 0.2}], [], [{\"rho\": 3, \"phi\": 0.3}]]\n", - " ).rotateZ([[0.1, 0.2], [], [0.3]])\n", - ")" - ] - }, - { - "cell_type": "markdown", - "id": "animal-specific", - "metadata": {}, - "source": [ - "Some methods are equivalent to binary operators." - ] - }, - { - "cell_type": "code", - "execution_count": 82, - "id": "statutory-bathroom", - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "VectorObject2D(x=30, y=40)" - ] - }, - "execution_count": 82, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "vector.obj(x=3, y=4).scale(10)" - ] - }, - { - "cell_type": "code", - "execution_count": 83, - "id": "foreign-celebration", - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "VectorObject2D(x=30, y=40)" - ] - }, - "execution_count": 83, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "vector.obj(x=3, y=4) * 10" - ] - }, - { - "cell_type": "code", - "execution_count": 84, - "id": "solved-resident", - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "VectorObject2D(x=30, y=40)" - ] - }, - "execution_count": 84, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "10 * vector.obj(x=3, y=4)" - ] - }, - { - "cell_type": "code", - "execution_count": 85, - "id": "comic-threshold", - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "VectorObject2D(rho=50, phi=0.5)" - ] - }, - "execution_count": 85, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "vector.obj(rho=5, phi=0.5) * 10" - ] - }, - { - "cell_type": "markdown", - "id": "novel-fancy", - "metadata": {}, - "source": [ - "Some methods involve more than one vector." - ] - }, - { - "cell_type": "code", - "execution_count": 86, - "id": "prescription-arkansas", - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "VectorObject2D(x=6, y=7)" - ] - }, - "execution_count": 86, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "vector.obj(x=1, y=2).add(vector.obj(x=5, y=5))" - ] - }, - { - "cell_type": "code", - "execution_count": 87, - "id": "sought-allah", - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "VectorObject2D(x=6, y=7)" - ] - }, - "execution_count": 87, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "vector.obj(x=1, y=2) + vector.obj(x=5, y=5)" - ] - }, - { - "cell_type": "code", - "execution_count": 88, - "id": "egyptian-nursing", - "metadata": {}, - "outputs": [ - { - "data": { - "image/png": "iVBORw0KGgoAAAANSUhEUgAAABMAAAAPCAYAAAAGRPQsAAAACXBIWXMAAA7EAAAOxAGVKw4bAAABIUlEQVQ4Ea2T0W3CMBRFTcUAEd3AbAAdgY7QFToCfCZ/SGwA3QC6QdsRyAgdAXWD9BxDEIQgJVWvdOPnm+fr5D07VFUVujLP80kzFy2DUX0YLlAUxYTpDk6Jfy5e1eEXesakPAnGYupjeHr5RnyATzDCezBHuOk3fIfLemPN/IIXGIjnDCbeQ0lOym1LeGgT/6r9q9lVA7p8Eb/5Sp6Ff4TW15qlhvT9Mk22LF7BBbHcE88YQy8zFj1DG5ZAbEc/4Vqhl5kLWqBhxDh2NiP5A+5bzGop62zGCg+0NWtipMBGZR+zDQvGTSfmFt+63dTMdou02zE8P9eYpULXCnNvjEi3YuBtR/RyC3fxVzw3FtY6bRgTiCOBx0G4oXd1gZ46/AvpNYSy4bXeMQAAAABJRU5ErkJggg==", - "text/latex": [ - "$\\displaystyle 15$" - ], - "text/plain": [ - "15" - ] - }, - "execution_count": 88, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "vector.obj(x=1, y=2).dot(vector.obj(x=5, y=5))" - ] - }, - { - "cell_type": "code", - "execution_count": 89, - "id": "hourly-section", - "metadata": {}, - "outputs": [ - { - "data": { - "image/png": "iVBORw0KGgoAAAANSUhEUgAAABMAAAAPCAYAAAAGRPQsAAAACXBIWXMAAA7EAAAOxAGVKw4bAAABIUlEQVQ4Ea2T0W3CMBRFTcUAEd3AbAAdgY7QFToCfCZ/SGwA3QC6QdsRyAgdAXWD9BxDEIQgJVWvdOPnm+fr5D07VFUVujLP80kzFy2DUX0YLlAUxYTpDk6Jfy5e1eEXesakPAnGYupjeHr5RnyATzDCezBHuOk3fIfLemPN/IIXGIjnDCbeQ0lOym1LeGgT/6r9q9lVA7p8Eb/5Sp6Ff4TW15qlhvT9Mk22LF7BBbHcE88YQy8zFj1DG5ZAbEc/4Vqhl5kLWqBhxDh2NiP5A+5bzGop62zGCg+0NWtipMBGZR+zDQvGTSfmFt+63dTMdou02zE8P9eYpULXCnNvjEi3YuBtR/RyC3fxVzw3FtY6bRgTiCOBx0G4oXd1gZ46/AvpNYSy4bXeMQAAAABJRU5ErkJggg==", - "text/latex": [ - "$\\displaystyle 15$" - ], - "text/plain": [ - "15" - ] - }, - "execution_count": 89, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "vector.obj(x=1, y=2) @ vector.obj(x=5, y=5)" - ] - }, - { - "cell_type": "markdown", - "id": "earned-precipitation", - "metadata": {}, - "source": [ - "The vectors can use different coordinate systems. Conversions are necessary, but minimized for speed and numeric stability." - ] - }, - { - "cell_type": "code", - "execution_count": 90, - "id": "unlike-melissa", - "metadata": {}, - "outputs": [ - { - "data": { - "image/png": "iVBORw0KGgoAAAANSUhEUgAAABMAAAAPCAYAAAAGRPQsAAAACXBIWXMAAA7EAAAOxAGVKw4bAAABa0lEQVQ4EZWT0VHCUBBFI2MBGegAOwDtADtQO5AS5BP+HOgAShA7ACtgoAPpAIYO8JwkizHAZNyZm913s7u5b/Necjwek+Fw2NGXAZeCdpmri2+T3L5Go1FKuCnWxlo3d79P8sbFaoe/A2O4rVzDB7YHB9ABNvoEXZLkTsZ6zWKFH4AJ8QAsiNtZktLZzrxuC+T0wXc1D24MFvKhLGtc83jmfYyhnLpi0UNd+p9mPYocR9WyeUH24gckdO5DOK8WcAbvcJkSvHydNUOZyR8UTYBDFWti1WjN3GU/qQjPXL5Nih7B6c8RK30Jpmcl14lWKLuUYsM2jd3ypVlFTajeNUj2nHh+rlnK+1B9aXbBbVV2D4IoN8y+SKM4Dm5blVULZUubzSjwWlTN4dsgbE7gh6vmlduo3mZTgj+DZv1WVHhQM4ObEezxTwWVELujF/Aqd+M1gFS+x0FTtgP3/h0kwopiL7q8F/0BnM7jD7/71BequctZAAAAAElFTkSuQmCC", - "text/latex": [ - "$\\displaystyle 50$" - ], - "text/plain": [ - "50" - ] - }, - "execution_count": 90, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "vector.obj(x=3, y=4) @ vector.obj(x=6, y=8) # both are Cartesian, dot product is exact" - ] - }, - { - "cell_type": "code", - "execution_count": 91, - "id": "seasonal-section", - "metadata": {}, - "outputs": [ - { - "data": { - "image/png": "iVBORw0KGgoAAAANSUhEUgAAAKAAAAAOCAYAAACo2RezAAAACXBIWXMAAA7EAAAOxAGVKw4bAAAE3ElEQVRoBd2a3XEUORSFB8oBgDcCIIO1iWBNBlAbAZABlN/8ChnARuDCGWAi4CcDyGDNZOD9Pk1Lpe7WjG9XqV/2VsmSro6O1Oj0ldTDvdvb203LLi4u/sT/mvz1tB3fh8p3TPklvm3lO1iM9u+Nc1K9OaN8a4y9hFNsNubcXFv8j8G8HXCn5DfW8f8YfCXD94DKeXFsNtY/4b+ufBvqcmYNibH+LuPuHRDgT4A/AL4gT0ZZgu+kD5Tf6yT3Yb6QTij/0rfPaA/1741zPr05o3xrjL2EU+zUmHtrbRWG6/os4ym/o/yG9IzyVFhis7BSF+qfKFySX+kgd70VW8FRfo5P3AvKV/cpzIwGB23ZPziPaU/iE0DZt+MbqY6KNrUs2r83zrn05ozyrTH2Ek6xxQ6srWIrQrEDWKPhlqRgiuF/RcVANLWXOOqoKO4VeEWXLQs54WYCBGxEc1DT1CRqRTlFeEZfFX/Iov1745xTb84o3xpjL+EUm+yOtT0D9LOxhgrmAX4jZLYnFEqkzM5Gri5GWoJnpKuZAOnwN6CPU7JqYjfTNur/Dr7TRltyRfv3xjl4b84o3xpjL+EUO7Hm2g4YhfaLZxsJpOpfB5ev+J+D/Vz9Wwg1ipadkLZr0kNzGzXKvrhawo0ESKNbbyFIsOEPbXliXjqm9sfgqN+SESbavzfOSfTmjPKtMfYSTrHZmPPetRVDu2cyI9vU3BFtN5olo+wZz2TU/E39DUndKMhZ8MKfjDbxaavPuCJAHIpnS97aYncMu0FbIkuTBFS/JblPnTvpSP/eOOfQmzPKt8bYSzg3wbWVc2T0c11dr3wzLu20eTnNYlNUiquItAApyEPyBfCMKeYbKdn9XCD3k0smrNyjoodMCR0sGWUnmaPjIfGKj/bvjfu/jb3kecRG1lbc1Lx8XLHG5dKZAfjcSl13o6ZbrEL1DJm3WKo7w+fXlPckRXtJ+p5x6TMMFW8r7tdFQJS95XgmKJ9hqG+oG+VUvFd5t17PAw6uz08xzbeAtmTR/r1xDt6bM8q3xthRTuYYXls5s9HPLfUx+eyyMXC61uXWTFnhKVhF+Yh6DkpUx0bbbzzq6OERFcXjLaeIbwwf1wbiMrCt+BSfdidHtH9vnJPrzRnlW2PsCCfzW7S2cmr0U7R+bpuJLwF2webRUE4ZWCOl0dDA5A5pfXZ+TODdFizm7Ig/TvIpYNVbW9r/B7+RcHYOqMBijaB7VV9hW8Vo/94459KbM8q3xtgjTtbjFMeitaWPkewJedn5KKuRDbk6MHIZsGZrPbR7Nj4Wj6Vvhfi9Cc/wAo5ocP8u12SdGn7DpKKqJ+Lk/ABbQiztTkg1n5AOGthQ/944J9WbM8q3xthRTuYYXtuB05dHwU6DjeuW7ge0eVE1uT23djz1kPWk6FqB6RS/dm0E3GcSmWrzTbipHZSNnB5yy9mPsv0UsIfPWpih/vTrjYOyO2d0jmuMvYRT7NRma8s6+TyupYKZfoo7w1dfRAxK/u77F2mbySm7dfspJgtzKuQNbYrZ8dXMdvZbMM50+ARgVNMMqV/x599+83lPEm32A7RO8J4FfJh958W7+kfHCeGGOYWwzLkrbo2xl3CK1XiuvWtLm+ulCFs2DSRyGS3PSXVAmmkBnDoquyhlxyj/GeE/jw1TQEn/J88AAAAASUVORK5CYII=", - "text/latex": [ - "$\\displaystyle 49.9999999994283$" - ], - "text/plain": [ - "49.99999999942831" - ] - }, - "execution_count": 91, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "vector.obj(rho=5, phi=0.9273) @ vector.obj(\n", - " x=6, y=8\n", - ") # one is polar, dot product is approximate" - ] - }, - { - "cell_type": "code", - "execution_count": 92, - "id": "second-joseph", - "metadata": {}, - "outputs": [ - { - "data": { - "image/png": "iVBORw0KGgoAAAANSUhEUgAAAKAAAAAOCAYAAACo2RezAAAACXBIWXMAAA7EAAAOxAGVKw4bAAAE3ElEQVRoBd2a3XEUORSFB8oBgDcCIIO1iWBNBlAbAZABlN/8ChnARuDCGWAi4CcDyGDNZOD9Pk1Lpe7WjG9XqV/2VsmSro6O1Oj0ldTDvdvb203LLi4u/sT/mvz1tB3fh8p3TPklvm3lO1iM9u+Nc1K9OaN8a4y9hFNsNubcXFv8j8G8HXCn5DfW8f8YfCXD94DKeXFsNtY/4b+ufBvqcmYNibH+LuPuHRDgT4A/AL4gT0ZZgu+kD5Tf6yT3Yb6QTij/0rfPaA/1741zPr05o3xrjL2EU+zUmHtrbRWG6/os4ym/o/yG9IzyVFhis7BSF+qfKFySX+kgd70VW8FRfo5P3AvKV/cpzIwGB23ZPziPaU/iE0DZt+MbqY6KNrUs2r83zrn05ozyrTH2Ek6xxQ6srWIrQrEDWKPhlqRgiuF/RcVANLWXOOqoKO4VeEWXLQs54WYCBGxEc1DT1CRqRTlFeEZfFX/Iov1745xTb84o3xpjL+EUm+yOtT0D9LOxhgrmAX4jZLYnFEqkzM5Gri5GWoJnpKuZAOnwN6CPU7JqYjfTNur/Dr7TRltyRfv3xjl4b84o3xpjL+EUO7Hm2g4YhfaLZxsJpOpfB5ev+J+D/Vz9Wwg1ipadkLZr0kNzGzXKvrhawo0ESKNbbyFIsOEPbXliXjqm9sfgqN+SESbavzfOSfTmjPKtMfYSTrHZmPPetRVDu2cyI9vU3BFtN5olo+wZz2TU/E39DUndKMhZ8MKfjDbxaavPuCJAHIpnS97aYncMu0FbIkuTBFS/JblPnTvpSP/eOOfQmzPKt8bYSzg3wbWVc2T0c11dr3wzLu20eTnNYlNUiquItAApyEPyBfCMKeYbKdn9XCD3k0smrNyjoodMCR0sGWUnmaPjIfGKj/bvjfu/jb3kecRG1lbc1Lx8XLHG5dKZAfjcSl13o6ZbrEL1DJm3WKo7w+fXlPckRXtJ+p5x6TMMFW8r7tdFQJS95XgmKJ9hqG+oG+VUvFd5t17PAw6uz08xzbeAtmTR/r1xDt6bM8q3xthRTuYYXls5s9HPLfUx+eyyMXC61uXWTFnhKVhF+Yh6DkpUx0bbbzzq6OERFcXjLaeIbwwf1wbiMrCt+BSfdidHtH9vnJPrzRnlW2PsCCfzW7S2cmr0U7R+bpuJLwF2webRUE4ZWCOl0dDA5A5pfXZ+TODdFizm7Ig/TvIpYNVbW9r/B7+RcHYOqMBijaB7VV9hW8Vo/94459KbM8q3xtgjTtbjFMeitaWPkewJedn5KKuRDbk6MHIZsGZrPbR7Nj4Wj6Vvhfi9Cc/wAo5ocP8u12SdGn7DpKKqJ+Lk/ABbQiztTkg1n5AOGthQ/944J9WbM8q3xthRTuYYXtuB05dHwU6DjeuW7ge0eVE1uT23djz1kPWk6FqB6RS/dm0E3GcSmWrzTbipHZSNnB5yy9mPsv0UsIfPWpih/vTrjYOyO2d0jmuMvYRT7NRma8s6+TyupYKZfoo7w1dfRAxK/u77F2mbySm7dfspJgtzKuQNbYrZ8dXMdvZbMM50+ARgVNMMqV/x599+83lPEm32A7RO8J4FfJh958W7+kfHCeGGOYWwzLkrbo2xl3CK1XiuvWtLm+ulCFs2DSRyGS3PSXVAmmkBnDoquyhlxyj/GeE/jw1TQEn/J88AAAAASUVORK5CYII=", - "text/latex": [ - "$\\displaystyle 49.9999999994283$" - ], - "text/plain": [ - "49.99999999942831" - ] - }, - "execution_count": 92, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "vector.obj(x=3, y=4) @ vector.obj(\n", - " rho=10, phi=0.9273\n", - ") # one is polar, dot product is approximate" - ] - }, - { - "cell_type": "code", - "execution_count": 93, - "id": "material-technician", - "metadata": {}, - "outputs": [ - { - "data": { - "image/png": "iVBORw0KGgoAAAANSUhEUgAAACMAAAAPCAYAAABut3YUAAAACXBIWXMAAA7EAAAOxAGVKw4bAAAByElEQVRIDbWV7VHCQBCGI2MBjHSAHYB2gB2oHYgdyE/yzwkdQAliB2AFDHSAHcjQQXzekA3HGe7iOO7My+3u3X7c7nJJ8jxPxuNxT6sLdG3QdXX/zV8mB/pI07QNuyll8aL+YTn+ci4rpS/Wa5Ch+zyeCHMh+1ZpumPdgx5QIu+gj6F0FSGvEVasIzCBH4EFfLc6FGCi9io97ZjHWsCZIdj659BlYOHrfbmJvVUmcJ9q6wHO2lgpYVZgwK2tte6ey0ftf5PMAM9qp082L9oPUdTeBjjhZkM86XYdoBl4RVdUosGtOZ5c6aeOmtpbZZTEG0YToKEU1vB2Wwt0MtBe4FCbGtkXyRD0DlSB4FX6JZh6AUOiKvoX6lhl6pwooS6JqWV1s2I2dmu9O+eokX2LYHon9H6cozb7VrW6VpjOBvmHn6b2qswNMIeuo+LGOCqGmA21TVXyySqj/RBF7ZXMjIB61n3S8LoB5shK3Cd9MjbO7f19k6P2SmaKo5NBRX4pPeihKgjdDGbHel+qEnhV9BE8uTr0OThpPXLU/kLPNgdVfv2dRSq7Bk7fn70URsgKrg+l9BrYW1C9R/AFcW4Ls2R9LlWmD9p/AykpbfH0zMymAAAAAElFTkSuQmCC", - "text/latex": [ - "$\\displaystyle 50.0$" - ], - "text/plain": [ - "50.0" - ] - }, - "execution_count": 93, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "vector.obj(rho=5, phi=0.9273) @ vector.obj(\n", - " rho=10, phi=0.9273\n", - ") # both are polar, a formula that depends on phi differences is used" - ] - }, - { - "cell_type": "markdown", - "id": "attractive-ebony", - "metadata": {}, - "source": [ - "In Python, some \"operators\" are actually built-in functions, such as `abs`." - ] - }, - { - "cell_type": "code", - "execution_count": 94, - "id": "focal-tactics", - "metadata": {}, - "outputs": [ - { - "data": { - "image/png": "iVBORw0KGgoAAAANSUhEUgAAABkAAAAPCAYAAAARZmTlAAAACXBIWXMAAA7EAAAOxAGVKw4bAAABjElEQVQ4Ea2U723CQAzFU9QBItgg3QDaDdIN2m5QukH5mHyrwgYwQmED0gkQbAAbgNgg/b3kjEKUP1VUSy/ne2efz/blvCzLvCiKxhrLgPNBUOb66vdeIT9xHPuoezeXLpkUQ/cX/8RZnRgfQAJ3FDfQBzmDCxgDBViDCUbiOgW7HUZbxhmYo8/ABj3InVUCyrLqWwp8p+BQ9YdLwEa8ZZIH7Pl5xc/KXN5iyyQkG/8/goRspnJXJe8HZGiN94g4hVA/RkC1/IKrOyFLhbAu+y4ZWiYy/sZpDtQ0YYeuU7bJ0C22XZCiXGz2DK6G6Eo1BYu2CH9cG1kmdfYKFBBQpWuSul6YrWV5GrCJ7rPueZM01h0/y77OxrijMnkERpQD5Sdho9bm46Cy1mVrmaQKsmQjPQNVUdO1QZesMNBBq6Inaa9sFWSBctNg5p/OQz9aLnA+yMBNaZkvMTgzvjhTD12VeQPv4u7020MqXV1bidJUQ/UOXUSYMD+gp4wfxmlkrk31QMpeD+QTuP5nv4JEA14+QuryAAAAAElFTkSuQmCC", - "text/latex": [ - "$\\displaystyle 5.0$" - ], - "text/plain": [ - "5.0" - ] - }, - "execution_count": 94, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "abs(vector.obj(x=3, y=4))" - ] - }, - { - "cell_type": "markdown", - "id": "stone-resource", - "metadata": {}, - "source": [ - "Note that `abs` returns\n", - "\n", - " * `rho` for 2D vectors\n", - " * `mag` for 3D vectors\n", - " * `tau` (`mass`) for 4D vectors\n", - "\n", - "Use the named properties when you want magnitude in a specific number of dimensions; use `abs` when you want the magnitude for any number of dimensions." - ] - }, - { - "cell_type": "markdown", - "id": "shared-resolution", - "metadata": {}, - "source": [ - "The vectors can be from different backends. Normal rules for broadcasting Python numbers, NumPy arrays, and Awkward Arrays apply." - ] - }, - { - "cell_type": "code", - "execution_count": 95, - "id": "purple-disco", - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "VectorNumpy2D([(11., 5.1), (12., 5.2), (13., 5.3), (14., 5.4), (15., 5.5)],\n", - " dtype=[('x', '[[{x: 11, y: 6.1}, {x: 12, y: 7.2}],\n", - " [],\n", - " [{x: 13, y: 8.3}],\n", - " [{x: 14, y: 9.4}, {x: 15, y: 10.5}]]\n", - "-------------------------------------\n", - "type: 4 * var * Vector2D[\n", - " x: int64,\n", - " y: float64\n", - "]" - ], - "text/plain": [ - "" - ] - }, - "execution_count": 96, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "(\n", - " vector.Array(\n", - " [ # an Awkward Array of vectors\n", - " [{\"x\": 1, \"y\": 1.1}, {\"x\": 2, \"y\": 2.2}],\n", - " [],\n", - " [{\"x\": 3, \"y\": 3.3}],\n", - " [{\"x\": 4, \"y\": 4.4}, {\"x\": 5, \"y\": 5.5}],\n", - " ]\n", - " )\n", - " + vector.obj(x=10, y=5) # and a single vector object\n", - ")" - ] - }, - { - "cell_type": "code", - "execution_count": 97, - "id": "empirical-starter", - "metadata": {}, - "outputs": [ - { - "data": { - "text/html": [ - "
[[{x: 5, y: 1.2}, {x: 6, y: 2.3}],\n",
-       " [],\n",
-       " [{x: 5, y: 3.4}],\n",
-       " [{x: 5, y: 4.5}, {x: 6, y: 5.6}]]\n",
-       "----------------------------------\n",
-       "type: 4 * var * Vector2D[\n",
-       "    x: float64,\n",
-       "    y: float64\n",
-       "]
" - ], - "text/plain": [ - "" - ] - }, - "execution_count": 97, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "(\n", - " vector.Array(\n", - " [ # an Awkward Array of vectors\n", - " [{\"x\": 1, \"y\": 1.1}, {\"x\": 2, \"y\": 2.2}],\n", - " [],\n", - " [{\"x\": 3, \"y\": 3.3}],\n", - " [{\"x\": 4, \"y\": 4.4}, {\"x\": 5, \"y\": 5.5}],\n", - " ]\n", - " )\n", - " + vector.array(\n", - " {\"x\": [4, 3, 2, 1], \"y\": [0.1, 0.1, 0.1, 0.1]}\n", - " ) # and a NumPy array of vectors\n", - ")" - ] - }, - { - "cell_type": "markdown", - "id": "pregnant-chest", - "metadata": {}, - "source": [ - "Some operations are defined for 2D or 3D vectors, but are usable on higher-dimensional vectors because the additional components can be ignored or are passed through unaffected." - ] - }, - { - "cell_type": "code", - "execution_count": 98, - "id": "blocked-keyboard", - "metadata": {}, - "outputs": [ - { - "data": { - "image/png": "iVBORw0KGgoAAAANSUhEUgAAABoAAAAOCAYAAAAxDQxDAAAACXBIWXMAAA7EAAAOxAGVKw4bAAABkElEQVQ4EY2U7U0CQRCGgVAAwQ6ODlQqEDrQFrQD/cs/gx1Qg3QgHah0AFYg0gE+z+bmclzWO99kM7PvzM7szH70T6dTL7BYLJal/o2cMJZw+7C3SfwK7E+lzzXy4Bx+K9ePRBCfzJ+Raw3IEUJujt6aDLtJVsg5MgHdTT8yXL8ZyKLcI0bIlKTkjkjnK+cdMOhD3YdYVmeMV/mUCHnHSCVK1vCOPmOR1bVhhnGX8dvAW0ARiXS0p01Ey7S3wYB7AlpBDqNhZhc5x3GODI4YdiSHS0nsWyuKIH/tRt+u1ulzBoKbpGCkmxitO3PKTC4yXBflJViT8EVHE+XORpuIan1X/wbBvameWdXSAZNoWa49wcWl6ExGPJ/KGFm9KRcNy5XeGvvZRFSkvRMEv8VpgqwqQU9x44zsp99GE1cQW5yj6qa9muPj4U+R8Q2FzeSH+he0g/Bvqn9BX3A3cOkxI23lD8PkbiIB3V2/MXKV++An0ToXuNBPdIr08JVVEvQetiPD8/pwXoNJTOb5NJE2+QsqvZDE0rxQTwAAAABJRU5ErkJggg==", - "text/latex": [ - "$\\displaystyle 0.2$" - ], - "text/plain": [ - "0.20000000000000018" - ] - }, - "execution_count": 98, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "vector.obj(rho=1, phi=0.5).deltaphi(\n", - " vector.obj(rho=2, phi=0.3)\n", - ") # deltaphi is a planar operation (defined on the transverse plane)" - ] - }, - { - "cell_type": "code", - "execution_count": 99, - "id": "exposed-pendant", - "metadata": {}, - "outputs": [ - { - "data": { - "image/png": "iVBORw0KGgoAAAANSUhEUgAAABoAAAAOCAYAAAAxDQxDAAAACXBIWXMAAA7EAAAOxAGVKw4bAAABkElEQVQ4EY2U7U0CQRCGgVAAwQ6ODlQqEDrQFrQD/cs/gx1Qg3QgHah0AFYg0gE+z+bmclzWO99kM7PvzM7szH70T6dTL7BYLJal/o2cMJZw+7C3SfwK7E+lzzXy4Bx+K9ePRBCfzJ+Raw3IEUJujt6aDLtJVsg5MgHdTT8yXL8ZyKLcI0bIlKTkjkjnK+cdMOhD3YdYVmeMV/mUCHnHSCVK1vCOPmOR1bVhhnGX8dvAW0ARiXS0p01Ey7S3wYB7AlpBDqNhZhc5x3GODI4YdiSHS0nsWyuKIH/tRt+u1ulzBoKbpGCkmxitO3PKTC4yXBflJViT8EVHE+XORpuIan1X/wbBvameWdXSAZNoWa49wcWl6ExGPJ/KGFm9KRcNy5XeGvvZRFSkvRMEv8VpgqwqQU9x44zsp99GE1cQW5yj6qa9muPj4U+R8Q2FzeSH+he0g/Bvqn9BX3A3cOkxI23lD8PkbiIB3V2/MXKV++An0ToXuNBPdIr08JVVEvQetiPD8/pwXoNJTOb5NJE2+QsqvZDE0rxQTwAAAABJRU5ErkJggg==", - "text/latex": [ - "$\\displaystyle 0.2$" - ], - "text/plain": [ - "0.20000000000000018" - ] - }, - "execution_count": 99, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "vector.obj(rho=1, phi=0.5, z=10).deltaphi(\n", - " vector.obj(rho=2, phi=0.3, theta=1.4)\n", - ") # but we can use it on 3D vectors" - ] - }, - { - "cell_type": "code", - "execution_count": 100, - "id": "liked-depression", - "metadata": {}, - "outputs": [ - { - "data": { - "image/png": "iVBORw0KGgoAAAANSUhEUgAAABoAAAAOCAYAAAAxDQxDAAAACXBIWXMAAA7EAAAOxAGVKw4bAAABkElEQVQ4EY2U7U0CQRCGgVAAwQ6ODlQqEDrQFrQD/cs/gx1Qg3QgHah0AFYg0gE+z+bmclzWO99kM7PvzM7szH70T6dTL7BYLJal/o2cMJZw+7C3SfwK7E+lzzXy4Bx+K9ePRBCfzJ+Raw3IEUJujt6aDLtJVsg5MgHdTT8yXL8ZyKLcI0bIlKTkjkjnK+cdMOhD3YdYVmeMV/mUCHnHSCVK1vCOPmOR1bVhhnGX8dvAW0ARiXS0p01Ey7S3wYB7AlpBDqNhZhc5x3GODI4YdiSHS0nsWyuKIH/tRt+u1ulzBoKbpGCkmxitO3PKTC4yXBflJViT8EVHE+XORpuIan1X/wbBvameWdXSAZNoWa49wcWl6ExGPJ/KGFm9KRcNy5XeGvvZRFSkvRMEv8VpgqwqQU9x44zsp99GE1cQW5yj6qa9muPj4U+R8Q2FzeSH+he0g/Bvqn9BX3A3cOkxI23lD8PkbiIB3V2/MXKV++An0ToXuNBPdIr08JVVEvQetiPD8/pwXoNJTOb5NJE2+QsqvZDE0rxQTwAAAABJRU5ErkJggg==", - "text/latex": [ - "$\\displaystyle 0.2$" - ], - "text/plain": [ - "0.20000000000000018" - ] - }, - "execution_count": 100, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "vector.obj(rho=1, phi=0.5, z=10, t=100).deltaphi(\n", - " vector.obj(rho=2, phi=0.3, theta=1.4, tau=1000)\n", - ") # and 4D vectors" - ] - }, - { - "cell_type": "code", - "execution_count": 101, - "id": "several-senator", - "metadata": {}, - "outputs": [ - { - "data": { - "image/png": "iVBORw0KGgoAAAANSUhEUgAAABoAAAAOCAYAAAAxDQxDAAAACXBIWXMAAA7EAAAOxAGVKw4bAAABkElEQVQ4EY2U7U0CQRCGgVAAwQ6ODlQqEDrQFrQD/cs/gx1Qg3QgHah0AFYg0gE+z+bmclzWO99kM7PvzM7szH70T6dTL7BYLJal/o2cMJZw+7C3SfwK7E+lzzXy4Bx+K9ePRBCfzJ+Raw3IEUJujt6aDLtJVsg5MgHdTT8yXL8ZyKLcI0bIlKTkjkjnK+cdMOhD3YdYVmeMV/mUCHnHSCVK1vCOPmOR1bVhhnGX8dvAW0ARiXS0p01Ey7S3wYB7AlpBDqNhZhc5x3GODI4YdiSHS0nsWyuKIH/tRt+u1ulzBoKbpGCkmxitO3PKTC4yXBflJViT8EVHE+XORpuIan1X/wbBvameWdXSAZNoWa49wcWl6ExGPJ/KGFm9KRcNy5XeGvvZRFSkvRMEv8VpgqwqQU9x44zsp99GE1cQW5yj6qa9muPj4U+R8Q2FzeSH+he0g/Bvqn9BX3A3cOkxI23lD8PkbiIB3V2/MXKV++An0ToXuNBPdIr08JVVEvQetiPD8/pwXoNJTOb5NJE2+QsqvZDE0rxQTwAAAABJRU5ErkJggg==", - "text/latex": [ - "$\\displaystyle 0.2$" - ], - "text/plain": [ - "0.20000000000000018" - ] - }, - "execution_count": 101, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "vector.obj(rho=1, phi=0.5).deltaphi(\n", - " vector.obj(rho=2, phi=0.3, theta=1.4, tau=1000)\n", - ") # and mixed dimensionality" - ] - }, - { - "cell_type": "markdown", - "id": "breathing-helicopter", - "metadata": {}, - "source": [ - "This is especially useful for giving 4D vectors all the capabilities of 3D vectors." - ] - }, - { - "cell_type": "code", - "execution_count": 102, - "id": "considerable-general", - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "VectorObject3D(x=1, y=-0.7071067811865472, z=3.5355339059327378)" - ] - }, - "execution_count": 102, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "vector.obj(x=1, y=2, z=3).rotateX(np.pi / 4)" - ] - }, - { - "cell_type": "code", - "execution_count": 103, - "id": "formed-fisher", - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "VectorObject4D(x=1, y=-0.7071067811865472, z=3.5355339059327378, tau=10)" - ] - }, - "execution_count": 103, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "vector.obj(x=1, y=2, z=3, tau=10).rotateX(np.pi / 4)" - ] - }, - { - "cell_type": "code", - "execution_count": 104, - "id": "tribal-danger", - "metadata": {}, - "outputs": [ - { - "data": { - "image/png": "iVBORw0KGgoAAAANSUhEUgAAAJQAAAAPCAYAAAACneZUAAAACXBIWXMAAA7EAAAOxAGVKw4bAAAFbUlEQVRoBe2a35XVNhCHDWcLWEgH0AGwHWw6CKECoIPk5G3fONBBoAL+dJCkAgIdQAeB7WDzfbqWIsuyr2TvCS/MObqSR6PfjDSjkezdG1dXV8N36l+Bi4uLe5SP+UieT3m+Tf0553+rNnbcQfc55Q3ty//DjpNcCUrv8fyWcn+PASPOU+qnOX5s9+pZwoPvgv064j6g/uIz/Imjx/5QHdM9Yka7DRB1PIf/Z45D+y949kddtqX7h2r+i/zzgvsaXhw/0G6ezyh7zE79+bsF+UJ1eLyEf8tWI94EgzGzeDmB6UK8ougMneKk9pJBmRZKsJ16anja6UL9KL5EW4d9kEdJAUC7aY6jnAEZHTXQ/gnMP6gfUt6pZyTXS3JRzUj2PUPmknpC8LTVOYgd7KL22XKXMowyPfNpsfMMaPXVMqaZK2xGdLs+LXjaubqWBpQL8JCi8C9ULtBmGjFm47fqWcJDgcGTHK9CZF2UJzR1VNh5I791jo59AoYBFIMnBuZv9EWesB+RCevmwxHSHrNRxFJcx+SObp4P45rtRGfacCqV4IWkQR3n04O3upY3Dyqu5xcDDUYVWnbTETx32CdkdExOOu0Ufli0vKOhbVad2A/Orrkw3gznurzM9cM3i+bO7plPq53vc51Z2yM834yteBlEvXlSZ2/mPsLQSercjHQYuIZn4HgxXnJ4GWhHTQFLzJTZHADPgJC8i2whHeddZcnOiNk8n1Y7kYsZKOoY4JkJnyUGDXjXNu9rCyiM8rjcuuj5/EL7GB79S8dNOLLpd9ftIjDMGuEooj3JMALD86gwcH+gmBG9Q5V6vZd+hq9djyj/ULw3vYWnIwPR3jwfxq7amenQRjdhfJGJXZO6FW8yaHy4loDCAA11F+Z3gpq+Jt5WPMbpNG1ZXbBjRow4OumMYoD8XRljIKXX8dFmj+DJCwEyMVM+oC/ZRfsr5TFllkWiLvpW5zP2H7Mzwlm7OSxV2oA3w7k542xj+IlgtoO3QYVRW/G8/L7Dlhc7dA+M98L9gmLWeE3xzTEefQGaZwMnHWO03UxmnJSl4cVgMiuU6/MG2VeZTMAtflbnw9ijdkY8ZN1o59QpK8a+WPfgxTFlvTugMMK0nxaxVND7vBWPcdrg0bJ0dPSaEuTBM4MYOB5RMUCWsAyqO8jpvJxqmfsDAuJ5JM4IjK75NNjpXa5mx0y3jAa86rhdAYVSF843qmZDq1aMzK14jDOo/UKdvzWtqar2Md5MEu5ghUA88jxeBmT8rGBALFEIPGQMRCnWh6fpbxl84q/Oh/4mO6dqBjPsl4IXHjfi1aCGvXcoF+MMg0zNOYWzf+SbNdLdIReqtLvxwHah7lKnzEQ7OIm6N9BDkDDuFmUtCMwqNefcdk6MzS/mHjGzoFFupImNjG2ZT6udQQWYBrg25HaN6kPVhZcPLNu7AgpDXazZmQz/q3zq5ORSce25Fw95A9eALgNWp5R3lprKkmcQaXcZTAaQFOf6sqLTfjNYlPFZ8ugqN5x8/0Tji0ySp906n1Y71SNF+2ubwP5ePMdUqQwoX38ld9pkUZnsKTwDxYvg4t+r6JeUtSzRop6FATM8bHDH6SgDoLzDncNbupiv6S4DcwDH4FS/LwqX1JJ/IrGkj4O0/WwiTTYRfF8StNGPiQGfWryfKY8dIMHrmU+rnQfw/3wR7Y/8WPfixXGztbzhfxswmbiD3GFO1tRoKvaukHY67U/wXJy0kDwngq9jXRhxJC+07+EH51I36Qkj+VnDo09b1FWjWdC36kZO2/OgUIfBkDKJCnmWHx3hBnT3+1G36jT4vq67tpLyk29W9PfOp8lOlYGtrR5ri58pkOnBW/Tjv+UeF7RHL5lRAAAAAElFTkSuQmCC", - "text/latex": [ - "$\\displaystyle 1.4142135623731$" - ], - "text/plain": [ - "1.4142135623730951" - ] - }, - "execution_count": 104, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "vector.obj(pt=1, phi=1.3, eta=2).deltaR(vector.obj(pt=2, phi=0.3, eta=1))" - ] - }, - { - "cell_type": "code", - "execution_count": 105, - "id": "strategic-hypothesis", - "metadata": {}, - "outputs": [ - { - "data": { - "image/png": "iVBORw0KGgoAAAANSUhEUgAAAJQAAAAPCAYAAAACneZUAAAACXBIWXMAAA7EAAAOxAGVKw4bAAAFbUlEQVRoBe2a35XVNhCHDWcLWEgH0AGwHWw6CKECoIPk5G3fONBBoAL+dJCkAgIdQAeB7WDzfbqWIsuyr2TvCS/MObqSR6PfjDSjkezdG1dXV8N36l+Bi4uLe5SP+UieT3m+Tf0553+rNnbcQfc55Q3ty//DjpNcCUrv8fyWcn+PASPOU+qnOX5s9+pZwoPvgv064j6g/uIz/Imjx/5QHdM9Yka7DRB1PIf/Z45D+y949kddtqX7h2r+i/zzgvsaXhw/0G6ezyh7zE79+bsF+UJ1eLyEf8tWI94EgzGzeDmB6UK8ougMneKk9pJBmRZKsJ16anja6UL9KL5EW4d9kEdJAUC7aY6jnAEZHTXQ/gnMP6gfUt6pZyTXS3JRzUj2PUPmknpC8LTVOYgd7KL22XKXMowyPfNpsfMMaPXVMqaZK2xGdLs+LXjaubqWBpQL8JCi8C9ULtBmGjFm47fqWcJDgcGTHK9CZF2UJzR1VNh5I791jo59AoYBFIMnBuZv9EWesB+RCevmwxHSHrNRxFJcx+SObp4P45rtRGfacCqV4IWkQR3n04O3upY3Dyqu5xcDDUYVWnbTETx32CdkdExOOu0Ufli0vKOhbVad2A/Orrkw3gznurzM9cM3i+bO7plPq53vc51Z2yM834yteBlEvXlSZ2/mPsLQSercjHQYuIZn4HgxXnJ4GWhHTQFLzJTZHADPgJC8i2whHeddZcnOiNk8n1Y7kYsZKOoY4JkJnyUGDXjXNu9rCyiM8rjcuuj5/EL7GB79S8dNOLLpd9ftIjDMGuEooj3JMALD86gwcH+gmBG9Q5V6vZd+hq9djyj/ULw3vYWnIwPR3jwfxq7amenQRjdhfJGJXZO6FW8yaHy4loDCAA11F+Z3gpq+Jt5WPMbpNG1ZXbBjRow4OumMYoD8XRljIKXX8dFmj+DJCwEyMVM+oC/ZRfsr5TFllkWiLvpW5zP2H7Mzwlm7OSxV2oA3w7k542xj+IlgtoO3QYVRW/G8/L7Dlhc7dA+M98L9gmLWeE3xzTEefQGaZwMnHWO03UxmnJSl4cVgMiuU6/MG2VeZTMAtflbnw9ijdkY8ZN1o59QpK8a+WPfgxTFlvTugMMK0nxaxVND7vBWPcdrg0bJ0dPSaEuTBM4MYOB5RMUCWsAyqO8jpvJxqmfsDAuJ5JM4IjK75NNjpXa5mx0y3jAa86rhdAYVSF843qmZDq1aMzK14jDOo/UKdvzWtqar2Md5MEu5ghUA88jxeBmT8rGBALFEIPGQMRCnWh6fpbxl84q/Oh/4mO6dqBjPsl4IXHjfi1aCGvXcoF+MMg0zNOYWzf+SbNdLdIReqtLvxwHah7lKnzEQ7OIm6N9BDkDDuFmUtCMwqNefcdk6MzS/mHjGzoFFupImNjG2ZT6udQQWYBrg25HaN6kPVhZcPLNu7AgpDXazZmQz/q3zq5ORSce25Fw95A9eALgNWp5R3lprKkmcQaXcZTAaQFOf6sqLTfjNYlPFZ8ugqN5x8/0Tji0ySp906n1Y71SNF+2ubwP5ePMdUqQwoX38ld9pkUZnsKTwDxYvg4t+r6JeUtSzRop6FATM8bHDH6SgDoLzDncNbupiv6S4DcwDH4FS/LwqX1JJ/IrGkj4O0/WwiTTYRfF8StNGPiQGfWryfKY8dIMHrmU+rnQfw/3wR7Y/8WPfixXGztbzhfxswmbiD3GFO1tRoKvaukHY67U/wXJy0kDwngq9jXRhxJC+07+EH51I36Qkj+VnDo09b1FWjWdC36kZO2/OgUIfBkDKJCnmWHx3hBnT3+1G36jT4vq67tpLyk29W9PfOp8lOlYGtrR5ri58pkOnBW/Tjv+UeF7RHL5lRAAAAAElFTkSuQmCC", - "text/latex": [ - "$\\displaystyle 1.4142135623731$" - ], - "text/plain": [ - "1.4142135623730951" - ] - }, - "execution_count": 105, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "vector.obj(pt=1, phi=1.3, eta=2, mass=5).deltaR(\n", - " vector.obj(pt=2, phi=0.3, eta=1, mass=10)\n", - ")" - ] - }, - { - "cell_type": "markdown", - "id": "sensitive-booking", - "metadata": {}, - "source": [ - "For a few operations - `+`, `-`, `==`, `!=`, ... - the dimension of the vectors should be equal. This can be achieved by using the `like` method, `to_{coordinate_name}` methods, `to_Vector*D` methods. The `to_Vector*D` methods provide more flexibility to the users, that is, new coordinate values can be passed into the methods as named arguments." - ] - }, - { - "cell_type": "code", - "execution_count": 106, - "id": "loaded-kidney", - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "VectorObject3D(x=0, y=0, z=3.0)\n", - "VectorObject2D(x=0, y=0)\n", - "VectorObject3D(x=0, y=0, z=3.0)\n", - "VectorObject2D(x=0, y=0)\n", - "VectorObject3D(x=0, y=0, z=0)\n", - "VectorObject2D(x=0, y=0)\n" - ] - } - ], - "source": [ - "v1 = vector.obj(x=1, y=2, z=3)\n", - "v2 = vector.obj(x=1, y=2)\n", - "\n", - "print(v1 - v2.like(v1)) # transforms v2 to v1's coordinate system (imputes z=0)\n", - "print(v1.like(v2) - v2) # transforms v1 to v2's coordinate system (removes z)\n", - "print(v1 - v2.to_xyz()) # transforms v2 to xyz coordinates (imputes z=0)\n", - "print(v1.to_xy() - v2) # transforms v1 to xy coordinates (removes z)\n", - "print(v1 - v2.to_Vector3D(z=3)) # transforms v2 to 3D (imputes z=3)\n", - "print(v1.to_Vector2D() - v2) # transforms v1 to 2D (removes z)" - ] - }, - { - "cell_type": "markdown", - "id": "willing-detail", - "metadata": {}, - "source": [ - "Similarly, for a few vector methods, the dimension of the input vectors are type checked strictly.\n", - "\n", - "For instance, a cross-product is only defined for 3D and 7D vectors; hence, running the method on a 4D vector will error out." - ] - }, - { - "cell_type": "code", - "execution_count": 107, - "id": "preceding-possibility", - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "VectorObject3D(x=-0.03, y=0.06, z=-0.030000000000000013)" - ] - }, - "execution_count": 107, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "vector.obj(x=0.1, y=0.2, z=0.3).cross(vector.obj(x=0.4, y=0.5, z=0.6))" - ] - }, - { - "cell_type": "markdown", - "id": "operational-accused", - "metadata": {}, - "source": [ - "The (current) list of properties and methods is:\n", - "\n", - "**Planar (2D, 3D, 4D):**\n", - "\n", - " * `x` (`px`)\n", - " * `y` (`py`)\n", - " * `rho` (`pt`): two-dimensional magnitude\n", - " * `rho2` (`pt2`): two-dimensional magnitude squared\n", - " * `phi`\n", - " * `deltaphi(vector)`: difference in `phi` (signed and rectified to $-\\pi$ through $\\pi$)\n", - " * `rotateZ(angle)`\n", - " * `transform2D(obj)`: the `obj` must supply components through `obj[\"xx\"]`, `obj[\"xy\"]`, `obj[\"yx\"]`, `obj[\"yy\"]`\n", - " * `is_parallel(vector, tolerance=1e-5)`: only true _if they're pointing in the same direction_\n", - " * `is_antiparallel(vector, tolerance=1e-5)`: only true _if they're pointing in opposite directions_\n", - " * `is_perpendicular(vector, tolerance=1e-5)`\n", - "\n", - "**Spatial (3D, 4D):**\n", - "\n", - " * `z` (`pz`)\n", - " * `theta`\n", - " * `eta`\n", - " * `costheta`\n", - " * `cottheta`\n", - " * `mag` (`p`): three-dimensional magnitude, does not include temporal component\n", - " * `mag2` (`p2`): three-dimensional magnitude squared\n", - " * `cross`: cross-product (strictly 3D)\n", - " * `deltaangle(vector)`: difference in angle (always non-negative)\n", - " * `deltaeta(vector)`: difference in `eta` (signed)\n", - " * `deltaR(vector)`: $\\Delta R = \\sqrt{\\Delta\\phi^2 + \\Delta\\eta^2}$\n", - " * `deltaR2(vector)`: the above, squared\n", - " * `rotateX(angle)`\n", - " * `rotateY(angle)`\n", - " * `rotate_axis(axis, angle)`: the magnitude of `axis` is ignored, but it must be at least 3D\n", - " * `rotate_euler(phi, theta, psi, order=\"zxz\")`: the arguments are in the same order as [ROOT::Math::EulerAngles](https://root.cern.ch/doc/master/classROOT_1_1Math_1_1EulerAngles.html), and `order=\"zxz\"` agrees with ROOT's choice of conventions\n", - " * `rotate_nautical(yaw, pitch, roll)`\n", - " * `rotate_quaternion(u, i, j, k)`: again, the conventions match [ROOT::Math::Quaternion](https://root.cern.ch/doc/master/classROOT_1_1Math_1_1Quaternion.html).\n", - " * `transform3D(obj)`: the `obj` must supply components through `obj[\"xx\"]`, `obj[\"xy\"]`, etc.\n", - " * `is_parallel(vector, tolerance=1e-5)`: only true _if they're pointing in the same direction_\n", - " * `is_antiparallel(vector, tolerance=1e-5)`: only true _if they're pointing in opposite directions_\n", - " * `is_perpendicular(vector, tolerance=1e-5)`\n", - "\n", - "**Lorentz (4D only):**\n", - "\n", - " * `t` (`E`, `energy`): follows the [ROOT::Math::LorentzVector](https://root.cern/doc/master/LorentzVectorPage.html) behavior of treating spacelike vectors as negative `t` and negative `tau` and truncating wrong-direction timelike vectors\n", - " * `t2` (`E2`, `energy2`)\n", - " * `tau` (`M`, `mass`): see note above\n", - " * `tau2` (`M2`, `mass2`)\n", - " * `beta`: scalar(s) between $0$ (inclusive) and $1$ (exclusive, unless the vector components are infinite)\n", - " * `deltaRapidityPhi`: $\\Delta R_{\\mbox{rapidity}} = \\Delta\\phi^2 + \\Delta \\mbox{rapidity}^2$\n", - " * `deltaRapidityPhi2`: the above, squared\n", - " * `gamma`: scalar(s) between $1$ (inclusive) and $\\infty$\n", - " * `rapidity`: scalar(s) between $0$ (inclusive) and $\\infty$\n", - " * `boost_p4(four_vector)`: change coordinate system using another 4D vector as the difference\n", - " * `boost_beta(three_vector)`: change coordinate system using a 3D beta vector (all components between $-1$ and $+1$)\n", - " * `boost(vector)`: uses the dimension of the given `vector` to determine behavior\n", - " * `boostX(beta=None, gamma=None)`: supply `beta` xor `gamma`, but not both\n", - " * `boostY(beta=None, gamma=None)`: supply `beta` xor `gamma`, but not both\n", - " * `boostZ(beta=None, gamma=None)`: supply `beta` xor `gamma`, but not both\n", - " * `transform4D(obj)`: the `obj` must supply components through `obj[\"xx\"]`, `obj[\"xy\"]`, etc.\n", - " * `to_beta3()`: turns a `four_vector` (for `boost_p4`) into a `three_vector` (for `boost_beta3`)\n", - " * `is_timelike(tolerance=0)`\n", - " * `is_spacelike(tolerance=0)`\n", - " * `is_lightlike(tolerance=1e-5)`: note the different tolerance\n", - "\n", - "**All numbers of dimensions:**\n", - "\n", - " * `unit()`: note the parentheses\n", - " * `dot(vector)`: can also use the `@` operator\n", - " * `add(vector)`: can also use the `+` operator\n", - " * `subtract(vector)`: can also use the `-` operator\n", - " * `scale(factor)`: can also use the `*` operator\n", - " * `equal(vector)`: can also use the `==` operator, but consider `isclose` instead\n", - " * `not_equal(vector)`: can also use the `!=` operator, but consider `isclose` instead\n", - " * `sum()`: can also use the `numpy.sum` or `awkward.sum`, only for NumPy and Awkward vectors\n", - " * `count_nonzero()`: can also use `numpy.count_nonzero` or `awkward.count_nonzero`, only for NumPy and Awkward vectors\n", - " * `count()`: can also use `awkward.count`, only for Awkward vectors\n", - " * `isclose(vector, rtol=1e-5, atol=1e-8, equal_nan=False)`: works like [np.isclose](https://numpy.org/doc/stable/reference/generated/numpy.isclose.html); arrays also have an [allclose](https://numpy.org/doc/stable/reference/generated/numpy.allclose.html) method\n", - " * `to_VectorND(coordinates)`/`to_ND(coordinates)`: replace `N` with the required vector dimension\n", - " * `to_{coordinate-names}`: for example - `to_rhophietatau`\n", - " * `like(other)`: projects the vector into the dimensions of `other`, for example - `two_d_vector.like(three_d_vector)`\n" - ] - }, - { - "cell_type": "markdown", - "id": "dedicated-exemption", - "metadata": {}, - "source": [ - "## Compiling your Python with Numba\n", - "\n", - "[Numba](https://numba.pydata.org/) is a just-in-time (JIT) compiler for a mathematically relevant subset of NumPy and Python. It allows you to write fast code without leaving the Python environment. The drawback of Numba is that it can only compile code blocks involving objects and functions that it recognizes.\n", - "\n", - "The Vector library includes extensions to inform Numba about vector objects, vector NumPy arrays, and vector Awkward Arrays. At the time of writing, the implementation of vector NumPy arrays is incomplete due to [numba/numba#6148](https://github.com/numba/numba/pull/6148).\n", - "\n", - "For instance, consider the following function:" - ] - }, - { - "cell_type": "code", - "execution_count": 108, - "id": "sporting-champion", - "metadata": {}, - "outputs": [], - "source": [ - "@nb.njit\n", - "def compute_mass(v1, v2):\n", - " return (v1 + v2).mass" - ] - }, - { - "cell_type": "code", - "execution_count": 109, - "id": "blocked-attribute", - "metadata": {}, - "outputs": [ - { - "data": { - "image/png": "iVBORw0KGgoAAAANSUhEUgAAABoAAAAOCAYAAAAxDQxDAAAACXBIWXMAAA7EAAAOxAGVKw4bAAABr0lEQVQ4EaWU7VECQQyGD8YCGOwAO/CjA+gA7UAtgfEX/HMoAS0BOpAOHOgAOgDp4HyeZffmgBVnNDO5JO8mm02yt42yLAtpNBq1EC/B2H+0p+DzGnZWxXccHTbIK3gMtg6YieThcDhJepJgU7if7HMSv0XdF70Fr+COcU2zkfUJsQiZDz+PmPUqD1ejFeNbyFlyQN+ha0/EQiKkZfYE/kj3xC0zsZ9gXZK2UiKBPsCHYC3AnocT1bCc2gXcZhb28yHZhYtsPpNR+/AX+gBplSau2oF9QqzXD3ayHoF2qqggwPLf4oKVeMpcO6JLJdpRcyY/UdU6E1mNzlbile7Aq4ij/osuQ0Vs5q3rIQfwGvZiWKH0jn2uPbnZ7COLIlW7Sa2zVc6lIjZ3NlZnEtuYJfxSy3KHSdi6GU/rP5ACqg3BvDUmTCer1o6U1OojuIqbm8gEO6QzyZGn+u0ZmuJzmwm+AVuaI7XOefiupVJDDLaz84qH/8F1uIQPXhFsb+sW6YUKhO5eD7CvS9HwHZJYuEb43NSHe/Ko4rfCZ458RlaE7cbOegf7qN7Br+DhF/kGiTPUL2upEhgAAAAASUVORK5CYII=", - "text/latex": [ - "$\\displaystyle 8.0$" - ], - "text/plain": [ - "8.0" - ] - }, - "execution_count": 109, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "compute_mass(vector.obj(px=1, py=2, pz=3, E=4), vector.obj(px=-1, py=-2, pz=-3, E=4))" - ] - }, - { - "cell_type": "markdown", - "id": "significant-sweden", - "metadata": {}, - "source": [ - "When the two `MomentumObject4D` objects are passed as arguments, Numba recognizes them and replaces the Python objects with low-level structs. When it compiles the function, it recognizes `+` as the 4D `add` function and recognizes `.mass` as the `tau` component of the result.\n", - "\n", - "Although this demonstrates that Numba can manipulate vector objects, there is no performance advantage (and a likely disadvantage) to compiling a calculation on just a few vectors. The advantage comes when many vectors are involved, in arrays." - ] - }, - { - "cell_type": "code", - "execution_count": 110, - "id": "round-supplier", - "metadata": {}, - "outputs": [ - { - "data": { - "text/html": [ - "
[[],\n",
-       " [{x: 0.68, y: 0.799, z: -0.423, t: 10.4}, ..., {x: -0.17, y: 1.11, ...}],\n",
-       " [{x: -1.23, y: 0.529, z: -0.974, t: 11.5}, {x: -1.95, y: 0.159, ...}],\n",
-       " [{x: 0.232, y: -1.05, z: 0.134, t: 8.56}],\n",
-       " [{x: 1.55, y: 0.503, z: 0.609, t: 7.54}],\n",
-       " [{x: -0.181, y: 0.579, z: 0.774, t: 8.93}, {x: -0.361, y: -0.517, ...}],\n",
-       " [{x: 0.746, y: -1.49, z: 0.096, t: 10.2}, ..., {x: -0.274, y: -0.0958, ...}],\n",
-       " [{x: 0.215, y: 1.29, z: -0.908, t: 11.8}],\n",
-       " [{x: -0.621, y: 0.148, z: 0.128, t: 10.6}],\n",
-       " [],\n",
-       " ...,\n",
-       " [],\n",
-       " [{x: 1.38, y: -0.677, z: 1.71, t: 11.9}],\n",
-       " [],\n",
-       " [{x: 0.0776, y: -0.233, z: 0.738, t: 11.6}, {x: -0.242, y: 2.69, ...}],\n",
-       " [],\n",
-       " [{x: 2.12, y: -0.294, z: 0.0647, t: 10}],\n",
-       " [{x: 0.431, y: 0.33, z: -0.372, t: 9.36}],\n",
-       " [{x: -0.144, y: 0.304, z: -0.333, t: 9.21}, {x: -1.65, y: -0.12, ...}],\n",
-       " [{x: 2.4, y: 0.994, z: 1.88, t: 8.42}, {x: 0.418, y: -1.66, z: ..., ...}]]\n",
-       "------------------------------------------------------------------------------\n",
-       "type: 50 * var * Momentum4D[\n",
-       "    x: float64,\n",
-       "    y: float64,\n",
-       "    z: float64,\n",
-       "    t: float64\n",
-       "]
" - ], - "text/plain": [ - "" - ] - }, - "execution_count": 110, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "# This is still not a large number. You want millions.\n", - "array = vector.Array(\n", - " [\n", - " [\n", - " dict(\n", - " {x: np.random.normal(0, 1) for x in (\"px\", \"py\", \"pz\")},\n", - " E=np.random.normal(10, 1),\n", - " )\n", - " for inner in range(np.random.poisson(1.5))\n", - " ]\n", - " for outer in range(50)\n", - " ]\n", - ")\n", - "array" - ] - }, - { - "cell_type": "code", - "execution_count": 111, - "id": "emotional-headquarters", - "metadata": {}, - "outputs": [], - "source": [ - "@nb.njit\n", - "def compute_masses(array):\n", - " out = np.empty(len(array), np.float64)\n", - " for i, event in enumerate(array):\n", - " total = vector.obj(px=0.0, py=0.0, pz=0.0, E=0.0)\n", - " for vec in event:\n", - " total = total + vec\n", - " out[i] = total.mass\n", - " return out" - ] - }, - { - "cell_type": "code", - "execution_count": 112, - "id": "recorded-grass", - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "array([ 0. , 29.75052555, 20.62838909, 8.48660722, 7.33516837,\n", - " 18.70338324, 29.7146754 , 11.65299876, 10.59925 , 0. ,\n", - " 0. , 21.27961128, 0. , 29.59277853, 27.32368944,\n", - " 0. , 0. , 10.59714826, 0. , 34.36150967,\n", - " 27.76305288, 10.42185596, 8.59241845, 0. , 19.31564032,\n", - " 9.3728877 , 20.05084709, 9.29945943, 10.5533362 , 28.56379761,\n", - " 10.27649379, 41.35441725, 0. , 10.73854109, 0. ,\n", - " 19.35692625, 28.85293189, 32.14146007, 21.7278048 , 10.27831307,\n", - " 39.11007941, 0. , 11.63961915, 0. , 20.42034302,\n", - " 0. , 9.78956764, 9.33434012, 20.00141989, 18.47871584])" - ] - }, - "execution_count": 112, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "compute_masses(array)" - ] - }, - { - "cell_type": "markdown", - "id": "f9f99531-245a-4a24-b717-42839ff542c0", - "metadata": {}, - "source": [ - "## Sub-classing Awkward mixins\n", - "\n", - "At the moment, it is possible to sub-class vector awkward mixins to extend the vector functionalities. Although the mechanism in place works well, it is still being improved.\n", - "\n", - "For instance, the `MomentumAwkward` classes can be extended in the following way:" - ] - }, - { - "cell_type": "code", - "execution_count": 113, - "id": "eabb3cc3-3df3-4052-a64d-84499866fdc9", - "metadata": {}, - "outputs": [], - "source": [ - "behavior = vector.backends.awkward.behavior\n", - "\n", - "\n", - "@ak.mixin_class(behavior)\n", - "class TwoVector(vector.backends.awkward.MomentumAwkward2D):\n", - " pass\n", - "\n", - "\n", - "@ak.mixin_class(behavior)\n", - "class ThreeVector(vector.backends.awkward.MomentumAwkward3D):\n", - " pass\n", - "\n", - "\n", - "# required for transforming vectors\n", - "# the class names must always end with \"Array\"\n", - "TwoVectorArray.ProjectionClass2D = TwoVectorArray # noqa: F821\n", - "TwoVectorArray.ProjectionClass3D = ThreeVectorArray # noqa: F821\n", - "TwoVectorArray.MomentumClass = TwoVectorArray # noqa: F821\n", - "\n", - "ThreeVectorArray.ProjectionClass2D = TwoVectorArray # noqa: F821\n", - "ThreeVectorArray.ProjectionClass3D = ThreeVectorArray # noqa: F821\n", - "ThreeVectorArray.MomentumClass = ThreeVectorArray # noqa: F821" - ] - }, - { - "cell_type": "code", - "execution_count": 114, - "id": "09fb1708-0205-409d-b348-e2d1611227f3", - "metadata": {}, - "outputs": [ - { - "data": { - "text/html": [ - "
[[{pt: 1, phi: 1.2}, {pt: 2, phi: 1.4}],\n",
-       " [],\n",
-       " [{pt: 3, phi: 1.6}],\n",
-       " [{pt: 4, phi: 3.4}]]\n",
-       "----------------------------------------\n",
-       "type: 4 * var * TwoVector[\n",
-       "    pt: int64,\n",
-       "    phi: float64\n",
-       "]
" - ], - "text/plain": [ - "" - ] - }, - "execution_count": 114, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "vec = ak.zip(\n", - " {\n", - " \"pt\": [[1, 2], [], [3], [4]],\n", - " \"phi\": [[1.2, 1.4], [], [1.6], [3.4]],\n", - " },\n", - " with_name=\"TwoVector\",\n", - " behavior=behavior,\n", - ")\n", - "vec" - ] - }, - { - "cell_type": "markdown", - "id": "7c2d0b74-0f87-417c-8e0c-5420408f3dff", - "metadata": {}, - "source": [ - "The binary operators are not automatically registered by awkward, but vector methods can be used to perform operations on sub-classed vectors." - ] - }, - { - "cell_type": "code", - "execution_count": 115, - "id": "a63c205e-4b80-4e78-a3c3-fda3be083085", - "metadata": {}, - "outputs": [ - { - "data": { - "text/html": [ - "
[[{rho: 2, phi: 1.2}, {rho: 4, phi: 1.4}],\n",
-       " [],\n",
-       " [{rho: 6, phi: 1.6}],\n",
-       " [{rho: 8, phi: -2.88}]]\n",
-       "------------------------------------------\n",
-       "type: 4 * var * TwoVector[\n",
-       "    rho: float64,\n",
-       "    phi: float64\n",
-       "]
" - ], - "text/plain": [ - "" - ] - }, - "execution_count": 115, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "vec.add(vec)" - ] - }, - { - "cell_type": "markdown", - "id": "a51204fc-e1e5-4bdc-a3a0-d51dbc786457", - "metadata": {}, - "source": [ - "Similarly, other vector methods can be used by the new methods internally." - ] - }, - { - "cell_type": "code", - "execution_count": 116, - "id": "f9feeec4-c730-4f7b-b5bd-05d401eb0ee1", - "metadata": {}, - "outputs": [], - "source": [ - "@ak.mixin_class(behavior)\n", - "class LorentzVector(vector.backends.awkward.MomentumAwkward4D):\n", - " @ak.mixin_class_method(np.divide, {numbers.Number})\n", - " def divide(self, factor):\n", - " return self.scale(1 / factor)\n", - "\n", - "\n", - "# required for transforming vectors\n", - "# the class names must always end with \"Array\"\n", - "LorentzVectorArray.ProjectionClass2D = TwoVectorArray # noqa: F821\n", - "LorentzVectorArray.ProjectionClass3D = ThreeVectorArray # noqa: F821\n", - "LorentzVectorArray.ProjectionClass4D = LorentzVectorArray # noqa: F821\n", - "LorentzVectorArray.MomentumClass = LorentzVectorArray # noqa: F821" - ] - }, - { - "cell_type": "code", - "execution_count": 117, - "id": "d66c5f27-ae2e-4659-b96a-bd0493bda557", - "metadata": {}, - "outputs": [ - { - "data": { - "text/html": [ - "
[[{pt: 1, eta: 1.2, phi: 0.3, energy: 50}, {pt: 2, eta: 1.4, ...}],\n",
-       " [],\n",
-       " [{pt: 3, eta: 1.6, phi: 0.5, energy: 52}],\n",
-       " [{pt: 4, eta: 3.4, phi: 0.6, energy: 60}]]\n",
-       "-------------------------------------------------------------------\n",
-       "type: 4 * var * LorentzVector[\n",
-       "    pt: int64,\n",
-       "    eta: float64,\n",
-       "    phi: float64,\n",
-       "    energy: int64\n",
-       "]
" - ], - "text/plain": [ - "" - ] - }, - "execution_count": 117, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "vec = ak.zip(\n", - " {\n", - " \"pt\": [[1, 2], [], [3], [4]],\n", - " \"eta\": [[1.2, 1.4], [], [1.6], [3.4]],\n", - " \"phi\": [[0.3, 0.4], [], [0.5], [0.6]],\n", - " \"energy\": [[50, 51], [], [52], [60]],\n", - " },\n", - " with_name=\"LorentzVector\",\n", - " behavior=behavior,\n", - ")\n", - "vec" - ] - }, - { - "cell_type": "code", - "execution_count": 118, - "id": "9841c7c5-745d-46bb-8d03-07d16f9bc2e1", - "metadata": {}, - "outputs": [ - { - "data": { - "text/html": [ - "
[[{rho: 0.5, phi: 0.3, eta: 1.2, t: 25}, {rho: 1, phi: 0.4, ...}],\n",
-       " [],\n",
-       " [{rho: 1.5, phi: 0.5, eta: 1.6, t: 26}],\n",
-       " [{rho: 2, phi: 0.6, eta: 3.4, t: 30}]]\n",
-       "------------------------------------------------------------------\n",
-       "type: 4 * var * LorentzVector[\n",
-       "    rho: float64,\n",
-       "    phi: float64,\n",
-       "    eta: float64,\n",
-       "    t: float64\n",
-       "]
" - ], - "text/plain": [ - "" - ] - }, - "execution_count": 118, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "vec / 2" - ] - }, - { - "cell_type": "code", - "execution_count": 119, - "id": "ce31f343-ced2-499a-8ae9-382ebe420351", - "metadata": {}, - "outputs": [ - { - "data": { - "text/html": [ - "
[[{rho: 1, phi: 0.3}, {rho: 2, phi: 0.4}],\n",
-       " [],\n",
-       " [{rho: 3, phi: 0.5}],\n",
-       " [{rho: 4, phi: 0.6}]]\n",
-       "------------------------------------------\n",
-       "type: 4 * var * TwoVector[\n",
-       "    rho: int64,\n",
-       "    phi: float64\n",
-       "]
" - ], - "text/plain": [ - "" - ] - }, - "execution_count": 119, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "vec.like(vector.obj(x=1, y=2))" - ] - }, - { - "cell_type": "code", - "execution_count": 120, - "id": "09a1492b-f3f3-4f24-965f-8973f98c6a2a", - "metadata": {}, - "outputs": [ - { - "data": { - "text/html": [ - "
[[{rho: 1, phi: 0.3, eta: 1.2}, {rho: 2, phi: 0.4, eta: 1.4}],\n",
-       " [],\n",
-       " [{rho: 3, phi: 0.5, eta: 1.6}],\n",
-       " [{rho: 4, phi: 0.6, eta: 3.4}]]\n",
-       "--------------------------------------------------------------\n",
-       "type: 4 * var * ThreeVector[\n",
-       "    rho: int64,\n",
-       "    phi: float64,\n",
-       "    eta: float64\n",
-       "]
" - ], - "text/plain": [ - "" - ] - }, - "execution_count": 120, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "vec.like(vector.obj(x=1, y=2, z=3))" - ] - }, - { - "cell_type": "markdown", - "id": "088b4d4a-882b-4082-bcef-04ea9c4e2a17", - "metadata": {}, - "source": [ - "It is also possible to manually add binary operations in vector's behavior dict to enable binary operations." - ] - }, - { - "cell_type": "code", - "execution_count": 121, - "id": "0b8e04b4-4117-4169-9d13-03dd0fea8161", - "metadata": {}, - "outputs": [], - "source": [ - "_binary_dispatch_cls = {\n", - " \"TwoVector\": TwoVector,\n", - " \"ThreeVector\": ThreeVector,\n", - " \"LorentzVector\": LorentzVector,\n", - "}\n", - "_rank = [TwoVector, ThreeVector, LorentzVector]\n", - "\n", - "for lhs, lhs_to in _binary_dispatch_cls.items():\n", - " for rhs, rhs_to in _binary_dispatch_cls.items():\n", - " out_to = min(lhs_to, rhs_to, key=_rank.index)\n", - " behavior[(np.add, lhs, rhs)] = out_to.add\n", - " behavior[(np.subtract, lhs, rhs)] = out_to.subtract" - ] - }, - { - "cell_type": "code", - "execution_count": 122, - "id": "09c03e49-8233-492c-8fa7-45029a774388", - "metadata": {}, - "outputs": [ - { - "data": { - "text/html": [ - "
[[{rho: 2, phi: 0.3, eta: 1.2, t: 100}, {rho: 4, phi: 0.4, eta: 1.4, ...}],\n",
-       " [],\n",
-       " [{rho: 6, phi: 0.5, eta: 1.6, t: 104}],\n",
-       " [{rho: 8, phi: 0.6, eta: 3.4, t: 120}]]\n",
-       "---------------------------------------------------------------------------\n",
-       "type: 4 * var * LorentzVector[\n",
-       "    rho: float64,\n",
-       "    phi: float64,\n",
-       "    eta: float64,\n",
-       "    t: int64\n",
-       "]
" - ], - "text/plain": [ - "" - ] - }, - "execution_count": 122, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "vec + vec" - ] - }, - { - "cell_type": "code", - "execution_count": 123, - "id": "7c13bd26-95b5-4ae3-9f17-4818493f510a", - "metadata": {}, - "outputs": [ - { - "data": { - "text/html": [ - "
[[{rho: 2, phi: 0.3}, {rho: 4, phi: 0.4}],\n",
-       " [],\n",
-       " [{rho: 6, phi: 0.5}],\n",
-       " [{rho: 8, phi: 0.6}]]\n",
-       "------------------------------------------\n",
-       "type: 4 * var * TwoVector[\n",
-       "    rho: float64,\n",
-       "    phi: float64\n",
-       "]
" - ], - "text/plain": [ - "" - ] - }, - "execution_count": 123, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "vec.to_2D() + vec.to_2D()" - ] - }, - { - "cell_type": "markdown", - "id": "326f3e22-d58e-4e82-9f63-99eab307ac52", - "metadata": {}, - "source": [ - "Finally, instead of manually registering the superclass ufuncs, one can use the utility `copy_behaviors` function to copy behavior items for a new subclass -" - ] - }, - { - "cell_type": "code", - "execution_count": 124, - "id": "48629f7e-306e-438d-bb15-a66f0acbdfc5", - "metadata": {}, - "outputs": [], - "source": [ - "behavior.update(ak._util.copy_behaviors(\"Vector2D\", \"TwoVector\", behavior))\n", - "behavior.update(ak._util.copy_behaviors(\"Vector3D\", \"ThreeVector\", behavior))\n", - "behavior.update(ak._util.copy_behaviors(\"Momentum4D\", \"LorentzVector\", behavior))" - ] - }, - { - "cell_type": "code", - "execution_count": 125, - "id": "8874188b-778e-45af-8320-7f472f9794a2", - "metadata": {}, - "outputs": [ - { - "data": { - "text/html": [ - "
[[{rho: 2, phi: 0.3, eta: 1.2, t: 100}, {rho: 4, phi: 0.4, eta: 1.4, ...}],\n",
-       " [],\n",
-       " [{rho: 6, phi: 0.5, eta: 1.6, t: 104}],\n",
-       " [{rho: 8, phi: 0.6, eta: 3.4, t: 120}]]\n",
-       "---------------------------------------------------------------------------\n",
-       "type: 4 * var * Momentum4D[\n",
-       "    rho: float64,\n",
-       "    phi: float64,\n",
-       "    eta: float64,\n",
-       "    t: int64\n",
-       "]
" - ], - "text/plain": [ - "" - ] - }, - "execution_count": 125, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "vec + vec" - ] - }, - { - "cell_type": "code", - "execution_count": 126, - "id": "051f94ac-b875-47f6-8b11-4725eeb6c2f3", - "metadata": {}, - "outputs": [ - { - "data": { - "text/html": [ - "
[[{rho: 2, phi: 0.3}, {rho: 4, phi: 0.4}],\n",
-       " [],\n",
-       " [{rho: 6, phi: 0.5}],\n",
-       " [{rho: 8, phi: 0.6}]]\n",
-       "------------------------------------------\n",
-       "type: 4 * var * Vector2D[\n",
-       "    rho: float64,\n",
-       "    phi: float64\n",
-       "]
" - ], - "text/plain": [ - "" - ] - }, - "execution_count": 126, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "vec.to_2D() + vec.to_2D()" - ] - }, - { - "cell_type": "markdown", - "id": "bb6c289a", - "metadata": {}, - "source": [ - "## Talks about vector\n", - "\n", - "- 3rd July 2024 - [A new SymPy backend for vector: uniting experimental and theoretical physicists](https://indi.to/pfTC6) - [PyHEP 2024 (virtual)](https://indico.cern.ch/event/1384010/)\n", - "- 9th October 2023 - [What’s new with Vector? First major release is out!](https://indi.to/35ym5) - [PyHEP 2023 (virtual)](https://indico.cern.ch/event/1252095/) [🎥](https://www.youtube.com/watch?v=JHEAb2R3xzE&list=PLKZ9c4ONm-VlAorAG8kR09ZqhMfHiH2LJ&index=10)\n", - "- 13th September 2022 - [Constructing HEP vectors and analyzing HEP data using Vector](https://indi.to/bPmMc) - [PyHEP 2022 (virtual)](https://indico.cern.ch/event/1150631/) [🎥](https://www.youtube.com/watch?v=4iveMzrbe7s&list=PLKZ9c4ONm-VkohKG-skzEG_gklMaSgaO7&index=15)\n", - "- 20th July 2022 - [Analysis Grand Challenge / HEP Scientific Python Ecosystem](https://indico.cern.ch/event/1151329/timetable/#3-analysis-grand-challenge-hep) - [DANCE/CoDaS@Snowmass 2022 computational and data science software training](https://indico.cern.ch/event/1151329/)\n", - "- 25th April 2022 - [Foundation libraries (uproot, awkward, hist, mplhep)](https://indico.cern.ch/event/1126109/contributions/4780138/) - [IRIS-HEP AGC Tools 2022 Workshop](https://indico.cern.ch/event/1126109/) [🎥](https://www.youtube.com/watch?v=O9KvsDMKOmY)\n", - "- 3rd November 2021 - [Data handling: uproot, awkward & vector](https://indico.cern.ch/event/1076231/contributions/4560398/) - [IRIS-HEP AGC Tools 2021 Workshop](https://indico.cern.ch/event/1076231/) [🎥](https://indico.cern.ch/event/1076231/contributions/4560398/attachments/2338579/4017718/agc_uproot_awk.mp4)\n" - ] - }, - { - "cell_type": "markdown", - "id": "particular-bangkok", - "metadata": {}, - "source": [ - "### Status as of November 17, 2023\n", - "\n", - "First major release of vector is out and the package has reached a stable position. The work is spearheaded by bug reports and feature requests created on GitHub. It can only be improved by your feedback!" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "7ab4764f-b030-4831-9568-e46e47faf40a", - "metadata": {}, - "outputs": [], - "source": [] - } - ], - "metadata": { - "kernelspec": { - "display_name": "Python 3 (ipykernel)", - "language": "python", - "name": "python3" - }, - "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.11.5" - } - }, - "nbformat": 4, - "nbformat_minor": 5 -} diff --git a/docs/usage/structure.md b/docs/usage/structure.md deleted file mode 100644 index 136bb8af..00000000 --- a/docs/usage/structure.md +++ /dev/null @@ -1,11 +0,0 @@ -# Structure of Vector - - - - - - - - - - From 2842fe92eb5bd7030cea3cb485f6cb41633a0a54 Mon Sep 17 00:00:00 2001 From: Jim Pivarski Date: Wed, 18 Dec 2024 11:35:31 -0600 Subject: [PATCH 03/23] switch from ReST to (Myst) Markdown --- README.md | 2 +- docs/conf.py | 9 +++--- docs/index.md | 51 +++++++++++++++++++++++++++++ docs/index.rst | 82 ----------------------------------------------- docs/src/talks.md | 9 ++++++ 5 files changed, 66 insertions(+), 87 deletions(-) create mode 100644 docs/index.md delete mode 100644 docs/index.rst create mode 100644 docs/src/talks.md diff --git a/README.md b/README.md index ea7344f3..4b146106 100644 --- a/README.md +++ b/README.md @@ -59,7 +59,7 @@ development environment. ## Acknowledgements -This library was primarily developed by Saransh Chopra, Jim Pivarski, Henry Schreiner, and Eduardo Rodrigues. +This library was primarily developed by Saransh Chopra, Henry Schreiner, Jim Pivarski, Eduardo Rodrigues, and Jonas Eschle. Support for this work was provided by the National Science Foundation cooperative agreement [OAC-1836650](https://www.nsf.gov/awardsearch/showAward?AWD_ID=1836650) and [PHY-2323298](https://www.nsf.gov/awardsearch/showAward?AWD_ID=2323298) (IRIS-HEP) and [OAC-1450377](https://www.nsf.gov/awardsearch/showAward?AWD_ID=1450377) (DIANA/HEP). Any opinions, findings, conclusions or recommendations expressed in this material are those of the authors and do not necessarily reflect the views of the National Science Foundation. diff --git a/docs/conf.py b/docs/conf.py index c5ebd7e4..f5dab3ad 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -7,6 +7,7 @@ from __future__ import annotations import importlib.metadata +from datetime import datetime # -- Path setup -------------------------------------------------------------- # If extensions (or modules to document with autodoc) are in another directory, @@ -21,10 +22,8 @@ # -- Project information ----------------------------------------------------- project = "Vector" -copyright = ( - "2019-2024, Jonas Eschle, Jim Pivarski, Eduardo Rodrigues, and Henry Schreiner" -) -author = "Jonas Eschle, Jim Pivarski, Eduardo Rodrigues, and Henry Schreiner" +copyright = f"2019\u2012{datetime.now().year}" +author = "Saransh Chopra, Henry Schreiner, Jim Pivarski, Eduardo Rodrigues, and Jonas Eschle" version = importlib.metadata.version("vector") @@ -43,6 +42,8 @@ "sphinx_math_dollar", ] +source_suffix = [".rst", ".md"] + mathjax3_config = { "tex2jax": { "inlineMath": [["\\(", "\\)"]], diff --git a/docs/index.md b/docs/index.md new file mode 100644 index 00000000..69cb9a9e --- /dev/null +++ b/docs/index.md @@ -0,0 +1,51 @@ +![](_images/vector-logo.png) + +[![Actions Status][actions-badge]][actions-link] +[![Documentation Status][rtd-badge]][rtd-link] +[![pre-commit.ci status][pre-commit-badge]][pre-commit-link] +[![codecov percentage][codecov-badge]][codecov-link] +[![GitHub Discussion][github-discussions-badge]][github-discussions-link] +[![Gitter][gitter-badge]][gitter-link] + +[![PyPI platforms][pypi-platforms]][pypi-link] +[![PyPI version][pypi-version]][pypi-link] +[![Conda latest release][conda-version]][conda-link] +[![DOI][zenodo-badge]][zenodo-link] +[![LICENSE][license-badge]][license-link] +[![Scikit-HEP][sk-badge]][sk-link] + +# Overview + +# Installation + +# Getting help + +# Contributing to Vector + +```{toctree} +src/talks.md +``` + +[actions-badge]: https://github.com/scikit-hep/vector/actions/workflows/ci.yml/badge.svg +[actions-link]: https://github.com/scikit-hep/vector/actions +[codecov-badge]: https://codecov.io/gh/scikit-hep/vector/branch/main/graph/badge.svg?token=YBv60ueORQ +[codecov-link]: https://codecov.io/gh/scikit-hep/vector +[conda-version]: https://img.shields.io/conda/vn/conda-forge/vector.svg +[conda-link]: https://github.com/conda-forge/vector-feedstock +[github-discussions-badge]: https://img.shields.io/static/v1?label=Discussions&message=Ask&color=blue&logo=github +[github-discussions-link]: https://github.com/scikit-hep/vector/discussions +[gitter-badge]: https://badges.gitter.im/Scikit-HEP/vector.svg +[gitter-link]: https://gitter.im/Scikit-HEP/vector?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge +[license-badge]: https://img.shields.io/badge/License-BSD_3--Clause-blue.svg +[license-link]: https://opensource.org/licenses/BSD-3-Clause +[pre-commit-badge]: https://results.pre-commit.ci/badge/github/scikit-hep/vector/main.svg +[pre-commit-link]: https://results.pre-commit.ci/repo/github/scikit-hep/vector +[pypi-link]: https://pypi.org/project/vector/ +[pypi-platforms]: https://img.shields.io/pypi/pyversions/vector +[pypi-version]: https://badge.fury.io/py/vector.svg +[rtd-badge]: https://readthedocs.org/projects/vector/badge/?version=latest +[rtd-link]: https://vector.readthedocs.io/en/latest/?badge=latest +[sk-badge]: https://scikit-hep.org/assets/images/Scikit--HEP-Project-blue.svg +[sk-link]: https://scikit-hep.org/ +[zenodo-badge]: https://zenodo.org/badge/DOI/10.5281/zenodo.7054478.svg +[zenodo-link]: https://doi.org/10.5281/zenodo.7054478 diff --git a/docs/index.rst b/docs/index.rst deleted file mode 100644 index 4afa28b3..00000000 --- a/docs/index.rst +++ /dev/null @@ -1,82 +0,0 @@ -.. Vector documentation master file, created by - sphinx-quickstart on Thu Mar 12 15:04:15 2020. - You can adapt this file completely to your liking, but it should at least - contain the root ``toctree`` directive. - -.. image:: _images/vector-logo.png - -|Action status| |Documentation Status| |pre-commit.ci status| |coverage| |GitHub Discussion| |Gitter| - -|PyPI platforms| |PyPI version| |Conda latest releasetatus| |DOI| |License| |Scikit-HEP| - -Overview --------- - -Installation ------------- - -Getting help ------------- - -Contributing to Vector ----------------------- - -Talks about Vector ------------------- - -- 21st October 2024 - `A new SymPy backend for vector: uniting - experimental and theoretical physicists - `__ - `CHEP 2024 - `__ -- 3rd July 2024 - `A new SymPy backend for vector: uniting - experimental and theoretical physicists - `__ - `PyHEP 2024 (virtual) - `__ - `🎥 `__ -- 9th October 2023 - `What’s new with Vector? First major - release is out! `__ - `PyHEP 2023 - (virtual) `__ - `🎥 `__ -- 13th September 2022 - `Constructing HEP vectors and analyzing HEP - data using Vector `__ - `PyHEP 2022 - (virtual) `__ - `🎥 `__ -- 20th July 2022 - `Analysis Grand Challenge / HEP Scientific Python - Ecosystem `__ - - `DANCE/CoDaS@Snowmass 2022 computational and data science software - training `__ -- 25th April 2022 - `Foundation libraries (uproot, awkward, hist, - mplhep) `__ - - `IRIS-HEP AGC Tools 2022 - Workshop `__ - `🎥 `__ -- 3rd November 2021 - `Data handling: uproot, awkward & - vector `__ - - `IRIS-HEP AGC Tools 2021 - Workshop `__ - `🎥 `__ - -.. |Action status| image:: https://github.com/scikit-hep/vector/actions/workflows/ci.yml/badge.svg - :target: https://github.com/scikit-hep/vector/actions -.. |Documentation Status| image:: https://readthedocs.org/projects/vector/badge/?version=latest - :target: https://vector.readthedocs.io/en/latest/?badge=latest -.. |pre-commit.ci status| image:: https://results.pre-commit.ci/badge/github/scikit-hep/vector/main.svg - :target: https://results.pre-commit.ci/repo/github/scikit-hep/vector -.. |GitHub Discussion| image:: https://img.shields.io/static/v1?label=Discussions&message=Ask&color=blue&logo=github - :target: https://github.com/scikit-hep/vector/discussions -.. |Gitter| image:: https://badges.gitter.im/Scikit-HEP/vector.svg - :target: https://gitter.im/Scikit-HEP/vector?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge -.. |PyPI platforms| image:: https://img.shields.io/pypi/pyversions/vector - :target: https://pypi.org/project/vector/ -.. |PyPI version| image:: https://badge.fury.io/py/vector.svg - :target: https://pypi.org/project/vector/ -.. |Conda latest releasetatus| image:: https://img.shields.io/conda/vn/conda-forge/vector.svg - :target: https://github.com/conda-forge/vector-feedstock -.. |DOI| image:: https://zenodo.org/badge/DOI/10.5281/zenodo.7054478.svg - :target: https://doi.org/10.5281/zenodo.7054478 -.. |License| image:: https://img.shields.io/badge/License-BSD_3--Clause-blue.svg - :target: https://opensource.org/licenses/BSD-3-Clause -.. |Scikit-HEP| image:: https://scikit-hep.org/assets/images/Scikit--HEP-Project-blue.svg - :target: https://scikit-hep.org/ -.. |coverage| image:: https://codecov.io/gh/scikit-hep/vector/branch/main/graph/badge.svg?token=YBv60ueORQ - :target: https://codecov.io/gh/scikit-hep/vector diff --git a/docs/src/talks.md b/docs/src/talks.md new file mode 100644 index 00000000..5b1c9bdd --- /dev/null +++ b/docs/src/talks.md @@ -0,0 +1,9 @@ +## Talks about Vector + +- [CHEP 2024](https://indico.cern.ch/event/1338689) (2024-10-21): [A new SymPy backend for vector: uniting experimental and theoretical physicists](https://indi.to/zTs5b) +- [PyHEP 2024](https://indico.cern.ch/event/1384010) (2024-07-03): [🎥](https://www.youtube.com/watch?v=aVPhP_APhqw) [A new SymPy backend for vector: uniting experimental and theoretical physicists](https://indi.to/pfTC6) +- [PyHEP 2023](https://indico.cern.ch/event/1252095) (2023-10-09): [🎥](https://www.youtube.com/watch?v=JHEAb2R3xzE&list=PLKZ9c4ONm-VlAorAG8kR09ZqhMfHiH2LJ&index=10) [What’s new with Vector? First major release is out!](https://indi.to/35ym5) +- [PyHEP 2022](https://indico.cern.ch/event/1150631) (2022-09-13): [🎥](https://www.youtube.com/watch?v=4iveMzrbe7s&list=PLKZ9c4ONm-VkohKG-skzEG_gklMaSgaO7&index=15) [Constructing HEP vectors and analyzing HEP data using Vector](https://indi.to/bPmMc) +- [DANCE/CoDaS@Snowmass 2022](https://indico.cern.ch/event/1151329) (2022-07-20): [Analysis Grand Challenge / HEP Scientific Python Ecosystem](https://indico.cern.ch/event/1151329/timetable/#3-analysis-grand-challenge-hep) +- [IRIS-HEP AGC Tools 2022](https://indico.cern.ch/event/1126109) (2022-04-25): [🎥](https://www.youtube.com/watch?v=O9KvsDMKOmY) [Foundation libraries (Uproot, Awkward, hist, mplhep)](https://indico.cern.ch/event/1126109/contributions/4780138) +- [IRIS-HEP AGC Tools 2021](https://indico.cern.ch/event/1076231) (2021-11-03): [🎥](https://indico.cern.ch/event/1076231/contributions/4560398/attachments/2338579/4017718/agc_uproot_awk.mp4) [Data handling: Uproot, Awkward & Vector](https://indico.cern.ch/event/1076231/contributions/4560398) From 4ad1777bfc7f1757df05017a6c496dfde4e23829 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Wed, 18 Dec 2024 17:36:27 +0000 Subject: [PATCH 04/23] style: pre-commit fixes --- docs/conf.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/docs/conf.py b/docs/conf.py index f5dab3ad..edb9f1c9 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -23,7 +23,9 @@ project = "Vector" copyright = f"2019\u2012{datetime.now().year}" -author = "Saransh Chopra, Henry Schreiner, Jim Pivarski, Eduardo Rodrigues, and Jonas Eschle" +author = ( + "Saransh Chopra, Henry Schreiner, Jim Pivarski, Eduardo Rodrigues, and Jonas Eschle" +) version = importlib.metadata.version("vector") From 2fc82ac200dbc850b421176819e1c61ce7c17f7b Mon Sep 17 00:00:00 2001 From: Jim Pivarski Date: Wed, 18 Dec 2024 11:36:54 -0600 Subject: [PATCH 05/23] skip test of non-existent notebook --- tests/test_notebooks.py | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/test_notebooks.py b/tests/test_notebooks.py index f06a4d42..5f2c3aa1 100644 --- a/tests/test_notebooks.py +++ b/tests/test_notebooks.py @@ -17,6 +17,7 @@ def common_kwargs(tmpdir): } +@pytest.mark.skip(reason="notebook was removed; will likely be recreated") def test_intro(common_kwargs): execution_dir = Path.cwd() / "docs" / "usage" pm.execute_notebook(execution_dir / "intro.ipynb", **common_kwargs) From bab27203c5dab1daf2cd811571a073a5f2f4bb23 Mon Sep 17 00:00:00 2001 From: Jim Pivarski Date: Wed, 18 Dec 2024 13:24:07 -0600 Subject: [PATCH 06/23] simplified the Overview page --- docs/_images/coordinate-systems.png | Bin 0 -> 97856 bytes docs/_images/coordinate-systems.svg | 323 ++++++++++++++++++++++++++++ docs/index.md | 56 ++++- 3 files changed, 375 insertions(+), 4 deletions(-) create mode 100644 docs/_images/coordinate-systems.png create mode 100644 docs/_images/coordinate-systems.svg diff --git a/docs/_images/coordinate-systems.png b/docs/_images/coordinate-systems.png new file mode 100644 index 0000000000000000000000000000000000000000..5aed54a459e4169657e02234949248ea55a36f06 GIT binary patch literal 97856 zcmX_I2RN1O|34_BA}f`V63R$8_DBiYLT2_jva@9?h3rurvmz=hD=VYy9DA?G2-$n{ z|33Bp{;um>?|X61^E~%`f5&HhPr>(*q*FB%I;Cyw0c;f zJ*;bMZJ%emIh2*78(027L7L-zKl__^K_5ylYimaFFED3g7lvoH8<|aC*q9|QEB-$8 z68mku(}rE%Ra9ghYu`><7bau+`_pBNp*fp$atiOR->LD-pXs$Hg~H1&qy!;9vfJhu zi^Rb(+(Ie8eHvDO);0UzhelswldUoKC6S^0)BSdhH~#*Xatp^fj7zaMmF(-#x2qv5eehPPjvHvcDLRXNMMvPA>bU*6|{P(LJ?n2S>$A3)Jw<-=(r2k%5 z@&$I3W-2|~Kt;)%`tK5gEHDy;J~L|DwXfoXkus;jTI^^d_d6Miz59b$|q-OBG z{JXXiQ_NgVR)CKh;p5v^F@IOml@mXB+bi*2pzdbSk|5Y zHiyy#w}3x>w&rn(>6~Q9d<<^~?Z22Hp}+{#;S5l(J1S#%{iI2c-~RVl6YOXOJUb#E zR9ywVGWP?NPWU8!p2Ytidg2s1@Z0@TQIuR^) z@%n#p#$|$8t>LeU2*$C6C_Q=i@!9__nEV6hL2#_I-Q*~obid%_gH&5h#*Xl6+)bcAJ#?dH#QphvG`VGauowU>(eNcaT zH7r#BR9zXJs|3&*X?!pt}V&kX0<{Q;U!>(t)BDl-YI5@0!HSAx4LE41c zQ_be}9SRPP29<~HKUDbfzel2I!9}lVsC~tcCrK}*Q!Q~KzwlG7Gs1)R-~I$&#t6`t z5|5SVJ9YS&>d#%f78C3L-zJn7m#gMG?TB5Zo3N9jm=qu9gqTpt$p4qEQFaYDLV_85 z^q-@|ark>Ce*BbBTSJVu|9?pmAdH?5v45~YKORzZ+3o5}cegJrYy|&3asUImg|O=W zwh+;UC5#xQk?;x&TzqJa>A&>2(uU*ppWBK4d=r(XM=G1(L>@mY)OPfx>i&P3A{mM$ z#c#vU=oMey%}kRaK(PaNH1v}4kZw~bI8)k{%#_XW`6;Wy<(Q454ysNEVa zBhi(QlS1bh$PA>?Psi&pai28Acg2ie?d^S&p7t6Q=RDQ$7TK3MJ{P$GY>j12X?f%Q z%j`{Wdr+c&q&1l}*J>J(Qo-4jA0!)qF8o<@afdP=?WgXit@SLrt%%Oh^58Cma4>QW z%aZbnDvOmT8lTy2CnfR}PY8XcHH_ZkT1lA{I=S?MnQ1f(8&n{u9X+JA)F4B{p!qPR^k4mD=53yN@K zqw-#dq=St?Up;PbZI`vJ+ut~skooN&t?)Aq(%2uH33(UOd<6&{syUQeuob^pDz+VU_vCk;ILfJ3<&eCLafw)*y%@1(*2-z$C`7E3gyJ9ygfCVuT` znC$nC!SKoK*@YN(NW$RzF4IZArw)jQR5A-+;oFZZbkPWh7dB42OTNU05pfZ6;VH9t z`5gW5bJ?LRKI?ZbeA322kl8W}D_kSx6+Ccq#|{4uYVl9BKWB;Lk8%w3c3d0LBWz(f0A+>vQ|Agn4fj1HgF8`ij{1%<7vwO47f z41ebachmG^=14s2RsEW3ysr#P`x(9G)JiE0&D(>y0;x`&T0N}xW^f;MNE+p8?6!^9 zp|1M)+3=(183#e8x!>&m6ycK#3!lgktl?~m5g^$isQP}2a_`ehj{YZ=o}UoDKSm>U zEijflT%malTD{6w&$SNM&FoK9o?8lb|BTf+Q$@LDh{x5a^--Pq!X;Pwncuk!w*gSe z3YuZCHNFI6QsLMMNs7276`sQMKan_<7j8ZIyE#8ZCHTnytT>E5yl|0VKIBAPj)Z;=kxH%uS31b zNGBz6!t^ng(iv`wQp}~uuP9mQ>uzf=0*t0poB5FVX~%qgzDD|XQ3XZtiJdcJd<|U3 z-s*712*@EBBkU}Bw<*pPg%NZ)Ddpz|t!v3n$kqZwOKT1O3c5BjVL&qmJM@i9>{k)g6y&QU!%KPL10)zXWec})ghWs7v4oOdq zoHLNmg~ksK)-3xs+ch#VUCFsHMq9k?&+ih!@Ga#?yCnaRZ~UOV(cSrw?boD6qXX9& zO^dyHataaxi~#ixLzQDE6Vsvty*828OZ!n=W{u|MF^8nC@RSjpSj~N}tHv>ZjzsZf z|IC(2>#dPCI;4B8>JW;IYnP0(rhIKn;V4 zHEa;HbqE;F2Y@E^forT};cu0e48SJ8%x;Z*#G-CX8;lByie~L8;u{NtN9KHtUMqN+$*#IJ`KNDwjjRtjU$UPB#eU9JI2_GA zkSueu;w}ZnDo^1V^!|-1c1x`{>6~U#($cFr_TC)h+B!NH+i&gL1h(xDm`3o6xYm*i zI?w+7{L@>ygyqDr`638PJn0jZ_X!*D=KFU^!ZR0cOG`gL9%zcXI{4X`AiR4^BDFDs zG1IWxCpI>ACt`E1JMiGZ%f!@Flm!FbmRd_Re7(fT?GwPLsLMQs7tj@#2JjE?SgdZL*`_8~3Y(?6M7`h`A4JQ-hj`U+=UFa@F1ZL%yvyW>(eCfxhwQ*MtYM$)Slx8Cm*&;PKlX>G!uRT05Rrijuv$NA{l5T7^wiIAPx2;>2DFOo)oh9GbbH>$1aq;;a zxGPH>ZupsAQ$LaZ@f~BFo+F8{uyFDv2tMZl)kcT#vfeVJQ3>!Cs<+w*SILK@jfUTQ zI$77X3m=(UZDh1}R+N^2Q+jQkX8vY^k%{SAEA9o}F{u}+w~tKH%a^Ad9UZS*K7%z$UmbfgDl zrFDzi%tgIDJ=|tZ4Q8_$5VLG%V6MYJ@oD~<`x!cr{6d~)0aS;izrR7SRfh0JC)R1545!QBS`54LR%9BCx!OV z988ollnjjyIc8PJS=wNA60qVZuYhP?hh}uU7*%Aff8K0hG@SY8NvkOC!(Q^J&t@1y zyi526qv6s_aabP5DOmygp9>N+5b#T*70o!DGY>DYi@+4X*DhIqHv<%^pDy*{G;h)s z^|pR+V5t5 zOwhKJBPaf54D%FLN1#f)8B@*>B3s#S=$l;f(}QDtpy#7HRz#zP0ahK0>h?yTYkWI532(yy^XQ$Rw)Lg!qrp*aGO$`|K+hXjx*&xji->3D}Jcm?Xx= zQXfG*M!TsQIL}` zeUyyPZi}Jg#_Y^~7%MAl^s86(v25zHDk^Ts8O)jGhQ|Yf4=T;bt!YHpKraVTEGnpE zz#%DQ^p75J+`4lvCvP2v!J|-6kdW${vNA>0;@-6`l+=v*^OZ~@8rsJ+P+KT3;y4N1 z$rhDZK_+>di7)F+->7RlcoNYL?igcY{57t#QNgu4sLyUZ&T@i8@0!Lfc#Ml1z4?nQ zf{JR2=R%?6rMJZEyu*rkvT>Du4kO9=S zC}j(bx_{i`vT}&*AX&QU(%yU^{<4|8h1iufQ^MNTuyC3ndwqQa3g{nd`M!!tM$ zJrXX>Jn-q$r_%K{(NVIyP&{RVu|WZO6w3sC;;ZK};rIBlEjwJvvqPCoJ zo)&SvkxIXd@~coEj3c)zG@;bFRz_%@_hI$JitDpaD9)!ZsNTrK*LSyY@rb0 z8Fjvs=DG)u%@Apa$+h7{M8%J& zOeuqWMWkrn!srNcdO0tm#`~$UzF0na=s@m zEln@(L7mq>?|S`?mX1zyXWG3(!_*I@rSU)?8U5bg4UA4qq{FQ!%hzt-*U;#l-Tm~5 z{doP{xpQ~Iaw^%`*>$~CjM<5_85flKVV`YHFzSB&Q2i#{Ca&uo7RgYMq}UFBarpUU z26?THIJK8Cga-&BrSK8D&}qe%J{dGfrnm3lP&&&CEK;7lNVKmSd>|_uHnz84zI++Y%gf0LYuXG^ zx-cb^iNvoo#+9Wio%0(+hoq{L#s!UJ)sY7e9@OReY;v$FC&}vR(OX(t*45Qwzco!ErgfrQMZ$Jt@2tc@$MFGx zzi|lzZSAIPox+{Y2%jm5EjWPP;Xa9~-Bx?Tq~+g<_L#nGoslOq$u}DGb#&$=8m~r( zb(st!6%;|;b#+o=m(I$`$tkAZN=9l<@ABCi01$`XHy(b;?p)v9-94I_ueOI;YO=L3 znEw8KRCKhYqT(4UR>koM-vdyndULk6E5;7PZ~Cl;OifKi!pb5pi3f#+nXgSXAFRby zPj$S#d+nU3V9dNLiirsiw{VQrc@-=hv$Z&E5k7gLW0uE##i*n<#_syfo9(DXu_um& zwzm#e?za5+VYN0>aP(`{ePKGz&~A&~BGvl~USFmPV@rE`Nz~PQ0-m{$Jww-0y}A~V z!(9B6m1oD3^3blV{*up*@o}|Qwsz;N*l8Nh6^Y}CkehoE%LDmo^-lc~yu7^lZE=Z- z)_%!Peq(QVx8xKR_4tODIn4+RFJ(#`T811Nx{bO(hZ8%lPTV`XsbAi6d_bil);YVY za%;El_+Zp+%r@fI-iP{z27%!jIK`ZdjErXYF|YO3n7t~19fSMJ)ng0$J_oCfhqlPC zX{zIl)BAAIL*973%1Frturlv|57mf-RPRK6$f5a~N|E=z>ld5B@1KoppVGgQDnOEJ zscc5=!GjYuP#th1Wlqh_&2Qhl@q^011CRIB;3nFl%?#Ss4I1o+>}<2&IIP#!poO0I zX0M*>p!vq1-jHWRXV+j+!EQgF1YW%t{>9$Tv+IQw|WGP8JId>bxwkI_3;+;eNi@OaY@g-a5Sff(X`qc17h zuXNzP^D7Xd&W8Xw{+-nbU)=6Ys*0o}KGKH;t9MCZ-j-<@W|0eUMu^ z@sehlPhzEpz%KCmsG{{%jN!q=`9lfck})687~3OQ{_Zeg?cccW_i-lZpXWBu*EN9(M^&fOGfv|(rAn=WuhNQ^LO|7#?j?L^iXXG!J( zD=RDa$uL1(n=}^;rQ-3?cJ-6>RzW;N;oZH?G^$bfo1Vwqdz8&!!Sgr+kB{~1N8>~i zUbq~Jm?qEQ1tub)4E9ySD&vAUPy z5J2iTiFf5j-<~Q5iDXX^R@6p*U7@6Kiyu5$;}o#MH?ufgQs_7>-0Y(u<(2C^eAog#pJ~qCrbFR3Vq@ZLIE~dPt9^W51BZ)_ z_Bt8E&cShbdQ?F{;n0^4s!N62a>L|mWJ-#%y!=biI|?Pv1>Mx=ZyIFRDL#Go%enZq zj2a3axar3ald&pqYHDh};kL=uq9J<|6DD9jM{FUR;g`h!r272KR7urrcjC2`RI;>W zgFm6Jz50BHe&ESI&Gu|(TKx|bUf>aHKhX#S^&}ozI=q-loO4k2o0Uo(iI2`OaoH}(1NIV?Uouj&i z8h--dL6fWQEAC=9l(#7?fA|v+?M%g}D1TafCmm8QL`#vnXITj9LtR6|m!Ybo-e*eAJsFXMBbt@9AvG2ve;w4Sd`xSC zUsNQBDKB5XJW#(b{bsS3hTn?yTgPLi&fl$x4{bbmR*a9S8*+8gu@GP~GK46kRu&&N z7tJX;I5?o_MP0M&U6nNWvLSO-Af^2?LQ<1v3)^p5-wn{W062HlS(SRYVA0BIzOqYO zNZflfKADY&D)=^rhV*~D*EB0npfk8+(YRvke*DMZ zPM+sB{}Ia-VhN4xsOvC<=EekQ6K8h3#5^{xOYD3*TY7x7Pe7TqHQSvTalG#N>-+N@ zp8XZ=g{nxO}ykdm`{OCy@Lqj0#=1ShaL#{PU+bvezB)| z%dcX&D)DY08Nb!~!Fs#X{$dFcI{Q9#4+Z+%F*#z7Qv!+o`OQT_RsIdQ+Fk6@9^mLdPrXQN z7v*p@f-VaMEnM?ckEHNNo!Z5-wez2X>ht+gC)3*68bTpJC8Za0k34Va6$LGqprgdz z@CYb|o28hls;U^UOoRx4#=Ev%eVlyqG!2p*pob5Bv89757)s0kQrPMD<6+wpyrK$J zH?-1HU@6x*InAJeY|Qt!SGV1OA0yf|KmqaG#`vjTYb2mhk^#3vFq#<#6P=pcUVXHA z^VI3nWs6^i;q$+bomrWgSL&!#ki)qTES0}suNGveS_DCQd5L9d;af zr}*s6xmK36#m2=o0{r^{IvEa>*$X@-C;IiANMWkRXi(}fdEn5Sm75E|sKM}M^-t)sLOusV zU=mzIqq}{*x-*pO>gy2>q^YU7^3$*A;hj5oLK0WMNX_GzF94NliMu(IV4Z8cI#Itc zR-H<8$^DILMYpnO7;IB+XIN%#WK2vg#6$}saRJPgwY9x5{Kb~Q%i2G${0}=qTT+sr7Rgsk)2XKjAU0uBr6^|!& zxY4cWwOa25Af8^>F}<_B8GuZ@gzqi;s@)6)iWeskX{QXAeZGn`T_x8_hS(~HJ?$aw zQfqgfp#%`ddpbHgHB1`?1-v!e_o{pXfDOHXT8dvKm3NDWgM-5q3LFHhnz}kcUvcoh z0k9L+{w8K-<`dL(z!gacYDq3jNTi0*3G!O?eBg>uFV6%0I|SM(zdSGPpWdwVkf$c~ zFV7*;jmvzW!^W&CY&WdQ4AL0k1~-;eU7=1nZuV-W_7ER~ka!P*E=0}%?)+r6{`_FI zuLPs_1_h{nOdK2`>dM0P$GiQXAIrG9PU`Ccg>OoWxOJ)~T~4V#R~~lfV`j<(=ndwZ ze|qTw%O6(^_FOW#`{Io8Xt|5n?o1R+D(TmVZ9z~*ME^};}YSX)$F+>GxL4&83E;RTt0 z*e;k9J`k&}BHlap9_{GQA9X-|q0( z5zXUl`?0Dd#~*B8H@Xy#Ou@yWg5DM@!ItL+rkEp~2O*1Q)MFD2l!F&=xQN&^$1=p? zOz%RUY4KU)bPJmjQx~i6Wn2vJN{)IHP+Q;QBjZ=G{`To0#juT&xmj7Ut7j-)xq0*E zn;&LQ=KI?VgS9V6>D-SGw+V(IRs#TAaQP77S0xgVX0qaez`hC*E|}oTZ&FA6np3Ci zk#*o!t_s!M($Q8)b-u%-465p2`ZGH%=jcO^(W<;VFk6^Thc2Y^qZUOCH1b^+bv1MKnjtg~ZL_knK4xd1 z=@Jd5hY(Y(ktu|9_`3T$5env~&RA~r4oTos{^w*dQ}0FNvMS+YVzFDg=1Q?tP|Lj3OwP)2i0OWM7NOAy7M zL4NapLdzPM2ul0n&yQeaSczAd= z=DLaU`iG}xbwQK7-5CqLSk1s7ym8VPItSiK`E-}fZt{J2I*?Pu`~d(xHeOCjPC>zRW&E4XSe5u2d6T=74PleMM>D=c&|~z1?x#!Nd1wlDeR?8K z;dP@++)azxA`iVK0YHRci?vlbDc!|VSYw_6Rf~>^VY_i-Gfy3j295)m8Su+)mK;>| z0$3hY7C;|11(XRjz?ODEq&$!t41P73knm%mBd%(L#lT~Zg{xwLHwPUPg!bBb{Ka+{ zfQzVhvDG=EvzHLX3uzO{$*lkt6O$*pB9tY`YXq)1i8Sl>CCE3xDL|`am6f-yVZhaAW@RM=y%IzpCe}L!l^*=|Usq)Uw=av%XBQsq zD*za$AUTbUMcSHTD*ZE6i#06oC@Lz}WDFecZ(kD?rOWH5`y6Fc`@?@T(IoL=h3n!w zKsnIgfSwcXWZb2pp_y29mz9&7du@&KU5iOADpk5`t$vYC1a45&Ttr+Ib#UKsJ|Q-? z4%8^rn|I7n3NTsfxb~;-)#16>zS9BV(|}oi??Z0x?;dp(Qd#EoLlYn{Dk^7%1RN%$ z;QZgee-Gz{cVA6S5(*@_P`N8`N08z0cTSo1d)B)URgryI@`6YZ-(Ovc+sFH;eGh{(Lp$2>4t#7YiQMk z3;D3XCh+oCJu306+Y*MUMWOk@hys11@kCwl(T^y2BG_0N9OxdF3D~IAR22}I5BG|{ zYCLdo;4#RH+t}EMG+5UKunrgnbU)^+S8IJu6~60sP!_IKJ!fNzAEX}FvTLL`1J4DN zCt!nddWlm+Bms^n3aaq^N}j7%p8??Z*!&}HW%cRU-TONRbJW>7G^BfLZ}uv}fXZFw z4{YZ-Y+q!3QG`+MG3sv)lMT@DC?69Ldo{O$Zd7kuGTIP8LIsSxesUE-lMtd8fET!p zI1oXnwc0vB^rV?&w@b(i;XNVwxJ1GBu`SSDNZfPN)9a2$7>`y0Sq%+An=m|DJD;JF zx^y$X2XMv2I>UtJJX$|4B)_u?$$lIsP> zr0$#$wzB(XVt?E4u0|3ITlRy#? zIR|;2fhIejTanxBO4)_@7Ro;kYm7>skqbvn3bp3a$*HI`&TkSbdS;KA=6v{Y-6-Kt zLm1u14*yzyh`d0o4r9k=Hbbq4DBSahM(1CKyt?>oaKYJ!jxk@#3BWjJ^jBw=3Yxf#pd< zz=Jvh=NAFos$|al@Yh-2m22iP*HnJLerRV5o3Jt4`3#Ctq35=pW{z(C803dQvX-R0 z74W@4;CtNW7(>FUU#|4u9;m9`F*j#{(#y=kV!7mV;SU@&NLWNG=P5s)r=q&+;^LC_ zoe8KL^|^DqRFzN)`*I!zHcnmvg28;s@)3KQY|F&N1ip`o?jD2iVo`Tfd%L~k)IqGe zvN2+M_#Pj69q*4_gUq^?;{J5m_jo^S2q6y#+rGzwC8Mr%0KleS(AkZb&7{Ck&Z50< zB0v=U$BhhbkHMrX+V$>Dy$MBlx+RXtW*(qR3+T6qLA%?V=X37!C9UuB9epZ~!mzRz zcncNBRZAv`zYq|St-y52I>_sfr`AD9urmK7DncF#4Vj~_pVUJ^%=md9?S)X!E_nGa4} zGZQ`L*m48@LhJYZ^m*_sK*XH}O_$IJc#_!GfGJ9B9fw9xJt_&TY{US%c9=ptRA_M) z1!&6BA+Ht0OF#ZnN==jbPlj&7VAus@O5o|(5mDHX-kj2SmA~&mf6eH00I0iAh-EA- zKT6yo7!xV>AidX5#&`<{0f2Xb-zwHuz6%jb5=|N#8{IaC$)iM|f=__nglP3}51Cg6 zqTe0pVO+;qz-9oMRnoQDj;lU+4(?xpMf;_y?aJk-*RLC3nBfef*fVe7+pU zxxlDW)zce!l&o9%qOrtwSO!`s5M0GXfiOrQK(a!v3l|{WlcTdOA&%aF&5{oxTT`Ox z3=wSmlL_G~2-N^}J|CVE6inI`uftuK;sD3+Di2S7^SYUt*$UWg4iGB$0V^#G7UGSy zRv`}OE$_Xe&Ba|Mpwb|{#8-N5^MWZ@wV7k@07L}s@~4O9-bt2)x-{^MX?Y9v#(hV_ zYi}e!Dbe^IHz|~!o*s$RST6uZpfiIvd3gTO^z`(RWf-YoITt(oTHL&SDVwXb^vUqa zM~ClZiQZ>qAX|ycZWWXO31N4z-KPQgk6TxFG>FIvN;s5n^B$s-9hrh88BsR=^z;z* zaInwOdMYBi1B{h3HooFE<}HZ4z+Xyo>C-{XBjlB{)XjS3CZ5pGzq6VoR4(g@srVj6 zeVWXa{2-0pySGpE<;8hh2n*WqDgdxC(AKGdOG5}8o*SWkeQ-W1qqnbbLWnGUGBPUa z8%UL4^j#AaEK!=-h3>gLhUNr5mgl`_JvBWY1bM0A)k%_$ms&mxTCk{ND zBCpuK%wmIdKs1d;M&BfWx38hMq(Z+!ocaPY63~Hud5-O0Dj9J+4GSr`b?>{DEz})l z2?nNLlYuqoN65Y_fip)PN>N6%)#m3$6jSh8xGOtEm=3uM+~wSf+Kv4KJjO6FJi->+Lk z2qAp-AXwv@>=bHXwKN7uWS*>?hur0eHx?R@|^dY0lTLNr-C#a}XNlv1D_D zh1Y=ZDq?w`gXD3%3S%k9nrAkHfrwm0B;mL?bxqCR_K4tmYiFF`*ua`8>IY7{!u7_z zaQa`M-@@2H&ghKC;b#BgLrd_*svilk5rECMFPDsl5^4_!@H1Q&mmv zJA^!ePoC%}x8^p?AifIyIW8&__Kg+2Q8 zQnX-M#{4q}3OU`5zLat96~lKtmwsX%EF{fM!5Mzgmn78W#$$K4o>U<-6br zzG;mgUh5Z8uO05?>SLd*87QU`Ff4_X8=>%8uxG!4@Ye|D0U2UqmrcKZIK*JD0E!tR zeZg484HPgfuf4fU{jNCYvNw9pNE4aezx4RU@ST9CV1@&Z_-Xe3R#aQh3hQlPo|!2g z?4T0iC7KA*vxw$v2ldaJgF<~2qJcJrQ41th!GxK(?k8LN;nOE30Rfs74TYSKAFr^m zyuT}*K$}Z7TIygLqaKLo1BgN0;HO8_SJ9=?XRkQ4@T*AQTeKyS)ZFylRRAs47I|HQ zZVUBK_>vYDBi{w z0JaN-x?yK^GEuK1H8OJC-VlxmYV$z3i*?Ng2iQSSv)S0$Ps#2{Ny0F|MMPGE{&Qps zq98+Vl4rxk)UiMijzsB{9>Vy;G^iib{zR7^6(1ZyK$mU*^u&wjvy48rUdcI~C}^MJ zo3j=s__GPR@-VfvswxH8i);#UT(+(>jhU%Fe+*B@LAnF-9_|SYI6)v{UuAt7=7uQW z;c(vspYyyg{=zg74miK7yPHn`GRDG!=z*8D_Q`@@LARkAK^MXInm(F8{R-ju0|Nto zl*ceeQcw`hZ`}tPp`4G;E!c=;O|qknZWRmQwVZ}kNr-;rJbNFoN-ZZ8jcK3Q7k3aJb`8^ z59lA6HAVq}YgKljAo)T?RS1CwZp7hnTT|0zE-o^_sYuClcS{0h=pfG|JG25G^RkMmmK-iIX?<~^A=2;Q&V{HMjJ~%v_@C^(h!CPRh($H)# zia1{%uOJS4`BJTbRX_LZ*O6)&D`5IiYJf+N&dq0lCZhw@7^XRlVAH2&W@6&wW#QP$ zX5WP%+!mB`)3zjG1ZUkI4+{en>I6nO@`?eCPWrrlkBM(JNb^Df6}i#$jc*GIx+F-2 z!FD)r;Ewm`>#`1X1R^qeBS8D$g(0Jog}%o=0Cp5@Y&ZefO(B5>;}yv%U*+$g%!$na zJlnBB9{JNMi&)*){}dFq(Yr9-PM6cngC-=ShhjlmI-bL*pOuqCx}y(tk7$2;`5Ft$ zb5PVC9lm!CMv$^`E#V6?hCiu}!+l|C!%VEKF9r)O&>+%bh85$v{Yj`;`9us13y#b{ z^;;{>^UfKZ(G~6gpqeJ~^?X7A9{@KgcJw|iclV-@B=7~8GCOyBeS;<4`8Q!VB*+}fQ3Xr`32^OB1=n!#4f3%i5@c9B33C_?-AI1^A;KyQxwsgy2~6& zPo{}zI+8)~Ed*a@(eV2~T4!B}nQ}pA*vNZm9lujwSGPk|uy@!8Wa0Xa8}EyXVqtvD z*F+NrqkviLhXljETOdr{_c{ zS&&rpi>uBc`_|(CJgzW;>~{@FEByF%76UtQg6R-oFfxjYp~v{1fEU3M8eesv9W2cB zDLJuXyMEu$1~b(Z1(ms@+Sga()GOISQEdijK=5r+*HbGupn$qC`s`c*j)nqp-0-pB zg(#6^;aB;Uhk|+$Fs<>U$g&&OLK>7)S~_s-QX8-cmE?%uMm&WX)irHJ3AE27yK$_I~blinuLc0#mbMgX~Q&qq_gaH-f`-*EB9I<}=l0sks;6fmiV=SLVB9+XGe3P4@{I^^$UxhF{DUo%oQmoh zR#jg=$Lz)#IO3gql4F4{PTlp%6l}aot3|y8zGv6mQ`8Sqj^g(OX#`KO$q6@K*4mBY+{YvL5c+ z)BJB1Kt>KrZ1b2tQ$QQBh8?1?N<_I3&X3h}b>#s>!-dl`GWKqwq?v^Z3JPfTKWk}e zb%Rv@)xf@{sATUiEP*n9*yy%2(hOcbgf+C26N)*puE zs1U8+8B|(_oAA4b$}Ik}Rt9IPcK<#K%!QbPlV_wxsM}x*??NdD#&-gLtO6Sar3{c- zno>SYy@9f~o~KG+sD|uaqo%Kw&>+3>s*^-K&c1w@4#AF@Ld8Z%M5mSQd0KE$krVw*&vjl zkhxf>rr)N6q$Inn8Xdmo2+oT^ZF`EtwV^N-4DcnG570l-wDJt_8XcXS=D=|Jd-W`p z0f3JO-E`2p1|YDiIN66TWmJ#)&{iVnp#?F=QlxOT}*8l7`bE(GgHW* z7SLJPu8A?iH=jPejE|2GlI=s<5cDU25s+Bia5f-e28Dz;iSk9=e~&2MiKpS){^Y-K z^P2_M{ah$$vajOhWIG--j62c?hK8O&MjpejF*Ab!`3xG^h?EE0`31H8WR>L);=1qn6ke+lDeO=UD}Gddi5$nT+91qX?6Kuj%CDz&r0>U zprN5wcD)X!Z~A`26h_6wq`3u#YWUyw+uCxCRr3gJ0ck0%mXc|x5+1WjH}wG}`buBh z;qBbcJ9Xu-bASH)`CT+fBN5RvJbnK$E0PhI)_OQamTWKB^05;h{3I z^`esH79qY8K<;FjkP*j&57L?{%nw63OFDd1IFsGV6}Ygt$U=R}IA6PTDq6vB&atVg z>K0rNTypCnqq}VN$d_6c7tJ3(js(%fSRm1yyM$a}`*nups7#VJ>>QIK+osR>p-dyi zO&CkDw6?y>CXK;l#7+}m`EK`CZBDrKwDhOY$u_w_C%|&W_MEm6Q`1 zRF#MX*Iipc;E!^x5I1Q~7+%b%t~Qhy>*yed#Zd^ykvsgkn5N7bj3uW?kL5*+E9wTw zU8gqj@}j>jPb=LMsn)O~7?a(qJdmx)0dUm}5~c0au*uzg7;z1&{e^mypRbzQ^4nQN zPDv@*DfCr=ZVtj)U%#dS6vNC$W%9(UCL&a%j2R;-)t7U-5~6@=?#K0jAR5*fl8Vt= z*LLwiX}re9X4(06U}Y((`2O`ehStiteh*2I>awzh^wL`=F?Y~~h6 z$CBhTjR~$zMaPp+2ydgF%Mel6^C>;-4%?9Ad>+gD(y5cr_8ayQYfLaG;4tv;JNs*E zcJ33g6k!QNkXV5lK_CP91$sH#&T#1x#?ettCYU&%w>2T-u(=7v%tOV5AFEbhGYV&& z2j}?qKJohp+FNE2U#bu>&{x+lm1uJU6a$3zn^~8NifZT32fQ_q)S00@LE0g<7;v9k zaZ1GbHfJv~_#vC#a2{_?i5~Cm{UD(1r14zVBOo?^qkt{h(RlFSKIq1m$!lx`2)fNf z&@3Y)BqV#2X!Dq~v^2<*$_0lGhy9;hWaEW~hIWjNwL{Er z+I>OJa${?Ymxt$yd5NUr{?iOgbs3^792m)fvHr-!OBDR-8CN}91IXvYy64QStoHUC z+}-1m>9>%O=GIno6O*SsJr54cLW&n9T>ivX?YTCy#6e{E-$n)2`j6T*S{46jCCpDL zB9IUeA&#t54En4l?@e6VH7hhR3L~6hWOsrJqcw;rkl{&1C8b}Fg`m82REWaiMJFeV z&y<0njohWVSuua~L}B4~iSxIno@z*S)zqNCX@W1xAngux&+hH`8_1YedO9J-eKpXQ3QR_^__&|5s%dbhm1e0F)c(MCYs&`?E2MyB*gM^fsUca2IInaK+{+<^8> zzZ)_{`Im%}l@EL*JO__5;1;>WdaSKNaRH%&x){a0q(``TDoSh$I~3SWSr5H2And?M9dR02;bP?kW! zBz7e6re^kXUkFy5g4_GN7A4x4Pp9}?Q~@wHi1u$rkH0;!hypxQ{CkGlgmi=IxnR$< zl}wO^n*1w#w~Gvo9$*<{jScEs3P+GjN?m?gBLBJQ z#_Vj)yA$M0p|`Ru6S`+Fw=u(UWNo7^Ki{_g02bLSd4LcHn>jVd+t_#Ty_BOPA3mk- z?PnJ&ndTkKX8-)b&)}eebmUpGNXQVkb|ya^rK2F3{Z#D}MQQV_Pyl%Y@7{Nvx(KZ1 zmOR^6gS>B@#1wAj@pgSQugvNdgL-$_9iN%D3e$s!e-H0En4MO|wDeKrlG!O4mOZ__ zon2j$V19xuA`^H*G47__An&NN`xeUjiislePC$mGsSHuU1vy-R_LcWNME)G1;ilrW zbaZJYCFlK;lIZ1dQaw>>GWic++PSEx2+3azh84=r-rn8^-RDZ6;0p^6LjTjw$+Jw@ z`qX(RDQsl!yvfN}HP(#n*CYfp+h)wLq z(x)h{eyxFWwi`w^r3V{mf{j&cu7Tc_pQ4kaDc2c4z6YCBXxabK^d0b6_U-$(kyH|)NHRi+WD`;e*+nHnR<>j(BZMMK z*)v5qX&9-j>{VvS&aRLmAuIfk>v{jb_w)35p7(hQ_jP^0=QxhzJkHY{Z%*M{Gvl1q z{2AC3&BhVLz~iMlnV|nXG<3_L*VN%-ZF%}a5)u+hS9NJz(ofdB86rina@6R4yqmz# z_&Bc!iZO;MkZmueww)BZ^DlNwo|1Z&`mjg(7(+X_NKPC(YwmbAA+LLKwLo2lHi_k z#EPDL>oZMXuI^HNX@VNb&D}i@JeTjj9$<&}={b*?+q7hz z9;m;Cc%fUOb;l{X**WgSOLa7BhS>0t!znYOpnSeRvfyRw=os5>&&_jfXW``ziHNp< zmq9P_1SCu-p6UsxA0*Ge-jm;}X>Oj@#vSUet#>&5k~4Q>5M)W3!Rg0ozEJT^rJj3G5(Nu-4FAd3b^3zab}H5!Av0H+GKAGC zqG$#LU}0+N53D|3Yk1q%tyiAC3E6bUCh_mnwv#V!BjzOs>ozpa4~j7=Tg8bssJJoS zdm8QRtE=AD)m4WBgttk|d?hvCZnhGamEay7a30Rb>$~*2UNa=WWK$1*B6H#V-tYlO zh!Dm3tw^C0Ow&OMdKVRyJdtGEkf6SP16p|h$O!M>zmFf_xW?dKhwnt>J`%K~LcP}b~-yE)WmD@BY)tkqPSxzA3AgMW?9>lEqVL?X?DCRMJ*&u+!PY| zJfo;Al|`wO%wB3r3QhhfBho7>&txc8F4VvN6l?=<8SrN1FOSwqdav)p!wI@| zEiKw>MbI=q%GW($o|It=NZkcU1zw=CvhK2Q&7PG5S{;AcIFt&B=i_5?N;X!d6eKCh zAUMQKI4%qs5g$a(<0o+#QDh;~0oTyf)+P=XgmQ-u-_sB-;ytv-smX0q%2lf!eGWIv zO@`8eXg)h&31vMx-^jSQ(~geWbU*KjIu;OP-4a^+F`R*;iw8Sa%vV-DV(R9`9Q9EN zIJ({o=4jee$6na>UB5@qvom~S+W{qJ9d%>9&{7^IA5Vi6szYQq|SfuEKqH?%Z*fO+is)B)l7wM`9xCd3&`pqwp*V z6&YqFh+_Sz{2+b@3MGmUA3mTyWXdlOFL~9;s%`up=w`8C!`)@SM?%h!-DOw_|$rtMcaTH!=*j{7j zP~!bqQpVt~dx(9>1Rpxq@yeATd|46@uWvk34Y)VAD!FhI(G&pHLs5EKAh>$u(;{tl zW>`O4V#dRSgrk|SRuF&_GoC~ziZ^*VIMCgxJ_)4*-GXFD$K+?G2|OgBUE9F7O#L`^ zKvMET-`8#FYx*5;I9WNAp1w-G&cfX?9p*nzd7nF9ZnW9aS~y%XF9<1#!j2vM7bCIiAaeJ$kf{ z=!Z}D2051doK%GW}}oV^+U71~`Kqbq#ecM-wCz^ET& zt^%H8RXXChB6J#-@g&e4myC-Au+x8thsG8V~9^kI6+Ba`lA>xsluT>lS(X^X)|sA2KE;C4Kzx0brK8aO8d{)re9aodViu z6DOHvFHuQJvh>8mt()@d9J?i6eZ(idYZQLhT}!}yzf(e+GcDtbWbFf2uU^F=I%{IG zLo-4Qf-}D3$NdI8oD3ZW#>{cwdkUQ$&!kOHJDPea*H5~so9|Ll7eKU}=LNsK6(?z0 zLzOI;F7jcAq?UITzC|SQFm=_*Bok3t`aH2r?Ub~foQM-#C$3)oRa};IH3-!WUZtsuNRT6k$fAw`vvYZig*;`Ntp-9GR~va0KP?sM%oV|SOeP~ zc9Ox5mA+nTJOeLJ++qZ3itp1iEIhX^`TL2;hP=gf(r;DR@iKy2!r8`Z2a~F8^QF0E zAIyfuqijS2j=~S0T2(PuMO{M!>}}OAkEz`skz+9`-qGK$apT5vaY7D@_Wz(K5)RJ3 z-4=VRY>&A=VZQAuTAI`3+hSeEwtSdrDpL13U12}sbpsk;(-m`WBTI|XFBn^v0ob=M zVzdA3tTO@^8oemF$$X_1>vjjJ)`SC+=LT7~2BUBcpC}r;0NN8j(#qWgUdtJTnU#90 ze1iry<)^+X9dGulY&N4-YpU^D5aBvyU>^T+>&sUOy2Js%rNous=H?CnKLnoP9(}8m zipjIC?(UA>-q6Nx?TxC|>T@_oPXotz&=&$KK!K5Ny9XHy6LF1;Q*?w<%E^hrAH(t= z%2XKDhPowwoyIq0#y2cZk6z(&dP|%XLEsBoT3TL{6HRxa<&Z*aM|1iBoCwzuqEP90 zMaqa%HIFzEZ3xVu@=mI-fq!*%6-N?yWmxdzBR<%i+T4yjl|+N_PEG!FDhBhz0%YBQ znLQkL^h-@eLLgZ-H>XT(wRV$nwg=b%zGO;`?F0t)QIJPQrv&SKdn?XYMxvskTB#Si zY+eTDXvCvLhp6}X(>Yo&6}hQo;QoMPT%;wV0F&m7;2bMQ$U}5uFQpf$Vt^>65=Z~6`c;Z)30Zo^efcwe z4Jp&VT}lQD2ORJ3J*tS2Bk1nJ@7>ceG!(qYXCBh)kWpOh)nbv7k}|)rAPW2mhq-$o zeoJOYsP0_^H%)$~g@px#ecO5Npu95FMQ6h4dG@H9^LK3`N7Kkt^0IP-(MJ4_`4&xT zewv}q8Rs-PGcyjB0I}M)C%eh`zbfF2faiSTEF&|ZCuYb4}8{(~=wRiX=+9jSoG+dzPP8b@pBWDn5rj(S! zyUm<=j~=~oS{vva;#EINqhjw~D4phk)+0Dn4D`JEHZrHCe`k6i!$V{-6hT#2#6E6q6+=-J z6&H8s;}ssrI@{ZIi75bKVJlP96SCQ_J|(=+$cz01GHjBwRlGO<+M`_!_V@rTZVR zq`iFEG$CTH!o~0yN`O1nl_)yUUlBnbS}l}e6v%|qGU|-mDFgi1orRi@ZVM)czR!Z7 zgi8qcI8d*r8g^HkA}$a$4&nmP3c&@zVQ+LY&G={M(*l;8_H8ov4h&*2`|47}x@Qk% z20ITj*X`T4@qenu=kkDC1@32V!;I1%#2*CR#a#kquuJjzuXkyoSOOz!g(3>!8Y5-e zs26xG&3KI2lv$H$9Dx$PYuM5i&uhiA&v*MXF$_w|(WM@Gz0agc1TT|>s2tjgJ#i6GC}ivz>gN|2L=Vma$^ds0YD{PYP{jIE0be5%D444w!VN z6i?X|SowHezBm0qEYJVs4J)gw$e>|~Pn*W)oJVW6VEQ1W)*Qr>^ZN35W4IW1TH{p3 zZUjd?1jo^jNZ-FVDzi3YzD5qu zNAkuP5PF-IhA^pTm2YxH{Lg#$Qtw3@x6*dtS(6=^pf!~`h(kHM?1Op-`nHCip7_i6 zJ^p-EBe0V*XQXB97&WX8SRw`yp#UWp!ikED%b&zLv|D&F6>gE=(RXQS8F#RDG39i> zC}`Ym&PLo16tU)^4owWAX9O;6lE31%SCQ4y&5f9&YwPSJA21=I@L#EY-f7pl7#R~C zt*Xnf=U``d_x^o)5-Ko!L;HQFkerZe(0q4%`oyJ{z|b~cP_YBgv+Kj%gb-VGfo;E; z8B&fVD=WQy_YMbAk*g<5`{e&=0T@i7wx0Ss+B8G7M-(!?D-tN#=G52`~w8M6G$~6w6(4;txU=hPhFq_WZP2skQ9v1$9Cx=6lu& z;}H&hyUn0zdFm$*WYXSV5MTgs+1$7Wn!uB5*T2jxGSSg|v%ax?*+*gR`$bqlRJMg2 zTujTb1xFF0&o^Vo!!JN~@lPeS-?HcEN3RDAPeK-J4LnLv@tqW?#gT$J9QYpZ%9ubL zS2VaH#x(rKtoyBx#fUvp6R7AbE%7IPRIwSuJ^L!Rc%e5EEG^#p%T3b7!ymvZ=Q(XrZRf^++SSr1%{LnjY?BOqpk zp`v&e#wWIWP+C-j{KZQ{v#_-|C+>y?faZ}rM5{ln-Skc zuSrR0WvF6vIK3ik>-gNHr53&q#&Y&>=qiEdt*fh>cd3O`7u5K{Lx*Iilp|}+pMbH) zRKih9YsDZ#bg~FB2#mgxmf$C&J_a>g8UCHsPL?@&eQ|ylQOvo!OLD0N=(M-Dclq$% z3ORblF7a^5$_pY&QCb-0rMeeqkmhuA#nKS;^$Vmt;) z7K~1O^Y_9;Gbzy6AOc8GWCPUzVTh7*+~-x}x2lnN;aN^j&bT!h^Jd#b6<^mOauy!8S};WCmOQiI`XY;(K5(9wZ zHja*UlWqt?xQ!4F@c!J;&T~1Som>I*Su6oRU;fd65b)kqbGDM-^v(l0J zJq*4^k$=OR9d{8-J0=(jrns!^rgn)t&?}4~YG*Qm7m;QP3gK9^N$j$4W0+O?`y=F8 zMszWqXU~L;lG`6odDOhli20}=!s)GRt#&>`>4`AXCUFm50+w;svMJhY`sn^>e&5Bi zgdKAMJAC~6;aUggjt*kug7USiz&Ve?7csJx1-%Kf)6@c?T|iSUQjm2TCm#(HQMdv< z{$x(aAA|?j%HzDVgAF1uNu_jhllWp^rBN8XRFEgh`F&)j2LwNF10KdC(7jn zZ>*WDb(+i$ZLAFerAe7vM$m(x-w6Shs0h(yPc5{6{;XtRkZ^fV!Qk!M`pA6u0G26T z(vr7UN7~{&VHJ=zA?ifozxzZ+TVBY7WXaw`UBzMuntx}8T0xwm@&)Ka>e!vvsMSF7 z^2&IjhD*xE9`#+{+zg3~a6_1jd<~ekr*`y(7g+D19p^6nEo^OdTSWs{zEP?gF{R<#FJOhis#4sj)2+S zC+-nH8m308KsW+G>~)O{w~|Ww*w6qJ0nPR0oa-0r^Dn*nA4C6j`knsSgUq8ajq9@B zXtr^1_@@)knrJ?DAzrUD|_7mxm{#7xzAi`)ztlqr*$$;lB6@{Mdhu764L9DWlC zJsaN0$l@xC7cDigc&|zDsw@hr5r~T{uOgfE^z~Iwo}>UQ;PS-YU;m(`4{QQGVF&eH{+(?H zKVelCnNqsMyHl&95VQ7}5+1v@{{7nbfBl4_o_NB-g~PY_>d}yCUA!2#Ui33K{N{f| zg^YDbp?<--GJ$KKtRYC&w(nsTTBymC3biyfbD;q4>+54>WhG^3h!)_q{&?zeJHysY zE;i%{ViBhIuC-X;{18fOYpn*WlF5vu!f&xf+g)OGiGhf5pI=a}!1{;CdX ziag;y4YpLcYu$+O#n`UVUuVRPLO2JE%YR?+f)M*={)D|%gfm|EK{64cpvyT@vOQQ) z!;zP#>rt~+wPOJ|x^Q}B*75qpj9=0?+vo#Cl68M<9X|f>ScG{(T9IHnq!yrnyb6@G zI-b3FL3r$%l@=zbsY+@^EuS&h@ms3q{O&_!`QY8z4uUfdn)>sZCW1H6F|NP4s1rrh+eryx+ya=vr&N~P}x-g zj&t?NQi~+WLyTu<0r8=TPt7mJ99l`Y14Ib~*`?J1KmeFq>caKMXb^$x49!?0;iIN_ zl9eUkf8+RRb7R&`Wp;QT!Ms*g4C-03!z@?)-_S-Su*s>gv9niybHPv$rDg&584y%y zX*@j6IKmLAAX`3+5p&iPuWqz%{P@wJQxvL;ab7F&)oKvyQS4-9-0Sh5D>5B)H4aia z%dIZguS-MvZ12^gpB`Ohp7%I9GCO>#W4EMM(guuZ6?cl~eUH}dthg4?Y0O4j>9!@N z{};{hv6&kY+@i_yH*`%z0Utnl4w@T7-}ift-no6782AH(n2rGw9K(>3_X=;v)AlH}+^X0ifdDOnXf&zs8v*|!GMg;vfi zrbjCZNLo8N@a=cstQ^&Mkxgf0=UAGzUM3 zG&B%hLAuX(E^$Oghl;$&$ua4e6Ch9g{P`5f000&IV1Xa6nB#TW7uO&DuQGcnDVG{@ z#G0M9l-YXPFu&I!Nb$)9={q6`n#j=3xDrxV``-MBY;+~2J-{#^p#2_PEQ=djo4#(p z{%GefC~{U8&qU-v%}1~gG^csHLSDwQoj?s=BS3yf@>7D@@n*C(DA_^w{kZ<%o`XD3 z`0i$M_%_?CSB+=wy}i7?Zx0m4Fdlk^afkUlX1y0N#C26`;E~MyW zp5O4q*CA{=%AsLplrwpW8Vq0`y76&IUqsX? zvwm~?QrYJBX{!s+@0F?e{aXY&JH`@548=Y=nhJDBxcr}s!BOu!y$)85v41YChbDO=rRPA;DTLWA-1O>NccBr|yyncc}|L*$C<>|t)`+To%0i*`VP1u(^7a6&h zdBA7roIY!U-2&8;;2hA4y;#37gEL-KWUw&=pXDOhh%HZ*uiGQwE*J!fgTmrms@S|# zzOlIBGJP$wueknh#mK^9E2Z4IZ&k{U`e@;dcAi-zh*_}?Aa6O zN_y_^-Wu#Ao3di}89gkNFBzcG?25S(o4-E`Rjv^ReuF9MrkR_Ia$u}?`wk8da{;gi zPCT13(^PJ?+GMT3^igEI=@i7#vz{$`avHx8!gN4jb8tZW1U3n#egwPYin0rqO1lX& z7z$4me68?ClAX~9BMn=G$c>ep4KWA*(l+#61bdiKel0S-_U%Ty#II+#|JDdZxo6c4 z0y6#W!|yAH#DG|M11#p~Q8f#T{XhkPg5;vwNIyko3UCJp@25wJTR^y2o_+)E?>hEt zPMsGn&cdqWaN!S>6RmibH!zmE3@_m(^k~UBgf*|13zIF*4OETzC_Sa#(%`fK6ZuBi zB7Gz806tA#ST%tU4sMW=g+=;$51co4X*OB4tirV*9!?W+?=gG6eYIS$PwirzyXA-p zWu6sEo);O>hbS*od$4hY>HF2y*R$=}qbQ*4;qmvmY;}r)@1-Lhc2}=j0!FeQ{4(YM zC{o7dYe?B*21eE<9w>#c^wcZV!5Y~jTK7GQ9YR`+t|%qK=j(olFNF_*P14ZN5RT5C zUmu?K#OE64*e@t(U&-=Dm6elo91c&JxU#4xpss1g-(!y*EWyBWoXO1uNQ{m~q}oe5 zc(}aN3$=NJIJmMXC?N20*hYzZfm9AeW&trE?~r;{O2rX>o^%Vwsg9+kLWPU)QnKw0 zP0&>@-)00u3b4LNX^>@{zMxApLDp9n=r!Tj`*v3_`!TXY4h$hG+}bzb{R^+$9YT`} z9wjNn!8bd+|500ierGepzu;-XeyR)jBt^39v;?{k3NVJ1GKJWi+VX@N_&+MBCC;TNz0ysXuTjTz^?EO-!r8kL0rfp_e8Mtq7B_qCX9S z)f^cNDmoQRXaR5<1RqDg78&?D=7@*M1LhiGQ$hytbCc%-jejtQ9fE?gi? z-%v$<0K#+8E&N;Y$ZdAdKOYaY-pIGaG~u{rlWB47`h|>j%&3uzh1wf_N7Lo;z}Oy}RDjmr5%7o@if)Um$Ag#^-d-Gbg;NMilkD^KD@D2Pnk33Q))^(G3js> zd%O#KMvh*Q8}@tfR8uJd!HSsEMw5RAMRi*16c|j*2NDbfp-BS?40uf^HJSo*8ZImI zwnXp9#wIGem+=6&ow5RZt8bXhk~3H9O#sBcT<`bq^ku&_cUf6k!oTn0u}3I(e=m(i z91#=Y1Dz0`TS08b{?mwUv%1; z^733h_@DO6$0r#C5cpCn8+iaNFt|8I2zmfEU9T*%8;9p`1A&MgP?!y6sm)DxsbdrW z*gMyHygbcSMGgQbWbBRwjq1KWD+z5BA=h!WcP(fO{woNWB2qzZ)1aKo_w_poW`+N? zJsLnr0SMw<+|aV1y8|p0!#1FhO!T6d@}zLHbvh(Kc72lAj*`&RA^}Px;t~J@FNAmG z#MG2w*Az67%kXY#gbVKoOMPx+4PC~Ny(3Jh9>HswCDo9Yiu$2g-7_BVrkY!W0>(b9 z27F99!jh6P&>PW4eUvz$HZ?u{9o8-|72_xw0P)3xM;qQt!-?WZXFyc9CN`l)6wnLo zT^}YUs$aU4$ejn`YqleGJsJj&rnN6Th^RCF=@j8Z_~NeR>fc`kizrSNXMy}i%vA%^ z#!pmtp_Wk#D9}--VUmdP_e+GpPKhUc@Uz5K+oVIai4R!BMeF6rVQ2P}!+2Cc3*$%G z6{dWqsko%%D8wbe8xRjc1)pf*w*(Z5h&vT^MnMe&h0;Sl`3n1|G%p%CZ^GoU$jx%UHj5O$_2qx?Oyvh* z2c#@FdRds9JR8XQkBjr)@aEk{we&QBUtpV0_$R)&&$q`W@iu5Q^E}|7_vlXt#qnC{ zsHn4TQWp^a-CD8Rf8yGi12sbUBsc{-@aWLUVXT`QRRJQlk#P6jJ+w-|%P{&@JGEe5 z(2uWC698W<$)R)K7gukLh8|d|+Fh1Av7JV%W9ic!g&G*B)MGqy>2s#S+lg5iG8|fm zNl+B>H$YIRnP@eVHPo60ede^ZQ)Gi{%}0p&c+cf;aX0V_MGi$qRQ?&CQKl6?3&OM|alSaic3XkiuG2#GU5f>(I3rD?pBw-zyah zk&f#mInD(fC;Q;hGeSa_G}u;GS8-}<-q&}h@m@tPhxu;^ZaA?V!wbFEvHB}w&I9h< z7%!+IJTQP^J@NYm(_u4D&vj2SVSWE!|M7i?ww4xwcHvn!Z)$ye9^EO?;?3>LdHy_c zZkYg@eK&rDL#*dm^lcX$o@^1+m+=r(uU$KWiF*@gd6jK6ftX`TcIOQZQQNR^Bbh6x zHFa^5&ll_dsIMre(%sExeqUETb;=T=OjvpW8i0`&vZuL|+e0Yq08fR6n)UF=f~kPa zu7Oy^07EHnh)&f7qIHRL$|y&a(@5-TsMh3W-n&-5TNK}707|VDIrCP^I$=F^G}S(_ zuDg8QeV^xWz^27}#RHDokL1-L3@9n_zVO0oTa5T1jGbI}_JN<8olD*DX|sTU5#S{y z{9pzz>}ZyXZ2V>pM1ZKgKo6kP8euBAzHJoD{8YH^50}TAmY%ic)dT{wf$HuC>WF1r zGO+z(vQG;!j0t`3C=%AnKtE100g4tHYyI&mU0PdzW)RGn#|`sx2qR33Q+(issMIPg zDoWVes6vd0M?QXwV<*$jol8mO%k0nzRS_P&kX7xHk8K@Kikb&C2B7a>kl#wC-=+C~ zFdYCkNZCQY_d=}+1YY}%hyi%_6O4)LzSZy2ufGY+(5-`b!ngGTmki~?oT}E!4E1mI;z%G>s z0NFRCMq$u_ur%O>oqzujzfV#c1 zM$waD)OZ+9b)&#tJ5m?%6DDA>Ti`a~LemT5hW7|dVi@syv{-mAPJb(&%HGyEi>C>z z$4w#*T`9D3cQR}Ra~4?`_xlZWQ;k{ld7*{|iPo>MDS`7KH4At!o zc>La&cyebxiO*VHQ}Zj~fL69T4GU_okM)lPESg$d$Kk7-n7{bb;icYGa%+sPpt|Z+ zDR#gjWAN6Y8OFM+<02`!LHPFGyZVQtkcSYo6BF~;1^(foU?`ob?d8<3`}JmeW! z=vg`Z_2d5qM_A0fsVv`I$jP>=6w@=tp%4GAAe9hsK#L7@82J*MT98?qKc9uD|m|8 z5Bnp2qb4vk>6AT(KaT_?4m+14wY39MDGL9m1*mP5E$jdF9oxY+K}!1`y)L1W?-liu z--oY+vTX!rIEHQB^LQGvM?|R#;n7zJlct4MP%}3W^_3yMeBH_&bTSbsQ%I;R`*M)B zzy*qbn?=gc-b`_kP1!5!Mu9aHu;Iux5`ubr4uLEgNLnzruCo*bX!*V9 zoMv5au;O{9;L#OfUh47Bn z=4NtQ+O4XpDwgtVn1+0fvG}8ywIFCM!o26$Bs(kXFo1*9bE5~9n4@Zh)YZ&)9f;QD zr1(pDRHgp49w0xWx~YKW7CG*vQaj54Ss>flz~Jv9##C{QPs*ya;ItY^eX`M*n#v>wfpz&ABA` zm5KDQY^mN~9tv{_txl*zf_yje?e+GM)PnPed1rkQtfF^oHi301g4@{*Sj^7X6E1+Y zmgZJ(FZB|7>AVoku_+6vHJK;t9^zP{|Lu&|L6{@_>n~qpC!h$J{8)QpwbC+*aOS+Z zQuOUB4?dx+f$$4<^t|HY=Qfs_>d`xlW-}^3JxHL>7<^;E038ZxaGICf?d$96CMFZ6 z|0P95F=*eTA_@;!5Pm<=9QaHb4w=JmX33`vIRY~o9M`{8 z!jhX!TzU&YBILR!_;kI}T|}L)EVq+*cdk40F~NKfXNV9PJoij*ZW@wflzv~4i{Xjj zk1Q5+=hTg<<+lixZg$?AC_p9*%WMFwz(8{R^zoI4Wd=ug!krd!e6N8ubD)n<$3RsI zXG2Z!MtB_1XH7(W`~Dpj{!{53{c8ZhF^lvc5k^GnI>!R=>2JSUG->PWiJzC+V<5B( zPlQxtc(?+ZBZ#^+G^+m_)s1K!H|%W1_~+&w3QJtXJy|F+wr=?NafHY#-=Nfk zq4(iJN@;JtY@ABR+dh967hO>dLir2_>?*sruOSL{km`TkkN~M4=3*+Yh}9bZiHweZ z^OE-htHoh;HaJrfN*HwkC^+YR;{}aluHhjInk;W6aDm-g9}sJofsIyUrx!=mj2xOd zFLNmokrNQ3>DMRy8yH&S0NY-&zKr`*3kTQE!b3MW+1bZ1G(lRqr^MK?Yf$7+8iq4O zRRk`y&gV|hAZuHphBN|DN&F(P2;iA{Fv?TDqm-%vT{^rBprmeQ|H>u|EDKp0cNFjb z*p%zoljzrA0!^G905hVMv`Ktt+Fk3Kcj=XL+=DI78F&Q~)ph;-{qTq|YI7#cI8mW} zfbD;j^2PW$aI7Gum+$y3-H8|8t_@x_H}~wuwL)v{K@?v^Kfj_djymYF=g207m9~i6 z3-Z>9$;n?)`-3sO1OHmz!ER!09Y)unY8nM_ce(RWCh(?>=~rLZ43tu0-U_hTD`t$= zgc ztE--NcKNy&QBLPRA{uNM%wUQhL9EfS`6jxVvcGS0QY5*tByOB2#sC627`<9iYR4w2 zh8=!Or`F~O5PRs~cWK6>-N0s>|G%R*Sy|5V5i~ZT#DDf%>-HlYRWJWNiafKB6bz>O z^)1d-dc2P639gzdUePcL^(>d+`ieh8I<>cOcW%JEZF%~7xp&LX>fU|cKSdFsyZDX| zjm;*D2TZ{;!_>4Q*QJpSG9A~*f?B;%+(kW~?l+h^!Gf4I`hO4#I2ITVoqDT#>eMMW z4-Y(3ct1QTEcCokAI1+p21P$-yzu@@FBt}@dFgitLvMC6)7I7Qj_>aHEdO{T8oyXZ<4c= z#dr>UwYRaevtut69d<|>_eH@f(vVm%C9C;?l9KW_%G(iyWvMA&%BiU-=Z$q=;Kxs} zL4kJrcFCS1P$>}Y`c-y7M1%o0 zlXWolw`Jt3*%?ZGG24iOq;F_w0nb93ft#a%h$@LC=4JGBbTz0N7lbkY`;G9KtaHCY zS8WOtTqNy6pXJvLLja}&fG|VMw8y#!R-N}@?wGjn^I&JT99=cth%BwTcw&44m*NK! zY4ZtoA18je%VVgt4loX0H2Lo$h)`v~cORvbKb=?45_mYJMvkVSpm1_?JAX8mfs(9i z`=HrfKz%m`Nh@I5-P`Rt-l7a4{N-`xuv+96e>9d@1paAK>n1n|sIb47DZ;8W2;PeZ znu=X|C|;lH3P8?AIH3owzsK!8S$=cveB@(%AzNePwntcdU=FV^yD>;O>ml*FKRj%T zxoS#~`sbEcq0}_1ytRq2U}%UDbOuBE))juYl&QXd4KhW+o8%>ZS;UqdF81r^lD%p~ zG`YG@o=r69I`eIxKf`OiwZ6>?UNu5Gi4;<@|g2B<8%CK-XF}2A~QFt_|Bw z_!k?pTe-!&BS-6IF=MtnrKJW2IB8{Ng9r0|TvG4V;pv7UT;fZeV>H~1{hFZV0I z9NG)kpCE?c&O&*!jo2st<9bADDkpI?A3R|2K_z#{4?fLO@6k>lni`X}XeggK_^Pcd zkw2W@ivJeFDBZ9isqR;vhI{C%SBJ4a<^n;kc`p6tE?fI+=mYmn&wopzHvvC+q+0!j zoJs2U>})_p#F@-yzCJ;+L(&J9UAxloW(Gk~$RP~|Hhxbo_e zb^|Rpjh4h^?_ZKJHDIYJ&?!&3EH>%ky(RRueuCxi2(}dcbonyXol}ny_lHo6-e*+& zO?-upnwP)!i1#g33w^3-3TmrqqGnK}p^%|IQL>4e`M|BfKw@PH8q?E4FYV(``9+fxT^?K$Qa z7CM(zG+?yjlmBD^V=E|5E15j^Au2T@}Ot6{IQn z6b`8aUT7}B#&DX#&ic(yO{#~g#L^4W;Z;{QF;Q0+mny7#z0kF5dZ^qavj)_v8eagV zzgiT(*^<*hLF!fnGHm!El!G3cS?7stScTi{u5hGt|0dFh?+8;IT1_&Fv}UB2)W5fo zyb3x`-SGAvL-qMhmQGtzLSh)H{ee0ee-UefSZ|+9Rq%bIa2h!&Rl5(g5k~TZF=XZO z4kF}d_0hU3OG_2auhuw3u|-r%Bc$npCjTj@B^4DFE5_$We*O%{0nGBrHe`B@%}IHy zy|!XjO{|0+8WwTTX?>6#{{Ec?&n`ie27d)Bntj^YdhzlNWj;|k5Sy^x?D3s=v)~q| zOd{5o56%+12M>iBcz4@r9Ey3J?@v!pKX6I(1e=zKjk#5%jd>k~VhEG}F_M)l$2R53 z#=gG9UrJrj&OB6o+9{Nf{pP9-<(p{HcLiD3`}1HflpeEXPjPg6Yik6*E&sC@GB)2Eu3NsNk$6nkkHTHJ-0$%1$~WZjR`FFN5Y%DihA zkG%Ysr|%e?TwSM}_@7^}7qIm9u6lca;f=03Y)db#+oaW)i{dZ;*re-u`gAy&2V>O# zVGW!<7QDaC@ArGG#UwVsmjClhSJy7r?@g63Ew8`7hTmYU-Sp_uz3UzxT|dmuTZ6G5 znVE@zSj*$(>(@J>|8#OmJH{N%D!!6xmvmvD;(Uwz%;&G)Q@08KQ;+b=!Bj>eqG zcns*$>1Ms@xVqy~s1lDVSvN-X+O=zeYd#CJvpQ-`q{omK4b(JMR#GS^D4abMV=Vmf zsphV$Qr2lU=3QE}+%G5`sPTywOt%J85?046;kbO%n+xPU$GnU+U_`{cbrUt^$vCF` zY?1Q()%1*$=TYE%@TsQ;KB ze3db$>5p^4F7Kgn9^z0b3JTLtzr->$6DX~%tvx(S^YR!$|HU75&Csjw?(EFE$L1oX zac+w>=qv!o5@ja+4OGuhKUvL=KbRQL#>O4AV|a)Z>r9;Zu-5VY^74Dp+x$Ft{v1y4 z7LA4>{!ACLVN! z_IBi3`kO88=#Y@>xumCIKzBq@Ris*EM-hFHt}>JOex4v1QqK;5Vamr|F9BuaG@HX> zA7wmdf@&Y13`9t<(v=>#dGjV$Q2cq#K07TpIvw@il?@O$>3mtYg~{k%gRu@l$6S&H z7Z&fzrD!j@)oPTju=PxvEk*GLvt;6|r=_J8AJuIn!VDzLg^-t8HuoY#p5K{I49TO+ z@3Pw=rZu$fwo!jyU;NWo_xEw3D0u?>7bJue)Sz~*2c8?=+jN3Soaq#PdhQ@klFU|9 z>h8R=(b))yv%k$6TYo`0Z#rBNK=Q}73}?1jmG$*?qdT7t!$I$}l~%GSYg+W5Nu?HC z06DOf_?W20eghWWhD^4n6|YIeqK@vRVS#qe+Vf{EFnLXHQG}l~6H57?m#+W|DD<4= z!JfFD$vm83yA&ovX-;Wst??f=_iS}`MYQ5TA?-a)677~Oa4kX%xWC1}n>WR|kN zIZSpKV9(A^kjd5{N)R~d-a`d43}Nu*eaCOUob`RRr5A<0r~|9Ti8hX^3|)}UCm+%bdaI(uW1xLdq#_bL7lu4DD9;fx&>Ys zA#ep%p!Ark(KIZM)%A$}z?L8V+WlH#3%uJa1_nwys9RcFTZg?bL4#wCau)>#=XuB6 zek^zL1ap{sbIl92O~vEx%r}7SZy}r^bOgrT!y2kAUaRtdf3^|pz---rLUsfizM+gi z=s$lieyw)F46uAJUL9bU_jJ0G|7qX8eYph%cZ`Ik8wRg2Tl3Iz@1v`x#mQf}cVnQ) zDV$;F?bxT`(`Bj)GWZ0jK~Sa#l$6L34z(v%d)cx(KYz|0XhP}Ld`Q%Sl?F-WfhsSu zF@jZcGxfq#UG=QX32dvYwVUcCps78~I+y|Ory zv$|Pz@)yQA!M#y_`tzw06U?ULj}&~1fztvBh93eN;7^lzSi46ANG?7;<(dELimMJk zd+s05-n)0Nrk$U9gQ+LUifZZh)QM+9@vSM_>emaL=h;YuM)it1#Wsies4hh&qgzdX zmm>Y<9bat5=Y+Pi*bcglL{sW4A$3(lK$(XTaq%qHuHm<#n;3z0^%8L7-bK8l6Itie zii&y<=Gpas3ThpPEe)0L$~;Qw9rDMHjr{uc>fMp(jL0+4jR7L!KvSn;YWn!(Sf<<9 z^z{9V41UaghA8m_-t=2uS>fT~p#;`tSr0pk`vi2>VSzyaEDO#(Y55cQUI2}W2L61{?t6t+{mmL!d@+MdrJ7! zWH7%KX499RSZ2JO>!ZFa#*G7qT7w}}i4}hLthWQ=;&vw|CwpD#-TI5!>hdLPT0`_H zw;0kcB0Vcj=(h?8{5=MPzy zpMGCDIcF_yv7L+Nja>Rik%5?h$4J~Y>=m0x^Na^O$G#N1hpkyc?v&GcPq>x?c??+@ zFC0VL+(JU(QxC$`h2yFR2QQP|^56n}Fex#tc9g!m{Ox@ZK1$#(DL_GwV z)FvjyLJ9VGCm7{L`~A7-{8=WHS37p>i1GaZIl?`nxbSko7z{*rgk`VTAX;in7UdZp z`oDhpMk_qoh{lt20#yOFyuK1!rFrx3OKVfpPdA#MBh`1%NYjv%l$2O4hotYGJI#7K zq1m0`{5DyOjQwae{7*erW9vMH^O}~OO;1-Hue|LaiY#1=lfrQp$Rzwl-H8e)zhM%- zYVB%mX&HQTZG{_3AP(=}!vQ)w#sAlU*>=VNu-u6>0_W~(oV!`baG%9!_Vx7SCaKw{ zojvF@JF0B--jfl_jP@ZJGVI=c2Tc>*9;NFBla81_#z639ZfY=v(i7eBC%7uWH#lQl z$KxliTIV6r{DOjdv;?BqS^su3GonN#@RU$&F}&C83R!YX>hTC58)necI|N4Qp;ZFt z(e+$Nl#9!MO>#}(t0wGxITCASJc=%mR z{Ia^u^}l;Gt?vm~D%~hk5FvwDN=bTd-L?l9HV^_p}dQz`UNrc+JX+S77SKB=1kOT$ea8A{vbL`Nc8$sE=2c zu;!CUcEsKsyL!;|-f$x40n_q4Hd>S}5QxKnJp3UVte^cm5`0v?CjGNMg=ZKtv$}QA zgCkp%7r4$mlIMo!Hy;+UfM7mqbjO03SY$~2-`&DST)6hczXG(Z#PiU}{Dr8AvoH9s7l)4=t4aJ#&2RsmnC?soSi>``c4= zvv{#vr>w8ONraA=!PXncOyE~QZdaNUC3(ffbf^3-0{`2|!J$PEnLs`7{d=f;`|0^Z zYUonWE2IL&ocVJDb@oT(LU-*3Sn{92q(X_$0P3>`s9pa11u3&I=a~i8BkbcX2|u>Z znLIN+5%j=@R8D&Ax*Yw{-gv0}(t1}hji9{z`|9>X4R06~KVd-x&gcQS?p+oPq)J_gd_x$%C4_RBGks{KUhCn}GO4YEoGaIJ);y&p zDK$0X>sOv_uD$=K1-L@YKq4Lf%GR(C!^{nY03o5FmG5uNG3?uy-SIYSdXA8RVDZ!y zlN_U>onR2VCXE1QR^ssmVF6wmzQBO4Ihu#1FN7RijHtoZw*$= zVYfV&arPir)JLwkMnF`uS5FTxh1QzGR*eeb6O|}3$+Na>cc97PFn>ZxY3CQWp} zWCOPMhyOv0kqgxS?*csWoqqL61}3j!MH3#V4jZ_s8MmAIzuzEz5Q}q2ptUCytiE5R zs}{LfNM9A%mO6NeE2xJ;m0GLe*}fCPar?!^nauN8VK7*lWyxCS5G6*!>#al2ie+Kh zF8i-(_cUc$Y4`_uus2HU)8vW<#vVJ3MOgprjPgg&dU9|8;{i;tQZ z(t|7{{h|=~wDUIxV(PZs#t92z`+rQm2RPR4A2xoAL`jlFs6?WW(X^5f8D)kP*|TI7 z5k-_$G7?GIBV?0=>{)h5NRf<)%*Ow`p5Obv$NxBbj^lZr)_s4!*Yz3a=lqk>e$mgj+Ki|L(;=dKEU2GL193~P9glE`Fpe6Gf_VW_tB*n;E9sJV zht?bCJcd_P5Q@?flEHT>ezS#Z(Nsucs@bw z)t>M^3Tq=Q@fny(y5V|wUxgSYFv?^FRV z9+KT-Bdk_bzT3Hdd-_A;rmv2M4!2Xk%rytLXB;ZdhwPZ`nM57Atlbd+J2f5(7;v=-ayd?ucc1Zh52z z=cQl{W^ms;WbCmh9tNX5#i_nepFVxT-o0Y^%~LyMJd{XCLaaijZ%d!0j(fKk!vY>a z;ky@q42~VVsigylS7=!WcXLAbNByf)F4}3ICyOZ7HC8=-^cTI`HO7~ilyL>^61xAK z)IkB($?e>}!Y-fbVnrt?+=&OgxeV)0XmCNrNdZhrto9K7{E*d^m1vjo&mE}cW{^9L z-#r$IMCrSESIioG^|BmbM;7O6PyK=D0WCfQf|J-cx0sk1Vv6`5uG1WM z+-SlHbRl9KW-~SbsrJ^ZC~4AO%Uqv%);jhbLN$z##Sg@qRK)Dej02d_+((aoulQS@orHZSL%9{1V-Nv3_K#5@_@ZmIKA_@HKZa_x|CRvIgY zp;*$-mA7{`NW80X`2waNnI)1xE@E~wkK)kp9@%h_Ux+Y6cY^eCeS|YLG_K2J~V$wr$(C@XqhGTX(pWTC7At(->aJ+5L-6_4U{< zyQO|Lm`zkJNlG(K+XQWyL~MpM=x9|aM!8wm>(uU5i}pnUv{+mg14T9Bw1e3!5NJAd zdNp8y!jz<#(NbD|_h#^BNuHhm-W4c)3KWhbitjdpVGR`|UmWfPEYrmb7oqI>X(T?7qsAMEQgMQ^^oyc%pHF+Dzatp>cy4v%b{L*Terb(9v;p}|Jg_yH+#a}h*U<>Z#U6ehWgG)z6? z90CE<==kaA=qQw>rKR`M=6%4~=+>{7gXD2a(s}9FjEwyro}M}e9upI2du+rF&;6eavYzHNy7|SX88o*I5V=--c->8Gz%y zKpQRuQo}GYWy0T%bcLY-QXe-A0B_y8bsZBkpeO;OqobDtJ{Ds%g9I&l=`9V0*UkJr z*H>O2x$@~?qYFb?eEb?fB8Vwhxbts$W~Mt=7#bVi@Jj%Hsd^&^7_Vyw35_}`@j^|4atab|?; z6tRWLymy~JmN-e&9d-Gx4aw*LPh!Ac)}3XKr3~zQXvJLegoE@;j0gkIXA6WXJph9M zf#Wv}ehePbl$Ms7Hiiq3k_}~Vvx#4u-sMlP({i^x%gYl7Q*z$D0(JJYLR}#dk@v>s zJSej3BA2kc*Zwa1tH2tjN)ZP8hTe?;plP|kTzO{O#J}YPT_sKdS$VAp1;rddyJC{9Q7Q9hsY-*Jhs>C@t#So|OgpVa@UP z^$?GS@*Mg{mt{jF?drk53r7kZ>oGYd3*8cRR>BxWVgc*HlP5t?Nz9alW_F(m9F_l1 z8S4J=ouC{Yrpp*8AVY3^lYE*ltg^RP-+WZy$dPS;J!s29xDkH0A@)$b;c^Sq+mUl~ z&8>Ire)_E_HY;*>taJ5d`b0+rY^^DO_&cuJh>IHxZYp=~UIY|+){eFb_h zeCGeEMrN7V+3x{j{fy3)%xRID1HOIx#%O7|hnXH!h8*A$C`5PTJi=Y1gWjJ;`zLyd*F0s~@?bY2fD1B=>09nL0Y^kA;u{tAr+t zB^@`KZ__Jm(DfPq`t=UxvuPh6Xhs9dgY0bMu6qG#m}#uVSOjG16Njt2ItOyD82#Dq zxV*Y*>%wIZxL5Fea$ltzxDoh+I=)}W6qrb?`~!PlyB6wKuG1gyp~pNk_M!R0L~=Le zV&yQ3gi=E=E;Xa&ng7j^bKt#=%A4ot(Wn8oer=BV{DH)Ny@@oi6|#P=pj#vf7$8#x z;5B4t_eZK)(yY`&<-Sb6c76{((Wa?L@qO@@GQH+opM^AwxhxnHn1LW&oH~2s*z2n!etitR=pRMUgvY*H{?f38 zhL$!rNry6nogWRMUUvg*$+8L?rWRVXVq!Gt^-ubu`}m$%(_Ax@+9-Wc{Z_(a1}dq~ zyRO3cvKIB&W)6-(l*bjo)apZRPVq7W3fV>`Zca`E^EDqRz{Fi)jti zOc(pdW=8!ON$uU6GT_gS;R9i5K$)zu*vE&O zkxRlCyo!t2*Hc;1A3Zu?q=@bXBso%!+qyg{E0cy#SP=3wobR5)5=b#5{5-z!J|ia* zbyo%hHeewQvTqcML8}r~g@oUwZbvTPlH8?g0LOGgR1}HhXIv!Fi27an@HiI!7N}B* zo1gUMljj3C@V+ok1gPcSB9DEsjd)KY#%9s6P^I`G54FA>h`n~Eoc~QyYt>TXq})gg z_8A4lzLCq9FCTTE=dVSrc1}=x6)_4Hek>5W8vz%^U`n!XY);gD-U={)3FZ=rKVC=V z`^wOP4^OO~pR<&S+Z3u~mb(d#ed4`83J_}B{4a(xSIjX~eJeMjPx8wWrT)th9j-wx zeX-jdABb1IIq%<}g~euDVohNkeIiBjmErDM_{uqKMN$HZdGQV)KGj&JtKYLiUlXDw5cN9IQ26M z#q;+`7tCG#5F!A|QCsx}J>oN6fk~bmO7t&|#}q?2tsf+_C1=6daDYu>*DeYkutcmS zpj~9wv+U>dtwJxxvTp*1yL)ODpeNfg$Hdk#yFFnIOq(|o^%qw=uocK?2S6V#bh3JE zdiQg2{6RPrd;?EEe#8*-H=rg6Aj?A)pgUFq1XWQqTqwYY?rgg#@?oVhB`GB(0TV+C zF=o>{&vA2kIZD*j;cMg8gvS z4%o$N*|}Bw&t;|VvGD7AqPvS}h!Cm(TYSg?}*en_!uz%Qo zAGgKC)D*Y6DN6+=!vC3AX==7lUj@&Kn3ZB7iwZ+))#!ut|AU=7CT#y%+e>Z&7oKB} z=!Q+3&M7ymx=B*4tlqOZb=2F__d#zy``uwZI{_ZmQSB{Abnx**fpVCnCzSO>Xkv<`-3~Kq*gN!8#~dP zzpqE+VEbqt2@@)f08kzN{&tHFf6PX%u(D=e~nMD|8X znI7Key$&R+$mgKEATR(7ds$GR0H~`%gh41p>?LZ}81p=eeS?`8_=~X?n?4QTNhY)MEAj{l||lX4wG#gXi`cFqdAA$=bJ7Rp2s^K7)MEV}8i46RVe;zmIzg^k*G9 zdw?NjuS`(q*gLpfuu6h%7^h6wrJvz?)*`RxSCF)zjNIpDLkJDveUaQuigaN)Roh7 zhm|nC<f3=MJRq2YVJ?r!I6imJ zurmiZh!_@-awx64g{7}OJZii{Kp2apo@{OVq@)bT=3LA`+}d8A!YZiejcuLBg^P!& zv3^g+4`e_MCxie|SHX|W z>f5HZ6edp27e8M?kJUc8M;r5(s)h!7b#?XmYumbZ*i!uIxL^I~m7{w3zM7%p$E9J= zAV=K6Ov^GVZ*4s)!r*iFE*--TsSo@c8q!!nDONgjrVdDTXXCf#Sj>W806Ti)TbCK(!+t;lH`ftsfA}`@?&#$&H^!D}bhC}X!N3I}Z zzR=H0?x-%ugdHnpH3$Pk`4tL;+oP?ZR<0_sYY+?zK6Mb*^{mPmeg-nknWLL$K z$T#3Nde_%0;bgV{*qhGNN_j}f{nT(>dziiR&g)4WccAz4_ui@m2-np=-y%{5`1m(X4FUulrIhsvGwN{Je;4 z4%5G!?7+==RO1}f#rpR-tY(&bqF`pD>&$5WKhaKSujZuhzR9_{iI zCb^k^e+U0nA@}K!I`+--D93N?M76JO4|gN;9sJ%p>jS04%GK${xejr!_je&q~~gV9LEcvCDmT;OS;MZU*mT z2>y>Z$;^ta>Z2Fve*0|SMp6THkW<4XW&(<9DJ zp>b*&!(QQ)&dWm=J!Wf!V^40mBXM*99_Zy2bAwyQ3DINTy{=@d{Xv6;xx>QlQ z`akIMwEgj%6#6@I*kap;_j?;yCz2gug#&f|&J|WvRMa?uM>XN8Zu;y3y8zdpFeb53 ze1Yxw0+b-yp*m2^myOvJ&ChJ}Jn|)Jo`*FM0$@Zkt88)T`#q=fd}5aUs(cs!2{b6`%D4efHZgFk*PJfawd>D_)v5uuCW+ZC^Yj#APHC2 zdPYB_TP^d5eV;FiNmv~c|ChJGt|e5ZKoufM43z4(AbH|E)d6~PnZCHa%OpHN$-nA2kO@UL;p-0R>dAI{9{ecS|qO;d~Ro%BMJpNh_Gm5J^uY!EWY_iqV%epCCOaq zAfPv{zU8$pZkZxzSgY=UN{gMwLRxdQ!tY5?8B0`&INyqA6%-OJr8j0nPLO^CHX|@Z zsDh(nqXNc*X;vRPBFmn`n0MFlPxT5_qEpMzWra%PT|A^~dMgE}16~-FUo^)u>n1c% z5?2H-fC`(YmGT*Q!@d!S4U;`E7_X;yxCx|7r9y8F6!|Xt32vZ~sNxN{et>z0 zeLGl6(?WkkuC)IgSaumwlVByK=xhrwF{l)2KAh$Ajb4yXl*f0T_AFJ?{=q~B5Hs)E zTian|OzQB_9enb9VUPx1&rpT-i3)&>p?@{I938;*v**tFV+1I?6X={j5RHgg(3gg> z(Nl5$N*N*MyTbdBnh=Lks_1-rH!|x0T@j*jBjL$_=o2Moz8<@DIpKKwU>P-3&`M9opGv) z-5E^$J`X5t4I&J&%+tPm_E^kPn2SSvzPr(J+v%_8rU7(J5;E4%C8wqpGz?47O_Z*K zTTGSqWx4{aQusr4Mc33i0>m`Tb=$zf0|bc@%5dZubk6<_ku{tipHodOL&&)I5lhm8 zHX+zyz~mdZ^MbJI)iJ~tQgNeqBS4N0$8xv78>&z;RV!up=vO4(IDF^sT}6$J2{q;Y zGWP}rs$weRgHc3S7-w0aA!sP0O?<_jB_^>BxwqOt5!1=rtnM9-tt-* z;9=tmZ{axT0y1O#Q4E0ZQ3yCw9}4YbT9x%t#QfI~Fp#u_XmO;3<6Prw{Dl~*!e9#N zKjYx__Af}EM`6PO)Qu>JTnmC&J^yKc)AzW*`1hOV2<57Hinbq7Ky$#vEcxJ9!*Lm6DRhXf09r}3`2OGhF ziD*eFl|wv%={fN%z2VdyiutWE=yz<=?)mCHrMPlrzsq&vp6)xDRY80(p;uB7-*?>K zdE7!$2uObA;GofjsjZC-IZUL*L~VyxI@w-;X-ojhi^tmcfJsUN)xZxlb2TnUwcmBq z7&BFgtTkL`k}kMgbk!(Bz2jp^sF*b>Yz64GqIwZ=7?NF4X{g3iHY|3aq6~feb{8dJ z2#?rKsL3p0_~(F?QOE-1nm+_(7XuCw)zJQmVw)iLyiMFOCtAD*o7LnNQ14KKz0Aw& zSOr|w3eb1gfdiW;Ow7z{uxt|B%Jcs~KwdsRo3dNZ*%!+Qg^%>defic7j*ji)D=g;m zH!axwrmwU!LaoDuiuWqlI`b94XaEI26qtguh_OE%BV+QBJD|JJ0Pm)LpZk0=RU_eO zNc}uj<^#<4FohkOoP42m{%;B_SP6f~CeM+u@c{$bYl_o_yMaIJbC%y% zGtC#njgKEc&da1|rlFpqjY-5^wRU-e?IT1W|EMT7Ow{gQZjgH%NY7A}c$LdnAU7Ne z8{YSE(ZuXAr-N+fExdIIw3U7oyd}0VbK(#N6KYwd?As7FW>8Yqn~BX&^lZW@7?I#T zM97yMS6)9awCu!ETQHOf4w#48A_h z-c4a^p?JglD%dd?2l{{^^wyVNv4qww=FKPk!($)pm7L@Y$%kn(2-&<>zZ83%uX zJcuo(`A4doTrm#E))y58Oj4!ekIs5hF0H5IzK%SZW8TCXaTP5sMo{aol>K5o6{?}# ztRyTzr2Kj%F5EUEjgJ%pAHj; zXPNT?7v#kmoT4Xosov`y%wdwVpd4*<;S9GXt|;i3sq$YafVwL7ZHr=nWKXt{rOGYn zCh5PD85h8L*d2N|?+~HRsYD9?mt@6+ndtt{IQV{8F@L&Fe;oG~K2?#&j~CH#z{q?p z8o^@c@rSxG#K$UVhxB%QyzAHq-MoFf%}g=YcJVI(NI@Pe<0<)pyj@%Of|gb5!jxRi z%$&DKu^XQc4p-p*kJ|~}4Nw6>Lc z7Akbp3moc*^@Mo|@k~v2lz4T7odHtZHCri`B+ORM>+)^KtNViTPnzY2RiVgwmX=qTKh-%ScI|-i2x+Xr=|0= zXITR&bmnZM+&#CV)~hHrzoD7&!rQ-^U7%ZDu=S1nZo(h?{pXK$35WS+vVny;7)93D zco$XzUrqIaM~nLOZFc$Jbg^mRZFs-Iw&(Z*zCTgoCI2@7WfbAPnMcLWE-u#PTX!%a zhi|)h{rP}@*x0)`f5aLT#P~di-kcI-P4N2n7kpN#Dv|4REk|a7(7)~K(iyuSn9Ih& z=J!0d<6qt64@G+J6w3QkM_93+0xO(t2u&DCVSMO|!W0i$y9kmKrx3Le`0oI^LF44y zi1Z*O?F%4Ydw4DGP=1$$_{czOK!YV#j#c{Yo%RNv?RYMO^MKm-k-Ex9?sXIu~g3OG?`DRIW3PtaX5fp%=?gwH;idLJg^uA0$oQF~JY`-5T zYD)X&?+WIZ%j17U&suzCMfsM@H5wPCKz+2vg;RUc9it;K{HZ9Q;ol7ii2rKGng}Qk zp#hg32y)T{{UJnG?5gcUp+eb(aT0hbw31%1i6LPdh<3y*CK;bG7ABhn9}4&z*?5`h zQL6}kzUGhH2}%X(BdE!wE{G&a6WA$;U7QJ@7+)ms_(?*10uqpa;|X~1P+0dG!X9~i z*M9B&dnniZF6B=cn$|Y2NZw}px!t=A_ul0IYH#FOpn)I+?*a$&?@UT+3L5GJ%*wIy zLdU@1i+y7D;$C@#L#&_8_g4k4xkI4{C(PS~#15KEnogG`azPR&H2(q;vAmuUMYO;?NEFK4NNCGXAoJ-)v;SCo@dLKyfVdVmTr zg)v~D7%V*3*cajKxmls$r0}DYf~*|Q;vaCjkd9G^rUn63;(*)6vzTHnzF;Oo!zUP5 zZLOcod+G<6U}EM^XybqhO)PsQ;WxyzeS2e8*Th{!4w;p2JY*C&P}qr5?TmdtBjrC< z*^$%sg!GSg!Da-U>Ud?#p5GCdqRO4PXnLAgQW&|v#8EztVIp)L_XB7fH-a>@I<{_A zI1*6kfX9O^gf-kWcs231&G`U6)`8^|dnM%N((pRLi?7)nOAO6D+Ts-m(N7`VS3~+d zc*7w3(LPJ^{7p2fuF8Mp@qLE5t*pwLhgec4ITTw;gsRnpcgujJY##nA>r5Cn?j&7b z^hp%senF+ydD#P$lxon7wQB)n1%dVc7NT3(dP2=!?0#-x6T6BnrU%xS6*GE^2_w=J z(x?bO%7{3l5t;J*ITc`Z0!!n~7Bkj;QBKl?l*KSGQP8hD$2p<=xs^=dBEyA@-f$9Z zkMP}|+fy^VI$W@}N`w#uK(%}7Hp))mNI01yn8-uSC{j@0V!CR?=xkVR!v5Xa+Z zVQT6F6sMp!hqT=o2wsrr0pq0ep%_|7e3kc!FDAat?`}RWD*n#(G;0>3m5YlD#o#m_ z`tso~UwqMB5~Li^%+<`Pp!;&qheRGeJ+V9VW&Z}0-m-$M*T$DH(Yn-|Yi_egJwrE> zn8;ZjW9u^gKRc)ZLGu~jYymHxkie%%tgNj6k27j&H9P;#tdqJvBbz;8pszoC z#%pB@-koJhgpjA2gL5Csn?_0XwhRGrzP!wLDCbs|9=JtrJm zK5ofdr8s+eoP7KQ^(oP`l2vIM0I*%SjV0;8e=CLbAk=1l%0A0aNRyL&1uEtrk(_X; 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⁢l0vk~TZs7TkT> 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 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + x + y + z + + + ϕ + ρ + + + + + θ + azimuthalplane + longitudinalaxis + + diff --git a/docs/index.md b/docs/index.md index 69cb9a9e..b5b67bca 100644 --- a/docs/index.md +++ b/docs/index.md @@ -1,5 +1,7 @@ ![](_images/vector-logo.png) +# Overview + [![Actions Status][actions-badge]][actions-link] [![Documentation Status][rtd-badge]][rtd-link] [![pre-commit.ci status][pre-commit-badge]][pre-commit-link] @@ -14,13 +16,59 @@ [![LICENSE][license-badge]][license-link] [![Scikit-HEP][sk-badge]][sk-link] -# Overview +## Installation + +You can install Vector with [pip](https://pypi.org/project/vector/) and [conda](https://anaconda.org/conda-forge/vector). + +```bash +pip install vector +``` + +## Purpose of this library + +Vector is a Python library for 2D and 3D spatial vectors, as well as 4D space-time vectors. It is especially intended for performing geometric calculations on _arrays of vectors_, rather than one vector at a time in a Python for loop. Vector is part of the [Scikit-HEP project](https://scikit-hep.org/), High Energy Physics (HEP) tools in Python. + +Vectors may be expressed in any of these coordinate systems: + +* the azimuthal plane may be Cartesian `x` `y` or polar `rho` ($\rho$) `phi` ($\phi$) +* the longitudinal axis may be Cartesian `z`, polar `theta` ($\theta$), or pseudorapidity `eta` ($\eta$) +* the temporal component for space-time vectors may be Cartesian `t` or proper time `tau` ($\tau$) + +in any combination. (That is, 4D vectors have 2×3×2 = 12 distinct coordinate systems.) -# Installation +![](_images/coordinate-systems.png) + +Vectors may be included in any of these data types: + +* `vector.obj` objects (pure Python) +* [NumPy structured arrays](https://numpy.org/doc/stable/user/basics.rec.html) of vectors +* [Awkward Arrays](https://awkward-array.org/) of vectors (possibly within variable-length lists or nested record structures) +* [SymPy expressions](https://www.sympy.org/en/index.html) for symbolic (non-numeric) manipulations + +Each of these "backends" includes the same suite of functions. + +## Getting help + +* Source code on GitHub: [scikit-hep/vector](https://github.com/scikit-hep/vector) +* Report bugs and request features on the [GitHub Issues page](https://github.com/scikit-hep/vector/issues) +* Ask questions on the [GitHub Discussions page](https://github.com/scikit-hep/vector/discussions) +* Real-time chat on Gitter: [Scikit-HEP/Vector](https://gitter.im/Scikit-HEP/vector) + +## Contributing to Vector + +If you want to contribute to Vector, [pull requests](https://github.com/scikit-hep/vector/pulls) are welcome! + +Please install the latest version of the `main` branch from source or a fork: + +```bash +git clone https://github.com/scikit-hep/vector.git +cd vector +pip install -e . +``` -# Getting help +Refer to [CONTRIBUTING.md](https://github.com/scikit-hep/vector/blob/main/.github/CONTRIBUTING.md) for more. -# Contributing to Vector +## Documentation ```{toctree} src/talks.md From 17650827b39ffa378b6212eb4e1a30601eb76899 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Wed, 18 Dec 2024 19:24:27 +0000 Subject: [PATCH 07/23] style: pre-commit fixes --- docs/index.md | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/docs/index.md b/docs/index.md index b5b67bca..8c191367 100644 --- a/docs/index.md +++ b/docs/index.md @@ -30,9 +30,9 @@ Vector is a Python library for 2D and 3D spatial vectors, as well as 4D space-ti Vectors may be expressed in any of these coordinate systems: -* the azimuthal plane may be Cartesian `x` `y` or polar `rho` ($\rho$) `phi` ($\phi$) -* the longitudinal axis may be Cartesian `z`, polar `theta` ($\theta$), or pseudorapidity `eta` ($\eta$) -* the temporal component for space-time vectors may be Cartesian `t` or proper time `tau` ($\tau$) +- the azimuthal plane may be Cartesian `x` `y` or polar `rho` ($\rho$) `phi` ($\phi$) +- the longitudinal axis may be Cartesian `z`, polar `theta` ($\theta$), or pseudorapidity `eta` ($\eta$) +- the temporal component for space-time vectors may be Cartesian `t` or proper time `tau` ($\tau$) in any combination. (That is, 4D vectors have 2×3×2 = 12 distinct coordinate systems.) @@ -40,19 +40,19 @@ in any combination. (That is, 4D vectors have 2×3×2 = 12 distinct coordinate s Vectors may be included in any of these data types: -* `vector.obj` objects (pure Python) -* [NumPy structured arrays](https://numpy.org/doc/stable/user/basics.rec.html) of vectors -* [Awkward Arrays](https://awkward-array.org/) of vectors (possibly within variable-length lists or nested record structures) -* [SymPy expressions](https://www.sympy.org/en/index.html) for symbolic (non-numeric) manipulations +- `vector.obj` objects (pure Python) +- [NumPy structured arrays](https://numpy.org/doc/stable/user/basics.rec.html) of vectors +- [Awkward Arrays](https://awkward-array.org/) of vectors (possibly within variable-length lists or nested record structures) +- [SymPy expressions](https://www.sympy.org/en/index.html) for symbolic (non-numeric) manipulations Each of these "backends" includes the same suite of functions. ## Getting help -* Source code on GitHub: [scikit-hep/vector](https://github.com/scikit-hep/vector) -* Report bugs and request features on the [GitHub Issues page](https://github.com/scikit-hep/vector/issues) -* Ask questions on the [GitHub Discussions page](https://github.com/scikit-hep/vector/discussions) -* Real-time chat on Gitter: [Scikit-HEP/Vector](https://gitter.im/Scikit-HEP/vector) +- Source code on GitHub: [scikit-hep/vector](https://github.com/scikit-hep/vector) +- Report bugs and request features on the [GitHub Issues page](https://github.com/scikit-hep/vector/issues) +- Ask questions on the [GitHub Discussions page](https://github.com/scikit-hep/vector/discussions) +- Real-time chat on Gitter: [Scikit-HEP/Vector](https://gitter.im/Scikit-HEP/vector) ## Contributing to Vector From ccb55e162385bc56228862a48a44aeffb5acc83b Mon Sep 17 00:00:00 2001 From: Jim Pivarski Date: Wed, 18 Dec 2024 15:17:53 -0600 Subject: [PATCH 08/23] also mention geometric vs momentum --- docs/index.md | 23 ++++++++++++++++++++--- 1 file changed, 20 insertions(+), 3 deletions(-) diff --git a/docs/index.md b/docs/index.md index b5b67bca..c6a6d430 100644 --- a/docs/index.md +++ b/docs/index.md @@ -24,9 +24,13 @@ You can install Vector with [pip](https://pypi.org/project/vector/) and [conda]( pip install vector ``` -## Purpose of this library +## Introduction -Vector is a Python library for 2D and 3D spatial vectors, as well as 4D space-time vectors. It is especially intended for performing geometric calculations on _arrays of vectors_, rather than one vector at a time in a Python for loop. Vector is part of the [Scikit-HEP project](https://scikit-hep.org/), High Energy Physics (HEP) tools in Python. +Vector is a Python library for 2D and 3D spatial vectors, as well as 4D space-time vectors. It is especially intended for performing geometric calculations on _arrays of vectors_, rather than one vector at a time in a Python for loop. + +Vector is part of the [Scikit-HEP project](https://scikit-hep.org/), High Energy Physics (HEP) tools in Python. + +### Coordinate systems Vectors may be expressed in any of these coordinate systems: @@ -38,6 +42,8 @@ in any combination. (That is, 4D vectors have 2×3×2 = 12 distinct coordinate s ![](_images/coordinate-systems.png) +### Backends + Vectors may be included in any of these data types: * `vector.obj` objects (pure Python) @@ -45,7 +51,18 @@ Vectors may be included in any of these data types: * [Awkward Arrays](https://awkward-array.org/) of vectors (possibly within variable-length lists or nested record structures) * [SymPy expressions](https://www.sympy.org/en/index.html) for symbolic (non-numeric) manipulations -Each of these "backends" includes the same suite of functions. +Each of these "backends" provides the same suite of properties and methods, through a common "compute" library. + +### Geometric versus momentum + +Finally, vectors come in two flavors: + +* geometric: only one name for each property or method +* momentum: same property or method can be accessed with several synonyms, such as `pt` ($p_T$, transverse momentum) for the azimuthal magnitude `rho` ($\rho$) and `energy` and `mass` for the Cartesian time `t` and proper time `tau` ($\tau$). + +### Familiar conventions + +Names and coordinate conventions were chosen to align with [ROOT](https://root.cern/)'s [TLorentzVector](https://root.cern.ch/doc/master/classTLorentzVector.html) and [Math::LorentzVector](https://root.cern.ch/doc/master/classROOT_1_1Math_1_1LorentzVector.html), as well as [scikit-hep/math](https://github.com/scikit-hep/scikit-hep/tree/master/skhep/math), [uproot-methods TLorentzVector](https://github.com/scikit-hep/uproot3-methods/blob/master/uproot3_methods/classes/TLorentzVector.py), [henryiii/hepvector](https://github.com/henryiii/hepvector), and [coffea.nanoevents.methods.vector](https://coffea-hep.readthedocs.io/en/latest/modules/coffea.nanoevents.methods.vector.html). ## Getting help From 34768f00c4e8e5305c8e59c8d5e8d850f924c268 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Wed, 18 Dec 2024 21:19:50 +0000 Subject: [PATCH 09/23] style: pre-commit fixes --- docs/index.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/index.md b/docs/index.md index 091a3b42..52dbbb5c 100644 --- a/docs/index.md +++ b/docs/index.md @@ -57,8 +57,8 @@ Each of these "backends" provides the same suite of properties and methods, thro Finally, vectors come in two flavors: -* geometric: only one name for each property or method -* momentum: same property or method can be accessed with several synonyms, such as `pt` ($p_T$, transverse momentum) for the azimuthal magnitude `rho` ($\rho$) and `energy` and `mass` for the Cartesian time `t` and proper time `tau` ($\tau$). +- geometric: only one name for each property or method +- momentum: same property or method can be accessed with several synonyms, such as `pt` ($p_T$, transverse momentum) for the azimuthal magnitude `rho` ($\rho$) and `energy` and `mass` for the Cartesian time `t` and proper time `tau` ($\tau$). ### Familiar conventions From 2f84f41baccfde58585b2cd95b21dd82ef33ff86 Mon Sep 17 00:00:00 2001 From: Jim Pivarski Date: Wed, 18 Dec 2024 16:10:41 -0600 Subject: [PATCH 10/23] added interfaces --- docs/index.md | 7 +++++++ docs/src/common.md | 13 +++++++++++++ docs/src/momentum2d.md | 12 ++++++++++++ docs/src/momentum3d.md | 12 ++++++++++++ docs/src/momentum4d.md | 12 ++++++++++++ docs/src/talks.md | 2 +- docs/src/vector2d.md | 12 ++++++++++++ docs/src/vector3d.md | 12 ++++++++++++ docs/src/vector4d.md | 12 ++++++++++++ 9 files changed, 93 insertions(+), 1 deletion(-) create mode 100644 docs/src/common.md create mode 100644 docs/src/momentum2d.md create mode 100644 docs/src/momentum3d.md create mode 100644 docs/src/momentum4d.md create mode 100644 docs/src/vector2d.md create mode 100644 docs/src/vector3d.md create mode 100644 docs/src/vector4d.md diff --git a/docs/index.md b/docs/index.md index 091a3b42..ce73c699 100644 --- a/docs/index.md +++ b/docs/index.md @@ -88,6 +88,13 @@ Refer to [CONTRIBUTING.md](https://github.com/scikit-hep/vector/blob/main/.githu ## Documentation ```{toctree} +src/common.md +src/vector2d.md +src/vector3d.md +src/vector4d.md +src/momentum2d.md +src/momentum3d.md +src/momentum4d.md src/talks.md ``` diff --git a/docs/src/common.md b/docs/src/common.md new file mode 100644 index 00000000..3f952960 --- /dev/null +++ b/docs/src/common.md @@ -0,0 +1,13 @@ +# Interface for all vectors + +Vectors of all backends, 2D/3D/4D, geometric and momentum, have the following attributes, properties, and methods. + +For interfaces specialized to 2D/3D/4D or momentum vectors, see the sections after this one. + +```{eval-rst} +.. autoclass:: vector._methods.VectorProtocol + :members: + :inherited-members: + :member-order: bysource + :exclude-members: lib,ProjectionClass2D,ProjectionClass3D,ProjectionClass4D,GenericClass,MomentumClass +``` diff --git a/docs/src/momentum2d.md b/docs/src/momentum2d.md new file mode 100644 index 00000000..a755037f --- /dev/null +++ b/docs/src/momentum2d.md @@ -0,0 +1,12 @@ +# Interface for 2D momentum + +2D momentum vectors of all backends have the following attributes, properties, and methods. + +This includes momentum synonyms. For purely geometric vectors, see [Interface for 2D vectors](vector2d.md). + +```{eval-rst} +.. autoclass:: vector._methods.MomentumProtocolPlanar + :members: + :inherited-members: + :member-order: bysource +``` diff --git a/docs/src/momentum3d.md b/docs/src/momentum3d.md new file mode 100644 index 00000000..9140f542 --- /dev/null +++ b/docs/src/momentum3d.md @@ -0,0 +1,12 @@ +# Interface for 3D momentum + +3D momentum vectors of all backends have the following attributes, properties, and methods. + +This includes momentum synonyms. For purely geometric vectors, see [Interface for 3D vectors](vector3d.md). + +```{eval-rst} +.. autoclass:: vector._methods.MomentumProtocolSpatial + :members: + :inherited-members: + :member-order: bysource +``` diff --git a/docs/src/momentum4d.md b/docs/src/momentum4d.md new file mode 100644 index 00000000..9f7abf91 --- /dev/null +++ b/docs/src/momentum4d.md @@ -0,0 +1,12 @@ +# Interface for 4D momentum + +4D momentum vectors of all backends have the following attributes, properties, and methods. + +This includes momentum synonyms. For purely geometric vectors, see [Interface for 4D vectors](vector4d.md). + +```{eval-rst} +.. autoclass:: vector._methods.MomentumProtocolLorentz + :members: + :inherited-members: + :member-order: bysource +``` diff --git a/docs/src/talks.md b/docs/src/talks.md index 5b1c9bdd..0b6c6323 100644 --- a/docs/src/talks.md +++ b/docs/src/talks.md @@ -1,4 +1,4 @@ -## Talks about Vector +# Talks about Vector - [CHEP 2024](https://indico.cern.ch/event/1338689) (2024-10-21): [A new SymPy backend for vector: uniting experimental and theoretical physicists](https://indi.to/zTs5b) - [PyHEP 2024](https://indico.cern.ch/event/1384010) (2024-07-03): [🎥](https://www.youtube.com/watch?v=aVPhP_APhqw) [A new SymPy backend for vector: uniting experimental and theoretical physicists](https://indi.to/pfTC6) diff --git a/docs/src/vector2d.md b/docs/src/vector2d.md new file mode 100644 index 00000000..6dc2208d --- /dev/null +++ b/docs/src/vector2d.md @@ -0,0 +1,12 @@ +# Interface for 2D vectors + +2D vectors of all backends have the following attributes, properties, and methods. + +For the momentum synonyms, see [Interface for 2D momentum](momentum2d.md). + +```{eval-rst} +.. autoclass:: vector._methods.VectorProtocolPlanar + :members: + :inherited-members: + :member-order: bysource +``` diff --git a/docs/src/vector3d.md b/docs/src/vector3d.md new file mode 100644 index 00000000..31ece24c --- /dev/null +++ b/docs/src/vector3d.md @@ -0,0 +1,12 @@ +# Interface for 3D vectors + +3D vectors of all backends have the following attributes, properties, and methods. + +For the momentum synonyms, see [Interface for 3D momentum](momentum3d.md). + +```{eval-rst} +.. autoclass:: vector._methods.VectorProtocolSpatial + :members: + :inherited-members: + :member-order: bysource +``` diff --git a/docs/src/vector4d.md b/docs/src/vector4d.md new file mode 100644 index 00000000..837246ba --- /dev/null +++ b/docs/src/vector4d.md @@ -0,0 +1,12 @@ +# Interface for 4D vectors + +4D vectors of all backends have the following attributes, properties, and methods. + +For the momentum synonyms, see [Interface for 4D momentum](momentum4d.md). + +```{eval-rst} +.. autoclass:: vector._methods.VectorProtocolLorentz + :members: + :inherited-members: + :member-order: bysource +``` From 377965638514a5891360de82a184653064e062c6 Mon Sep 17 00:00:00 2001 From: Jim Pivarski Date: Wed, 18 Dec 2024 16:10:58 -0600 Subject: [PATCH 11/23] pre-commit --- docs/index.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/index.md b/docs/index.md index ce73c699..e32c86bc 100644 --- a/docs/index.md +++ b/docs/index.md @@ -57,8 +57,8 @@ Each of these "backends" provides the same suite of properties and methods, thro Finally, vectors come in two flavors: -* geometric: only one name for each property or method -* momentum: same property or method can be accessed with several synonyms, such as `pt` ($p_T$, transverse momentum) for the azimuthal magnitude `rho` ($\rho$) and `energy` and `mass` for the Cartesian time `t` and proper time `tau` ($\tau$). +- geometric: only one name for each property or method +- momentum: same property or method can be accessed with several synonyms, such as `pt` ($p_T$, transverse momentum) for the azimuthal magnitude `rho` ($\rho$) and `energy` and `mass` for the Cartesian time `t` and proper time `tau` ($\tau$). ### Familiar conventions From 23f44952d8e4503e8678fbb9cd9d3c68f5985d6c Mon Sep 17 00:00:00 2001 From: Jim Pivarski Date: Wed, 18 Dec 2024 16:11:57 -0600 Subject: [PATCH 12/23] rename 'talks' to 'presentations' --- docs/src/talks.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/src/talks.md b/docs/src/talks.md index 0b6c6323..00fd2737 100644 --- a/docs/src/talks.md +++ b/docs/src/talks.md @@ -1,4 +1,4 @@ -# Talks about Vector +# Presentations about Vector - [CHEP 2024](https://indico.cern.ch/event/1338689) (2024-10-21): [A new SymPy backend for vector: uniting experimental and theoretical physicists](https://indi.to/zTs5b) - [PyHEP 2024](https://indico.cern.ch/event/1384010) (2024-07-03): [🎥](https://www.youtube.com/watch?v=aVPhP_APhqw) [A new SymPy backend for vector: uniting experimental and theoretical physicists](https://indi.to/pfTC6) From 1405409f70f4fb5a6fa57df3e1176f3e526038d9 Mon Sep 17 00:00:00 2001 From: Jim Pivarski Date: Wed, 18 Dec 2024 18:11:53 -0600 Subject: [PATCH 13/23] finished the (public) reference documentation --- docs/index.md | 14 ++++++++- docs/src/common.md | 9 +++++- docs/src/make_awkward.md | 48 +++++++++++++++++++++++++++++ docs/src/make_numpy.md | 47 +++++++++++++++++++++++++++++ docs/src/make_object.md | 47 +++++++++++++++++++++++++++++ docs/src/make_sympy.md | 57 +++++++++++++++++++++++++++++++++++ pyproject.toml | 1 + src/vector/backends/numpy.py | 50 ++++++++++++++++++++++++++++++ src/vector/backends/object.py | 50 +++++++++++++++--------------- src/vector/backends/sympy.py | 32 -------------------- 10 files changed, 296 insertions(+), 59 deletions(-) create mode 100644 docs/src/make_awkward.md create mode 100644 docs/src/make_numpy.md create mode 100644 docs/src/make_object.md create mode 100644 docs/src/make_sympy.md diff --git a/docs/index.md b/docs/index.md index e32c86bc..5231f1e8 100644 --- a/docs/index.md +++ b/docs/index.md @@ -46,10 +46,11 @@ in any combination. (That is, 4D vectors have 2×3×2 = 12 distinct coordinate s Vectors may be included in any of these data types: -- `vector.obj` objects (pure Python) +- [vector.obj](src/make_object.md) objects (pure Python) - [NumPy structured arrays](https://numpy.org/doc/stable/user/basics.rec.html) of vectors - [Awkward Arrays](https://awkward-array.org/) of vectors (possibly within variable-length lists or nested record structures) - [SymPy expressions](https://www.sympy.org/en/index.html) for symbolic (non-numeric) manipulations +- In [Numba-compiled functions](https://numba.pydata.org/), with [vector.obj](src/make_object.md) objects or Awkward Arrays Each of these "backends" provides the same suite of properties and methods, through a common "compute" library. @@ -87,7 +88,18 @@ Refer to [CONTRIBUTING.md](https://github.com/scikit-hep/vector/blob/main/.githu ## Documentation + + + + + + ```{toctree} +:maxdepth: 1 +src/make_object.md +src/make_numpy.md +src/make_awkward.md +src/make_sympy.md src/common.md src/vector2d.md src/vector3d.md diff --git a/docs/src/common.md b/docs/src/common.md index 3f952960..418fe369 100644 --- a/docs/src/common.md +++ b/docs/src/common.md @@ -2,7 +2,14 @@ Vectors of all backends, 2D/3D/4D, geometric and momentum, have the following attributes, properties, and methods. -For interfaces specialized to 2D/3D/4D or momentum vectors, see the sections after this one. +For interfaces specialized to 2D/3D/4D vectors or momentum vectors, see + +* [Interface for 2D vectors](vector2d.md) +* [Interface for 3D vectors](vector3d.md) +* [Interface for 4D vectors](vector4d.md) +* [Interface for 2D momentum](momentum2d.md) +* [Interface for 3D momentum](momentum3d.md) +* [Interface for 4D momentum](momentum4d.md) ```{eval-rst} .. autoclass:: vector._methods.VectorProtocol diff --git a/docs/src/make_awkward.md b/docs/src/make_awkward.md new file mode 100644 index 00000000..44b10a2b --- /dev/null +++ b/docs/src/make_awkward.md @@ -0,0 +1,48 @@ +# Making Awkward Arrays of vectors + +An Awkward Array of vectors is an Awkward Array containing appropriately named records, appropriately named fields, and the Vector behaviors registered in the array. Here's a complete example for illustration: + +```python +>>> import awkward as ak +>>> import vector +>>> vector.register_awkward() +>>> +>>> vec = ak.Array([ +... [{"x": 1.1, "y": 2.2}, {"x": 3.3, "y": 4.4}], +... [], +... [{"x": 5.5, "y": 6.6}], +... ], with_name="Vector2D") +>>> +>>> abs(vec) + +``` + +In the above, + +1. `vector.register_awkward()` loads Vector's `vector.backends.awkward.behavior` dict of functionality into the global `ak.behavior` +2. the Awkward Array contains records (inside variable-length lists) with field names `"x"` and `"y"` +3. those records are labeled with type name `"Vector2D"` + +and thus the `abs` function computes the magnitude of each record as `sqrt(x**2 + y**2)`, through the variable-length lists. + +It is not necessary to install Vector's behaviors globally. They could be installed in the `vec` array only by passing `behavior=vector.backends.awkward.behavior` to the [ak.Array](https://awkward-array.org/doc/main/reference/generated/ak.Array.html) constructor. + +The records can contain more fields than those that specify coordinates, which can be useful for specifying properties of a particle other than its momentum. Only the coordinate names are considered when performing vector calculations. Coordinates must be numbers (not, for instance, lists of numbers). Be careful about field names that coincide with coordinates, such as `rho` (azimuthal magnitude) and `tau` (proper time). + +The `vector.Array` function (`vector.awk` is a synonym) is an alternative to the [ak.Array](https://awkward-array.org/doc/main/reference/generated/ak.Array.html) constructor, which installs Vector's behavior in the new array (not globally in `ak.behavior`). + +The `vector.zip` function is an alternative to the [ak.zip](https://awkward-array.org/doc/main/reference/generated/ak.zip.html) function, which installs Vector's behavior in the new array (not globally in `ak.behavior`). + +Awkward Arrays can be used in [Numba-compiled functions](https://numba.pydata.org/), including those that contain vectors. + +```{eval-rst} +.. autofunction:: vector.register_awkward +``` + +```{eval-rst} +.. autofunction:: vector.Array +``` + +```{eval-rst} +.. autofunction:: vector.zip +``` diff --git a/docs/src/make_numpy.md b/docs/src/make_numpy.md new file mode 100644 index 00000000..80f96f36 --- /dev/null +++ b/docs/src/make_numpy.md @@ -0,0 +1,47 @@ +# Making NumPy arrays of vectors + +A NumPy array of vectors is a subclass of [np.ndarray](https://numpy.org/doc/stable/reference/generated/numpy.ndarray.html) with vector properties and methods. The [dtype](https://numpy.org/doc/stable/reference/arrays.dtypes.html) of this array is [structured](https://numpy.org/doc/stable/user/basics.rec.html) to specify the coordinate names; an array with fields `x` and `y` (Cartesian) performs computations differently from an array with fields `rho` and `phi` (polar). + +To create a NumPy array of vectors, + +1. use the `vector.array` function (`vector.arr` is a synonym) +2. use the `vector.VectorNumpy` class constructor +3. or cast a structured NumPy array as the appropriate class. + +## General constructor + +```{eval-rst} +.. autofunction:: vector.array +``` + +```{eval-rst} +.. autoclass:: vector.VectorNumpy +``` + +## Casting structured arrays + +[NumPy structured arrays](https://numpy.org/doc/stable/user/basics.rec.html) with appropriately named fields (see above) can be _cast_ as arrays of vectors using [np.ndarray.view](https://numpy.org/doc/stable/reference/generated/numpy.ndarray.view.html). Use the NumPy array subclass with the appropriate dimension below. + +```{eval-rst} +.. autoclass:: vector.VectorNumpy2D +``` + +```{eval-rst} +.. autoclass:: vector.MomentumNumpy2D +``` + +```{eval-rst} +.. autoclass:: vector.VectorNumpy3D +``` + +```{eval-rst} +.. autoclass:: vector.MomentumNumpy3D +``` + +```{eval-rst} +.. autoclass:: vector.VectorNumpy4D +``` + +```{eval-rst} +.. autoclass:: vector.MomentumNumpy4D +``` diff --git a/docs/src/make_object.md b/docs/src/make_object.md new file mode 100644 index 00000000..ab6c7bd0 --- /dev/null +++ b/docs/src/make_object.md @@ -0,0 +1,47 @@ +# Making vector objects + +A vector object represents a single vector, rather than an array of vectors. Lists of vector objects are slower to compute and have more memory overhead than arrays of vectors, _unless_ those computations are performed in [Numba-compiled functions](https://numba.pydata.org/). + +To create a vector object, use the `vector.obj` function with appropriate arguments for 2D/3D/4D and geometric versus momentum. + +## General constructor + +```{eval-rst} +.. autofunction:: vector.obj +``` + +## 2D constructors + +```{eval-rst} +.. autoclass:: vector.VectorObject2D + :members: from_rhophi,from_xy +``` + +```{eval-rst} +.. autoclass:: vector.MomentumObject2D + :members: from_rhophi,from_xy +``` + +## 3D constructors + +```{eval-rst} +.. autoclass:: vector.VectorObject3D + :members: from_rhophieta,from_rhophitheta,from_rhophiz,from_xyeta,from_xytheta,from_xyz +``` + +```{eval-rst} +.. autoclass:: vector.MomentumObject3D + :members: from_rhophieta,from_rhophitheta,from_rhophiz,from_xyeta,from_xytheta,from_xyz +``` + +## 4D constructors + +```{eval-rst} +.. autoclass:: vector.VectorObject4D + :members: from_rhophietat,from_rhophietatau,from_rhophithetat,from_rhophithetatau,from_rhophizt,from_rhophiztau,from_xyetat,from_xyetatau,from_xythetat,from_xythetatau,from_xyzt,from_xyztau +``` + +```{eval-rst} +.. autoclass:: vector.MomentumObject4D + :members: from_rhophietat,from_rhophietatau,from_rhophithetat,from_rhophithetatau,from_rhophizt,from_rhophiztau,from_xyetat,from_xyetatau,from_xythetat,from_xythetatau,from_xyzt,from_xyztau +``` diff --git a/docs/src/make_sympy.md b/docs/src/make_sympy.md new file mode 100644 index 00000000..47ca03f4 --- /dev/null +++ b/docs/src/make_sympy.md @@ -0,0 +1,57 @@ +# Making SymPy vector expressions + +SymPy expressions are not numerical, they're purely algebraic. However, the same Vector computations can be performed on them. + +To construct a symbolic vector, first create symbols for its components and ensure that they are real-valued (not complex), + +```python +>>> import sympy +>>> x, y, z, t, px, py, pz, eta, tau = sympy.symbols( +... "x y z t px py pz eta tau", real=True +... ) +``` + +then use one of Vector's SymPy constructors (geometric or momentum), + +```python +>>> vector.VectorSympy2D(x=x, y=y) +VectorSympy2D(x=x, y=y) +>>> +>>> vector.MomentumSympy3D(px=px, py=py, pz=pz) +MomentumSympy3D(px=px, py=py, pz=pz) +>>> +>>> vector.VectorSympy4D(x=x, y=y, eta=eta, tau=tau) +vector.VectorSympy4D(x=x, y=y, eta=eta, tau=tau) +``` + +which are documented below. + +## 2D constructors + +```{eval-rst} +.. autoclass:: vector.VectorSympy2D +``` + +```{eval-rst} +.. autoclass:: vector.MomentumSympy2D +``` + +## 3D constructors + +```{eval-rst} +.. autoclass:: vector.VectorSympy3D +``` + +```{eval-rst} +.. autoclass:: vector.MomentumSympy3D +``` + +## 4D constructors + +```{eval-rst} +.. autoclass:: vector.VectorSympy4D +``` + +```{eval-rst} +.. autoclass:: vector.MomentumSympy4D +``` diff --git a/pyproject.toml b/pyproject.toml index f0a59ddd..3a1b0096 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -62,6 +62,7 @@ optional-dependencies.dev = [ ] optional-dependencies.docs = [ "awkward>=2", + "sympy", "ipykernel", "myst-parser>0.13", "nbsphinx", diff --git a/src/vector/backends/numpy.py b/src/vector/backends/numpy.py index 98a6f6ca..056e22e4 100644 --- a/src/vector/backends/numpy.py +++ b/src/vector/backends/numpy.py @@ -1143,6 +1143,14 @@ class VectorNumpy2D(VectorNumpy, Planar, Vector2D, FloatArray): # type: ignore[ >>> vec VectorNumpy2D([(1.1, 2.1), (1.2, 2.2), (1.3, 2.3), (1.4, 2.4), (1.5, 2.5)], dtype=[('x', '>> import numpy as np + >>> import vector + >>> arr = np.array([(1.1, 2.1), (1.2, 2.2), (1.3, 2.3), (1.4, 2.4), (1.5, 2.5)], + ... dtype=[('x', float), ('y', float)]) + >>> arr.view(vector.VectorNumpy2D) + VectorNumpy2D([(1.1, 2.1), (1.2, 2.2), (1.3, 2.3), (1.4, 2.4), (1.5, 2.5)], + dtype=[('x', '>> vec MomentumNumpy2D([(1.1, 2.1), (1.2, 2.2), (1.3, 2.3), (1.4, 2.4), (1.5, 2.5)], dtype=[('x', '>> import numpy as np + >>> import vector + >>> arr = np.array([(1.1, 2.1), (1.2, 2.2), (1.3, 2.3), (1.4, 2.4), (1.5, 2.5)], + ... dtype=[('px', float), ('py', float)]) + >>> arr.view(vector.MomentumNumpy2D) + MomentumNumpy2D([(1.1, 2.1), (1.2, 2.2), (1.3, 2.3), (1.4, 2.4), (1.5, 2.5)], + dtype=[('x', '>> vec VectorNumpy3D([(1.1, 2.1, 3.1), (1.2, 2.2, 3.2), (1.3, 2.3, 3.3), (1.4, 2.4, 3.4), (1.5, 2.5, 3.5)], dtype=[('x', '>> import numpy as np + >>> import vector + >>> arr = np.array([(1.1, 2.1, 3.1), (1.2, 2.2, 3.2), (1.3, 2.3, 3.3), (1.4, 2.4, 3.4), (1.5, 2.5, 3.5)], + ... dtype=[('x', float), ('y', float), ('z', float)]) + >>> arr.view(vector.VectorNumpy3D) + VectorNumpy3D([(1.1, 2.1, 3.1), (1.2, 2.2, 3.2), (1.3, 2.3, 3.3), (1.4, 2.4, 3.4), + (1.5, 2.5, 3.5)], dtype=[('x', '>> vec MomentumNumpy3D([(1.1, 2.1, 3.1), (1.2, 2.2, 3.2), (1.3, 2.3, 3.3), (1.4, 2.4, 3.4), (1.5, 2.5, 3.5)], dtype=[('x', '>> import numpy as np + >>> import vector + >>> arr = np.array([(1.1, 2.1, 3.1), (1.2, 2.2, 3.2), (1.3, 2.3, 3.3), (1.4, 2.4, 3.4), (1.5, 2.5, 3.5)], + ... dtype=[('px', float), ('py', float), ('pz', float)]) + >>> arr.view(vector.MomentumNumpy3D) + MomentumNumpy3D([(1.1, 2.1, 3.1), (1.2, 2.2, 3.2), (1.3, 2.3, 3.3), (1.4, 2.4, 3.4), + (1.5, 2.5, 3.5)], dtype=[('x', '>> import numpy as np + >>> import vector + >>> arr = np.array([(1.1, 2.1, 3.1, 4.1), (1.2, 2.2, 3.2, 4.2), (1.3, 2.3, 3.3, 4.3), (1.4, 2.4, 3.4, 4.4), (1.5, 2.5, 3.5, 4.5)], + ... dtype=[('x', float), ('y', float), ('z', float), ('t', float)]) + >>> arr.view(vector.VectorNumpy4D) + VectorNumpy4D([(1.1, 2.1, 3.1, 4.1), (1.2, 2.2, 3.2, 4.2), (1.3, 2.3, 3.3, 4.3), + (1.4, 2.4, 3.4, 4.4), (1.5, 2.5, 3.5, 4.5)], + dtype=[('x', '>> import numpy as np + >>> import vector + >>> arr = np.array([(1.1, 2.1, 3.1, 4.1), (1.2, 2.2, 3.2, 4.2), (1.3, 2.3, 3.3, 4.3), (1.4, 2.4, 3.4, 4.4), (1.5, 2.5, 3.5, 4.5)], + ... dtype=[('px', float), ('py', float), ('pz', float), ('t', float)]) + >>> arr.view(vector.MomentumNumpy4D) + MomentumNumpy4D([(1.1, 2.1, 3.1, 4.1), (1.2, 2.2, 3.2, 4.2), (1.3, 2.3, 3.3, 4.3), + (1.4, 2.4, 3.4, 4.4), (1.5, 2.5, 3.5, 4.5)], + dtype=[('x', ' VectorObject: to make the vector a momentum vector. - Alternatively, the :class:`vector.backends.object.VectorObject2D`, - :class:`vector.backends.object.VectorObject3D`, and - :class:`vector.backends.object.VectorObject4D` classes (with momentum + Alternatively, the :class:`vector.VectorObject2D`, + :class:`vector.VectorObject3D`, and + :class:`vector.VectorObject4D` classes (with momentum subclasses) have explicit constructors: - - :meth:`vector.backends.object.VectorObject2D.from_xy` - - :meth:`vector.backends.object.VectorObject2D.from_rhophi` - - - :meth:`vector.backends.object.VectorObject3D.from_xyz` - - :meth:`vector.backends.object.VectorObject3D.from_xytheta` - - :meth:`vector.backends.object.VectorObject3D.from_xyeta` - - :meth:`vector.backends.object.VectorObject3D.from_rhophiz` - - :meth:`vector.backends.object.VectorObject3D.from_rhophitheta` - - :meth:`vector.backends.object.VectorObject3D.from_rhophieta` - - - :meth:`vector.backends.object.VectorObject4D.from_xyzt` - - :meth:`vector.backends.object.VectorObject4D.from_xyztau` - - :meth:`vector.backends.object.VectorObject4D.from_xythetat` - - :meth:`vector.backends.object.VectorObject4D.from_xythetatau` - - :meth:`vector.backends.object.VectorObject4D.from_xyetat` - - :meth:`vector.backends.object.VectorObject4D.from_xyetatau` - - :meth:`vector.backends.object.VectorObject4D.from_rhophizt` - - :meth:`vector.backends.object.VectorObject4D.from_rhophiztau` - - :meth:`vector.backends.object.VectorObject4D.from_rhophithetat` - - :meth:`vector.backends.object.VectorObject4D.from_rhophithetatau` - - :meth:`vector.backends.object.VectorObject4D.from_rhophietat` - - :meth:`vector.backends.object.VectorObject4D.from_rhophietatau` + - :meth:`vector.VectorObject2D.from_xy` + - :meth:`vector.VectorObject2D.from_rhophi` + + - :meth:`vector.VectorObject3D.from_xyz` + - :meth:`vector.VectorObject3D.from_xytheta` + - :meth:`vector.VectorObject3D.from_xyeta` + - :meth:`vector.VectorObject3D.from_rhophiz` + - :meth:`vector.VectorObject3D.from_rhophitheta` + - :meth:`vector.VectorObject3D.from_rhophieta` + + - :meth:`vector.VectorObject4D.from_xyzt` + - :meth:`vector.VectorObject4D.from_xyztau` + - :meth:`vector.VectorObject4D.from_xythetat` + - :meth:`vector.VectorObject4D.from_xythetatau` + - :meth:`vector.VectorObject4D.from_xyetat` + - :meth:`vector.VectorObject4D.from_xyetatau` + - :meth:`vector.VectorObject4D.from_rhophizt` + - :meth:`vector.VectorObject4D.from_rhophiztau` + - :meth:`vector.VectorObject4D.from_rhophithetat` + - :meth:`vector.VectorObject4D.from_rhophithetatau` + - :meth:`vector.VectorObject4D.from_rhophietat` + - :meth:`vector.VectorObject4D.from_rhophietatau` """ is_momentum = False generic_coordinates = {} diff --git a/src/vector/backends/sympy.py b/src/vector/backends/sympy.py index 19a0acfc..be253766 100644 --- a/src/vector/backends/sympy.py +++ b/src/vector/backends/sympy.py @@ -615,9 +615,6 @@ class VectorSympy2D(VectorSympy, Planar, Vector2D): >>> vec = vector.VectorSympy2D(rho=sympy.Symbol("rho"), phi=sympy.Symbol("phi")) >>> vec.rho, vec.phi (rho, phi) - >>> vec = vector.VectorObject2D(azimuthal=vector.backends.sympy.AzimuthalSympyXY(sympy.Symbol("x"), sympy.Symbol("y"))) - >>> vec.x, vec.y - (x, y) For two dimensional momentum SymPy vectors, see :class:`vector.backends.sympy.MomentumSympy2D`. @@ -759,9 +756,6 @@ class MomentumSympy2D(PlanarMomentum, VectorSympy2D): >>> vec = vector.MomentumSympy2D(pt=sympy.Symbol("pt"), phi=sympy.Symbol("phi")) >>> vec.pt, vec.phi (pt, phi) - >>> vec = vector.MomentumSympy2D(azimuthal=vector.backends.sympy.AzimuthalSympyXY(sympy.Symbol("px"), sympy.Symbol("py"))) - >>> vec.px, vec.py - (px, py) For two dimensional SymPy vectors, see :class:`vector.backends.object.VectorSympy2D`. @@ -812,12 +806,6 @@ class VectorSympy3D(VectorSympy, Spatial, Vector3D): >>> vec = vector.VectorSympy3D(rho=sympy.Symbol("rho"), phi=sympy.Symbol("phi"), eta=sympy.Symbol("eta")) >>> vec.rho, vec.phi, vec.eta (rho, phi, eta) - >>> vec = vector.VectorSympy3D( - ... azimuthal=vector.backends.sympy.AzimuthalSympyXY(sympy.Symbol("x"), sympy.Symbol("y")), - ... longitudinal=vector.backends.sympy.LongitudinalSympyTheta(sympy.Symbol("theta")) - ... ) - >>> vec.x, vec.y, vec.theta - (x, y, theta) For three dimensional momentum SymPy vectors, see :class:`vector.backends.object.MomentumSympy3D`. @@ -1025,12 +1013,6 @@ class MomentumSympy3D(SpatialMomentum, VectorSympy3D): >>> vec = vector.MomentumSympy3D(pt=sympy.Symbol("pt"), phi=sympy.Symbol("phi"), pz=sympy.Symbol("pz")) >>> vec.pt, vec.phi, vec.pz (pt, phi, pz) - >>> vec = vector.MomentumSympy3D( - ... azimuthal=vector.backends.sympy.AzimuthalSympyXY(sympy.Symbol("x"), sympy.Symbol("y")), - ... longitudinal=vector.backends.sympy.LongitudinalSympyTheta(sympy.Symbol("theta")) - ... ) - >>> vec.x, vec.y, vec.theta - (x, y, theta) For three dimensional SymPy vectors, see :class:`vector.backends.sympy.VectorSympy3D`. @@ -1093,13 +1075,6 @@ class VectorSympy4D(VectorSympy, Lorentz, Vector4D): >>> vec = vector.VectorSympy4D(rho=sympy.Symbol("rho"), phi=sympy.Symbol("phi"), eta=sympy.Symbol("eta"), tau=sympy.Symbol("tau")) >>> vec.rho, vec.phi, vec.eta, vec.tau (rho, phi, eta, tau) - >>> vec = vector.VectorSympy4D( - ... azimuthal=vector.backends.sympy.AzimuthalSympyXY(sympy.Symbol("x"), sympy.Symbol("y")), - ... longitudinal=vector.backends.sympy.LongitudinalSympyTheta(sympy.Symbol("theta")), - ... temporal=vector.backends.sympy.TemporalSympyTau(sympy.Symbol("tau")) - ... ) - >>> vec.x, vec.y, vec.theta, vec.tau - (x, y, theta, tau) For four dimensional momentum SymPy vectors, see :class:`vector.backends.sympy.MomentumSympy4D`. @@ -1386,13 +1361,6 @@ class MomentumSympy4D(LorentzMomentum, VectorSympy4D): >>> vec = vector.MomentumSympy4D(pt=sympy.Symbol("pt"), phi=sympy.Symbol("phi"), pz=sympy.Symbol("pz"), M=sympy.Symbol("M")) >>> vec.pt, vec.phi, vec.pz, vec.M (pt, phi, pz, M) - >>> vec = vector.MomentumSympy4D( - ... azimuthal=vector.backends.sympy.AzimuthalSympyXY(sympy.Symbol("x"), sympy.Symbol("y")), - ... longitudinal=vector.backends.sympy.LongitudinalSympyTheta(sympy.Symbol("theta")), - ... temporal=vector.backends.sympy.TemporalSympyTau(sympy.Symbol("tau")) - ... ) - >>> vec.x, vec.y, vec.theta, vec.tau - (x, y, theta, tau) For four dimensional SymPy vectors, see :class:`vector.backends.sympy.VectorSympy4D`. From fd1c65223110cd1a0a4d2a35c98fcda3b32f2a05 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Thu, 19 Dec 2024 00:12:11 +0000 Subject: [PATCH 14/23] style: pre-commit fixes --- docs/src/common.md | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/docs/src/common.md b/docs/src/common.md index 418fe369..291c26e6 100644 --- a/docs/src/common.md +++ b/docs/src/common.md @@ -4,12 +4,12 @@ Vectors of all backends, 2D/3D/4D, geometric and momentum, have the following at For interfaces specialized to 2D/3D/4D vectors or momentum vectors, see -* [Interface for 2D vectors](vector2d.md) -* [Interface for 3D vectors](vector3d.md) -* [Interface for 4D vectors](vector4d.md) -* [Interface for 2D momentum](momentum2d.md) -* [Interface for 3D momentum](momentum3d.md) -* [Interface for 4D momentum](momentum4d.md) +- [Interface for 2D vectors](vector2d.md) +- [Interface for 3D vectors](vector3d.md) +- [Interface for 4D vectors](vector4d.md) +- [Interface for 2D momentum](momentum2d.md) +- [Interface for 3D momentum](momentum3d.md) +- [Interface for 4D momentum](momentum4d.md) ```{eval-rst} .. autoclass:: vector._methods.VectorProtocol From 699438571f2232e4dac31291fbdb0870f689ea09 Mon Sep 17 00:00:00 2001 From: Jim Pivarski Date: Wed, 18 Dec 2024 18:26:35 -0600 Subject: [PATCH 15/23] made stubs for tutorials --- docs/index.md | 25 ++++++++++++++++++++----- docs/src/awkward.ipynb | 33 +++++++++++++++++++++++++++++++++ docs/src/numba.ipynb | 33 +++++++++++++++++++++++++++++++++ docs/src/numpy.ipynb | 33 +++++++++++++++++++++++++++++++++ docs/src/object.ipynb | 33 +++++++++++++++++++++++++++++++++ docs/src/sympy.ipynb | 33 +++++++++++++++++++++++++++++++++ 6 files changed, 185 insertions(+), 5 deletions(-) create mode 100644 docs/src/awkward.ipynb create mode 100644 docs/src/numba.ipynb create mode 100644 docs/src/numpy.ipynb create mode 100644 docs/src/object.ipynb create mode 100644 docs/src/sympy.ipynb diff --git a/docs/index.md b/docs/index.md index 5231f1e8..971fa0ea 100644 --- a/docs/index.md +++ b/docs/index.md @@ -88,18 +88,28 @@ Refer to [CONTRIBUTING.md](https://github.com/scikit-hep/vector/blob/main/.githu ## Documentation - - - - - +```{toctree} +:maxdepth: 1 +:caption: Tutorials +src/object.ipynb +src/numpy.ipynb +src/awkward.ipynb +src/numba.ipynb +src/sympy.ipynb +``` ```{toctree} :maxdepth: 1 +:caption: Vector constructors src/make_object.md src/make_numpy.md src/make_awkward.md src/make_sympy.md +``` + +```{toctree} +:maxdepth: 1 +:caption: Vector functions src/common.md src/vector2d.md src/vector3d.md @@ -107,6 +117,11 @@ src/vector4d.md src/momentum2d.md src/momentum3d.md src/momentum4d.md +``` + +```{toctree} +:maxdepth: 1 +:caption: More ways to learn src/talks.md ``` diff --git a/docs/src/awkward.ipynb b/docs/src/awkward.ipynb new file mode 100644 index 00000000..ddf39462 --- /dev/null +++ b/docs/src/awkward.ipynb @@ -0,0 +1,33 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "13ca882a-504d-409f-b6df-ac91f4e8f803", + "metadata": {}, + "source": [ + "# Awkward Arrays of vectors" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.11.10" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/docs/src/numba.ipynb b/docs/src/numba.ipynb new file mode 100644 index 00000000..e9f56cdc --- /dev/null +++ b/docs/src/numba.ipynb @@ -0,0 +1,33 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "1af51709-6860-4e5c-96c9-6a437eaed606", + "metadata": {}, + "source": [ + "# Compiling functions on vectors with Numba" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.11.10" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/docs/src/numpy.ipynb b/docs/src/numpy.ipynb new file mode 100644 index 00000000..89e32171 --- /dev/null +++ b/docs/src/numpy.ipynb @@ -0,0 +1,33 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "20258df9-4dbb-4457-945c-c9b6abe58cf9", + "metadata": {}, + "source": [ + "# NumPy arrays of vectors" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.11.10" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/docs/src/object.ipynb b/docs/src/object.ipynb new file mode 100644 index 00000000..289d45b0 --- /dev/null +++ b/docs/src/object.ipynb @@ -0,0 +1,33 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "c08fcf32-5e96-44a0-a520-f8472ca398cb", + "metadata": {}, + "source": [ + "# Vector objects" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.11.10" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/docs/src/sympy.ipynb b/docs/src/sympy.ipynb new file mode 100644 index 00000000..a7ab2d39 --- /dev/null +++ b/docs/src/sympy.ipynb @@ -0,0 +1,33 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "dd79e619-a48d-415b-9d7a-7dd5b3970475", + "metadata": {}, + "source": [ + "# Vector expressions with SymPy" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.11.10" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} From 294db57b7096d5d75a57a3dadbe2bb9bd123e2e7 Mon Sep 17 00:00:00 2001 From: Jim Pivarski Date: Wed, 18 Dec 2024 18:42:23 -0600 Subject: [PATCH 16/23] use SVG and make README match readthedocs --- README.md | 99 +++++++++++++++++++++++++++++++++++++++++++++++++-- docs/index.md | 4 +-- 2 files changed, 98 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 4b146106..831cb60e 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -Vector logo +Vector logo # Vector: arrays of 2D, 3D, and Lorentz vectors @@ -16,14 +16,107 @@ [![LICENSE][license-badge]][license-link] [![Scikit-HEP][sk-badge]][sk-link] -## Overview - ## Installation +You can install Vector with [pip](https://pypi.org/project/vector/) and [conda](https://anaconda.org/conda-forge/vector). + +```bash +pip install vector +``` + +## Introduction + +Vector is a Python library for 2D and 3D spatial vectors, as well as 4D space-time vectors. It is especially intended for performing geometric calculations on _arrays of vectors_, rather than one vector at a time in a Python for loop. + +Vector is part of the [Scikit-HEP project](https://scikit-hep.org/), High Energy Physics (HEP) tools in Python. + +### Coordinate systems + +Vectors may be expressed in any of these coordinate systems: + +- the azimuthal plane may be Cartesian `x` `y` or polar `rho` ($\rho$) `phi` ($\phi$) +- the longitudinal axis may be Cartesian `z`, polar `theta` ($\theta$), or pseudorapidity `eta` ($\eta$) +- the temporal component for space-time vectors may be Cartesian `t` or proper time `tau` ($\tau$) + +in any combination. (That is, 4D vectors have 2×3×2 = 12 distinct coordinate systems.) + +Diagram of coordinate systems + +### Backends + +Vectors may be included in any of these data types: + +- [vector.obj](https://vector.readthedocs.io/en/latest/src/make_object.html) objects (pure Python) +- [NumPy structured arrays](https://numpy.org/doc/stable/user/basics.rec.html) of vectors +- [Awkward Arrays](https://awkward-array.org/) of vectors (possibly within variable-length lists or nested record structures) +- [SymPy expressions](https://www.sympy.org/en/index.html) for symbolic (non-numeric) manipulations +- In [Numba-compiled functions](https://numba.pydata.org/), with [vector.obj](https://vector.readthedocs.io/en/latest/src/make_object.html) objects or Awkward Arrays + +Each of these "backends" provides the same suite of properties and methods, through a common "compute" library. + +### Geometric versus momentum + +Finally, vectors come in two flavors: + +- geometric: only one name for each property or method +- momentum: same property or method can be accessed with several synonyms, such as `pt` ($p_T$, transverse momentum) for the azimuthal magnitude `rho` ($\rho$) and `energy` and `mass` for the Cartesian time `t` and proper time `tau` ($\tau$). + +### Familiar conventions + +Names and coordinate conventions were chosen to align with [ROOT](https://root.cern/)'s [TLorentzVector](https://root.cern.ch/doc/master/classTLorentzVector.html) and [Math::LorentzVector](https://root.cern.ch/doc/master/classROOT_1_1Math_1_1LorentzVector.html), as well as [scikit-hep/math](https://github.com/scikit-hep/scikit-hep/tree/master/skhep/math), [uproot-methods TLorentzVector](https://github.com/scikit-hep/uproot3-methods/blob/master/uproot3_methods/classes/TLorentzVector.py), [henryiii/hepvector](https://github.com/henryiii/hepvector), and [coffea.nanoevents.methods.vector](https://coffea-hep.readthedocs.io/en/latest/modules/coffea.nanoevents.methods.vector.html). + ## Getting help +- Source code on GitHub: [scikit-hep/vector](https://github.com/scikit-hep/vector) +- Report bugs and request features on the [GitHub Issues page](https://github.com/scikit-hep/vector/issues) +- Ask questions on the [GitHub Discussions page](https://github.com/scikit-hep/vector/discussions) +- Real-time chat on Gitter: [Scikit-HEP/Vector](https://gitter.im/Scikit-HEP/vector) + ## Contributing to Vector +If you want to contribute to Vector, [pull requests](https://github.com/scikit-hep/vector/pulls) are welcome! + +Please install the latest version of the `main` branch from source or a fork: + +```bash +git clone https://github.com/scikit-hep/vector.git +cd vector +pip install -e . +``` + +Refer to [CONTRIBUTING.md](https://github.com/scikit-hep/vector/blob/main/.github/CONTRIBUTING.md) for more. + +## Documentation + +### Tutorials + +* [Vector objects](https://vector.readthedocs.io/en/latest/src/object.html) +* [NumPy arrays of vectors](https://vector.readthedocs.io/en/latest/src/numpy.html) +* [Awkward Arrays of vectors](https://vector.readthedocs.io/en/latest/src/awkward.html) +* [Compiling functions on vectors with Numba](https://vector.readthedocs.io/en/latest/src/numba.html) +* [Vector expressions with SymPy](https://vector.readthedocs.io/en/latest/src/sympy.html) + +### Vector constructors + +* [Making vector objects](https://vector.readthedocs.io/en/latest/src/make_object.html) +* [Making NumPy arrays of vectors](https://vector.readthedocs.io/en/latest/src/make_numpy.html) +* [Making Awkward Arrays of vectors](https://vector.readthedocs.io/en/latest/src/make_awkward.html) +* [Making SymPy vector expressions](https://vector.readthedocs.io/en/latest/src/make_sympy.html) + +### Vector functions + +* [Interface for all vectors](https://vector.readthedocs.io/en/latest/src/common.html) +* [Interface for 2D vectors](https://vector.readthedocs.io/en/latest/src/vector2d.html) +* [Interface for 3D vectors](https://vector.readthedocs.io/en/latest/src/vector3d.html) +* [Interface for 4D vectors](https://vector.readthedocs.io/en/latest/src/vector4d.html) +* [Interface for 2D momentum](https://vector.readthedocs.io/en/latest/src/momentum2d.html) +* [Interface for 3D momentum](https://vector.readthedocs.io/en/latest/src/momentum3d.html) +* [Interface for 4D momentum](https://vector.readthedocs.io/en/latest/src/momentum4d.html) + +### More ways to learn + +* [Presentations about Vector](https://vector.readthedocs.io/en/latest/src/talks.html) + ## Contributors Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/docs/en/emoji-key)): diff --git a/docs/index.md b/docs/index.md index 971fa0ea..99ccd37f 100644 --- a/docs/index.md +++ b/docs/index.md @@ -1,4 +1,4 @@ -![](_images/vector-logo.png) +![](_images/LogoSrc.svg) # Overview @@ -40,7 +40,7 @@ Vectors may be expressed in any of these coordinate systems: in any combination. (That is, 4D vectors have 2×3×2 = 12 distinct coordinate systems.) -![](_images/coordinate-systems.png) +![](_images/coordinate-systems.svg) ### Backends From f1296317d24f3f3b2d955e04ff45b1c49d9a3fbb Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Thu, 19 Dec 2024 00:43:11 +0000 Subject: [PATCH 17/23] style: pre-commit fixes --- README.md | 34 +++++++++++++++++----------------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/README.md b/README.md index 831cb60e..126d17c2 100644 --- a/README.md +++ b/README.md @@ -90,32 +90,32 @@ Refer to [CONTRIBUTING.md](https://github.com/scikit-hep/vector/blob/main/.githu ### Tutorials -* [Vector objects](https://vector.readthedocs.io/en/latest/src/object.html) -* [NumPy arrays of vectors](https://vector.readthedocs.io/en/latest/src/numpy.html) -* [Awkward Arrays of vectors](https://vector.readthedocs.io/en/latest/src/awkward.html) -* [Compiling functions on vectors with Numba](https://vector.readthedocs.io/en/latest/src/numba.html) -* [Vector expressions with SymPy](https://vector.readthedocs.io/en/latest/src/sympy.html) +- [Vector objects](https://vector.readthedocs.io/en/latest/src/object.html) +- [NumPy arrays of vectors](https://vector.readthedocs.io/en/latest/src/numpy.html) +- [Awkward Arrays of vectors](https://vector.readthedocs.io/en/latest/src/awkward.html) +- [Compiling functions on vectors with Numba](https://vector.readthedocs.io/en/latest/src/numba.html) +- [Vector expressions with SymPy](https://vector.readthedocs.io/en/latest/src/sympy.html) ### Vector constructors -* [Making vector objects](https://vector.readthedocs.io/en/latest/src/make_object.html) -* [Making NumPy arrays of vectors](https://vector.readthedocs.io/en/latest/src/make_numpy.html) -* [Making Awkward Arrays of vectors](https://vector.readthedocs.io/en/latest/src/make_awkward.html) -* [Making SymPy vector expressions](https://vector.readthedocs.io/en/latest/src/make_sympy.html) +- [Making vector objects](https://vector.readthedocs.io/en/latest/src/make_object.html) +- [Making NumPy arrays of vectors](https://vector.readthedocs.io/en/latest/src/make_numpy.html) +- [Making Awkward Arrays of vectors](https://vector.readthedocs.io/en/latest/src/make_awkward.html) +- [Making SymPy vector expressions](https://vector.readthedocs.io/en/latest/src/make_sympy.html) ### Vector functions -* [Interface for all vectors](https://vector.readthedocs.io/en/latest/src/common.html) -* [Interface for 2D vectors](https://vector.readthedocs.io/en/latest/src/vector2d.html) -* [Interface for 3D vectors](https://vector.readthedocs.io/en/latest/src/vector3d.html) -* [Interface for 4D vectors](https://vector.readthedocs.io/en/latest/src/vector4d.html) -* [Interface for 2D momentum](https://vector.readthedocs.io/en/latest/src/momentum2d.html) -* [Interface for 3D momentum](https://vector.readthedocs.io/en/latest/src/momentum3d.html) -* [Interface for 4D momentum](https://vector.readthedocs.io/en/latest/src/momentum4d.html) +- [Interface for all vectors](https://vector.readthedocs.io/en/latest/src/common.html) +- [Interface for 2D vectors](https://vector.readthedocs.io/en/latest/src/vector2d.html) +- [Interface for 3D vectors](https://vector.readthedocs.io/en/latest/src/vector3d.html) +- [Interface for 4D vectors](https://vector.readthedocs.io/en/latest/src/vector4d.html) +- [Interface for 2D momentum](https://vector.readthedocs.io/en/latest/src/momentum2d.html) +- [Interface for 3D momentum](https://vector.readthedocs.io/en/latest/src/momentum3d.html) +- [Interface for 4D momentum](https://vector.readthedocs.io/en/latest/src/momentum4d.html) ### More ways to learn -* [Presentations about Vector](https://vector.readthedocs.io/en/latest/src/talks.html) +- [Presentations about Vector](https://vector.readthedocs.io/en/latest/src/talks.html) ## Contributors From 3cb81568080e32502a2234f0420effd1b7e6aedd Mon Sep 17 00:00:00 2001 From: Jim Pivarski Date: Wed, 18 Dec 2024 18:43:21 -0600 Subject: [PATCH 18/23] pre-commit --- README.md | 34 +++++++++++++++++----------------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/README.md b/README.md index 831cb60e..126d17c2 100644 --- a/README.md +++ b/README.md @@ -90,32 +90,32 @@ Refer to [CONTRIBUTING.md](https://github.com/scikit-hep/vector/blob/main/.githu ### Tutorials -* [Vector objects](https://vector.readthedocs.io/en/latest/src/object.html) -* [NumPy arrays of vectors](https://vector.readthedocs.io/en/latest/src/numpy.html) -* [Awkward Arrays of vectors](https://vector.readthedocs.io/en/latest/src/awkward.html) -* [Compiling functions on vectors with Numba](https://vector.readthedocs.io/en/latest/src/numba.html) -* [Vector expressions with SymPy](https://vector.readthedocs.io/en/latest/src/sympy.html) +- [Vector objects](https://vector.readthedocs.io/en/latest/src/object.html) +- [NumPy arrays of vectors](https://vector.readthedocs.io/en/latest/src/numpy.html) +- [Awkward Arrays of vectors](https://vector.readthedocs.io/en/latest/src/awkward.html) +- [Compiling functions on vectors with Numba](https://vector.readthedocs.io/en/latest/src/numba.html) +- [Vector expressions with SymPy](https://vector.readthedocs.io/en/latest/src/sympy.html) ### Vector constructors -* [Making vector objects](https://vector.readthedocs.io/en/latest/src/make_object.html) -* [Making NumPy arrays of vectors](https://vector.readthedocs.io/en/latest/src/make_numpy.html) -* [Making Awkward Arrays of vectors](https://vector.readthedocs.io/en/latest/src/make_awkward.html) -* [Making SymPy vector expressions](https://vector.readthedocs.io/en/latest/src/make_sympy.html) +- [Making vector objects](https://vector.readthedocs.io/en/latest/src/make_object.html) +- [Making NumPy arrays of vectors](https://vector.readthedocs.io/en/latest/src/make_numpy.html) +- [Making Awkward Arrays of vectors](https://vector.readthedocs.io/en/latest/src/make_awkward.html) +- [Making SymPy vector expressions](https://vector.readthedocs.io/en/latest/src/make_sympy.html) ### Vector functions -* [Interface for all vectors](https://vector.readthedocs.io/en/latest/src/common.html) -* [Interface for 2D vectors](https://vector.readthedocs.io/en/latest/src/vector2d.html) -* [Interface for 3D vectors](https://vector.readthedocs.io/en/latest/src/vector3d.html) -* [Interface for 4D vectors](https://vector.readthedocs.io/en/latest/src/vector4d.html) -* [Interface for 2D momentum](https://vector.readthedocs.io/en/latest/src/momentum2d.html) -* [Interface for 3D momentum](https://vector.readthedocs.io/en/latest/src/momentum3d.html) -* [Interface for 4D momentum](https://vector.readthedocs.io/en/latest/src/momentum4d.html) +- [Interface for all vectors](https://vector.readthedocs.io/en/latest/src/common.html) +- [Interface for 2D vectors](https://vector.readthedocs.io/en/latest/src/vector2d.html) +- [Interface for 3D vectors](https://vector.readthedocs.io/en/latest/src/vector3d.html) +- [Interface for 4D vectors](https://vector.readthedocs.io/en/latest/src/vector4d.html) +- [Interface for 2D momentum](https://vector.readthedocs.io/en/latest/src/momentum2d.html) +- [Interface for 3D momentum](https://vector.readthedocs.io/en/latest/src/momentum3d.html) +- [Interface for 4D momentum](https://vector.readthedocs.io/en/latest/src/momentum4d.html) ### More ways to learn -* [Presentations about Vector](https://vector.readthedocs.io/en/latest/src/talks.html) +- [Presentations about Vector](https://vector.readthedocs.io/en/latest/src/talks.html) ## Contributors From ce1ef28a130753a65ce05ea076354d93fb34b580 Mon Sep 17 00:00:00 2001 From: Jim Pivarski Date: Thu, 19 Dec 2024 15:06:01 -0600 Subject: [PATCH 19/23] finished the 'Vector objects' tutorial --- docs/src/awkward.ipynb | 16 + docs/src/numba.ipynb | 16 + docs/src/numpy.ipynb | 16 + docs/src/object.ipynb | 962 ++++++++++++++++++++++++++++++++++++++++ docs/src/sympy.ipynb | 16 + pyproject.toml | 4 +- tests/test_notebooks.py | 7 +- 7 files changed, 1031 insertions(+), 6 deletions(-) diff --git a/docs/src/awkward.ipynb b/docs/src/awkward.ipynb index ddf39462..b69019a7 100644 --- a/docs/src/awkward.ipynb +++ b/docs/src/awkward.ipynb @@ -7,6 +7,22 @@ "source": [ "# Awkward Arrays of vectors" ] + }, + { + "cell_type": "markdown", + "id": "26894013-8d55-45b5-9592-6a82c6e7440a", + "metadata": {}, + "source": [ + "First, [install](index.md#installation) and import Vector." + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "id": "8f504534-1fa5-4dfb-b0c9-f7a2b2d12eae", + "metadata": {}, + "outputs": [], + "source": [] } ], "metadata": { diff --git a/docs/src/numba.ipynb b/docs/src/numba.ipynb index e9f56cdc..4c5f9bcd 100644 --- a/docs/src/numba.ipynb +++ b/docs/src/numba.ipynb @@ -7,6 +7,22 @@ "source": [ "# Compiling functions on vectors with Numba" ] + }, + { + "cell_type": "markdown", + "id": "26a7599a-5b33-4f6d-85d2-788295abe176", + "metadata": {}, + "source": [ + "First, [install](index.md#installation) and import Vector." + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "id": "2ccf22f1-fc21-4afe-8e46-baef45a1e85b", + "metadata": {}, + "outputs": [], + "source": [] } ], "metadata": { diff --git a/docs/src/numpy.ipynb b/docs/src/numpy.ipynb index 89e32171..d2ad995c 100644 --- a/docs/src/numpy.ipynb +++ b/docs/src/numpy.ipynb @@ -7,6 +7,22 @@ "source": [ "# NumPy arrays of vectors" ] + }, + { + "cell_type": "markdown", + "id": "1144533f-0290-43f2-a9f2-adc9d042ed1a", + "metadata": {}, + "source": [ + "First, [install](index.md#installation) and import Vector." + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "id": "04ce97c4-d7db-458a-9976-68af8eeb9b58", + "metadata": {}, + "outputs": [], + "source": [] } ], "metadata": { diff --git a/docs/src/object.ipynb b/docs/src/object.ipynb index 289d45b0..7f7848dc 100644 --- a/docs/src/object.ipynb +++ b/docs/src/object.ipynb @@ -7,6 +7,968 @@ "source": [ "# Vector objects" ] + }, + { + "cell_type": "markdown", + "id": "495d94df-054f-47dc-bdf3-6ba9cea4b4d6", + "metadata": {}, + "source": [ + "First, [install](index.md#installation) and import Vector." + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "id": "95d2e6db-0b23-4d6e-8b5a-739c5f2676c7", + "metadata": {}, + "outputs": [], + "source": [ + "import vector" + ] + }, + { + "cell_type": "markdown", + "id": "8fd65e09-8b31-4b65-b3c5-3d7ab6baba9d", + "metadata": {}, + "source": [ + "## Making a vector" + ] + }, + { + "cell_type": "markdown", + "id": "b32006b4-6577-4a77-bfff-9ad33ec1455f", + "metadata": {}, + "source": [ + "If you only need a few vectors or performance is not a concern, you can make vectors as Python objects. The basic constructor for that is [vector.obj](make_object.md), and the type of vector (2D/3D/4D, coordinate system, geometric or momentum) depends on the pattern of keyword arguments provided." + ] + }, + { + "cell_type": "markdown", + "id": "7384e13c-d120-473a-9ebb-2e26ec95ec41", + "metadata": {}, + "source": [ + "Below is a 2D, Cartesian, geometric vector:" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "id": "b790c4c5-f586-4da3-bff6-401a880e9fd6", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "VectorObject2D(x=1.1, y=2.2)" + ] + }, + "execution_count": 2, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "vector.obj(x=1.1, y=2.2)" + ] + }, + { + "cell_type": "markdown", + "id": "a0fb4212-f434-4017-af59-913ec5e34945", + "metadata": {}, + "source": [ + "Below is a 3D, Cartesian, momentum vector:" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "id": "42f34307-ecc8-4cff-b2d7-e4029acf0793", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "MomentumObject3D(px=1.1, py=2.2, pz=3.3)" + ] + }, + "execution_count": 3, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "vector.obj(px=1.1, py=2.2, pz=3.3)" + ] + }, + { + "cell_type": "markdown", + "id": "94789dfa-f0b0-41ad-949a-786097ba63de", + "metadata": {}, + "source": [ + "Below is a 4D geometric vector that has Cartesian azimuthal components (`x` and `y`), the longitudinal component is expressed in [pseudorapidity](https://en.wikipedia.org/wiki/Pseudorapidity), and the temporal component is expressed using proper time:" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "id": "02fddde9-9998-4699-b8a6-ce025ec4beab", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "VectorObject4D(x=1.1, y=2.2, eta=3.3, tau=4.4)" + ] + }, + "execution_count": 4, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "vector.obj(x=1.1, y=2.2, eta=3.3, tau=4.4)" + ] + }, + { + "cell_type": "markdown", + "id": "075849bd-942d-4ef6-abee-b1f7920c7225", + "metadata": {}, + "source": [ + "The allowed keyword arguments for 2D vectors are:\n", + "\n", + "* `x` and `y` for Cartesian azimuthal coordinates,\n", + "* `px` ($p_x$) and `py` ($p_y$) for momentum,\n", + "* `rho` ($\\rho$) and `phi` ($\\phi$) for polar azimuthal coordinates,\n", + "* `pt` ($p_T$) and `phi` ($\\phi$) for momentum.\n", + "\n", + "For 3D vectors, you need the above and:\n", + "\n", + "* `z` for the Cartesian longitudinal coordinate,\n", + "* `pz` ($p_z$) for momentum,\n", + "* `theta` ($\\theta$) for the spherical polar angle (from $0$ to $\\pi$, inclusive),\n", + "* `eta` ($\\eta$) for [pseudorapidity](https://en.wikipedia.org/wiki/Pseudorapidity), which is a kind of spherical polar angle: $\\eta = -\\ln \\left[ \\tan \\left( \\frac{\\theta}{2} \\right) \\right]$.\n", + "\n", + "For 4D vectors, you need the above and:\n", + "\n", + "* `t` for the Cartesian temporal coordinate,\n", + "* `e`, `E`, or `energy` to get four-momentum,\n", + "* `tau` ($\\tau$) for the \"proper time\" (temporal coordinate in the vector’s rest coordinate system),\n", + "* `m`, `M`, or `mass` to get four-momentum.\n", + "\n", + "Since momentum vectors have momentum-synonyms in addition to the geometrical names, any momentum-synonym will make the whole vector a momentum vector. The meanings of the geometric components are illustrated below:\n", + "\n", + "\n", + "\n", + "This one constructor, [vector.obj](make_object.md), can output a variety of data types. If you want to control the type more explicitly, you can use [vector.VectorObject2D](make_object.md#vector.VectorObject2D), [vector.MomentumObject2D](make_object.md#vector.MomentumObject2D), [vector.VectorObject3D](make_object.md#vector.VectorObject3D), [vector.MomentumObject3D](make_object.md#vector.MomentumObject3D), [vector.VectorObject4D](make_object.md#vector.VectorObject4D), and [vector.MomentumObject4D](make_object.md#vector.MomentumObject4D) to construct or check the type explicitly. These classes also have `from_*` methods to construct vectors from positional arguments, rather than keyword arguments." + ] + }, + { + "cell_type": "markdown", + "id": "d9a23b9b-a19f-49a9-b1ae-7b86c51a17f1", + "metadata": {}, + "source": [ + "## Using a vector" + ] + }, + { + "cell_type": "markdown", + "id": "959d7c4e-f7a6-4220-877a-dfedc6a873b7", + "metadata": {}, + "source": [ + "Vector objects have a suite of properties and methods appropriate to their type (2D/3D/4D, geometric or momentum). For example, to compute the cross-product of two vectors, you would use [cross](vector3d.md#vector._methods.VectorProtocolSpatial.cross):" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "id": "51d9350f-66e7-447c-840c-ed6bd899bd37", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "VectorObject3D(x=6, y=0, z=-3)" + ] + }, + "execution_count": 5, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "a = vector.obj(x=2, y=3, z=4)\n", + "b = vector.obj(x=1, y=0, z=2)\n", + "\n", + "a.cross(b)" + ] + }, + { + "cell_type": "markdown", + "id": "98530a7c-5413-4268-9312-91e1e8054c50", + "metadata": {}, + "source": [ + "or to compute the angle between them, you would use [deltaangle](vector3d.md#vector._methods.VectorProtocolSpatial.deltaangle):" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "id": "eee16a4d-b15b-434b-868b-ef7a11d8e101", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "0.590872750145419" + ] + }, + "execution_count": 6, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "a.deltaangle(b)" + ] + }, + { + "cell_type": "markdown", + "id": "ac749138-ed71-4a07-92a8-af33785eb5ea", + "metadata": {}, + "source": [ + "or to compute their sum, you would use `+`:" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "id": "5686fc89-5cb0-4a5f-b521-41dd7d0a3b10", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "VectorObject3D(x=3, y=3, z=6)" + ] + }, + "execution_count": 7, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "a + b" + ] + }, + { + "cell_type": "markdown", + "id": "eeaf4807-b338-4f17-ba35-a7a3f7f43d97", + "metadata": {}, + "source": [ + "In this last example, the `+` operator overloads the [add](common.md#vector._methods.VectorProtocol.add) method. Similarly, multiplication between a vector and a scalar number overloads [scale](common.md#vector._methods.VectorProtocol.scale), etc. Since they overload standard operators, vectors can be used in Python built-in functions like [sum](https://docs.python.org/3/library/functions.html#sum), as long as you provide a `start`:" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "id": "10b5f3e3-db5d-421e-89a4-5929fe720af1", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "VectorObject2D(x=45, y=4.5)" + ] + }, + "execution_count": 8, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "vs = [vector.obj(x=x, y=x / 10) for x in range(10)]\n", + "\n", + "sum(vs, start=vector.obj(x=0, y=0))" + ] + }, + { + "cell_type": "markdown", + "id": "32c06273-06ae-4cfa-8e79-f55586148283", + "metadata": {}, + "source": [ + "The same applies to [abs](https://docs.python.org/3/library/functions.html#abs) for the vector's magnitude, but note that this depends on the number of dimensions:" + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "id": "e821c6d7-db8c-47cd-93a0-5eb7bf3e023f", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "5.0" + ] + }, + "execution_count": 9, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "abs(vector.obj(x=3, y=4)) # sqrt(3**2 + 4**2)" + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "id": "bf89db7e-6326-46e4-8add-fa5e7e7df799", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "3.0" + ] + }, + "execution_count": 10, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "abs(vector.obj(x=1, y=2, z=2)) # sqrt(1**2 + 2**2 + 2**2)" + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "id": "9f6d19e6-ca20-4f8b-a8d9-57950c24655b", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "3.0" + ] + }, + "execution_count": 11, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "abs(vector.obj(x=3, y=3, z=3, t=6)) # sqrt(6**2 - 3**2 - 3**2 - 3**2)" + ] + }, + { + "cell_type": "markdown", + "id": "2d9407af-0641-403c-822c-d89344dd95db", + "metadata": {}, + "source": [ + "Equality ([equal](common.md#vector._methods.VectorProtocol.equal)) and inequality ([not_equal](common.md#vector._methods.VectorProtocol.not_equal)) are defined:" + ] + }, + { + "cell_type": "code", + "execution_count": 12, + "id": "41ca1487-4a33-493f-9d9b-dd452255ae73", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "True" + ] + }, + "execution_count": 12, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "vector.obj(x=3, y=4) == vector.obj(x=3, y=4)" + ] + }, + { + "cell_type": "markdown", + "id": "bf85dc4f-88de-4e07-9303-c1f364a0a227", + "metadata": {}, + "source": [ + "But you'll probably want to use [isclose](common.md#vector._methods.VectorProtocol.isclose) (and possibly specify tolerances):" + ] + }, + { + "cell_type": "code", + "execution_count": 13, + "id": "7604a176-efd9-4cbd-947c-90c8bbb20685", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "False" + ] + }, + "execution_count": 13, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "vector.obj(x=3, y=4) == vector.obj(rho=5, phi=0.9272952180016122)" + ] + }, + { + "cell_type": "code", + "execution_count": 14, + "id": "0a3d1aa1-eeda-486a-84b2-e9d43e102117", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "True" + ] + }, + "execution_count": 14, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "vector.obj(x=3, y=4).isclose(vector.obj(rho=5, phi=0.9272952180016122))" + ] + }, + { + "cell_type": "markdown", + "id": "70a3c4b3-8a81-4bb2-b6f7-1ebb57889c0a", + "metadata": {}, + "source": [ + "The full set of properties and methods available to each type of vector (2D/3D/4D, geometric or momentum) is described in\n", + "\n", + "* [Interface for all vectors](common.md)\n", + "* [Interface for 2D vectors](vector2d.md)\n", + "* [Interface for 3D vectors](vector3d.md)\n", + "* [Interface for 4D vectors](vector4d.md)\n", + "* [Interface for 2D momentum](momentum2d.md)\n", + "* [Interface for 3D momentum](momentum3d.md)\n", + "* [Interface for 4D momentum](momentum4d.md)" + ] + }, + { + "cell_type": "markdown", + "id": "6d1f1795-1051-4b32-b9b8-222a2f2228f9", + "metadata": {}, + "source": [ + "## Using coordinate systems" + ] + }, + { + "cell_type": "markdown", + "id": "0e80cf47-801f-421a-818a-e70db3356a5a", + "metadata": {}, + "source": [ + "A vector can be constructed using any combination of coordinate systems and computations will be performed using whatever coordinate system it has. Thus, after creating vectors, you can write code that does not depend on the coordinate system—it becomes a hidden implementation detail." + ] + }, + { + "cell_type": "code", + "execution_count": 15, + "id": "a96ddaad-7c6b-487f-8d23-fdd2fde159bc", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "VectorObject2D(x=5.0, y=1.0)" + ] + }, + "execution_count": 15, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "a = vector.obj(x=2, y=1)\n", + "b = vector.obj(rho=3, phi=0)\n", + "\n", + "a + b" + ] + }, + { + "cell_type": "markdown", + "id": "4f4552b3-bd21-4760-90fc-92002a2f14ad", + "metadata": {}, + "source": [ + "Some of the properties of a vector are coordinates, so you can use Vector to convert coordinates." + ] + }, + { + "cell_type": "code", + "execution_count": 16, + "id": "d0ce4192-f634-40f3-900a-4d143b0050d6", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "(2.23606797749979, 0.4636476090008061)" + ] + }, + "execution_count": 16, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "a.rho, a.phi" + ] + }, + { + "cell_type": "markdown", + "id": "633a6970-6986-40e3-a3aa-1fde0edc0a0a", + "metadata": {}, + "source": [ + "Since the way that you access the original coordinates is the same as the way that you access converted coordinates," + ] + }, + { + "cell_type": "code", + "execution_count": 17, + "id": "38006968-210d-4568-a94a-e13d31b048a7", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "(2, 1)" + ] + }, + "execution_count": 17, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "a.x, a.y" + ] + }, + { + "cell_type": "markdown", + "id": "31f7e65a-ed4e-48a8-a761-4c70cf81eca4", + "metadata": {}, + "source": [ + "these conversions are part of the coordinate-abstraction.\n", + "\n", + "For reasons of numerical precision, you might want to open this black box and explicitly change the coordinate system. These methods start with `to_*`:" + ] + }, + { + "cell_type": "code", + "execution_count": 18, + "id": "83c22d5b-a251-42c2-9527-87695c9d5dac", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "VectorObject2D(rho=2.23606797749979, phi=0.4636476090008061)" + ] + }, + "execution_count": 18, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "a.to_rhophi()" + ] + }, + { + "cell_type": "code", + "execution_count": 19, + "id": "01754e13-3c0c-4b1e-be0e-0e0d01585b63", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "VectorObject2D(x=3.0, y=0.0)" + ] + }, + "execution_count": 19, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "b.to_xy()" + ] + }, + { + "cell_type": "markdown", + "id": "3c4a7d35-74a6-4d90-b195-68fc6a77cbec", + "metadata": {}, + "source": [ + "## Geometric versus momentum vectors" + ] + }, + { + "cell_type": "markdown", + "id": "459d089b-8569-4eff-a316-6ff40cc1b145", + "metadata": {}, + "source": [ + "Vectors come in two flavors:\n", + "\n", + "* geometric: only one name for each property or method\n", + "* momentum: same property or method can be accessed with several synonyms (which assume that the vector is a [momentum](https://en.wikipedia.org/wiki/Momentum) vector)." + ] + }, + { + "cell_type": "code", + "execution_count": 20, + "id": "e86873c1-f8aa-447d-b265-2a6b42b9e1ba", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "VectorObject3D(x=1, y=2, z=3)" + ] + }, + "execution_count": 20, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "v = vector.obj(x=1, y=2, z=3)\n", + "v" + ] + }, + { + "cell_type": "code", + "execution_count": 21, + "id": "0d4fab89-cf8c-43f9-a7d9-34083ac70eb7", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "MomentumObject3D(px=1, py=2, pz=3)" + ] + }, + "execution_count": 21, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "p = vector.obj(px=1, py=2, pz=3)\n", + "p" + ] + }, + { + "cell_type": "markdown", + "id": "1f19524b-e98a-461e-a098-6d5b803dc693", + "metadata": {}, + "source": [ + "Calculations are the same in both cases:" + ] + }, + { + "cell_type": "code", + "execution_count": 22, + "id": "0eaf2b80-9e94-41bb-b251-1b713df0e829", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "3.7416573867739413" + ] + }, + "execution_count": 22, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "abs(v)" + ] + }, + { + "cell_type": "code", + "execution_count": 23, + "id": "f1c35d52-9e8d-44d1-b1e8-a4c0f3405370", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "3.7416573867739413" + ] + }, + "execution_count": 23, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "abs(p)" + ] + }, + { + "cell_type": "markdown", + "id": "dec60082-29ca-47b8-b9c4-3d68ff967a06", + "metadata": {}, + "source": [ + "but there are more ways to express some operations:" + ] + }, + { + "cell_type": "code", + "execution_count": 24, + "id": "1a3540ed-c4f1-4df0-af75-0a0c75b83c89", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "2.23606797749979" + ] + }, + "execution_count": 24, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "v.rho" + ] + }, + { + "cell_type": "code", + "execution_count": 25, + "id": "061c00d9-2134-41bb-9275-a81eccb4a71c", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "2.23606797749979" + ] + }, + "execution_count": 25, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "p.rho" + ] + }, + { + "cell_type": "code", + "execution_count": 26, + "id": "0fb9656b-97d7-49f0-b61e-c99bccf2e31d", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "2.23606797749979" + ] + }, + "execution_count": 26, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "p.pt" + ] + }, + { + "cell_type": "markdown", + "id": "375ac938-9ef0-493b-b94a-52cab0c1b359", + "metadata": {}, + "source": [ + "The geometric vector satisfies the [Zen of Python](https://en.wikipedia.org/wiki/Zen_of_Python) stipulation that\n", + "\n", + "> There should be one-- and preferably only one --obvious way to do it.\n", + "\n", + "and code that uses, for example, \"`pt`\" to specify \"distance from the beamline\" is obfuscated code. However, the most common use for these vectors in High Energy Physics (HEP) is to represent the momentum of particles. For that purpose, using \"`rho`\" for $p_T$ is not self-documenting.\n", + "\n", + "Momentum vectors have all of the same properties and methods as geometric vectors _as well as_ momentum synonyms. In some cases, there are multiple momentum synonyms for adherence to different conventions. For example, energy and mass (the [temporal component of momentum](https://en.wikipedia.org/wiki/Four-momentum), as Cartesian and proper time, respectively) have four different spellings:\n", + "\n", + "| energy spelling | mass spelling | rationale |\n", + "|:--:|:--:|:--|\n", + "| `t` | `tau` | geometric coordinates; $\\tau$ for proper time is conventional |\n", + "| `energy` | `mass` | full names are more self-documenting in the code |\n", + "| `e` | `m` | all other coordinates are lower-case single letters (sometimes Greek letters) |\n", + "| `E` | `M` | capital E and M (only!) are used in other HEP vector libraries |\n", + "\n", + "If any momentum components are used to construct a vector (or if [vector.MomentumObject2D](make_object.md#vector.MomentumObject2D), [vector.MomentumObject3D](make_object.md#vector.MomentumObject3D), or [vector.MomentumObject4D](make_object.md#vector.MomentumObject4D) are used explicitly), then the vector is momentum and all synonyms become available." + ] + }, + { + "cell_type": "markdown", + "id": "0560e95f-48e9-454d-9db1-f85386d5e9ed", + "metadata": {}, + "source": [ + "## Numeric data types and numerical error" + ] + }, + { + "cell_type": "markdown", + "id": "c3ba958e-9c1b-4721-8f40-b1112ea6a068", + "metadata": {}, + "source": [ + "Vector does not require any specific numeric data type, such as `np.float32` or `np.float64`, it only requires that vector components are some kind of number, including integers." + ] + }, + { + "cell_type": "code", + "execution_count": 27, + "id": "15ca1301-574c-43dd-bb83-f85c71a5f8dc", + "metadata": {}, + "outputs": [], + "source": [ + "v = vector.obj(x=1, y=2.2)" + ] + }, + { + "cell_type": "code", + "execution_count": 28, + "id": "c1883cf8-231f-4996-840a-65c4f30eced4", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "int" + ] + }, + "execution_count": 28, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "type(v.x)" + ] + }, + { + "cell_type": "code", + "execution_count": 29, + "id": "18f515ee-1c9d-480f-b4c8-ba3033afcff0", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "float" + ] + }, + "execution_count": 29, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "type(v.y)" + ] + }, + { + "cell_type": "code", + "execution_count": 30, + "id": "b1a2e4d9-8381-4bc2-9332-52fa475d6c4b", + "metadata": {}, + "outputs": [], + "source": [ + "import numpy as np" + ] + }, + { + "cell_type": "code", + "execution_count": 31, + "id": "e35f37d0-b6bd-45d0-ad78-7a17629a4e3a", + "metadata": {}, + "outputs": [], + "source": [ + "v = vector.obj(x=np.float32(1.1), y=np.float64(2.2))" + ] + }, + { + "cell_type": "code", + "execution_count": 32, + "id": "6bd30abb-4566-4551-9fb7-c7bc8643d487", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "numpy.float32" + ] + }, + "execution_count": 32, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "type(v.x)" + ] + }, + { + "cell_type": "code", + "execution_count": 33, + "id": "e4fabf24-2799-4b0a-9e29-c106986c3330", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "numpy.float64" + ] + }, + "execution_count": 33, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "type(v.y)" + ] + }, + { + "cell_type": "markdown", + "id": "11c3e336-4ced-4704-a1c8-54363687c20f", + "metadata": {}, + "source": [ + "The same formulas are applied, regardless of the numeric type, so if the numerical error is larger than you expect it to be, check your types (and coordinate systems)." + ] + }, + { + "cell_type": "markdown", + "id": "0dab118c-e262-45ec-b121-4c0172603b4a", + "metadata": {}, + "source": [ + "## Application to other backends" + ] + }, + { + "cell_type": "markdown", + "id": "75959cc7-a64b-48ac-9b48-1244887d7d9a", + "metadata": {}, + "source": [ + "Everything stated above about vector objects (except their methods of construction) apply equally to all other backends. Arrays of vectors and symbolic vector expressions in SymPy have the same properties and methods as vector objects, they can hide choice of coordinate system as an abstraction, and the set of synonyms can be minimal for geometric vectors and maximal for momentum vectors. Therefore, it can be convenient to use vector objects as a quick way to debug issues in large arrays. However, note that different backends can use different libraries for computations, and results might differ in numerical error.\n", + "\n", + "In particular, note that SymPy vector expressions have a different convention for operations on space-like and negative time-like 4D vectors. For all other backends, Vector's conventions were chosen to agree with popular HEP libraries, particularly [ROOT](https://root.cern), but for the SymPy backend, those conventions would insert piecewise if-then branches, which would complicate symbolic expressions." + ] } ], "metadata": { diff --git a/docs/src/sympy.ipynb b/docs/src/sympy.ipynb index a7ab2d39..033414e9 100644 --- a/docs/src/sympy.ipynb +++ b/docs/src/sympy.ipynb @@ -7,6 +7,22 @@ "source": [ "# Vector expressions with SymPy" ] + }, + { + "cell_type": "markdown", + "id": "3f40d8aa-c1d4-4106-859a-04d8452673a0", + "metadata": {}, + "source": [ + "First, [install](index.md#installation) and import Vector." + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "id": "405dce26-762d-438b-8b8c-f693d0333a32", + "metadata": {}, + "outputs": [], + "source": [] } ], "metadata": { diff --git a/pyproject.toml b/pyproject.toml index 3a1b0096..e392a387 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -135,8 +135,8 @@ isort.required-imports = [ "tests/*" = [ "T20", ] -"docs/usage/intro.ipynb" = [ - "T20", +"docs/src/*.ipynb" = [ + "T20", "I001", "I002" ] "src/vector/backends/_numba_object.py" = [ "PGH003", diff --git a/tests/test_notebooks.py b/tests/test_notebooks.py index 5f2c3aa1..9fe28b84 100644 --- a/tests/test_notebooks.py +++ b/tests/test_notebooks.py @@ -17,7 +17,6 @@ def common_kwargs(tmpdir): } -@pytest.mark.skip(reason="notebook was removed; will likely be recreated") -def test_intro(common_kwargs): - execution_dir = Path.cwd() / "docs" / "usage" - pm.execute_notebook(execution_dir / "intro.ipynb", **common_kwargs) +def test_object(common_kwargs): + execution_dir = Path.cwd() / "docs" / "src" + pm.execute_notebook(execution_dir / "object.ipynb", **common_kwargs) From 035b79f477957a9af35b715dbaafaee6a4df8230 Mon Sep 17 00:00:00 2001 From: Jim Pivarski Date: Thu, 19 Dec 2024 15:53:53 -0600 Subject: [PATCH 20/23] finished the 'SymPy expressions' tutorial --- docs/src/object.ipynb | 2 +- docs/src/sympy.ipynb | 395 +++++++++++++++++++++++++++++++++++++++- pyproject.toml | 1 + tests/test_notebooks.py | 20 ++ 4 files changed, 415 insertions(+), 3 deletions(-) diff --git a/docs/src/object.ipynb b/docs/src/object.ipynb index 7f7848dc..35d680b5 100644 --- a/docs/src/object.ipynb +++ b/docs/src/object.ipynb @@ -967,7 +967,7 @@ "source": [ "Everything stated above about vector objects (except their methods of construction) apply equally to all other backends. Arrays of vectors and symbolic vector expressions in SymPy have the same properties and methods as vector objects, they can hide choice of coordinate system as an abstraction, and the set of synonyms can be minimal for geometric vectors and maximal for momentum vectors. Therefore, it can be convenient to use vector objects as a quick way to debug issues in large arrays. However, note that different backends can use different libraries for computations, and results might differ in numerical error.\n", "\n", - "In particular, note that SymPy vector expressions have a different convention for operations on space-like and negative time-like 4D vectors. For all other backends, Vector's conventions were chosen to agree with popular HEP libraries, particularly [ROOT](https://root.cern), but for the SymPy backend, those conventions would insert piecewise if-then branches, which would complicate symbolic expressions." + "In particular, note that SymPy vector expressions have a different sign convention for operations on space-like and negative time-like 4D vectors. For all other backends, Vector's conventions were chosen to agree with popular HEP libraries, particularly [ROOT](https://root.cern), but for the SymPy backend, those conventions would insert piecewise if-then branches, which would complicate symbolic expressions." ] } ], diff --git a/docs/src/sympy.ipynb b/docs/src/sympy.ipynb index 033414e9..9614c45b 100644 --- a/docs/src/sympy.ipynb +++ b/docs/src/sympy.ipynb @@ -13,7 +13,7 @@ "id": "3f40d8aa-c1d4-4106-859a-04d8452673a0", "metadata": {}, "source": [ - "First, [install](index.md#installation) and import Vector." + "First, [install](index.md#installation) and import Vector and [SymPy](https://www.sympy.org/)." ] }, { @@ -22,7 +22,398 @@ "id": "405dce26-762d-438b-8b8c-f693d0333a32", "metadata": {}, "outputs": [], - "source": [] + "source": [ + "import vector\n", + "import sympy" + ] + }, + { + "cell_type": "markdown", + "id": "00b96b54-33e4-459b-8fa6-bbebf1df0319", + "metadata": {}, + "source": [ + "## How the SymPy backend differs from the others" + ] + }, + { + "cell_type": "markdown", + "id": "07e49af1-a2e4-43e9-b265-38d917456ce0", + "metadata": {}, + "source": [ + "[SymPy](https://www.sympy.org/) is a computer algebra system like Mathematica and Maple. It primarily deals with algebraic expressions, rather than concrete numbers. However, all of the coordinate transformations and vector manipulations can be applied symbolically through Vector's SymPy backend.\n", + "\n", + "When comparing SymPy to the other backends, note that SymPy vector expressions have a different sign convention for operations on space-like and negative time-like 4D vectors. For all other backends, Vector's conventions were chosen to agree with popular HEP libraries, particularly [ROOT](https://root.cern), but for the SymPy backend, those conventions would insert piecewise if-then branches, which would complicate symbolic expressions.\n", + "\n", + "When vector expressions are evaluated numerically, you can expect agreement in 2D and 3D vector operations, as well as 4D vector operations if all of the vectors have a positive time-like part (which is [necessary for real momentum vectors and causal relationships between events](https://en.wikipedia.org/wiki/Light_cone))." + ] + }, + { + "cell_type": "markdown", + "id": "afce6222-03bb-40b7-8789-4e98782ebede", + "metadata": {}, + "source": [ + "## Making a vector expression" + ] + }, + { + "cell_type": "markdown", + "id": "10257bc9-a064-4ede-bcdb-d906a25598e2", + "metadata": {}, + "source": [ + "Before making a vector expression, we need symbols for each of the components, so use the [sympy.symbols](https://docs.sympy.org/latest/modules/core.html#sympy.core.symbol.symbols) function. Be sure to [tell SymPy to assume](https://docs.sympy.org/latest/guides/assumptions.html) that they are all real-valued, not complex numbers." + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "id": "e74eaaea-c607-47c0-a228-9b3530863bf7", + "metadata": {}, + "outputs": [], + "source": [ + "x, y, z, t, px, py, pz, eta, tau = sympy.symbols(\"x y z t px py pz eta tau\", real=True)" + ] + }, + { + "cell_type": "markdown", + "id": "8216735e-eb82-4ba9-92c3-12f45a9400a8", + "metadata": {}, + "source": [ + "Now we can make vectors [just as we did with objects](object.md#Making-a-vector), though these lack concrete numerical values." + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "id": "0beb59b0-7cea-4d06-b437-da0597ba027e", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "VectorSympy2D(x=x, y=y)" + ] + }, + "execution_count": 3, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "vector.VectorSympy2D(x=x, y=y)" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "id": "8dc8eb68-89e3-4794-b533-e9f5d521770b", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "MomentumSympy3D(px=px, py=py, pz=pz)" + ] + }, + "execution_count": 4, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "vector.MomentumSympy3D(px=px, py=py, pz=pz)" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "id": "921724ac-2d20-4a82-8e0b-3cc571d7d909", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "VectorSympy4D(x=x, y=y, eta=eta, tau=tau)" + ] + }, + "execution_count": 5, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "vector.VectorSympy4D(x=x, y=y, eta=eta, tau=tau)" + ] + }, + { + "cell_type": "markdown", + "id": "6ac26f0b-8fb6-410c-865f-6fefaeb2302b", + "metadata": {}, + "source": [ + "## Using a vector expression" + ] + }, + { + "cell_type": "markdown", + "id": "59c644ed-32af-42f1-bac7-a27c7ec55035", + "metadata": {}, + "source": [ + "All of the vector operations performed on these expressions return symbolic results." + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "id": "9dd7d004-9635-427c-8394-f0e65906f564", + "metadata": {}, + "outputs": [], + "source": [ + "v = vector.VectorSympy2D(x=x, y=y)" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "id": "3b3af4ee-b0a7-4379-ab8e-ac674037db18", + "metadata": {}, + "outputs": [ + { + "data": { + "text/latex": [ + "$\\displaystyle \\sqrt{x^{2} + y^{2}}$" + ], + "text/plain": [ + "sqrt(x**2 + y**2)" + ] + }, + "execution_count": 7, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "v.rho" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "id": "9430dd6e-ceef-4977-ab1f-5d78ff7d6d83", + "metadata": {}, + "outputs": [ + { + "data": { + "text/latex": [ + "$\\displaystyle \\text{True}$" + ], + "text/plain": [ + "True" + ] + }, + "execution_count": 8, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "sympy.Eq(v.rho, abs(v))" + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "id": "7c674475-b882-44fc-b01a-f04800eb0205", + "metadata": {}, + "outputs": [], + "source": [ + "v = vector.VectorSympy4D(x=x, y=y, z=z, t=t)" + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "id": "c25ea976-b913-4717-9858-3e2c926a99c2", + "metadata": {}, + "outputs": [ + { + "data": { + "text/latex": [ + "$\\displaystyle \\sqrt{\\left|{- t^{2} + x^{2} + y^{2} + z^{2}}\\right|}$" + ], + "text/plain": [ + "sqrt(Abs(-t**2 + x**2 + y**2 + z**2))" + ] + }, + "execution_count": 10, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "v.tau" + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "id": "3d258221-4cd4-43fb-8710-d9bc96827132", + "metadata": {}, + "outputs": [ + { + "data": { + "text/latex": [ + "$\\displaystyle t^{2} - x^{2} - y^{2} - z^{2} > 0$" + ], + "text/plain": [ + "t**2 - x**2 - y**2 - z**2 > 0" + ] + }, + "execution_count": 11, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "v.is_timelike()" + ] + }, + { + "cell_type": "code", + "execution_count": 12, + "id": "86dcae0d-22ba-4621-82b8-397a94fecfc6", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "VectorSympy4D(x=x*(1 + x**2/(t**2*(1 + 1/sqrt(1 - x**2/t**2 - y**2/t**2 - z**2/t**2))*(1 - x**2/t**2 - y**2/t**2 - z**2/t**2))) + x/sqrt(1 - x**2/t**2 - y**2/t**2 - z**2/t**2) + x*y**2/(t**2*(1 + 1/sqrt(1 - x**2/t**2 - y**2/t**2 - z**2/t**2))*(1 - x**2/t**2 - y**2/t**2 - z**2/t**2)) + x*z**2/(t**2*(1 + 1/sqrt(1 - x**2/t**2 - y**2/t**2 - z**2/t**2))*(1 - x**2/t**2 - y**2/t**2 - z**2/t**2)), y=y*(1 + y**2/(t**2*(1 + 1/sqrt(1 - x**2/t**2 - y**2/t**2 - z**2/t**2))*(1 - x**2/t**2 - y**2/t**2 - z**2/t**2))) + y/sqrt(1 - x**2/t**2 - y**2/t**2 - z**2/t**2) + x**2*y/(t**2*(1 + 1/sqrt(1 - x**2/t**2 - y**2/t**2 - z**2/t**2))*(1 - x**2/t**2 - y**2/t**2 - z**2/t**2)) + y*z**2/(t**2*(1 + 1/sqrt(1 - x**2/t**2 - y**2/t**2 - z**2/t**2))*(1 - x**2/t**2 - y**2/t**2 - z**2/t**2)), z=z*(1 + z**2/(t**2*(1 + 1/sqrt(1 - x**2/t**2 - y**2/t**2 - z**2/t**2))*(1 - x**2/t**2 - y**2/t**2 - z**2/t**2))) + z/sqrt(1 - x**2/t**2 - y**2/t**2 - z**2/t**2) + x**2*z/(t**2*(1 + 1/sqrt(1 - x**2/t**2 - y**2/t**2 - z**2/t**2))*(1 - x**2/t**2 - y**2/t**2 - z**2/t**2)) + y**2*z/(t**2*(1 + 1/sqrt(1 - x**2/t**2 - y**2/t**2 - z**2/t**2))*(1 - x**2/t**2 - y**2/t**2 - z**2/t**2)), t=t/sqrt(1 - x**2/t**2 - y**2/t**2 - z**2/t**2) + x**2/(t*sqrt(1 - x**2/t**2 - y**2/t**2 - z**2/t**2)) + y**2/(t*sqrt(1 - x**2/t**2 - y**2/t**2 - z**2/t**2)) + z**2/(t*sqrt(1 - x**2/t**2 - y**2/t**2 - z**2/t**2)))" + ] + }, + "execution_count": 12, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "boosted = v.boost(v.to_beta3())\n", + "boosted" + ] + }, + { + "cell_type": "code", + "execution_count": 13, + "id": "1e5a3bf0-1784-4d29-8b7c-1b8904de8a20", + "metadata": {}, + "outputs": [ + { + "data": { + "text/latex": [ + "$\\displaystyle \\frac{t}{\\sqrt{1 - \\frac{x^{2}}{t^{2}} - \\frac{y^{2}}{t^{2}} - \\frac{z^{2}}{t^{2}}}} + \\frac{x^{2}}{t \\sqrt{1 - \\frac{x^{2}}{t^{2}} - \\frac{y^{2}}{t^{2}} - \\frac{z^{2}}{t^{2}}}} + \\frac{y^{2}}{t \\sqrt{1 - \\frac{x^{2}}{t^{2}} - \\frac{y^{2}}{t^{2}} - \\frac{z^{2}}{t^{2}}}} + \\frac{z^{2}}{t \\sqrt{1 - \\frac{x^{2}}{t^{2}} - \\frac{y^{2}}{t^{2}} - \\frac{z^{2}}{t^{2}}}}$" + ], + "text/plain": [ + "t/sqrt(1 - x**2/t**2 - y**2/t**2 - z**2/t**2) + x**2/(t*sqrt(1 - x**2/t**2 - y**2/t**2 - z**2/t**2)) + y**2/(t*sqrt(1 - x**2/t**2 - y**2/t**2 - z**2/t**2)) + z**2/(t*sqrt(1 - x**2/t**2 - y**2/t**2 - z**2/t**2))" + ] + }, + "execution_count": 13, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "boosted.t" + ] + }, + { + "cell_type": "markdown", + "id": "d7e6de0b-917e-4d87-bade-74bd62db93f2", + "metadata": {}, + "source": [ + "They can be [simplified](https://docs.sympy.org/latest/modules/simplify/simplify.html):" + ] + }, + { + "cell_type": "code", + "execution_count": 14, + "id": "7bcac010-14a5-4d81-9e8a-c4cc9d84067a", + "metadata": {}, + "outputs": [ + { + "data": { + "text/latex": [ + "$\\displaystyle \\frac{t \\sqrt{\\frac{t^{2} - x^{2} - y^{2} - z^{2}}{t^{2}}} \\left(t^{2} + x^{2} + y^{2} + z^{2}\\right)}{t^{2} - x^{2} - y^{2} - z^{2}}$" + ], + "text/plain": [ + "t*sqrt((t**2 - x**2 - y**2 - z**2)/t**2)*(t**2 + x**2 + y**2 + z**2)/(t**2 - x**2 - y**2 - z**2)" + ] + }, + "execution_count": 14, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "boosted.t.simplify()" + ] + }, + { + "cell_type": "markdown", + "id": "8e29d643-52e8-4b7d-bbd3-2b864d5efdb6", + "metadata": {}, + "source": [ + "And the symbols can be [replaced with numerical values](https://docs.sympy.org/latest/modules/core.html#sympy.core.basic.Basic.subs):" + ] + }, + { + "cell_type": "code", + "execution_count": 15, + "id": "0b9b401d-43a1-411f-9d88-f7c91fa6c5e7", + "metadata": {}, + "outputs": [ + { + "data": { + "text/latex": [ + "$\\displaystyle \\frac{57 \\sqrt{86}}{43}$" + ], + "text/plain": [ + "57*sqrt(86)/43" + ] + }, + "execution_count": 15, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "boosted.t.subs({x: 3, y: 2, z: 1, t: 10})" + ] + }, + { + "cell_type": "markdown", + "id": "55befc25-e5a1-465c-9dfa-850f0dc06cf5", + "metadata": {}, + "source": [ + "Or [converted into code](https://docs.sympy.org/latest/modules/printing.html#prettyprinter-class) for a programming language:" + ] + }, + { + "cell_type": "code", + "execution_count": 16, + "id": "57fa1123-2d1a-47ac-ad8e-31a0ceee8747", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + " t*sqrt((t**2 - x**2 - y**2 - z**2)/t**2)*(t**2 + x**2 + y**2 + z**\n", + " @ 2)/(t**2 - x**2 - y**2 - z**2)\n" + ] + } + ], + "source": [ + "import sympy.printing.fortran\n", + "\n", + "print(sympy.printing.fortran.fcode(boosted.t.simplify()))" + ] } ], "metadata": { diff --git a/pyproject.toml b/pyproject.toml index e392a387..75070e31 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -52,6 +52,7 @@ optional-dependencies.awkward = [ optional-dependencies.dev = [ "awkward>=2", "dask-awkward", + "sympy", "nox", "numba>=0.57; python_version<'3.13'", "papermill>=2.4", diff --git a/tests/test_notebooks.py b/tests/test_notebooks.py index 9fe28b84..b3c842e5 100644 --- a/tests/test_notebooks.py +++ b/tests/test_notebooks.py @@ -20,3 +20,23 @@ def common_kwargs(tmpdir): def test_object(common_kwargs): execution_dir = Path.cwd() / "docs" / "src" pm.execute_notebook(execution_dir / "object.ipynb", **common_kwargs) + + +def test_numpy(common_kwargs): + execution_dir = Path.cwd() / "docs" / "src" + pm.execute_notebook(execution_dir / "numpy.ipynb", **common_kwargs) + + +def test_awkward(common_kwargs): + execution_dir = Path.cwd() / "docs" / "src" + pm.execute_notebook(execution_dir / "awkward.ipynb", **common_kwargs) + + +def test_numba(common_kwargs): + execution_dir = Path.cwd() / "docs" / "src" + pm.execute_notebook(execution_dir / "numba.ipynb", **common_kwargs) + + +def test_sympy(common_kwargs): + execution_dir = Path.cwd() / "docs" / "src" + pm.execute_notebook(execution_dir / "sympy.ipynb", **common_kwargs) From 67f7700f04add3da59ca13adf2e5e798b1288986 Mon Sep 17 00:00:00 2001 From: Jim Pivarski Date: Thu, 19 Dec 2024 17:32:19 -0600 Subject: [PATCH 21/23] finished the 'NumPy arrays' tutorial --- docs/src/awkward.ipynb | 2 +- docs/src/make_numpy.md | 2 +- docs/src/numba.ipynb | 2 +- docs/src/numpy.ipynb | 766 ++++++++++++++++++++++++++++++++++++++++- docs/src/object.ipynb | 2 +- docs/src/sympy.ipynb | 4 +- 6 files changed, 770 insertions(+), 8 deletions(-) diff --git a/docs/src/awkward.ipynb b/docs/src/awkward.ipynb index b69019a7..a4a99237 100644 --- a/docs/src/awkward.ipynb +++ b/docs/src/awkward.ipynb @@ -13,7 +13,7 @@ "id": "26894013-8d55-45b5-9592-6a82c6e7440a", "metadata": {}, "source": [ - "First, [install](index.md#installation) and import Vector." + "First, [install](../index.md#installation) and import Vector." ] }, { diff --git a/docs/src/make_numpy.md b/docs/src/make_numpy.md index 80f96f36..57cd325d 100644 --- a/docs/src/make_numpy.md +++ b/docs/src/make_numpy.md @@ -6,7 +6,7 @@ To create a NumPy array of vectors, 1. use the `vector.array` function (`vector.arr` is a synonym) 2. use the `vector.VectorNumpy` class constructor -3. or cast a structured NumPy array as the appropriate class. +3. or cast a structured NumPy array as the appropriate class, which can avoid copying data. ## General constructor diff --git a/docs/src/numba.ipynb b/docs/src/numba.ipynb index 4c5f9bcd..952d49c4 100644 --- a/docs/src/numba.ipynb +++ b/docs/src/numba.ipynb @@ -13,7 +13,7 @@ "id": "26a7599a-5b33-4f6d-85d2-788295abe176", "metadata": {}, "source": [ - "First, [install](index.md#installation) and import Vector." + "First, [install](../index.md#installation) and import Vector." ] }, { diff --git a/docs/src/numpy.ipynb b/docs/src/numpy.ipynb index d2ad995c..2694368e 100644 --- a/docs/src/numpy.ipynb +++ b/docs/src/numpy.ipynb @@ -13,7 +13,7 @@ "id": "1144533f-0290-43f2-a9f2-adc9d042ed1a", "metadata": {}, "source": [ - "First, [install](index.md#installation) and import Vector." + "First, [install](../index.md#installation) and import Vector and NumPy. (Vector requires NumPy, so if you can use Vector, you've already installed NumPy.)" ] }, { @@ -22,7 +22,769 @@ "id": "04ce97c4-d7db-458a-9976-68af8eeb9b58", "metadata": {}, "outputs": [], - "source": [] + "source": [ + "import vector\n", + "import numpy as np" + ] + }, + { + "cell_type": "markdown", + "id": "c9492633-fa30-458d-ba40-3c1b12a067b6", + "metadata": {}, + "source": [ + "## Making an array of vectors" + ] + }, + { + "cell_type": "markdown", + "id": "f84dbc67-e195-4ee7-a11f-cd8040c09fa8", + "metadata": {}, + "source": [ + "If you want to do calculations with large numbers of vectors or performance is important, it's better to make arrays of vectors than lists of [vector objects](object.md).\n", + "\n", + "The [vector.array](make_numpy.md#general-constructor) function is a general-purpose constructor. It works like [np.array](https://numpy.org/doc/stable/reference/generated/numpy.array.html) and expects the [dtype](https://numpy.org/doc/stable/reference/arrays.dtypes.html) to correspond to a [structured array](https://numpy.org/doc/stable/user/basics.rec.html) in which the field names are recognized coordinate names:" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "id": "de83bfb0-37ec-4d1a-a6c4-31de7ee94998", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "VectorNumpy2D([(1.1, 2.2), (3.3, 4.4), (5.5, 6.6)],\n", + " dtype=[('x', ' abs(b), a, b)" + ] + }, + { + "cell_type": "code", + "execution_count": 22, + "id": "b1a1236b-81f2-40a4-b5c5-5c46a7cb5e57", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "VectorNumpy3D((496.97860925, -22.8454872, -148.7924227),\n", + " dtype=[('x', ' Date: Thu, 19 Dec 2024 19:05:29 -0600 Subject: [PATCH 22/23] finished the 'Awkward Arrays' tutorial --- docs/src/awkward.ipynb | 1001 +++++++++++++++++++++++++++++++++++++- docs/src/make_awkward.md | 2 +- docs/src/numpy.ipynb | 2 +- docs/src/sympy.ipynb | 2 +- 4 files changed, 1002 insertions(+), 5 deletions(-) diff --git a/docs/src/awkward.ipynb b/docs/src/awkward.ipynb index a4a99237..3f5da595 100644 --- a/docs/src/awkward.ipynb +++ b/docs/src/awkward.ipynb @@ -13,7 +13,7 @@ "id": "26894013-8d55-45b5-9592-6a82c6e7440a", "metadata": {}, "source": [ - "First, [install](../index.md#installation) and import Vector." + "First, [install](../index.md#installation) and import Vector and [Awkward Array](https://awkward-array.org/)." ] }, { @@ -22,7 +22,1004 @@ "id": "8f504534-1fa5-4dfb-b0c9-f7a2b2d12eae", "metadata": {}, "outputs": [], - "source": [] + "source": [ + "import vector\n", + "import awkward as ak" + ] + }, + { + "cell_type": "markdown", + "id": "b119a69a-19e6-4568-bdde-fca92ec23f2f", + "metadata": {}, + "source": [ + "## Making an Awkward Array of vectors" + ] + }, + { + "cell_type": "markdown", + "id": "bb1e0f46-627e-463a-840b-bac3bf0588eb", + "metadata": {}, + "source": [ + "Awkward Arrays are arrays with more complex data structures than NumPy allows, such as variable-length lists, nested records, missing and even heterogeneous data (different data types in the same array).\n", + "\n", + "Vectors can be included among those data structures. In this context, vectors are Awkward \"records,\" objects with named fields, that can be nested inside of other structures. The vector properties and methods are implemented through Awkward Array's [behavior](https://awkward-array.org/doc/main/reference/ak.behavior.html) mechanism. Unlike [vector objects](object.md) and [NumPy subclasses](numpy.md), the vectors can't be ordinary Python classes because they might be nested within other data structures, such as variable-length lists, and these lists are implemented in a columnar way that isn't open to Python's introspection.\n", + "\n", + "Let's start with an example. Below, we create an Awkward Array using its [ak.Array](https://awkward-array.org/doc/main/reference/generated/ak.Array.html) constructor, but include `with_name` and `behavior` arguments:" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "id": "42b68d0a-d867-4fed-84ad-59d4732e112b", + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "
[[{x: 1.1, y: 2.2}, {x: 3.3, y: 4.4}],\n",
+       " [],\n",
+       " [{x: 5.5, y: 6.6}]]\n",
+       "----------------------------------------------------------\n",
+       "backend: cpu\n",
+       "nbytes: 80 B\n",
+       "type: 3 * var * Vector2D[\n",
+       "    x: float64,\n",
+       "    y: float64\n",
+       "]
" + ], + "text/plain": [ + "" + ] + }, + "execution_count": 2, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "arr = ak.Array(\n", + " [\n", + " [{\"x\": 1.1, \"y\": 2.2}, {\"x\": 3.3, \"y\": 4.4}],\n", + " [],\n", + " [{\"x\": 5.5, \"y\": 6.6}],\n", + " ],\n", + " with_name=\"Vector2D\",\n", + " behavior=vector.backends.awkward.behavior,\n", + ")\n", + "arr" + ] + }, + { + "cell_type": "markdown", + "id": "e674ffdd-a42e-4707-911d-def1a0010858", + "metadata": {}, + "source": [ + "The above array contains 3 lists, the first has length 2, the second has length 0, and the third has length 1. The lists contain records with field names `\"x\"` and `\"y\"`, and the record type is named `\"Vector2D\"`. In addition, this array has `behavior` from `vector.backends.awkward.behavior`, which is a large dict containing classes and functions to implement vector operations.\n", + "\n", + "For instance, we can compute `rho` and `phi` coordinates in the same way as with the [NumPy subclasses](numpy.md), an array at a time:" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "id": "1d5484f9-07e1-4192-bf88-3b32f1028bf5", + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "
[[2.46, 5.5],\n",
+       " [],\n",
+       " [8.59]]\n",
+       "-----------------------\n",
+       "backend: cpu\n",
+       "nbytes: 56 B\n",
+       "type: 3 * var * float64
" + ], + "text/plain": [ + "" + ] + }, + "execution_count": 3, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "arr.rho" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "id": "61e61f29-015d-4f53-94cd-07444811c9ec", + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "
[[1.11, 0.927],\n",
+       " [],\n",
+       " [0.876]]\n",
+       "-----------------------\n",
+       "backend: cpu\n",
+       "nbytes: 56 B\n",
+       "type: 3 * var * float64
" + ], + "text/plain": [ + "" + ] + }, + "execution_count": 4, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "arr.phi" + ] + }, + { + "cell_type": "markdown", + "id": "66d1c600-568a-41cc-b31a-f7eaedef1c68", + "metadata": {}, + "source": [ + "As with NumPy, performing operations an array at a time is usually much faster than writing Python for loops. What Awkward Array provides on top of that is the ability to do these operations _through_ variable-length lists and other structures.\n", + "\n", + "An Awkward Array needs all of the following for its records to be interpreted as vectors:\n", + "\n", + "1. the record name, which can be assigned using [ak.with_name](https://awkward-array.org/doc/main/reference/generated/ak.with_name.html) or as a constructor argument, must be one of `\"Vector2D\"`, `\"Momentum2D\"`, `\"Vector3D\"`, `\"Momentum3D\"`, `\"Vector4D\"`, and `\"Momentum4D\"`\n", + "2. the field names must be recognized coordinate names, following the same conventions as [vector objects](object.md)\n", + "3. the array must have `vector.backends.awkward.behavior` as its `behavior`.\n", + "\n", + "When Awkward Arrays are saved in files, such as with [ak.to_parquet](https://awkward-array.org/doc/main/reference/generated/ak.to_parquet.html), they retain their record names and field names, so conditions 1 and 2 above are persistent. They don't preserve condition 3, the behaviors, since these are Python classes and functions.\n", + "\n", + "To make sure that Vector behaviors are always available, you can call [vector.register_awkward](make_awkward.md#vector.register_awkward) at the beginning of every script, like this:\n", + "\n", + "```python\n", + "import awkward as ak\n", + "import vector\n", + "vector.register_awkward()\n", + "```\n", + "\n", + "This function copies Vector's behaviors into Awkward's global [ak.behavior](https://awkward-array.org/doc/main/reference/ak.behavior.html) so that any array with the right record and field names (such as one read from a file) automatically have Vector behaviors.\n", + "\n", + "Vector also has a [vector.Array](make_awkward.md#vector.Array) constructor, which works like [ak.Array](https://awkward-array.org/doc/main/reference/generated/ak.Array.html) but sets `with_name` automatically, as well as [vector.zip](make_awkward.md#vector.zip), which works like [ak.zip](https://awkward-array.org/doc/main/reference/generated/ak.zip.html) and sets `with_name` automatically. However, these functions still require you to set field names appropriately and if you need to do something complex, it's easier to use Awkward Array's own functions and assign the record name after the array is built, using [ak.with_name](https://awkward-array.org/doc/main/reference/generated/ak.with_name.html)." + ] + }, + { + "cell_type": "markdown", + "id": "467f6d6d-dd6a-4c6e-8ff2-cc7b61e6b949", + "metadata": {}, + "source": [ + "## Using an Awkward array of vectors" + ] + }, + { + "cell_type": "markdown", + "id": "8677dc3e-1482-42c4-9157-75c0cea61f45", + "metadata": {}, + "source": [ + "First, let's make some arrays to use in examples:" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "id": "025fcf28-c946-4c52-9c06-333a217ead52", + "metadata": {}, + "outputs": [], + "source": [ + "import numpy as np\n", + "import awkward as ak\n", + "import vector\n", + "\n", + "vector.register_awkward()" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "id": "15050418-eab0-4da4-a1bd-c8ceef2a47c2", + "metadata": {}, + "outputs": [], + "source": [ + "def array_of_momentum3d(num_vectors):\n", + " return ak.zip(\n", + " {\n", + " \"px\": np.random.normal(0, 1, num_vectors),\n", + " \"py\": np.random.normal(0, 1, num_vectors),\n", + " \"pz\": np.random.normal(0, 1, num_vectors),\n", + " },\n", + " with_name=\"Momentum3D\",\n", + " )\n", + "\n", + "\n", + "def array_of_lists_of_momentum3d(mean_num_per_list, num_lists):\n", + " num_per_list = np.random.poisson(mean_num_per_list, num_lists)\n", + " return ak.unflatten(\n", + " array_of_momentum3d(np.sum(num_per_list)),\n", + " num_per_list,\n", + " )\n", + "\n", + "\n", + "a = array_of_momentum3d(10)\n", + "b = array_of_lists_of_momentum3d(1.5, 10)" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "id": "43fbd738-8243-45bf-af35-2b09ef196bff", + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "
[{px: -0.541, py: 0.714, pz: -0.983},\n",
+       " {px: 0.61, py: -0.48, pz: -0.0845},\n",
+       " {px: 0.929, py: 0.718, pz: 0.0935},\n",
+       " {px: 1.52, py: -1.39, pz: -0.0187},\n",
+       " {px: 0.675, py: 0.0216, pz: -1.12},\n",
+       " {px: 0.542, py: -0.524, pz: 0.586},\n",
+       " {px: 0.927, py: 0.476, pz: 0.602},\n",
+       " {px: 0.615, py: 1.23, pz: -0.59},\n",
+       " {px: -0.626, py: 0.072, pz: 0.136},\n",
+       " {px: 2.23, py: 1.05, pz: -0.355}]\n",
+       "--------------------------------------------------------------------------\n",
+       "backend: cpu\n",
+       "nbytes: 240 B\n",
+       "type: 10 * Momentum3D[\n",
+       "    px: float64,\n",
+       "    py: float64,\n",
+       "    pz: float64\n",
+       "]
" + ], + "text/plain": [ + "" + ] + }, + "execution_count": 7, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "a" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "id": "c347edb1-78b3-4963-a503-b877597c2ee5", + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "
[[{px: 0.73, py: 0.862, pz: -0.129}, {px: 0.746, py: 0.614, pz: ..., ...}],\n",
+       " [],\n",
+       " [{px: 0.493, py: -0.633, pz: -0.413}, {px: 0.836, py: -1.77, ...}],\n",
+       " [{px: -0.58, py: -0.586, pz: -0.513}, {...}, ..., {px: -0.201, py: 1.52, ...}],\n",
+       " [{px: -0.474, py: 1.6, pz: -0.1}, {px: 0.218, py: 0.155, pz: 0.834}],\n",
+       " [{px: -0.881, py: -0.183, pz: -0.725}, {px: -0.108, py: -0.889, ...}],\n",
+       " [{px: -1.77, py: 2.04, pz: 0.896}],\n",
+       " [{px: -1.08, py: -0.591, pz: -0.0674}, {px: -0.183, py: -0.289, ...}],\n",
+       " [{px: -1.08, py: -1.15, pz: 2.6}],\n",
+       " [{px: -0.419, py: -0.363, pz: -0.563}, {px: -2.48, py: -0.228, ...}]]\n",
+       "--------------------------------------------------------------------------------\n",
+       "backend: cpu\n",
+       "nbytes: 544 B\n",
+       "type: 10 * var * Momentum3D[\n",
+       "    px: float64,\n",
+       "    py: float64,\n",
+       "    pz: float64\n",
+       "]
" + ], + "text/plain": [ + "" + ] + }, + "execution_count": 8, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "b" + ] + }, + { + "cell_type": "markdown", + "id": "7a6e73c4-cc2c-4cb5-9807-13c1bc970f78", + "metadata": {}, + "source": [ + "Awkward Array uses array-at-a-time functions like NumPy, so if we want to compute dot products of each vector in `a` with every vector of each list in `b`, we'd say:" + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "id": "144ee86e-2b47-4526-9d6b-3d490be69ba8", + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "
[[0.347, -1.32],\n",
+       " [],\n",
+       " [-0.035, -0.385],\n",
+       " [-0.0551, 0.194, 2.28, -2.86, -2.39],\n",
+       " [-0.173, -0.782],\n",
+       " [-0.807, 0.704],\n",
+       " [-0.128],\n",
+       " [-1.35, -0.446],\n",
+       " [0.945],\n",
+       " [-1.11, -5.58]]\n",
+       "--------------------------------------\n",
+       "backend: cpu\n",
+       "nbytes: 240 B\n",
+       "type: 10 * var * float64
" + ], + "text/plain": [ + "" + ] + }, + "execution_count": 9, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "a.dot(b)" + ] + }, + { + "cell_type": "markdown", + "id": "1088c2a6-e744-4308-bd74-4ed9471d3bd1", + "metadata": {}, + "source": [ + "Note that `a` and `b` have different numbers of vectors, but the same array lengths. The operation above [broadcasts](https://awkward-array.org/doc/main/user-guide/how-to-math-broadcasting.html) array `a` into `b`, like the following code:" + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "id": "9edab13c-5b8e-47f2-afac-c0dd7241a8ca", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[0.3470024410105361 -1.32262374856204 ]\n", + "[]\n", + "[-0.0350058354646221 -0.3845727581312185 ]\n", + "[-0.05513156034267678 0.1939866533163302 2.2806023784977056 -2.861051860111839 -2.3860250251022475 ]\n", + "[-0.17338156209593328 -0.7816799910864897 ]\n", + "[-0.8071770038569903 0.7044860439866077 ]\n", + "[-0.1279745100114199 ]\n", + "[-1.3483450919978617 -0.44626327125953613 ]\n", + "[0.9449043237160631 ]\n", + "[-1.1124522691465186 -5.579496184145224 ]\n" + ] + } + ], + "source": [ + "for i in range(len(a)):\n", + " print(\"[\", end=\"\")\n", + "\n", + " for j in range(len(b[i])):\n", + " out = a[i].dot(b[i, j])\n", + "\n", + " print(out, end=\" \")\n", + "\n", + " print(\"]\")" + ] + }, + { + "cell_type": "markdown", + "id": "0e17784d-a838-4c87-a708-f530bd0fbe59", + "metadata": {}, + "source": [ + "Like NumPy, the array-at-a-time expression is more concise and faster:" + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "id": "1e3ffd74-469d-4ccd-984d-706413442700", + "metadata": {}, + "outputs": [], + "source": [ + "a = array_of_momentum3d(10000)\n", + "b = array_of_lists_of_momentum3d(1.5, 10000)" + ] + }, + { + "cell_type": "code", + "execution_count": 12, + "id": "135e44f1-7e25-49ef-8805-8638b3d0e9be", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "9.08 s ± 0 ns per loop (mean ± std. dev. of 1 run, 1 loop each)\n" + ] + } + ], + "source": [ + "%%timeit -n1 -r1\n", + "\n", + "out = np.zeros(10000)\n", + "\n", + "for i in range(len(a)):\n", + " for j in range(len(b[i])):\n", + " out[i] += a[i].dot(b[i, j])" + ] + }, + { + "cell_type": "code", + "execution_count": 13, + "id": "6b4d2c04-9034-4558-905a-af4539be1d40", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2.44 ms ± 20.2 μs per loop (mean ± std. dev. of 7 runs, 100 loops each)\n" + ] + } + ], + "source": [ + "%%timeit\n", + "\n", + "out = np.sum(a.dot(b), axis=1)" + ] + }, + { + "cell_type": "markdown", + "id": "cd509b13-8e87-40b0-b478-bb40154dd5c1", + "metadata": {}, + "source": [ + "(Note the units.)\n", + "\n", + "Just as with NumPy, all of the coordinate transformations and vector operations are implemented for Awkward Arrays of vectors." + ] + }, + { + "cell_type": "markdown", + "id": "716cd51c-88ec-42e7-89ae-719cef7e4368", + "metadata": {}, + "source": [ + "## Some troubleshooting hints" + ] + }, + { + "cell_type": "markdown", + "id": "904561c9-b998-4e4a-8ce1-e799931d9285", + "metadata": {}, + "source": [ + "Make sure that the Vector behaviors are actually installed and applied to your data. In the data type, the record type should appear as `\"Vector2D\"`, `\"Momentum2D\"`, `\"Vector3D\"`, `\"Momentum3D\"`, `\"Vector4D\"`, or `\"Momentum4D\"`, rather than the generic curly brackets `{` and `}`, and if you extract one record from the array, can you perform a vector operation on it?\n", + "\n", + "Make sure that your arrays broadcast the way that you want them to. If the vector behaviors are clouding the picture, make simpler arrays with numbers in place of records. Can you add them with `+`? (Addition uses the same broadcasting rules as all other operations.)\n", + "\n", + "If your code runs but doesn't give the results you expect, try slicing the arrays to just the first two items with `arr[:2]`. Step through the calculation on just two elements, observing the results of each operation. Are they what you expect?" + ] + }, + { + "cell_type": "markdown", + "id": "60db1ccb-8d0a-4bc8-9050-6f68b03e2ee4", + "metadata": {}, + "source": [ + "## Advanced: subclassing Awkward-Vector behaviors" + ] + }, + { + "cell_type": "markdown", + "id": "00d4f231-46f3-41a0-8573-9564aad8b29b", + "metadata": {}, + "source": [ + "It is possible to write subclasses for Awkward-Vector behaviors as mixins to extend the vector functionalities. For instance, the `MomentumAwkward` classes can be extended in the following way:" + ] + }, + { + "cell_type": "code", + "execution_count": 14, + "id": "967444cc-a4f1-4e2b-8289-3224333218f1", + "metadata": {}, + "outputs": [], + "source": [ + "behavior = vector.backends.awkward.behavior\n", + "\n", + "\n", + "@ak.mixin_class(behavior)\n", + "class TwoVector(vector.backends.awkward.MomentumAwkward2D):\n", + " pass\n", + "\n", + "\n", + "@ak.mixin_class(behavior)\n", + "class ThreeVector(vector.backends.awkward.MomentumAwkward3D):\n", + " pass\n", + "\n", + "\n", + "# required for transforming vectors\n", + "# the class names must always end with \"Array\"\n", + "TwoVectorArray.ProjectionClass2D = TwoVectorArray # noqa: F821\n", + "TwoVectorArray.ProjectionClass3D = ThreeVectorArray # noqa: F821\n", + "TwoVectorArray.MomentumClass = TwoVectorArray # noqa: F821\n", + "\n", + "ThreeVectorArray.ProjectionClass2D = TwoVectorArray # noqa: F821\n", + "ThreeVectorArray.ProjectionClass3D = ThreeVectorArray # noqa: F821\n", + "ThreeVectorArray.MomentumClass = ThreeVectorArray # noqa: F821" + ] + }, + { + "cell_type": "code", + "execution_count": 15, + "id": "42ea1b53-6003-4294-ac52-3e014eab92b7", + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "
[[{pt: 1, phi: 1.2}, {pt: 2, phi: 1.4}],\n",
+       " [],\n",
+       " [{pt: 3, phi: 1.6}],\n",
+       " [{pt: 4, phi: 3.4}]]\n",
+       "------------------------------------------------------------\n",
+       "backend: cpu\n",
+       "nbytes: 104 B\n",
+       "type: 4 * var * TwoVector[\n",
+       "    pt: int64,\n",
+       "    phi: float64\n",
+       "]
" + ], + "text/plain": [ + "" + ] + }, + "execution_count": 15, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "vec = ak.zip(\n", + " {\n", + " \"pt\": [[1, 2], [], [3], [4]],\n", + " \"phi\": [[1.2, 1.4], [], [1.6], [3.4]],\n", + " },\n", + " with_name=\"TwoVector\",\n", + " behavior=behavior,\n", + ")\n", + "vec" + ] + }, + { + "cell_type": "markdown", + "id": "c2889f3f-5fb3-42ea-bd5d-8c0135aa7c81", + "metadata": {}, + "source": [ + "The binary operators are not automatically registered by Awkward, but Vector methods can be used to perform operations on subclassed vectors." + ] + }, + { + "cell_type": "code", + "execution_count": 16, + "id": "b4ecc08c-253b-46b7-a78a-1aca4558d863", + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "
[[{rho: 2, phi: 1.2}, {rho: 4, phi: 1.4}],\n",
+       " [],\n",
+       " [{rho: 6, phi: 1.6}],\n",
+       " [{rho: 8, phi: -2.88}]]\n",
+       "---------------------------------------------------------------\n",
+       "backend: cpu\n",
+       "nbytes: 104 B\n",
+       "type: 4 * var * TwoVector[\n",
+       "    rho: float64,\n",
+       "    phi: float64\n",
+       "]
" + ], + "text/plain": [ + "" + ] + }, + "execution_count": 16, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "vec.add(vec)" + ] + }, + { + "cell_type": "markdown", + "id": "41426373-4492-4ff6-9496-3e5d88ef630e", + "metadata": {}, + "source": [ + "Similarly, other vector methods can be used by the new methods internally." + ] + }, + { + "cell_type": "code", + "execution_count": 17, + "id": "2c05135c-ba70-4b24-9d9f-2b04f72bf1ce", + "metadata": {}, + "outputs": [], + "source": [ + "import numbers" + ] + }, + { + "cell_type": "code", + "execution_count": 18, + "id": "8e24d10e-a1ab-4614-9e8e-62a6378c0864", + "metadata": {}, + "outputs": [], + "source": [ + "@ak.mixin_class(behavior)\n", + "class LorentzVector(vector.backends.awkward.MomentumAwkward4D):\n", + " @ak.mixin_class_method(np.divide, {numbers.Number})\n", + " def divide(self, factor):\n", + " return self.scale(1 / factor)\n", + "\n", + "\n", + "# required for transforming vectors\n", + "# the class names must always end with \"Array\"\n", + "LorentzVectorArray.ProjectionClass2D = TwoVectorArray # noqa: F821\n", + "LorentzVectorArray.ProjectionClass3D = ThreeVectorArray # noqa: F821\n", + "LorentzVectorArray.ProjectionClass4D = LorentzVectorArray # noqa: F821\n", + "LorentzVectorArray.MomentumClass = LorentzVectorArray # noqa: F821" + ] + }, + { + "cell_type": "code", + "execution_count": 19, + "id": "203112e0-217e-4dc5-8145-881d48c9cf08", + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "
[[{pt: 1, eta: 1.2, phi: 0.3, energy: 50}, {pt: 2, eta: 1.4, ...}],\n",
+       " [],\n",
+       " [{pt: 3, eta: 1.6, phi: 0.5, energy: 52}],\n",
+       " [{pt: 4, eta: 3.4, phi: 0.6, energy: 60}]]\n",
+       "-----------------------------------------------------------------------------------------------------\n",
+       "backend: cpu\n",
+       "nbytes: 168 B\n",
+       "type: 4 * var * LorentzVector[\n",
+       "    pt: int64,\n",
+       "    eta: float64,\n",
+       "    phi: float64,\n",
+       "    energy: int64\n",
+       "]
" + ], + "text/plain": [ + "" + ] + }, + "execution_count": 19, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "vec = ak.zip(\n", + " {\n", + " \"pt\": [[1, 2], [], [3], [4]],\n", + " \"eta\": [[1.2, 1.4], [], [1.6], [3.4]],\n", + " \"phi\": [[0.3, 0.4], [], [0.5], [0.6]],\n", + " \"energy\": [[50, 51], [], [52], [60]],\n", + " },\n", + " with_name=\"LorentzVector\",\n", + " behavior=behavior,\n", + ")\n", + "vec" + ] + }, + { + "cell_type": "code", + "execution_count": 20, + "id": "6bf279a8-fca7-4c16-aca8-90565818a646", + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "
[[{rho: 0.5, phi: 0.3, eta: 1.2, t: 25}, {rho: 1, phi: 0.4, ...}],\n",
+       " [],\n",
+       " [{rho: 1.5, phi: 0.5, eta: 1.6, t: 26}],\n",
+       " [{rho: 2, phi: 0.6, eta: 3.4, t: 30}]]\n",
+       "-----------------------------------------------------------------------------------------------------\n",
+       "backend: cpu\n",
+       "nbytes: 168 B\n",
+       "type: 4 * var * LorentzVector[\n",
+       "    rho: float64,\n",
+       "    phi: float64,\n",
+       "    eta: float64,\n",
+       "    t: float64\n",
+       "]
" + ], + "text/plain": [ + "" + ] + }, + "execution_count": 20, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "vec / 2" + ] + }, + { + "cell_type": "code", + "execution_count": 21, + "id": "6648d398-60e4-4a7d-bd88-a7dd4a35e8d0", + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "
[[{rho: 1, phi: 0.3}, {rho: 2, phi: 0.4}],\n",
+       " [],\n",
+       " [{rho: 3, phi: 0.5}],\n",
+       " [{rho: 4, phi: 0.6}]]\n",
+       "-------------------------------------------------------------\n",
+       "backend: cpu\n",
+       "nbytes: 104 B\n",
+       "type: 4 * var * TwoVector[\n",
+       "    rho: int64,\n",
+       "    phi: float64\n",
+       "]
" + ], + "text/plain": [ + "" + ] + }, + "execution_count": 21, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "vec.like(vector.obj(x=1, y=2))" + ] + }, + { + "cell_type": "code", + "execution_count": 22, + "id": "09854ba6-f571-42f8-95a9-b0ac52553cda", + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "
[[{rho: 1, phi: 0.3, eta: 1.2}, {rho: 2, phi: 0.4, eta: 1.4}],\n",
+       " [],\n",
+       " [{rho: 3, phi: 0.5, eta: 1.6}],\n",
+       " [{rho: 4, phi: 0.6, eta: 3.4}]]\n",
+       "---------------------------------------------------------------------------------\n",
+       "backend: cpu\n",
+       "nbytes: 136 B\n",
+       "type: 4 * var * ThreeVector[\n",
+       "    rho: int64,\n",
+       "    phi: float64,\n",
+       "    eta: float64\n",
+       "]
" + ], + "text/plain": [ + "" + ] + }, + "execution_count": 22, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "vec.like(vector.obj(x=1, y=2, z=3))" + ] + }, + { + "cell_type": "markdown", + "id": "59cf3641-e227-4f0b-a1fa-99b0d196f02f", + "metadata": {}, + "source": [ + "It is also possible to manually add binary operations in vector's behavior dict to enable binary operations." + ] + }, + { + "cell_type": "code", + "execution_count": 23, + "id": "11778dd0-4726-43cc-817b-3326528dd144", + "metadata": {}, + "outputs": [], + "source": [ + "_binary_dispatch_cls = {\n", + " \"TwoVector\": TwoVector,\n", + " \"ThreeVector\": ThreeVector,\n", + " \"LorentzVector\": LorentzVector,\n", + "}\n", + "_rank = [TwoVector, ThreeVector, LorentzVector]\n", + "\n", + "for lhs, lhs_to in _binary_dispatch_cls.items():\n", + " for rhs, rhs_to in _binary_dispatch_cls.items():\n", + " out_to = min(lhs_to, rhs_to, key=_rank.index)\n", + " behavior[(np.add, lhs, rhs)] = out_to.add\n", + " behavior[(np.subtract, lhs, rhs)] = out_to.subtract" + ] + }, + { + "cell_type": "code", + "execution_count": 24, + "id": "3088485c-70e4-461d-86b3-5db81148389f", + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "
[[{rho: 2, phi: 0.3, eta: 1.2, t: 100}, {rho: 4, phi: 0.4, eta: 1.4, ...}],\n",
+       " [],\n",
+       " [{rho: 6, phi: 0.5, eta: 1.6, t: 104}],\n",
+       " [{rho: 8, phi: 0.6, eta: 3.4, t: 120}]]\n",
+       "---------------------------------------------------------------------------------------------------\n",
+       "backend: cpu\n",
+       "nbytes: 168 B\n",
+       "type: 4 * var * LorentzVector[\n",
+       "    rho: float64,\n",
+       "    phi: float64,\n",
+       "    eta: float64,\n",
+       "    t: int64\n",
+       "]
" + ], + "text/plain": [ + "" + ] + }, + "execution_count": 24, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "vec + vec" + ] + }, + { + "cell_type": "code", + "execution_count": 25, + "id": "040e47cc-013d-423e-b5df-b0982a2279aa", + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "
[[{rho: 2, phi: 0.3}, {rho: 4, phi: 0.4}],\n",
+       " [],\n",
+       " [{rho: 6, phi: 0.5}],\n",
+       " [{rho: 8, phi: 0.6}]]\n",
+       "---------------------------------------------------------------\n",
+       "backend: cpu\n",
+       "nbytes: 104 B\n",
+       "type: 4 * var * TwoVector[\n",
+       "    rho: float64,\n",
+       "    phi: float64\n",
+       "]
" + ], + "text/plain": [ + "" + ] + }, + "execution_count": 25, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "vec.to_2D() + vec.to_2D()" + ] + }, + { + "cell_type": "markdown", + "id": "e2259fbe-3eea-4fde-bedb-b5631f639ca3", + "metadata": {}, + "source": [ + "Finally, instead of manually registering the superclass ufuncs, one can use the utility `copy_behaviors` function to copy behavior items for a new subclass -" + ] + }, + { + "cell_type": "code", + "execution_count": 26, + "id": "4af071da-8612-49a2-9a56-7e49487cf866", + "metadata": {}, + "outputs": [], + "source": [ + "behavior.update(ak._util.copy_behaviors(\"Vector2D\", \"TwoVector\", behavior))\n", + "behavior.update(ak._util.copy_behaviors(\"Vector3D\", \"ThreeVector\", behavior))\n", + "behavior.update(ak._util.copy_behaviors(\"Momentum4D\", \"LorentzVector\", behavior))" + ] + }, + { + "cell_type": "code", + "execution_count": 27, + "id": "1c434751-a932-4694-92fc-9e48b51905b0", + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "
[[{rho: 2, phi: 0.3, eta: 1.2, t: 100}, {rho: 4, phi: 0.4, eta: 1.4, ...}],\n",
+       " [],\n",
+       " [{rho: 6, phi: 0.5, eta: 1.6, t: 104}],\n",
+       " [{rho: 8, phi: 0.6, eta: 3.4, t: 120}]]\n",
+       "------------------------------------------------------------------------------------------------\n",
+       "backend: cpu\n",
+       "nbytes: 168 B\n",
+       "type: 4 * var * Momentum4D[\n",
+       "    rho: float64,\n",
+       "    phi: float64,\n",
+       "    eta: float64,\n",
+       "    t: int64\n",
+       "]
" + ], + "text/plain": [ + "" + ] + }, + "execution_count": 27, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "vec + vec" + ] + }, + { + "cell_type": "code", + "execution_count": 28, + "id": "09e2bc41-340d-4ad6-82d8-f08cf869644a", + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "
[[{rho: 2, phi: 0.3}, {rho: 4, phi: 0.4}],\n",
+       " [],\n",
+       " [{rho: 6, phi: 0.5}],\n",
+       " [{rho: 8, phi: 0.6}]]\n",
+       "--------------------------------------------------------------\n",
+       "backend: cpu\n",
+       "nbytes: 104 B\n",
+       "type: 4 * var * Vector2D[\n",
+       "    rho: float64,\n",
+       "    phi: float64\n",
+       "]
" + ], + "text/plain": [ + "" + ] + }, + "execution_count": 28, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "vec.to_2D() + vec.to_2D()" + ] } ], "metadata": { diff --git a/docs/src/make_awkward.md b/docs/src/make_awkward.md index 44b10a2b..fae35119 100644 --- a/docs/src/make_awkward.md +++ b/docs/src/make_awkward.md @@ -1,6 +1,6 @@ # Making Awkward Arrays of vectors -An Awkward Array of vectors is an Awkward Array containing appropriately named records, appropriately named fields, and the Vector behaviors registered in the array. Here's a complete example for illustration: +An Awkward Array of vectors is an Awkward Array containing appropriately named records, appropriately named fields, and the Vector [behaviors](https://awkward-array.org/doc/main/reference/ak.behavior.html) registered in the array. Here's a complete example for illustration: ```python >>> import awkward as ak diff --git a/docs/src/numpy.ipynb b/docs/src/numpy.ipynb index 2694368e..d830eb60 100644 --- a/docs/src/numpy.ipynb +++ b/docs/src/numpy.ipynb @@ -13,7 +13,7 @@ "id": "1144533f-0290-43f2-a9f2-adc9d042ed1a", "metadata": {}, "source": [ - "First, [install](../index.md#installation) and import Vector and NumPy. (Vector requires NumPy, so if you can use Vector, you've already installed NumPy.)" + "First, [install](../index.md#installation) and import Vector and [NumPy](https://numpy.org/). (Vector requires NumPy, so if you can use Vector, you've already installed NumPy.)" ] }, { diff --git a/docs/src/sympy.ipynb b/docs/src/sympy.ipynb index afc0b10d..df5e10ac 100644 --- a/docs/src/sympy.ipynb +++ b/docs/src/sympy.ipynb @@ -40,7 +40,7 @@ "id": "07e49af1-a2e4-43e9-b265-38d917456ce0", "metadata": {}, "source": [ - "[SymPy](https://www.sympy.org/) is a computer algebra system like Mathematica and Maple. It primarily deals with algebraic expressions, rather than concrete numbers. However, all of the coordinate transformations and vector manipulations can be applied symbolically through Vector's SymPy backend.\n", + "SymPy is a computer algebra system like Mathematica and Maple. It primarily deals with algebraic expressions, rather than concrete numbers. However, all of the coordinate transformations and vector manipulations can be applied symbolically through Vector's SymPy backend.\n", "\n", "When comparing SymPy to the other backends, note that SymPy vector expressions have a different sign convention for operations on space-like and negative time-like 4D vectors. For all other backends, Vector's conventions were chosen to agree with popular HEP libraries, particularly [ROOT](https://root.cern), but for the SymPy backend, those conventions would insert piecewise if-then branches, which would complicate symbolic expressions.\n", "\n", From d8efb141d05cb1e71f69fe17b77b979144670b8b Mon Sep 17 00:00:00 2001 From: Jim Pivarski Date: Thu, 19 Dec 2024 19:14:34 -0600 Subject: [PATCH 23/23] the tutorials are all done now --- docs/src/numba.ipynb | 180 ++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 176 insertions(+), 4 deletions(-) diff --git a/docs/src/numba.ipynb b/docs/src/numba.ipynb index 952d49c4..444a9926 100644 --- a/docs/src/numba.ipynb +++ b/docs/src/numba.ipynb @@ -10,19 +10,191 @@ }, { "cell_type": "markdown", - "id": "26a7599a-5b33-4f6d-85d2-788295abe176", + "id": "03064225-ea6b-4f6b-a5bf-08a47b62350e", "metadata": {}, "source": [ - "First, [install](../index.md#installation) and import Vector." + "First, [install](../index.md#installation) and import Vector and [Numba](https://numba.pydata.org/)." ] }, { "cell_type": "code", "execution_count": 1, - "id": "2ccf22f1-fc21-4afe-8e46-baef45a1e85b", + "id": "df8bea35-cf3c-4f87-8e3d-8ffe06264811", "metadata": {}, "outputs": [], - "source": [] + "source": [ + "import vector\n", + "import numba as nb\n", + "import numpy as np" + ] + }, + { + "cell_type": "markdown", + "id": "7fff9620-227b-4e5e-a211-4daf1fb96298", + "metadata": {}, + "source": [ + "Numba is a just-in-time (JIT) compiler for a mathematically relevant subset of NumPy and Python. It allows you to write fast code without leaving the Python environment. The drawback of Numba is that it can only compile code blocks involving objects and functions that it recognizes.\n", + "\n", + "The Vector library includes extensions to inform Numba about [vector objects](object.md), ~~[arrays of vectors](numpy.md)~~, and [arrays of Awkward Arrays](awkward.md). At the time of writing, the implementation of vector NumPy arrays is incomplete (see issue [#43](https://github.com/scikit-hep/vector/issues/43)).\n", + "\n", + "Consider the following function:" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "id": "0e7f7c5c-2ce3-4f55-9159-363910fac6b9", + "metadata": {}, + "outputs": [], + "source": [ + "@nb.njit\n", + "def compute_mass(v1, v2):\n", + " return (v1 + v2).mass" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "id": "16d0fe04-fc8d-4d1f-bb68-0f869c1d2bdb", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "8.0" + ] + }, + "execution_count": 3, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "compute_mass(vector.obj(px=1, py=2, pz=3, E=4), vector.obj(px=-1, py=-2, pz=-3, E=4))" + ] + }, + { + "cell_type": "markdown", + "id": "69c36f6d-3b54-4db8-9890-9245d64fefe7", + "metadata": {}, + "source": [ + "When the two `MomentumObject4D` objects are passed as arguments, Numba recognizes them and replaces the Python objects with low-level structs. When it compiles the function, it recognizes `+` as the 4D `add` function and recognizes `.mass` as the `tau` component of the result.\n", + "\n", + "Although this demonstrates that Numba can manipulate vector objects, there is no performance advantage (and a likely disadvantage) to compiling a calculation on just a few vectors. The advantage comes when many vectors are involved, in arrays." + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "id": "63f614a2-969d-465d-8d74-a44f6f77eab4", + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "
[[],\n",
+       " [{x: 1.96, y: -0.654, z: -0.443, t: 8.88}, ..., {x: -0.0976, y: 0.877, ...}],\n",
+       " [{x: -0.543, y: 1.82, z: 0.177, t: 10.1}],\n",
+       " [{x: 0.0705, y: 0.816, z: -0.607, t: 10.1}, ..., {x: -0.756, y: -2.23, ...}],\n",
+       " [{x: -1.61, y: -1.14, z: 0.312, t: 10.2}, ..., {x: -0.878, y: -0.803, ...}],\n",
+       " [{x: -1.4, y: -1.09, z: 1.13, t: 9.03}],\n",
+       " [{x: 0.634, y: -0.0388, z: -0.44, t: 10.5}],\n",
+       " [{x: -0.767, y: 0.0841, z: -0.344, t: 9.34}],\n",
+       " [{x: -1.89, y: 0.295, z: -1.95, t: 10.1}],\n",
+       " [{x: -1.85, y: -0.832, z: -0.816, t: 8.2}],\n",
+       " ...,\n",
+       " [{x: 0.496, y: 0.791, z: 1.67, t: 10.8}],\n",
+       " [{x: -1.09, y: 1.42, z: -0.299, t: 11.4}],\n",
+       " [{x: -0.885, y: -0.537, z: -0.0475, t: 9.95}, {x: -0.615, y: 1.19, ...}],\n",
+       " [{x: -0.503, y: -3.06, z: 0.893, t: 9.61}, ..., {x: 0.263, y: -0.493, ...}],\n",
+       " [{x: 2.16, y: -1.11, z: 0.696, t: 11.2}, {x: 0.824, y: 0.604, ...}],\n",
+       " [],\n",
+       " [{x: 1.55, y: 0.497, z: -0.764, t: 10.3}, {x: 0.311, y: 0.545, ...}],\n",
+       " [],\n",
+       " [{x: 0.0877, y: 0.334, z: -1.5, t: 10.5}, {x: 1.26, y: 1.94, ...}]]\n",
+       "---------------------------------------------------------------------------------------------\n",
+       "backend: cpu\n",
+       "nbytes: 3.0 kB\n",
+       "type: 50 * var * Momentum4D[\n",
+       "    x: float64,\n",
+       "    y: float64,\n",
+       "    z: float64,\n",
+       "    t: float64\n",
+       "]
" + ], + "text/plain": [ + "" + ] + }, + "execution_count": 4, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# This is still not a large number. You want millions.\n", + "array = vector.Array(\n", + " [\n", + " [\n", + " dict(\n", + " {x: np.random.normal(0, 1) for x in (\"px\", \"py\", \"pz\")},\n", + " E=np.random.normal(10, 1),\n", + " )\n", + " for inner in range(np.random.poisson(1.5))\n", + " ]\n", + " for outer in range(50)\n", + " ]\n", + ")\n", + "array" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "id": "f6edd6c9-a423-4662-bcae-c685686633c8", + "metadata": {}, + "outputs": [], + "source": [ + "@nb.njit\n", + "def compute_masses(array):\n", + " out = np.empty(len(array), np.float64)\n", + " for i, event in enumerate(array):\n", + " total = vector.obj(px=0.0, py=0.0, pz=0.0, E=0.0)\n", + " for vec in event:\n", + " total = total + vec\n", + " out[i] = total.mass\n", + " return out" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "id": "fa854373-aeba-4274-8ab8-c1c85d5a931b", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "array([ 0. , 29.59334472, 9.96825092, 29.98088102, 30.022318 ,\n", + " 8.77904697, 10.52123699, 9.30633562, 9.69685471, 7.90724598,\n", + " 8.22083106, 12.10506017, 9.14678916, 42.27902654, 10.08573923,\n", + " 9.98477624, 0. , 22.79438116, 29.12919935, 32.07848403,\n", + " 29.6325778 , 0. , 8.11447927, 39.07959905, 30.54027295,\n", + " 18.39609413, 21.15982485, 18.62455179, 7.75621961, 19.52526457,\n", + " 19.52907948, 20.40038164, 8.84074954, 9.18655937, 30.22076618,\n", + " 8.47538375, 10.42253874, 17.84485932, 0. , 41.55064913,\n", + " 0. , 10.60246245, 11.24522316, 19.32603825, 31.28879051,\n", + " 20.49852241, 0. , 20.21304572, 0. , 20.76651039])" + ] + }, + "execution_count": 6, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "compute_masses(array)" + ] } ], "metadata": {