use of org.apache.sis.referencing.operation.transform.TransferFunction in project sis by apache.
the class SampleDimensionTest method testQuantitativeWithMissingValues.
/**
* Tests a sample dimension having one quantitative category and a few "no data" values.
* Expected value:
*
* {@preformat text
* ┌────────────┬──────────────────┬─────────────┐
* │ Values │ Measures │ Name │
* ╞════════════╧══════════════════╧═════════════╡
* │ Temperature │
* ├────────────┬──────────────────┬─────────────┤
* │ 0 │ NaN #0 │ Fill value │
* │ 1 │ NaN #1 │ Clouds │
* │ [10 … 200) │ [6.00 … 25.00)°C │ Temperature │
* │ 255 │ NaN #255 │ Lands │
* └────────────┴──────────────────┴─────────────┘
* }
*/
@Test
public void testQuantitativeWithMissingValues() {
final int lower = 10;
final int upper = 200;
final double scale = 0.1;
final double offset = 5.0;
final SampleDimension dimension = new SampleDimension.Builder().setBackground(null, // Default to "Fill value" name, potentially localized.
0).addQualitative("Clouds", 1).addQualitative("Lands", 255).addQuantitative("Temperature", lower, upper, scale, offset, Units.CELSIUS).build();
assertEquals("name", "Temperature", String.valueOf(dimension.getName()));
assertEquals("background", 0, dimension.getBackground().get());
final Set<Number> nodataValues = dimension.getNoDataValues();
assertArrayEquals("nodataValues", new Integer[] { 0, 1, 255 }, nodataValues.toArray());
NumberRange<?> range = dimension.getSampleRange().get();
assertEquals("minimum", 0, range.getMinDouble(), STRICT);
assertEquals("maximum", 255, range.getMaxDouble(), STRICT);
range = dimension.getMeasurementRange().get();
assertEquals("minimum", lower * scale + offset, range.getMinDouble(true), CategoryTest.EPS);
assertEquals("maximum", upper * scale + offset, range.getMaxDouble(false), CategoryTest.EPS);
assertEquals("units", Units.CELSIUS, dimension.getUnits().get());
final TransferFunction tr = dimension.getTransferFunctionFormula().get();
assertFalse("identity", dimension.getTransferFunction().get().isIdentity());
assertFalse("identity", tr.getTransform().isIdentity());
assertEquals("scale", scale, tr.getScale(), STRICT);
assertEquals("offset", offset, tr.getOffset(), STRICT);
/*
* Verifies SampleDimension properties after we converted integers to real values.
*/
final SampleDimension converted = dimension.forConvertedValues(true);
assertNotSame(dimension, converted);
assertSame(dimension, dimension.forConvertedValues(false));
assertSame(dimension, converted.forConvertedValues(false));
assertSame(converted, converted.forConvertedValues(true));
assertSame(range, converted.getSampleRange().get());
assertTrue("identity", converted.getTransferFunction().get().isIdentity());
assertTrue("background", Double.isNaN(converted.getBackground().get().doubleValue()));
final Iterator<Number> it = converted.getNoDataValues().iterator();
assertEquals("nodataValues", 0, MathFunctions.toNanOrdinal(it.next().floatValue()));
assertEquals("nodataValues", 1, MathFunctions.toNanOrdinal(it.next().floatValue()));
assertEquals("nodataValues", 255, MathFunctions.toNanOrdinal(it.next().floatValue()));
assertFalse("nodataValues", it.hasNext());
}
use of org.apache.sis.referencing.operation.transform.TransferFunction in project sis by apache.
the class Axis method read.
/**
* Returns the coordinates in the localization grid, excluding some trailing NaN values if any.
* This method typically returns a cached vector if the coordinates have already been read.
*
* @throws IOException if an error occurred while reading the data.
* @throws DataStoreException if a logical error occurred.
*/
final Vector read() throws IOException, DataStoreException {
final TransferFunction tr = coordinates.getTransferFunction();
if (TransferFunctionType.LINEAR.equals(tr.getType())) {
Vector data = coordinates.read();
if (gridSizes != null) {
// Trim trailing NaN values.
data = data.subList(0, getSizeProduct(0));
}
// Apply scale and offset attributes, if any.
data = data.transform(tr.getScale(), tr.getOffset());
return data;
} else {
throw new DataStoreException(coordinates.resources().getString(Resources.Keys.CanNotUseAxis_1, getName()));
}
}
use of org.apache.sis.referencing.operation.transform.TransferFunction in project sis by apache.
the class GCOM_W method transferFunction.
/**
* Builds the function converting values from their packed formats in the variable to "real" values.
* This method is invoked only if {@link #validRange(Variable)} returned a non-null value.
*
* @param data the variable from which to determine the transfer function.
* @return a transfer function built from the attributes defined in the given variable.
*/
@Override
public TransferFunction transferFunction(final Variable data) {
final TransferFunction tr = super.transferFunction(data);
if (tr.isIdentity()) {
final double slope = data.getAttributeAsNumber("SCALE FACTOR");
final double offset = data.getAttributeAsNumber("OFFSET");
if (Double.isFinite(slope))
tr.setScale(slope);
if (Double.isFinite(offset))
tr.setOffset(offset);
}
return tr;
}
use of org.apache.sis.referencing.operation.transform.TransferFunction in project sis by apache.
the class Convention method transferFunction.
/**
* Builds the function converting values from their packed formats in the variable to "real" values.
* The transfer function is typically built from the {@code "scale_factor"} and {@code "add_offset"}
* attributes associated to the given variable, but other conventions could use different attributes.
* The returned function will be a component of the {@link org.apache.sis.coverage.SampleDimension}
* to be created for each variable.
*
* <p>This method is invoked in contexts where a transfer function is assumed to exist, for example
* because {@link #validRange(Variable)} returned a non-null value. Consequently this method shall
* never return {@code null}, but can return the identity function.</p>
*
* @param data the variable from which to determine the transfer function.
* This is usually a variable containing raster data.
*
* @return a transfer function built from the attributes defined in the given variable. Never null;
* if no information is found in the given {@code data} variable, then the return value
* shall be an identity function.
*/
public TransferFunction transferFunction(final Variable data) {
/*
* If scale_factor and/or add_offset variable attributes are present, then this is
* a "packed" variable. Otherwise the transfer function is the identity transform.
*/
final TransferFunction tr = new TransferFunction();
final double scale = data.getAttributeAsNumber(CDM.SCALE_FACTOR);
final double offset = data.getAttributeAsNumber(CDM.ADD_OFFSET);
if (!Double.isNaN(scale))
tr.setScale(scale);
if (!Double.isNaN(offset))
tr.setOffset(offset);
return tr;
}
use of org.apache.sis.referencing.operation.transform.TransferFunction in project sis by apache.
the class SampleDimension method getTransferFunctionFormula.
/**
* Returns the scale factor and offset of the transfer function.
* The formula returned by this method does <strong>not</strong> take
* "{@linkplain #getNoDataValues() no data values}" in account.
* For a more generic transfer function, see {@link #getTransferFunction()}.
*
* @return a description of the part of the transfer function working on real numbers.
* @throws IllegalStateException if the transfer function can not be simplified in a form representable
* by {@link TransferFunction}.
*/
public Optional<TransferFunction> getTransferFunctionFormula() {
MathTransform1D tr = null;
for (final Category category : categories) {
final Optional<MathTransform1D> c = category.getTransferFunction();
if (c.isPresent()) {
if (tr == null) {
tr = c.get();
} else if (!tr.equals(c.get())) {
throw new IllegalStateException(Resources.format(Resources.Keys.CanNotSimplifyTransferFunction_1));
}
}
}
if (tr == null) {
return Optional.empty();
}
final TransferFunction f = new TransferFunction();
try {
f.setTransform(tr);
} catch (IllegalArgumentException e) {
throw new IllegalStateException(Resources.format(Resources.Keys.CanNotSimplifyTransferFunction_1, e));
}
return Optional.of(f);
}
Aggregations