Skip to main content

Offline-capable toolkit: PCAP, geo, time-series, clustering, and path estimation

Project description

Pegasource

Offline-capable Python toolkit — PCAP analysis, geographic functions, time-series forecasting, optional hardware-inventory clustering, and path estimation (GPS / map-matching / filters / NN).

Python 3.10+ License: MIT


Modules

Module Description
pegasource.pcap PCAP reader, statistics, anomaly & pattern detection
pegasource.geo Distance, coordinate transforms, road vectorizer, Israel road network
pegasource.timeseries Automatic time-series forecasting (SARIMAX + fallback)
pegasource.dataset_clustering Dirty hardware CSV → embeddings, hierarchical clustering, optional FastAPI + browser UI
pegasource.path_estimation Trajectory reconstruction: graph map-matching, KF/EKF/UKF/particle, LSTM/Transformer/GNN (optional [path_estimation])

Installation

pip install -e ".[dev]"              # development install (tests + docs)
pip install -e ".[clustering]"       # adds embedding server deps (sentence-transformers, FastAPI, …)
pip install -e ".[path_estimation]"  # torch, torch-geometric, filterpy, osmnx, contextily, …
# or
pip install pegasource               # once published

Install [clustering] when you use pegasource.dataset_clustering for full pipelines (embeddings, HTTP server, Excel export). Core imports such as load_data and cluster_embeddings need scikit-learn and pandas (already in the base package); generate_embeddings needs sentence-transformers (included in [clustering]).

Install [path_estimation] for run_evaluation, neural estimators, and Kalman/particle filters. Submodules such as pegasource.path_estimation.metrics work with the base install; from pegasource.path_estimation import run_evaluation loads the full stack.

scapy requires root privileges to capture live traffic, but reading PCAP files works without root.


Quick Start

PCAP Analysis

from pegasource.pcap import read_pcap, generate_report

packets = read_pcap("capture.pcap")
report  = generate_report(packets, output_path="report.json")

# Individual detectors
from pegasource.pcap import detect_port_scan, detect_beaconing, detect_dns_anomalies

scans    = detect_port_scan(packets, threshold=20)
beacons  = detect_beaconing(packets, min_occurrences=5)
dns_anom = detect_dns_anomalies(packets)

Geographic Functions

from pegasource.geo import haversine, wgs84_to_itm, load_israel_graph, shortest_path

# Distances
dist_m = haversine(31.7683, 35.2137, 32.0853, 34.7818)   # Jerusalem → TLV ≈ 54 km
print(f"Distance: {dist_m / 1000:.1f} km")

# Coordinate conversion
easting, northing = wgs84_to_itm(31.7683, 35.2137)   # WGS84 → ITM (EPSG:2039)

# Israel road network
G = load_israel_graph()                               # loads pre-processed graph
route = shortest_path(G, (31.7683, 35.2137), (32.0853, 34.7818))
print("First waypoint:", route[0])

Downloading the road graph (one-time, ~90 MB)

pegasource-download-roads
# or
python -m pegasource.geo.israel_roads

This downloads the Geofabrik israel-and-palestine-latest.osm.pbf and saves a pre-processed israel_roads.pkl.gz to pegasource/data/.

Road Vectorizer (from density maps)

import numpy as np
from pegasource.geo import build_graph, plot_graph_overlay

density = np.load("my_density_map.npy")
G = build_graph(density, threshold=0.3, prune_length=5)
plot_graph_overlay(density, G)

API mirrors josefberman/RoadVectorizer:

Function Description
build_graph(density_map, **kwargs) Convert 2D density histogram → nx.Graph
compute_road_coverage(full_graph, partial_graph, tolerance=2) Coverage fraction
plot_graph_overlay(density_map, graph, **kwargs) Matplotlib overlay

Time-Series Prediction

import numpy as np
from pegasource.timeseries import AutoForecaster

# Univariate
y = np.sin(np.linspace(0, 8 * np.pi, 96)) + np.random.randn(96) * 0.1
fc = AutoForecaster()
fc.fit(y)
pred = fc.predict(steps=12)
print(fc.diagnostics())
fc.plot(steps=12)

# With exogenous variables
import pandas as pd
exog = pd.DataFrame({"temperature": ..., "holiday": ...})    # shape (n, k)
fc2 = AutoForecaster()
fc2.fit(y, exog=exog)
pred2 = fc2.predict(steps=6, exog=exog_future)

AutoForecaster automatically:

  1. Detects the dominant seasonal period via ACF
  2. Tries multiple SARIMAX configurations and selects by AIC
  3. Falls back to OLS linear trend + seasonal dummies if SARIMAX fails

Dataset clustering (hardware inventory)

Cluster messy tabular inventory (e.g. hardware types/models) using sentence embeddings and agglomerative clustering. A bundled sample CSV lives under pegasource/dataset_clustering/data/.

from pegasource.dataset_clustering import (
    load_data,
    build_text_representations,
    generate_embeddings,
    cluster_embeddings,
)

df = load_data("path/to/data.csv")           # use any CSV; CLI defaults to bundled sample if omitted
texts = build_text_representations(df)
emb = generate_embeddings(
    texts,
    "sentence-transformers/paraphrase-multilingual-MiniLM-L12-v2",
    batch_size=512,
    device="cpu",
)
labels = cluster_embeddings(emb, threshold=0.3)
df["cluster_id"] = labels

CLI — batch clustering to CSV

python -m pegasource.dataset_clustering.cluster_hardware \
  --input path/to.csv --output clustered.csv --threshold 0.3

Interactive visualization server (requires [clustering]):

pegasource-cluster-viz --port 8001
# or
python -m pegasource.dataset_clustering.server --port 8001

Serves the bundled cluster_viz frontend, loads the default dataset (or --data), and computes embeddings in the background. For richer device matching in the UI, download the iFixit device list once:

python -m pegasource.dataset_clustering.fetch_ifixit_devices

Regenerate bundled sample data (optional, long run):

python -m pegasource.dataset_clustering.dataset_generator

Static viz JSON from an existing clustered_output.csv:

python -m pegasource.dataset_clustering.prepare_viz_data

Path estimation (trajectories)

Evaluate reconstruction methods on observation CSVs vs a 1 Hz ground-truth path (requires [path_estimation] for the full estimator stack):

pip install -e ".[path_estimation]"
from pegasource.path_estimation.evaluate import run_evaluation
from pathlib import Path

summary = run_evaluation(
    observations_csv=Path("run_1_observations.csv"),
    true_path_csv=Path("run_1_true_path.csv"),
    output_dir=Path("out"),
    methods=["dijkstra", "hmm", "kf"],
)

Observations only (no ground-truth CSV) — use estimate_paths_only when you do not have a true path file. It builds an internal time grid from the observation span and returns per-method EstimationResult values (or {"error": ...}). Methods lstm, transformer, and gnn need labels; use run_evaluation / evaluate_path_estimation with a true path instead.

from pathlib import Path

from pegasource.path_estimation import estimate_paths_only
from pegasource.path_estimation.graph_utils import get_projected_graph

obs = Path("run_1_observations.csv")
G = get_projected_graph()  # same OSM walk graph as evaluation uses

results = estimate_paths_only(
    obs,
    G,
    methods=["dijkstra", "hmm", "kf", "ekf"],
    output_hz=1.0,
    output_dir=Path("out_no_gt"),
    plot=True,   # writes out_no_gt/figures/<method>_path_enu.png
)
# results["kf"] is an EstimationResult with times_s, east_m, north_m (or {"error": "..."})

Synthetic data (generate_dataset in pegasource.path_estimation.generate_synthetic_datasets) and batch method comparison (main in pegasource.path_estimation.run_method_evaluation) are invoked from your own Python code, not as installed console commands.


Running Tests

pip install -e ".[dev]"
pytest tests/ -v

Package Structure

pegasource/
├── pcap/
│   ├── reader.py        # read_pcap, packet_summary
│   ├── stats.py         # protocol_distribution, top_talkers, conversation_table
│   ├── patterns.py      # port scan, beaconing, DNS anomalies, …
│   └── report.py        # generate_report
├── geo/
│   ├── distance.py      # haversine, vincenty, bearing
│   ├── projection.py    # wgs84_to_itm, itm_to_wgs84, wgs84_to_utm, meters_offset
│   ├── vectorizer.py    # build_graph, compute_road_coverage, plot_graph_overlay
│   ├── israel_roads.py  # load_israel_graph, shortest_path, subgraph_bbox
│   └── _rv_*.py         # vendored RoadVectorizer source (josefberman)
├── timeseries/
│   ├── auto.py          # AutoForecaster
│   ├── models.py        # SARIMAXModel, LinearTrendModel
│   └── utils.py         # detect_seasonality, train_test_split_ts, rmse
├── dataset_clustering/  # optional [clustering] extra for full stack
│   ├── cluster_hardware.py   # CLI + core clustering API
│   ├── server.py             # FastAPI + static cluster_viz UI
│   ├── custom_devices.py     # supplemental device names for matching
│   ├── fetch_ifixit_devices.py
│   ├── prepare_viz_data.py
│   ├── dataset_generator.py
│   ├── data/                 # sample CSVs
│   └── cluster_viz/          # HTML/JS frontend
├── path_estimation/          # optional [path_estimation] for evaluate + NN/torch
│   ├── evaluate.py         # run_evaluation, metrics, figures
│   ├── metrics.py, io.py, graph_utils.py, …
│   ├── filters/, nn/, gnn/
│   ├── london_street_path.py, geo_reference.py, plotting_utils.py
│   └── sample_*.csv, cache/  # bundled samples + OSM graph cache
└── data/
    └── israel_roads.pkl.gz   # pre-processed OSM graph (after download)

Dependencies

  • scapy — PCAP parsing
  • numpy, scipy, scikit-image — numerical + image processing
  • networkx — road graphs
  • pyproj — coordinate transforms
  • shapely — geometric operations
  • statsmodels — SARIMAX
  • scikit-learn — feature engineering, clustering in dataset_clustering
  • pandas — data manipulation
  • matplotlib — visualisation

Optional [clustering]: sentence-transformers, FastAPI, uvicorn, python-multipart, openpyxl, requests.

Optional [path_estimation]: filterpy, torch, torch-geometric, contextily, osmnx, tqdm (plus base networkx, pyproj, matplotlib, pandas, scipy already in the package).


License

MIT © Josef Berman

Road Vectorizer code adapted from josefberman/RoadVectorizer (MIT).
Road data © OpenStreetMap contributors (ODbL).

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

pegasource-0.2.3.tar.gz (48.3 MB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

pegasource-0.2.3-py3-none-any.whl (48.5 MB view details)

Uploaded Python 3

File details

Details for the file pegasource-0.2.3.tar.gz.

File metadata

  • Download URL: pegasource-0.2.3.tar.gz
  • Upload date:
  • Size: 48.3 MB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.13.9

File hashes

Hashes for pegasource-0.2.3.tar.gz
Algorithm Hash digest
SHA256 a869d5da18aa2c1955fdef2c5f32ed1b32c09b34b2d66ec00538a55e455680aa
MD5 a0c34e7628409d30ade647c3c3ef93b5
BLAKE2b-256 cad97c506026535514726eefc00ea8b04d85a4efb4a30ff2a2d36d88467d1f89

See more details on using hashes here.

File details

Details for the file pegasource-0.2.3-py3-none-any.whl.

File metadata

  • Download URL: pegasource-0.2.3-py3-none-any.whl
  • Upload date:
  • Size: 48.5 MB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.13.9

File hashes

Hashes for pegasource-0.2.3-py3-none-any.whl
Algorithm Hash digest
SHA256 1eb4a8f1b632776f349560948428f411f417f3a6f1f9c3bacb27fad7518dc9db
MD5 a8319d942983ee08fb84fc1ea41bf2ff
BLAKE2b-256 c1f5bc8429495d74dff5f2c909d81a7b684d2273ea1d0ea4b71373aaf96a8ac9

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page