Skip to content

Commit 1e4a473

Browse files
rdhyeeclaude
andcommitted
Implement differentiated geographic visualization with color-coding
MAJOR FEATURE: Geographic locations now color-coded by semantic role Query Changes: - Add CTE to classify GeospatialCoordLocations by usage type - Join with edges to determine sample_location vs site_location usage - Return location_type field: 'sample_location_only', 'site_location_only', 'both' Visualization Changes: - Blue (3px): sample_location_only - precise field collection points (Path 1) - Purple (6px): site_location_only - administrative site markers (Path 2) - Orange (5px): both - dual-purpose locations (~10k geos) Implementation Details: - Use Cesium.Color.fromCssColorString() for hex colors (#2E86AB, #A23B72, #F18F01) - Conditional styling per point based on location_type - Updated Data tab table header to show location_type column Documentation Updates: - Changed "Future Enhancement" to "✅ IMPLEMENTED" - Added color legend with emoji indicators - Updated SQL example to use 'nodes' table (not 'pqg') - Documented performance impact (minimal) - Listed future enhancements (UI filters, Site Explorer Mode) Benefits: - Makes Path 1 vs Path 2 distinction visually concrete - Users can SEE semantic difference between precise and administrative locations - Transforms visualization into pedagogical tool for understanding iSamples model 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
1 parent 96f68d8 commit 1e4a473

File tree

1 file changed

+76
-29
lines changed

1 file changed

+76
-29
lines changed

tutorials/parquet_cesium.qmd

Lines changed: 76 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -119,19 +119,56 @@ async function loadData(query, params = [], waiting_id = null, key = "default")
119119
}
120120
121121
locations = {
122-
// get the content form the parquet file
123-
const query = `SELECT pid, latitude, longitude FROM nodes WHERE otype='GeospatialCoordLocation'`;
122+
// Get geographic locations with classification by usage type
123+
const query = `
124+
WITH geo_classification AS (
125+
SELECT
126+
geo.pid,
127+
geo.latitude,
128+
geo.longitude,
129+
MAX(CASE WHEN e.p = 'sample_location' THEN 1 ELSE 0 END) as is_sample_location,
130+
MAX(CASE WHEN e.p = 'site_location' THEN 1 ELSE 0 END) as is_site_location
131+
FROM nodes geo
132+
JOIN nodes e ON (geo.row_id = e.o[1])
133+
WHERE geo.otype = 'GeospatialCoordLocation'
134+
GROUP BY geo.pid, geo.latitude, geo.longitude
135+
)
136+
SELECT
137+
pid,
138+
latitude,
139+
longitude,
140+
CASE
141+
WHEN is_sample_location = 1 AND is_site_location = 1 THEN 'both'
142+
WHEN is_sample_location = 1 THEN 'sample_location_only'
143+
WHEN is_site_location = 1 THEN 'site_location_only'
144+
END as location_type
145+
FROM geo_classification
146+
`;
124147
const data = await loadData(query, [], "loading_1", "locations");
125148
126149
// Clear the existing PointPrimitiveCollection
127150
content.points.removeAll();
128-
//content.points = new Cesium.PointPrimitiveCollection();
129151
130-
// create point primitives for cesium display
152+
// Color and size styling by location type
153+
const styles = {
154+
sample_location_only: {
155+
color: Cesium.Color.fromCssColorString('#2E86AB'),
156+
size: 3
157+
}, // Blue - field collection points
158+
site_location_only: {
159+
color: Cesium.Color.fromCssColorString('#A23B72'),
160+
size: 6
161+
}, // Purple - administrative markers
162+
both: {
163+
color: Cesium.Color.fromCssColorString('#F18F01'),
164+
size: 5
165+
} // Orange - dual-purpose
166+
};
167+
168+
// Create point primitives for cesium display
131169
const scalar = new Cesium.NearFarScalar(1.5e2, 2, 8.0e6, 0.2);
132-
const color = Cesium.Color.PINK;
133-
const point_size = 4;
134170
for (const row of data) {
171+
const style = styles[row.location_type] || styles.both; // fallback to orange
135172
content.points.add({
136173
id: row.pid,
137174
// https://cesium.com/learn/cesiumjs/ref-doc/Cartesian3.html#.fromDegrees
@@ -140,8 +177,8 @@ locations = {
140177
row.latitude, //latitude
141178
0,//randomCoordinateJitter(10.0, 10.0), //elevation, m
142179
),
143-
pixelSize: point_size,
144-
color: color,
180+
pixelSize: style.size,
181+
color: style.color,
145182
scaleByDistance: scalar,
146183
});
147184
}
@@ -463,10 +500,10 @@ md`Retrieved ${pointdata.length} locations from ${parquet_path}.`;
463500
viewof pointdata = {
464501
const data_table = Inputs.table(locations, {
465502
header: {
466-
row_id:"Row ID",
467503
pid: "PID",
468504
latitude: "Latitude",
469-
longitude: "Longitude"
505+
longitude: "Longitude",
506+
location_type: "Location Type"
470507
},
471508
});
472509
return data_table;
@@ -679,12 +716,16 @@ ${JSON.stringify(samples_combined, null, 2)}
679716
`
680717
```
681718

682-
## Design Note: Differentiated Geographic Visualization
719+
## Geographic Location Classification
683720

684-
::: {.callout-note icon=false}
685-
## Future Enhancement - Geographic Location Classification
721+
::: {.callout-tip icon=false}
722+
## ✅ IMPLEMENTED - Differentiated Geographic Visualization
686723

687-
**Current implementation**: All 198,433 GeospatialCoordLocations are rendered identically (orange points), without differentiating their semantic roles in the graph.
724+
**Current implementation**: GeospatialCoordLocations are now color-coded by their semantic role in the property graph:
725+
726+
- 🔵 **Blue (small)** - `sample_location_only`: Precise field collection points (Path 1)
727+
- 🟣 **Purple (large)** - `site_location_only`: Administrative site markers (Path 2)
728+
- 🟠 **Orange (medium)** - `both`: Dual-purpose locations (used for both Path 1 and Path 2)
688729

689730
**Discovery**: Analysis of the OpenContext parquet data reveals that geos fall into three distinct categories based on their usage:
690731

@@ -730,19 +771,19 @@ const styles = {
730771
☐ Highlight overlap points only (10,346 dual-purpose geos)
731772
```
732773

733-
**Query modification needed**:
774+
**Implementation - Classification Query**:
734775

735776
```sql
736-
-- Add classification to geo query
777+
-- Classify geos by usage type
737778
WITH geo_classification AS (
738779
SELECT
739780
geo.pid,
740781
geo.latitude,
741782
geo.longitude,
742783
MAX(CASE WHEN e.p = 'sample_location' THEN 1 ELSE 0 END) as is_sample_location,
743784
MAX(CASE WHEN e.p = 'site_location' THEN 1 ELSE 0 END) as is_site_location
744-
FROM pqg geo
745-
JOIN pqg e ON (geo.row_id = list_extract(e.o, 1))
785+
FROM nodes geo
786+
JOIN nodes e ON (geo.row_id = e.o[1])
746787
WHERE geo.otype = 'GeospatialCoordLocation'
747788
GROUP BY geo.pid, geo.latitude, geo.longitude
748789
)
@@ -791,20 +832,26 @@ User clicks PKAP Survey Area marker (purple)
791832

792833
### Implementation Status
793834

794-
**Status**: Design note only - not yet implemented
835+
**Status**: ✅ **IMPLEMENTED** (Basic color-coding by location type)
836+
837+
**What's implemented**:
838+
- ✅ Classification query with CTE (lines 123-146)
839+
- ✅ Conditional styling by location_type (lines 153-166)
840+
- ✅ Color-coded points: Blue (sample_location), Purple (site_location), Orange (both)
841+
- ✅ Size differentiation: 3px (field points), 6px (sites), 5px (dual-purpose)
795842

796-
**Implementation complexity**: Moderate
797-
- Query modification: Simple (add classification CTE)
798-
- Client-side rendering: Medium (conditional styling in Cesium primitives)
799-
- UI controls: Medium (checkbox filters + event handlers)
800-
- Advanced features: High (site explorer mode with interactive highlighting)
843+
**Performance impact**:
844+
- Query execution time increased slightly due to JOIN and GROUP BY
845+
- Same 198k points rendered, now with semantic color coding
846+
- No noticeable performance degradation in browser rendering
801847

802-
**Performance impact**: Minimal
803-
- Same 198k points, just enriched with `location_type` metadata
804-
- Filtering happens client-side (fast)
805-
- Could add server-side aggregation for zoom-based LOD
848+
**Future enhancements** (not yet implemented):
849+
- ⬜ UI filter controls (checkbox toggles for each location type)
850+
- ⬜ Site Explorer Mode (click site → highlight all sample_locations)
851+
- ⬜ Convex hull/region drawing for distributed sites
852+
- ⬜ Dynamic statistics display on site selection
806853

807-
This enhancement would transform the visualization from "pretty dots on a map" into a pedagogical tool for understanding the iSamples metadata model architecture.
854+
This implementation transforms the visualization from uniform points into a pedagogical tool that visually demonstrates the Path 1 vs Path 2 distinction in the iSamples metadata model architecture.
808855

809856
:::
810857
```

0 commit comments

Comments
 (0)