-
Notifications
You must be signed in to change notification settings - Fork 0
Add documentation for types: scalars, lists, and NumPy arrays #81
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,168 @@ | ||
| --- | ||
| sidebar_position: 5 | ||
| --- | ||
|
|
||
| # Input types (Python / NumPy) and numerical precision | ||
|
|
||
| `pyamtrack` is a Python interface to the C/C++ **libamtrack** library. Many functions accept either a **single number** or a **set of numbers** (a Python list or a NumPy array). Internally, most continuous physical quantities are computed using C/C++ **double precision** (`double`). | ||
|
|
||
| This page explains what you can pass to `pyamtrack` functions and how to avoid the most common numerical pitfalls—especially when using `numpy.float32`. | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I wouldn't expose the |
||
|
|
||
| --- | ||
|
|
||
| ## Quick recommendations (safe defaults) | ||
|
|
||
| If you only read one section, read this: | ||
|
|
||
| - For **single values** (energy, LET, etc.): use Python `float` | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. scientists like exponential notation, mentioning number like |
||
| (example: `150.0`, not `np.float32(150)`). | ||
| - For **arrays of values**: use NumPy arrays with `dtype=np.float64`. | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. See: by default we get float64. Its safe to recommend np.array and give such example. |
||
| - For **IDs** (material IDs, model IDs): use Python `int` or integer NumPy arrays (`np.int32` / `np.int64`). | ||
| - Avoid `numpy.float32` / `dtype=np.float32` for inputs to physics calculations unless you really know you can tolerate reduced precision. | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. that should go to bottom of the page |
||
|
|
||
| --- | ||
|
|
||
| ## 1) What inputs are accepted? | ||
|
|
||
| Most numeric functions accept these input forms: | ||
|
|
||
| ### A. A single number | ||
| Use when you want one result. | ||
|
|
||
| ```python | ||
| import pyamtrack | ||
| pyamtrack.converters.beta_from_energy(150.0) | ||
| ``` | ||
|
|
||
| ### B. A list of numbers | ||
| Use when you want results for multiple values. | ||
|
|
||
| ```python | ||
| import pyamtrack | ||
| energies = [50.0, 100.0, 150.0] | ||
| pyamtrack.stopping.electron_range(energies, material=1, model="tabata") | ||
| ``` | ||
|
|
||
| ### C. A NumPy array (`ndarray`) | ||
| Recommended for performance and clarity, especially for longer vectors. | ||
|
|
||
| ```python | ||
| import numpy as np | ||
| import pyamtrack | ||
|
|
||
| energies = np.asarray([50.0, 100.0, 150.0], dtype=np.float64) | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I would recommend numpy array when plotting is needed and you need hundreds of values, like: using numpy array just for few numbers is weird. You can mention plotting, its frequent use case |
||
| pyamtrack.stopping.electron_range(energies, material=1, model="tabata") | ||
| ``` | ||
|
|
||
| **Note:** Some functions require NumPy input arrays to be **1‑dimensional** (a simple vector). | ||
|
|
||
| --- | ||
|
|
||
| ## 2) Continuous values vs IDs (different “kinds” of inputs) | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Continous vs discrete ? |
||
|
|
||
| In `pyamtrack`, it helps to think of inputs in two categories: | ||
|
|
||
| ### A. Continuous physical quantities (use float64) | ||
| Examples: energies, ranges, stopping power values, etc. | ||
|
|
||
| - Recommended dtype for arrays: **`np.float64`** | ||
| - Recommended type for scalars: Python **`float`** | ||
|
|
||
| ### B. Integer identifiers (use integers) | ||
| Examples: `material` ID, sometimes model ID. | ||
|
|
||
| - Recommended dtype for arrays: **`np.int32`** or **`np.int64`** | ||
| - Recommended type for scalars: Python **`int`** | ||
|
|
||
| Example (material IDs as an integer array): | ||
|
|
||
| ```python | ||
| import numpy as np | ||
| import pyamtrack | ||
|
|
||
| energies = np.asarray([50.0, 100.0, 150.0], dtype=np.float64) | ||
| materials = np.asarray([1, 1, 1], dtype=np.int32) | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. here for materials I'd use simple list, not an array. I'd also use the opportunity to say to the user that you can mix types, like one argument being np.array, another list and another string. |
||
|
|
||
| pyamtrack.stopping.electron_range(energies, material=materials, model="tabata") | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. do we support strings as model ? |
||
| ``` | ||
|
|
||
| --- | ||
|
|
||
| ## 3) Why `numpy.float32` is not recommended | ||
|
|
||
| You will often see NumPy arrays created with `dtype=np.float32` to save memory. However, for `pyamtrack` this can be a bad default. | ||
|
|
||
| ### What happens | ||
| Even though the C/C++ code uses `double`, if you store inputs as `float32`: | ||
|
|
||
| - the values are already rounded to about **7 significant digits**, | ||
| - and converting that float32 value to C/C++ `double` **cannot recover the lost precision**. | ||
|
|
||
| So you can get slightly different results compared to float64 inputs. | ||
|
|
||
| ### What to do instead | ||
| Prefer `float64`: | ||
|
|
||
| ```python | ||
| import numpy as np | ||
|
|
||
| # Not recommended for numerically sensitive inputs | ||
| x32 = np.asarray([0.1, 0.2, 0.3], dtype=np.float32) | ||
|
|
||
| # Recommended | ||
| x64 = np.asarray([0.1, 0.2, 0.3], dtype=np.float64) | ||
|
|
||
| # If you receive float32 from elsewhere, convert early: | ||
| x = np.asarray(x32, dtype=np.float64) | ||
| ``` | ||
|
|
||
| --- | ||
|
|
||
| ## 4) NumPy dtype vs C type (quick reference) | ||
|
|
||
| This is a short summary based on the NumPy documentation section | ||
| “Relationship Between NumPy Data Types and C Data Types”. | ||
| ([numpy.org](https://numpy.org/doc/stable/user/basics.types.html?utm_source=openai)) | ||
|
|
||
| | Recommended NumPy dtype | NumPy “C-like” name | Rough C type | Notes | | ||
| |---|---|---|---| | ||
| | `np.int32` | *(no single alias on every platform)* | usually `int32_t` | fixed width (portable) | | ||
| | `np.int64` | `np.longlong` | `long long` | fixed width (portable) | | ||
| | `np.float32` | `np.single` | `float` | ~7 significant digits | | ||
| | `np.float64` | `np.double` | `double` | ~15–16 significant digits | | ||
|
|
||
| --- | ||
|
|
||
| ## 5) “One value” vs “many values”: how results are returned | ||
|
|
||
| Many functions behave like this: | ||
|
|
||
| - If you pass a **single value**, you get a **single value** back (Python `float`). | ||
| - If you pass a **list** or **NumPy array**, you get a **vector of results** back (often a NumPy array). | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. always a numpy array ? |
||
|
|
||
| Example: | ||
|
|
||
| ```python | ||
| import numpy as np | ||
| import pyamtrack | ||
|
|
||
| print(pyamtrack.converters.beta_from_energy(150.0)) # scalar -> scalar | ||
|
|
||
| arr = np.asarray([50.0, 100.0, 150.0], dtype=np.float64) | ||
| print(pyamtrack.converters.beta_from_energy(arr)) # array -> array | ||
| ``` | ||
|
|
||
| --- | ||
|
|
||
| ## 6) Practical checklist for users | ||
|
|
||
| Before running calculations, quickly check: | ||
|
|
||
| 1. Are my **continuous values** stored as `float64`? | ||
| - `np.asarray(x, dtype=np.float64)` | ||
| 2. Are my **ID-like inputs** (materials/models) integers? | ||
| - `np.asarray(ids, dtype=np.int32)` or plain `int` | ||
| 3. Am I accidentally using `float32` because of upstream data loading? | ||
| - If yes: upcast early to `float64`. | ||
|
|
||
| --- | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
set of numbers : set is something that is not ordered, I would rather say "vector"/"matrix".
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would also avoid here mentioning the double precision stuff.
what I'd expect here is a few sentences like "The aim of this page is to familiarize the user with the input/output datatypes for functions available in libamtrack...."