# Nata API design
## Plugins
```python
@register_plugin([ParticleDataset, ParticleArray], name="awesome")
def my_plugin(ds: Union[ParticleDataset, ParticleArray]):
pass
```
---
## Particles
| Class | Output shape of `to.numpy()` or `.to_dask()` |
| ----------------- | ----------------------------------------------------- |
| `ParticleDataset` | 2d structured array of `[("q1", int), ("q2", float)]` |
| `ParticleArray` | 1d structured array of `[("q1", int), ("q2", float)]` |
| `Particle` | 0d structured array of `[("q1", int), ("q2", float)]` |
| `QuantityArray` | 1d array of `int/float/...` |
| `Quantity` | 0d array of `int/float/...` |
### Indexing summary:
#### `ParticleDataset` indexing:
pds[t1:t2] -> ParticleDataset
pds[t1] -> ParticleArray
pds[t1, i1:i2] -> ParticleArray
pds[t1, i1:i2, ["x1", "x2"]] -> ParticleArray
pds[t1, i1:i2, "x1"] -> QuantityArray
pds[t1, i1:i2, ["x1"]] -> ParticleArray
pds[t1, i1] -> Particle
pds[t1, i1, ["x1", "x2"]] -> Particle
pds[t1, i1, "x1"] -> Quantity
#### `ParticleArray` indexing:
arr = pds[t1]
arr[i1:i2] = pds[t1, i1:i2] -> ParticleArray
arr[i1:i2, ["x1", "x2"]] -> ParticleArray
arr["x1"] -> QuantityArray
arr[i1:i2, "x1"] -> QuantityArray
arr[i1:i2, ["x1"]] -> ParticleArray
arr[i1] -> Particle
arr[i1, ["x1", "x2"]] -> Particle
arr[i1, "x1"] -> Quantity
#### `Particle` indexing:
prt = arr[i1]
prt["x1"] -> Quantity
prt[["x1", "x2"]] -> Particle
#### Example
- 10 time steps
- 123 particles
- 3 quantities
```python
pds = ParticleDataset.from_array(...)
pds.shape == (10, 123)
arr = pds[t0]
type(arr) == ParticleArray
arr.shape == (123,)
prt = arr[i1]
type(prt) == Particle
prt.shape == (,)
```
### Design decision for `Particles`
| Property | Meaning |
| ----------------- | ---------------------------------------------------------------------------- |
| `name` | Short name of the particle, e.g. species. |
| `label` | Descriptive name of the particle, e.g. species. |
| `time` | Associated time axis for the particle data. |
| `num` | Number of particles. |
| `quantities` | Tuple of containing tuples of `(name, label, unit)` for particle quantities. |
| `quantity_names` | Tuple of containing quantity names. |
| `quantity_labels` | Tuple of containing quantity labels. |
| `quantity_units` | Tuple of containing quantity units. |
---
## Grids
| Class | Output shape of `.to_numpy()` or `.to_dask()`
| ------------- | ------------------------------------------------------------
| `GridDataset` | (n+1)-d array, `.shape == (nt, nx, ny, ...)`, `.ndim == n+1`
| `GridArray` | (n)-d array, `.shape == (nx, ny, ...)`, `.ndim == n`
### Indexing summary:
#### `GridDataset` indexing:
gds[t1:t2] -> GridDataset
gds[t1, ...] -> GridArray, ndim == n
gds[t1, i1:i2, ...] -> GridArray, ndim == n-1
gds[t1, i1:i2, j1:j2, ...] -> GridArray, ndim == n-2
#### `GridArray` indexing:
arr = gds[t1]
arr[i1:i2, ...] = gds[t1, i1:i2] -> GridArray, ndim == n
arr[i1, ...] -> GridArray, ndim == n-1
### Axes summary:
#### `GridDataset` axes:
gds.axes -> (Axis(...), Axis(...), Axis(...))
gds.axes[0].shape == (100,)
gds.axes[1].shape == (100, 10)
gds.axes[2].shape == (100, 5)
gds.shape == (100, 10, 5)
#### `GridArray` axes:
arr = gds[t1]
arr.axes -> (Axis(...), Axis(...))
arr.axes[0].shape == (10,)
arr.axes[1].shape == (5,)
arr.shape == (10, 5)
---
## Scratchpad
:::danger
DO NOT CONSIDER THIS FOR API
:::
```python
gds.shape == (10, 50)
arr = gds.streak() #-> GridArray
arr.shape == (10, 50)
# if moving window
gds.to_static_window(v=.99, offset=100).streak()
gds.shape == (10, 50)
A(x, t)
A(x=2, t)
gds.func(const="x", val=2)
```
GridDataset.from_path("*", tempral_axis="time")
GridDataset.from_path("*", tempral_axis="iteration")
GridDataset.from_path("*", tempral_axis="iteration").axes[0]._data *= (ndump * dt)
foo = ParticleDataset.from_path("*", time_prop="abc")
foo.time.name == "abc"
bar = GridDataset.from_path("*", time_prop="abc")
bar.time.name == "abc"
bar.time -> bar.axes[0]
baz = bar[t0] -> GridArray
baz.time -> Axis, 0d
---
**May the fourth be with you**
| Class | Output shape of `.to_numpy()` or `.to_dask()` |
| ----------------- | ----------------------------------------------------- |
| `ParticleDataset` | 2d structured array of `[("q1", int), ("q2", float)]` |
| `ParticleArray` | 1d structured array of `[("q1", int), ("q2", float)]` |
| `Particle` | 0d structured array of `[("q1", int), ("q2", float)]` |
| `Quantity` | 0d array of `int/float/...` |
| `QuantityArray` | 1d array of `int/float/...` |
| Class | Output shape of `.to_numpy()` or `.to_dask()` |
| ----------------- | --------------------------------------------- |
| `ParticleDataset` | 2d/3d array of `int/float/...` |
| `ParticleArray` | 1d/2d array of `int/float/...` |
| `QuantityArray` | 1d array of `int/float/...` |
```python
prt = ParticleArray.from_array(...)
prt[quant_idx, particle_idx]
prt[quant_idx, :] -> QuantityArray
prt[quant_idx, :].ndim == 1
prt[:, particle_idx] -> ParticleArray
prt[:, particle_idx].ndim == 2
```
```python
# init with array with shape == (2, 3)
# ^----- number of quantities
# ^-------- number of particles
prt = ParticleArray.from_array(
[[1, 2, 3], [3, 4, 5]],
quantity_names=("x1", "x2", "x3")
)
assert prt.ndim == 2
assert prt.shape == (2, 3)
assert prt.number == 2
assert prt.quantity_names == ("x1", "x2", "x3")
assert prt.quantity_labels == ("unlabeled", "unlabeled", "unlabeled")
assert prt.quantity_units == ("", "", "")
# init with array with shape == (6,)
# ^-------- number of particles
prt = ParticleArray.from_array([1, 2, 3, 3, 4, 5])
assert prt.ndim == 1
assert prt.shape == (6,)
assert prt.number == 6
assert prt.quantity_names == ()
assert prt.quantity_labels == ()
assert prt.quantity_units == ()
# init with array with just a number
prt = ParticleArray.from_array(1)
assert prt.ndim == 0
assert prt.shape == ()
assert prt.number == 1
assert prt.quantity_names == ()
assert prt.quantity_labels == ()
assert prt.quantity_units == ()
# init with array with empty tuple (a.k.a. no particles)
prt = ParticleArray.from_array(())
assert prt.ndim == 1
assert prt.shape == (0,)
assert prt.number == 0
assert prt.quantity_names == ()
assert prt.quantity_labels == ()
assert prt.quantity_units == ()
```
{"metaMigratedAt":"2023-06-15T22:58:17.438Z","metaMigratedFrom":"Content","title":"Nata API design","breaks":true,"contributors":"[{\"id\":\"54197f01-0ce8-491e-a753-e36658126153\",\"add\":6227,\"del\":1286},{\"id\":\"b75f5995-0a30-4f2d-8aba-2b5f77658f75\",\"add\":7575,\"del\":5108},{\"id\":null,\"add\":153,\"del\":0}]"}