use of javax.measure.Unit in project n2a by frothga.
the class ExportJob method appendUnits.
@SuppressWarnings({ "rawtypes", "unchecked" })
public void appendUnits(boolean assumeNML) {
// Purge pure dimensions (added independent of specific unit) if they are standard and NML dimensions are available.
if (assumeNML) {
List<String> keys = new ArrayList<String>(dimensionsUsed.keySet());
for (String key : keys) {
Dimension d = dimensionsUsed.get(key);
if (dimensionsNML.containsKey(d))
dimensionsUsed.remove(key);
}
}
for (Entry<Unit<?>, String> e : unitsUsed.entrySet()) {
Unit<?> key = e.getKey();
if (assumeNML && unitsNML.containsKey(key))
continue;
String symbol = e.getValue();
Dimension dimension = key.getDimension();
String dimensionName = dimensionsNML.get(dimension);
if (// Not a standard NML dimension
dimensionName == null) {
dimensionName = dimension.toString();
dimensionsUsed.put(dimensionName, dimension);
} else if (// Is a standard NML dimension, so only add if don't have NML dimensions available.
!assumeNML) {
dimensionsUsed.put(dimensionName, dimension);
}
Element unit = addElement("Unit", elements);
unit.setAttribute("symbol", symbol);
unit.setAttribute("dimension", dimensionName);
// Determine offset
Unit systemUnit = key.getSystemUnit();
UnitConverter converter = key.getConverterTo(systemUnit);
double offset = converter.convert(Integer.valueOf(0)).doubleValue();
if (offset != 0)
unit.setAttribute("offset", String.valueOf(offset));
// Determine power*scale
double scale = converter.convert(Integer.valueOf(1)).doubleValue() - offset;
int power = (int) Math.round(Math.log(scale) / Math.log(10));
if (Math.abs(scale - Math.pow(10, power)) < epsilon) {
unit.setAttribute("power", String.valueOf(power));
} else {
unit.setAttribute("scale", String.valueOf(scale));
}
}
for (Entry<String, Dimension> d : dimensionsUsed.entrySet()) {
String name = d.getKey();
Dimension value = d.getValue();
Element dimension = addElement("Dimension", elements);
dimension.setAttribute("name", name);
Map<? extends Dimension, Integer> bases = value.getBaseDimensions();
if (bases == null) {
Map<Dimension, Integer> temp = new HashMap<Dimension, Integer>();
temp.put(value, 1);
bases = temp;
}
for (Entry<? extends Dimension, Integer> e : bases.entrySet()) {
String base = e.getKey().toString().substring(1, 2).toLowerCase();
if (base.equals("θ"))
base = "k";
dimension.setAttribute(base, e.getValue().toString());
}
}
}
use of javax.measure.Unit in project n2a by frothga.
the class ImportJob method unit.
@SuppressWarnings({ "rawtypes", "unchecked" })
public void unit(Node node) {
String symbol = getAttribute(node, "symbol");
String dimension = getAttribute(node, "dimension");
int power = getAttribute(node, "power", 0);
double scale = getAttribute(node, "scale", 1.0);
double offset = getAttribute(node, "offset", 0.0);
Unit unit = dimensions.get(dimension);
if (unit == null)
unit = nmlDimensions.get(dimension);
// fall back, but in general something is broken about the file
if (unit == null)
unit = AbstractUnit.ONE;
if (power > 0)
unit = unit.transform(MultiplyConverter.ofRational(BigInteger.TEN.pow(power), BigInteger.ONE));
else if (power < 0)
unit = unit.transform(MultiplyConverter.ofRational(BigInteger.ONE, BigInteger.TEN.pow(-power)));
else {
if (scale == 1.0) {
unit = unit.shift(offset);
} else {
// UCUM only allows rational numbers, so convert scale
MultiplyConverter ratio = null;
if (scale < 1.0) {
// Attempt to find a simple ratio of 1/integer
double inverse = 1.0 / scale;
long integer = Math.round(inverse);
if (Math.abs(inverse - integer) < epsilon)
ratio = MultiplyConverter.ofRational(1, integer);
}
if (ratio == null) {
String s = getAttribute(node, "scale").toLowerCase();
String[] pieces = s.split("e");
int shift = 0;
if (pieces.length > 1)
shift = Integer.valueOf(pieces[1]);
pieces = pieces[0].split(".");
if (pieces.length > 1) {
shift -= pieces[1].length();
s = pieces[0] + pieces[1];
}
BigInteger numerator = new BigInteger(s);
BigInteger denominator = new BigDecimal(10).pow(shift).toBigInteger();
ratio = MultiplyConverter.ofRational(numerator, denominator);
}
unit = unit.transform(ratio).shift(offset);
}
}
// Since LEMS and NeuroML tend to follow certain naming practices, we may be able to retrieve
// a more parsimonious unit based on direct name translation.
String tempName = symbol;
tempName = tempName.replace("_per_", "/");
tempName = tempName.replace("per_", "/");
tempName = tempName.replace("_", ".");
tempName = tempName.replace("ohm", "Ohm");
tempName = tempName.replace("hour", "h");
Unit temp = null;
try {
temp = UCUM.parse(tempName);
} catch (MeasurementParseException | TokenException e) {
}
if (// found a unit with matching dimension ...
temp != null && temp.isCompatible(unit)) {
Number tempScale = temp.getConverterTo(temp.getSystemUnit()).convert(Integer.valueOf(1));
Number unitScale = temp.getConverterTo(unit.getSystemUnit()).convert(Integer.valueOf(1));
if (// ... and matching scale ...
tempScale.equals(unitScale)) {
int unitLength = UCUM.format(unit).length();
int tempLength = UCUM.format(temp).length();
if (// ... and at least as parsimonious
tempLength <= unitLength) {
unit = temp;
// Update dimension if this is directly equivalent, but strictly more parsimonious
if (power == 0 && scale == 1 && offset == 0 && tempLength < unitLength) {
dimensions.put(dimension, temp);
}
}
}
}
ExpressionParser.namedUnits.put(symbol, unit);
}
Aggregations