-
Notifications
You must be signed in to change notification settings - Fork 113
New issue
Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? # to your account
How to get a parseable unit string #412
Comments
I put a lenient parser here. This uses an unregistered fork of Unitful, but should be easily adaptable. It's lenient with regards to space or no space between number and unit. |
...also lenient with regards to brackets. It's used for parsing output from proprietary applications with various formats.
|
Same question here! julia> u"angstrom^3"
ų
julia> uparse("ų")
ERROR: ArgumentError: Symbol ų could not be found in unit modules Module[Unitful]
Stacktrace:
[1] lookup_units(unitmods::Vector{Module}, sym::Symbol)
@ Unitful ~/.julia/packages/Unitful/1t88N/src/user.jl:581
[2] lookup_units
@ ~/.julia/packages/Unitful/1t88N/src/user.jl:593 [inlined]
[3] uparse(str::String; unit_context::Module)
@ Unitful ~/.julia/packages/Unitful/1t88N/src/user.jl:536
[4] uparse(str::String)
@ Unitful ~/.julia/packages/Unitful/1t88N/src/user.jl:535
[5] top-level scope
@ REPL[5]:1 This is not helpful when I want to serialize a quantity with units into a JSON or YAML file, then reconstruct it from that file later. |
Bump. Is there any update on this? I don't necessarily need a unit string that can be parsed by Julia. But I would like a unit string that can at least be parsed by E.g. currently none of these work: julia> a = Unitful.u"mg/dL/dL"
mg dL⁻²
julia> string(a)
"mg dL⁻²"
julia> Unitful.uparse(string(a))
ERROR: Base.Meta.ParseError("extra token \"dL⁻²\" after end of expression")
Stacktrace:
[1] #parse#3
@ ./meta.jl:227 [inlined]
[2] parse(str::String; raise::Bool, depwarn::Bool)
@ Base.Meta ./meta.jl:258
[3] parse
@ ./meta.jl:258 [inlined]
[4] uparse(str::String; unit_context::Module)
@ Unitful ~/.julia/packages/Unitful/PcVKX/src/user.jl:535
[5] uparse(str::String)
@ Unitful ~/.julia/packages/Unitful/PcVKX/src/user.jl:535
[6] top-level scope
@ REPL[6]:1
julia> b = Unitful.mg / Unitful.dL / Unitful.dL
mg dL⁻²
julia> a === b
true
julia> string(b)
"mg dL⁻²"
julia> Unitful.uparse(string(b))
ERROR: Base.Meta.ParseError("extra token \"dL⁻²\" after end of expression")
Stacktrace:
[1] #parse#3
@ ./meta.jl:227 [inlined]
[2] parse(str::String; raise::Bool, depwarn::Bool)
@ Base.Meta ./meta.jl:258
[3] parse
@ ./meta.jl:258 [inlined]
[4] uparse(str::String; unit_context::Module)
@ Unitful ~/.julia/packages/Unitful/PcVKX/src/user.jl:535
[5] uparse(str::String)
@ Unitful ~/.julia/packages/Unitful/PcVKX/src/user.jl:535
[6] top-level scope
@ REPL[10]:1
julia> repr(a)
"mg dL⁻²"
julia> repr(b)
"mg dL⁻²"
julia> Unitful.uparse(repr(a))
ERROR: Base.Meta.ParseError("extra token \"dL⁻²\" after end of expression")
Stacktrace:
[1] #parse#3
@ ./meta.jl:227 [inlined]
[2] parse(str::String; raise::Bool, depwarn::Bool)
@ Base.Meta ./meta.jl:258
[3] parse
@ ./meta.jl:258 [inlined]
[4] uparse(str::String; unit_context::Module)
@ Unitful ~/.julia/packages/Unitful/PcVKX/src/user.jl:535
[5] uparse(str::String)
@ Unitful ~/.julia/packages/Unitful/PcVKX/src/user.jl:535
[6] top-level scope
@ REPL[13]:1
julia> Unitful.uparse(repr(b))
ERROR: Base.Meta.ParseError("extra token \"dL⁻²\" after end of expression")
Stacktrace:
[1] #parse#3
@ ./meta.jl:227 [inlined]
[2] parse(str::String; raise::Bool, depwarn::Bool)
@ Base.Meta ./meta.jl:258
[3] parse
@ ./meta.jl:258 [inlined]
[4] uparse(str::String; unit_context::Module)
@ Unitful ~/.julia/packages/Unitful/PcVKX/src/user.jl:535
[5] uparse(str::String)
@ Unitful ~/.julia/packages/Unitful/PcVKX/src/user.jl:535
[6] top-level scope
@ REPL[14]:1 |
I don’t think this is easily possible right now, since there is no way to recover the symbol that a unit is bound to just from its value. For example, in UnitfulAtomic.jl there is a unit |
One way would be to provide a utility function that converts a unit to a parseable unit string, something like "parseableString(vunit)" |
Any news here? To repeat the most important information: My current bad implementation is
|
One way would be to return a string of the actual representation of the unit: julia> str = parseable(u"km^2") # this function does not exist yet
"FreeUnits{(Unit{:Meter, Dimensions{(Dimension{:Length}(1),)}()}(3, 2),), Dimensions{(Dimension{:Length}(2),)}(), nothing}()"
julia> Unitful.eval(Meta.parse(str))
km^2
julia> ans === u"km^2"
true Right now, parsing such a string does work with julia> uparse(str)
ERROR: ArgumentError: FreeUnits{(Unit{:Meter, Dimensions{(Dimension{:Length}(1),)}()}(3, 2),), Dimensions{(Dimension{:Length}(2),)}(), nothing} is not a valid function call when parsing a unit.
Only the following functions are allowed: [:*, :/, :^, :sqrt, :√, :+, :-, ://] |
It seems that only I am currently trying to create a package called UnitfulParsabelString.jl, which will allow me to add a parsable string without breaking Unitful by defining julia> using Unitful, UnitfulParsableString # <- my package
julia> a = u"mg/dL/dL"
mg dL⁻²
julia> string(a)
"mg*dL^-2"
julia> string(a) |> uparse
mg dL⁻²
julia> b = u"angstrom^3"
ų
julia> string(b)
"Å^3"
julia> string(b) |> uparse
ų
julia> c = 1.0u"m*kg/s^2"
1.0 kg m s⁻²
julia> string(c)
"1.0(kg*m*s^-2)"
julia> string(c) |> uparse
1.0 kg m s⁻² Is there a demand for this package? |
This problem may be solved by specifying the function uparse(str; unit_context=Unitful)
ex = Meta.parse(str)
eval(lookup_units(unit_context, ex))
end |
Yes, there is a demand for such a package (e.g. whenever something needs to be stored on file in a standardized format such as JSON). So, I highly appreciate if you can provide such a package (it would be even better, if it would be part of Unitful.jl). All your examples looks good. I am just a bit surprised for:
that this can be parsed with uparse. I checked, and indeed this works with Unitful.jl. |
@MartinOtter You have encouraged me to complete the package to the point where I am satisfied with it. (@v1.8) pkg > add https://github.com/michikawa07/UnitfulParsableString.jl |
I have the following problem:
The reason is that string(unit(v)) returns a string that cannot be parsed. In Julia this seems to be an unusual behavior because string(something) typically returns a string representation of something that can be again parsed by Julia.
I searched extensively in Unitful documentation and the Issues but did not find a solution.
I currently use a bad hack (that most likely does not work in all situations), by replacing " " by "*":
Help is appreciated
The text was updated successfully, but these errors were encountered: