{"id":44415054,"url":"https://github.com/akspa0/floppyai","last_synced_at":"2026-02-12T08:22:25.314Z","repository":{"id":315625677,"uuid":"1060267967","full_name":"akspa0/floppyai","owner":"akspa0","description":"Experimental Kryoflux STREAM file parsing tools","archived":false,"fork":false,"pushed_at":"2025-09-19T17:58:05.000Z","size":36,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2025-09-19T18:44:48.608Z","etag":null,"topics":["experimental","floppy-disks","kryoflux","lm-studio","retrocomputing"],"latest_commit_sha":null,"homepage":"","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/akspa0.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2025-09-19T16:26:13.000Z","updated_at":"2025-09-19T17:58:09.000Z","dependencies_parsed_at":"2025-09-19T18:55:43.577Z","dependency_job_id":null,"html_url":"https://github.com/akspa0/floppyai","commit_stats":null,"previous_names":["akspa0/floppyai"],"tags_count":null,"template":false,"template_full_name":null,"purl":"pkg:github/akspa0/floppyai","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/akspa0%2Ffloppyai","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/akspa0%2Ffloppyai/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/akspa0%2Ffloppyai/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/akspa0%2Ffloppyai/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/akspa0","download_url":"https://codeload.github.com/akspa0/floppyai/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/akspa0%2Ffloppyai/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":29361815,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-02-12T01:03:07.613Z","status":"online","status_checked_at":"2026-02-12T02:00:06.911Z","response_time":55,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["experimental","floppy-disks","kryoflux","lm-studio","retrocomputing"],"created_at":"2026-02-12T08:22:21.712Z","updated_at":"2026-02-12T08:22:25.298Z","avatar_url":"https://github.com/akspa0.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"# FloppyAI\n\n\u003cp align=\"center\"\u003e\n  \u003ca href=\"src/samples/disk1_composite_report.png\"\u003e\n    \u003cimg src=\"src/samples/disk1_composite_report.png\" alt=\"Sample per-disk composite report\" width=\"600\" /\u003e\n  \u003c/a\u003e\n  \u003cbr/\u003e\n  \u003cem\u003eSample per‑disk composite: flux plots, polar disk surface (both sides), density/variance by track\u003c/em\u003e\n \u003c/p\u003e\n\nFloppyAI visualizes KryoFlux STREAM flux data to study the magnetic surface of floppy disks. It assumes no filesystem/sectors by default and focuses on flux behavior: density per track, instability, angular structure, and interval distributions. Perfect for experiments and media/head tolerance studies.\n\n## Quick Start: Visualize KryoFlux Streams\n\n1) Capture STREAMs on Linux (KryoFlux DTC)\n- Use the provided forensic‑rich scripts to capture flux with many revolutions and cooldowns:\n  - `scripts/linux/capture_forensic_full_disk.sh`\n  - `scripts/linux/capture_forensic_repeat_track.sh`\n  - `scripts/linux/capture_forensic_sweep.sh`\n  - `scripts/linux/capture_forensic_long_rev.sh`\n- See the full guide: `FloppyAI/docs/forensic_capture_guide.md`.\n\n2) Analyze on Windows (or any machine with Python)\n```bash\npython FloppyAI/src/main.py analyze_disk .\\captures\\\u003cyour_run_folder\u003e \\\n  --profile 35HD \\\n  --output-dir .\\test_outputs\\\u003cname\u003e\n```\n\n3) Open the outputs\n- `\u003cname\u003e_disk_surface.png` — Side 0 | Side 1 polar density per track\n- `\u003cname\u003e_instability_map.png` — Both sides instability (bright hotspots; auto-contrast)\n- `\u003cname\u003e_side0_report.png`, `\u003cname\u003e_side1_report.png` — Per‑side composite:\n  - Top: density polar (optional sector overlays)\n  - Middle‑left: instability polar\n  - Middle‑right: angular heatmap (track × angle)\n  - Bottom‑right: aggregated flux interval histogram (log ns)\n- `surface_map.json`, `run.log` — Provenance and stats\n\nNotes:\n- Default export is PNG; SVG for large reports will be added where appropriate.\n- Profiles set RPM and bias overlay heuristics. Supported: `35HD`, `35DD`, `525HD`, `525DD`, plus GCR variants `35HDGCR`, `35DDGCR`, `525DDGCR`.\n\n## How to Run\n\n- Recommended: run directly from the repository root\n```bash\npython FloppyAI/src/main.py --help\n```\n- Alternate: module mode also works from the repository root\n```bash\npython -m FloppyAI.src.main --help\n```\n\n## Documentation\n\n- Docs Index: [docs/index.md](docs/index.md)\n- Usage Guide: [docs/usage.md](docs/usage.md)\n- Cheatsheet: [docs/cheatsheet.md](docs/cheatsheet.md)\n\n## Common Tasks\n\n- Analyze a full disk (PC 3.5\" DD/HD with MFM overlays; overlay mode is auto from profile)\n  ```bash\n  python FloppyAI/src/main.py analyze_disk .\\stream_dumps\\example_disk \\\n    --profile 35DD --format-overlay --align-to-sectors auto --label-sectors \\\n    --output-dir .\\test_outputs\\example_run\n  ```\n\n- Analyze a Mac GCR disk (400K/800K) with zoned overlays (auto candidates by profile)\n  ```bash\n  python FloppyAI/src/main.py analyze_disk .\\stream_dumps\\mac_example \\\n    --profile 35DDGCR --format-overlay --align-to-sectors auto --label-sectors \\\n    --output-dir .\\test_outputs\\mac_example\n  ```\n\n- Compare two reads (requires each to have surface_map.json)\n  ```bash\n  python FloppyAI/src/main.py compare_reads .\\test_outputs\\run_A .\\test_outputs\\run_B \\\n    --output-dir .\\test_outputs\\diff_example\n  ```\n\n- Build a corpus and auto-generate missing per-disk maps\n  ```bash\n  python FloppyAI/src/main.py analyze_corpus .\\stream_dumps \\\n    --generate-missing --profile 35HD \\\n    --format-overlay \\\n    --output-dir .\\test_outputs\\corpus\n  ```\n\n### analyze_corpus\n```\npython FloppyAI/src/main.py analyze_corpus \u003croot_or_map.json\u003e [--generate-missing] [--rpm FLOAT] [--profile 35HD|35DD|35HDGCR|35DDGCR|525HD|525DD|525DDGCR] [--summarize] \\\n  [--lm-host HOST:PORT] [--lm-model MODEL] [--lm-temperature 0.2] [--output-dir]\n```\nOutputs are placed under `test_outputs/\u003ctimestamp\u003e/disks/\u003cdisk-label\u003e/`. If you provide `--output-dir` to analyze_corpus, that directory is used instead of a timestamp.\n\nNotes on RPM/Profile:\n- `--rpm` accepts any float; if provided, it overrides `--profile`.\n- `--profile` maps common drives and formats to RPM and overlay bias: `35HD`/`35DD` → 300 (MFM), `525HD` → 360 (MFM), `525DD` → 300 (MFM), `35DDGCR`/`35HDGCR`/`525DDGCR` → 300 (GCR).\n- `--generate-missing` will propagate effective RPM and overlay flags to each `analyze_disk` call.\n\n### analyze_disk\n```\npython FloppyAI/src/main.py analyze_disk \u003cpath-to-dir-or-raw\u003e [--rpm FLOAT] [--profile 35HD|35DD|35HDGCR|35DDGCR|525HD|525DD|525DDGCR] [--summarize] [--lm-host HOST:PORT] \\\n  [--lm-model MODEL] [--lm-temperature 0.2] [--output-dir]\n```\nSaves `surface_map.json`, flux plots, the combined polar disk‑surface (`\u003clabel\u003e_surface_disk_surface.png`), per‑side high‑res surfaces (`\u003clabel\u003e_surface_side0.png`, `..._side1.png`), Instability Map (`\u003clabel\u003e_instability_map.png`), Instability CSV (`\u003clabel\u003e_instability_summary.csv`), and a composite image (`\u003clabel\u003e_composite_report.png`).\n\n### analyze (single .raw)\n```\npython FloppyAI/src/main.py analyze \u003cinput.raw\u003e [--output-dir]\n```\nGenerates per-file flux plots and stats.\n\n## Installation\n\n1. Python 3.8+ and `pip`.\n2. `pip install -r requirements.txt`.\n3. Hardware: KryoFlux connected.\n   - Local (Windows) setups: DTC.exe in `../lib/kryoflux_3.50_windows_r2/dtc/`.\n   - Cross‑machine setups: If DTC is on a Linux host (sudo required), do not attempt to orchestrate DTC from Windows. Instead, generate `.raw` on Windows, run write/read via bash scripts on the Linux host, then analyze on Windows. See `docs/usage.md` → “Cross‑machine (Linux DTC) workflow”.\n4. Optional LLM: run LM Studio locally and pass `--lm-host` and `--lm-model`.\n\n## Disk Surface Visualization\n\nPolar map shows average bits‑per‑revolution per track (radius = track index). Both sides are in one figure with the colorbar to the right. Output naming uses input‑derived labels for clarity.\n\nHigh‑fidelity rendering:\n- Combined polar and Instability maps are saved at high DPI with increased angular resolution and radial upsampling for smooth imagery.\n- Per‑side high‑res surfaces are provided to inspect each side independently while preserving a shared density scale.\n\nInstability and Structure:\n- For each track/side we compute `instability_score` (0‑1) and a simple `structure_score` (0‑1). These are saved into `surface_map.json` and summarized in `\u003clabel\u003e_instability_summary.csv`.\n- The composite prefers the Instability Map panel; if unavailable, it falls back to the revolution heatmap.\n\n### Instability: definition and interpretation\n\n- Instability measures repeatability of transition patterns across revolutions at each angle. Brighter regions in the panels indicate angles that vary more between spins.\n- It is not an audio‑like waveform or a decoded data visualization; it’s a statistical repeatability map derived from flux transitions.\n- Format structures (sectors/gaps) and small mechanical effects can create wedge‑like angular patterns; that does not imply synthetic content.\n- Verify with `surface_map.json` per track/side: `analysis.instability_theta`, `analysis.instability_features`, `analysis.instability_score`.\n- Learn more: see [docs/instability.md](docs/instability.md).\n\nSingle‑sided detection:\n- We detect likely single‑sided disks either by very low Side‑1 coverage or by near‑duplicate Side‑1 vs Side‑0 density radials.\n- When detected, the composite title includes “Single‑sided (S1 missing|duplicated)”, and `surface_map.json` records the reason and coverage metrics under `global.insights`.\n\n### Format‑Aware Overlays (MFM \u0026 GCR)\n\nFloppyAI can draw sector‑arc overlays on the polar surface maps and persist the detected boundaries to JSON.\n\nNote: overlays are non‑synthetic guides (spokes/labels only). They do not add fill or alter the underlying data.\n\n- Enable overlays via:\n  - `--format-overlay`\n  - `--overlay-mode mfm|gcr|auto` (default `auto`, profile‑driven)\n  - `--angular-bins N` (resolution; default auto by quality)\n  - `--gcr-candidates` is optional; for GCR profiles sensible defaults are chosen automatically (e.g., `12,11,10,9,8` for 400K/800K Mac).\n\nWhat the options mean:\n- `--overlay-mode mfm` uses an FFT+autocorrelation method to estimate the dominant sector count per revolution and phase (typical IBM MFM counts: 8, 9, 15, 18).\n- `--overlay-mode gcr` uses a boundary‑contrast search tailored for Apple GCR media (e.g., classic Macintosh 400K/800K). It tests a set of hypothesized sector counts and picks the one with the strongest gap contrast.\n- `--overlay-mode auto` defers to profile first and may cross‑check; you can still force a mode explicitly if needed.\n- `--gcr-candidates` is only needed for unusual media; GCR profiles auto‑select good candidates (`12,11,10,9,8` for classic Mac).\n\nChoosing good GCR candidates:\n- If you know the likely format, put the expected k first. For many classic Mac GCR tracks, 10 or 12 are common; include neighbors to be safe (e.g., `12,10,8,9,11,13`).\n- If you don’t know, use a wider set (e.g., `6,7,8,9,10,11,12,13,14`), and optionally increase `--angular-bins` (e.g., 900) for finer phase resolution.\n- For IBM MFM (PC) media, you can use `--overlay-mode mfm` and ignore GCR candidates.\n\nOutputs written when overlays are enabled:\n- Per‑disk images (in the selected `--output-dir` or timestamped run):\n  - `\u003clabel\u003e_surface_disk_surface_overlay.png` (both sides)\n  - `\u003clabel\u003e_surface_side0_overlay.png`, `\u003clabel\u003e_surface_side1_overlay.png`\n- Per‑disk JSON:\n  - `surface_map.json` includes `global.insights.overlay.by_side[\"0\"|\"1\"] = { sector_count, boundaries_deg[], confidence, method }`\n  - Per‑track hints: `surface_map[\"\u003ctrack\u003e\"].overlay[\"0\"|\"1\"]`\n  - `overlay_debug.json` contains only the overlay block for quick inspection.\n\nCorpus behavior with overlays:\n- `analyze_corpus` aggregates any `surface_map.json` it finds under the input root. Use `--generate-missing` to build per‑disk maps first (propagates overlay flags to those runs).\n- A manifest `corpus_inputs.txt` is written under `run_dir/corpus/` listing exactly which maps were consumed. If none are found, `corpus_no_inputs.txt` explains the search root.\n\nExamples:\n```\n# MFM (PC) overlays (auto-picked by profile)\npython FloppyAI/src/main.py analyze_disk .\\streams\\pc_disk --profile 35HD --format-overlay --align-to-sectors auto --label-sectors\n\n# GCR (Mac) overlays (auto candidates by profile)\npython FloppyAI/src/main.py analyze_disk .\\streams\\mac_disk --profile 35DDGCR --format-overlay --align-to-sectors auto --label-sectors\n\n# Corpus from raw streams, generating per‑disk maps first\npython FloppyAI/src/main.py analyze_corpus .\\stream_dumps --generate-missing --profile 35DDGCR --format-overlay\n```\n\n#### Interpreting overlay visuals\n\n- The overlay draws radial spokes at the detected sector boundary angles (`boundaries_deg`). Your eye sees the wedges between spokes as sector \"slices\".\n- The number of spokes equals the detected `sector_count` (k). For example, k=10 yields lines every 36°.\n- For MFM (IBM‑like) media, k is usually constant per side (e.g., 9, 15, 18) and the spokes are evenly spaced.\n- For Mac GCR 400K/800K (CLV with zones), k can differ by radius (track). The per‑side overlay is a single aggregate; per‑track overlays recorded in `surface_map.json` show the zoned variation. If aggregate confidence is low, the tool falls back to the per‑track median k.\n- Confidence reflects how much the boundary windows look like gaps (low transition density) compared to within‑sector windows. Low confidence suggests weak periodicity or heavy zoning across the tracks used.\n\n#### Improving overlay visibility\n\n- Use `--overlay-color` to change line color and `--overlay-alpha` to change opacity.\n- Examples:\n  - Bright red, 80% opacity:\n    ```\n    --overlay-color \"#ff3333\" --overlay-alpha 0.8\n    ```\n  - Bright yellow, 70% opacity:\n    ```\n    --overlay-color \"#ffd60a\" --overlay-alpha 0.7\n    ```\n- Increase `--angular-bins` (e.g., 900) for finer phase alignment if the lines look off.\n\n#### Troubleshooting\n\n- Empty or all‑around spokes at tiny increments usually mean a bad fallback. Re‑run with:\n  - A sensible `--gcr-candidates` list for Mac GCR, e.g., `\"12,11,10,9,8\"`.\n  - Moderate `--angular-bins` (720–1080).\n  - If using `--overlay-mode auto` on Mac disks, pass `--media-type 35DD` to bias auto toward GCR.\n- If per‑side detection remains weak on GCR, consult per‑track overlays in `surface_map.json`:\n  - `\"\u003ctrack\u003e\".overlay[\"0\"|\"1\"].sector_count` shows the zoned k per track.\n  - The per‑side overlay will fall back to the median per‑track k when confidence is low.\n\n## Notes\n\n- Outputs respect `--output-dir` without adding timestamps. If omitted, `test_outputs/\u003ctimestamp\u003e/` is used.\n- We intentionally avoid sector/FS assumptions to focus on physical surface characteristics.\n- The corpus overlays and per-disk labels prefer stream file names.\n- Cross‑machine Linux DTC: See `docs/usage.md` → “Cross‑machine (Linux DTC) workflow” for the recommended manual script-based process.\n\n### Linux DTC Script (on the hardware host)\n\nWhen running hardware on a Linux host, you can use the helper script to write then read with DTC:\n```bash\nchmod +x FloppyAI/scripts/linux/dtc_write_read.sh\nFloppyAI/scripts/linux/dtc_write_read.sh \\\n  --write /path/to/generated.raw --track 80 --side 0 --revs 3 \\\n  --out-dir ./captures --drive 0\n```\nThis produces a timestamped capture in `--out-dir` along with a `.log` containing the exact `dtc` commands and version used. Adjust flags to suit your environment; sudo is used by default (pass `--no-sudo` to disable).\n\n## Commands\n\n1. **Analyze a Stream File** (Decode and visualize `.raw`):\n   ```\n   python FloppyAI/src/main.py analyze \u003cinput.raw\u003e [--output-dir]\n   ```\n   - Parses flux transitions, computes stats (mean interval, noise variance).\n   - Detects anomalies (short/long cells, weak bits via rev inconsistencies).\n   - Generates plots: \u003cinput\u003e_intervals.png (time series), \u003cinput\u003e_hist.png (distribution), \u003cinput\u003e_heatmap.png (if multi-rev).\n   - Example: `python FloppyAI/src/main.py analyze example_stream_data/example00.0.raw`\n     - Output: Stats like \"Mean Interval: 4000.50 ns\", \"Short Cells: 5\", visualizations saved.\n   - For blanks: High variance indicates surface irregularities; low anomalies = clean media.\n\n2. **Read Track from Hardware**:\n  ```\n  python FloppyAI/src/main.py read \u003ctrack\u003e \u003cside\u003e [--revs 3] [--simulate] [--analyze] [--output-dir]\n  ```\n  - Reads track/side (e.g., 0 0) to .raw using DTC.\n  - --revs: Revolutions (default 3 for better analysis).\n  - --simulate: Dry-run without hardware (no-op).\n  - --analyze: Auto-analyze output .raw.\n  - --rpm: Known RPM for normalization (default 360).\n  - Note: This command assumes local DTC availability. For cross‑machine Linux DTC setups, use the Linux bash scripts on that host and then analyze the captured `.raw` on Windows.\n   - Use for blanks: Reveals baseline flux noise for custom encoding.\n\n3. **Write Stream to Hardware**:\n  ```\n  python FloppyAI/src/main.py write \u003cinput.raw\u003e \u003ctrack\u003e \u003cside\u003e [--simulate] [--output-dir]\n  ```\n  - Writes .raw to track/side.\n  - --simulate: Dry-run (logs command).\n  - Test custom flux on blanks to explore readability.\n  - Note: This command assumes local DTC availability. For cross‑machine setups, perform the write on the Linux DTC host via bash scripts.\n\n4. **Generate Dummy Stream** (Build custom flux for testing):\n   ```\n   python FloppyAI/src/main.py generate \u003ctrack\u003e \u003cside\u003e [--revs 1] [--cell 4000] [--analyze] [--output-dir]\n   ```\n  - --revs: Number of revolutions.\n  - --cell: Nominal cell length ns (vary for density: shorter = higher density).\n  - --analyze: Auto-analyze output.\n  - --rpm: Known RPM for normalization (default 360).\n  - Example: `python FloppyAI/src/main.py generate 0 0 --cell 2000 --analyze`\n  - Generates denser flux; analyze to see interval distribution.\n\n5. **Encode Binary Data to Custom Stream** (Prototype higher density encoding):\n   ```\n   python FloppyAI/src/main.py encode \u003cinput.bin\u003e \u003ctrack\u003e \u003cside\u003e [--density 1.0] [--variable] [--revs 1] [--output \u003coutput.raw\u003e] [--write] [--simulate] [--analyze] [--rpm 360] [--output-dir]\n   ```\n   - Encodes binary file to .raw using Manchester or variable RLL-like flux encoding.\n   - --density: Scaling factor (\u003e1.0 shortens cells for higher density; e.g., 2.0 for ~2x bits).\n   - --variable: Use RLL-like variable cell lengths (short for 0s, long for 1s) for advanced packing.\n   - --revs: Revolutions to fill (repeats data to embed continuously).\n   - --output: Custom .raw path (default: encoded_track_X_Y.raw in timestamp dir).\n   - --write: Auto-write .raw to hardware track/side after generation.\n   - --simulate: Dry-run for --write (no hardware).\n   - --analyze: Auto-analyze generated .raw (check density estimate vs. achieved).\n   - --rpm: Known RPM for normalization (default 360).\n   - Outputs achieved density (bits/rev) based on input size.\n   - Example: `python FloppyAI/src/main.py encode test_data.bin 0 0 --density 2.0 --variable --rpm 360 --analyze`\n     - Encodes 1KB data at 2x density with variable cells; prints ~8192 bits/rev (vs. standard ~4000); analyzes for noise/readability.\n   - For density testing: Compare bits/rev in output to standard (analyze dummy at density=1.0); higher = success if low anomalies.\n\n6. **Decode Custom Stream** (Recover binary data from encoded .raw):\n   ```\n   python FloppyAI/src/main.py decode \u003cinput.raw\u003e [--density 1.0] [--variable] [--revs 1] [--output \u003coutput.bin\u003e] [--expected \u003coriginal.bin\u003e] [--rpm 360] [--output-dir]\n   ```\n   - Decodes flux to binary using matching parameters.\n   - --density: Expected density used in encoding.\n   - --variable: Assume RLL-like variable cells.\n   - --revs: Number of revolutions.\n   - --output: Custom .bin path.\n   - --expected: Original .bin for verification (reports % match, byte errors).\n   - --rpm: Known RPM for normalization (default 360).\n   - Example: `python FloppyAI/src/main.py decode test_encoded.raw --density 2.0 --variable --rpm 360 --expected test_data.bin`\n     - Outputs test_decoded.bin; verifies 100% recovery for all-zero data (perfect for blanks).\n\n7. **Analyze Disk Surface** (Batch process streams for full disk map):\n   ```\n   python FloppyAI/src/main.py analyze_disk [input] [--track N] [--side 0|1] [--rpm 360] [--output-dir] [--summarize]\n   ```\n   - input: Optional directory or single .raw file (default: example_stream_data/). Globs all *.raw if dir; auto-batches parent dir if single numbered file and siblings exist.\n   - Parses track/side from filename ending in \\d+\\.\\d+\\.raw (e.g., MyDisk00.0.raw → track 0 side 0); handles concatenated prefixes (e.g., prefix180.1.raw → track 80 side 1).\n   - Filters to tracks 0-83, sides 0-1; processes in order (00.0, 00.1, ..., 83.1), logging found vs expected (up to 168 files).\n   - Use --track/--side for manual override if unparsable (applies to all files if no pattern).\n   - --rpm: Known RPM for normalization/validation (default 360; scales partial reads to full rev, computes drift_pct ~0-5%, normalized densities).\n   - Outputs surface_map.json: Per-track/side list of files with stats/analysis (normalized mean/std intervals, protection_score 0-1 from anomalies/variance, max_theoretical_density ~rev_time/min_int, is_protected \u003e0.3); includes side summaries (avg_protection, likely_protected) and global (side_diff, packing_potential).\n   - Generates combined PNG visualizations for entire disk (intervals, histogram, heatmap) and side_density_heatmap.png (bar charts of density per track/side, highlighting protection asymmetry).\n   - --summarize: Auto-generates LLM-powered report. The tool now requests a strict JSON summary from the LLM and saves it to `llm_summary.json`, then renders the narrative to `llm_summary.txt`.\n     - `--lm-temperature 0.2` recommended for accurate numeric reporting.\n     - `--summary-format json|text` controls whether to write JSON plus text (json, default) or only text (text).\n     - Works best with coder/instruct models like Qwen2-Coder Instruct.\n   - Per-run outputs (in `--output-dir` if provided, otherwise under `test_outputs/\u003ctimestamp\u003e/`):\n     - `\u003clabel\u003e_surface_disk_surface.png` (combined polar map for Side 0 and Side 1)\n     - `\u003clabel\u003e_density_by_track.png`, `\u003clabel\u003e_variance_by_track.png`\n     - `\u003clabel\u003e_composite_report.png` (single composite image)\n   - `\u003clabel\u003e` is derived from the input stream filename or folder name.\n   - Examples:\n     - Default batch: `python FloppyAI/src/main.py analyze_disk`\n     - Full disk dir: `python FloppyAI/src/main.py analyze_disk .\\stream_dumps\\\u003cdisk_label\u003e\\kryoflux_stream`\n     - With normalization/summary: `python FloppyAI/src/main.py analyze_disk [path] --rpm 360 --summarize --lm-host HOST[:PORT] --lm-model MODEL_NAME`\n\n8. **Compare Reads** (Diff multiple reads of the same disk):\n  ```\n  python FloppyAI/src/main.py compare_reads \u003cpath_or_dir1\u003e \u003cpath_or_dir2\u003e [\u003c...\u003e] [--output-dir DIR]\n  ```\n  - Each item can be a surface_map.json or a directory containing one. Ensure you ran `analyze_disk` for each read first.\n  - Outputs: `diff/diff_summary.json`, `diff/diff_densities.csv`\n  - Example:\n    - `python FloppyAI/src/main.py compare_reads .\\test_outputs\\run_A .\\test_outputs\\run_B --output-dir .\\test_outputs\\diff_example`\n\n9. **Classify Surface** (Blank-like vs written-like labels):\n   ```\n   python FloppyAI/src/main.py classify_surface \u003csurface_map.json\u003e [--blank-density-thresh 1000] [--output-dir DIR]\n   ```\n   - Writes `classification.json` with labels per track/side.\n\n10. **Plan Pool** (Select top-quality tracks for a dense bit pool):\n   ```\n   python FloppyAI/src/main.py plan_pool \u003csurface_map.json\u003e [--min-density 2000] [--top-percent 0.2] [--output-dir DIR]\n   ```\n   - Writes `pool_plan.json` with selected tracks per side.\n\n## Tips\n- Use `--rpm 360` (or `--profile 525HD`) to normalize stats for 1.2MB 5.25\" drives; use `--rpm 300` (or `--profile 35HD/35DD`) for 3.5\".\n- The composite title includes a simple HD/DD heuristic based on mean cell interval length.\n- Run `analyze_disk` on blanks vs formatted to compare surfaces; use Instability Map and per‑side images to guide placement.\n- LLM summaries use strict JSON schemas and deterministic fallbacks when no valid measurements are present.\n\n## Next Steps\n- Integrate AI EC (phase 3): Train models on surface map for error prediction, puzzle‑like patterns.\n- LLM Enhancements: Customize prompts or integrate more models via LM Studio; tune per‑disk narrative schemas as needed.\n- See [`docs/roadmap.md`](docs/roadmap.md) for the roadmap.\n\nFor issues, ensure running from the repository root and use `python FloppyAI/src/main.py` (or module mode as an alternative).","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fakspa0%2Ffloppyai","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fakspa0%2Ffloppyai","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fakspa0%2Ffloppyai/lists"}