@@ -221,7 +221,7 @@ function updateSampleDetail(detail) {
221221 : '';
222222 el.innerHTML = `${desc ? `<div style="font-size: 12px; color: #444; margin-top: 6px; line-height: 1.4;">${desc}</div>` : ''}
223223 <div style="margin-top: 8px;">
224- <a class="detail-link" href="zenodo_isamples_analysis.html" target="_blank">Open in Analysis Tool →</a>
224+ <a class="detail-link" href="zenodo_isamples_analysis.html" target="_blank" rel="noopener noreferrer" >Open in Analysis Tool →</a>
225225 </div>`;
226226}
227227
@@ -363,7 +363,7 @@ viewer = {
363363 const delta = meta.resolution === 4 ? 2.0 : meta.resolution === 6 ? 0.5 : 0.1;
364364 try {
365365 const samples = await db.query(`
366- SELECT pid, label, n as source, latitude, longitude, description
366+ SELECT pid, label, source, latitude, longitude, description
367367 FROM read_parquet('${lite_url}')
368368 WHERE latitude BETWEEN ${meta.lat - delta} AND ${meta.lat + delta}
369369 AND longitude BETWEEN ${meta.lng - delta} AND ${meta.lng + delta}
@@ -393,7 +393,6 @@ phase1 = {
393393 SELECT h3_cell, sample_count, center_lat, center_lng,
394394 dominant_source, source_count
395395 FROM read_parquet('${h3_res4_url}')
396- ORDER BY sample_count DESC
397396 `);
398397
399398 const scalar = new Cesium.NearFarScalar(1.5e2, 1.5, 8.0e6, 0.5);
@@ -414,7 +413,7 @@ phase1 = {
414413
415414 performance.mark('p1-end');
416415 performance.measure('p1', 'p1-start', 'p1-end');
417- const elapsed = performance.getEntriesByName('p1')[0] .duration;
416+ const elapsed = performance.getEntriesByName('p1').pop() .duration;
418417
419418 updateStats('H3 Res4', data.length, totalSamples, `${(elapsed/1000).toFixed(1)}s`);
420419 updatePhaseMsg(`${data.length.toLocaleString()} clusters, ${totalSamples.toLocaleString()} samples. Zoom in for finer detail.`, 'done');
@@ -453,40 +452,45 @@ zoomWatcher = {
453452 loading = true;
454453 updatePhaseMsg(`Loading H3 res${res}...`, 'loading');
455454
456- performance.mark(`r${res}-s`);
457- const data = await db.query(`
458- SELECT h3_cell, sample_count, center_lat, center_lng,
459- dominant_source, source_count
460- FROM read_parquet('${url}')
461- ORDER BY sample_count DESC
462- `);
463-
464- viewer.h3Points.removeAll();
465- const scalar = new Cesium.NearFarScalar(1.5e2, 1.5, 8.0e6, 0.3);
466- let total = 0;
455+ try {
456+ performance.mark(`r${res}-s`);
457+ const data = await db.query(`
458+ SELECT h3_cell, sample_count, center_lat, center_lng,
459+ dominant_source, source_count
460+ FROM read_parquet('${url}')
461+ `);
467462
468- for (const row of data) {
469- total += row.sample_count;
470- const size = Math.min(3 + Math.log10(row.sample_count) * 3.5, 18);
471- viewer.h3Points.add({
472- id: { count: row.sample_count, source: row.dominant_source, lat: row.center_lat, lng: row.center_lng, resolution: res },
473- position: Cesium.Cartesian3.fromDegrees(row.center_lng, row.center_lat, 0),
474- pixelSize: size,
475- color: Cesium.Color.fromCssColorString(SOURCE_COLORS[row.dominant_source] || '#666').withAlpha(0.85),
476- scaleByDistance: scalar,
477- });
478- }
463+ viewer.h3Points.removeAll();
464+ const scalar = new Cesium.NearFarScalar(1.5e2, 1.5, 8.0e6, 0.3);
465+ let total = 0;
466+
467+ for (const row of data) {
468+ total += row.sample_count;
469+ const size = Math.min(3 + Math.log10(row.sample_count) * 3.5, 18);
470+ viewer.h3Points.add({
471+ id: { count: row.sample_count, source: row.dominant_source, lat: row.center_lat, lng: row.center_lng, resolution: res },
472+ position: Cesium.Cartesian3.fromDegrees(row.center_lng, row.center_lat, 0),
473+ pixelSize: size,
474+ color: Cesium.Color.fromCssColorString(SOURCE_COLORS[row.dominant_source] || '#666').withAlpha(0.85),
475+ scaleByDistance: scalar,
476+ });
477+ }
479478
480- performance.mark(`r${res}-e`);
481- performance.measure(`r${res}`, `r${res}-s`, `r${res}-e`);
482- const elapsed = performance.getEntriesByName(`r${res}`)[0] .duration;
479+ performance.mark(`r${res}-e`);
480+ performance.measure(`r${res}`, `r${res}-s`, `r${res}-e`);
481+ const elapsed = performance.getEntriesByName(`r${res}`).pop() .duration;
483482
484- updateStats(`H3 Res${res}`, data.length, total, `${(elapsed/1000).toFixed(1)}s`);
485- updatePhaseMsg(`${data.length.toLocaleString()} clusters, ${total.toLocaleString()} samples. ${res < 8 ? 'Zoom in for finer detail.' : 'Zoom closer for individual samples.'}`, 'done');
483+ updateStats(`H3 Res${res}`, data.length, total, `${(elapsed/1000).toFixed(1)}s`);
484+ updatePhaseMsg(`${data.length.toLocaleString()} clusters, ${total.toLocaleString()} samples. ${res < 8 ? 'Zoom in for finer detail.' : 'Zoom closer for individual samples.'}`, 'done');
486485
487- currentRes = res;
488- loading = false;
489- console.log(`Res${res}: ${data.length} clusters in ${elapsed.toFixed(0)}ms`);
486+ currentRes = res;
487+ console.log(`Res${res}: ${data.length} clusters in ${elapsed.toFixed(0)}ms`);
488+ } catch(err) {
489+ console.error(`Failed to load res${res}:`, err);
490+ updatePhaseMsg(`Failed to load H3 res${res} — try zooming again.`, 'loading');
491+ } finally {
492+ loading = false;
493+ }
490494 };
491495
492496 // --- Get camera viewport bounds ---
0 commit comments