-
Notifications
You must be signed in to change notification settings - Fork 4
Generalized indexing, correct formatting for arrays, new constants. #100
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
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 | ||||
|---|---|---|---|---|---|---|
|
|
@@ -5,6 +5,11 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), | |||||
| and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). | ||||||
|
|
||||||
| ## [Unreleased] | ||||||
| ### Fixed | ||||||
| - Correctly formats output of arrays with a unit. | ||||||
|
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. also link the PR here |
||||||
|
|
||||||
| ### Added | ||||||
| - Getter and Setter generalized to common NumPy indexing, such that general slicing operations are possible in multiple dimensions. | ||||||
|
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.
Suggested change
|
||||||
|
|
||||||
| ## [0.11.1] - 2026-01-22 | ||||||
| ### Fixed | ||||||
|
|
||||||
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -1,5 +1,7 @@ | ||||||||||||||||||||||||
| #![warn(clippy::all)] | ||||||||||||||||||||||||
| #![allow(non_snake_case)] | ||||||||||||||||||||||||
| use std::f64::consts::PI; | ||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
| use ndarray::{Array1, arr1}; | ||||||||||||||||||||||||
| use numpy::IntoPyArray; | ||||||||||||||||||||||||
| use pyo3::basic::CompareOp; | ||||||||||||||||||||||||
|
|
@@ -78,11 +80,20 @@ impl PySIObject { | |||||||||||||||||||||||
| if let Ok(v) = self.value.extract::<f64>(py) { | ||||||||||||||||||||||||
| Ok(SINumber::new(v, self.unit).to_string()) | ||||||||||||||||||||||||
| } else { | ||||||||||||||||||||||||
| let value = self | ||||||||||||||||||||||||
| .value | ||||||||||||||||||||||||
| .call_method0(py, "__repr__")? | ||||||||||||||||||||||||
| .extract::<String>(py)?; | ||||||||||||||||||||||||
| Ok(format!("{} {}", value, self.unit)) | ||||||||||||||||||||||||
| let (multiplier, symbol) = SINumber::new(1.0, self.unit).into_scaled_parts(); | ||||||||||||||||||||||||
|
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. Is this for the annoying thing with grams and kilograms? I'm not sure I follow here. |
||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
| let value_str = if (multiplier - 1.0).abs() > 1e-15 { | ||||||||||||||||||||||||
| let scaled_val = self.value.call_method1(py, "__mul__", (multiplier,))?; | ||||||||||||||||||||||||
| scaled_val | ||||||||||||||||||||||||
| .call_method0(py, "__repr__")? | ||||||||||||||||||||||||
| .extract::<String>(py)? | ||||||||||||||||||||||||
| } else { | ||||||||||||||||||||||||
| self.value | ||||||||||||||||||||||||
| .call_method0(py, "__repr__")? | ||||||||||||||||||||||||
| .extract::<String>(py)? | ||||||||||||||||||||||||
| }; | ||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
| Ok(format!("{} {}", value_str, symbol)) | ||||||||||||||||||||||||
| } | ||||||||||||||||||||||||
| } | ||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
|
|
@@ -258,25 +269,43 @@ impl PySIObject { | |||||||||||||||||||||||
| .and_then(|v| v.extract::<usize>(py)) | ||||||||||||||||||||||||
| } | ||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
| fn __getitem__(&self, py: Python, idx: isize) -> PyResult<Self> { | ||||||||||||||||||||||||
| fn __getitem__(&self, py: Python, idx: &Bound<'_, PyAny>) -> PyResult<Self> { | ||||||||||||||||||||||||
| let value = self.value.call_method1(py, "__getitem__", (idx,))?; | ||||||||||||||||||||||||
| Ok(Self::new(value, self.unit)) | ||||||||||||||||||||||||
| } | ||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
| fn __setitem__(&self, py: Python, idx: isize, value: SINumber) -> PyResult<()> { | ||||||||||||||||||||||||
| if self.unit == value.unit { | ||||||||||||||||||||||||
| fn __setitem__( | ||||||||||||||||||||||||
| &self, | ||||||||||||||||||||||||
| py: Python, | ||||||||||||||||||||||||
| idx: &Bound<'_, PyAny>, | ||||||||||||||||||||||||
| value: &Bound<'_, PyAny>, | ||||||||||||||||||||||||
|
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.
Suggested change
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. We only need |
||||||||||||||||||||||||
| ) -> PyResult<()> { | ||||||||||||||||||||||||
| if let Ok(v) = value.extract::<SINumber>() { | ||||||||||||||||||||||||
| if self.unit == v.unit { | ||||||||||||||||||||||||
| self.value.call_method1(py, "__setitem__", (idx, v.value))?; | ||||||||||||||||||||||||
| return Ok(()); | ||||||||||||||||||||||||
| } | ||||||||||||||||||||||||
| return Err(QuantityError::InconsistentUnits { | ||||||||||||||||||||||||
| unit1: self.unit, | ||||||||||||||||||||||||
| unit2: v.unit, | ||||||||||||||||||||||||
| } | ||||||||||||||||||||||||
| .into()); | ||||||||||||||||||||||||
| } | ||||||||||||||||||||||||
|
Comment on lines
+283
to
+293
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.
Suggested change
I don't think that does anything. |
||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
| let ob = value.extract::<PyRef<PySIObject>>()?; | ||||||||||||||||||||||||
| if self.unit == ob.unit { | ||||||||||||||||||||||||
| self.value | ||||||||||||||||||||||||
| .call_method1(py, "__setitem__", (idx, value.value))?; | ||||||||||||||||||||||||
| .call_method1(py, "__setitem__", (idx, &ob.value))?; | ||||||||||||||||||||||||
| Ok(()) | ||||||||||||||||||||||||
| } else { | ||||||||||||||||||||||||
| Err(QuantityError::InconsistentUnits { | ||||||||||||||||||||||||
| unit1: self.unit, | ||||||||||||||||||||||||
| unit2: value.unit, | ||||||||||||||||||||||||
| })? | ||||||||||||||||||||||||
| unit2: ob.unit, | ||||||||||||||||||||||||
| } | ||||||||||||||||||||||||
| .into()) | ||||||||||||||||||||||||
| } | ||||||||||||||||||||||||
| } | ||||||||||||||||||||||||
| } | ||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
| #[derive(Clone, Copy)] | ||||||||||||||||||||||||
| pub struct SIObject<T> { | ||||||||||||||||||||||||
| value: T, | ||||||||||||||||||||||||
|
|
@@ -396,6 +425,9 @@ const _TESLA: SIUnit = SIUnit([0, 1, -2, -1, 0, 0, 0]); | |||||||||||||||||||||||
| const _HENRY: SIUnit = SIUnit([2, 1, -2, -2, 0, 0, 0]); | ||||||||||||||||||||||||
| const _METER_PER_SECOND: SIUnit = SIUnit([1, 0, -1, 0, 0, 0, 0]); | ||||||||||||||||||||||||
| const _LUMEN_PER_WATT: SIUnit = SIUnit([-2, -1, 3, 0, 0, 0, 1]); | ||||||||||||||||||||||||
| const _FARAD_PER_METER: SIUnit = SIUnit([-3, -1, 4, 2, 0, 0, 0]); | ||||||||||||||||||||||||
| const _METER_PER_FARAD: SIUnit = SIUnit([3, 1, -4, -2, 0, 0, 0]); | ||||||||||||||||||||||||
| const _PASCAL_SECOND: SIUnit = SIUnit([-1, 1, -1, 0, 0, 0, 0]); | ||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
| /// Prefix quecto $\\left(\text{q}=10^{-30}\\right)$ | ||||||||||||||||||||||||
| pub const QUECTO: f64 = 1e-30; | ||||||||||||||||||||||||
|
|
@@ -471,6 +503,13 @@ pub fn _core(m: &Bound<'_, PyModule>) -> PyResult<()> { | |||||||||||||||||||||||
| add_constant(m, "KB", 1.380649e-23, _JOULE_PER_KELVIN)?; | ||||||||||||||||||||||||
| add_constant(m, "NAV", 6.02214076e23, _PER_MOL)?; | ||||||||||||||||||||||||
| add_constant(m, "KCD", 683.0, _LUMEN_PER_WATT)?; | ||||||||||||||||||||||||
| add_constant(m, "EPSILON0", 8.8541878188e-12, _FARAD_PER_METER)?; | ||||||||||||||||||||||||
| add_constant( | ||||||||||||||||||||||||
| m, | ||||||||||||||||||||||||
| "KE", | ||||||||||||||||||||||||
| 1.0_f64 / (4.0_f64 * PI * 8.8541878188e-12), | ||||||||||||||||||||||||
| _METER_PER_FARAD, | ||||||||||||||||||||||||
| )?; | ||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
| add_constant(m, "HERTZ", 1.0, _HERTZ)?; | ||||||||||||||||||||||||
| add_constant(m, "NEWTON", 1.0, _NEWTON)?; | ||||||||||||||||||||||||
|
|
@@ -489,6 +528,7 @@ pub fn _core(m: &Bound<'_, PyModule>) -> PyResult<()> { | |||||||||||||||||||||||
| add_constant(m, "ANGSTROM", 1e-10, _METER)?; | ||||||||||||||||||||||||
| add_constant(m, "AMU", 1.6605390671738466e-27, _KILOGRAM)?; | ||||||||||||||||||||||||
| add_constant(m, "AU", 149597870700.0, _METER)?; | ||||||||||||||||||||||||
| add_constant(m, "ATM", 101325.0, _PASCAL)?; | ||||||||||||||||||||||||
| add_constant(m, "BAR", 1e5, _PASCAL)?; | ||||||||||||||||||||||||
| add_constant(m, "CALORIE", 4.184, _JOULE)?; | ||||||||||||||||||||||||
| m.add("CELSIUS", Celsius)?; | ||||||||||||||||||||||||
|
|
@@ -499,6 +539,7 @@ pub fn _core(m: &Bound<'_, PyModule>) -> PyResult<()> { | |||||||||||||||||||||||
| add_constant(m, "HOUR", 3600.0, _SECOND)?; | ||||||||||||||||||||||||
| add_constant(m, "LITER", 1e-3, _CUBIC_METER)?; | ||||||||||||||||||||||||
| add_constant(m, "MINUTE", 60.0, _SECOND)?; | ||||||||||||||||||||||||
| add_constant(m, "POISE", 0.1, _PASCAL_SECOND)?; | ||||||||||||||||||||||||
| m.add("RADIANS", Angle(1.0))?; | ||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
| add_constant(m, "G", 6.6743e-11, SIUnit([3, -1, -2, 0, 0, 0, 0]))?; | ||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -44,6 +44,8 @@ impl<Inner: fmt::Display> fmt::Display for Quantity<Inner, _Dimensionless> { | |
| #[cfg(feature = "pyo3")] | ||
| pub(crate) trait PrintUnit { | ||
| const UNIT: &'static str; | ||
|
|
||
| fn scale() -> f64; | ||
|
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. is this used anywhere? |
||
| } | ||
|
|
||
| macro_rules! impl_fmt { | ||
|
|
@@ -95,6 +97,10 @@ macro_rules! impl_fmt { | |
| #[cfg(feature = "python")] | ||
| impl<T> PrintUnit for Quantity<T, SIUnit<$t, $l, $m, $i, $theta, $n, 0>> { | ||
| const UNIT: &'static str = $symbol; | ||
|
|
||
| fn scale() -> f64 { | ||
| $unit.0 | ||
| } | ||
| } | ||
| }; | ||
| } | ||
|
|
||
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.
link to the PR, not the issue