gars_v2
Version:
Geo Assistant Research System
145 lines (138 loc) • 5 kB
JavaScript
import fs from 'fs';
import readline from 'readline';
import error from './error';
class Data {
constructor() {}
read(datapath) {
var p = new Promise((resolve, reject) => {
var s = fs.createReadStream(datapath, { encoding: 'utf8' });
var rl = readline.createInterface({
input: s
});
var meta = [];
var rows = [];
var i = 0;
rl.on('line', line => {
line = line.trim();
if (i < 5) {
meta.push(line);
} else {
var row = line.split(/\s+/).map(Number);
rows.push(row);
}
i++;
});
rl.on('close', () => {
this.parse(datapath, meta, rows);
resolve();
});
s.on('error', e => {
console.error(e);
reject(e);
});
});
return p;
}
parse(datapath, meta, rows) {
this.FP = datapath;
this.title = meta[0];
this.unit = meta[1];
this.cols = Number(meta[2]);
this.rows = Number(meta[3]);
this.llrange = meta[4].split(/\s+/).map(Number);
this.meta = meta;
this.data = rows;
var actualRows = this.data.length;
var actualCols = this.data.length ? this.data[0].length : 0;
if (actualRows != this.rows || actualCols != this.cols) {
var msg = [
'declared rows: ' + this.rows,
'declared cols: ' + this.cols,
'actual rows: ' + actualRows,
'actual cols: ' + actualCols
].join('\n');
error('Corrupted Data', msg);
}
console.log('map data loaded', `rows: ${this.rows} cols: ${this.cols}`);
}
// closed range to avoid data loss
rangeAveX(x1, y1, x2, y2) {
console.log('calculating average X for range', `x1:${x1},x2:${x2},y1:${y1},y2:${y2}`);
x1 = Math.max(0, Math.floor(x1));
y1 = Math.max(0, Math.floor(y1));
x2 = Math.min(this.cols - 1, Math.ceil(x2));
y2 = Math.min(this.rows - 1, Math.ceil(y2));
var points = [];
for (var x = x1; x < x2; x++) {
var total = 0,
count = 0;
for (var y = y1; y < y2; y++) {
var d = this.data[y][x];
if (d === -999) continue;
total += d;
count++;
}
if (count === 0) continue;
var ave = total / count;
var x2lon = (x / this.cols) * (this.llrange[1] - this.llrange[0]) + this.llrange[0];
points.push([x2lon, ave]);
}
console.log('average X computed', points.length, 'points');
return points;
}
rangeAveY(x1, y1, x2, y2) {
console.log('calculating average Y for range', `x1:${x1},x2:${x2},y1:${y1},y2:${y2}`);
x1 = Math.max(0, Math.floor(x1));
y1 = Math.max(0, Math.floor(y1));
x2 = Math.min(this.cols - 1, Math.ceil(x2));
y2 = Math.min(this.rows - 1, Math.ceil(y2));
var points = [];
for (var y = y1; y < y2; y++) {
var total = 0,
count = 0;
for (var x = x1; x < x2; x++) {
var d = this.data[y][x];
if (d === -999) continue;
total += d;
count++;
}
if (count === 0) continue;
var ave = total / count;
var y2lat = - (y / this.rows) * (this.llrange[3] - this.llrange[2]) - this.llrange[2];
points.push([y2lat, ave]);
}
console.log('average Y computed', points.length, 'points');
return points;
}
accData(x1, y1, x2, y2) {
x1 = Math.max(0, Math.floor(x1));
y1 = Math.max(0, Math.floor(y1));
x2 = Math.min(this.cols - 1, Math.ceil(x2));
y2 = Math.min(this.rows - 1, Math.ceil(y2));
var points = [];
for (var y = y1; y < y2; y++) {
for (var x = x1; x < x2; x++) {
if (this.data[y][x] === -999) continue;
points.push(this.data[y][x]);
}
}
return points;
}
longitude(i) {
return i * (this.llrange[1] - this.llrange[0]) / this.cols + this.llrange[0];
}
latitude(i) {
return - i * (this.llrange[3] - this.llrange[2]) / this.rows - this.llrange[2];
}
longitudeText(i){
var val = this.longitude(i).toFixed(3);
var unit = val >= 0 ? 'E' : 'W';
return val + '° ' + unit;
}
latitudeText(i){
var val = this.latitude(i).toFixed(3);
var unit = val >= 0 ? 'N' : 'S';
return val + '° ' + unit;
}
}
export default Data;