Skip to content

nobulart/drift

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

79 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

DRIFT Dashboard

Constraint-first polar-motion diagnostics dashboard for geometry, phase structure, and experimental transition-probability diagnostics

Source paper: Earth-Fixed Geometric Structure, Bistable Dynamics, and Phase-Locked Planetary Torque Coupling in Polar Motion

DRIFT Dashboard screenshot

Current release: v1.5.1

Release Notes

v1.5.1

  • Added the Loop-Center Angular Velocity panel, reproducing the paper diagnostic from the live EOP store instead of a static figure.
  • Preserved the paper-equivalent completed-loop smoothing while showing the newest incomplete-loop estimate as a separate provisional endpoint.
  • Labeled low-radius provisional centers as low-confidence and added a visible endpoint error bar that combines robust residual spread with near-origin angular sensitivity.
  • Added dashboard/docs guidance for interpreting provisional loop-center angular velocity without over-reading endpoint instability.

v1.5.0

  • Added confirmed turning-point markers to the Polar Motion Trajectory and Residual Polar Motion (XY) path views.
  • Filtered unconfirmed boundary turning-point regions so the newest sample is not marked before the low-omega episode is bracketed by future data.
  • Increased horizontal legend spacing in the Conditional Lag Response phase-bin slice plot.
  • Updated internal docs with reordered experimental panel guides and a companion Phase-Locked Escape Model detail panel.

v1.4.9

  • Fixed adaptive turning-point detection so the default threshold no longer collapses the full omega history into one turning region.
  • Reworked the conditional lag response anchors so all selected states can populate from contiguous state episodes, with sample-count metadata exposed to the transition panel.
  • Updated transition probability to use the computed lag kernel, preserve base probability in cumulative probabilities, and report P(≤30d) against the actual 30-day lag.
  • Fixed R(t) tail computation so the latest samples use trailing windows instead of being forward-filled from the last pre-padding value.
  • Added rolling-stats cache invalidation for model-code changes so derived outputs refresh when the Python computation changes.

v1.4.8

  • Added the Residual Polar Motion (XY) panel and Polar Motion Trajectory panel, both with square plot geometry and chronological path coloring.
  • Standardized the polar-motion displays against the IERS EOP convention: x_pole is shown north/up along the Greenwich meridian and y_pole is shown west/left toward 90°W.
  • Aligned the 3D Vector View with the same frame, including unambiguous vector labels, drift longitude in E/W notation, and clearer label placement.
  • Enlarged and corrected square fullscreen modals so the residual, trajectory, and 3D views can use the available browser window efficiently.

v1.4.7

  • Added the Phase-Locked Escape Model as the first full-width dashboard panel, using internal DRIFT state plus DE442-derived phase composites rather than exploratory CSV exports.
  • Added phase drift, local linear time-to-alignment, oscillatory regime detection, phase acceleration, curvature signal, and phase stability diagnostics.
  • Added the escape-energy diagnostic: phase kinetic energy, phase potential energy, total phase energy, barrier ratio, energy-state classification, and a Kramers-like comparative index using R(t) as a noise proxy.
  • Added energy overlays and optional time-series traces for phase potential energy, total phase energy, and barrier ratio.

v1.4.6

  • Added a sidebar-driven Update Data workflow that runs scripts/fetch_latest.py through a local API route, with spinner feedback and post-update dashboard reload.
  • Added timestamp-aware freshness checks to scripts/fetch_latest.py so EOP, GFZ-KP, GRACE, and combined outputs are skipped while local files are still fresh; use --force for a full manual refresh.
  • Reworked panel fullscreen behavior so the existing panel instance expands in place, preserving selected traces, ranges, controls, and guide/info content across panel and fullscreen views.

v1.4.5

  • Removed synthetic GRACE, inertia, and fallback geomagnetic-axis data from the ingestion and retrieval pipeline so the dashboard now serves real inputs only.
  • Corrected the phase portrait and phase-diagnostics handling around phase-wrap artifacts to avoid spurious branch-cut spikes in the displayed loop geometry.
  • Temporarily disabled the Angle Diagnostics and Alignment panels in the UI while their real-data-only replacements are being reworked.

v1.4.4

  • Added date information to the Phase Portrait hover popup so users can identify when specific phase-space features, loops, and turning points occurred.

v1.4.3

  • Added a highlighted present-state marker and recent trajectory overlay to the Phase Portrait, now focused on the last 180 days.
  • Enlarged fullscreen popup charts to use roughly 85% of browser width and a taller plotting area, with responsive plot resizing inside the modal.
  • Added shared fullscreen-aware plot sizing so expanded charts across the dashboard actually use the larger popup dimensions.

v1.4.2

  • Moved stale-data checking and conditional pipeline execution to server startup so the dashboard only launches after required data are current.
  • Fixed Transition Probability plot redraw and rescaling when State or Base Prob changes.
  • Compacted the sidebar layout, restored clean stacking between Sources and Panels, and improved sidebar scrolling on medium-height displays.

v1.4.1

  • Corrected the Transition Probability expected-date label so it now adds the probability horizon to the actual current date rather than the cached data timestamp.

v1.4.0

  • Added start, back, forward, and finish controls to the 3D Vector View timeline for direct frame stepping.
  • Reworked 3D playback timing to use elapsed time rather than rounded interval steps, improving low-speed behavior and realtime smoothness.
  • Anchored Transition Probability expected dates to the latest available sample so 3D timeline scrubbing no longer shifts the probability horizon.
  • Replaced the plain startup loading text with a centered animated progress widget for a cleaner initial launch experience.

v1.3.0

  • Added DE442-backed Earth-geocentric overlay signals for all tracked bodies.
  • Added a slim daily ephemeris cache covering 1973-01-02 through 2050-12-31.
  • Added overlay-selectable distance, angular velocity, radial velocity, ecliptic longitude, and heuristic torque-proxy series.
  • Removed hidden default ephemeris selections so an unchecked overlay plot is truly empty.

Scientific Basis

The dashboard is built around the source paper Earth-Fixed Geometric Structure, Bistable Dynamics, and Phase-Locked Planetary Torque Coupling in Polar Motion, which analyzes polar motion with a constraint-first method: start from the geometric structure required by the observations, then interpret cautiously.

The paper's strongest claims are:

  • polar motion is confined to a low-dimensional, near-planar structure over the observed interval
  • projection onto the dominant axis reveals a robust two-state or bistable organization
  • residual phase space shows coupled fast-slow behavior: looping motion embedded in a slower drifting structure

The paper is also explicit about what is weaker:

  • absolute directional anisotropy and apparent axis stability are not statistically decisive against correlated-noise null models
  • conclusions apply to the observed record, not necessarily to all times outside that window
  • comparative geomagnetic context may be suggestive, but it is not by itself proof of a causal coupling

This repository should therefore be read as a geometry-first monitoring tool. The geomagnetic panels are comparison layers, and the Transition Probability and Phase-Locked Escape Model panels are explicitly experimental diagnostics derived from lag-conditioned and phase-conditioned state structure rather than deterministic prediction engines.

Quick Start

# Install dependencies
npm install

# Refresh pipeline artifacts as needed; fresh local source files are skipped
python scripts/fetch_latest.py
python scripts/fetch_latest.py --force
python scripts/combine_data.py

# Run development server
npm run dev

# Open http://localhost:3000

Docker Deployment

Build the production image:

docker build -t drift-dashboard:latest .

Run it locally or on a Linux host:

docker run -d \
  --name drift-dashboard \
  -p 3000:3000 \
  --restart unless-stopped \
  drift-dashboard:latest

Notes:

  • The container serves the Next.js app on port 3000.
  • Python runtime dependencies are bundled because /api/rolling-stats computes diagnostics on demand.
  • The image includes the current data/, public/data/, and scripts/ directories needed by the dashboard.
  • Point your reverse proxy or firewall rule at the host’s port 3000.

Production Hosting

The live deployment is designed around a single Linux VM:

  • public app URL: https://drift.nobulart.com
  • app container port: 3000
  • edge web server: nginx
  • TLS: Let's Encrypt via certbot

Architecture

Internet
  -> nginx on ports 80/443
  -> reverse proxy to 127.0.0.1:3000
  -> Docker container running the Next.js standalone server

Rebuild And Publish

Build and publish the production image for the target host architecture:

docker buildx build \
  --platform linux/amd64 \
  -t sunbear73/drift-dashboard:latest \
  --push .

First-Time Server Setup

Install Docker:

apt-get update
apt-get install -y docker.io
systemctl enable --now docker

Install the reverse proxy and TLS tooling:

apt-get install -y nginx certbot python3-certbot-nginx
systemctl enable --now nginx

Run Or Update The App Container

Pull the latest image and replace the running container:

docker pull sunbear73/drift-dashboard:latest
docker rm -f drift-dashboard || true
docker run -d \
  --name drift-dashboard \
  --restart unless-stopped \
  -p 3000:3000 \
  sunbear73/drift-dashboard:latest

Verify locally on the server:

docker ps
docker logs --tail=100 drift-dashboard
curl -I http://127.0.0.1:3000

Nginx Configuration

Create /etc/nginx/sites-available/drift.nobulart.com:

server {
    listen 80;
    listen [::]:80;
    server_name drift.nobulart.com;

    location / {
        proxy_pass http://127.0.0.1:3000;
        proxy_http_version 1.1;
        proxy_set_header Host $host;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
        proxy_read_timeout 300;
    }
}

Enable the site:

ln -sf /etc/nginx/sites-available/drift.nobulart.com /etc/nginx/sites-enabled/drift.nobulart.com
rm -f /etc/nginx/sites-enabled/default
nginx -t
systemctl reload nginx

TLS Issuance

After the DNS A record for drift.nobulart.com points to the server public IP, issue the certificate:

certbot --nginx -d drift.nobulart.com --redirect

Useful checks:

dig +short drift.nobulart.com
curl -I http://drift.nobulart.com
curl -I https://drift.nobulart.com
certbot certificates

Routine Redeploy

For subsequent updates, the deployment cycle is:

  1. npm run build
  2. docker buildx build --platform linux/amd64 -t sunbear73/drift-dashboard:latest --push .
  3. SSH to the deployment host
  4. docker pull sunbear73/drift-dashboard:latest
  5. docker rm -f drift-dashboard || true
  6. docker run -d --name drift-dashboard --restart unless-stopped -p 3000:3000 sunbear73/drift-dashboard:latest
  7. Verify https://drift.nobulart.com

Staging Checklist

Use this sequence when staging a new build to the live VM.

  1. Confirm the working tree is clean enough to release:
git status --short --branch
npm run lint
npx tsc --noEmit
npm run build
  1. Push the release commit to GitHub:
git push origin main
  1. Build and publish the Linux image used by the deployment host:
docker buildx build \
  --platform linux/amd64 \
  -t sunbear73/drift-dashboard:latest \
  --push .
  1. SSH to the deployment VM as root and confirm the currently running container:
ssh root@drift.nobulart.com
docker ps --format 'table {{.Names}}\t{{.Image}}\t{{.Status}}'
  1. Pull the freshly published image and replace the container:
docker pull sunbear73/drift-dashboard:latest
docker rm -f drift-dashboard || true
docker run -d \
  --name drift-dashboard \
  --restart unless-stopped \
  -p 3000:3000 \
  sunbear73/drift-dashboard:latest
  1. Verify on the VM before checking the public URL:
docker ps --format 'table {{.Names}}\t{{.Image}}\t{{.Status}}'
docker logs --tail=100 drift-dashboard
curl -I http://127.0.0.1:3000
  1. Verify the public deployment and the visible version from another shell:
curl -I https://drift.nobulart.com
curl -s https://drift.nobulart.com/docs | rg 'Version v'
  1. If the public site still appears stale in a browser, hard-refresh first. If the curl checks still show the old version, the container was not actually refreshed and steps 4-7 should be repeated.

Notes From Recent Deploys

  • A successful image push does not mean the live host is updated. The VM must still docker pull and restart drift-dashboard.
  • The most reliable user-visible version check is currently the docs badge at /docs.
  • If SSH by hostname fails, use the current VM address from the hosting console rather than hard-coding server IPs or credentials into the repo.

Project Structure

drift/
├── app/                 # Next.js App Router pages
├── components/          # React components
│   ├── Controls.tsx     # UI controls
│   ├── PolarPlot.tsx    # Polar motion visualization
│   ├── DriftDirectionPlot.tsx  # Drift direction plot (PRIMARY)
│   ├── TransitionForecastPanel.tsx  # Experimental lag-conditioned transition probability
│   └── SphereView.tsx          # 3D frame visualization
├── lib/                 # Core libraries
│   ├── math.ts          # Vec3 operations
│   ├── transforms.ts    # Frame transformation utilities
│   ├── drift.ts         # PCA-based drift extraction
│   ├── parsing.ts       # Data parsing utilities
│   └── types.ts         # Shared type definitions
├── store/               # Zustand state management
├── scripts/             # Data pipeline scripts
├── public/data/         # Preprocessed data files
└── api/                 # Next.js API routes

Features

  1. Polar Motion Visualization - Plot xp/yp from IERS and inspect confinement, loops, and turning points
  2. Drift Direction - Track the dominant axis implied by the local geometry
  3. Phase Diagnostics - Read looping structure, angular velocity, and intermittency in phase space
  4. Orthogonal Deviation and Lag Structure - Compare local anisotropy, turning-point response, and conditional lag behavior
  5. Geomagnetic Context - Compare dashboard geometry with Kp/ap and related context without assuming causation
  6. Transition Probability - Surface transition-like similarity using lag-conditioned historical structure
  7. Planetary Overlay Context - Compare drift and related signals against DE442-derived Earth-geocentric planetary observables
  8. Phase-Locked Escape Model - Inspect phase-dependent escape probability, phase drift, curvature, escape-energy diagnostics, barrier ratio, and residual phase misalignment from internal DRIFT state plus DE442

Data Pipeline

Precomputed (offline, Python)

  • scripts/fetch_latest.py - Refresh upstream source caches
  • scripts/combine_data.py - Merge observed source products into dashboard-ready JSON
  • scripts/compute_rolling_stats.py - Compute rolling diagnostics, lag models, and transition-probability inputs
  • scripts/build_ephemeris.py - Extract slim DE442 overlay series into daily JSON cache
  • scripts/compute_phase_escape.py - Build phase-escape state inputs from internal EOP and DE442 caches

Live API (Next.js)

GET /api/eop

  • Returns cached historical Earth Orientation Parameters from eop_historic.json.
  • Primary fields: t, xp, yp.

GET /api/inertia

  • Returns cached inertia-frame time series from inertia_timeseries.json when real upstream inputs are available.
  • Primary fields: t, e1, e2, e3.

GET /api/grace

  • Returns cached GRACE / GRACE-FO mass-context series from grace_historic.json when real upstream inputs are available.
  • Primary fields: t, lwe_mean, lwe_std.

GET /api/geomag

  • Returns normalized daily GFZ geomagnetic records derived from geomag_gfz_kp.json.
  • Primary fields: t, kp, ap, cp, c9.

GET /api/geomag-gfz

  • Returns the raw cached GFZ geomagnetic history from geomag_gfz_kp.json.
  • Use this when you want the underlying cached series without the extra normalization wrapper used by /api/geomag.

GET /api/combined

  • Returns a lightweight merged series combining EOP with any available real auxiliary fields where dates overlap.
  • Primary fields: t, xp, yp, optional grace_lwe_mean, grace_lwe_std.

GET /api/combined-full

  • Returns the full combined dashboard dataset from combined_historic.json.
  • Primary fields include t, xp, yp, geomagnetic context, GRACE context, and inertia-frame vectors when available from real cached products.

GET /api/ephemeris

  • Returns the cached DE442-derived Earth-geocentric overlay dataset.
  • Current cache window: 1973-01-02 through 2050-12-31.
  • Primary payload shape: source metadata plus records[], where each record has t and bodies.
  • Per-body overlay metrics currently exposed: distance_au, angular_velocity_deg_per_day, radial_velocity_km_s, ecliptic_longitude_deg, torque_proxy.

GET /api/rolling-stats

  • Computes or serves cached rolling diagnostics from compute_rolling_stats.py.
  • Supported query params: windowSize, turnThreshold, centerWindow, centerStep, danceWindow, conditionalTargetState.
  • Returns rolling geometry and state outputs such as theta, omega, rRatio, turningPoints, lagModel, and conditionalLagModel.

GET /api/transition-forecast

  • Converts the requested lag-conditioned state kernel into a forward transition probability curve.
  • Supported query params: currentState, theta, baseProb, smoothSigma.
  • Returns lags, P_tau, expected_time, peak_time, cumulative, probability_level, probability_message, and related probability-summary metadata.

GET /api/phase-escape

  • Builds the Phase-Locked Escape Model inputs from the internal DRIFT EOP state and the cached DE442 ephemeris series.
  • Computes solar-residual DRIFT phase, DE442 torque-proxy analytic phases, the registered planetary composites, and residual phase misalignment.
  • Supports the panel's phase-drift, phase-acceleration, escape-energy, barrier-ratio, and Kramers-like comparative diagnostics in the frontend model layer.
  • Does not depend on docs/drift.csv or any docs/outputs exploratory artifacts.

Math Overview

  • Drift Axis: PCA on sliding window of polar motion
  • θ3: Angle between drift and e3 (out-of-plane tilt)
  • θ12: In-plane alignment angle to e1
  • Phase Portrait: Fast cyclic structure in (theta, omega) state space
  • Orthogonal Deviation Ratio: Local elongation versus isotropy of the inferred structure

Reading Guidance

Use the dashboard in this order when you want the most paper-aligned interpretation:

  1. Start with Polar Motion, Drift Direction, and R(t) to assess the geometry itself.
  2. Use Phase Portrait and Phase Diagnostics to inspect fast-slow organization and intermittent behavior.
  3. Check the 3D panel, overlays, and any available geomagnetic context for timing comparison.
  4. Use the Phase-Locked Escape Model (experimental) to inspect phase-conditioned escape probability, drift, curvature, barrier ratio, and comparative escape-energy diagnostics.
  5. Read Transition Probability (experimental) as an exploratory summary of whether the current state resembles prior transition-like behavior.

If a conclusion depends mainly on geomagnetic coincidence or on a single transition-probability peak, it is weaker than a conclusion supported by the geometric panels together.

Phase-Locked Escape Model

The Phase-Locked Escape Model panel uses the production DRIFT database/state and the internal DE442 ephemeris pipeline. docs/drift.csv was an exploratory analysis export only; the production panel does not read that CSV and does not require files from docs/outputs at runtime.

The model is an experimental phase-conditioned metastable escape diagnostic. It reports residual phase misalignment, phase-dependent escape probability, phase drift, local linear time-to-alignment, phase acceleration, curvature signal, phase stability, the current metastable phase-well state, and high-R escape modulation. It should not be read as deterministic planetary forcing or prediction certainty.

The escape-energy diagnostic treats residual phase motion as movement in a modulated phase potential. Kinetic energy is estimated from phase velocity, potential energy from angular offset relative to the preferred escape phase, and the barrier ratio normalizes the current phase-energy state against the empirical modulation barrier. The Kramers-like index uses R(t) as a noise proxy and should be interpreted as a comparative index rather than an absolute probability, physical-joule energy, or deterministic transition clock.

Tech Stack

  • Next.js 14+ (App Router)
  • TypeScript (strict mode)
  • Plotly.js for charts
  • Three.js (react-three-fiber) for 3D
  • Zustand for state
  • Tailwind for styling

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors