[GIS] netCDF-java has trouble reading this netCDF file(format) and fetching values from the latlon dimension

javanetcdfraster

I'm developing an application where I need to extract variable-values from netCDF files.

I'm processing several different formatted netCDF files and now one format seems to be creating some issues.

The problem is to correctly fetch data from lat/lon variables. Some lat/lon works, but the mapping does not seem to be complete.

ncdump of the netCDF file:

netcdf test2 {
dimensions:
        x = 182 ;
        y = 149 ;
        lev = 31 ;
        time = UNLIMITED ; // (72 currently)
variables:
        double lev(lev) ;
                lev:long_name = "generic" ;
                lev:units = "level" ;
                lev:axis = "Z" ;
        double time(time) ;
                time:standard_name = "time" ;
                time:units = "months since 1991-01-15 12:00:00" ;
                time:calendar = "standard" ;
        float variable1(time, lev, y, x) ;
                variable1:long_name = "Variable 1" ;
                variable1:units = "mg" ;
                variable1:_FillValue = 9.96921e+036f ;
                variable1:coordinates = "nav_lon nav_lat time lev" ;
        float nav_lon(y, x) ;
                nav_lon:long_name = "longitude" ;
                nav_lon:units = "degrees_east" ;
        float nav_lat(y, x) ;
                nav_lat:long_name = "latitude" ;
                nav_lat:units = "degrees_north" ;

// global attributes:
                :CDI = "Climate Data Interface version 1.5.1 (http://code.zmaw.de/projects/cdi)" ;
                :Conventions = "CF-1.0" ;
                :Title = "Test" ;
                :CDO = "Climate Data Operators version 1.5.1 (http://code.zmaw.de/projects/cdo)" ;
data:

 lev = 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20,
    21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31 ;

 time = 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121,
    122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135,
    136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149,
    150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163,
    164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177,
    178, 179 ;
}

I can also show you subset of the nav_lon data (from opendap) if that could be of help to understand the format:

Dataset {
    Float32 nav_lon[y = 4][x = 4];
} test2.nc;
---------------------------------------------
nav_lon[4][4]
[0], 78.00004, 80.0, 81.99996, 83.99992
[1], 78.00004, 80.0, 81.99996, 83.99992
[2], 78.00004, 80.0, 81.99996, 83.99992
[3], 35.53008, 36.53008, 37.53008, 38.53008

Now to the actual code that is not producing the desired results. I'm using the latest version of NetCDF-Java, 4.3.19:

public class TestReadNetCDF {
    public static void main(String[] args) {
        String fileURI = "URI_TO_THE_FILE";
        readNetCDFFile(fileURI);
    }

    private static void readNetCDFFile(String filename) {
        NetcdfDataset ncfile = null;
        try {
            ncfile = NetcdfDataset.openDataset(filename);
            GridDataset grid = new GridDataset(ncfile);
            System.out.println("GRID:" + grid);
            process(grid);
        } catch (IOException ioe) {
            log("trying to open " + filename, ioe);
        } finally {
            if (null != ncfile)
                try {
                    ncfile.close();
                } catch (IOException ioe) {
                    log("trying to close " + filename, ioe);
                }
        }
        NetcdfDataset.shutdown();
    }
    private static void process(GridDataset gds) throws IOException {
        System.out.println("VARS:");
        for (VariableSimpleIF v : gds.getDataVariables())
            System.out.println(v.getFullName());
        GridDatatype grid = gds.findGridDatatype("variable1");
        GridCoordSystem gcs = grid.getCoordinateSystem();
        double lat = -63.63;
        double lon = -14.83;
        //lat = -61.24769;
        //lon = 78.00004;
        lat = -77.7742;
        lon = 78.00004;

        // find the x,y index for a specific lat/lon position
        // xy[0] = x, xy[1] = y
        int[] xy = gcs.findXYindexFromLatLonBounded(lat, lon, null);

        // read the data at that lat, lon and the first time and z level (if any)
        // note order is t, z, y, x
        System.out.println("x,y:" + xy[0] + "," + xy[1]);
        Array data = grid.readDataSlice(0, 0, xy[1], xy[0]);
        // we know its a scalar
        double val = data.getDouble(0);

        System.out.printf("Value at %f %f == %f%n", lat, lon, val);
    }
}

The problem seems to be that findXYindexFromLatLonBounded gets the wrong x/y indices (on most input values). If I drop "bounded", then it will fetch -1, -1, even though the latlon are within the "range" – though the mapping does not seem to be complete.

I could mention that ncWMS can read these files just fine and I can display the files as a WMS (and get point data out from there, but that is really inefficient and I'd like something better). Thredds can also read the files and output them through i.e. OpenDAP or Godiva2. If I use the OpenDAP URL it provides the same result as if I use the nc-file URI.

Any thoughts?

Best Answer

I cant tell if the lat / lon 2D arrays are correct, or if you are seeing a bug.

One way to test is to bring it up in the ToolsUI (example given).

Go to FeatureType / Grids, open the dataset and see what the grid looks like by hitting the red alien button (twice).

Publishing the dods URL lets others look at it remotely; you should also send what version of netcdf-java you are using.