sis-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From desruisse...@apache.org
Subject [sis] branch geoapi-4.0 updated: If a netCDF variable contains "flag_names" or "flag_meanings" attribute, create categories for enumeration values instead than for the range of quantitative values.
Date Thu, 18 Apr 2019 16:59:27 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


The following commit(s) were added to refs/heads/geoapi-4.0 by this push:
     new 6f2b61e  If a netCDF variable contains "flag_names" or "flag_meanings" attribute,
create categories for enumeration values instead than for the range of quantitative values.
6f2b61e is described below

commit 6f2b61ef7e549ce2958139dcfa938d0126f2956f
Author: Martin Desruisseaux <martin.desruisseaux@geomatys.com>
AuthorDate: Thu Apr 18 16:15:53 2019 +0200

    If a netCDF variable contains "flag_names" or "flag_meanings" attribute, create categories
for enumeration values instead than for the range of quantitative values.
---
 .../org/apache/sis/internal/netcdf/Convention.java |  8 ++---
 .../apache/sis/internal/netcdf/RasterResource.java | 41 ++++++++++++++++++++--
 .../org/apache/sis/internal/netcdf/Variable.java   |  8 ++---
 .../sis/internal/netcdf/impl/VariableInfo.java     | 18 +++++-----
 .../sis/internal/netcdf/ucar/VariableWrapper.java  | 10 +++---
 5 files changed, 61 insertions(+), 24 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 17d8877..da1e979 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
@@ -320,7 +320,7 @@ public class Convention {
      *
      * Whether the returned range is a range of packed values or a range of real values is
ambiguous.
      * An heuristic rule is documented in UCAR {@link ucar.nc2.dataset.EnhanceScaleMissing}
interface.
-     * If both type of ranges are available, then this method should return the range of
packed value.
+     * If both types of range are available, then this method should return the range of
packed value.
      * Otherwise if this method returns the range of real values, then that range shall be
an instance
      * of {@link MeasurementRange} for allowing the caller to distinguish the two cases.
      *
@@ -428,9 +428,9 @@ public class Convention {
      * 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 only if {@link #validRange(Variable)} returned a non-null
value.
-     * Since a transfer function is assumed to exist in such case (even if that function
is identity),
-     * this method shall never return {@code null}.</p>
+     * <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.
diff --git a/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/RasterResource.java
b/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/RasterResource.java
index e384680..08ffea1 100644
--- a/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/RasterResource.java
+++ b/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/RasterResource.java
@@ -37,6 +37,7 @@ import org.apache.sis.coverage.grid.GridExtent;
 import org.apache.sis.coverage.grid.GridCoverage;
 import org.apache.sis.coverage.grid.GridGeometry;
 import org.apache.sis.coverage.grid.GridDerivation;
+import org.apache.sis.storage.netcdf.AttributeNames;
 import org.apache.sis.storage.DataStoreException;
 import org.apache.sis.storage.DataStoreContentException;
 import org.apache.sis.storage.DataStoreReferencingException;
@@ -45,6 +46,7 @@ import org.apache.sis.math.MathFunctions;
 import org.apache.sis.measure.MeasurementRange;
 import org.apache.sis.measure.NumberRange;
 import org.apache.sis.util.Numbers;
+import org.apache.sis.util.CharSequences;
 import org.apache.sis.util.resources.Errors;
 import org.apache.sis.util.resources.Vocabulary;
 import org.apache.sis.internal.jdk9.JDK9;
@@ -398,8 +400,8 @@ public final class RasterResource extends AbstractGridResource implements
Resour
          * is used only as a fallback. We give precedence to the range computed by Apache
SIS instead than the range given
          * by UCAR because we need the range of packed values instead than the range of converted
values.
          */
-        NumberRange<?> range = band.getValidRange();
-        if (range != null) {
+        NumberRange<?> range;
+        if (!createEnumeration(builder, band, index) && (range = band.getValidRange())
!= null) {
             final MathTransform1D mt = band.getTransferFunction().getTransform();
             if (!mt.isIdentity() && range instanceof MeasurementRange<?>) {
                 /*
@@ -490,6 +492,41 @@ public final class RasterResource extends AbstractGridResource implements
Resour
     }
 
     /**
+     * Appends qualitative categories in the given builder for {@code "flag_values"} or {@code
"flag_masks"} attribute.
+     *
+     * @param  builder  the builder to use for creating the sample dimension.
+     * @param  band     the data for which to create a sample dimension.
+     * @param  index    index in the variable dimension identified by {@link #bandDimension}.
+     * @return {@code true} if flag attributes have been found, or {@code false} otherwise.
+     */
+    private static boolean createEnumeration(final SampleDimension.Builder builder, final
Variable band, final int index) {
+        Object[] names = band.getAttributeValues(AttributeNames.FLAG_NAMES, false);
+        if (names.length == 0) {
+            names = band.getAttributeValues(AttributeNames.FLAG_MEANINGS, false);
+            if (names.length == 0) return false;
+        }
+        Object[] values = band.getAttributeValues(AttributeNames.FLAG_VALUES, true);
+        if (values.length == 0) {
+            values = band.getAttributeValues(AttributeNames.FLAG_MASKS, true);
+            if (values.length == 0) return false;
+        }
+        if (names.length == 1) {
+            names = CharSequences.split((CharSequence) names[0], ' ');
+        }
+        for (int i=0; i<values.length; i++) {
+            final Number value = (Number) values[i];
+            final CharSequence name;
+            if (i < names.length) {
+                name = (CharSequence) names[i];
+            } else {
+                name = Vocabulary.formatInternational(Vocabulary.Keys.Unnamed);
+            }
+            builder.addQualitative(name, value, value);
+        }
+        return true;
+    }
+
+    /**
      * Loads a subset of the grid coverage represented by this resource.
      *
      * @param  domain  desired grid extent and resolution, or {@code null} for reading the
whole domain.
diff --git a/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/Variable.java
b/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/Variable.java
index a0f9737..e2d74b8 100644
--- a/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/Variable.java
+++ b/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/Variable.java
@@ -799,15 +799,15 @@ public abstract class Variable extends NamedElement {
     public abstract Collection<String> getAttributeNames();
 
     /**
-     * Returns the numeric type of the attribute of the given name, or {@code null}
-     * if the given attribute is not found or its value is not numeric.
+     * Returns the type of the attribute of the given name,
+     * or {@code null} if the given attribute is not found.
      *
      * @param  attributeName  the name of the attribute for which to get the type.
-     * @return type of the given attribute, or {@code null} if none or not numeric.
+     * @return type of the given attribute, or {@code null} if the attribute does not exist.
      *
      * @see #getDataType()
      */
-    public abstract Class<? extends Number> getAttributeType(String attributeName);
+    public abstract Class<?> getAttributeType(String attributeName);
 
     /**
      * Returns the sequence of values for the given attribute, or an empty array if none.
diff --git a/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/impl/VariableInfo.java
b/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/impl/VariableInfo.java
index 1d58f8a..40e8fc6 100644
--- a/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/impl/VariableInfo.java
+++ b/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/impl/VariableInfo.java
@@ -176,6 +176,10 @@ final class VariableInfo extends Variable implements Comparable<VariableInfo>
{
      *
      * @see #isEnumeration()
      * @see #meaning(int)
+     *
+     * @todo Need to be consistent with {@code VariableWrapper}. We could move this field
to {@link FeaturesInfo},
+     *       or provides the same functionality in {@code VariableWrapper}. Whatever solution
is chosen,
+     *       {@code RasterResource.createEnumeration(…)} needs to use the mechanism common
to both implementations.
      */
     private final String[] meanings;
 
@@ -510,20 +514,16 @@ final class VariableInfo extends Variable implements Comparable<VariableInfo>
{
     }
 
     /**
-     * Returns the numeric type of the attribute of the given name, or {@code null}
-     * if the given attribute is not found or its value is not numeric.
+     * Returns the type of the attribute of the given name,
+     * or {@code null} if the given attribute is not found.
      */
     @Override
-    @SuppressWarnings("unchecked")
-    public Class<? extends Number> getAttributeType(final String attributeName) {
+    public Class<?> getAttributeType(final String attributeName) {
         final Object value = getAttributeValue(attributeName);
         if (value != null) {
-            Class<?> type = value.getClass();
+            final Class<?> type = value.getClass();
             final Class<?> c = type.getComponentType();
-            if (c != null) type = c;
-            if (Number.class.isAssignableFrom(type)) {
-                return (Class<? extends Number>) type;
-            }
+            return (c != null) ? c : type;
         }
         return null;
     }
diff --git a/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/ucar/VariableWrapper.java
b/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/ucar/VariableWrapper.java
index 74de8e9..39f25c1 100644
--- a/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/ucar/VariableWrapper.java
+++ b/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/ucar/VariableWrapper.java
@@ -298,13 +298,11 @@ final class VariableWrapper extends Variable {
     }
 
     /**
-     * Returns the numeric type of the attribute of the given name, or {@code null}
-     * if the given attribute is not found or its value is not numeric.
-     *
-     * @see #getDataType()
+     * Returns the type of the attribute of the given name,
+     * or {@code null} if the given attribute is not found.
      */
     @Override
-    public Class<? extends Number> getAttributeType(final String attributeName) {
+    public Class<?> getAttributeType(final String attributeName) {
         final Attribute attribute = raw.findAttributeIgnoreCase(attributeName);
         if (attribute != null) {
             switch (attribute.getDataType()) {
@@ -314,6 +312,8 @@ final class VariableWrapper extends Variable {
                 case LONG:   return Long.class;
                 case FLOAT:  return Float.class;
                 case DOUBLE: return Double.class;
+                case STRING: return String.class;
+                default:     return Object.class;
             }
         }
         return null;


Mime
View raw message