Skip to content

Commit

Permalink
finished the (public) reference documentation
Browse files Browse the repository at this point in the history
  • Loading branch information
jpivarski committed Dec 19, 2024
1 parent 23f4495 commit 1405409
Show file tree
Hide file tree
Showing 10 changed files with 296 additions and 59 deletions.
14 changes: 13 additions & 1 deletion docs/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -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.

Expand Down Expand Up @@ -87,7 +88,18 @@ Refer to [CONTRIBUTING.md](https://github.com/scikit-hep/vector/blob/main/.githu

## Documentation

<!-- src/object.ipynb -->
<!-- src/numpy.ipynb -->
<!-- src/awkward.ipynb -->
<!-- src/numba.ipynb -->
<!-- src/sympy.ipynb -->

```{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
Expand Down
9 changes: 8 additions & 1 deletion docs/src/common.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
48 changes: 48 additions & 0 deletions docs/src/make_awkward.md
Original file line number Diff line number Diff line change
@@ -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)
<Array [[2.46, 5.5], [], [8.59]] type='3 * var * float64'>
```

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
```
47 changes: 47 additions & 0 deletions docs/src/make_numpy.md
Original file line number Diff line number Diff line change
@@ -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
```
47 changes: 47 additions & 0 deletions docs/src/make_object.md
Original file line number Diff line number Diff line change
@@ -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
```
57 changes: 57 additions & 0 deletions docs/src/make_sympy.md
Original file line number Diff line number Diff line change
@@ -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
```
1 change: 1 addition & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ optional-dependencies.dev = [
]
optional-dependencies.docs = [
"awkward>=2",
"sympy",
"ipykernel",
"myst-parser>0.13",
"nbsphinx",
Expand Down
50 changes: 50 additions & 0 deletions src/vector/backends/numpy.py
Original file line number Diff line number Diff line change
Expand Up @@ -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', '<f8'), ('y', '<f8')])
>>> 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', '<f8'), ('y', '<f8')])
"""

ObjectClass = vector.backends.object.VectorObject2D
Expand Down Expand Up @@ -1316,6 +1324,14 @@ class MomentumNumpy2D(PlanarMomentum, VectorNumpy2D):
>>> vec
MomentumNumpy2D([(1.1, 2.1), (1.2, 2.2), (1.3, 2.3), (1.4, 2.4), (1.5, 2.5)],
dtype=[('x', '<f8'), ('y', '<f8')])
>>> 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', '<f8'), ('y', '<f8')])
"""

ObjectClass = vector.backends.object.MomentumObject2D
Expand Down Expand Up @@ -1365,6 +1381,14 @@ class VectorNumpy3D(VectorNumpy, Spatial, Vector3D, FloatArray): # type: ignore
>>> 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', '<f8'), ('y', '<f8'), ('z', '<f8')])
>>> 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', '<f8'), ('y', '<f8'), ('z', '<f8')])
"""

ObjectClass = vector.backends.object.VectorObject3D
Expand Down Expand Up @@ -1604,6 +1628,14 @@ class MomentumNumpy3D(SpatialMomentum, VectorNumpy3D):
>>> 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', '<f8'), ('y', '<f8'), ('z', '<f8')])
>>> 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', '<f8'), ('y', '<f8'), ('z', '<f8')])
"""

ObjectClass = vector.backends.object.MomentumObject3D
Expand Down Expand Up @@ -1664,6 +1696,15 @@ class VectorNumpy4D(VectorNumpy, Lorentz, Vector4D, FloatArray): # type: ignore
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', '<f8'), ('y', '<f8'), ('z', '<f8'), ('t', '<f8')])
>>> 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', '<f8'), ('y', '<f8'), ('z', '<f8'), ('t', '<f8')])
"""

ObjectClass = vector.backends.object.VectorObject4D
Expand Down Expand Up @@ -1972,6 +2013,15 @@ class MomentumNumpy4D(LorentzMomentum, VectorNumpy4D):
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', '<f8'), ('y', '<f8'), ('z', '<f8'), ('t', '<f8')])
>>> 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', '<f8'), ('y', '<f8'), ('z', '<f8'), ('t', '<f8')])
"""

ObjectClass = vector.backends.object.MomentumObject4D
Expand Down
Loading

0 comments on commit 1405409

Please sign in to comment.