Unit Converter
Before diving into how unit conversion is handled in InDSL, it is necessary define the terms and basic logic it all revolves around:
Unit type: the physical unit assigned to a time series. Typical unit types are pressure, temperature, length, volumetric flow-rate and so on.
Unit of measure (UoM): the unit, from any particular system (e.g., International System or SI), assigned to the time series. For instance length can be measured in UoM meters (m) or feet (ft).
Base unit of measure: the reference unit of measure from the Internal System of Units (SI). All other units of measure are converted using conversion factors relative to the base unit of measure.
Unit conversion is based on the following basic operation:
where y is the target UoM and x is the base unit of measure. A and -B are the conversion factors, which are, for programmatic reasons, named multiplier and shift, respectively. Also note that the shift is defined as negative B. This is due to the algorithm being based on referencing all conversions to the base unit of measure. Therefore, when solving for it one obtains \(x = (y-B)/A\).
Dictionaries
The conversion toolbox and algorithms are structured around four JSON dictionaries:
Fundamental units: unit_type_fundamental.json
Unit types, UoM, conversion factors: unit_conversion.json
Scalers: scalers.json
Unit type aliases: unit_type_alias.json
Fundamental units
The unit_type_fundamental.json dictionary contains all the supported fundamental units types supported and expressed as a combination of other fundamental unit types. For example, mass is a fundamental unit type that can only be defined by itself, and pressure is a fundamental unit type that can be expressed as multiple combinations of other runit types. This is represented in the dictionary as follows:
{
"mass": [
"mass"
],
"pressure": [
"mass/(distance*time*time)",
"force/(distance*distance)",
"force/area",
"pressure"
],
}
By defining fundamental unit types we can leverage them to curate a list of supported unit types and their associated conversion factors (more on this below) relative to a base unit; instead of a large matrix of unit types and conversion factors with a one-to-one relationship.
Unit conversion
The unit conversion dictionary contains all the supported unit types and their respective conversion factors to the
base unit. The dictionary is nested, with the highest branch being the unit type. The unit conversion dictionary
currently supports the following unit types and corresponding [base unit of measure]:
Mass [
kg]Distance [
m]Time [
s]Temperature [
degC]Pressure [
kg/(m*s*s)]Area [
m*m]Volume [
m*m*m]Velocity [
m/s]Volumetric Flowrate [
m*m*m/s]Gas Flowrate [
m*m*m/s]Mass Flowrate [
kg/s]Acceleration [
m/(s*s)]Force [
kg*m/(s*s)]Density [
kg/(m*m*m)]
A unit type in the dictionary must contain of the following fields:
fundamental: “true” if it is a fundamental unit type
base unit: base unit of measure from the SI system
units: dictionary will all the supported units of measure for each unit type
multiplier: conversion factor value (float) relative to the base unit of measure.
description: Human readable description of the unit of measure. If it is a base units it should be indicated with the label[base unit]at the end of the description.
shift(Optional): conversion factor shift value (float) relative to the base unit of measure.
aliases(Optional): unit of measure aliases
Note that “shift” and “aliases” are optional. Not all conversions require “shift” parameter and aliases are used to accommodate other notations or names used to designate the same unit of measure.
Below is an example of the dictionary containing the base unit [kg] and an additional unit of mass [lbm].
{
"mass": {
"fundamental": "true",
"base_unit": "kg",
"units": {
"kg": {
"multiplier": "1.000000",
"description": "kilogram [base unit]"
},
"lbm": {
"multiplier": "0.453592",
"description": "pound mass"
},
}
}
Note that the that the multiplier is 0.453592 which means that 1 lbm = 0.453592 kg. The conversion has to be
stated in this format (1 unit = x base unit) not the other way (1 base unit = x unit).
An example using shift is temperature conversion from degrees Celsius (degC) to Fahrenheit (degF), where
degF = degC * 1.8 + 32. In this case, degC = (degF - 32)/1.8, therefore, the multiplier is 1/1.8 = 0.555555555555556
and the shift is -32.000000. The example below shows how this looks in the dictionary and also contains a few
unit of measure aliases for degrees Celsius.
{
"temperature": {
"fundamental": "true",
"base_unit": "degC",
"units": {
"degC": {
"multiplier": "1.000000",
"description":"degrees celsius",
"aliases": ["deg_C", "deg C"]
},
"degF": {
"multiplier": "0.555555555555556",
"shift": "-32.000000",
"description":"degrees fahrenheit"
},
"degR": {
"multiplier": "0.555555555555556",
"shift": "-491.670000",
"description":"degrees rankine"
},
"degK": {
"multiplier": "1.000000",
"shift": "-273.150000",
"description":"degrees kelvin"
}
}
}
Scalers
Dictionary containing the name, numerical value and aliases of the metric prefixes. It is used to support conversion to and from units containing prefixes in the unit of measure (e.g. kN)
Unit type aliases
This dictionary is used to support unit type names that require special treatment or special names used by certain industries or sectors of an industry. For example, gas volumetric flowrate is an alias for volumetric flowrate but given the quantities measured and conditions, the units of measure are sometimes very different from the traditional ones (e.g. standard liters per minute or slpm)
Contributing to the unit converter
Contributing to the unit converter means adding new units to the dictionary. To contribute, it is important to follow the beginning section of the Contributing guide under the Preliminaries and setup section.
If a desired
unitis missing in the unit_conversion.json dictionary, add a new entry under the appropriateunit type. The key should be theunitand the value should be a dictionary consisting of themultiplier,description,shift, andaliases. The itemsmultiplierandshiftmust contain at least 6 be at least 6 significant digits or figures. This aims to minimize error propagation and to estimate it if necessary. For example, even if the conversion is only two decimal points1.23, additional four zeroes,1.230000, must be added for the entry to be correct.If a
unit typeis missing, add the new unit type to the dictionary. The first entry of theunit typehas to be the base SI unit which is typically a combination ofkg,m,sanddegC. An additional entry has to be added for thebase unitentry which is"base": "true".If a new
unit typeis added then add thatunit typeto the unit_type_fundamental.json dictionary with all the ways theunit typecan be broken down (see example at the start of this section). The key to this dictionary is theunit typeand the value is the list with the brake down of fundamental combinations.Once all the required changes are made to the dictionaries, skip to the Create a pull request section of the Contributing guide and follow the steps.