# penn-electric-racing/per-data-analyzer architecture

> Architecture diagram of the GitHub repository penn-electric-racing/per-data-analyzer, generated by GitDiagram from its file tree, README and a sample of source files (last updated 2026-09-27). It is an AI-made overview: check details against the source.

- Interactive diagram: https://gitdiagram.com/penn-electric-racing/per-data-analyzer
- Repository: https://github.com/penn-electric-racing/per-data-analyzer

## Overview

PER-Data-Analyzer is an in-house telemetry log parsing and analysis library. Its main workflow loads a CSV into an Analyzer, parses signals into per-variable time-series data, optionally preprocesses and searches that data, then exposes plotting and analysis results. It also supports multi-run collections, live CDP access, and remote log retrieval. The excerpts establish the CSV, Analyzer, search, plotting, and remote-download links; unsampled utility and collection internals are represented without speculative wiring.

Main entry points: [`perda/analyzer/analyzer.py`](https://github.com/penn-electric-racing/per-data-analyzer/blob/main/perda/analyzer/analyzer.py) (Analyzer API), [`perda/core_data_structures/data_instance.py`](https://github.com/penn-electric-racing/per-data-analyzer/blob/main/perda/core_data_structures/data_instance.py) (Data Instance), [`perda/core_data_structures/single_run_data.py`](https://github.com/penn-electric-racing/per-data-analyzer/blob/main/perda/core_data_structures/single_run_data.py) (Single Run Data), [`perda/server.py`](https://github.com/penn-electric-racing/per-data-analyzer/blob/main/perda/server.py) (Remote Loader)

## Diagram (Mermaid)

```mermaid
flowchart TD

subgraph group_ingest["Log Ingestion"]
  node_csv["CSV Parser<br/>[csv.py]"]
  node_analyzer["Analyzer API<br/>[analyzer.py]"]
  node_remote_loader["Remote Loader<br/>[server.py]"]
  node_collections["Run Collections<br/>[run_collection.py]"]
end

subgraph group_data["Telemetry Data"]
  node_single_run["Single Run Data<br/>[single_run_data.py]"]
  node_instance["Data Instance<br/>[data_instance.py]"]
  node_preprocess["Preprocessing<br/>[preprocessing.py]"]
  node_joins["Alignment and Joins<br/>[joins.py]"]
  node_resampling["Resampling<br/>[resampling.py]"]
end

subgraph group_analysis["Analysis Tools"]
  node_search["Signal Search<br/>[search.py]"]
  node_indexes["Search Indexes<br/>[search_indexes.py]"]
  node_signal_tools["Signal Analysis"]
  node_frequency["Frequency Analysis"]
  node_gps["GPS Analysis<br/>[gps_analysis.py]"]
  node_summary["Data Summary<br/>[data_summary.py]"]
end

subgraph group_interfaces["Access and Output"]
  node_plot_api["Plot API<br/>[analyzer.py]"]
  node_plotter["Signal Plotters"]
  node_subplots["Subplot Builder<br/>[subplots.py]"]
  node_live["Live Analyzer<br/>[live_analyzer.py]"]
  node_cdp["CDP Client<br/>[cdp_client.py]"]
end

node_user(("Analyst"))
node_remote{{"Data Server"}}
node_s3[("S3 Log Bucket")]

node_user -->|"loads log"| node_analyzer
node_analyzer -->|"parses CSV"| node_csv
node_csv -->|"builds data"| node_single_run
node_csv -->|"builds signals"| node_instance
node_analyzer -->|"applies steps"| node_preprocess
node_preprocess -->|"transforms data"| node_single_run
node_single_run -->|"stores indexes"| node_indexes
node_analyzer -->|"searches signals"| node_search
node_search -->|"uses index"| node_indexes
node_search -->|"reads signals"| node_single_run
node_analyzer -->|"plots data"| node_plot_api
node_plot_api -->|"renders signals"| node_plotter
node_plot_api -->|"builds subplots"| node_subplots
node_plotter -->|"reads series"| node_instance
node_subplots -->|"reads series"| node_instance
node_collections -->|"manages runs"| node_single_run
node_instance -->|"aligns series"| node_joins
node_instance -->|"resamples series"| node_resampling
node_user -->|"requests log"| node_remote_loader
node_remote_loader -->|"authenticates"| node_remote
node_remote_loader -->|"downloads log"| node_s3
node_remote_loader -->|"loads download"| node_analyzer
node_user -->|"uses live data"| node_live
node_live -->|"requests data"| node_cdp
node_cdp -.->|"communicates"| node_remote

click node_csv "https://github.com/penn-electric-racing/per-data-analyzer/blob/main/perda/analyzer/csv.py"
click node_analyzer "https://github.com/penn-electric-racing/per-data-analyzer/blob/main/perda/analyzer/analyzer.py"
click node_remote_loader "https://github.com/penn-electric-racing/per-data-analyzer/blob/main/perda/server.py"
click node_collections "https://github.com/penn-electric-racing/per-data-analyzer/blob/main/perda/analyzer/run_collection.py"
click node_single_run "https://github.com/penn-electric-racing/per-data-analyzer/blob/main/perda/core_data_structures/single_run_data.py"
click node_instance "https://github.com/penn-electric-racing/per-data-analyzer/blob/main/perda/core_data_structures/data_instance.py"
click node_preprocess "https://github.com/penn-electric-racing/per-data-analyzer/blob/main/perda/utils/preprocessing.py"
click node_joins "https://github.com/penn-electric-racing/per-data-analyzer/blob/main/perda/core_data_structures/joins.py"
click node_resampling "https://github.com/penn-electric-racing/per-data-analyzer/blob/main/perda/core_data_structures/resampling.py"
click node_search "https://github.com/penn-electric-racing/per-data-analyzer/blob/main/perda/utils/search.py"
click node_indexes "https://github.com/penn-electric-racing/per-data-analyzer/blob/main/perda/core_data_structures/search_indexes.py"
click node_signal_tools "https://github.com/penn-electric-racing/per-data-analyzer/blob/main/perda/utils/signal_processing.py"
click node_frequency "https://github.com/penn-electric-racing/per-data-analyzer/blob/main/perda/utils/frequency_analysis.py"
click node_gps "https://github.com/penn-electric-racing/per-data-analyzer/blob/main/perda/utils/gps_analysis.py"
click node_summary "https://github.com/penn-electric-racing/per-data-analyzer/blob/main/perda/utils/data_summary.py"
click node_plot_api "https://github.com/penn-electric-racing/per-data-analyzer/blob/main/perda/analyzer/analyzer.py"
click node_plotter "https://github.com/penn-electric-racing/per-data-analyzer/blob/main/perda/plotting/data_instance_plotter.py"
click node_subplots "https://github.com/penn-electric-racing/per-data-analyzer/blob/main/perda/plotting/subplots.py"
click node_live "https://github.com/penn-electric-racing/per-data-analyzer/blob/main/perda/live/live_analyzer.py"
click node_cdp "https://github.com/penn-electric-racing/per-data-analyzer/blob/main/perda/live/cdp_client.py"

classDef toneNeutral fill:#f8fafc,stroke:#334155,stroke-width:1.5px,color:#0f172a
classDef toneBlue fill:#dbeafe,stroke:#2563eb,stroke-width:1.5px,color:#172554
classDef toneAmber fill:#fef3c7,stroke:#d97706,stroke-width:1.5px,color:#78350f
classDef toneMint fill:#dcfce7,stroke:#16a34a,stroke-width:1.5px,color:#14532d
classDef toneRose fill:#ffe4e6,stroke:#e11d48,stroke-width:1.5px,color:#881337
classDef toneIndigo fill:#e0e7ff,stroke:#4f46e5,stroke-width:1.5px,color:#312e81
classDef toneTeal fill:#ccfbf1,stroke:#0f766e,stroke-width:1.5px,color:#134e4a
class node_csv,node_analyzer,node_remote_loader,node_collections toneBlue
class node_single_run,node_instance,node_preprocess,node_joins,node_resampling,node_s3 toneAmber
class node_search,node_indexes,node_signal_tools,node_frequency,node_gps,node_summary,node_remote toneMint
class node_plot_api,node_plotter,node_subplots,node_live,node_cdp toneRose
class node_user toneIndigo
```

## Components

### Log Ingestion

- [CSV Parser](https://github.com/penn-electric-racing/per-data-analyzer/blob/main/perda/analyzer/csv.py): `perda/analyzer/csv.py`
- [Analyzer API](https://github.com/penn-electric-racing/per-data-analyzer/blob/main/perda/analyzer/analyzer.py): `perda/analyzer/analyzer.py`
- [Remote Loader](https://github.com/penn-electric-racing/per-data-analyzer/blob/main/perda/server.py): `perda/server.py`
- [Run Collections](https://github.com/penn-electric-racing/per-data-analyzer/blob/main/perda/analyzer/run_collection.py): `perda/analyzer/run_collection.py`

### Telemetry Data

- [Single Run Data](https://github.com/penn-electric-racing/per-data-analyzer/blob/main/perda/core_data_structures/single_run_data.py): `perda/core_data_structures/single_run_data.py`
- [Data Instance](https://github.com/penn-electric-racing/per-data-analyzer/blob/main/perda/core_data_structures/data_instance.py): `perda/core_data_structures/data_instance.py`
- [Preprocessing](https://github.com/penn-electric-racing/per-data-analyzer/blob/main/perda/utils/preprocessing.py): `perda/utils/preprocessing.py`
- [Alignment and Joins](https://github.com/penn-electric-racing/per-data-analyzer/blob/main/perda/core_data_structures/joins.py): `perda/core_data_structures/joins.py`
- [Resampling](https://github.com/penn-electric-racing/per-data-analyzer/blob/main/perda/core_data_structures/resampling.py): `perda/core_data_structures/resampling.py`

### Analysis Tools

- [Signal Search](https://github.com/penn-electric-racing/per-data-analyzer/blob/main/perda/utils/search.py): `perda/utils/search.py`
- [Search Indexes](https://github.com/penn-electric-racing/per-data-analyzer/blob/main/perda/core_data_structures/search_indexes.py): `perda/core_data_structures/search_indexes.py`
- [Signal Analysis](https://github.com/penn-electric-racing/per-data-analyzer/blob/main/perda/utils/signal_processing.py): `perda/utils/signal_processing.py`
- [Frequency Analysis](https://github.com/penn-electric-racing/per-data-analyzer/blob/main/perda/utils/frequency_analysis.py): `perda/utils/frequency_analysis.py`
- [GPS Analysis](https://github.com/penn-electric-racing/per-data-analyzer/blob/main/perda/utils/gps_analysis.py): `perda/utils/gps_analysis.py`
- [Data Summary](https://github.com/penn-electric-racing/per-data-analyzer/blob/main/perda/utils/data_summary.py): `perda/utils/data_summary.py`

### Access and Output

- [Plot API](https://github.com/penn-electric-racing/per-data-analyzer/blob/main/perda/analyzer/analyzer.py): `perda/analyzer/analyzer.py`
- [Signal Plotters](https://github.com/penn-electric-racing/per-data-analyzer/blob/main/perda/plotting/data_instance_plotter.py): `perda/plotting/data_instance_plotter.py`
- [Subplot Builder](https://github.com/penn-electric-racing/per-data-analyzer/blob/main/perda/plotting/subplots.py): `perda/plotting/subplots.py`
- [Live Analyzer](https://github.com/penn-electric-racing/per-data-analyzer/blob/main/perda/live/live_analyzer.py): `perda/live/live_analyzer.py`
- [CDP Client](https://github.com/penn-electric-racing/per-data-analyzer/blob/main/perda/live/cdp_client.py): `perda/live/cdp_client.py`

### Other components

- **Analyst**
- **Data Server**
- **S3 Log Bucket**

## Connections

- Analyst → Analyzer API: loads log
- Analyzer API → CSV Parser: parses CSV
- CSV Parser → Single Run Data: builds data
- CSV Parser → Data Instance: builds signals
- Analyzer API → Preprocessing: applies steps
- Preprocessing → Single Run Data: transforms data
- Single Run Data → Search Indexes: stores indexes
- Analyzer API → Signal Search: searches signals
- Signal Search → Search Indexes: uses index
- Signal Search → Single Run Data: reads signals
- Analyzer API → Plot API: plots data
- Plot API → Signal Plotters: renders signals
- Plot API → Subplot Builder: builds subplots
- Signal Plotters → Data Instance: reads series
- Subplot Builder → Data Instance: reads series
- Run Collections → Single Run Data: manages runs
- Data Instance → Alignment and Joins: aligns series
- Data Instance → Resampling: resamples series
- Analyst → Remote Loader: requests log
- Remote Loader → Data Server: authenticates
- Remote Loader → S3 Log Bucket: downloads log
- Remote Loader → Analyzer API: loads download
- Analyst → Live Analyzer: uses live data
- Live Analyzer → CDP Client: requests data
- CDP Client → Data Server: communicates
