@aguacerowx/mapsgl 0.0.49 → 0.0.51

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.
@@ -10,48 +10,6 @@ import WorkerPool from './WorkerPool.js';
10
10
 
11
11
  import { DEFAULT_BASIS_BASE_URL } from './defaultBasisBaseUrl.js';
12
12
 
13
- const DEBUG_NS = '[WeatherLayerManager:debug]';
14
-
15
- /**
16
- * Redact secrets for console output.
17
- * @param {object} options
18
- */
19
- function _debugSanitizeOptions(options) {
20
- if (!options || typeof options !== 'object') return options;
21
- const o = { ...options };
22
- if (typeof o.apiKey === 'string' && o.apiKey.length > 0) {
23
- o.apiKey = `${o.apiKey.slice(0, 4)}…(${o.apiKey.length} chars)`;
24
- }
25
- return o;
26
- }
27
-
28
- /**
29
- * Compact summary of timestamp / hour arrays (MRMS timeline debugging).
30
- * @param {unknown[]} arr
31
- */
32
- function _debugSummarizeNumericSeries(arr) {
33
- if (!Array.isArray(arr) || arr.length === 0) {
34
- return { length: 0, min: null, max: null, spanSec: null, head: [], tail: undefined };
35
- }
36
- const nums = arr.map((x) => Number(x)).filter((n) => !Number.isNaN(n));
37
- if (nums.length === 0) {
38
- return { length: 0, min: null, max: null, spanSec: null, head: [], tail: undefined };
39
- }
40
- const sorted = [...nums].sort((a, b) => a - b);
41
- const min = sorted[0];
42
- const max = sorted[sorted.length - 1];
43
- const head = sorted.slice(0, Math.min(8, sorted.length));
44
- const tail = sorted.length > 16 ? sorted.slice(-8) : [];
45
- return {
46
- length: sorted.length,
47
- min,
48
- max,
49
- spanSec: max != null && min != null ? max - min : null,
50
- head,
51
- tail: tail.length ? tail : undefined,
52
- };
53
- }
54
-
55
13
  function findLatestModelRun(modelsData, modelName) {
56
14
  const model = modelsData?.[modelName];
57
15
  if (!model) return null;
@@ -77,7 +35,7 @@ function findLatestModelRun(modelsData, modelName) {
77
35
  * @param {string} [options.belowID] - Style layer id to insert Aguacero weather layers **below** (default `AML_-_terrain` when present). Alias of `weatherBeforeLayerId`.
78
36
  * @param {string} [options.weatherBeforeLayerId] - Same as `belowID`.
79
37
  * @param {string} [options.nexradLayerId] - Override Mapbox id for the NEXRAD custom layer (default: derived from `layerId`).
80
- * @param {boolean} [options.debug] - When `true`, logs detailed diagnostics to the console (prefix `[WeatherLayerManager:debug]`). Off by default.
38
+ * @param {boolean} [options.mrmsTimelineLog] - When `true`, logs MRMS duration / raw vs filtered timeline counts (prefix `[WeatherLayerManager MRMS]`). Off by default.
81
39
  * @param {string} [options.basisBaseUrl] - URL prefix for satellite KTX2 Basis transcoder assets (`basis_transcoder.js`, `basis_transcoder.wasm`). Defaults to jsDelivr for the published package version; override (e.g. `/basis/`) for strict CSP or offline.
82
40
  */
83
41
  export class WeatherLayerManager extends EventEmitter {
@@ -85,10 +43,10 @@ export class WeatherLayerManager extends EventEmitter {
85
43
  super();
86
44
  if (!map) throw new Error('A Mapbox GL map instance is required.');
87
45
  this.map = map;
88
- /** @private When true, emit verbose `[WeatherLayerManager:debug]` logs. */
89
- this._debug = options.debug === true;
90
- /** @private Monotonic counter for correlating state:change logs. */
91
- this._debugStateSeq = 0;
46
+ /** @private MRMS-only timeline diagnostics (duration, raw vs filtered counts). */
47
+ this._mrmsTimelineLog = options.mrmsTimelineLog === true;
48
+ /** @private Dedupes repeated MRMS timeline log lines. */
49
+ this._mrmsLogKey = '';
92
50
  this.layerId =
93
51
  options.layerId ||
94
52
  options.id ||
@@ -159,30 +117,6 @@ export class WeatherLayerManager extends EventEmitter {
159
117
  // 1. CREATE an instance of the core engine
160
118
  this.core = new AguaceroCore(options);
161
119
 
162
- if (this._debug) {
163
- const layerOpts = options.layerOptions || {};
164
- console.log(DEBUG_NS, 'constructor', {
165
- layerId: this.layerId,
166
- nexradLayerId: this._nexradLayerId,
167
- mapLoaded: typeof this.map?.loaded === 'function' ? this.map.loaded() : undefined,
168
- styleLoaded: this.map?.isStyleLoaded?.() ?? undefined,
169
- weatherBeforeLayerId: this._weatherBeforeLayerId,
170
- options: _debugSanitizeOptions(options),
171
- layerOptions: layerOpts,
172
- coreStateSnapshot: {
173
- isMRMS: this.core.state?.isMRMS,
174
- isSatellite: this.core.state?.isSatellite,
175
- isNexrad: this.core.state?.isNexrad,
176
- model: this.core.state?.model,
177
- variable: this.core.state?.variable,
178
- mrmsDurationValue: this.core.state?.mrmsDurationValue,
179
- mrmsTimestamp: this.core.state?.mrmsTimestamp,
180
- nexradDurationValue: this.core.state?.nexradDurationValue,
181
- satelliteDurationValue: this.core.state?.satelliteDurationValue,
182
- },
183
- });
184
- }
185
-
186
120
  // 2. LISTEN for events from the core engine
187
121
  this.core.on('state:change', (newState) => {
188
122
  this._lastEmittedState = newState;
@@ -203,17 +137,44 @@ export class WeatherLayerManager extends EventEmitter {
203
137
  }
204
138
 
205
139
  /**
206
- * Structured debug log (no-op unless `options.debug === true` on construction).
207
- * @param {string} scope
208
- * @param {object} [data]
140
+ * Logs MRMS timeline facts when `options.mrmsTimelineLog` is enabled (once per distinct snapshot).
141
+ * @param {object} state
209
142
  */
210
- _debugLog(scope, data) {
211
- if (!this._debug) return;
212
- if (data !== undefined) {
213
- console.log(DEBUG_NS, scope, data);
214
- } else {
215
- console.log(DEBUG_NS, scope);
216
- }
143
+ _logMrmsTimelineIfEnabled(state) {
144
+ if (!this._mrmsTimelineLog || !state.isMRMS || !state.variable) return;
145
+ const raw = this.core.mrmsStatus?.[state.variable];
146
+ const rawLen = Array.isArray(raw) ? raw.length : 0;
147
+ const avail = state.availableTimestamps || [];
148
+ const filteredLen = avail.length;
149
+ let spanH = null;
150
+ let minT = null;
151
+ let maxT = null;
152
+ if (filteredLen) {
153
+ const nums = avail.map(Number).filter(Number.isFinite).sort((a, b) => a - b);
154
+ minT = nums[0];
155
+ maxT = nums[nums.length - 1];
156
+ spanH = (maxT - minT) / 3600;
157
+ }
158
+ const key = `${state.variable}|${state.mrmsDurationValue}|${state.mrmsTimestamp}|${rawLen}|${filteredLen}|${minT}|${maxT}`;
159
+ if (key === this._mrmsLogKey) return;
160
+ this._mrmsLogKey = key;
161
+ const rawSpanH =
162
+ rawLen > 1 && Array.isArray(raw)
163
+ ? (Math.max(...raw.map(Number)) - Math.min(...raw.map(Number))) / 3600
164
+ : null;
165
+ console.log('[WeatherLayerManager MRMS]', {
166
+ variable: state.variable,
167
+ durationSettingHours: state.mrmsDurationValue,
168
+ selectedUnix: state.mrmsTimestamp,
169
+ rawStatusScanCount: rawLen,
170
+ rawWallClockSpanHoursApprox: rawSpanH != null ? Number(rawSpanH.toFixed(2)) : null,
171
+ filteredTimelineCount: filteredLen,
172
+ filteredSpanHoursApprox: spanH != null ? Number(spanH.toFixed(2)) : null,
173
+ filteredWindow:
174
+ minT != null && maxT != null ? { minUnix: minT, maxUnix: maxT } : null,
175
+ note:
176
+ 'Timeline cannot extend beyond scans returned by the MRMS status feed; widening "hours" only includes more of that list when older scans exist.',
177
+ });
217
178
  }
218
179
 
219
180
  /**
@@ -262,38 +223,11 @@ export class WeatherLayerManager extends EventEmitter {
262
223
  * @private
263
224
  */
264
225
  _handleStateChange(state) {
265
- const seq = this._debug ? ++this._debugStateSeq : 0;
266
226
  /** NEXRAD setup is async (`sites.show`, frame fetch). `finally` would run before the radar layer exists, so NWS fill stacks above terrain instead of under the custom layer — defer sync until the handler settles. */
267
227
  let deferNwsSyncUntilNexradReady = false;
268
228
  try {
269
- if (this._debug) {
270
- const tsSummary = state.isMRMS
271
- ? _debugSummarizeNumericSeries(state.availableTimestamps || [])
272
- : null;
273
- this._debugLog('state:change', {
274
- seq,
275
- mode: state.isSatellite
276
- ? 'satellite'
277
- : state.isNexrad
278
- ? 'nexrad'
279
- : state.isMRMS
280
- ? 'mrms'
281
- : 'model',
282
- model: state.model,
283
- variable: state.variable,
284
- runKey: `${state.model}-${state.date}-${state.run}-${state.variable}`,
285
- timeKey: state.isMRMS
286
- ? (state.mrmsTimestamp == null ? null : Number(state.mrmsTimestamp))
287
- : Number(state.forecastHour),
288
- mrmsTimestamp: state.mrmsTimestamp,
289
- mrmsDurationValue: state.mrmsDurationValue,
290
- availableTimestampsSummary: tsSummary,
291
- availableHoursLen: Array.isArray(state.availableHours) ? state.availableHours.length : 0,
292
- shaderLayerRunKey: this.shaderLayer?.runKey ?? null,
293
- currentLoadedTimeKey: this.currentLoadedTimeKey,
294
- rebuildId: this.currentRebuildId,
295
- initialGridLoadPending: this._initialGridLoadPending,
296
- });
229
+ if (state.isMRMS) {
230
+ this._logMrmsTimelineIfEnabled(state);
297
231
  }
298
232
 
299
233
  if (state.isSatellite) {
@@ -325,21 +259,6 @@ export class WeatherLayerManager extends EventEmitter {
325
259
  : Number(state.forecastHour);
326
260
  const runKey = `${state.model}-${state.date}-${state.run}-${state.variable}`;
327
261
 
328
- if (this._debug && state.isMRMS) {
329
- this._debugLog('grid path (mrms/model)', {
330
- seq,
331
- prevMrmsDurationValue: prevMrmsDur,
332
- mrmsDurationChanged,
333
- willRebuild: !this.shaderLayer || this.shaderLayer.runKey !== runKey,
334
- willUpdateData:
335
- this.shaderLayer &&
336
- this.shaderLayer.runKey === runKey &&
337
- this.currentLoadedTimeKey !== timeKey,
338
- shaderRunKey: this.shaderLayer?.runKey,
339
- targetRunKey: runKey,
340
- });
341
- }
342
-
343
262
  if (!this.shaderLayer || this.shaderLayer.runKey !== runKey) {
344
263
  this._rebuildLayerAndPreload(state);
345
264
  } else if (this.currentLoadedTimeKey !== timeKey) {
@@ -349,12 +268,6 @@ export class WeatherLayerManager extends EventEmitter {
349
268
  timeKey === this._rebuildTargetTimeKey;
350
269
  if (!duplicateBeforeFirstPaint) {
351
270
  this._updateLayerData(state);
352
- } else if (this._debug) {
353
- this._debugLog('skip _updateLayerData (duplicate before first paint)', {
354
- seq,
355
- timeKey,
356
- _rebuildTargetTimeKey: this._rebuildTargetTimeKey,
357
- });
358
271
  }
359
272
  }
360
273
 
@@ -365,13 +278,6 @@ export class WeatherLayerManager extends EventEmitter {
365
278
  }
366
279
 
367
280
  if (state.isMRMS && this.shaderLayer && mrmsDurationChanged) {
368
- if (this._debug) {
369
- this._debugLog('_preloadAllTimeSteps (mrms duration changed)', {
370
- seq,
371
- from: prevMrmsDur,
372
- to: state.mrmsDurationValue,
373
- });
374
- }
375
281
  this._preloadAllTimeSteps(state);
376
282
  }
377
283
  } finally {
@@ -418,12 +324,17 @@ export class WeatherLayerManager extends EventEmitter {
418
324
  const enabled = masterEnabled && !isModelMode;
419
325
 
420
326
  let timelineUnix = null;
327
+ /** Same list the core uses for the time slider — enables NWS “live edge” (wall clock at latest step) like aguacero-frontend. */
328
+ let timelineTimes = null;
421
329
  if (state.isSatellite) {
422
330
  timelineUnix = state.satelliteTimestamp == null ? null : Number(state.satelliteTimestamp);
331
+ timelineTimes = state.availableSatelliteTimestamps;
423
332
  } else if (state.isNexrad) {
424
333
  timelineUnix = state.nexradTimestamp == null ? null : Number(state.nexradTimestamp);
334
+ timelineTimes = state.availableNexradTimestamps;
425
335
  } else if (state.isMRMS) {
426
336
  timelineUnix = state.mrmsTimestamp == null ? null : Number(state.mrmsTimestamp);
337
+ timelineTimes = state.availableTimestamps;
427
338
  }
428
339
 
429
340
  if (!this._nwsOverlay) {
@@ -453,7 +364,7 @@ export class WeatherLayerManager extends EventEmitter {
453
364
  ...(wopt.activeOnlyRealtime !== undefined ? { activeOnlyRealtime: wopt.activeOnlyRealtime } : {}),
454
365
  },
455
366
  });
456
- this._nwsOverlay.syncWithMode({ enabled, timelineUnix });
367
+ this._nwsOverlay.syncWithMode({ enabled, timelineUnix, timelineTimes });
457
368
  }
458
369
 
459
370
  /**
@@ -784,68 +695,10 @@ export class WeatherLayerManager extends EventEmitter {
784
695
  // to the core engine. This keeps the API consistent for your users.
785
696
 
786
697
  async initialize(options) {
787
- const t0 =
788
- typeof performance !== 'undefined' && typeof performance.now === 'function'
789
- ? performance.now()
790
- : Date.now();
791
- this._debugLog('initialize:start', {
792
- autoRefreshEnabled: this.autoRefreshEnabled,
793
- autoRefreshIntervalSeconds: this.autoRefreshIntervalSeconds,
794
- passedOptions: options && typeof options === 'object' ? { ...options } : options,
795
- coreStateBefore: {
796
- isMRMS: this.core.state?.isMRMS,
797
- variable: this.core.state?.variable,
798
- mrmsTimestamp: this.core.state?.mrmsTimestamp,
799
- mrmsDurationValue: this.core.state?.mrmsDurationValue,
800
- },
801
- mrmsStatusVariableLen: this.core.state?.variable
802
- ? (this.core.mrmsStatus?.[this.core.state.variable]?.length ?? 'n/a')
803
- : 'n/a',
804
- });
805
698
  if (this.autoRefreshEnabled) {
806
699
  this.setAutoRefresh(true, this.autoRefreshIntervalSeconds);
807
700
  }
808
- try {
809
- const result = await this.core.initialize({ ...options, autoRefresh: false });
810
- const t1 =
811
- typeof performance !== 'undefined' && typeof performance.now === 'function'
812
- ? performance.now()
813
- : Date.now();
814
- this._debugLog('initialize:done', {
815
- elapsedMs: Math.round(t1 - t0),
816
- coreStateAfter: {
817
- isMRMS: this.core.state?.isMRMS,
818
- variable: this.core.state?.variable,
819
- model: this.core.state?.model,
820
- date: this.core.state?.date,
821
- run: this.core.state?.run,
822
- forecastHour: this.core.state?.forecastHour,
823
- mrmsTimestamp: this.core.state?.mrmsTimestamp,
824
- mrmsDurationValue: this.core.state?.mrmsDurationValue,
825
- },
826
- availableTimestampsSummary: _debugSummarizeNumericSeries(
827
- this._lastEmittedState?.availableTimestamps || [],
828
- ),
829
- availableHoursLen: Array.isArray(this._lastEmittedState?.availableHours)
830
- ? this._lastEmittedState.availableHours.length
831
- : 0,
832
- modelStatusLoaded: this.core.modelStatus != null,
833
- mrmsStatusKeys:
834
- this.core.mrmsStatus && typeof this.core.mrmsStatus === 'object'
835
- ? Object.keys(this.core.mrmsStatus).length
836
- : 0,
837
- mrmsStatusVariableLen: this.core.state?.variable
838
- ? (this.core.mrmsStatus?.[this.core.state.variable]?.length ?? 0)
839
- : 0,
840
- });
841
- return result;
842
- } catch (err) {
843
- this._debugLog('initialize:error', {
844
- message: err?.message || String(err),
845
- stack: err?.stack,
846
- });
847
- throw err;
848
- }
701
+ return this.core.initialize({ ...options, autoRefresh: false });
849
702
  }
850
703
  async setState(newState) { return this.core.setState(newState); }
851
704
  play() { this.core.play(); }
@@ -892,14 +745,6 @@ export class WeatherLayerManager extends EventEmitter {
892
745
  async setNexradProduct(product) {
893
746
  return this.core.setNexradProduct(product);
894
747
  }
895
- /** @param {'level2'|'level3'} dataSource @param {string} product */
896
- async setNexradProductMode(dataSource, product) {
897
- return this.core.setNexradProductMode(dataSource, product);
898
- }
899
- /** @param {'level2'|'level3'} source */
900
- async setNexradDataSource(source) {
901
- return this.core.setNexradDataSource(source);
902
- }
903
748
  async setNexradTilt(tilt) {
904
749
  return this.core.setNexradTilt(tilt);
905
750
  }
@@ -983,17 +828,6 @@ export class WeatherLayerManager extends EventEmitter {
983
828
  const out = (timeSteps || [])
984
829
  .map(t => Number(t))
985
830
  .filter(t => !Number.isNaN(t));
986
- if (this._debug && state.isMRMS) {
987
- this._debugLog('_collectNormalizedTimelineSteps', {
988
- variable: state.variable,
989
- mrmsDurationValue: state.mrmsDurationValue,
990
- fromStateLen: fromState.length,
991
- fromCoreLen: fromCore.length,
992
- chosenSource: mrmsTimelineSource || (state.isMRMS ? 'n/a' : 'model'),
993
- normalizedLen: out.length,
994
- summary: _debugSummarizeNumericSeries(out),
995
- });
996
- }
997
831
  return out;
998
832
  }
999
833
 
@@ -1008,50 +842,27 @@ export class WeatherLayerManager extends EventEmitter {
1008
842
  if (mode === 'rebuild') {
1009
843
  this._initialGridLoadPending = false;
1010
844
  }
1011
- this._debugLog('_runParallelGridFrameLoads:skip', {
1012
- reason: !times.length ? 'no times' : 'no shaderLayer',
1013
- mode,
1014
- rebuildId,
1015
- timesLen: times.length,
1016
- });
1017
845
  return;
1018
846
  }
1019
847
 
1020
- // Number(null) === 0, which is falsy and causes _loadGridData to return null immediately
1021
- // (the core guards with `if (!mrmsTimestamp) return null`). Treat null as NaN so that
1022
- // primaryTimeForRebuild falls through to times[0] the first real MRMS timestamp.
848
+ // Number(null) === 0 treat null as NaN. For MRMS, when the active timestep is unset,
849
+ // prefer the **newest** scan in the timeline (matches AguaceroCore default); model grids
850
+ // keep using the first forecast hour in the list.
1023
851
  const _rawFrameTime = state.isMRMS ? state.mrmsTimestamp : state.forecastHour;
1024
852
  const currentFrameTime = _rawFrameTime == null ? NaN : Number(_rawFrameTime);
1025
- /** When the active timestep is unset/NaN, paint the first timeline step (legacy single-fetch behavior). */
1026
853
  let primaryTimeForRebuild = Number.NaN;
1027
854
  if (mode === 'rebuild') {
1028
- primaryTimeForRebuild = Number.isFinite(currentFrameTime)
1029
- ? currentFrameTime
1030
- : times[0];
855
+ if (Number.isFinite(currentFrameTime)) {
856
+ primaryTimeForRebuild = currentFrameTime;
857
+ } else if (times.length > 0) {
858
+ const finite = times.map(Number).filter(Number.isFinite);
859
+ primaryTimeForRebuild = state.isMRMS ? Math.max(...finite) : Number(times[0]);
860
+ }
1031
861
  }
1032
862
  const tsKey = state.isMRMS ? 'mrmsTimestamp' : 'forecastHour';
1033
863
  const gridModel = state.isMRMS ? 'mrms' : state.model;
1034
864
  const { gridDef } = this.core._getGridCornersAndDef(gridModel);
1035
865
 
1036
- this._debugLog('_runParallelGridFrameLoads', {
1037
- mode,
1038
- rebuildId,
1039
- gridModel,
1040
- timesLen: times.length,
1041
- timesSummary: _debugSummarizeNumericSeries(times),
1042
- currentFrameTime,
1043
- primaryTimeForRebuild:
1044
- mode === 'rebuild'
1045
- ? Number.isFinite(currentFrameTime)
1046
- ? currentFrameTime
1047
- : times[0]
1048
- : undefined,
1049
- tsKey,
1050
- gridNxNy: gridDef?.grid_params
1051
- ? { nx: gridDef.grid_params.nx, ny: gridDef.grid_params.ny }
1052
- : null,
1053
- });
1054
-
1055
866
  times.forEach((time) => {
1056
867
  const stateForTime = { ...state, [tsKey]: time };
1057
868
  this.core._loadGridData(stateForTime)
@@ -1080,21 +891,10 @@ export class WeatherLayerManager extends EventEmitter {
1080
891
  : Number(this.core.state.mrmsTimestamp))
1081
892
  : Number(this.core.state.forecastHour);
1082
893
  if (coreTimeKey !== this._rebuildTargetTimeKey) {
1083
- this._debugLog('_loadGridData:skip primary (core time drifted vs rebuild target)', {
1084
- time,
1085
- coreTimeKey,
1086
- _rebuildTargetTimeKey: this._rebuildTargetTimeKey,
1087
- rebuildId,
1088
- });
1089
894
  return;
1090
895
  }
1091
896
  }
1092
897
  if (!grid?.data) {
1093
- this._debugLog('_loadGridData:primary frame missing grid.data', {
1094
- time,
1095
- rebuildId,
1096
- mode,
1097
- });
1098
898
  this._initialGridLoadPending = false;
1099
899
  return;
1100
900
  }
@@ -1127,17 +927,9 @@ export class WeatherLayerManager extends EventEmitter {
1127
927
  this.currentLoadedTimeKey = time;
1128
928
  this.map.triggerRepaint();
1129
929
  }
1130
- } else if (this._debug && mode === 'append') {
1131
- this._debugLog('_loadGridData:empty grid (append)', { time, mode, rebuildId });
1132
930
  }
1133
931
  })
1134
- .catch((err) => {
1135
- this._debugLog('_loadGridData:error', {
1136
- time,
1137
- mode,
1138
- rebuildId,
1139
- message: err?.message || String(err),
1140
- });
932
+ .catch(() => {
1141
933
  if (
1142
934
  mode === 'rebuild' &&
1143
935
  Number.isFinite(primaryTimeForRebuild) &&
@@ -1215,26 +1007,8 @@ export class WeatherLayerManager extends EventEmitter {
1215
1007
  if (timesToLoad.length === 0 && !Number.isNaN(currentFrameTime)) {
1216
1008
  timesToLoad = [currentFrameTime];
1217
1009
  }
1218
- this._debugLog('_rebuildLayerAndPreload:timeline', {
1219
- rebuildId,
1220
- isMRMS: state.isMRMS,
1221
- variable: state.variable,
1222
- normalizedLen: normalized.length,
1223
- normalizedSummary: _debugSummarizeNumericSeries(normalized),
1224
- currentFrameTime,
1225
- timesToLoadLen: timesToLoad.length,
1226
- timesToLoadSummary: _debugSummarizeNumericSeries(timesToLoad),
1227
- insertBeforeId: beforeId ?? '(stack top)',
1228
- });
1229
1010
  if (timesToLoad.length === 0) {
1230
1011
  this._initialGridLoadPending = false;
1231
- this._debugLog('_rebuildLayerAndPreload:no times to load — check availableTimestamps / duration window', {
1232
- rebuildId,
1233
- availableTimestampsLen: Array.isArray(state.availableTimestamps)
1234
- ? state.availableTimestamps.length
1235
- : 0,
1236
- mrmsDurationValue: state.mrmsDurationValue,
1237
- });
1238
1012
  return;
1239
1013
  }
1240
1014
 
@@ -1249,21 +1023,11 @@ export class WeatherLayerManager extends EventEmitter {
1249
1023
  const currentFrameTime = _rawPft == null ? NaN : Number(_rawPft);
1250
1024
  const stepsToPreload = normalized.filter(t => t !== currentFrameTime);
1251
1025
 
1252
- this._debugLog('_preloadAllTimeSteps', {
1253
- normalizedLen: normalized.length,
1254
- currentFrameTime,
1255
- stepsToPreloadLen: stepsToPreload.length,
1256
- stepsSummary: _debugSummarizeNumericSeries(stepsToPreload),
1257
- });
1258
-
1259
1026
  if (normalized.length === 0) {
1260
1027
  return;
1261
1028
  }
1262
1029
 
1263
1030
  if (stepsToPreload.length === 0) {
1264
- this._debugLog('_preloadAllTimeSteps:skip (nothing to preload besides current)', {
1265
- currentFrameTime,
1266
- });
1267
1031
  return;
1268
1032
  }
1269
1033
 
@@ -1510,7 +1274,6 @@ export class WeatherLayerManager extends EventEmitter {
1510
1274
  * Cleans up all resources.
1511
1275
  */
1512
1276
  destroy() {
1513
- this._debugLog('destroy');
1514
1277
  this.setAutoRefresh(false);
1515
1278
 
1516
1279
  // 1. Unbind the map's mousemove event listener