Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

19 unit conversion #20

Draft
wants to merge 8 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from 6 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 13 additions & 1 deletion pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.icatproject</groupId>
<version>4.16.2-SNAPSHOT</version>
<version>4.17.0-SNAPSHOT</version>
<artifactId>icat.utils</artifactId>
<packaging>jar</packaging>
<name>ICAT Utils</name>
Expand Down Expand Up @@ -63,6 +63,18 @@
<scope>test</scope>
</dependency>

<dependency>
<groupId>javax.measure</groupId>
<artifactId>unit-api</artifactId>
<version>2.1.3</version>
</dependency>

<dependency>
<groupId>tech.units</groupId>
<artifactId>indriya</artifactId>
<version>2.1.3</version>
</dependency>

</dependencies>

<build>
Expand Down
89 changes: 89 additions & 0 deletions src/main/java/org/icatproject/utils/IcatUnits.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
package org.icatproject.utils;

import javax.measure.IncommensurableException;
import javax.measure.UnconvertibleException;
import javax.measure.Unit;
import javax.measure.UnitConverter;
import javax.measure.format.MeasurementParseException;

import tech.units.indriya.format.SimpleUnitFormat;

/**
* Utility to perform conversions to SI (System) units.
*/
public class IcatUnits {

/**
* Holds the SI units and value for a quantity. If the units provided at
* construction could not be parsed, then these will be null.
*/
public class SystemValue {
public String units = null;
public Double value = null;

/**
* Converts value units into an SI quantity.
*
* @param value Quantity in (potentially) non-SI units.
* @param units Units of the provided value.
*/
public SystemValue(Double value, String units) {
VKTB marked this conversation as resolved.
Show resolved Hide resolved
try {
Unit<?> unit = unitFormat.parse(units);
Unit<?> systemUnit = unit.getSystemUnit();
this.units = systemUnit.getName();
if (value == null) {
return;
}
UnitConverter converter = unit.getConverterToAny(systemUnit);
this.value = converter.convert(value.doubleValue());
} catch (MeasurementParseException | UnconvertibleException | IncommensurableException e) {
// If the units can't be parsed, or the value converted, then just return
return;
}
}
}

private static final SimpleUnitFormat unitFormat = SimpleUnitFormat.getInstance();

/**
* Creates instance with any aliasing.
*/
public IcatUnits() {
}

/**
* In addition to the standard names and prefixes, allows aliasing other terms
* for a unit. Note that Unit should be referred to by the symbol specified in
* the
* <a href=
* "https://javadoc.io/doc/tech.units/indriya/latest/tech/units/indriya/unit/Units.html">Indriya
* documentation</a>, but the aliases can be any string. However, OoM prefixes
* will not be applied to aliases. For example, "mK" would be understood as
* 0.001K, but if "Kelvin" is aliased than "mKelvin" will not be understood.
*
* If needed, a conversion factor can be provided alongside an alias, for
* example to alias "eV" as a unit of energy, a factor of 1.602176634e-19 should
* be applied to convert to the SI unit J.
*
* @param aliasOptions String with the format
* <code>symbolA: aliasA1, aliasA2 factorA2; symbolB: aliasB1 ...</code>
*/
public IcatUnits(String aliasOptions) {
if (!aliasOptions.equals("")) {
for (String unitAliases : aliasOptions.split(";")) {
String[] splitUnitAliases = unitAliases.split(":");
Unit<?> unit = unitFormat.parse(splitUnitAliases[0].trim());
for (String alias : splitUnitAliases[1].trim().split(",")) {
String[] aliasSplit = alias.trim().split("\\s+");
if (aliasSplit.length == 2) {
unitFormat.alias(unit.multiply(new Double(aliasSplit[1])), aliasSplit[0]);
} else {
unitFormat.alias(unit, aliasSplit[0]);
}
}
}
}
}

}
51 changes: 51 additions & 0 deletions src/test/java/org/icatproject/utils/TestIcatUnits.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
package org.icatproject.utils;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNull;

import org.icatproject.utils.IcatUnits.SystemValue;
import org.junit.Test;

public class TestIcatUnits {
VKTB marked this conversation as resolved.
Show resolved Hide resolved
@Test
public void testArguments() {
// Both null
IcatUnits icatUnits = new IcatUnits();
SystemValue systemValue = icatUnits.new SystemValue(null, "impossible to parse");
assertNull(systemValue.units);
assertNull(systemValue.value);

// Unit parsed, value null
systemValue = icatUnits.new SystemValue(null, "K");
assertEquals("Kelvin", systemValue.units);
assertNull(systemValue.value);

// Unit parsed, value converted
systemValue = icatUnits.new SystemValue(1., "GK");
assertEquals("Kelvin", systemValue.units);
assertEquals(new Double(1e9), systemValue.value);
}

@Test
public void testAliasing() {
IcatUnits icatUnits = new IcatUnits();
SystemValue systemValue = icatUnits.new SystemValue(null, "celsius");
assertNull(systemValue.units);
systemValue = icatUnits.new SystemValue(null, "degC");
assertNull(systemValue.units);
systemValue = icatUnits.new SystemValue(null, "kelvin");
assertNull(systemValue.units);
systemValue = icatUnits.new SystemValue(null, "eV");
assertNull(systemValue.units);

new IcatUnits("\u2103: celsius, degC; K: kelvin; J: eV 1.602176634e-19");
new IcatUnits();
systemValue = icatUnits.new SystemValue(null, "celsius");
assertEquals("Kelvin", systemValue.units);
systemValue = icatUnits.new SystemValue(null, "degC");
assertEquals("Kelvin", systemValue.units);
systemValue = icatUnits.new SystemValue(1., "eV");
assertEquals("Joule", systemValue.units);
assertEquals(new Double(1.602176634e-19), systemValue.value);
}
}