Skip to content

Conversation

@icweaver
Copy link
Contributor

@icweaver icweaver commented May 31, 2025

Closes #166

To-do

@icweaver icweaver changed the title Additional QuantityArray constructions Additional QuantityArray constructions May 31, 2025
@icweaver icweaver marked this pull request as draft May 31, 2025 00:08
@github-actions
Copy link
Contributor

github-actions bot commented May 31, 2025

Benchmark Results (Julia v1.10)

Time benchmarks
main 22767a5... main / 22767a5...
Quantity/creation/Quantity(x) 3.1 ± 0.01 ns 4.02 ± 0.011 ns 0.771 ± 0.0033
Quantity/creation/Quantity(x, length=y) 3.11 ± 0.001 ns 3.11 ± 0.01 ns 1 ± 0.0032
Quantity/with_numbers/*real 3.11 ± 0.01 ns 3.11 ± 0.001 ns 1 ± 0.0032
Quantity/with_numbers/^int 8.67 ± 2.5 ns 8.67 ± 2.5 ns 1 ± 0.4
Quantity/with_numbers/^int * real 8.37 ± 2.2 ns 8.37 ± 2.2 ns 1 ± 0.37
Quantity/with_quantity/+y 4.04 ± 0.001 ns 4.04 ± 0.01 ns 1 ± 0.0025
Quantity/with_quantity//y 3.42 ± 0.01 ns 3.42 ± 0.011 ns 1 ± 0.0044
Quantity/with_self/dimension 3.1 ± 0.01 ns 3.1 ± 0.01 ns 0.997 ± 0.0045
Quantity/with_self/inv 3.42 ± 0.01 ns 3.41 ± 0.011 ns 1 ± 0.0044
Quantity/with_self/ustrip 3.11 ± 0.01 ns 3.1 ± 0.01 ns 1 ± 0.0046
QuantityArray/broadcasting/multi_array_of_quantities 0.147 ± 0.0027 ms 0.146 ± 0.0011 ms 1 ± 0.02
QuantityArray/broadcasting/multi_normal_array 0.0559 ± 0.003 ms 0.0558 ± 0.0031 ms 1 ± 0.078
QuantityArray/broadcasting/multi_quantity_array 0.157 ± 0.00084 ms 0.157 ± 0.00085 ms 1 ± 0.0077
QuantityArray/broadcasting/x^2_array_of_quantities 24.5 ± 2.1 μs 26.4 ± 2.6 μs 0.928 ± 0.12
QuantityArray/broadcasting/x^2_normal_array 4.43 ± 0.69 μs 5.25 ± 0.7 μs 0.844 ± 0.17
QuantityArray/broadcasting/x^2_quantity_array 7.04 ± 0.26 μs 6.95 ± 0.27 μs 1.01 ± 0.054
QuantityArray/broadcasting/x^4_array_of_quantities 0.0817 ± 0.00062 ms 0.0817 ± 0.001 ms 1 ± 0.014
QuantityArray/broadcasting/x^4_normal_array 0.0498 ± 0.00019 ms 0.0499 ± 0.00019 ms 0.999 ± 0.0054
QuantityArray/broadcasting/x^4_quantity_array 0.05 ± 0.00019 ms 0.0499 ± 0.00018 ms 1 ± 0.0053
time_to_load 0.186 ± 0.00057 s 0.205 ± 0.0021 s 0.906 ± 0.0096
Memory benchmarks
main 22767a5... main / 22767a5...
Quantity/creation/Quantity(x) 0 allocs: 0 B 0 allocs: 0 B
Quantity/creation/Quantity(x, length=y) 0 allocs: 0 B 0 allocs: 0 B
Quantity/with_numbers/*real 0 allocs: 0 B 0 allocs: 0 B
Quantity/with_numbers/^int 0 allocs: 0 B 0 allocs: 0 B
Quantity/with_numbers/^int * real 0 allocs: 0 B 0 allocs: 0 B
Quantity/with_quantity/+y 0 allocs: 0 B 0 allocs: 0 B
Quantity/with_quantity//y 0 allocs: 0 B 0 allocs: 0 B
Quantity/with_self/dimension 0 allocs: 0 B 0 allocs: 0 B
Quantity/with_self/inv 0 allocs: 0 B 0 allocs: 0 B
Quantity/with_self/ustrip 0 allocs: 0 B 0 allocs: 0 B
QuantityArray/broadcasting/multi_array_of_quantities 2 allocs: 0.382 MB 2 allocs: 0.382 MB 1
QuantityArray/broadcasting/multi_normal_array 2 allocs: 0.0763 MB 2 allocs: 0.0763 MB 1
QuantityArray/broadcasting/multi_quantity_array 2 allocs: 0.0763 MB 2 allocs: 0.0763 MB 1
QuantityArray/broadcasting/x^2_array_of_quantities 2 allocs: 0.382 MB 2 allocs: 0.382 MB 1
QuantityArray/broadcasting/x^2_normal_array 2 allocs: 0.0763 MB 2 allocs: 0.0763 MB 1
QuantityArray/broadcasting/x^2_quantity_array 2 allocs: 0.0763 MB 2 allocs: 0.0763 MB 1
QuantityArray/broadcasting/x^4_array_of_quantities 2 allocs: 0.382 MB 2 allocs: 0.382 MB 1
QuantityArray/broadcasting/x^4_normal_array 2 allocs: 0.0763 MB 2 allocs: 0.0763 MB 1
QuantityArray/broadcasting/x^4_quantity_array 2 allocs: 0.0763 MB 2 allocs: 0.0763 MB 1
time_to_load 0.153 k allocs: 14.5 kB 0.153 k allocs: 14.5 kB 1

@github-actions
Copy link
Contributor

github-actions bot commented May 31, 2025

Benchmark Results (Julia v1)

Time benchmarks
main 22767a5... main / 22767a5...
Quantity/creation/Quantity(x) 3.1 ± 0.01 ns 2.79 ± 0.001 ns 1.11 ± 0.0036
Quantity/creation/Quantity(x, length=y) 3.73 ± 0.009 ns 3.43 ± 0.011 ns 1.09 ± 0.0044
Quantity/with_numbers/*real 3.1 ± 0.01 ns 3.41 ± 0.01 ns 0.911 ± 0.004
Quantity/with_numbers/^int 8.98 ± 2.2 ns 8.98 ± 2.2 ns 1 ± 0.34
Quantity/with_numbers/^int * real 9.29 ± 2.2 ns 9.29 ± 2.2 ns 1 ± 0.33
Quantity/with_quantity/+y 4.35 ± 0.01 ns 4.04 ± 0.001 ns 1.08 ± 0.0025
Quantity/with_quantity//y 3.42 ± 0.01 ns 3.11 ± 0.001 ns 1.1 ± 0.0032
Quantity/with_self/dimension 2.79 ± 0.01 ns 3.1 ± 0.01 ns 0.903 ± 0.0044
Quantity/with_self/inv 3.11 ± 0.01 ns 3.41 ± 0.01 ns 0.912 ± 0.004
Quantity/with_self/ustrip 2.79 ± 0.01 ns 2.79 ± 0.01 ns 1 ± 0.0051
QuantityArray/broadcasting/multi_array_of_quantities 0.0904 ± 0.0012 ms 0.0906 ± 0.0013 ms 0.999 ± 0.019
QuantityArray/broadcasting/multi_normal_array 0.0498 ± 0.00029 ms 0.0499 ± 0.00034 ms 0.999 ± 0.009
QuantityArray/broadcasting/multi_quantity_array 0.0591 ± 0.0062 ms 0.0622 ± 0.0032 ms 0.95 ± 0.11
QuantityArray/broadcasting/x^2_array_of_quantities 15.4 ± 8 μs 18 ± 9.9 μs 0.856 ± 0.65
QuantityArray/broadcasting/x^2_normal_array 3.32 ± 3.2 μs 3.46 ± 2.9 μs 0.959 ± 1.2
QuantityArray/broadcasting/x^2_quantity_array 3.57 ± 0.34 μs 3.91 ± 1.1 μs 0.913 ± 0.27
QuantityArray/broadcasting/x^4_array_of_quantities 0.0843 ± 0.00097 ms 0.0876 ± 0.0013 ms 0.963 ± 0.018
QuantityArray/broadcasting/x^4_normal_array 0.0466 ± 0.00019 ms 0.0498 ± 0.00025 ms 0.938 ± 0.0061
QuantityArray/broadcasting/x^4_quantity_array 0.0499 ± 0.00018 ms 0.0499 ± 0.00023 ms 0.999 ± 0.0059
time_to_load 0.205 ± 0.0035 s 0.237 ± 0.0064 s 0.865 ± 0.027
Memory benchmarks
main 22767a5... main / 22767a5...
Quantity/creation/Quantity(x) 0 allocs: 0 B 0 allocs: 0 B
Quantity/creation/Quantity(x, length=y) 0 allocs: 0 B 0 allocs: 0 B
Quantity/with_numbers/*real 0 allocs: 0 B 0 allocs: 0 B
Quantity/with_numbers/^int 0 allocs: 0 B 0 allocs: 0 B
Quantity/with_numbers/^int * real 0 allocs: 0 B 0 allocs: 0 B
Quantity/with_quantity/+y 0 allocs: 0 B 0 allocs: 0 B
Quantity/with_quantity//y 0 allocs: 0 B 0 allocs: 0 B
Quantity/with_self/dimension 0 allocs: 0 B 0 allocs: 0 B
Quantity/with_self/inv 0 allocs: 0 B 0 allocs: 0 B
Quantity/with_self/ustrip 0 allocs: 0 B 0 allocs: 0 B
QuantityArray/broadcasting/multi_array_of_quantities 3 allocs: 0.382 MB 3 allocs: 0.382 MB 1
QuantityArray/broadcasting/multi_normal_array 3 allocs: 0.0764 MB 3 allocs: 0.0764 MB 1
QuantityArray/broadcasting/multi_quantity_array 3 allocs: 0.0764 MB 3 allocs: 0.0764 MB 1
QuantityArray/broadcasting/x^2_array_of_quantities 3 allocs: 0.382 MB 3 allocs: 0.382 MB 1
QuantityArray/broadcasting/x^2_normal_array 3 allocs: 0.0764 MB 3 allocs: 0.0764 MB 1
QuantityArray/broadcasting/x^2_quantity_array 3 allocs: 0.0764 MB 3 allocs: 0.0764 MB 1
QuantityArray/broadcasting/x^4_array_of_quantities 3 allocs: 0.382 MB 3 allocs: 0.382 MB 1
QuantityArray/broadcasting/x^4_normal_array 3 allocs: 0.0764 MB 3 allocs: 0.0764 MB 1
QuantityArray/broadcasting/x^4_quantity_array 3 allocs: 0.0764 MB 3 allocs: 0.0764 MB 1
time_to_load 0.159 k allocs: 11.2 kB 0.159 k allocs: 11.2 kB 1

@icweaver icweaver marked this pull request as ready for review June 3, 2025 20:36
@icweaver
Copy link
Contributor Author

icweaver commented Jun 3, 2025

Hi @MilesCranmer, this PR should be ready for your review now. Two follow-up questions I had were:

  1. Do we also want to add methods for creating QuantityArrays from generators? I just went with the types defined in ABSTRACT_QUANTITY_TYPES for now https://github.com/SymbolicML/DynamicQuantities.jl/blob/fe78d12e69e98a1d9e7a0b2eeb060558afc62cad/src/types.jl#L212-L216
  2. Did you also want the assorted examples docs for QuantityArray updated, or would you prefer just keeping the explicit QuantityArray(<blah>) constructions there as-is?

@icweaver
Copy link
Contributor Author

icweaver commented Jul 10, 2025

Sweet, looks like this is working nicely with the new Makie PR:

julia> using CairoMakie, DynamicQuantities

julia> x = [6, 7, 8]us"cm"
3-element QuantityArray(::Vector{Float64}, ::Quantity{Float64, SymbolicDimensions{FixedRational{Int32, 25200}}}):
 6.0 cm
 7.0 cm
 8.0 cm

julia> y = (4:6)u"kg"
3-element QuantityArray(::StepRangeLen{Float64, Base.TwicePrecision{Float64}, Base.TwicePrecision{Float64}, Int64}, ::Quantity{Float64, Dimensions{FixedRational{Int32, 25200}}}):
 4.0 kg
 5.0 kg
 6.0 kg

julia> scatter(x, y)
display

@icweaver
Copy link
Contributor Author

  1. Did you also want the assorted examples docs for QuantityArray updated, or would you prefer just keeping the explicit QuantityArray() constructions there as-is?

Actually, think I found a good balance, just pushed. Does this look alright to you?

Copy link
Member

@MilesCranmer MilesCranmer left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good! Thanks for this and sorry for the delay. I only had a couple requests

@MilesCranmer
Copy link
Member

Also re: your question, I think creating from generators is probably too much for now.

@icweaver
Copy link
Contributor Author

Thanks Miles! Sorry for the mix-up with the README and generated index file; I think things have been straightened out now.

In the process, I think I noticed that the HTML table of contents does not work as intended on my end at least, I think due to the case-sensitivity of the section headers. I'd be happy to open up a separate PR for this and maybe exploring the preprocessing step you mentioned for README code blocks if you think that would be useful

@MilesCranmer
Copy link
Member

Sure! Sounds great, thanks

@codecov
Copy link

codecov bot commented Jul 15, 2025

Codecov Report

Attention: Patch coverage is 66.66667% with 1 line in your changes missing coverage. Please review.

Project coverage is 95.62%. Comparing base (b209b7c) to head (12b20d2).

Files with missing lines Patch % Lines
src/math.jl 66.66% 1 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main     #178      +/-   ##
==========================================
- Coverage   99.21%   95.62%   -3.60%     
==========================================
  Files          21       20       -1     
  Lines        1273     1211      -62     
==========================================
- Hits         1263     1158     -105     
- Misses         10       53      +43     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@icweaver icweaver changed the title Additional QuantityArray constructions Additional QuantityArray constructions [OLD] Aug 30, 2025
@icweaver icweaver changed the title Additional QuantityArray constructions [OLD] Additional QuantityArray constructions Aug 30, 2025
@icweaver
Copy link
Contributor Author

icweaver commented Sep 1, 2025

Hi Miles, sorry for the delay on this. I think test coverage should be up now and things should be ready for another review

Comment on lines 367 to 393
By default, DynamicQuantities will create a `QuantityArray` from an `AbstractArray`, similarly to how a `Quantity` is created from a scalar in the [Usage](@ref) examples:

```julia
julia> x = [0.3, 0.4, 0.5]u"km/s"
3-element QuantityArray(::Vector{Float64}, ::Quantity{Float64, Dimensions{FixedRational{Int32, 25200}}}):
300.0 m s⁻¹
400.0 m s⁻¹
500.0 m s⁻¹

julia> y = (42:45) * u"kg"
4-element QuantityArray(::StepRangeLen{Float64, Base.TwicePrecision{Float64}, Base.TwicePrecision{Float64}, Int64}, ::Quantity{Float64, Dimensions{FixedRational{Int32, 25200}}}):
42.0 kg
43.0 kg
44.0 kg
45.0 kg
```

This can be overridden to produce a vector of `Quantity`s by explicitly broadcasting the unit:

```julia
julia> z = [0.3, 0.4, 0.5] .* u"km/s"
3-element Vector{Quantity{Float64, Dimensions{FixedRational{Int32, 25200}}}}:
300.0 m s⁻¹
400.0 m s⁻¹
500.0 m s⁻¹
```

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Likely don't need 3 separate examples. I think just the first example is good. The rest can be deleted; users can figure it out by playing around (it's fairly intuitive I think

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok, dropped the last two examples 3c97dab

@MilesCranmer
Copy link
Member

Rest is looking ok. One tricky thing is that I think this might be a breaking change (??). I'm not sure what to do with that in mind.

# Test multiplying ranges with units
x = (1:0.25:4)u"inch"
@test x isa StepRangeLen
@test x isa T_QA_StepRangeLen
Copy link
Member

@MilesCranmer MilesCranmer Sep 1, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
@test x isa T_QA_StepRangeLen
@test x isa QuantityArray
@test DQ.array_type(x) <: StepRangeLen
@test DQ.dim_type(x) <: Dimensions

bit more readable like this.

Same comment for other T_QA_AbstractArray types - we can swap them for using the interface to inspect the type parameters

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok, will swap these out. Sorry, by using the interface to inspect type parameters, is there something else that you would like to see instead?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@icweaver
Copy link
Contributor Author

icweaver commented Sep 1, 2025

#178 (comment)

Sure! Sounds great, thanks

For sure, just opened #188

@MilesCranmer
Copy link
Member

MilesCranmer commented Sep 11, 2025

Thanks for sticking with this and putting up with my many suggestions!! I made a couple minor changes.

However, I did notice one issue before merging:

julia> x = randn(3) .* u"km/s"
3-element Vector{Quantity{Float64, Dimensions{FixedRational{Int32, 25200}}}}:
 1124.2145905299506 m s⁻¹
 -451.8046249866915 m s⁻¹
 1332.2748352376054 m s⁻¹

julia> x * u"km"
3-element QuantityArray(::Vector{Quantity{Float64, Dimensions{FixedRational{Int32, 25200}}}}, ::Quantity{Quantity{Float64, Dimensions{FixedRational{Int32, 25200}}}, Dimensions{FixedRational{Int32, 25200}}}):
 (1.1242145905299506e6 m s⁻¹) m
   (-451804.6249866915 m s⁻¹) m
 (1.3322748352376055e6 m s⁻¹) m

In other words it seems like if you multiply a vector of quantities with a quantity, it becomes a quantity array containing internally a vector of quantities.

Is this intentional or should this be handled somehow? Seems kinda tricky because certain things like Measurement{T} or Complex{T} might internally wrap a quantity... In which case I don't know how this could generically handle such things

@MilesCranmer
Copy link
Member

Fixed

@MilesCranmer
Copy link
Member

Hm... the load time is increased by over 10%. Not sure why.

@MilesCranmer
Copy link
Member

Ok the load time seems related to the many methods defined for different array types in the LinearAlgebra extension. It's still the case that LinearAlgebra is loaded automatically in Julia, so the extension doesn't really function as a dynamically loaded set of methods yet.

Basically it just means this is something to fix later. But it's a high priority fix as the load time is painfully high for DQ (although it's still not near as bad as Unitful)

@MilesCranmer MilesCranmer merged commit 13fbf02 into JuliaPhysics:main Sep 13, 2025
6 of 7 checks passed
@MilesCranmer
Copy link
Member

Thanks again!

@icweaver
Copy link
Contributor Author

Ah, interesting. Thanks for walking me through this PR, Miles; it taught me a lot!

@icweaver icweaver deleted the quantityarray-construction branch September 13, 2025 17:25
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

QuantityArray convenience

2 participants