netbymatt / nexrad-level-2-plot

Plot nexrad level 2 radar data
MIT License
6 stars 2 forks source link

[feature] Possible web app, and vector/GeoJSON output #5

Closed SteepAtticStairs closed 1 year ago

SteepAtticStairs commented 2 years ago

I apologize for the amount of issues I've been opening on this project, but I am fascinated with the work you have done and am determined to create it into something useable for someone not familiar with code - e.g. a website. I think this is doable, because it is written in JavaScript, and I am already able to get the barebones working, as I will detail.

Here is how I have gone about making this into a rudimentary web app.

UPDATE: I have forked your repo and made these changes to my fork, so these instructions aren't really necessary, you can just clone my fork. Here is the commit where I added all of the stuff detailed in the instructions: https://github.com/SteepAtticStairs/nexrad-level-2-plot/commit/27910eb5b35ef74671bcbb35d029f3335ba85e7f

Instructions (in case you want to do it yourself. If not, check out my fork) 1. Clone the repo and cd into the root directory ``` git clone https://github.com/netbymatt/nexrad-level-2-plot.git cd nexrad-level-2-plot ``` 2. Install `node-fetch` ``` npm install node-fetch@2.0 ``` 3. In `./demos` make a file called `myTest.js`, and put these contents into the file: ```javascript const fetch = require('node-fetch'); const { plot } = require('../src'); const { Level2Radar } = require('nexrad-level-2-data'); function toBuffer(ab) { const buf = Buffer.alloc(ab.byteLength); const view = new Uint8Array(ab); for (let i = 0; i < buf.length; ++i) { buf[i] = view[i]; } return buf; } // https://php-cors-proxy.herokuapp.com/?https://noaa-nexrad-level2.s3.amazonaws.com/2017/08/25/KCRP/KCRP20170825_235733_V06 // https://php-cors-proxy.herokuapp.com/?https://noaa-nexrad-level2.s3.amazonaws.com/2009/06/03/KBLX/KBLX20090603_004417_V03.gz fetch('https://php-cors-proxy.herokuapp.com/?https://noaa-nexrad-level2.s3.amazonaws.com/2009/06/03/KBLX/KBLX20090603_004417_V03.gz') .then(res => res.arrayBuffer()) .then(rawData => { var l2rad = new Level2Radar(toBuffer(rawData)) const level2Plot = plot(l2rad, 'REF', {elevations: 1, background: 'rgba(0, 0, 0, 0)'}); }) .catch(err => console.error(err)); ``` 4. In `src/draw/index.js`, currently at line `90` (at the time of writing this), replace ```javascript const canvas = createCanvas(cropTo, cropTo); ``` with ```javascript const canvas = document.getElementById('myCanvas'); ``` This will allow the project to interact with the DOM. Then, right after `ctx` is declared (on the next line), add these two lines: ```javascript ctx.canvas.width = cropTo; ctx.canvas.height = cropTo; ``` In the end, from the current state of the repo, you should have ```javascript // create the canvas and context const canvas = document.getElementById('theCanvas'); const ctx = canvas.getContext('2d', { alpha: options.alpha }); ctx.canvas.width = cropTo; ctx.canvas.height = cropTo; ctx.antialias = options.antialias; ctx.imageSmoothingEnabled = options.imageSmoothingEnabled; ``` 6. Run [`browserify`](https://browserify.org) in the root project folder to compile the project into a web app: ``` browserify demos/myTest.js -o bundle.js ``` 7. In the root project folder, make a file called `index.html` and put this code in that file: ```html Add a canvas source
``` 8. To view the web app, just start a server in the root folder of the project. I personally use [Live Preview](https://marketplace.visualstudio.com/items?itemName=ms-vscode.live-server), but you can also use python's `http.server`: ``` python3 -m http.server 8888 ``` and then open `localhost:8888` - however I'm certain you already know how to do this. To see the radar drawn on the map, zoom into the bottom of Myanmar (those were the coordinates given in the [Mapbox `Canvas` example](https://docs.mapbox.com/mapbox-gl-js/example/canvas-source/) I was using haha) I would be happy to provide a `zip` of my project, if these instructions do not work for you.


Please excuse the lengthy instructions, I just wanted to add them for the sake of displaying the little amount of changes needed for this to work in a browser.

Given all of this, I was wondering your opinion on an idea I had to make this better. First, I was wondering if there was a way to easily render high-quality graphics onto the map. Using this function:

function setDPI(canvas, dpi) {
    // Set up CSS size.
    canvas.style.width = canvas.style.width || canvas.width + 'px';
    canvas.style.height = canvas.style.height || canvas.height + 'px';

    // Resize canvas and scale future draws.
    var scaleFactor = dpi / 96;
    canvas.width = Math.ceil(canvas.width * scaleFactor);
    canvas.height = Math.ceil(canvas.height * scaleFactor);
    var ctx = canvas.getContext('2d');
    ctx.scale(scaleFactor, scaleFactor);
}

you are able to set the DPI of the canvas, making the resolution of the outputted image higher. However, it is still a raster image being rendered, and I haven't found a way to change this, since <canvas> renders pixels, not vector nodes. Do you have an idea on how, given this current system I have put forward, could one render each radial gate as a vector object, instead of part of a raster image? Maybe a plugin that allows for modification of <canvas>?

Perhaps a better idea to that regard would be to find a way to render the plotted data as a GeoJSON object, instead of putting the data into canvas? Mapbox supports GeoJSON easily, and renders it very quickly. It might require some georeferencing, but you would end up having a polygon for each gate in the GeoJSON object, with a property key containing the dBZ value of that gate. This would allow the map to render each polygon's shape, and then draw their color from that property value. Does this sound doable, and if so, how might I go about doing it, in your opinion?

I found some articles detailing how someone managed to do just this: https://observablehq.com/@00ad408474591e33/weather-data-mapping-gridded-radar-data-from-ksgf-with-d3-de https://observablehq.com/@00ad408474591e33/mapping-gridded-radar-data-from-khtx-with-a-voronoi-diagram

I appreciate any help you can give - I really do think this library you've made can be made into something cool.

EDIT: An issue I am running into is that whenever I load a file onto the website version, it seems to do fine. But ANY FILE after June 2016 (when they changed the file compression format detailed here) will not load. What irks me is that these later files load fine in the CLI version of neared-level-2-data and nexrad-level-2-plot. I don't know what the issue here is, but if you have any idea what it is I would greatly appreciate it. I have attached a video of me using the file KTLX20130520_200356_V06.gz and it working fine, but then the file KLWX20220623_014344_V06 giving errors

https://user-images.githubusercontent.com/80776609/179282877-8e5df6ab-69ab-4e9c-a0da-ed3398a375f6.mov

netbymatt commented 2 years ago

I'll offer a few suggestions but my intent and need is centered around raster images.

SteepAtticStairs commented 2 years ago

Thanks for the reply! My intent was indeed to do this in a fork - I assumed you would only be needing raster for your use of the library.

I'll look for a GeoJSON option, because that looks like the best way to go at this point. I can probably create it dynamically in src/draw/index.js. I don't think canvas natively supports svg, but there are libraries such as svg.js that are interesting.

As to the issue I was facing, do you have any idea why all radar files work in the main project, but only some work when using Browserify?

netbymatt commented 2 years ago

Node-canvas points you at this file if you're using it in the browser. https://github.com/Automattic/node-canvas/blob/master/browser.js