-
-
Notifications
You must be signed in to change notification settings - Fork 97
User Guide for QUDT
This guide attempts to explain how the QUDT model should be used.
3. Introducing Dimension Vectors (for SI units)
4. Conversion Multipliers in QUDT
6. The same dimension vector does not guarantee commensurability
7. Special case of Quantity Kind with no Dimension Vector
8. A Quantity with multiple units
Please refer to the following architecture diagram for the key QUDT classes (the QUDT architecture overview can be read here.
Let's suppose you have a smart thermostat and it generates a digital signal for the temperature setting in degrees Fahrenheit. You could name the QUDT Quantity something like wiki-examples:MyThermostatSetting. The Quantity instance is yours - you can name it whatever you want, but in a professional/interoperability scenario the name might include other information, such as the location of the thermostat. One way or another, the name establishes the context of the value you are storing. For the simple case, the Quantity instance has a property qudt:value, which you could assign the value 72.0. The Quantity instance also points to an instance of qudt:Unit called unit:DEG_F.
Here's the Turtle source code for this:
wiki-examples:MyThermostatSetting
rdf:type qudt:Quantity ;
qudt:hasUnit unit:DEG_F ;
qudt:value "72.0"^^xsd:float ;
.
Here's how it fits into the QUDT model. (Orange is your new instance, blue is defined by QUDT).
The next important concept to understand is the QuantityKind. Simply stated, a QuantityKind is just that: a kind, and answers the question "What is this measurement and unit a measure of?". Answers might be things like "Thermodynamic Temperature" (i.e. quantitykind:ThermodynamicTemperature). So the QuantityKind vocabulary is a set of all the kinds of things we might measure... length, area, electrical capacitance, torque, and really obscure ones like power per area quartic temperature. This last one is measured in units of Watts Per Square Meter Per Quartic Kelvin by the way.
Every Unit is associated with at least one QuantityKind - sometimes more than one if there are different ways people refer to a QuantityKind, but usually just one. (This is actually a simplification of the more complex topic of commensurability, discussed here, but suffices for this introduction). You don't need to populate the association between a Unit and a QuantityKind, it is already populated. For example, the following SPARQL query produces 2 quantity kinds associated with the unit unit:A-PER-MilliM:
SELECT ?un ?qk
WHERE {
BIND (unit:A-PER-MilliM AS ?un) .
?un qudt:hasQuantityKind ?qk
}
which produces the following:
un qk
unit:A-PER-MilliM quantitykind:LinearElectricCurrentDensity
unit:A-PER-MilliM quantitykind:MagneticFieldStrength
Of course, each QuantityKind could be measured in any of several units, such as different units for temperature, or different units for length. For example, the following SPARQL query shows the different units associated with the quantity kind quantitykind:Force: (Try it here)
SELECT DISTINCT ?qk ?qku (COALESCE(?labelEn, ?qkl) AS ?label)
WHERE {
BIND (quantitykind:Force AS ?arg1) .
?qk rdf:type qudt:QuantityKind .
FILTER (?qk = ?arg1) .
?qku qudt:hasQuantityKind ?qk .
?qku a qudt:Unit .
?qku rdfs:label ?qkl .
OPTIONAL {
?qku rdfs:label ?labelEn .
FILTER (lang(?labelEn) = "en")
}
} ORDER BY ?qku
which results in 23 values for ?qku:
qk qku label
qudtqk:Force unit:CentiN CentiNewton
qudtqk:Force unit:DYN Dyne
qudtqk:Force unit:DeciN DeciNewton
qudtqk:Force unit:GM_F Gram Force
qudtqk:Force unit:GigaN GigaN
qudtqk:Force unit:KIP_F Kip
qudtqk:Force unit:KiloGM-M-PER-SEC2 kilogram metre per second squared
qudtqk:Force unit:KiloGM_F Kilogram Force
qudtqk:Force unit:KiloLB_F KiloPound Force
qudtqk:Force unit:KiloN Kilonewton
qudtqk:Force unit:KiloPOND Kilopond
qudtqk:Force unit:LB_F Pound Force
qudtqk:Force unit:MegaLB_F Mega Pound Force
qudtqk:Force unit:MegaN Meganewton
qudtqk:Force unit:MicroN Micronewton
qudtqk:Force unit:MilliN Millinewton
qudtqk:Force unit:N newton
qudtqk:Force unit:NanoN NanoN
qudtqk:Force unit:OZ_F Imperial Ounce Force
qudtqk:Force unit:PDL Poundal
qudtqk:Force unit:POND pond
qudtqk:Force unit:PlanckForce Planck Force
qudtqk:Force unit:TON_F_US Ton Force (US Short)
Here is where the power of the QUDT ontology starts to reveal itself. In the SI system of units, all physical measurements can be described in terms of 7 basic dimensions, and the associated base units:
- Amount of substance - mole (mole)
- Electric current - ampere (A)
- Length - meter (m)
- Luminous intensity - candela (cd)
- Mass - kilogram (kg)
- Temperature - kelvin (K)
- Time - second (s)
(Note that the choice of what the basic dimensions are could have been different. The SI community could have chosen Electric charge instead of Electric current, for example, in which case the Coulomb would have been the base unit for SI. This is important, because there are other systems of units, such as the CGS-EMU system, and the CGS-ESU system, that made different choices for the base dimensions.)
In QUDT every dimension vector is comprised of each of the above base dimensions and an associated exponent in the following way:
(Dimension1 * dimensional_exponent1) * (Dimension2 * dimensional_exponent2) * ...
This is repeated for all 7 dimensions and the dimensionless indicator in the following order:
Amount of substance, Electric current, Length, Luminous intensity, Mass, Temperature, Time, Dimensionless
The dimensions and the dimensionless value are indicated with single letter codes which, for the above dimensions and dimensionless are, in order, as above:
A E L I M H T D
An example for the QuantityKindDimensionVector associated with Force is:
qkdv:A0E0L1I0M1H0T-2D0
where the only non-zero exponents are for L (length), M (mass), and T (time), i.e., M1L1T-2. (Please note that in QUDT we add a coefficient for dimensionless quantity kinds. This is the last item, D, in the example above. When a quantity kind is dimensionless all the base units will have zero exponents except D. An example of a dimensionless quantity kind is TemperatureRatio:
qkdv:A0E0L0I0M0H0T0D1
To determine whether one unit can be converted into another, they must at least be associated with the same "dimension vector". The dimension vector (known in QUDT as the QuantityKindDimensionVector) is simply a description of a given unit in terms of the appropriate powers of the underlying base dimensions. For example, speed is (Length / Time); acceleration is (Length / Time**2).
The QUDT vocabulary contains over two thousand units compliant with ISO 80000 and several other standards including IEC 61360. For example, we could execute the following SPARQL query to produce all of the units in the vocabulary associated with the base units of M * L / T^2. We get to this through the DimensionVector: (Try it here)
SELECT DISTINCT ?un (COALESCE(?labelEn, ?unl) AS ?label)
WHERE {
BIND ("A0E0L1I0M1H0T-2D0" AS ?arg1) .
?dv rdf:type qudt:QuantityKindDimensionVector .
BIND(REPLACE(STR(?dv), ".*[#/]", "") AS ?dvn) .
FILTER CONTAINS(UCASE(STR(?dvn)), UCASE(STR(?arg1)))
?qk qudt:hasDimensionVector ?dv .
?un qudt:unitForQuantityKind ?qk .
?un a qudt:Unit .
?un rdfs:label ?unl .
OPTIONAL {
?un rdfs:label ?labelEn .
FILTER (lang(?labelEn) = "en")
}
}
ORDER BY ?un
which produces the following:
un label
unit:CentiN CentiNewton
unit:DYN Dyne
unit:DeciN DeciNewton
unit:ERG-PER-CentiM Erg per Centimetre
unit:EV-PER-ANGSTROM Electronvolt per Angstrom
unit:EV-PER-M Electronvolt per Metre
unit:GM_F Gram Force
unit:GigaN GigaN
unit:J-PER-M Joule per Metre
unit:KIP_F Kip
unit:KiloEV-PER-MicroM Kilo Electron Volt per Micrometre
unit:KiloGM-M-PER-SEC2 kilogram metre per second squared
unit:KiloGM_F Kilogram Force
unit:KiloLB_F KiloPound Force
unit:KiloN Kilonewton
unit:KiloN-M-PER-DEG-M kilonewton metre per degree metre
unit:KiloN-M-PER-M Kilonewton Metre per metre
unit:KiloPOND Kilopond
unit:LB_F Pound Force
unit:LB_F-FT-PER-IN pound-force foot per inch
unit:LB_F-IN-PER-IN pound-force inch per inch
unit:MegaEV-PER-CentiM Mega Electron Volt per Centimetre
unit:MegaLB_F Mega Pound Force
unit:MegaN Meganewton
unit:MicroN Micronewton
unit:MilliN Millinewton
unit:N newton
unit:N-M-PER-DEG-M Newton metre per degree metre
unit:N-M-PER-M Newton metre per metre
unit:N-M-PER-M-RAD Newton Metre per Metre Radian
unit:N-PER-RAD Newton per radian
unit:NanoN NanoN
unit:OZ_F Imperial Ounce Force
unit:PDL Poundal
unit:POND pond
unit:PlanckForce Planck Force
unit:TON_F_US Ton Force (US Short)
Every unit has an associated quantity kind and dimension vector. You cannot add a speed to a temperature because Length / Time is different from Temperature. You can add a furlong to a kilometer, because they both have a dimension vector of Length. Of course, you need to convert one unit into the other before adding the numbers, which leads us to...
Each instance of Unit has a property called qudt:conversionMultiplier. The value of the multiplier tells you what number to multiply to convert a given unit into the SI version of that unit. So, for example the conversionMultiplier for an inch (unit:IN) is 0.0245. That is, 1 Inch equals 0.0245 Meters.
Measurements that have the same QuantityKind can often be combined mathematically. You can add two lengths, once you accommodate their conversion multipliers, but it doesn't make sense to add a length and a temperature - they are of different quantity kinds. As an example of how to use conversion multipliers in QUDT, consider the following relationship to calculate the circumference of a rectangle:
rectangleCircumference = 2 x length + 2 * width
Lets say that, for the purposes of discussion, the length is measured in inches (IN) and the width is measured in centimeters (CentiM). Then if the length is 19 and the width is 12 we could use the following to calculate the circumference in the base unit of Meters. The essence of the query, after doing some bindings for the values and the unit types, comes down to getting the conversion multipliers for the units and performing the calculation:
SELECT ?rectCircum
WHERE {
BIND (19 AS ?length) .
BIND (12 AS ?width) .
BIND (unit:IN AS ?arg1) .
BIND (unit:CentiM AS ?arg2) .
?arg1 qudt:conversionMultiplier ?cm1 .
?arg2 qudt:conversionMultiplier ?cm2 .
BIND (((2 * ?length * ?cm1) + (2 * ?width * ?cm2)) AS ?rectCircum) .
}
The query above produces the value of 1.2052, which is now in SI units of meter (M). Of course, we could add another last line (e.g., BIND ((?rectCircum / ?cm1) AS ?rectCircumIN) ., which produces 47.44881 in, or BIND ((?rectCircum / ?cm2) AS ?rectCircumCentiM) ., which produces 120.52 cm) to the query to return the circumference in either inches or centimeters, respectively. Alternatively, we could have just converted one of the two (length or width) to the other before calculating the circumference.
Building on the above discussion of dimension vectors and conversion multipliers leads us to an elegant way to do unit conversions. (Important caveat: The following example works to convert incremental values of units where the only important factor is the relative size of the unit. This example does not handle absolute values for units with offsets (think Celsius and Fahrenheit degrees). QUDT supports that too - the QUDT treatment of absolute and incremental values is discussed here.
The approach we will use is shown in the following pseudocode:
1. start with a given instance of a Unit
1.1 find out what QuantityKind it has
1.1.1 determine its QuantityKindDimensionVector
1.2 find out all the QuantityKinds that have that same QuantityKindDimensionVector
1.3 find all the Units with those QuantityKinds
2. multiply your starting unit by its conversionMultiplier
2.1 divide the result by the target unit conversionMultiplier
That is the logic behind the following SPARQL query:
SELECT DISTINCT ?toConvert ?label ?into (COALESCE(?labelEn, ?otherUnitLabel) AS ?otherlabel) ?multiplyBy ?multiplier
WHERE {
BIND ("To convert" AS ?toConvert) .
BIND ("into" AS ?into) .
BIND ("multiply by" AS ?multiplyBy) .
BIND (unit:MilliGRAY as ?unit) .
?unit rdfs:label ?label .
FILTER (lang(?label) = "en") .
?unit qudt:conversionMultiplier ?cm1 .
?unit qudt:hasQuantityKind/qudt:hasDimensionVector ?qkdv .
?otherUnit qudt:hasQuantityKind/qudt:hasDimensionVector ?qkdv .
?otherUnit a qudt:Unit .
FILTER (?otherUnit != ?unit) .
FILTER NOT EXISTS {?otherUnit qudt:deprecated true}
?otherUnit qudt:conversionMultiplier ?cm2 .
?otherUnit rdfs:label ?otherUnitLabel .
OPTIONAL {
?otherUnit rdfs:label ?labelEn .
FILTER (lang(?labelEn) = "en") .
}
BIND ((?cm1/?cm2) AS ?multiplier) .
}
ORDER BY ?otherlabel
Executing this query produces output that looks like this:
toConvert label into otherlabel multiplyBy multiplier
To convert Milligray into British Thermal Unit (international Definition) per Pound Mass multiply by 0.000000429922613929492691
To convert Milligray into British Thermal Unit (thermochemical Definition) per Pound Mass multiply by 0.00000043021032504326744
To convert Milligray into Centigray multiply by 0.1
To convert Milligray into Erg per Gram multiply by 10.0
To convert Milligray into Gigapascal Cubic Centimetre per Gram multiply by 0.000000001
To convert Milligray into Gray multiply by 0.001
To convert Milligray into International Table Calorie per Gram multiply by 0.000000238845896627495939
To convert Milligray into Joule per Gram multiply by 0.000001
To convert Milligray into Joule per Kilogram multiply by 0.001
To convert Milligray into Kilo Pound Force Foot per Pound Mass multiply by 0.000000334552548302427649
To convert Milligray into Kilocalorie per Gram multiply by 0.000000000239005736137667
To convert Milligray into Kilogray multiply by 0.000001
To convert Milligray into Kilojoule per Kilogram multiply by 0.000001
To convert Milligray into Megagray multiply by 0.000000001
To convert Milligray into Megajoule per Kilogram multiply by 0.000000001
To convert Milligray into Microgray multiply by 1000.0
To convert Milligray into Microsievert multiply by 1000.0
To convert Milligray into Milli Roentgen Equivalent Man multiply by 100.0
To convert Milligray into Millijoule per Gram multiply by 0.001
To convert Milligray into Millirad multiply by 100.0
To convert Milligray into Millisievert multiply by 1.0
To convert Milligray into Nanogray multiply by 1000000.0
To convert Milligray into Nanosievert multiply by 1000000.0
To convert Milligray into Newton Metre per Kilogram multiply by 0.001
To convert Milligray into Rad multiply by 0.1
To convert Milligray into Rem multiply by 0.1
To convert Milligray into Roentgen Equivalent Man multiply by 0.1
To convert Milligray into Sievert multiply by 0.001
To convert Milligray into Square Kilometre per Square Second multiply by 0.000000001
To convert Milligray into Square Metre per Square Second multiply by 0.001
To convert Milligray into Thermochemical Calorie per Gram multiply by 0.000000239005736137667304
To convert Milligray into Watt Hour per Kilogram multiply by 0.000000277777777777777777
None of these pairwise relationships had to be stored. The query simply returns all the other units that have the same associated dimension vector. You can try queries for both incremental and absolute unit conversion, as well as any of the above examples, using our SPARQL endpoint.
A quantity kind's dimension vector (qudt:hasDimensionVector) captures its composition in terms of the seven SI base dimensions. It is tempting to assume that two quantity kinds with the same dimension vector are interchangeable — that their values can be compared, added, or converted between one another. In general they cannot. Sharing a dimension vector is necessary but not sufficient for commensurability.
The classic illustration is torque and energy. Both quantitykind:Torque and quantitykind:Energy have the identical dimension vector qkdv:A0E0L2I0M1H0T-2D0 (M·L²·T⁻²), and both are even measured with the same unit — the newton metre, since 1 J = 1 N·m. Yet a torque is not an energy: it makes no physical sense to add a torque to an energy, or to convert one into the other. Neither the dimension nor the unit tells them apart; only the quantity kind does.
QUDT therefore decides commensurability not from the dimension vector alone but also from explicit, curated relations — chiefly qudt:specializationOf and qudt:exactMatch. quantitykind:ThermalEnergy is qudt:specializationOf quantitykind:Energy - they share the same dimension and are genuinely commensurable (fully interconvertible), so they sit in one commensurability family. Torque carries that very same dimension vector but has no such link to Energy or Thermal Energy, so it forms a separate family.
In short, the dimension vector tells you whether two quantity kinds could be related by a numeric factor at all; the commensurability relations tell you whether they actually are. For the full treatment — including how units, and ultimately individual qudt:Quantity instances, fit into this picture — see Commensurability, Composition, Semantics and Context.
On rare occasions, one encounters a quantity kind that has no dimension vector. (Normally, all quantity kinds are required to have an associated dimension vector). It is important to recognize this as distinct from quantity kinds that have a dimensionless dimension vector (i.e. A0E0L0I0M0H0T0D1). These quantity kinds might be useful to refer to in some specialized domain, but they are ambiguous. For example, quantitykind:VisionThresholds refers to the sensitivity of the eye to light. It might be reported as the number of photons incident on a prescribed part of the retina, or it might be in terms of luminance, or even illuminance. It is arguable that such concepts don't really even belong in QUDT as defined Quantity Kinds and are best treated as contextual Quantity instances instead. As of the writing of this wiki, QUDT only has 7 such quantity kinds.
Let's say your smart thermostat is even smarter than the one in the first example, and communicates in both Fahrenheit and Kelvin (the SI unit for temperature). Here's how we could store all that information. Keep in mind that the "concept" of the temperature setting is still a single concept, even when its value is represented in multiple units. So in this case, instead of using the built-in data property qudt:hasUnit inside the qudt:Quantity class, we use the object property qudt:quantityValue that points to the class qudt:QuantityValue in the first diagram on this page. There will be two instances of qudt:QuantityValue, one that points to the unit:DEG_F unit instance, and one that points to the unit:K unit instance. Here's the code:
wiki-examples:MySmarterThermostatSetting
a qudt:Quantity ;
qudt:quantityValue wiki-examples:FahrenheitSetting ;
qudt:quantityValue wiki-examples:KelvinSetting ;
.
wiki-examples:FahrenheitSetting
rdf:type qudt:QuantityValue ;
qudt:hasUnit unit:DEG_F ;
qudt:value "72.0"^^xsd:float ;
.
wiki-examples:KelvinSetting
rdf:type qudt:QuantityValue ;
qudt:hasUnit unit:K ;
qudt:value "295.37"^^xsd:float ;
.
Installing QUDT for Contributors
Publishing QUDT to a TopBraid EDG Server
Unit Vocabulary Submission Guide
Quantity Kind Vocabulary Submission Guide
Dimension Vector Vocabulary Submission Guide
Defining a new unit (local Maven validation)
Defining a new unit (no local Maven)