{ "cells": [ { "cell_type": "markdown", "id": "2324d26e", "metadata": {}, "source": [ "# PADM2M Charlie Index Walkthrough\n", "\n", "This notebook documents the step-by-step exploration of the Charlie Index (C) and its derivative (C′) using the **PADM2M** model.\n", "\n", "We show the progression from raw data (Panel A), to smoothed representations (Panel B), to centered and aligned views (Panel C).\n", "\n", "The goal is transparency: nothing hidden, just progressively easier-to-read representations." ] }, { "cell_type": "markdown", "id": "5b2920a3", "metadata": {}, "source": [ "## 1. Load data\n", "We start with the processed `padm2m_charlie_index.json` file produced by the pipeline." ] }, { "cell_type": "code", "execution_count": null, "id": "69ed4883", "metadata": {}, "outputs": [], "source": [ "import os, json\n", "import numpy as np\n", "import matplotlib.pyplot as plt\n", "from scipy.ndimage import gaussian_filter1d\n", "\n", "# Paths\n", "input_file = os.path.join(\"..\", \"processed\", \"padm2m_charlie_index.json\")\n", "fig_dir = os.path.join(\"..\", \"figures\")\n", "os.makedirs(fig_dir, exist_ok=True)\n", "\n", "with open(input_file, \"r\") as f:\n", " records = json.load(f)\n", "\n", "time = np.array([r[\"time_ka\"] for r in records])\n", "C = np.array([r[\"C\"] for r in records])\n", "Cprime = np.array([r[\"C_prime\"] for r in records])\n", "\n", "def normalize(arr):\n", " return (arr - np.min(arr)) / (np.max(arr) - np.min(arr))\n", "\n", "C_norm = normalize(C)\n", "Cprime_norm = (Cprime - np.mean(Cprime)) / np.max(np.abs(Cprime))\n", "\n", "time[:5], C[:5], Cprime[:5]" ] }, { "cell_type": "markdown", "id": "fcbd22de", "metadata": {}, "source": [ "## 2. Panel A: Raw data\n", "This is the unaltered view of C and C′. It shows all the natural noise and variance." ] }, { "cell_type": "code", "execution_count": null, "id": "eb4d908a", "metadata": {}, "outputs": [], "source": [ "fig, ax = plt.subplots(figsize=(12,5))\n", "ax.plot(time, C_norm, color=\"blue\", alpha=0.7, label=\"C (raw)\")\n", "ax.set_ylabel(\"C (normalized)\")\n", "ax.set_ylim(0,0.9)\n", "ax.set_xlim(left=0)\n", "\n", "ax2 = ax.twinx()\n", "ax2.plot(time, Cprime_norm, color=\"red\", alpha=0.4, label=\"C′ (raw)\")\n", "ax2.set_ylabel(\"C′ (normalized)\")\n", "ax2.set_ylim(-0.18,0.18)\n", "\n", "ax.set_xlabel(\"Time (ka BP)\")\n", "ax.set_title(\"Panel A — Raw Data\")\n", "fig.tight_layout()\n", "plt.show()\n", "fig.savefig(os.path.join(fig_dir, \"padm2m_panel_a_raw.png\"), dpi=300)" ] }, { "cell_type": "markdown", "id": "613a58b0", "metadata": {}, "source": [ "## 3. Panel B: Smoothed data\n", "We apply Gaussian filters to reduce noise while retaining structure.\n", "- C: σ = 5\n", "- C′: σ = 1.5 (less smoothing to keep detail)" ] }, { "cell_type": "code", "execution_count": null, "id": "9f785216", "metadata": {}, "outputs": [], "source": [ "sigma_C = 5\n", "sigma_Cp = 1.5\n", "\n", "C_smooth = gaussian_filter1d(C_norm, sigma=sigma_C)\n", "Cp_smooth = gaussian_filter1d(Cprime_norm, sigma=sigma_Cp)\n", "\n", "fig, ax = plt.subplots(figsize=(12,5))\n", "ax.plot(time, C_smooth, color=\"blue\", label=f\"C (σ={sigma_C})\")\n", "ax.set_ylabel(\"C (normalized)\")\n", "ax.set_ylim(0,0.9)\n", "ax.set_xlim(left=0)\n", "\n", "ax2 = ax.twinx()\n", "ax2.plot(time, Cp_smooth, color=\"red\", label=f\"C′ (σ={sigma_Cp})\")\n", "ax2.set_ylabel(\"C′ (normalized)\")\n", "ax2.set_ylim(-0.18,0.18)\n", "\n", "ax.set_xlabel(\"Time (ka BP)\")\n", "ax.set_title(\"Panel B — Smoothed Data\")\n", "fig.tight_layout()\n", "plt.show()\n", "fig.savefig(os.path.join(fig_dir, \"padm2m_panel_b_smoothed.png\"), dpi=300)" ] }, { "cell_type": "markdown", "id": "06c8bf70", "metadata": {}, "source": [ "## 4. Panel C: Centered & aligned view\n", "We normalize and center the signals so that C and C′ can be visually compared. This does not hide anything — it just aligns them to reveal correlation/divergence patterns more clearly." ] }, { "cell_type": "code", "execution_count": null, "id": "6e7e2086", "metadata": {}, "outputs": [], "source": [ "sigma_Cp_high = 4.0\n", "Cp_smooth_high = gaussian_filter1d(Cprime_norm, sigma=sigma_Cp_high)\n", "\n", "fig, ax = plt.subplots(figsize=(12,5))\n", "ax.plot(time, C_smooth, color=\"blue\", label=f\"C (σ={sigma_C})\")\n", "ax.set_ylabel(\"C (normalized)\")\n", "ax.set_ylim(0,0.9)\n", "ax.set_xlim(left=0)\n", "\n", "ax2 = ax.twinx()\n", "ax2.plot(time, Cp_smooth_high, color=\"red\", label=f\"C′ (σ={sigma_Cp_high})\")\n", "ax2.set_ylabel(\"C′ (normalized)\")\n", "ax2.set_ylim(-0.18,0.18)\n", "\n", "ax.set_xlabel(\"Time (ka BP)\")\n", "ax.set_title(\"Panel C — Smoothed & Centered\")\n", "fig.tight_layout()\n", "plt.show()\n", "fig.savefig(os.path.join(fig_dir, \"padm2m_panel_c_centered.png\"), dpi=300)" ] }, { "cell_type": "markdown", "id": "90a5dd81", "metadata": {}, "source": [ "## 5. Notes\n", "- Panel A shows everything raw (full noise).\n", "- Panel B smooths but keeps independent scaling.\n", "- Panel C centers for visual comparison — the keystone representation.\n", "\n", "This sequence should form the foundation figure set for introducing the Reliford Principle." ] } ], "metadata": { "kernelspec": { "display_name": ".venv", "language": "python", "name": "python3" }, "language_info": { "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "pygments_lexer": "ipython3", "version": "3.11.2" } }, "nbformat": 4, "nbformat_minor": 5 }