tsupinie / autumnplot-gl

Hardware-accelerated geospatial data plotting in the browser
MIT License
18 stars 4 forks source link

NBM Data Projection - Compatible? #6

Closed Craytor closed 10 months ago

Craytor commented 11 months ago

I was wondering if you have had any experience plotting NBM data using autumnplot-gl. I have some data available here https://wxlogic-models.nyc3.cdn.digitaloceanspaces.com/nbm-test/18z-asnow.dat (compressed gzip).

I have tried adding using the LambertGrid, however no data is being displayed.

const fac = 1e-6;
const ni = 2345;
const nj = 1597;
const dx = 2539703;
const dy = 2539703;
const lon_0 = 265000000 * fac;
const lat_0 = 25000000 * fac;
const lat_std = [25000000 * fac, 25000000 * fac];

const grid1 = new apgl.LambertGrid(ni, nj, lon_0, lat_0, lat_std, -ni * dx / 2, -nj * dy / 2, ni * dx / 2, nj * dy / 2);

I modeled this off from the HRRR demo to no avail.

Any thoughts on this?

Craytor commented 11 months ago

Some additional information regarding the projection specs...

HRRR

Grib2LambertConformalGridDefinition {
  contents: {
    earth_shape: 6,
    spherical_earth_radius_scale_factor: 0,
    spherical_earth_radius_value: 0,
    oblate_earth_semimajor_axis_scale_factor: 0,
    oblate_earth_semimajor_axis_value: 0,
    oblate_earth_semiminor_axis_scale_factor: 0,
    oblate_earth_semiminor_axis_value: 0,
    ngrid_i: 1799,
    ngrid_j: 1059,
    lat_first: 21138123,
    lon_first: 237280472,
    resolution_component_flags: 8,
    center_latitude: 38500000,
    standard_longitude: 262500000,
    grid_dx: 3000000,
    grid_dy: 3000000,
    projection_center_flag: 0,
    scanning_mode_flag: 64,
    standard_latitude_1: 38500000,
    standard_latitude_2: 38500000,
    south_pole_latitude: 0,
    south_pole_longitude: 0
  },
  offset: 51
}

NBM

Grib2LambertConformalGridDefinition {
  contents: {
    earth_shape: 1,
    spherical_earth_radius_scale_factor: 0,
    spherical_earth_radius_value: 6371200,
    oblate_earth_semimajor_axis_scale_factor: 255,
    oblate_earth_semimajor_axis_value: 255,
    oblate_earth_semiminor_axis_scale_factor: 255,
    oblate_earth_semiminor_axis_value: 255,
    ngrid_i: 2345,
    ngrid_j: 1597,
    lat_first: 19229000,
    lon_first: 233723400,
    resolution_component_flags: 48,
    center_latitude: 25000000,
    standard_longitude: 265000000,
    grid_dx: 2539703,
    grid_dy: 2539703,
    projection_center_flag: 0,
    scanning_mode_flag: 80,
    standard_latitude_1: 25000000,
    standard_latitude_2: 25000000,
    south_pole_latitude: -90000000,
    south_pole_longitude: 0
  },
  offset: 51
}
Craytor commented 11 months ago

I managed to get it kind of working. I had to use QGIS to determine the extents of the grid. However, these bars are occurring now.

const grid1 = new apgl.LambertGrid(nx, ny, 265, 25, [25, 25], -3271151.6058371709659696, -263793.7334645641967654, 2681912.2261628294363618, 3789572.2545354356989264);
Screenshot 2023-11-27 at 5 06 48 AM Screenshot 2023-11-27 at 5 08 01 AM
tsupinie commented 11 months ago

With respect to your original attempt:

const dx = 2539703;
const dy = 2539703;

Those don't look like meters. Try dividing by 1000, and I bet that works.

With respect to the bars on the second attempt, how are you reading the NBM grib file? In grib, there is an option to alternate the direction of rows, and IIRC, the NBM file is encoded in this way. I assume provides some improvement in compression ratio, because I can't for the life of me think of another reason why one would encode model output this way. Either way, I think some grib parsers might ignore that option. Python's cfgrib is (or at least used to be) one of them, and gribjs is also definitely one of them.

Craytor commented 10 months ago

Both of your suggestions worked 100% -- thank you!

I created a simple function to take the data and switch the orders if you would like to incorporate it/build from it in gribjs. The remaining task would be determining when to use it as you have mentioned above.

// This function will only work as expected on data that contains rows of
// data in alternating directions
async function correctDataOrder(msg) {
    let nx = msg.headers.sec3.contents.grid_definition_template.ngrid_i;

    let counter = 0;
    let rowCount = 0;

    let startingSectionIndex = 0;
    let endIndex = nx - 1;

    let originalData = msg.data;

    let returnData = Array(originalData.length);
    for (let i = 0; i < originalData.length; i++) {
        if (i % nx == 0) {
            startingSectionIndex = i;
            endIndex = i + nx - 1;
            counter = 0;
            rowCount++;
        } else {
            counter++;
        }

        if (rowCount % 2 == 0) {
            returnData[endIndex - counter] = originalData[i];
        } else {
            returnData[i] = originalData[i];
        }

    }
    return new Float32Array(returnData);
}
tsupinie commented 10 months ago

Thanks! I'll probably do something similar in gribjs, but I'd rather do the switching in place to save the overhead of another (potentially quite large) array.