sis-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From desruisse...@apache.org
Subject [sis] 01/05: refactor(NetCDF): Move some logic for Grid sample dimension building from GridResource to Convention
Date Fri, 15 Feb 2019 19:23:45 GMT
This is an automated email from the ASF dual-hosted git repository.

desruisseaux pushed a commit to branch geoapi-4.0
in repository https://gitbox.apache.org/repos/asf/sis.git

commit 336d3018f96713c8f9ed1c188de1a1f72681ab7c
Author: Alexis Manin <alexis.manin@gmail.com>
AuthorDate: Thu Feb 14 17:39:09 2019 +0100

    refactor(NetCDF): Move some logic for Grid sample dimension building from GridResource
to Convention
    
    This will allow users to add custom behavior using a convention override, leading to better
management for multiple conventions.
---
 .../org/apache/sis/internal/netcdf/Convention.java | 40 +++++++++++
 .../apache/sis/storage/netcdf/GridResource.java    | 82 +++++++++++-----------
 2 files changed, 82 insertions(+), 40 deletions(-)

diff --git a/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/Convention.java
b/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/Convention.java
index a946200..14c3733 100644
--- a/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/Convention.java
+++ b/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/Convention.java
@@ -17,7 +17,11 @@
 package org.apache.sis.internal.netcdf;
 
 import java.util.Iterator;
+import java.util.Optional;
 import org.apache.sis.internal.referencing.LazySet;
+import org.apache.sis.measure.NumberRange;
+import org.apache.sis.referencing.operation.transform.TransferFunction;
+import ucar.nc2.constants.CDM;
 
 
 /**
@@ -119,4 +123,40 @@ public class Convention {
     public String[] namesOfAxisVariables(Variable variable) {
         return null;
     }
+
+    /**
+     * Build a function aiming to convert values packed in given variable into geophysical
measures.
+     *
+     * @param source The variable specifying the transfer function.
+     *
+     * @return A transfer function matching given variable. Note that if we cannot find any
information in input
+     * variable, we return an identity transform. Never null.
+     */
+    public TransferFunction getTransferFunction(final Variable source) {
+        /*
+         * 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 = source.getAttributeAsNumber(CDM.SCALE_FACTOR);
+        final double offset = source.getAttributeAsNumber(CDM.ADD_OFFSET);
+        if (!Double.isNaN(scale)) {
+            tr.setScale(scale);
+        }
+        if (!Double.isNaN(offset)) {
+            tr.setOffset(offset);
+        }
+
+        return tr;
+    }
+
+    /**
+     * Search in given variable for information about its range of valid values.
+     *
+     * @param source The variable to get valid range of values for.
+     * @return The range of expected measures, or nothing if we didn't find any related information.
+     */
+    public Optional<NumberRange<?>> getValidValues(final Variable source) {
+        return Optional.ofNullable(source.getValidValues());
+    }
 }
diff --git a/storage/sis-netcdf/src/main/java/org/apache/sis/storage/netcdf/GridResource.java
b/storage/sis-netcdf/src/main/java/org/apache/sis/storage/netcdf/GridResource.java
index fef9e5e..50f2540 100644
--- a/storage/sis-netcdf/src/main/java/org/apache/sis/storage/netcdf/GridResource.java
+++ b/storage/sis-netcdf/src/main/java/org/apache/sis/storage/netcdf/GridResource.java
@@ -40,6 +40,7 @@ import org.apache.sis.internal.storage.ResourceOnFileSystem;
 import org.apache.sis.coverage.SampleDimension;
 import org.apache.sis.coverage.grid.GridCoverage;
 import org.apache.sis.coverage.grid.GridDerivation;
+import org.apache.sis.internal.netcdf.Convention;
 import org.apache.sis.internal.raster.RasterFactory;
 import org.apache.sis.storage.DataStoreException;
 import org.apache.sis.storage.DataStoreContentException;
@@ -52,7 +53,6 @@ import org.apache.sis.util.Numbers;
 import org.apache.sis.util.resources.Errors;
 import org.apache.sis.util.resources.Vocabulary;
 import org.apache.sis.internal.util.UnmodifiableArrayList;
-import ucar.nc2.constants.CDM;                      // We use only String constants.
 
 
 /**
@@ -128,6 +128,12 @@ final class GridResource extends AbstractGridResource implements ResourceOnFileS
     private final Path location;
 
     /**
+     * Allow to fetch referencing information from source variables. It's mostly useful to
handle multiple
+     * NetCDF structures (CF, GCOM, etc.)
+     */
+    private final Convention convention;
+
+    /**
      * Creates a new resource. All variables in the {@code data} list shall have the same
domain and the same grid geometry.
      *
      * @param  decoder  the implementation used for decoding the netCDF file.
@@ -144,6 +150,7 @@ final class GridResource extends AbstractGridResource implements ResourceOnFileS
         gridGeometry = grid.getGridGeometry(decoder);
         identifier   = decoder.nameFactory.createLocalName(decoder.namespace, name);
         location     = decoder.location;
+        convention   = decoder.convention();
     }
 
     /**
@@ -263,51 +270,46 @@ final class GridResource extends AbstractGridResource implements ResourceOnFileS
         return UnmodifiableArrayList.wrap(ranges);
     }
 
+    private void addQuantitativeInfo(final SampleDimension.Builder target, NumberRange<?>
range, final Variable data) {
+        final TransferFunction tr = convention.getTransferFunction(data);
+        final MathTransform1D mt = tr.getTransform();
+        if (!mt.isIdentity() && range instanceof MeasurementRange<?>) {
+            /*
+             * Heuristic rule defined in UCAR documentation (see EnhanceScaleMissing interface):
+             * if the type of the range is equal to the type of the scale, and the type of
the
+             * data is not wider, then assume that the minimum and maximum are real values.
+             * This is identified in Apache SIS by the range given as a MeasurementRange.
+             */
+            final boolean isMinIncluded = range.isMinIncluded();
+            final boolean isMaxIncluded = range.isMaxIncluded();
+            double minimum = (range.getMinDouble() - tr.getOffset()) / tr.getScale();
+            double maximum = (range.getMaxDouble() - tr.getOffset()) / tr.getScale();
+            if (maximum < minimum) {
+                final double swap = maximum;
+                maximum = minimum;
+                minimum = swap;
+            }
+            if (data.getDataType().number < Numbers.FLOAT && minimum >= Long.MIN_VALUE
&& maximum <= Long.MAX_VALUE) {
+                range = NumberRange.create(Math.round(minimum), isMinIncluded, Math.round(maximum),
isMaxIncluded);
+            } else {
+                range = NumberRange.create(minimum, isMinIncluded, maximum, isMaxIncluded);
+            }
+        }
+        String name = data.getDescription();
+        if (name == null) name = data.getName();
+        target.addQuantitative(name, range, mt, data.getUnit());
+    }
+
     /**
      * Creates a single sample dimension for the given variable.
      *
      * @param  builder  the builder to use for creating the sample dimension.
      * @param  data     the data for which to create a sample dimension.
      */
-    private static SampleDimension createSampleDimension(final SampleDimension.Builder builder,
final Variable data) {
-        NumberRange<?> range = data.getValidValues();
-        if (range != null) {
-            /*
-             * 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);
-            final MathTransform1D mt = tr.getTransform();
-            if (!mt.isIdentity() && range instanceof MeasurementRange<?>) {
-                /*
-                 * Heuristic rule defined in UCAR documentation (see EnhanceScaleMissing
interface):
-                 * if the type of the range is equal to the type of the scale, and the type
of the
-                 * data is not wider, then assume that the minimum and maximum are real values.
-                 * This is identified in Apache SIS by the range given as a MeasurementRange.
-                 */
-                final boolean isMinIncluded = range.isMinIncluded();
-                final boolean isMaxIncluded = range.isMaxIncluded();
-                double minimum = (range.getMinDouble() - offset) / scale;
-                double maximum = (range.getMaxDouble() - offset) / scale;
-                if (maximum < minimum) {
-                    final double swap = maximum;
-                    maximum = minimum;
-                    minimum = swap;
-                }
-                if (data.getDataType().number < Numbers.FLOAT && minimum >=
Long.MIN_VALUE && maximum <= Long.MAX_VALUE) {
-                    range = NumberRange.create(Math.round(minimum), isMinIncluded, Math.round(maximum),
isMaxIncluded);
-                } else {
-                    range = NumberRange.create(minimum, isMinIncluded, maximum, isMaxIncluded);
-                }
-            }
-            String name = data.getDescription();
-            if (name == null) name = data.getName();
-            builder.addQuantitative(name, range, mt, data.getUnit());
-        }
+    private SampleDimension createSampleDimension(final SampleDimension.Builder builder,
final Variable data) {
+        convention.getValidValues(data)
+                .ifPresent(range -> addQuantitativeInfo(builder, range, data));
+
         /*
          * Adds the "missing value" or "fill value" as qualitative categories.  If a value
has both roles, use "missing value"
          * as category name. If the sample values are already real values, then the "no data"
values have been replaced by NaN


Mime
View raw message