app
Sample Experiment: RC Low-Pass Filter Response
Public Made by Adomby adom
Working sample of Adom's experiment publication format: JSONL data, sidecar metadata, provenance, and an AI reproduction skill. Prepared for NSF PCL FAIR-data due diligence.
← Commit history
Publish 1.0.0
10 files changed
+361
analysis/run_experiment.pyadded+84@@ -0,0 +1,84 @@+#!/usr/bin/env python3+"""Sample Experiment: frequency response of a first-order RC low-pass filter.++Computes |H(f)| and phase for H(f) = 1 / (1 + j*2*pi*f*R*C) over 10 Hz - 1 MHz,+writes the dataset as JSONL plus a sidecar metadata JSON, and renders a Bode plot.+Fully deterministic: re-running this script reproduces the dataset bit-for-bit.+"""+import json, math, hashlib, datetime, pathlib++R_OHMS = 1000.0 # 1 kOhm (design ref: Yageo RC0603FR-071KL)+C_FARADS = 100e-9 # 100 nF (design ref: Murata GRM188R71H104KA93D)+F_CUTOFF = 1.0 / (2.0 * math.pi * R_OHMS * C_FARADS) # ~1591.55 Hz++POINTS_PER_DECADE = 20+F_START_EXP, F_STOP_EXP = 1, 6 # 10 Hz .. 1 MHz++root = pathlib.Path(__file__).resolve().parent.parent+data_path = root / "data" / "rc_lowpass_response.jsonl"+rows = []+n = (F_STOP_EXP - F_START_EXP) * POINTS_PER_DECADE + 1+for i in range(n):+ f = 10 ** (F_START_EXP + i / POINTS_PER_DECADE)+ w_rc = 2.0 * math.pi * f * R_OHMS * C_FARADS+ gain = 1.0 / math.sqrt(1.0 + w_rc * w_rc)+ rows.append({+ "point": i,+ "frequency_hz": round(f, 6),+ "gain_linear": round(gain, 9),+ "gain_db": round(20.0 * math.log10(gain), 6),+ "phase_deg": round(-math.degrees(math.atan(w_rc)), 6),+ })++with open(data_path, "w") as fh:+ for r in rows:+ fh.write(json.dumps(r) + "\n")++sha = hashlib.sha256(data_path.read_bytes()).hexdigest()+sidecar = {+ "dataset": "rc_lowpass_response.jsonl",+ "title": "RC low-pass filter frequency response (computed)",+ "description": "Magnitude and phase of a first-order RC low-pass filter (R=1 kOhm, C=100 nF, fc~=1591.5 Hz), 20 points/decade from 10 Hz to 1 MHz.",+ "created_utc": "2026-07-10T00:00:00Z",+ "generator": {"script": "analysis/run_experiment.py", "runtime": "python3", "deterministic": True},+ "method": "closed-form transfer function H(f) = 1/(1 + j*2*pi*f*R*C); no physical measurement",+ "parameters": {"R_ohms": R_OHMS, "C_farads": C_FARADS, "f_cutoff_hz": round(F_CUTOFF, 3),+ "points_per_decade": POINTS_PER_DECADE, "f_range_hz": [10, 1000000]},+ "schema": {+ "format": "jsonl",+ "fields": [+ {"name": "point", "type": "int", "unit": None, "description": "0-based sample index"},+ {"name": "frequency_hz", "type": "float", "unit": "Hz", "description": "stimulus frequency"},+ {"name": "gain_linear", "type": "float", "unit": "V/V", "description": "|H(f)|"},+ {"name": "gain_db", "type": "float", "unit": "dB", "description": "20*log10(|H(f)|)"},+ {"name": "phase_deg", "type": "float", "unit": "degrees", "description": "arg(H(f)), negative = lag"},+ ],+ },+ "rows": len(rows),+ "sha256": sha,+ "license": "CC-BY-4.0",+}+(root / "data" / "rc_lowpass_response.sidecar.json").write_text(json.dumps(sidecar, indent=2) + "\n")+print(f"wrote {len(rows)} rows, fc={F_CUTOFF:.2f} Hz, sha256={sha[:16]}...")++# Bode plot+import matplotlib+matplotlib.use("Agg")+import matplotlib.pyplot as plt++freqs = [r["frequency_hz"] for r in rows]+gains = [r["gain_db"] for r in rows]+phases = [r["phase_deg"] for r in rows]++fig, (ax1, ax2) = plt.subplots(2, 1, figsize=(9, 6.5), sharex=True)+ax1.semilogx(freqs, gains, color="#1a4480", lw=2)+ax1.axvline(F_CUTOFF, color="#c05621", ls="--", lw=1, label=f"fc = {F_CUTOFF:.1f} Hz (-3 dB)")+ax1.axhline(-3.0103, color="#c05621", ls=":", lw=1)+ax1.set_ylabel("Gain (dB)"); ax1.grid(True, which="both", alpha=0.3); ax1.legend()+ax1.set_title("RC low-pass frequency response - R=1 k$\\Omega$, C=100 nF")+ax2.semilogx(freqs, phases, color="#1a4480", lw=2)+ax2.axvline(F_CUTOFF, color="#c05621", ls="--", lw=1)+ax2.set_ylabel("Phase (deg)"); ax2.set_xlabel("Frequency (Hz)"); ax2.grid(True, which="both", alpha=0.3)+fig.tight_layout()+fig.savefig(root / "docs" / "bode-plot.png", dpi=110)+print("plot saved")
data/rc_lowpass_response.jsonladded+101@@ -0,0 +1,101 @@+{"point": 0, "frequency_hz": 10.0, "gain_linear": 0.999980261, "gain_db": -0.000171, "phase_deg": -0.359995}+{"point": 1, "frequency_hz": 11.220185, "gain_linear": 0.999975151, "gain_db": -0.000216, "phase_deg": -0.40392}+{"point": 2, "frequency_hz": 12.589254, "gain_linear": 0.999968717, "gain_db": -0.000272, "phase_deg": -0.453204}+{"point": 3, "frequency_hz": 14.125375, "gain_linear": 0.999960617, "gain_db": -0.000342, "phase_deg": -0.5085}+{"point": 4, "frequency_hz": 15.848932, "gain_linear": 0.999950421, "gain_db": -0.000431, "phase_deg": -0.570543}+{"point": 5, "frequency_hz": 17.782794, "gain_linear": 0.999937585, "gain_db": -0.000542, "phase_deg": -0.640154}+{"point": 6, "frequency_hz": 19.952623, "gain_linear": 0.999921426, "gain_db": -0.000683, "phase_deg": -0.718257}+{"point": 7, "frequency_hz": 22.387211, "gain_linear": 0.999901084, "gain_db": -0.000859, "phase_deg": -0.805886}+{"point": 8, "frequency_hz": 25.118864, "gain_linear": 0.999875477, "gain_db": -0.001082, "phase_deg": -0.904204}+{"point": 9, "frequency_hz": 28.183829, "gain_linear": 0.999843243, "gain_db": -0.001362, "phase_deg": -1.014512}+{"point": 10, "frequency_hz": 31.622777, "gain_linear": 0.999802666, "gain_db": -0.001714, "phase_deg": -1.13827}+{"point": 11, "frequency_hz": 35.481339, "gain_linear": 0.999751591, "gain_db": -0.002158, "phase_deg": -1.277117}+{"point": 12, "frequency_hz": 39.810717, "gain_linear": 0.999687301, "gain_db": -0.002716, "phase_deg": -1.432887}+{"point": 13, "frequency_hz": 44.668359, "gain_linear": 0.999606384, "gain_db": -0.00342, "phase_deg": -1.607639}+{"point": 14, "frequency_hz": 50.118723, "gain_linear": 0.999504542, "gain_db": -0.004305, "phase_deg": -1.803678}+{"point": 15, "frequency_hz": 56.234133, "gain_linear": 0.999376375, "gain_db": -0.005418, "phase_deg": -2.023587}+{"point": 16, "frequency_hz": 63.095734, "gain_linear": 0.999215093, "gain_db": -0.00682, "phase_deg": -2.270258}+{"point": 17, "frequency_hz": 70.794578, "gain_linear": 0.999012162, "gain_db": -0.008584, "phase_deg": -2.546926}+{"point": 18, "frequency_hz": 79.432823, "gain_linear": 0.998756862, "gain_db": -0.010804, "phase_deg": -2.857211}+{"point": 19, "frequency_hz": 89.125094, "gain_linear": 0.998435737, "gain_db": -0.013598, "phase_deg": -3.205156}+{"point": 20, "frequency_hz": 100.0, "gain_linear": 0.998031905, "gain_db": -0.017112, "phase_deg": -3.595274}+{"point": 21, "frequency_hz": 112.201845, "gain_linear": 0.997524206, "gain_db": -0.021531, "phase_deg": -4.032595}+{"point": 22, "frequency_hz": 125.892541, "gain_linear": 0.996886151, "gain_db": -0.027089, "phase_deg": -4.522714}+{"point": 23, "frequency_hz": 141.253754, "gain_linear": 0.996084626, "gain_db": -0.034075, "phase_deg": -5.071846}+{"point": 24, "frequency_hz": 158.489319, "gain_linear": 0.995078309, "gain_db": -0.042855, "phase_deg": -5.686867}+{"point": 25, "frequency_hz": 177.827941, "gain_linear": 0.993815758, "gain_db": -0.053882, "phase_deg": -6.375363}+{"point": 26, "frequency_hz": 199.526231, "gain_linear": 0.992233112, "gain_db": -0.067726, "phase_deg": -7.145665}+{"point": 27, "frequency_hz": 223.872114, "gain_linear": 0.990251389, "gain_db": -0.085091, "phase_deg": -8.006864}+{"point": 28, "frequency_hz": 251.188643, "gain_linear": 0.98777335, "gain_db": -0.106854, "phase_deg": -8.968811}+{"point": 29, "frequency_hz": 281.838293, "gain_linear": 0.984679975, "gain_db": -0.134098, "phase_deg": -10.042073}+{"point": 30, "frequency_hz": 316.227766, "gain_linear": 0.980826659, "gain_db": -0.168155, "phase_deg": -11.237841}+{"point": 31, "frequency_hz": 354.813389, "gain_linear": 0.976039339, "gain_db": -0.210654, "phase_deg": -12.567764}+{"point": 32, "frequency_hz": 398.107171, "gain_linear": 0.970110966, "gain_db": -0.263572, "phase_deg": -14.043691}+{"point": 33, "frequency_hz": 446.683592, "gain_linear": 0.962798955, "gain_db": -0.329288, "phase_deg": -15.677284}+{"point": 34, "frequency_hz": 501.187234, "gain_linear": 0.953824547, "gain_db": -0.41063, "phase_deg": -17.479487}+{"point": 35, "frequency_hz": 562.341325, "gain_linear": 0.942875373, "gain_db": -0.510914, "phase_deg": -19.459816}+{"point": 36, "frequency_hz": 630.957344, "gain_linear": 0.92961279, "gain_db": -0.633958, "phase_deg": -21.625464}+{"point": 37, "frequency_hz": 707.945784, "gain_linear": 0.913685695, "gain_db": -0.784063, "phase_deg": -23.980238}+{"point": 38, "frequency_hz": 794.328235, "gain_linear": 0.894752233, "gain_db": -0.965944, "phase_deg": -26.523377}+{"point": 39, "frequency_hz": 891.250938, "gain_linear": 0.872509929, "gain_db": -1.184592, "phase_deg": -29.248367}+{"point": 40, "frequency_hz": 1000.0, "gain_linear": 0.846733016, "gain_db": -1.44507, "phase_deg": -32.141908}+{"point": 41, "frequency_hz": 1122.018454, "gain_linear": 0.817313258, "gain_db": -1.752229, "phase_deg": -35.183262}+{"point": 42, "frequency_hz": 1258.925412, "gain_linear": 0.784297864, "gain_db": -2.110379, "phase_deg": -38.344214}+{"point": 43, "frequency_hz": 1412.537545, "gain_linear": 0.747916172, "gain_db": -2.522942, "phase_deg": -41.589809}+{"point": 44, "frequency_hz": 1584.893192, "gain_linear": 0.708586968, "gain_db": -2.992137, "phase_deg": -44.879937}+{"point": 45, "frequency_hz": 1778.27941, "gain_linear": 0.666901282, "gain_db": -3.518769, "phase_deg": -48.171648}+{"point": 46, "frequency_hz": 1995.262315, "gain_linear": 0.623581005, "gain_db": -4.102142, "phase_deg": -51.421887}+{"point": 47, "frequency_hz": 2238.721139, "gain_linear": 0.5794198, "gain_db": -4.740133, "phase_deg": -54.590255}+{"point": 48, "frequency_hz": 2511.886432, "gain_linear": 0.535217207, "gain_db": -5.429399, "phase_deg": -57.641357}+{"point": 49, "frequency_hz": 2818.382931, "gain_linear": 0.49171779, "gain_db": -6.165682, "phase_deg": -60.54645}+{"point": 50, "frequency_hz": 3162.27766, "gain_linear": 0.449564593, "gain_db": -6.944158, "phase_deg": -63.284248}+{"point": 51, "frequency_hz": 3548.133892, "gain_linear": 0.409271441, "gain_db": -7.759771, "phase_deg": -65.840924}+{"point": 52, "frequency_hz": 3981.071706, "gain_linear": 0.371213879, "gain_db": -8.607516, "phase_deg": -68.2095}+{"point": 53, "frequency_hz": 4466.835922, "gain_linear": 0.335635108, "gain_db": -9.482652, "phase_deg": -70.388837}+{"point": 54, "frequency_hz": 5011.872336, "gain_linear": 0.302661856, "gain_db": -10.380846, "phase_deg": -72.382449}+{"point": 55, "frequency_hz": 5623.413252, "gain_linear": 0.272325219, "gain_db": -11.298243, "phase_deg": -74.197322}+{"point": 56, "frequency_hz": 6309.573445, "gain_linear": 0.244582562, "gain_db": -12.23149, "phase_deg": -75.842834}+{"point": 57, "frequency_hz": 7079.457844, "gain_linear": 0.219337917, "gain_db": -13.177726, "phase_deg": -77.329851}+{"point": 58, "frequency_hz": 7943.282347, "gain_linear": 0.196459493, "gain_db": -14.13454, "phase_deg": -78.670004}+{"point": 59, "frequency_hz": 8912.509381, "gain_linear": 0.175793839, "gain_db": -15.099927, "phase_deg": -79.875142}+{"point": 60, "frequency_hz": 10000.0, "gain_linear": 0.157176725, "gain_db": -16.072235, "phase_deg": -80.956939}+{"point": 61, "frequency_hz": 11220.184543, "gain_linear": 0.140441151, "gain_db": -17.050112, "phase_deg": -81.926625}+{"point": 62, "frequency_hz": 12589.254118, "gain_linear": 0.125422962, "gain_db": -18.032459, "phase_deg": -82.794818}+{"point": 63, "frequency_hz": 14125.375446, "gain_linear": 0.111964605, "gain_db": -19.018385, "phase_deg": -83.571421}+{"point": 64, "frequency_hz": 15848.931925, "gain_linear": 0.099917452, "gain_db": -20.007173, "phase_deg": -84.265583}+{"point": 65, "frequency_hz": 17782.7941, "gain_linear": 0.089143089, "gain_db": -20.998246, "phase_deg": -84.885688}+{"point": 66, "frequency_hz": 19952.62315, "gain_linear": 0.079513866, "gain_db": -21.991143, "phase_deg": -85.439377}+{"point": 67, "frequency_hz": 22387.211386, "gain_linear": 0.070912928, "gain_db": -22.985492, "phase_deg": -85.933576}+{"point": 68, "frequency_hz": 25118.864315, "gain_linear": 0.063233922, "gain_db": -23.980998, "phase_deg": -86.374544}+{"point": 69, "frequency_hz": 28183.829313, "gain_linear": 0.056380481, "gain_db": -24.977425, "phase_deg": -86.767923}+{"point": 70, "frequency_hz": 31622.776602, "gain_linear": 0.05026559, "gain_db": -25.974584, "phase_deg": -87.11878}+{"point": 71, "frequency_hz": 35481.338923, "gain_linear": 0.044810899, "gain_db": -26.972327, "phase_deg": -87.431665}+{"point": 72, "frequency_hz": 39810.717055, "gain_linear": 0.039946005, "gain_db": -27.970533, "phase_deg": -87.710653}+{"point": 73, "frequency_hz": 44668.359215, "gain_linear": 0.035607758, "gain_db": -28.969107, "phase_deg": -87.959394}+{"point": 74, "frequency_hz": 50118.723363, "gain_linear": 0.031739587, "gain_db": -29.967975, "phase_deg": -88.18115}+{"point": 75, "frequency_hz": 56234.132519, "gain_linear": 0.028290867, "gain_db": -30.967075, "phase_deg": -88.378836}+{"point": 76, "frequency_hz": 63095.734448, "gain_linear": 0.025216338, "gain_db": -31.96636, "phase_deg": -88.555057}+{"point": 77, "frequency_hz": 70794.578438, "gain_linear": 0.022475554, "gain_db": -32.965792, "phase_deg": -88.712137}+{"point": 78, "frequency_hz": 79432.823472, "gain_linear": 0.0200324, "gain_db": -33.965341, "phase_deg": -88.852151}+{"point": 79, "frequency_hz": 89125.093813, "gain_linear": 0.017854632, "gain_db": -34.964982, "phase_deg": -88.976951}+{"point": 80, "frequency_hz": 100000.0, "gain_linear": 0.015913479, "gain_db": -35.964697, "phase_deg": -89.088186}+{"point": 81, "frequency_hz": 112201.84543, "gain_linear": 0.014183272, "gain_db": -36.964471, "phase_deg": -89.187331}+{"point": 82, "frequency_hz": 125892.541179, "gain_linear": 0.012641116, "gain_db": -37.964291, "phase_deg": -89.275698}+{"point": 83, "frequency_hz": 141253.754462, "gain_linear": 0.011266592, "gain_db": -38.964149, "phase_deg": -89.354458}+{"point": 84, "frequency_hz": 158489.319246, "gain_linear": 0.010041492, "gain_db": -39.964035, "phase_deg": -89.424655}+{"point": 85, "frequency_hz": 177827.941004, "gain_linear": 0.008949582, "gain_db": -40.963945, "phase_deg": -89.48722}+{"point": 86, "frequency_hz": 199526.231497, "gain_linear": 0.007976389, "gain_db": -41.963874, "phase_deg": -89.542982}+{"point": 87, "frequency_hz": 223872.113857, "gain_linear": 0.007109011, "gain_db": -42.963817, "phase_deg": -89.59268}+{"point": 88, "frequency_hz": 251188.643151, "gain_linear": 0.006335945, "gain_db": -43.963772, "phase_deg": -89.636975}+{"point": 89, "frequency_hz": 281838.293126, "gain_linear": 0.00564694, "gain_db": -44.963736, "phase_deg": -89.676452}+{"point": 90, "frequency_hz": 316227.766017, "gain_linear": 0.005032857, "gain_db": -45.963707, "phase_deg": -89.711637}+{"point": 91, "frequency_hz": 354813.389234, "gain_linear": 0.004485551, "gain_db": -46.963685, "phase_deg": -89.742996}+{"point": 92, "frequency_hz": 398107.170553, "gain_linear": 0.003997759, "gain_db": -47.963667, "phase_deg": -89.770945}+{"point": 93, "frequency_hz": 446683.592151, "gain_linear": 0.003563013, "gain_db": -48.963653, "phase_deg": -89.795854}+{"point": 94, "frequency_hz": 501187.233627, "gain_linear": 0.003175543, "gain_db": -49.963641, "phase_deg": -89.818055}+{"point": 95, "frequency_hz": 562341.32519, "gain_linear": 0.002830208, "gain_db": -50.963632, "phase_deg": -89.837841}+{"point": 96, "frequency_hz": 630957.34448, "gain_linear": 0.002522428, "gain_db": -51.963625, "phase_deg": -89.855475}+{"point": 97, "frequency_hz": 707945.784384, "gain_linear": 0.002248118, "gain_db": -52.963619, "phase_deg": -89.871192}+{"point": 98, "frequency_hz": 794328.234724, "gain_linear": 0.002003638, "gain_db": -53.963615, "phase_deg": -89.8852}+{"point": 99, "frequency_hz": 891250.938134, "gain_linear": 0.001785745, "gain_db": -54.963611, "phase_deg": -89.897684}+{"point": 100, "frequency_hz": 1000000.0, "gain_linear": 0.001591547, "gain_db": -55.963608, "phase_deg": -89.908811}
data/rc_lowpass_response.sidecar.jsonadded+60@@ -0,0 +1,60 @@+{+ "dataset": "rc_lowpass_response.jsonl",+ "title": "RC low-pass filter frequency response (computed)",+ "description": "Magnitude and phase of a first-order RC low-pass filter (R=1 kOhm, C=100 nF, fc~=1591.5 Hz), 20 points/decade from 10 Hz to 1 MHz.",+ "created_utc": "2026-07-10T00:00:00Z",+ "generator": {+ "script": "analysis/run_experiment.py",+ "runtime": "python3",+ "deterministic": true+ },+ "method": "closed-form transfer function H(f) = 1/(1 + j*2*pi*f*R*C); no physical measurement",+ "parameters": {+ "R_ohms": 1000.0,+ "C_farads": 1e-07,+ "f_cutoff_hz": 1591.549,+ "points_per_decade": 20,+ "f_range_hz": [+ 10,+ 1000000+ ]+ },+ "schema": {+ "format": "jsonl",+ "fields": [+ {+ "name": "point",+ "type": "int",+ "unit": null,+ "description": "0-based sample index"+ },+ {+ "name": "frequency_hz",+ "type": "float",+ "unit": "Hz",+ "description": "stimulus frequency"+ },+ {+ "name": "gain_linear",+ "type": "float",+ "unit": "V/V",+ "description": "|H(f)|"+ },+ {+ "name": "gain_db",+ "type": "float",+ "unit": "dB",+ "description": "20*log10(|H(f)|)"+ },+ {+ "name": "phase_deg",+ "type": "float",+ "unit": "degrees",+ "description": "arg(H(f)), negative = lag"+ }+ ]+ },+ "rows": 101,+ "sha256": "f622e21f616ffe606c482b424fa144e978c0398e9b09ec57e1d0db93fb4268b3",+ "license": "CC-BY-4.0"+}
docs/bode-plot.pngadded⋯ 1 unchanged line ⋯
docs/hero.pngadded⋯ 1 unchanged line ⋯
install.shadded+3@@ -0,0 +1,3 @@+#!/bin/sh+# Reference experiment page - nothing to install.+exit 0
package.jsonadded+49@@ -0,0 +1,49 @@+{+ "slug": "sample-experiment-rc-lowpass",+ "title": "Sample Experiment: RC Low-Pass Filter Response",+ "type": "app",+ "version": "1.0.0",+ "description": "Working sample of Adom's experiment publication format: RC low-pass frequency response with JSONL dataset, sidecar metadata, provenance, and a reproduction skill. Prepared for NSF PCL FAIR-data due diligence.",+ "tags": [+ "experiment",+ "sample",+ "fair-data",+ "rc-filter"+ ],+ "dependencies": {},+ "discovery_triggers": [+ "sample experiment page",+ "adom experiment format",+ "fair data example",+ "rc lowpass sample experiment",+ "nsf data sharing example"+ ],+ "discovery_pitch": "One line: when should an agent reach for sample-experiment-rc-lowpass?",+ "sample_prompts": [+ {+ "label": "Example",+ "prompt": "a real user utterance that should surface sample-experiment-rc-lowpass"+ }+ ],+ "metadata": {+ "activate": {+ "kind": "bridge",+ "skill": "sample-experiment-rc-lowpass",+ "requires": [],+ "verbPrefixes": []+ }+ },+ "scripts": {+ "install": "./install.sh",+ "uninstall": "./uninstall.sh"+ },+ "hero": {+ "headline": "Sample Experiment: RC Low-Pass Filter Response",+ "subhead": "A one-line tagline (replace me).",+ "screenshot": "docs/hero.png"+ },+ "license": "CC-BY-4.0",+ "confirmed_user_skills": [+ "reproduce-rc-characterization"+ ]+}
provenance.jsonadded+31@@ -0,0 +1,31 @@+{+ "experiment": "sample-experiment-rc-lowpass",+ "performed_utc": "2026-07-10T00:00:00Z",+ "performed_by": {+ "agent": "Claude (Adom AI agent)",+ "direction": "human-prompted, AI-executed",+ "prompted_by": "John Lauer <[email protected]>, PI"+ },+ "kind": "computed characterization (closed-form model); no physical parts consumed",+ "reproduce": "python3 analysis/run_experiment.py (deterministic; regenerates data + sidecar + plot bit-for-bit)",+ "inputs": {+ "model": "first-order RC low-pass transfer function H(f) = 1/(1 + j*2*pi*f*R*C)",+ "code": "analysis/run_experiment.py",+ "runtime": "python3 + matplotlib"+ },+ "design_references": [+ {"role": "R (1 kOhm 1% 0603)", "mpn": "RC0603FR-071KL", "manufacturer": "Yageo"},+ {"role": "C (100 nF X7R 0603)", "mpn": "GRM188R71H104KA93D", "manufacturer": "Murata"}+ ],+ "outputs": [+ {"file": "data/rc_lowpass_response.jsonl", "sha256": "f622e21f616ffe60", "note": "full hash in sidecar"},+ {"file": "data/rc_lowpass_response.sidecar.json"},+ {"file": "docs/bode-plot.png"}+ ],+ "chain": [+ "PI request (NSF PCL FAIR-data questionnaire, July 2026)",+ "AI skill authored: skills/reproduce-rc-characterization",+ "analysis/run_experiment.py generated dataset + sidecar + plot",+ "page published to wiki.adom.inc/adom/sample-experiment-rc-lowpass (immediate publication, no embargo)"+ ]+}
skills/reproduce-rc-characterization/SKILL.mdadded+30@@ -0,0 +1,30 @@+---+name: reproduce-rc-characterization+description: Reproduce the sample RC low-pass characterization experiment on this page - regenerate the JSONL dataset, sidecar metadata, and Bode plot deterministically. Trigger words - reproduce the experiment, rerun the RC experiment, regenerate the dataset, verify the data, rc lowpass sample experiment.+user-invocable: true+---++# Reproduce the RC low-pass characterization++This page's dataset is fully reproducible. One command regenerates everything:++```bash+python3 analysis/run_experiment.py+```++It rewrites, deterministically (bit-for-bit):++- `data/rc_lowpass_response.jsonl` - 101 rows, 20 points/decade, 10 Hz - 1 MHz+- `data/rc_lowpass_response.sidecar.json` - dataset metadata (schema, units, parameters, sha256)+- `docs/bode-plot.png` - the Bode plot in the README++To verify integrity instead of regenerating, compare the dataset's sha256 with+the value recorded in the sidecar:++```bash+sha256sum data/rc_lowpass_response.jsonl+python3 -c "import json; print(json.load(open('data/rc_lowpass_response.sidecar.json'))['sha256'])"+```++Change `R_OHMS` / `C_FARADS` at the top of `analysis/run_experiment.py` to+characterize a different filter; the sidecar and plot update to match.
uninstall.shadded+3@@ -0,0 +1,3 @@+#!/bin/sh+# Reference experiment page - nothing to uninstall.+exit 0