3

I have two very similar NetCDFs. "temp_4.nc", that I can load into GeoServer, and "temp_5_e.nc", that I can't. Both file have a single data variable "temp". In the first one, it has dimensions (time, Z, lat, lon) and the second one has a dimension more (scen, time, Z, lat, lon).

I think my problem is that this extra dimension is not recognized by GeoServer. I tried adding attributes "axis: Z" and "units: m" (dim Z has the same attributes). As it didn't work, I also tried "axis: E" (ensemble) and no units.

When I try to create a store, I get the following error:

Could not list layers for this store, an error occurred retrieving them: Failed to create reader from file:///geodata/temp_5_e.nc and hints Hints: REPOSITORY = org.geoserver.catalog.CatalogRepository@42b74f33 EXECUTOR_SERVICE = java.util.concurrent.ThreadPoolExecutor@1bf473ef[Running, pool size = 0, active threads = 0, queued tasks = 0, completed tasks = 0] System defaults: LENIENT_DATUM_SHIFT = true FORCE_AXIS_ORDER_HONORING = http GRID_COVERAGE_FACTORY = GridCoverageFactory TILE_ENCODING = null FEATURE_FACTORY = org.geotools.feature.LenientFeatureFactoryImpl@702a025e STYLE_FACTORY = StyleFactoryImpl FILTER_FACTORY = FilterFactoryImpl COMPARISON_TOLERANCE = 1.0E-8 FORCE_LONGITUDE_FIRST_AXIS_ORDER = true 

And in the GeoServer log, I get a few miles of text. The full log is here : https://pastebin.com/2GZ4myYu.

11 Mar 21:24:15 WARN [imageio.netcdf] - Unsupported axis: long scen(scen=5);
  :axis = "E";
 in input: file:/geodata/temp_5_e.nc has been found
11 Mar 21:24:15 WARN [io.netcdf] - Unable to connect
org.geotools.data.DataSourceException: Unable to connect
    at org.geotools.coverage.io.netcdf.NetCDFReader.<init>(NetCDFReader.java:158)
    at org.geotools.coverage.io.netcdf.NetCDFFormat.getReader(NetCDFFormat.java:94)
    at org.geoserver.catalog.ResourcePool.getGridCoverageReader(ResourcePool.java:1571)
    at org.geoserver.catalog.ResourcePool.getGridCoverageReader(ResourcePool.java:1516)
    [truncated output]
11 Mar 21:24:15 INFO [geoserver.web] - Getting list of coverages for saved store file:///geodata/temp_5_e.nc
java.lang.RuntimeException: Could not list layers for this store, an error occurred retrieving them: Failed to create reader from file:///geodata/temp_5_e.nc and hints Hints:
  REPOSITORY       = org.geoserver.catalog.CatalogRepository@42b74f33                                                                                   
  EXECUTOR_SERVICE = java.util.concurrent.ThreadPoolExecutor@1bf473ef[Running, pool size = 0, active threads = 0, queued tasks = 0, completed tasks = 0]
System defaults:
  LENIENT_DATUM_SHIFT              = true                                                   
  FORCE_AXIS_ORDER_HONORING        = http                                                   
  GRID_COVERAGE_FACTORY            = GridCoverageFactory                                    
    TILE_ENCODING                  = null                                                   
  FEATURE_FACTORY                  = org.geotools.feature.LenientFeatureFactoryImpl@702a025e
  STYLE_FACTORY                    = StyleFactoryImpl                                       
  FILTER_FACTORY                   = FilterFactoryImpl                                      
  COMPARISON_TOLERANCE             = 1.0E-8                                                 
  FORCE_LONGITUDE_FIRST_AXIS_ORDER = true                                                   

[truncated output]

Caused by: java.io.IOException: Failed to create reader from file:///geodata/temp_5_e.nc and hints Hints:
  REPOSITORY       = org.geoserver.catalog.CatalogRepository@42b74f33                                                                                   
  EXECUTOR_SERVICE = java.util.concurrent.ThreadPoolExecutor@1bf473ef[Running, pool size = 0, active threads = 0, queued tasks = 0, completed tasks = 0]
System defaults:
  LENIENT_DATUM_SHIFT              = true                                                   
  FORCE_AXIS_ORDER_HONORING        = http                                                   
  GRID_COVERAGE_FACTORY            = GridCoverageFactory                                    
    TILE_ENCODING                  = null                                                   
  FEATURE_FACTORY                  = org.geotools.feature.LenientFeatureFactoryImpl@702a025e
  STYLE_FACTORY                    = StyleFactoryImpl                                       
  FILTER_FACTORY                   = FilterFactoryImpl                                      
  COMPARISON_TOLERANCE             = 1.0E-8                                                 
  FORCE_LONGITUDE_FIRST_AXIS_ORDER = true                                                   

    at org.geoserver.catalog.ResourcePool.getGridCoverageReader(ResourcePool.java:1573)
    at org.geoserver.catalog.ResourcePool.getGridCoverageReader(ResourcePool.java:1516)
    at org.geoserver.catalog.impl.CoverageStoreInfoImpl.getGridCoverageReader(CoverageStoreInfoImpl.java:57)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.base/java.lang.reflect.Method.invoke(Method.java:566)
    at org.geoserver.catalog.impl.ModificationProxy.invoke(ModificationProxy.java:129)
    at com.sun.proxy.$Proxy42.getGridCoverageReader(Unknown Source)
    at org.geoserver.web.data.layer.NewLayerPageProvider.getItemsInternal(NewLayerPageProvider.java:98)
    ... 147 more

Anyone has any idea of what's going on? How can I add 5D netCDf to geoserver?

I was guessing that the warning at the very top might be the reason for this error? How should I set this fifth coordinate so that geotools can understand it?


Below if the python code (with xarray) to generate the netcdf files:

import xarray as xr
import numpy as np

ds = xr.DataArray(
    np.random.sample((5,5,5,5,5)),
    dims=('scen', 'time', 'Z', 'lat', 'lon'),
    coords={
        'time': xr.cftime_range('1900-01-01', freq='D', periods=5),
        'Z': xr.DataArray(np.arange(5), dims=('Z',), attrs={'axis': 'Z', 'units': 'm'}, name='Z'),
        'lat': xr.DataArray(np.arange(5), dims=('lat',), attrs={'axis': 'Y', 'units': 'degrees_north'}, name='lat'),
        'lon': xr.DataArray(np.arange(5), dims=('lon',), attrs={'axis': 'X', 'units': 'degrees_east'}, name='lon'),
        'scen': xr.DataArray(np.arange(5), dims=('scen',), attrs={'axis': 'E'}, name='scen')
    },
    name='temp'
).to_netcdf('temp_5_e.nc')

Comment the 'scen' line and remove one 5 from the random data to get the (working) 4D case.

And the output of ncdump for each file:

# ncdump -sh temp_4.nc
netcdf temp_4 {
dimensions:
    time = 5 ;
    Z = 5 ;
    lat = 5 ;
    lon = 5 ;
variables:
    int64 time(time) ;
        time:units = "days since 1900-01-01 00:00:00.000000" ;
        time:calendar = "gregorian" ;
        time:_Storage = "contiguous" ;
        time:_Endianness = "little" ;
    int64 Z(Z) ;
        Z:axis = "Z" ;
        Z:units = "m" ;
        Z:_Storage = "contiguous" ;
        Z:_Endianness = "little" ;
    int64 lat(lat) ;
        lat:axis = "Y" ;
        lat:units = "degrees_north" ;
        lat:_Storage = "contiguous" ;
        lat:_Endianness = "little" ;
    int64 lon(lon) ;
        lon:axis = "X" ;
        lon:units = "degrees_east" ;
        lon:_Storage = "contiguous" ;
        lon:_Endianness = "little" ;
    double temp(time, Z, lat, lon) ;
        temp:_FillValue = NaN ;
        temp:_Storage = "contiguous" ;
        temp:_Endianness = "little" ;

// global attributes:
        :_NCProperties = "version=2,netcdf=4.7.4,hdf5=1.12.0," ;
        :_SuperblockVersion = 0 ;
        :_IsNetcdf4 = 1 ;
        :_Format = "netCDF-4" ;
}

# ncdump -sh temp_5_e.nc
netcdf temp_5_e {
dimensions:
    time = 5 ;
    Z = 5 ;
    lat = 5 ;
    lon = 5 ;
    scen = 5 ;
variables:
    int64 time(time) ;
        time:units = "days since 1900-01-01 00:00:00.000000" ;
        time:calendar = "gregorian" ;
        time:_Storage = "contiguous" ;
        time:_Endianness = "little" ;
    int64 Z(Z) ;
        Z:axis = "Z" ;
        Z:units = "m" ;
        Z:_Storage = "contiguous" ;
        Z:_Endianness = "little" ;
    int64 lat(lat) ;
        lat:axis = "Y" ;
        lat:units = "degrees_north" ;
        lat:_Storage = "contiguous" ;
        lat:_Endianness = "little" ;
    int64 lon(lon) ;
        lon:axis = "X" ;
        lon:units = "degrees_east" ;
        lon:_Storage = "contiguous" ;
        lon:_Endianness = "little" ;
    int64 scen(scen) ;
        scen:axis = "E" ;
        scen:_Storage = "contiguous" ;
        scen:_Endianness = "little" ;
    double temp(scen, time, Z, lat, lon) ;
        temp:_FillValue = NaN ;
        temp:_Storage = "contiguous" ;
        temp:_Endianness = "little" ;

// global attributes:
        :_NCProperties = "version=2,netcdf=4.7.4,hdf5=1.12.0," ;
        :_SuperblockVersion = 0 ;
        :_IsNetcdf4 = 1 ;
        :_Format = "netCDF-4" ;
}

0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Browse other questions tagged or ask your own question.