@@ -788,72 +788,86 @@ md`Retrieved ${pointdata.length} locations from ${parquet_path}.`;
788788 console.log("Classifying dots by type...");
789789 performance.mark('classify-start');
790790
791- // Run the classification query
792- const query = `
793- WITH geo_classification AS (
791+ try {
792+ // Run the classification query
793+ const query = `
794+ WITH geo_classification AS (
795+ SELECT
796+ geo.pid,
797+ MAX(CASE WHEN e.p = 'sample_location' THEN 1 ELSE 0 END) as is_sample_location,
798+ MAX(CASE WHEN e.p = 'site_location' THEN 1 ELSE 0 END) as is_site_location
799+ FROM nodes geo
800+ JOIN nodes e ON (geo.row_id = e.o[1])
801+ WHERE geo.otype = 'GeospatialCoordLocation'
802+ GROUP BY geo.pid
803+ )
794804 SELECT
795- geo.pid,
796- MAX(CASE WHEN e.p = 'sample_location' THEN 1 ELSE 0 END) as is_sample_location,
797- MAX(CASE WHEN e.p = 'site_location' THEN 1 ELSE 0 END) as is_site_location
798- FROM nodes geo
799- JOIN nodes e ON (geo.row_id = e.o[1])
800- WHERE geo.otype = 'GeospatialCoordLocation'
801- GROUP BY geo.pid
802- )
803- SELECT
804- pid,
805- CASE
806- WHEN is_sample_location = 1 AND is_site_location = 1 THEN 'both'
807- WHEN is_sample_location = 1 THEN 'sample_location_only'
808- WHEN is_site_location = 1 THEN 'site_location_only'
809- END as location_type
810- FROM geo_classification
811- `;
812-
813- const classifications = await db.query(query);
814-
815- // Build lookup map: pid -> location_type
816- const typeMap = new Map();
817- for (const row of classifications) {
818- typeMap.set(row.pid, row.location_type);
819- }
805+ pid,
806+ CASE
807+ WHEN is_sample_location = 1 AND is_site_location = 1 THEN 'both'
808+ WHEN is_sample_location = 1 THEN 'sample_location_only'
809+ WHEN is_site_location = 1 THEN 'site_location_only'
810+ END as location_type
811+ FROM geo_classification
812+ `;
813+
814+ const classifications = await db.query(query);
815+
816+ // Build lookup map: pid -> location_type
817+ const typeMap = new Map();
818+ for (const row of classifications) {
819+ typeMap.set(row.pid, row.location_type);
820+ }
820821
821- // Color and size styling by location type
822- const styles = {
823- sample_location_only: {
824- color: Cesium.Color.fromCssColorString('#2E86AB'),
825- size: 3
826- }, // Blue - field collection points
827- site_location_only: {
828- color: Cesium.Color.fromCssColorString('#A23B72'),
829- size: 6
830- }, // Purple - administrative markers
831- both: {
832- color: Cesium.Color.fromCssColorString('#F18F01'),
833- size: 5
834- } // Orange - dual-purpose
835- };
836-
837- // Update colors of existing points
838- const points = content.points;
839- for (let i = 0; i < points.length; i++) {
840- const point = points.get(i);
841- const pid = point.id;
842- const locationType = typeMap.get(pid);
843-
844- if (locationType && styles[locationType]) {
845- point.color = styles[locationType].color;
846- point.pixelSize = styles[locationType].size;
822+ // Color and size styling by location type
823+ const styles = {
824+ sample_location_only: {
825+ color: Cesium.Color.fromCssColorString('#2E86AB'),
826+ size: 3
827+ }, // Blue - field collection points
828+ site_location_only: {
829+ color: Cesium.Color.fromCssColorString('#A23B72'),
830+ size: 6
831+ }, // Purple - administrative markers
832+ both: {
833+ color: Cesium.Color.fromCssColorString('#F18F01'),
834+ size: 5
835+ } // Orange - dual-purpose
836+ };
837+
838+ // Update colors of existing points
839+ const points = content.points;
840+ for (let i = 0; i < points.length; i++) {
841+ const point = points.get(i);
842+ const pid = point.id;
843+ const locationType = typeMap.get(pid);
844+
845+ if (locationType && styles[locationType]) {
846+ point.color = styles[locationType].color;
847+ point.pixelSize = styles[locationType].size;
848+ }
847849 }
848- }
849850
850- performance.mark('classify-end');
851- performance.measure('classification', 'classify-start', 'classify-end');
852- const classifyTime = performance.getEntriesByName('classification')[0].duration;
853- console.log(`Classification completed in ${classifyTime.toFixed(0)}ms - updated ${points.length} points`);
854- console.log(` - Blue (sample_location_only): field collection points`);
855- console.log(` - Purple (site_location_only): administrative markers`);
856- console.log(` - Orange (both): dual-purpose locations`);
851+ performance.mark('classify-end');
852+ performance.measure('classification', 'classify-start', 'classify-end');
853+ const classifyTime = performance.getEntriesByName('classification')[0].duration;
854+ console.log(`Classification completed in ${classifyTime.toFixed(0)}ms - updated ${points.length} points`);
855+ console.log(` - Blue (sample_location_only): field collection points`);
856+ console.log(` - Purple (site_location_only): administrative markers`);
857+ console.log(` - Orange (both): dual-purpose locations`);
858+ } catch (error) {
859+ console.error("Classification failed:", error);
860+ console.error("Error details:", error.message);
861+
862+ // Show user-friendly message in browser console
863+ console.warn("⚠️ Color-coding failed due to a data loading issue.");
864+ console.warn("💡 Tip: This is an intermittent DuckDB-WASM issue with remote files.");
865+ console.warn(" Try clicking the button again, or use a local cached file for better reliability.");
866+ console.warn(" See the 'Using a local cached file' section above for instructions.");
867+
868+ // Note: We don't show an alert() to avoid disrupting the user experience
869+ // The page remains functional, just without the color-coding
870+ }
857871 }
858872}
859873```
0 commit comments