Open pospi opened 1 year ago
I don't think VF should care, seems to me that retrieval by whatever is cleanest should be done, and really whatever people prefer. And noting that id's will be different things in different technical ecosystems, although there should be a unique URL id for each unit in OM2.
I don't think all the units in OM2 have symbols, you'll probably have to substitute whatever seems best.
Hrmm, there may be some additions or revisions needed for the GraphQL Unit
API here.
Problem 1: equivalence
There currently cannot be any guarantee of equivalence or availability of different Units
in different networks, since they are just records. This seems advisable / unavoidable since every collaboration space has different needs and (for example) a coffee shop baking cakes probably will never need to measure light-seconds or megatons.
However this does also mean that we cannot know that an 'hours' Unit
created in one network is actually the same unit of measure as 'hours' created elsewhere.
Problem 2: grammar standardisation
there should be a unique URL id for each unit in OM2
This is currently the case per network but presents an issue with associating units back to OM. To avoid falsely indicating equivalence between units and to enable referential integrity checks against the zome, unit IDs are returned as universally-unique strings which include the DnaHash
. In this way, an 'hours' created in one space is automatically different to an 'hours' created elsewhere, and the correct associations must be made by the application when storing other referencing records. The IDs themselves are meaningless.
I was going to currently specify associations to OM2 by Unit.label
, for example { label: "http://www.ontology-of-units-of-measure.org/resource/om-2/hour", symbol: "h" }
. But at best that seems like an awkward workaround.
By providing such associations to external vocabs we would be able to solve equivalence since two different 'hour's can be said to be equivalent if they both correspond to http://www.ontology-of-units-of-measure.org/resource/om-2/hour.
Question 1: how to associate units with OM2?
Should we have a better way of making this association? Some field on Unit
that behaves like classifiedAs
in other record types?
Question 2: how to load selections of available units in applications?
App developers are likely to want to be able to perform logic such as, "Does the 'hours' Unit
exist? If not, create it."
This PR was an attempt to facilitate that by allowing units to be queried directly by symbol (hopefully the unique part of a unit) for retrieval, without modifying the GraphQL spec. However maybe it's not the best approach.
Better may be adding filter
parameters to the root-level units()
query, where filters may include symbol
. "Does the 'hours' Unit
exist?" would then be achievable via query { units(filter: { symbol: ['hours'] }) { ... } }
.
Further work may involve integration of the OM ontology more directly into applications. For example, we might want to deny creating custom units with any OM symbol
assigned; which would be a way of ensuring that any 'hours' in any network corresponds to http://www.ontology-of-units-of-measure.org/resource/om-2/hour.
Either this kind of validation, or we could add a filter parameter for classifiedAs
when implemented, which enables more exacting queries. "Does the 'hours' Unit
exist?" would become "Does the 'hours' Unit
from the OM ontology exist?".
Question 1: how to associate units with OM2?
I wonder if we (meaning you of course :) in the graphql ) could add a field to Unit just for the OM2 url? Use label for the actual short label. Maybe also VF itself could put a recommendation for that into one of those kinds of sections, especially once it is tried.
Question 2: how to load selections of available units in applications?
This is a hard one. And yes, different networks will want different sets of units. I have always pictured some kind of utility for populating OM2 units into a DNA/DHT, where any network who needs units for whatever reason could pick out what they want from some big query-able list. What you are suggesting also makes sense because they will run into needing new ones as they work.
Just making sure you know about these references:
Thanks for that second link, it was worth taking the time to look through the exported definitions. Not all units having a symbol
requires some dealing with, since the symbol
is currently configured as the element's (unique) index.
What do you think of this, as an example of inserting core time-based units?
const timeUnits = {
hours: {
label: 'hour',
symbol: 'h',
description: 'The hour is a unit of time defined as 3600 second.',
classifiedAs: ['http://www.ontology-of-units-of-measure.org/resource/om-2/hour'],
},
minutes: {
label: 'minute',
symbol: 'min',
description: 'The minute (time) is a unit of time defined as 60 second.',
classifiedAs: ['http://www.ontology-of-units-of-measure.org/resource/om-2/minute-Time'],
},
seconds: {
label: 'second',
symbol: 's',
description: 'The second is a unit of time defined as the duration of 9 192 631 770 periods of the radiation corresponding to the transition between the two hyperfine levels of the ground state of the cesium 133 atom.',
classifiedAs: ['http://www.ontology-of-units-of-measure.org/resource/om-2/second-Time'],
},
}
I think the best thing to do in terms of indexing might actually be to re-key on label
since that fields appears to be unique for every unit.
Could also consider ommitting description
, changing classifiedAs: [URI!]
to definedAs: URI
(or whatever other core semantic meaning for this, there is probably something in the rdf vocab itself). But the point is from 1:many to 1:1 and we would setup a unique index on that field; whilst allowing both label and symbol to be non-unique.
I want to point out that there's a lot more to the OM2 model than any of us have referenced in the code (and more than I've actually seen documented anywhere).
Each unit has a well known key as its ID such as om:kilometrePerHour
. That means this value forms a natural key for the unit being used.
Each unit has a mapping to the UCUM ontology defined in https://github.com/HajoRijgersberg/OM/blob/master/om-2-ucum.ttl.
There is the first most straightforward hierarchy of 161 objects that subclass om:Unit
:
om:Unit
om:PrefixedUnit
om:hasPrefix
and om:hasUnit
om:UnitMultiple
om:SingularUnit
om:hasFactor
and om:hasUnit
om:CompoundUnit
om:UnitMultiplication
om:hasTerm1
and om:hasTerm2
(but this seems hypothetical, since nothing in the spec uses this in its definition).om:UnitExponentiation
om:hasBase
and om:hasExponent
om:UnitDivision
om:hasNumerator
and om:hasDenominator
One possible traversal down this chain of subclassing looks like:
Mathematical relationships can be defined between om:SingularUnit
s. For instance, om:degree
has a reference definition of 1.745329e-2 radians:
<!-- hasDefinition --> <om:hasFactor rdf:datatype="&xsd;float">1.745329e-2</om:hasFactor>
<!-- hasDefinition --> <om:hasUnit rdf:resource="&om;radian"/>
<om:hasDimension rdf:resource="&om;dimensionOne"/>
The spec defines a hierarchy of prefixes:
om:Prefix
om:SIPrefix
om:hasFactor
values.There is enough information to use a symbolic system to perform dimensional analysis and convert between units based on the dimensions of each measurement used in a calculation in order to normalize the results.
This does exempt the units starting at om:barFood
through om:wineGlass
. These units have no conversion factors or relationships to any other unit. However, if the particular network wanted to have specific conversion factors for these sorts of things, there's nothing stopping them from doing that, other than it should probably be another layer that stores that besides modifying the units directly.
The spec defines 24 om:ApplicationArea
s which each form a hierarchy of grouping of units and their hierarchies above. For instance, let's look at a path through to the om:geometry
hierarchy:
om:geometry
references om:length
om:length
's definition pulls in all units from the om:LengthUnit
collections:om:LengthUnit
om:metre
om:lengthOfThePathTravelledByLightInVacuumDuringATimeIntervalOf1299792458OfASecond
.om:FontLengthUnit
There are groupings of 76 different om:Dimension
s, such as [om:lengthDimension
](https://github.com/HajoRijgersberg/OM/blob/master/om-2.0.rdf#L4729].
This means there's enough data in the ontology to both allow narrowing down and selecting units based on application area and dimension type.
My suggestion would be to have some configuration mechanism of configuring which units are used by the particular organizations/groups/agents. We could also allow aliases for all units and conversions for the unit-less units (eg. om:barFood
). That way we could probably still look up the units by their canonical OM2 URI fragment instead of having random names for everything in every group.
It's funny, OM2 seems to have everything but the om:kitchenSink
.
Maybe I left this comment in the wrong place, so referencing it here. Sorry for any confusion over many issues in different places.
Could also consider ommitting description, changing classifiedAs: [URI!] to definedAs: URI (or whatever other core semantic meaning for this, there is probably something in the rdf vocab itself). But the point is from 1:many to 1:1 and we would setup a unique index on that field; whilst allowing both label and symbol to be non-unique.
Something like that makes sense to me. Suggest:
hour: {
label: 'hour',
symbol: 'h',
comment: 'The hour is a unit of time defined as 3600 second.',
definedAs: 'http://www.ontology-of-units-of-measure.org/resource/om-2/hour',
}
I like having the description handy (maybe useful for mouse-overs), although in OM2 it looks like they use rdfs:comment
, and seems like we should use their terms. (I thought I saw definition
there, but that isn't in their rawgit version.) I like definedAs
better than classifiedAs
, since it is more creating a cross reference than a classification. I made definedAs
not be a list, agree with your suggestion.
I'm not sure how you might feel about this addition; but it seems like a necessary bit of ergonomics for hREA-based apps.
I want to be able to declare this as a data dependency in my view component(s):
The key parameter is the
id
in each query. The only way of interacting currently is to pass the values directly; i.e. the universally-unique combination of(DnaHash, String)
, which necessitates query variables:Where would
dnaHashB64
come from? This seems like an implementation detail of the Valueflows network, which client applications should not have to interact with at all. So, we should be able to refer to units by well-known strings for simplified retrieval. I think with this addition to the top-level query we can take the wrappedUnitIds
from this request and link to other records as needed in mutations.