We're in the middle of integrating Eric Kansa's 4 query functions from oc_parquet_analysis_enhanced.ipynb into /tutorials/parquet_cesium.qmd.
Phase 1: Documentation (Commit d5d6690)
- ✅ Added comprehensive Path 1/Path 2 explanation with diagrams
- ✅ Added full relationship map (Agent, IdentifiedConcept paths)
- ✅ Added Eric's 4 query function analysis with summary table
Phase 2: First Query Implementation (Commit 3224eb1)
- ✅ Implemented
get_samples_at_geo_cord_location_via_sample_event() - ✅ Combines Path 1 + Path 2 with UNION
- ✅ Returns rich metadata: thumbnail_url, description, alternate_identifiers, site info
- ✅ Added reactive cell
selectedSamplesCombinedwith loading state - ✅ Added display section "Combined Samples at Location"
Remaining 2 queries from Eric's notebook (cell 59):
-
Agent Query -
get_sample_data_agents_sample_pid(sample_pid)- Shows who collected/registered samples
- Path: MaterialSampleRecord → produced_by → SamplingEvent → {responsibility, registrant} → Agent
- Returns: sample metadata + agent info (agent_pid, agent_name, predicate)
- Note: Independent of Path 1/Path 2 (no geographic data needed)
-
Keywords/Concepts Query -
get_sample_types_and_keywords_via_sample_pid(sample_pid)- Shows material types and classifications
- Path: MaterialSampleRecord → {keywords, has_sample_object_type, has_material_category} → IdentifiedConcept
- Returns: sample metadata + concept info (keyword_pid, keyword, predicate)
- Note: Direct edges to concepts, bypasses SamplingEvent entirely!
Table alias difference:
- Eric's Python notebook uses:
FROM pqg AS ... - Our JavaScript implementation uses:
FROM nodes ... - DuckDB view is created as:
CREATE VIEW nodes AS SELECT * FROM read_parquet('${parquet_path}')
Loading pattern to follow:
async function get_FUNCTION_NAME(pid) {
if (pid === null || pid ==="" || pid == "unset") return [];
const q = `SQL QUERY HERE`;
const result = await loadData(q, [pid], "loading_ID", "key");
return result ?? [];
}
mutable FUNCTIONLoading = false;
selectedFUNCTION = {
mutable FUNCTIONLoading = true;
try {
return await get_FUNCTION_NAME(clickedPointId);
} finally {
mutable FUNCTIONLoading = false;
}
}Display pattern:
## Section Title
<div id="loading_ID" hidden>Loading message…</div>
Explanation text...
\`\`\`{ojs}
//| echo: false
variable = selectedFUNCTION
FUNCTIONLoading ? md`(loading…)` : md`\`\`\`
${JSON.stringify(variable, null, 2)}
\`\`\`
`
\`\`\`Main working file: /Users/raymondyee/C/src/iSamples/isamplesorg.github.io/tutorials/parquet_cesium.qmd
Reference notebook: /Users/raymondyee/C/src/iSamples/isamples-python/examples/basic/oc_parquet_analysis_enhanced.ipynb (cell 59)
Local parquet: http://localhost:4979/assets/oc_isamples_pqg.parquet (691MB, in docs/assets/)
Branch: issue-13-parquet-duckdb
# Navigate to project
cd /Users/raymondyee/C/src/iSamples/isamplesorg.github.io
# Check current branch
git status
# Start Quarto preview (if needed)
quarto preview
# View notebook for reference
code /Users/raymondyee/C/src/iSamples/isamples-python/examples/basic/oc_parquet_analysis_enhanced.ipynb"Let's continue integrating Eric's queries into parquet_cesium.qmd. We completed Phase 2 (combined samples query). Next we need to add the agent query and keywords/concepts query. Should we start with the agent query?"
- All existing queries (
get_samples_1,get_samples_2,get_samples_at_geo_cord_location_via_sample_event) are working and preserved - Pattern is established - just need to adapt Eric's remaining 2 SQL queries to JavaScript
- Consider UI improvements after Phase 3 complete (tables, clickable links, thumbnails)