You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@sis.apache.org by de...@apache.org on 2022/08/03 08:26:34 UTC

[sis] branch geoapi-4.0 updated (02d0e99b52 -> ac6a4fdb02)

This is an automated email from the ASF dual-hosted git repository.

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


    from 02d0e99b52 Add a "Pseudo sinusoidal" projection similar to Pseudo Mercator: use spherical formulas but apply the result on WGS84 ellipsoid.
     new a4f26d4229 Make the netCDF reader more robust to the case where a coordinate system axis has zero dimension. Such axes are omitted, but we need to adjust the number of dimensions accordingly.
     new ac6a4fdb02 Allow to fetch statistics in last resort if min/max are not specified in a netCDF file. This is disabled by default, because this operation is potentially costly.

The 2 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.


Summary of changes:
 .../java/org/apache/sis/internal/netcdf/Grid.java  | 31 +++++++++-------------
 .../org/apache/sis/internal/netcdf/Variable.java   | 10 ++++++-
 .../apache/sis/internal/netcdf/impl/GridInfo.java  | 19 +++++++------
 .../sis/internal/netcdf/impl/package-info.java     |  2 +-
 .../sis/internal/netcdf/ucar/GridWrapper.java      | 29 ++++++++++----------
 .../apache/sis/storage/netcdf/MetadataReader.java  | 21 +++++++--------
 .../org/apache/sis/internal/netcdf/GridTest.java   |  6 ++---
 .../sis/internal/netcdf/impl/GridInfoTest.java     |  4 +--
 .../sis/internal/storage/StoreUtilities.java       | 13 ++++++++-
 .../apache/sis/internal/storage/package-info.java  |  2 +-
 10 files changed, 74 insertions(+), 63 deletions(-)


[sis] 01/02: Make the netCDF reader more robust to the case where a coordinate system axis has zero dimension. Such axes are omitted, but we need to adjust the number of dimensions accordingly.

Posted by de...@apache.org.
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 a4f26d4229b3bc599f26bbf8c8f3805a01608de7
Author: Martin Desruisseaux <ma...@geomatys.com>
AuthorDate: Tue Aug 2 14:55:35 2022 +0200

    Make the netCDF reader more robust to the case where a coordinate system axis has zero dimension.
    Such axes are omitted, but we need to adjust the number of dimensions accordingly.
---
 .../java/org/apache/sis/internal/netcdf/Grid.java  | 31 +++++++++-------------
 .../apache/sis/internal/netcdf/impl/GridInfo.java  | 19 +++++++------
 .../sis/internal/netcdf/impl/package-info.java     |  2 +-
 .../sis/internal/netcdf/ucar/GridWrapper.java      | 29 ++++++++++----------
 .../apache/sis/storage/netcdf/MetadataReader.java  | 21 +++++++--------
 .../org/apache/sis/internal/netcdf/GridTest.java   |  6 ++---
 .../sis/internal/netcdf/impl/GridInfoTest.java     |  4 +--
 7 files changed, 52 insertions(+), 60 deletions(-)

diff --git a/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/Grid.java b/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/Grid.java
index 71af070182..0438456f1a 100644
--- a/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/Grid.java
+++ b/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/Grid.java
@@ -48,7 +48,7 @@ import org.apache.sis.util.ArraysExt;
  * if a variable dimensions should considered as bands instead of spatiotemporal dimensions.
  *
  * @author  Martin Desruisseaux (Geomatys)
- * @version 1.2
+ * @version 1.3
  *
  * @see Decoder#getGridCandidates()
  *
@@ -144,20 +144,17 @@ public abstract class Grid extends NamedElement {
      * This is the number of dimensions of the <em>grid</em>.
      * It should be equal to the size of {@link #getDimensions()} list.
      *
+     * <h4>Note on target dimensions</h4>
+     * A {@code getTargetDimensions()} method would return the number of dimensions of the
+     * <em>coordinate reference system</em>, which is the target of the <cite>"grid to CRS"</cite> conversion.
+     * However we do not provide that method because, while it should be equal to {@code getAxes(decoder).length},
+     * it sometime differs because {@link #getAxes(Decoder)} may exclude axis with zero dimensions.
+     * The latter method should be used as the authoritative one.
+     *
      * @return number of grid dimensions.
      */
     public abstract int getSourceDimensions();
 
-    /**
-     * Returns the number of dimensions of target coordinates in the <cite>"grid to CRS"</cite> conversion.
-     * This is the number of dimensions of the <em>coordinate reference system</em>.
-     * It should be equal to the length of the array returned by {@link #getAxes(Decoder)},
-     * but caller should be robust to inconsistencies.
-     *
-     * @return number of CRS dimensions.
-     */
-    public abstract int getTargetDimensions();
-
     /**
      * Returns the dimensions of this grid, in netCDF (reverse of "natural") order. Each element in the list
      * contains the number of cells in the dimension, together with implementation-specific information.
@@ -182,10 +179,8 @@ public abstract class Grid extends NamedElement {
     protected abstract List<Dimension> getDimensions();
 
     /**
-     * Returns the axes of the coordinate reference system. The size of this array is expected equals to the
-     * value returned by {@link #getTargetDimensions()}, but the caller should be robust to inconsistencies.
-     * The axis order is CRS order (reverse of netCDF order) for consistency with the common practice in the
-     * {@code "coordinates"} attribute.
+     * Returns the axes of the coordinate reference system. The axis order is CRS order (reverse of netCDF order)
+     * for consistency with the common practice in the {@code "coordinates"} attribute.
      *
      * <p>This method returns a direct reference to the cached array; do not modify.</p>
      *
@@ -397,9 +392,9 @@ public abstract class Grid extends NamedElement {
              * (the source) +1, and the number of rows is the number of dimensions in the CRS (the target) +1.
              * The order of dimensions in the transform is the reverse of the netCDF dimension order.
              */
-            int lastSrcDim = getSourceDimensions();                         // Will be decremented later, then kept final.
-            int lastTgtDim = getTargetDimensions();
-            final int[] deferred = new int[axes.length];                    // Indices of axes that have been deferred.
+            int lastSrcDim = getSourceDimensions();         // Will be decremented later, then kept final.
+            int lastTgtDim = axes.length;                   // Should be `getTargetDimensions()` but some axes may have been excluded.
+            final int[] deferred = new int[axes.length];    // Indices of axes that have been deferred.
             final List<MathTransform> nonLinears = new ArrayList<>(axes.length);
             final Matrix affine = Matrices.createZero(lastTgtDim + 1, lastSrcDim + 1);
             affine.setElement(lastTgtDim--, lastSrcDim--, 1);
diff --git a/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/impl/GridInfo.java b/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/impl/GridInfo.java
index 27c97fd734..f41c864edf 100644
--- a/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/impl/GridInfo.java
+++ b/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/impl/GridInfo.java
@@ -42,7 +42,7 @@ import ucar.nc2.constants.CF;
  *
  * @author  Martin Desruisseaux (Geomatys)
  * @author  Johann Sorel (Geomatys)
- * @version 1.0
+ * @version 1.3
  * @since   0.3
  * @module
  */
@@ -120,16 +120,15 @@ final class GridInfo extends Grid {
         return domain.length;
     }
 
-    /**
-     * Returns the number of dimensions of target coordinates in the <cite>"grid to CRS"</cite> conversion.
-     * This is the number of dimensions of the <em>coordinate reference system</em>.
-     * It should be equal to the size of the array returned by {@link #getAxes(Decoder)},
-     * but caller should be robust to inconsistencies.
+    /*
+     * A `getTargetDimensions()` method would be like below, but is
+     * excluded because `getAxes(…).length` is the authoritative value:
+     *
+     *     @Override
+     *     public int getTargetDimensions() {
+     *         return range.length;
+     *     }
      */
-    @Override
-    public int getTargetDimensions() {
-        return range.length;
-    }
 
     /**
      * Returns the dimensions of this grid, in netCDF (reverse of "natural") order.
diff --git a/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/impl/package-info.java b/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/impl/package-info.java
index 2319110d21..c44733af16 100644
--- a/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/impl/package-info.java
+++ b/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/impl/package-info.java
@@ -30,7 +30,7 @@
  *
  * @author  Johann Sorel (Geomatys)
  * @author  Martin Desruisseaux (Geomatys)
- * @version 1.0
+ * @version 1.3
  * @since   0.3
  * @module
  */
diff --git a/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/ucar/GridWrapper.java b/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/ucar/GridWrapper.java
index 2d0cde99b6..2eb9b2a8fc 100644
--- a/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/ucar/GridWrapper.java
+++ b/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/ucar/GridWrapper.java
@@ -45,7 +45,7 @@ import org.apache.sis.util.ArraysExt;
  * Many netCDF variables may be associated to the same {@code GridWrapper} instance.</p>
  *
  * @author  Martin Desruisseaux (Geomatys)
- * @version 1.1
+ * @version 1.3
  * @since   0.3
  * @module
  */
@@ -193,16 +193,15 @@ final class GridWrapper extends Grid {
         return netcdfCS.getRankDomain();
     }
 
-    /**
-     * Returns the number of dimensions of target coordinates in the <cite>"grid to CRS"</cite> conversion.
-     * This is the number of dimensions of the <em>coordinate reference system</em>.
-     * It should be equal to the length of the array returned by {@link #getAxes(Decoder)},
-     * but caller should be robust to inconsistencies.
+    /*
+     * A `getTargetDimensions()` method would be like below, but is
+     * excluded because `getAxes(…).length` is the authoritative value:
+     *
+     *     @Override
+     *     public int getTargetDimensions() {
+     *         return netcdfCS.getRankRange();
+     *     }
      */
-    @Override
-    public int getTargetDimensions() {
-        return netcdfCS.getRankRange();
-    }
 
     /**
      * Returns the dimensions of this grid, in netCDF (reverse of "natural") order.
@@ -257,9 +256,9 @@ next:       for (final String name : axisNames) {
          * In this method, `sourceDim` and `targetDim` are relative to "grid to CRS" conversion.
          * So `sourceDim` is the grid (domain) dimension and `targetDim` is the CRS (range) dimension.
          */
+        int axisCount = 0;
         int targetDim = range.size();
         final Axis[] axes = new Axis[targetDim];
-        final int lastDim = targetDim - 1;
         while (--targetDim >= 0) {
             final CoordinateAxis axis = range.get(targetDim);
             final Variable wrapper = ((DecoderWrapper) decoder).getWrapperFor(axis);
@@ -307,9 +306,11 @@ next:       for (final String name : axisNames) {
                  * package, we can proceed as if the dimension does not exist (`i` not incremented).
                  */
             }
-            axes[lastDim - targetDim] = new Axis(abbreviation, axis.getPositive(),
-                    ArraysExt.resize(indices, i), ArraysExt.resize(sizes, i), wrapper);
+            if (i != 0) {   // Variables with 0 dimensions sometime happen.
+                axes[axisCount++] = new Axis(abbreviation, axis.getPositive(),
+                        ArraysExt.resize(indices, i), ArraysExt.resize(sizes, i), wrapper);
+            }
         }
-        return axes;
+        return ArraysExt.resize(axes, axisCount);
     }
 }
diff --git a/storage/sis-netcdf/src/main/java/org/apache/sis/storage/netcdf/MetadataReader.java b/storage/sis-netcdf/src/main/java/org/apache/sis/storage/netcdf/MetadataReader.java
index 15c099b14b..d4996187bc 100644
--- a/storage/sis-netcdf/src/main/java/org/apache/sis/storage/netcdf/MetadataReader.java
+++ b/storage/sis-netcdf/src/main/java/org/apache/sis/storage/netcdf/MetadataReader.java
@@ -113,7 +113,7 @@ import static org.apache.sis.internal.util.CollectionsExt.first;
  * @author  Martin Desruisseaux (Geomatys)
  * @author  Thi Phuong Hao Nguyen (VNSC)
  * @author  Alexis Manin (Geomatys)
- * @version 1.2
+ * @version 1.3
  * @since   0.3
  * @module
  */
@@ -684,17 +684,13 @@ split:  while ((start = CharSequences.skipLeadingWhitespaces(value, start, lengt
     /**
      * Adds information about axes and cell geometry.
      * This is the {@code <mdb:spatialRepresentationInfo>} element in XML.
+     * We work on grid axes instead of Coordinate Reference System axes because
+     * {@code metadata/spatialRepresentationInfo/axisDimensionProperties/dimensionSize} seems to imply that.
      *
      * @param  cs  the grid geometry (related to the netCDF coordinate system).
      * @throws ArithmeticException if the size of an axis exceeds {@link Integer#MAX_VALUE}, or other overflow occurs.
      */
-    private void addSpatialRepresentationInfo(final Grid cs) throws IOException, DataStoreException {
-        /*
-         * We work on grid axes instead of Coordinate Reference System axes because
-         * `metadata/spatialRepresentationInfo/axisDimensionProperties/dimensionSize`
-         * seems to imply that.
-         */
-        final Axis[] axes = cs.getAxes(decoder);
+    private void addSpatialRepresentationInfo(final Axis[] axes) throws IOException, DataStoreException {
         for (int i=0; i<axes.length; i++) {
             final Axis axis = axes[i];
             /*
@@ -1059,10 +1055,11 @@ split:  while ((start = CharSequences.skipLeadingWhitespaces(value, start, lengt
          * is built from the netCDF CoordinateSystem objects.
          */
         for (final Grid cs : decoder.getGridCandidates()) {
-            if (cs.getSourceDimensions() >= Grid.MIN_DIMENSION &&
-                cs.getTargetDimensions() >= Grid.MIN_DIMENSION)
-            {
-                addSpatialRepresentationInfo(cs);
+            if (cs.getSourceDimensions() >= Grid.MIN_DIMENSION) {
+                final Axis[] axes = cs.getAxes(decoder);
+                if (axes.length >= Grid.MIN_DIMENSION) {
+                    addSpatialRepresentationInfo(axes);
+                }
             }
         }
         setISOStandards(hasGridCoverages);
diff --git a/storage/sis-netcdf/src/test/java/org/apache/sis/internal/netcdf/GridTest.java b/storage/sis-netcdf/src/test/java/org/apache/sis/internal/netcdf/GridTest.java
index f9f487d1e1..7f14447fb2 100644
--- a/storage/sis-netcdf/src/test/java/org/apache/sis/internal/netcdf/GridTest.java
+++ b/storage/sis-netcdf/src/test/java/org/apache/sis/internal/netcdf/GridTest.java
@@ -63,7 +63,7 @@ public strictfp class GridTest extends TestCase {
     }
 
     /**
-     * Tests {@link Grid#getSourceDimensions()} and {@link Grid#getTargetDimensions()}.
+     * Tests {@link Grid#getSourceDimensions()} and {@code Grid.getTargetDimensions()}.
      *
      * @throws IOException if an I/O error occurred while opening the file.
      * @throws DataStoreException if a logical error occurred.
@@ -72,12 +72,12 @@ public strictfp class GridTest extends TestCase {
     public void testDimensions() throws IOException, DataStoreException {
         Grid geometry = getSingleton(filter(selectDataset(TestData.NETCDF_2D_GEOGRAPHIC).getGridCandidates()));
         assertEquals("getSourceDimensions()", 2, geometry.getSourceDimensions());
-        assertEquals("getTargetDimensions()", 2, geometry.getTargetDimensions());
+        assertEquals("getTargetDimensions()", 2, geometry.getAxes(decoder()).length);
 
         final int n = includeRuntimeDimension ? 5 : 4;
         geometry = getSingleton(filter(selectDataset(TestData.NETCDF_4D_PROJECTED).getGridCandidates()));
         assertEquals("getSourceDimensions()", 4, geometry.getSourceDimensions());
-        assertEquals("getTargetDimensions()", n, geometry.getTargetDimensions());
+        assertEquals("getTargetDimensions()", n, geometry.getAxes(decoder()).length);
     }
 
     /**
diff --git a/storage/sis-netcdf/src/test/java/org/apache/sis/internal/netcdf/impl/GridInfoTest.java b/storage/sis-netcdf/src/test/java/org/apache/sis/internal/netcdf/impl/GridInfoTest.java
index 3ed876279a..e084c7b054 100644
--- a/storage/sis-netcdf/src/test/java/org/apache/sis/internal/netcdf/impl/GridInfoTest.java
+++ b/storage/sis-netcdf/src/test/java/org/apache/sis/internal/netcdf/impl/GridInfoTest.java
@@ -34,7 +34,7 @@ import org.opengis.test.dataset.TestData;
  * passed.
  *
  * @author  Martin Desruisseaux (Geomatys)
- * @version 1.1
+ * @version 1.3
  * @since   0.3
  * @module
  */
@@ -70,7 +70,7 @@ public final strictfp class GridInfoTest extends GridTest {
         final Grid[] copy = new Grid[geometries.length];
         int count = 0;
         for (final Grid geometry : geometries) {
-            if (geometry.getSourceDimensions() != 1 || geometry.getTargetDimensions() != 1) {
+            if (geometry.getSourceDimensions() != 1) {
                 copy[count++] = geometry;
             }
         }


[sis] 02/02: Allow to fetch statistics in last resort if min/max are not specified in a netCDF file. This is disabled by default, because this operation is potentially costly.

Posted by de...@apache.org.
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 ac6a4fdb0219c1ecceba890a50e81e4caea8161c
Author: Martin Desruisseaux <ma...@geomatys.com>
AuthorDate: Tue Aug 2 16:28:06 2022 +0200

    Allow to fetch statistics in last resort if min/max are not specified in a netCDF file.
    This is disabled by default, because this operation is potentially costly.
---
 .../main/java/org/apache/sis/internal/netcdf/Variable.java  | 10 +++++++++-
 .../org/apache/sis/internal/storage/StoreUtilities.java     | 13 ++++++++++++-
 .../java/org/apache/sis/internal/storage/package-info.java  |  2 +-
 3 files changed, 22 insertions(+), 3 deletions(-)

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 6bbb896069..4305b22bfa 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
@@ -48,13 +48,15 @@ import org.apache.sis.util.resources.Errors;
 import ucar.nc2.constants.CDM;                      // We use only String constants.
 import ucar.nc2.constants.CF;
 
+import static org.apache.sis.internal.storage.StoreUtilities.ALLOW_LAST_RESORT_STATISTICS;
+
 
 /**
  * A netCDF variable created by {@link Decoder}.
  *
  * @author  Martin Desruisseaux (Geomatys)
  * @author  Johann Sorel (Geomatys)
- * @version 1.1
+ * @version 1.3
  * @since   0.3
  * @module
  */
@@ -851,6 +853,12 @@ public abstract class Variable extends Node {
         NumberRange<?> range = decoder.convention().validRange(this);
         if (range == null) {
             range = getRangeFallback();
+            if (ALLOW_LAST_RESORT_STATISTICS && range == null) try {
+                range = read().range();
+            } catch (DataStoreException | IOException e) {
+                // It should be a fatal error, but maybe the user wants only metadata.
+                error(Variable.class, "getValidRange", e, Errors.Keys.CanNotRead_1, getName());
+            }
         }
         return range;
     }
diff --git a/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/StoreUtilities.java b/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/StoreUtilities.java
index cd8fd65d9a..eaeb355bab 100644
--- a/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/StoreUtilities.java
+++ b/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/StoreUtilities.java
@@ -62,11 +62,22 @@ import org.opengis.feature.Feature;
  * Some methods may also move in public API if we feel confident enough.
  *
  * @author  Martin Desruisseaux (Geomatys)
- * @version 1.2
+ * @version 1.3
  * @since   1.0
  * @module
  */
 public final class StoreUtilities extends Static {
+    /**
+     * Whether to allow computation of statistics when no minimum/maximum values can be determined.
+     * This is a costly operation because it requires loading all data, so any code enabled by this
+     * flag should be executed in last resort only.
+     *
+     * <p>This flag can be set to {@code true} for exploring data that we can not visualize otherwise.
+     * But it should generally stay to {@code false}, because otherwise browsing resource metadata can
+     * become as costly (slow and high memory usage) as visualizing the full raster.</p>
+     */
+    public static final boolean ALLOW_LAST_RESORT_STATISTICS = false;
+
     /**
      * Logger for the {@value Modules#STORAGE} module. This is used when no more specific logger is available,
      * or if the more specific logger is not appropriate (e.g. because the log message come from base class).
diff --git a/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/package-info.java b/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/package-info.java
index d07eeacb65..a110dc7d1f 100644
--- a/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/package-info.java
+++ b/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/package-info.java
@@ -25,7 +25,7 @@
  *
  * @author  Martin Desruisseaux (Geomatys)
  * @author  Johann Sorel (Geomatys)
- * @version 1.2
+ * @version 1.3
  * @since   0.4
  * @module
  */