GeoDA Tools
The @openassistant/geoda package provides comprehensive spatial statistics and analysis tools powered by GeoDa algorithms running in WebAssembly.
Installation
bash
npm install @openassistant/geodaAvailable Tools
Data Classification
dataClassify- Classify numerical data into bins using various statistical methods
Spatial Statistics
globalMoran- Global Moran's I for spatial autocorrelationlisa- Local Indicators of Spatial Association (LISA)
Spatial Regression
regression- OLS and spatial regression models
Spatial Weights
spatialWeights- Create spatial weights matrices (queen, rook, knn, distance-based)
Spatial Operations
area- Calculate areas of polygonsbuffer- Create buffer zones around featurescentroid- Calculate centroids of geometriesdissolve- Dissolve adjacent polygonsgrid- Create regular gridslength- Calculate lengths of line featuresperimeter- Calculate perimeters of polygonsthiessenPolygons- Generate Thiessen/Voronoi polygonsmst- Minimum spanning treecartogram- Create cartograms
Spatial Join
spatialJoin- Join features based on spatial relationshipsspatialFilter- Filter features spatially
Variable Operations
variable- Create new variables from existing onesrate- Calculate rates and ratios
Basic Usage
Using Data Classification
typescript
import { dataClassify } from '@openassistant/geoda';
import { Assistant, type AssistantOptions } from '@openassistant/assistant';
const DATASETS = {
counties: [
{ name: 'County A', population: 100000, income: 50000 },
{ name: 'County B', population: 200000, income: 75000 },
// ...more counties
],
};
const dataClassifyTool = {
...dataClassify,
context: {
getValues: async (datasetName: string, variableName: string) => {
return DATASETS[datasetName].map((item) => item[variableName]);
},
},
};
const config: AssistantOptions = {
ai: {
getInstructions: () => `
You can classify data using various statistical methods.
Available dataset: counties with fields: name, population, income
`,
tools: {
dataClassify: dataClassifyTool,
},
},
};
export function App() {
return <Assistant options={config} />;
}Spatial Weights with Spatial Statistics
typescript
import { spatialWeights, globalMoran, lisa } from '@openassistant/geoda';
import { Assistant } from '@openassistant/assistant';
import { ToolCache } from '@openassistant/utils';
const toolResultCache = ToolCache.getInstance();
const GEOJSON_DATASETS = {
neighborhoods: {
type: 'FeatureCollection',
features: [
{
type: 'Feature',
geometry: { type: 'Polygon', coordinates: [[...]] },
properties: { name: 'Downtown', crime_rate: 45.2 },
},
// ...more features
],
},
};
const spatialWeightsTool = {
...spatialWeights,
context: {
getGeometries: async (datasetName: string) => {
return [GEOJSON_DATASETS[datasetName]];
},
},
onToolCompleted: (toolCallId, additionalData) => {
toolResultCache.addDataset(toolCallId, additionalData);
},
};
const globalMoranTool = {
...globalMoran,
context: {
getGeometries: async (datasetName: string) => {
return [GEOJSON_DATASETS[datasetName]];
},
getValues: async (datasetName: string, variableName: string) => {
return GEOJSON_DATASETS[datasetName].features.map(
(f) => f.properties[variableName]
);
},
getWeights: async (weightsId: string) => {
if (toolResultCache.hasDataset(weightsId)) {
return toolResultCache.getDataset(weightsId);
}
throw new Error(`Weights ${weightsId} not found`);
},
},
};
const lisaTool = {
...lisa,
context: {
getGeometries: async (datasetName: string) => {
return [GEOJSON_DATASETS[datasetName]];
},
getValues: async (datasetName: string, variableName: string) => {
return GEOJSON_DATASETS[datasetName].features.map(
(f) => f.properties[variableName]
);
},
getWeights: async (weightsId: string) => {
if (toolResultCache.hasDataset(weightsId)) {
return toolResultCache.getDataset(weightsId);
}
throw new Error(`Weights ${weightsId} not found`);
},
},
};
const config = {
ai: {
getInstructions: () => `
You can perform spatial analysis on the neighborhoods dataset.
Steps: 1) Create spatial weights, 2) Run spatial statistics
Available dataset: neighborhoods with field: crime_rate
`,
tools: {
spatialWeights: spatialWeightsTool,
globalMoran: globalMoranTool,
lisa: lisaTool,
},
},
};
export function App() {
return <Assistant options={config} />;
}Using Spatial Operations
typescript
import { buffer, centroid, area } from '@openassistant/geoda';
import { Assistant } from '@openassistant/assistant';
const GEOJSON_DATASETS = {
schools: {
type: 'FeatureCollection',
features: [
{
type: 'Feature',
geometry: { type: 'Point', coordinates: [-122.4, 37.7] },
properties: { name: 'School A' },
},
// ...more schools
],
},
};
const bufferTool = {
...buffer,
context: {
getGeometries: async (datasetName: string) => {
return [GEOJSON_DATASETS[datasetName]];
},
},
};
const centroidTool = {
...centroid,
context: {
getGeometries: async (datasetName: string) => {
return [GEOJSON_DATASETS[datasetName]];
},
},
};
const areaTool = {
...area,
context: {
getGeometries: async (datasetName: string) => {
return [GEOJSON_DATASETS[datasetName]];
},
},
};
const config = {
ai: {
getInstructions: () => `
You can perform spatial operations on datasets.
Available dataset: schools (point features)
`,
tools: {
buffer: bufferTool,
centroid: centroidTool,
area: areaTool,
},
},
};
export function App() {
return <Assistant options={config} />;
}Example User Prompts
The AI can respond to prompts like:
- "Classify the income data into 5 classes using natural breaks"
- "Create queen contiguity weights for the neighborhoods dataset"
- "Test for spatial autocorrelation in crime rates"
- "Find crime hotspots using LISA analysis"
- "Create a 500-meter buffer around schools"
- "Calculate the area of each neighborhood"
Complete Example: Hotspot Analysis
typescript
import { dataClassify, spatialWeights, lisa } from '@openassistant/geoda';
import { keplergl } from '@openassistant/map';
import { KeplerGlComponent } from '@openassistant/keplergl';
import { ToolCache } from '@openassistant/utils';
import { Assistant, type AssistantOptions } from '@openassistant/assistant';
const toolResultCache = ToolCache.getInstance();
const DATASETS = {
neighborhoods: {
type: 'FeatureCollection',
features: [
{
type: 'Feature',
geometry: { type: 'Polygon', coordinates: [[...]] },
properties: { name: 'Area 1', crime_rate: 45.2 },
},
// ...more neighborhoods
],
},
};
const dataClassifyTool = {
...dataClassify,
context: {
getValues: async (datasetName, variableName) => {
return DATASETS[datasetName].features.map((f) => f.properties[variableName]);
},
},
};
const spatialWeightsTool = {
...spatialWeights,
context: {
getGeometries: async (datasetName) => [DATASETS[datasetName]],
},
onToolCompleted: (toolCallId, additionalData) => {
toolResultCache.addDataset(toolCallId, additionalData);
},
};
const lisaTool = {
...lisa,
context: {
getGeometries: async (datasetName) => [DATASETS[datasetName]],
getValues: async (datasetName, variableName) => {
return DATASETS[datasetName].features.map((f) => f.properties[variableName]);
},
getWeights: async (weightsId) => {
return toolResultCache.getDataset(weightsId);
},
},
onToolCompleted: (toolCallId, additionalData) => {
toolResultCache.addDataset(toolCallId, additionalData);
},
};
const keplerglTool = {
...keplergl,
context: {
getDataset: async (datasetName) => {
if (toolResultCache.hasDataset(datasetName)) {
return toolResultCache.getDataset(datasetName);
}
return DATASETS[datasetName];
},
},
component: KeplerGlComponent,
};
const config: AssistantOptions = {
ai: {
getInstructions: () => `
You can analyze spatial patterns in the neighborhoods dataset.
Available dataset: neighborhoods with field: crime_rate
For hotspot analysis:
1. Create spatial weights using queen contiguity
2. Run LISA analysis on crime_rate
3. Visualize the results on a map
`,
tools: {
dataClassify: dataClassifyTool,
spatialWeights: spatialWeightsTool,
lisa: lisaTool,
keplergl: keplerglTool,
},
},
};
export function App() {
return <Assistant options={config} />;
}Performance Considerations
- WebAssembly: All spatial computations run in WASM for optimal performance
- Large Datasets: Consider simplifying geometries for very large datasets
- Weights Caching: Spatial weights can be cached and reused via ToolCache
- Browser Environment: Most tools are designed to run in the browser
API Reference
For detailed API documentation, see the GeoDA API Reference.
Next Steps
- Map Tools - Visualize spatial analysis results
- Plots Tools - Create charts from analysis results
- DuckDB Tools - Query spatial data with SQL
