Reorganize directory, add manual dataset and sync tooling

- Move all scripts to scripts/, web assets to web/, analysis results
  into self-contained data/readings/<type>_<YYYYMMDD>/ directories
- Add data/readings/manual_20260320/ with 32 JSON readings from
  git.medlab.host/ntnsndr/protocol-bicorder-data
- Add scripts/json_to_csv.py to convert bicorder JSON files to CSV
- Add scripts/sync_readings.sh for one-command sync + re-analysis of
  any dataset backed by a .sync_source config file
- Add scripts/classify_readings.py to apply the LDA classifier to all
  readings and save per-reading cluster assignments
- Add --min-coverage flag to multivariate_analysis.py for sparse/shortform
  datasets; also applies in lda_visualization.py
- Fix lda_visualization.py NaN handling and 0-d array annotation bug
- Update README.md and WORKFLOW.md to document datasets, sync workflow,
  shortform handling, and new scripts

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Nathan Schneider
2026-03-20 17:35:13 -06:00
parent 0c794dddae
commit 897c30406b
545 changed files with 10715 additions and 718 deletions

View File

@@ -0,0 +1,41 @@
import { BicorderClassifier } from './bicorder-classifier.js';
import { fileURLToPath } from 'url';
import path from 'path';
import fs from 'fs';
const __dirname = path.dirname(fileURLToPath(import.meta.url));
const modelPath = path.join(__dirname, '..', 'bicorder_model.json');
const modelData = JSON.parse(fs.readFileSync(modelPath, 'utf8'));
const classifier = new BicorderClassifier(modelData);
console.log('='.repeat(80));
console.log('BICORDER CLASSIFIER - TEST');
console.log('='.repeat(80));
// Test 1
console.log('\nTest 1: Institutional Protocol (e.g., Airport Security)');
console.log('-'.repeat(80));
const institutional = {
'Design_elite_vs_vernacular': 1,
'Design_explicit_vs_implicit': 1,
'Entanglement_flocking_vs_swarming': 1,
'Entanglement_obligatory_vs_voluntary': 1,
};
const result1 = classifier.predict(institutional);
console.log(JSON.stringify(result1, null, 2));
// Test 2
console.log('\n\nTest 2: Relational Protocol (e.g., Indigenous Practices)');
console.log('-'.repeat(80));
const relational = {
'Design_elite_vs_vernacular': 9,
'Entanglement_flocking_vs_swarming': 9,
'Entanglement_obligatory_vs_voluntary': 9,
};
const result2 = classifier.predict(relational);
console.log(JSON.stringify(result2, null, 2));
console.log('\n\n' + '='.repeat(80));
console.log('✓ JavaScript classifier working correctly!');
console.log(' Model size:', Math.round(fs.statSync(modelPath).size / 1024), 'KB');
console.log('='.repeat(80));