@aguacerowx/javascript-sdk 0.0.5 → 0.0.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@aguacerowx/javascript-sdk",
3
- "version": "0.0.5",
3
+ "version": "0.0.7",
4
4
  "private": false,
5
5
  "publishConfig": {
6
6
  "access": "public"
@@ -7,7 +7,6 @@ import { getUnitConversionFunction } from './unitConversions.js';
7
7
  import { DICTIONARIES, MODEL_CONFIGS } from './dictionaries.js';
8
8
  import { DEFAULT_COLORMAPS } from './default-colormaps.js';
9
9
  import proj4 from 'proj4';
10
- import { decompress } from 'fzstd';
11
10
  import { getBundleId } from './getBundleId';
12
11
 
13
12
  // --- Non-UI Helper Functions ---
@@ -177,19 +176,58 @@ export class AguaceroCore extends EventEmitter {
177
176
  this._emitStateChange(); // Notify UI that isPlaying is now false
178
177
  }
179
178
 
180
- togglePlay() { this.isPlaying ? this.pause() : this.play(); }
179
+ togglePlay() {
180
+ this.isPlaying ? this.pause() : this.play();
181
+ }
181
182
 
182
183
  step(direction = 1) {
183
- const { model, date, run, forecastHour } = this.state;
184
- const forecastHours = this.modelStatus?.[model]?.[date]?.[run];
185
- if (!forecastHours || forecastHours.length === 0) return;
186
- const currentIndex = forecastHours.indexOf(forecastHour);
187
- if (currentIndex === -1) return;
188
- const maxIndex = forecastHours.length - 1;
189
- let nextIndex = currentIndex + direction;
190
- if (nextIndex > maxIndex) nextIndex = 0;
191
- if (nextIndex < 0) nextIndex = maxIndex;
192
- this.setState({ forecastHour: forecastHours[nextIndex] });
184
+ // --- THIS IS THE CORRECTED MRMS LOGIC ---
185
+ if (this.state.isMRMS) {
186
+ const { variable, mrmsTimestamp } = this.state;
187
+ if (!this.mrmsStatus || !this.mrmsStatus[variable]) {
188
+ console.warn('[Core.step] MRMS status or variable not available.');
189
+ return;
190
+ }
191
+
192
+ // CRITICAL FIX: The UI and state emissions use a REVERSED array (newest first).
193
+ // The step logic MUST use the same reversed array for indexes to match.
194
+ const availableTimestamps = [...(this.mrmsStatus[variable] || [])].reverse();
195
+ if (availableTimestamps.length === 0) return;
196
+
197
+ const currentIndex = availableTimestamps.indexOf(mrmsTimestamp);
198
+
199
+ if (currentIndex === -1) {
200
+ // If not found, reset to the first (newest) frame
201
+ this.setState({ mrmsTimestamp: availableTimestamps[0] });
202
+ return;
203
+ }
204
+
205
+ const maxIndex = availableTimestamps.length - 1;
206
+ let nextIndex = currentIndex + direction;
207
+
208
+ // Loop animation
209
+ if (nextIndex > maxIndex) nextIndex = 0;
210
+ if (nextIndex < 0) nextIndex = maxIndex;
211
+
212
+ const newTimestamp = availableTimestamps[nextIndex];
213
+ this.setState({ mrmsTimestamp: newTimestamp });
214
+
215
+ } else {
216
+ const { model, date, run, forecastHour } = this.state;
217
+ const forecastHours = this.modelStatus?.[model]?.[date]?.[run];
218
+ if (!forecastHours || forecastHours.length === 0) return;
219
+
220
+ const currentIndex = forecastHours.indexOf(forecastHour);
221
+ if (currentIndex === -1) return;
222
+
223
+ const maxIndex = forecastHours.length - 1;
224
+ let nextIndex = currentIndex + direction;
225
+ if (nextIndex > maxIndex) nextIndex = 0;
226
+ if (nextIndex < 0) nextIndex = maxIndex;
227
+
228
+ const newHour = forecastHours[nextIndex];
229
+ this.setState({ forecastHour: newHour });
230
+ }
193
231
  }
194
232
 
195
233
  setPlaybackSpeed(speed) {
@@ -364,7 +402,7 @@ export class AguaceroCore extends EventEmitter {
364
402
  const baseUrl = `${this.baseGridUrl}${resourcePath}`;
365
403
  const urlWithApiKeyParam = `${baseUrl}?apiKey=${this.apiKey}`;
366
404
  const headers = { 'x-api-key': this.apiKey };
367
- if (this.bundleId) {
405
+ if (this.bundleId && this.isReactNative) {
368
406
  headers['x-app-identifier'] = this.bundleId;
369
407
  }
370
408
 
@@ -455,12 +493,33 @@ export class AguaceroCore extends EventEmitter {
455
493
  const index1D = j * nx + i;
456
494
  const byteValue = gridData.data[index1D];
457
495
  const signedQuantizedValue = byteValue - 128;
458
- const { scale, offset, missing_quantized } = gridData.encoding;
496
+
497
+ // --- START OF FIX ---
498
+ // You were missing 'scale_type' in this destructuring assignment.
499
+ const { scale, offset, missing_quantized, scale_type } = gridData.encoding;
500
+ // --- END OF FIX ---
459
501
 
460
502
  if (signedQuantizedValue === missing_quantized) return null;
461
503
 
462
- const nativeValue = signedQuantizedValue * scale + offset;
463
- const { baseUnit } = this._getColormapForVariable(variable);
504
+ const intermediateValue = signedQuantizedValue * scale + offset;
505
+
506
+ // Step 2: Apply non-linear scaling if specified
507
+ let nativeValue = intermediateValue;
508
+ if (scale_type === 'sqrt') {
509
+ // Square the value while preserving its sign
510
+ nativeValue = intermediateValue < 0 ? -(intermediateValue * intermediateValue) : (intermediateValue * intermediateValue);
511
+ }
512
+ const { colormap, baseUnit } = this._getColormapForVariable(variable);
513
+
514
+ // If the value is outside the colormap's bounds, return null.
515
+ if (colormap && colormap.length >= 2) {
516
+ const minBound = colormap[0];
517
+ const maxBound = colormap[colormap.length - 2];
518
+ if (nativeValue < minBound || nativeValue > maxBound) {
519
+ return null;
520
+ }
521
+ }
522
+
464
523
  let dataNativeUnit = baseUnit || (DICTIONARIES.fld[variable] || {}).defaultUnit || 'none';
465
524
 
466
525
  const displayUnit = this._getTargetUnit(dataNativeUnit, units);
@@ -493,26 +552,29 @@ export class AguaceroCore extends EventEmitter {
493
552
 
494
553
  _getColormapForVariable(variable) {
495
554
  if (!variable) return { colormap: [], baseUnit: '' };
555
+
496
556
  if (this.customColormaps[variable] && this.customColormaps[variable].colormap) {
497
557
  return {
498
558
  colormap: this.customColormaps[variable].colormap,
499
- baseUnit: this.customColormaps[variable].baseUnit || ''
559
+ baseUnit: this.customColormaps[variable].defaultUnit || ''
500
560
  };
501
561
  }
562
+
502
563
  const colormapKey = DICTIONARIES.variable_cmap[variable] || variable;
503
564
  const customColormap = this.customColormaps[colormapKey];
504
565
  if (customColormap && customColormap.colormap) {
505
- return { colormap: customColormap.colormap, baseUnit: customColormap.baseUnit || '' };
566
+ return { colormap: customColormap.colormap, baseUnit: customColormap.defaultUnit || '' };
506
567
  }
568
+
507
569
  const defaultColormapData = DEFAULT_COLORMAPS[colormapKey];
508
570
  if (defaultColormapData && defaultColormapData.units) {
509
- const availableUnits = Object.keys(defaultColormapData.units);
510
- if (availableUnits.length > 0) {
511
- const baseUnit = availableUnits[0];
512
- const unitData = defaultColormapData.units[baseUnit];
513
- if (unitData && unitData.colormap) {
514
- return { colormap: unitData.colormap, baseUnit: baseUnit };
515
- }
571
+ // Get defaultUnit from the field dictionary
572
+ const fieldInfo = DICTIONARIES.fld[variable] || {};
573
+ const baseUnit = fieldInfo.defaultUnit || Object.keys(defaultColormapData.units)[0];
574
+
575
+ const unitData = defaultColormapData.units[baseUnit];
576
+ if (unitData && unitData.colormap) {
577
+ return { colormap: unitData.colormap, baseUnit: baseUnit };
516
578
  }
517
579
  }
518
580
  return { colormap: [], baseUnit: '' };
@@ -2114,7 +2114,7 @@ export const DEFAULT_COLORMAPS = {
2114
2114
  0.01,0.1,0.25,0.5,0.75,1,1.5,2,2.5,3,3.5,4,4.5,5,5.5,6,7,8,9,10
2115
2115
  ]
2116
2116
  },
2117
- "cm": {
2117
+ "cm [QPF]": {
2118
2118
  "colormap": [
2119
2119
  0.03, "#eeccff",
2120
2120
  .25, "#ff9999",
@@ -2129,7 +2129,7 @@ export const DEFAULT_COLORMAPS = {
2129
2129
  3.75,4,4.5,5,5.5,6,7,8,9,10,12,14,16,18,20,22,24,26
2130
2130
  ]
2131
2131
  },
2132
- "mm": {
2132
+ "mm [QPF]": {
2133
2133
  "colormap": [
2134
2134
  0.3, "#eeccff",
2135
2135
  2.5, "#ff9999",
@@ -2166,7 +2166,7 @@ export const DEFAULT_COLORMAPS = {
2166
2166
  0.01,0.1,0.2,0.3,0.4,0.5,0.6,0.7,0.8,0.9,1,1.25,1.5,1.75,2,2.5,3
2167
2167
  ]
2168
2168
  },
2169
- "cm": {
2169
+ "cm [QPF]": {
2170
2170
  "colormap": [
2171
2171
  0.03, "#eeccff",
2172
2172
  .25, "#ff9999",
@@ -2181,7 +2181,7 @@ export const DEFAULT_COLORMAPS = {
2181
2181
  5.5,6,7,8,9,10,12,14,16
2182
2182
  ]
2183
2183
  },
2184
- "mm": {
2184
+ "mm [QPF]": {
2185
2185
  "colormap": [
2186
2186
  0.3, "#eeccff",
2187
2187
  2.5, "#ff9999",
@@ -278,7 +278,7 @@ export const MODEL_CONFIGS = {
278
278
  },
279
279
  'gfs': {
280
280
  max_zoom: 3,
281
- vars: ['2r_2', '2t_2', 'refd_1000', 'vis_0', 'gust_runmax', "gh_tendency_500", 'bulk_shear_speedmb_500', 'bulk_shear_speedmb_700', 'bulk_shear_speedmb_850', 'bulk_shear_speedmb_925','2t_2iso0', 'crain_total', 'crain_3', 'crain_6', 'crain_12', 'crain_24', 'crain_48', 'cicep_total', 'cicep_3', 'cicep_6', 'cicep_12', 'cicep_24', 'cicep_48', 'cfrzr_total', 'cfrzr_3', 'cfrzr_6', 'cfrzr_12', 'cfrzr_24', 'cfrzr_48', 'csnow_total', 'csnow_3', 'csnow_6', 'csnow_12', 'csnow_24', 'csnow_48', 'tp_0_total', 'tp_3', 'tp_6', 'tp_12', 'tp_24', 'tp_48', 'cin_0', 'wind_speed_700', 'wind_speed_200', 'divergence_200', 'd_925', 'tadv_300', 'w_850', 'rainRefl', 'icepRefl', 'snowRefl', 'frzrRefl', 'lftx_0', 'refc_0', 'fgen_850', 'hcc_0', 'r_700', 't_850', 't_850iso0', 'r_850', 'tcc_0', 'hlcy_3000', 'thickness', 'vo_850', 'wind_direction_2000', 'r_500', 'gh_500', 'wind_speed_500', '2d_2', 'cape_25500', 'mcc_0', 'w_500', 'pwat_0', 'divergence_850', 't_500', 'wind_speed_850', 'lcl', 'cape_0', 'tadv_850', 'tadv_700', 'theta2PVU', 'wind_speed_2000', 'lapse_rates_500700', 'vo_500', 'irsat', 't_700', 't_700iso0', 'cin_25500', 'ehi_3000', 'lcc_0', 'gh_850', 'wind_speed_925', 'gh_200', 'wind_speed_300', 'fgen_700', 'vo_700', 'd_850', 'thetaE', 'pres2PVU', 'd_700', 'crain', 'csnow', 'cicep', 'cfrzr', 'w_700', 'gust_0', 'ivt', 'atemp', 'cape_9000', 'r_925', 'mslma_0', 'w_925', 'cin_9000', 'mean700300mbRH', 'wind_speed_10', 't_925', 't_925iso0', 'gh_925', 'gh_700', 'gh_300'],
281
+ vars: ['cfrzr_total', 'tp_0_total', '2r_2', '2t_2', 'refd_1000', 'vis_0', 'gust_runmax', "gh_tendency_500", 'bulk_shear_speedmb_500', 'bulk_shear_speedmb_700', 'bulk_shear_speedmb_850', 'bulk_shear_speedmb_925','2t_2iso0', 'crain_total', 'crain_3', 'crain_6', 'crain_12', 'crain_24', 'crain_48', 'cicep_total', 'cicep_3', 'cicep_6', 'cicep_12', 'cicep_24', 'cicep_48', 'cfrzr_total', 'cfrzr_3', 'cfrzr_6', 'cfrzr_12', 'cfrzr_24', 'cfrzr_48', 'csnow_total', 'csnow_3', 'csnow_6', 'csnow_12', 'csnow_24', 'csnow_48', 'tp_3', 'tp_6', 'tp_12', 'tp_24', 'tp_48', 'cin_0', 'wind_speed_700', 'wind_speed_200', 'divergence_200', 'd_925', 'tadv_300', 'w_850', 'rainRefl', 'icepRefl', 'snowRefl', 'frzrRefl', 'lftx_0', 'refc_0', 'fgen_850', 'hcc_0', 'r_700', 't_850', 't_850iso0', 'r_850', 'tcc_0', 'hlcy_3000', 'thickness', 'vo_850', 'wind_direction_2000', 'r_500', 'gh_500', 'wind_speed_500', '2d_2', 'cape_25500', 'mcc_0', 'w_500', 'pwat_0', 'divergence_850', 't_500', 'wind_speed_850', 'lcl', 'cape_0', 'tadv_850', 'tadv_700', 'theta2PVU', 'wind_speed_2000', 'lapse_rates_500700', 'vo_500', 'irsat', 't_700', 't_700iso0', 'cin_25500', 'ehi_3000', 'lcc_0', 'gh_850', 'wind_speed_925', 'gh_200', 'wind_speed_300', 'fgen_700', 'vo_700', 'd_850', 'thetaE', 'pres2PVU', 'd_700', 'crain', 'csnow', 'cicep', 'cfrzr', 'w_700', 'gust_0', 'ivt', 'atemp', 'cape_9000', 'r_925', 'mslma_0', 'w_925', 'cin_9000', 'mean700300mbRH', 'wind_speed_10', 't_925', 't_925iso0', 'gh_925', 'gh_700', 'gh_300'],
282
282
  category: 'Global',
283
283
  name: 'GFS',
284
284
  bounds: [-180, -90, 180, 90],