parro-it / netcdf4

NodeJS addon to read and write NetCDF4 files
ISC License
39 stars 14 forks source link

How to use readSlice in 4 dimensional array #4

Closed JonathanVandal closed 7 years ago

JonathanVandal commented 7 years ago

Hi, I have to read in my 4 dimensional array with readSlice(). When I'm using read() it's work :

// Time, Level, Latitude, Longitude
file.root.variables['pm10_conc'].read(0, 0, 0, 0)

This will output well my first cell.

Time max array index = 24 Level max array index = 0 Latitude max array index = 400 Longitude max array index = 700

But I want to read this :

Latitude -> from 69.95 to 69.85 Longitude -> from 335.05 to 335.25

As you can see in my image here I should get this data

69.95, 335.05 = 0.122270
69.95, 335.15 = 0.122270
69.95, 335.25 = 0.122015

69.85, 335.05 = 0.133071
69.85, 335.15 = 0.122697
69.85, 335.25 = 0.120764

I did this but this will returns me all my data.

file.root.variables['pm10_conc'].readSlice(0, 24, 0, 1, 0, 400, 0, 700)

Normal because max lat = 400 and max lng = 700. Could you tell me how can I use readSlice() in my case ? Thanks.

swillner commented 7 years ago

Hi. You need to use the indices of the latitudes and longitudes you want to use. Let's say lat_from is the index for Latitude==69.95 and lat_to that for Latitude==69.85 (lat_to > lat_from since it looks like latitude is decreasing with the indices for your data). Similar for longitudes, lon_from and lon_to. Then use

file.root.variables['pm10_conc'].readSlice(0, 24, 0, 1, lat_from, (lat_to - lat_from + 1), lon_from, (lon_to - lon_from + 1))

to read the slice of all 24 time steps, the first level and the lon/lat region you are interested in (alternating position and size to read, i.e. for longitudes read starting from lat_from the next lat_to - lat_from + 1 values along that dimension). Hope that helps...

JonathanVandal commented 7 years ago

Thanks for you answer. I tried this :

lat_from = 69.95;
lat_to = 69.85;
lng_from = 335.05;
lng_to = 335.25;

console.log(file.root.variables['pm10_conc'].readSlice(0, 24, 0, 1, lat_from, (lat_to - lat_from + 1), lng_from, (lng_to - lng_from + 1)));

But it returns me an empty Array

Float32Array [  ]
swillner commented 7 years ago

lat_from and the others need to be indices, not values of the latitudes/longitudes, i.e. you need something like this:

lat_from = file.root.variables['lat'].readSlice(0, 400).indexOf(69.95)
JonathanVandal commented 7 years ago

Ok. So I tried this :

lat_from = file.root.variables['latitude'].readSlice(0, 400).indexOf(69.95)
lat_to   = file.root.variables['latitude'].readSlice(0, 400).indexOf(69.85)
lng_from = file.root.variables['longitude'].readSlice(0, 700).indexOf(335.05)
lng_to   = file.root.variables['longitude'].readSlice(0, 700).indexOf(335.25)

console.log(lat_from)  // -1
console.log(lat_to)    // -1
console.log(lng_from)  // -1
console.log(lng_to)    //  2

console.log(lat_to - lat_from + 1)  // 1
console.log(lng_to - lng_from + 1)  // 3

console.log(file.root.variables['pm10_conc'].readSlice(0, 24, 0, 1, lat_from, (lat_to - lat_from + 1), lng_from, (lng_to - lng_from + 1)));

This throw me this error :

console.log(file.root.variables['pm10_conc'].readSlice(0, 24, 0, 1, lat_from, (lat_to - lat_from + 1), lng_from, (lng_to - lng_from + 1)));
                                             ^

TypeError: Operation not permitted
    at TypeError (native)
    at Object.<anonymous> (/Users/.../nc.js:37:46)
    at Module._compile (module.js:570:32)
    at Object.Module._extensions..js (module.js:579:10)
    at Module.load (module.js:487:32)
    at tryModuleLoad (module.js:446:12)
    at Function.Module._load (module.js:438:3)
    at Module.runMain (module.js:604:10)
    at run (bootstrap_node.js:394:7)
    at startup (bootstrap_node.js:149:9)

I solved it with the true value like this (maybe should I use Math.round) :

lat_from = file.root.variables['latitude'].readSlice(0, 400).indexOf(69.94999694824219)
lat_to   = file.root.variables['latitude'].readSlice(0, 400).indexOf(69.8499984741211)
lng_from = file.root.variables['longitude'].readSlice(0, 700).indexOf(335.04998779296875)
lng_to   = file.root.variables['longitude'].readSlice(0, 700).indexOf(335.25)

So now the slice works fine but I have to change the time position with 1 instead of 24.

console.log(file.root.variables['pm10_conc'].readSlice(0, 1, 0, 1, lat_from, (lat_to - lat_from + 1), lng_from, (lng_to - lng_from + 1)));

Thank you so much for your support !! :)

swillner commented 7 years ago

great! ;)