# Awkward Arrays of vectors

First, [install](../index.html.md#installation) and import Vector and [Awkward Array](https://awkward-array.org/).

```none
[1]:
```

## Making an Awkward Array of vectors

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).

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.html.md) and [NumPy subclasses](numpy.html.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.

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:

```none
[2]:
```

```none
[2]:
```

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.

For instance, we can compute `rho` and `phi` coordinates in the same way as with the [NumPy subclasses](numpy.html.md), an array at a time:

```none
[3]:
```

```none
[3]:
```

```none
[4]:
```

```none
[4]:
```

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.

An Awkward Array needs all of the following for its records to be interpreted as vectors:

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"`
2. the field names must be recognized coordinate names, following the same conventions as [vector objects](object.html.md)
3. the array must have `vector.backends.awkward.behavior` as its `behavior`.

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.

To make sure that Vector behaviors are always available, you can call [vector.register_awkward](make_awkward.html.md#vector.register_awkward) at the beginning of every script, like this:

```python
import awkward as ak
import vector
vector.register_awkward()
```

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.

Vector also has a [vector.Array](make_awkward.html.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.html.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).

## Using an Awkward array of vectors

First, let’s make some arrays to use in examples:

```none
[5]:
```

```none
[6]:
```

```none
[7]:
```

```none
[7]:
```

```none
[8]:
```

```none
[8]:
```

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:

```none
[9]:
```

```none
[9]:
```

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:

```none
[10]:
```

Like NumPy, the array-at-a-time expression is more concise and faster:

```none
[11]:
```

```none
[12]:
```

```none
[13]:
```

(Note the units.)

Just as with NumPy, all of the coordinate transformations and vector operations are implemented for Awkward Arrays of vectors.

## Some troubleshooting hints

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?

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.)

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?

## Advanced: subclassing Awkward-Vector behaviors

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:

```none
[14]:
```

```none
[15]:
```

```none
[15]:
```

The binary operators are not automatically registered by Awkward, but Vector methods can be used to perform operations on subclassed vectors.

```none
[16]:
```

```none
[16]:
```

Similarly, other vector methods can be used by the new methods internally.

```none
[17]:
```

```none
[18]:
```

```none
[19]:
```

```none
[19]:
```

```none
[20]:
```

```none
[20]:
```

```none
[21]:
```

```none
[21]:
```

```none
[22]:
```

```none
[22]:
```

It is also possible to manually add binary operations in vector’s behavior dict to enable binary operations.

```none
[23]:
```

```none
[24]:
```

```none
[24]:
```

```none
[25]:
```

```none
[25]:
```

Finally, instead of manually registering the superclass ufuncs, one can use the utility `copy_behaviors` function to copy behavior items for a new subclass -

```none
[26]:
```

```none
[27]:
```

```none
[27]:
```

```none
[28]:
```

```none
[28]:
```
