glitchgan 0.1.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (45) hide show
  1. glitchgan-0.1.0/.gitattributes +1 -0
  2. glitchgan-0.1.0/.github/workflows/publish.yml +51 -0
  3. glitchgan-0.1.0/.gitignore +41 -0
  4. glitchgan-0.1.0/.readthedocs.yaml +16 -0
  5. glitchgan-0.1.0/MODEL_CARD.md +146 -0
  6. glitchgan-0.1.0/PKG-INFO +125 -0
  7. glitchgan-0.1.0/README.md +89 -0
  8. glitchgan-0.1.0/docs/_static/custom.css +120 -0
  9. glitchgan-0.1.0/docs/conf.py +83 -0
  10. glitchgan-0.1.0/docs/guides/installation.rst +58 -0
  11. glitchgan-0.1.0/docs/guides/overview.rst +84 -0
  12. glitchgan-0.1.0/docs/guides/quickstart.rst +70 -0
  13. glitchgan-0.1.0/docs/guides/training.rst +65 -0
  14. glitchgan-0.1.0/docs/index.rst +40 -0
  15. glitchgan-0.1.0/environment.yml +51 -0
  16. glitchgan-0.1.0/history.json +1 -0
  17. glitchgan-0.1.0/models/README.md +26 -0
  18. glitchgan-0.1.0/notebooks/evaluation.ipynb +999 -0
  19. glitchgan-0.1.0/notebooks/gspy_classification.ipynb +420 -0
  20. glitchgan-0.1.0/notebooks/inject_into_detector_noise.ipynb +449 -0
  21. glitchgan-0.1.0/pyproject.toml +62 -0
  22. glitchgan-0.1.0/scripts/convert_keras2_to_keras3.py +145 -0
  23. glitchgan-0.1.0/scripts/convert_tf_generator.py +73 -0
  24. glitchgan-0.1.0/scripts/setup_local.sh +75 -0
  25. glitchgan-0.1.0/setup.cfg +4 -0
  26. glitchgan-0.1.0/src/glitchgan/__init__.py +5 -0
  27. glitchgan-0.1.0/src/glitchgan/_version.py +24 -0
  28. glitchgan-0.1.0/src/glitchgan/glitchgan.py +372 -0
  29. glitchgan-0.1.0/src/glitchgan/tf/__init__.py +5 -0
  30. glitchgan-0.1.0/src/glitchgan/tf/gan_models.py +317 -0
  31. glitchgan-0.1.0/src/glitchgan/tf/model_components.py +202 -0
  32. glitchgan-0.1.0/src/glitchgan/tf/train.py +162 -0
  33. glitchgan-0.1.0/src/glitchgan/tf/utils.py +320 -0
  34. glitchgan-0.1.0/src/glitchgan/utils.py +481 -0
  35. glitchgan-0.1.0/src/glitchgan.egg-info/PKG-INFO +125 -0
  36. glitchgan-0.1.0/src/glitchgan.egg-info/SOURCES.txt +43 -0
  37. glitchgan-0.1.0/src/glitchgan.egg-info/dependency_links.txt +1 -0
  38. glitchgan-0.1.0/src/glitchgan.egg-info/entry_points.txt +2 -0
  39. glitchgan-0.1.0/src/glitchgan.egg-info/requires.txt +19 -0
  40. glitchgan-0.1.0/src/glitchgan.egg-info/top_level.txt +1 -0
  41. glitchgan-0.1.0/tests/conftest.py +28 -0
  42. glitchgan-0.1.0/tests/test_glitchgan.py +181 -0
  43. glitchgan-0.1.0/tests/test_snr.py +58 -0
  44. glitchgan-0.1.0/weights/pytorch/README.md +38 -0
  45. glitchgan-0.1.0/weights/tensorflow/generator_210_keras3.keras +0 -0
@@ -0,0 +1 @@
1
+ *pkl filter=lfs diff=lfs merge=lfs -text
@@ -0,0 +1,51 @@
1
+ name: Publish to PyPI
2
+
3
+ on:
4
+ push:
5
+ tags:
6
+ - "v*"
7
+
8
+ jobs:
9
+ build:
10
+ runs-on: ubuntu-latest
11
+ steps:
12
+ - uses: actions/checkout@v4
13
+ with:
14
+ fetch-depth: 0
15
+
16
+ - uses: actions/setup-python@v5
17
+ with:
18
+ python-version: "3.11"
19
+
20
+ - name: Extract version from tag
21
+ id: version
22
+ run: echo "version=${GITHUB_REF_NAME#v}" >> $GITHUB_OUTPUT
23
+
24
+ - name: Build distributions
25
+ env:
26
+ SETUPTOOLS_SCM_PRETEND_VERSION: ${{ steps.version.outputs.version }}
27
+ run: |
28
+ pip install build
29
+ python -m build
30
+
31
+ - name: Upload build artifacts
32
+ uses: actions/upload-artifact@v4
33
+ with:
34
+ name: dist
35
+ path: dist/
36
+
37
+ publish:
38
+ needs: build
39
+ runs-on: ubuntu-latest
40
+ environment: pypi
41
+ permissions:
42
+ id-token: write # required for Trusted Publisher (OIDC)
43
+ steps:
44
+ - name: Download build artifacts
45
+ uses: actions/download-artifact@v4
46
+ with:
47
+ name: dist
48
+ path: dist/
49
+
50
+ - name: Publish to PyPI
51
+ uses: pypa/gh-action-pypi-publish@release/v1
@@ -0,0 +1,41 @@
1
+ # Data (too large for git — see README for download instructions)
2
+ data/
3
+
4
+ # Generated outputs
5
+ evaluation_plots/
6
+ plots/
7
+ GAN_outputs*/
8
+
9
+ # GravitySpy model weights (large binary — download separately)
10
+ models/
11
+
12
+ # PyTorch weights (not part of published release)
13
+ weights/pytorch/
14
+
15
+ # Python
16
+ __pycache__/
17
+ *.py[cod]
18
+ *.egg-info/
19
+ dist/
20
+ build/
21
+ .eggs/
22
+ *.egg
23
+ src/cdvgan/_version.py
24
+ src/glitchgan/_version.py
25
+
26
+ # Jupyter
27
+ .ipynb_checkpoints/
28
+
29
+ # Environment
30
+ .env
31
+ *.log
32
+
33
+ # macOS
34
+ .DS_Store
35
+
36
+ # Classification output CSVs
37
+ notebooks/*.csv
38
+
39
+ # Sphinx docs build + auto-copied notebooks (canonical copies live in notebooks/)
40
+ docs/_build/
41
+ docs/notebooks/
@@ -0,0 +1,16 @@
1
+ version: 2
2
+
3
+ build:
4
+ os: ubuntu-24.04
5
+ tools:
6
+ python: "3.11"
7
+
8
+ sphinx:
9
+ configuration: docs/conf.py
10
+
11
+ python:
12
+ install:
13
+ - method: pip
14
+ path: .
15
+ extra_requirements:
16
+ - docs
@@ -0,0 +1,146 @@
1
+ ---
2
+ license: mit
3
+ tags:
4
+ - gravitational-waves
5
+ - time-series
6
+ - generative-model
7
+ - gan
8
+ - ligo
9
+ - detector-characterization
10
+ - physics
11
+ library_name: keras
12
+ pipeline_tag: time-series-to-time-series
13
+ ---
14
+
15
+ # GlitchGAN — Synthetic LIGO Glitch Generator
16
+
17
+ GlitchGAN is a class-conditional generative model that synthesizes realistic
18
+ gravitational-wave detector glitches directly in the time domain.
19
+ It is built on the **cDVGAN** (Conditional Derivative GAN) architecture,
20
+ which uses a first-derivative discriminator alongside the standard signal
21
+ discriminator to enforce temporal smoothness in generated waveforms.
22
+
23
+ The model is trained on high-quality glitch reconstructions produced by
24
+ [DeepExtractor](https://github.com/fbianco/deepextractor), a U-Net framework
25
+ for glitch reconstruction from LIGO strain data, covering seven common glitch
26
+ classes observed during LIGO's third observing run (O3).
27
+
28
+ ## Supported glitch classes
29
+
30
+ | Index | Class | Description |
31
+ |-------|-------|-------------|
32
+ | 0 | Blip | Short, broadband transient |
33
+ | 1 | Fast\_Scattering | Arches at low frequency from scattered light |
34
+ | 2 | Koi\_Fish | Low-frequency dispersive burst |
35
+ | 3 | Low\_Frequency\_Burst | Broadband low-frequency transient |
36
+ | 4 | Scattered\_Light | Repeated arch pattern from optical scattering |
37
+ | 5 | Tomte | Short, low-frequency transient |
38
+ | 6 | Whistle | Narrow-band high-frequency chirp |
39
+
40
+ ## Quick start
41
+
42
+ ```bash
43
+ pip install glitchgan
44
+ ```
45
+
46
+ ```python
47
+ from cdvgan import GlitchGAN
48
+
49
+ # Download pretrained weights automatically (cached after first call)
50
+ model = GlitchGAN.from_pretrained()
51
+
52
+ # Generate 10 Blip glitches at SNR 50
53
+ blips = model.generate("Blip", n=10, snr=50)
54
+ # blips.shape → (10, 8192) — 2 s at 4096 Hz
55
+
56
+ # Generate a mix of classes
57
+ glitches = model.generate(["Blip", "Tomte", "Whistle"], n=3, snr=30)
58
+
59
+ # Class interpolation — hybrid Blip/Koi Fish morphology
60
+ hybrids = model.interpolate([0.5, 0, 0.5, 0, 0, 0, 0], n=5)
61
+ ```
62
+
63
+ Output waveforms are 2-second segments at 4096 Hz (8192 samples).
64
+ Pass `snr=None` (default) to get the raw normalized generator output,
65
+ or specify a target SNR to rescale to a physically meaningful amplitude.
66
+
67
+ ## Model details
68
+
69
+ | Property | Value |
70
+ |----------|-------|
71
+ | Architecture | cDVGAN (conditional WGAN-GP + derivative discriminator) |
72
+ | Signal length | 8192 samples (2 s at 4096 Hz) |
73
+ | Noise dim | 100 |
74
+ | Num classes | 7 |
75
+ | Training epochs | 210 |
76
+ | Optimizer | RMSprop (lr=1e-4) |
77
+ | Gradient penalty weight | 10 |
78
+ | Framework | TensorFlow / Keras 3 |
79
+
80
+ ## Training data
81
+
82
+ The model was trained on DeepExtractor reconstructions of real LIGO glitches
83
+ from O3 (2019–2020), curated using [Gravity Spy](https://www.zooniverse.org/projects/zooniverse/gravity-spy)
84
+ classifications.
85
+ Seven glitch classes were selected with balanced class sizes.
86
+ Waveforms are whitened and normalized before training; the generator
87
+ therefore learns a normalized waveform distribution and SNR scaling is
88
+ applied at inference time.
89
+
90
+ ## Evaluation
91
+
92
+ Synthetic glitches were evaluated against real data using:
93
+
94
+ 1. **Gravity Spy classification** — the fraction of generated samples
95
+ correctly classified by the state-of-the-art Gravity Spy classifier.
96
+ 2. **UMAP embeddings** — unsupervised 3-D projections to compare the
97
+ morphological distributions of real and synthetic samples.
98
+
99
+ Selected Gravity Spy results at SNR 100 (100 samples per class):
100
+
101
+ | Class | Accuracy |
102
+ |-------|----------|
103
+ | Blip | 88% |
104
+ | Fast Scattering | 72% |
105
+ | Koi Fish | 20% (SNR-sensitive; 79% at SNR 150) |
106
+ | Low Frequency Burst | 100% |
107
+ | Scattered Light | 42% (often confused with Fast Scattering) |
108
+ | Tomte | 92% |
109
+ | Whistle | 94% |
110
+
111
+ UMAP embeddings show strong overlap between real and synthetic samples
112
+ for most classes. Whistle glitches show partial separation, attributed to
113
+ the model's difficulty with fine-scale high-frequency structure.
114
+
115
+ ## Limitations
116
+
117
+ - **SNR sensitivity**: GlitchGAN does not model an SNR distribution.
118
+ Generated waveforms must be manually rescaled. Classification accuracy
119
+ for morphologically ambiguous classes (Koi Fish, Scattered Light) is
120
+ strongly SNR-dependent.
121
+ - **Whistle class**: Synthetic Whistle glitches form a partially distinct
122
+ cluster from real data in UMAP space, indicating incomplete capture of
123
+ high-frequency structure.
124
+ - **Seven classes only**: The model covers the seven classes present in
125
+ the O3 training set. It cannot generate unseen glitch morphologies.
126
+ - **LIGO-specific**: Trained on LIGO H1/L1 data. Generalization to Virgo
127
+ or KAGRA data has not been evaluated.
128
+
129
+ ## Citation
130
+
131
+ If you use GlitchGAN in your work, please cite:
132
+
133
+ ```bibtex
134
+ @article{Dooney2026GlitchGAN,
135
+ title = {Realistic Time-Domain Synthesis of Gravitational-Wave Detector
136
+ Glitches using Class-Conditional Derivative Generative Adversarial Networks},
137
+ author = {Dooney, Tom and de Boer, Mees and Narola, Harsh and Lopez, Melissa
138
+ and Bromuri, Stefano and Tan, Daniel Stanley and Van Den Broeck, Chris},
139
+ journal = {Physical Review D},
140
+ year = {2026},
141
+ }
142
+ ```
143
+
144
+ ## License
145
+
146
+ MIT
@@ -0,0 +1,125 @@
1
+ Metadata-Version: 2.4
2
+ Name: glitchgan
3
+ Version: 0.1.0
4
+ Summary: Synthetic LIGO gravitational-wave glitch generator (cDVGAN architecture)
5
+ Author-email: Tom Dooney <tom.dooney95@gmail.com>
6
+ License: MIT
7
+ Project-URL: Repository, https://github.com/tomdooney95/glitchgan
8
+ Project-URL: Documentation, https://glitchgan.readthedocs.io/
9
+ Keywords: gravitational-waves,LIGO,GAN,glitch,machine-learning
10
+ Classifier: Development Status :: 4 - Beta
11
+ Classifier: Intended Audience :: Science/Research
12
+ Classifier: License :: OSI Approved :: MIT License
13
+ Classifier: Programming Language :: Python :: 3
14
+ Classifier: Programming Language :: Python :: 3.10
15
+ Classifier: Programming Language :: Python :: 3.11
16
+ Classifier: Topic :: Scientific/Engineering :: Astronomy
17
+ Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
18
+ Requires-Python: >=3.10
19
+ Description-Content-Type: text/markdown
20
+ Requires-Dist: numpy>=1.26
21
+ Requires-Dist: matplotlib>=3.9
22
+ Requires-Dist: huggingface_hub>=0.23
23
+ Requires-Dist: tensorflow>=2.16
24
+ Requires-Dist: keras>=3.0
25
+ Provides-Extra: dev
26
+ Requires-Dist: pytest>=8; extra == "dev"
27
+ Requires-Dist: pytest-cov>=5; extra == "dev"
28
+ Provides-Extra: docs
29
+ Requires-Dist: sphinx>=7; extra == "docs"
30
+ Requires-Dist: sphinx-autoapi>=3; extra == "docs"
31
+ Requires-Dist: furo>=2024.1.29; extra == "docs"
32
+ Requires-Dist: myst-parser>=3; extra == "docs"
33
+ Requires-Dist: nbsphinx>=0.9; extra == "docs"
34
+ Provides-Extra: all
35
+ Requires-Dist: glitchgan[dev,docs]; extra == "all"
36
+
37
+ # GlitchGAN
38
+
39
+ Conditional Dual-discriminator Variational GAN (cDVGAN) for synthesising LIGO gravitational-wave glitch signals. Trained on seven Gravity Spy glitch classes from the O3 observing run.
40
+
41
+ ## Overview
42
+
43
+ GlitchGAN uses a Wasserstein GAN with gradient penalty (WGAN-GP) augmented by a first-derivative discriminator. The derivative discriminator encourages the generator to produce signals with realistic time-domain structure, not just realistic amplitude distributions.
44
+
45
+ **Architecture:** Generator + Discriminator + Derivative Discriminator
46
+ **Classes:** Blip, Fast Scattering, Koi Fish, Low Frequency Burst, Scattered Light, Tomte, Whistle
47
+ **Signal length:** 8192 samples @ 4096 Hz (~2 s)
48
+
49
+ ## Repository structure
50
+
51
+ ```
52
+ glitchgan/
53
+ ├── evaluation.ipynb # UMAP + GravitySpy evaluation notebook
54
+ ├── src/cdvgan/
55
+ │ ├── tf/
56
+ │ │ ├── model_components.py # Generator / discriminator layers
57
+ │ │ ├── gan_models.py # cWGAN, cDVGAN, cDVGAN2, GlitchGAN
58
+ │ │ ├── train.py # Training entry point
59
+ │ │ └── utils.py # Dataset, callbacks, checkpointing
60
+ │ └── utils.py # Signal processing utilities
61
+ ├── weights/tensorflow/
62
+ │ └── generator_210_keras3.keras # Trained generator (epoch 210)
63
+ ├── models/ # GravitySpy CNN weights (gitignored — see below)
64
+ ├── data/ # Training data (gitignored — see below)
65
+ └── environment.yml
66
+ ```
67
+
68
+ ## Setup
69
+
70
+ ```bash
71
+ conda env create -f environment.yml
72
+ conda activate cdvgan
73
+ ```
74
+
75
+ The environment installs TensorFlow, Keras 3, GWpy, PyCBC, umap-learn, and GravitySpy.
76
+
77
+ > **Note:** `environment.yml` targets Apple Silicon (tensorflow-macos / tensorflow-metal). On Linux/HPC replace those with `tensorflow` and remove `tensorflow-metal`.
78
+
79
+ ## Data
80
+
81
+ The training data (~2.3 GB) is not included in this repository.
82
+
83
+ **Download from Zenodo:** *(link TBD — will be added before publication)*
84
+
85
+ Place the downloaded files in `data/`:
86
+
87
+ ```
88
+ data/
89
+ ├── glitch_GAN_samples_scaled_balanced.npy # (N, 8192) float32 signals
90
+ ├── glitch_GAN_labels_balanced.npy # (N, 7) one-hot labels
91
+ └── glitch_GAN_label_order.npy # class name ordering
92
+ ```
93
+
94
+ ## GravitySpy model
95
+
96
+ The GravitySpy O3 CNN (`sidd-cqg-paper-O3-model.h5`) is not included. It ships with the `gravityspy` package or can be found in a local GravitySpy clone.
97
+
98
+ 1. Install GravitySpy: `pip install gravityspy`
99
+ 2. Copy the model to `models/sidd-cqg-paper-O3-model.h5`
100
+ 3. Set `PATH_TO_REPO` in `evaluation.ipynb` to your GravitySpy clone path
101
+
102
+ ## Training
103
+
104
+ ```bash
105
+ python -m cdvgan.tf.train \
106
+ --data-dir data/ \
107
+ --variant cDVGAN \
108
+ --epochs 500 \
109
+ --output-dir GAN_outputs/
110
+ ```
111
+
112
+ See `src/cdvgan/tf/train.py` for all options.
113
+
114
+ ## Evaluation
115
+
116
+ Open `evaluation.ipynb` and run all cells. The notebook:
117
+
118
+ 1. Loads real glitch data and the trained generator
119
+ 2. Visualises real vs generated waveforms
120
+ 3. Embeds real and generated signals jointly in 3D UMAP space (correlation metric)
121
+ 4. Injects generated signals into whitened H1 background and classifies with GravitySpy
122
+
123
+ ## Citation
124
+
125
+ *(BibTeX will be added upon publication)*
@@ -0,0 +1,89 @@
1
+ # GlitchGAN
2
+
3
+ Conditional Dual-discriminator Variational GAN (cDVGAN) for synthesising LIGO gravitational-wave glitch signals. Trained on seven Gravity Spy glitch classes from the O3 observing run.
4
+
5
+ ## Overview
6
+
7
+ GlitchGAN uses a Wasserstein GAN with gradient penalty (WGAN-GP) augmented by a first-derivative discriminator. The derivative discriminator encourages the generator to produce signals with realistic time-domain structure, not just realistic amplitude distributions.
8
+
9
+ **Architecture:** Generator + Discriminator + Derivative Discriminator
10
+ **Classes:** Blip, Fast Scattering, Koi Fish, Low Frequency Burst, Scattered Light, Tomte, Whistle
11
+ **Signal length:** 8192 samples @ 4096 Hz (~2 s)
12
+
13
+ ## Repository structure
14
+
15
+ ```
16
+ glitchgan/
17
+ ├── evaluation.ipynb # UMAP + GravitySpy evaluation notebook
18
+ ├── src/cdvgan/
19
+ │ ├── tf/
20
+ │ │ ├── model_components.py # Generator / discriminator layers
21
+ │ │ ├── gan_models.py # cWGAN, cDVGAN, cDVGAN2, GlitchGAN
22
+ │ │ ├── train.py # Training entry point
23
+ │ │ └── utils.py # Dataset, callbacks, checkpointing
24
+ │ └── utils.py # Signal processing utilities
25
+ ├── weights/tensorflow/
26
+ │ └── generator_210_keras3.keras # Trained generator (epoch 210)
27
+ ├── models/ # GravitySpy CNN weights (gitignored — see below)
28
+ ├── data/ # Training data (gitignored — see below)
29
+ └── environment.yml
30
+ ```
31
+
32
+ ## Setup
33
+
34
+ ```bash
35
+ conda env create -f environment.yml
36
+ conda activate cdvgan
37
+ ```
38
+
39
+ The environment installs TensorFlow, Keras 3, GWpy, PyCBC, umap-learn, and GravitySpy.
40
+
41
+ > **Note:** `environment.yml` targets Apple Silicon (tensorflow-macos / tensorflow-metal). On Linux/HPC replace those with `tensorflow` and remove `tensorflow-metal`.
42
+
43
+ ## Data
44
+
45
+ The training data (~2.3 GB) is not included in this repository.
46
+
47
+ **Download from Zenodo:** *(link TBD — will be added before publication)*
48
+
49
+ Place the downloaded files in `data/`:
50
+
51
+ ```
52
+ data/
53
+ ├── glitch_GAN_samples_scaled_balanced.npy # (N, 8192) float32 signals
54
+ ├── glitch_GAN_labels_balanced.npy # (N, 7) one-hot labels
55
+ └── glitch_GAN_label_order.npy # class name ordering
56
+ ```
57
+
58
+ ## GravitySpy model
59
+
60
+ The GravitySpy O3 CNN (`sidd-cqg-paper-O3-model.h5`) is not included. It ships with the `gravityspy` package or can be found in a local GravitySpy clone.
61
+
62
+ 1. Install GravitySpy: `pip install gravityspy`
63
+ 2. Copy the model to `models/sidd-cqg-paper-O3-model.h5`
64
+ 3. Set `PATH_TO_REPO` in `evaluation.ipynb` to your GravitySpy clone path
65
+
66
+ ## Training
67
+
68
+ ```bash
69
+ python -m cdvgan.tf.train \
70
+ --data-dir data/ \
71
+ --variant cDVGAN \
72
+ --epochs 500 \
73
+ --output-dir GAN_outputs/
74
+ ```
75
+
76
+ See `src/cdvgan/tf/train.py` for all options.
77
+
78
+ ## Evaluation
79
+
80
+ Open `evaluation.ipynb` and run all cells. The notebook:
81
+
82
+ 1. Loads real glitch data and the trained generator
83
+ 2. Visualises real vs generated waveforms
84
+ 3. Embeds real and generated signals jointly in 3D UMAP space (correlation metric)
85
+ 4. Injects generated signals into whitened H1 background and classifies with GravitySpy
86
+
87
+ ## Citation
88
+
89
+ *(BibTeX will be added upon publication)*
@@ -0,0 +1,120 @@
1
+ /* ── GlitchGAN custom dark theme ─────────────────────────────────────── */
2
+
3
+ /* Force dark mode as default */
4
+ :root {
5
+ color-scheme: dark;
6
+ }
7
+
8
+ /* Code blocks */
9
+ [data-theme="dark"] div[class*="highlight"] {
10
+ background: #161b27;
11
+ border: 1px solid #2a3147;
12
+ border-radius: 6px;
13
+ }
14
+
15
+ [data-theme="dark"] pre {
16
+ background: #161b27 !important;
17
+ }
18
+
19
+ /* Inline code */
20
+ [data-theme="dark"] code.literal {
21
+ background: #1c2333;
22
+ border: 1px solid #2a3147;
23
+ border-radius: 4px;
24
+ color: #79c0ff;
25
+ padding: 1px 5px;
26
+ }
27
+
28
+ /* Tables */
29
+ [data-theme="dark"] table.docutils {
30
+ border: 1px solid #2a3147;
31
+ border-radius: 6px;
32
+ overflow: hidden;
33
+ }
34
+
35
+ [data-theme="dark"] table.docutils th {
36
+ background: #161b27;
37
+ color: #e6edf3;
38
+ border-bottom: 2px solid #2a3147;
39
+ }
40
+
41
+ [data-theme="dark"] table.docutils td {
42
+ border-color: #2a3147;
43
+ }
44
+
45
+ [data-theme="dark"] table.docutils tr:hover td {
46
+ background: #1c2333;
47
+ }
48
+
49
+ /* Admonition boxes */
50
+ [data-theme="dark"] .admonition {
51
+ border-radius: 6px;
52
+ border-left: 4px solid var(--color-brand-primary);
53
+ background: #161b27;
54
+ }
55
+
56
+ [data-theme="dark"] .admonition.note {
57
+ border-left-color: #58a6ff;
58
+ }
59
+
60
+ [data-theme="dark"] .admonition.warning {
61
+ border-left-color: #d29922;
62
+ }
63
+
64
+ [data-theme="dark"] .admonition.tip {
65
+ border-left-color: #3fb950;
66
+ }
67
+
68
+ /* Sidebar logo / title */
69
+ .sidebar-brand-text {
70
+ font-weight: 700;
71
+ letter-spacing: 0.02em;
72
+ }
73
+
74
+ /* Content headings */
75
+ [data-theme="dark"] h1,
76
+ [data-theme="dark"] h2,
77
+ [data-theme="dark"] h3 {
78
+ color: #e6edf3;
79
+ }
80
+
81
+ [data-theme="dark"] h1 {
82
+ border-bottom: 1px solid #2a3147;
83
+ padding-bottom: 0.3em;
84
+ }
85
+
86
+ /* API reference member entries */
87
+ [data-theme="dark"] dl.py dt {
88
+ background: #161b27;
89
+ border-left: 3px solid #58a6ff;
90
+ border-radius: 0 4px 4px 0;
91
+ padding: 4px 8px;
92
+ color: #79c0ff;
93
+ }
94
+
95
+ /* Search bar */
96
+ [data-theme="dark"] input[type="search"] {
97
+ background: #161b27;
98
+ border: 1px solid #2a3147;
99
+ color: #e6edf3;
100
+ border-radius: 6px;
101
+ }
102
+
103
+ /* Scrollbar */
104
+ [data-theme="dark"] ::-webkit-scrollbar {
105
+ width: 6px;
106
+ height: 6px;
107
+ }
108
+
109
+ [data-theme="dark"] ::-webkit-scrollbar-track {
110
+ background: #0d1117;
111
+ }
112
+
113
+ [data-theme="dark"] ::-webkit-scrollbar-thumb {
114
+ background: #2a3147;
115
+ border-radius: 3px;
116
+ }
117
+
118
+ [data-theme="dark"] ::-webkit-scrollbar-thumb:hover {
119
+ background: #58a6ff;
120
+ }
@@ -0,0 +1,83 @@
1
+ import os
2
+ import shutil
3
+
4
+ # Auto-copy notebooks into docs/notebooks/ so Sphinx can include them in the
5
+ # toctree (Sphinx cannot reference files outside its source directory).
6
+ # docs/notebooks/ is gitignored — the canonical copies live in notebooks/.
7
+ _here = os.path.dirname(__file__)
8
+ _nb_src = os.path.join(_here, "..", "notebooks")
9
+ _nb_dst = os.path.join(_here, "notebooks")
10
+ os.makedirs(_nb_dst, exist_ok=True)
11
+ for _nb in [
12
+ "evaluation.ipynb",
13
+ "gspy_classification.ipynb",
14
+ "inject_into_detector_noise.ipynb",
15
+ ]:
16
+ _src = os.path.join(_nb_src, _nb)
17
+ if os.path.exists(_src):
18
+ shutil.copy(_src, os.path.join(_nb_dst, _nb))
19
+
20
+ project = "GlitchGAN"
21
+ author = "Tom Dooney"
22
+ copyright = "2026, Tom Dooney"
23
+ html_title = "GlitchGAN"
24
+
25
+ extensions = [
26
+ "sphinx.ext.autodoc",
27
+ "sphinx.ext.autosummary",
28
+ "sphinx.ext.napoleon", # Google/NumPy-style docstrings
29
+ "sphinx.ext.viewcode",
30
+ "sphinx.ext.intersphinx",
31
+ "autoapi.extension",
32
+ "myst_parser", # Markdown support
33
+ "nbsphinx", # Render Jupyter notebooks
34
+ ]
35
+
36
+ autoapi_dirs = ["../src"]
37
+ autoapi_type = "python"
38
+ autoapi_options = ["members", "undoc-members", "show-inheritance"]
39
+
40
+ intersphinx_mapping = {
41
+ "python": ("https://docs.python.org/3", None),
42
+ "numpy": ("https://numpy.org/doc/stable", None),
43
+ }
44
+
45
+ html_theme = "furo"
46
+ html_static_path = ["_static"]
47
+ html_css_files = ["custom.css"]
48
+
49
+ html_theme_options = {
50
+ "dark_css_variables": {
51
+ "--color-background-primary": "#0f1117",
52
+ "--color-background-secondary": "#161b27",
53
+ "--color-background-hover": "#1c2333",
54
+ "--color-background-border": "#2a3147",
55
+ "--color-brand-primary": "#58a6ff",
56
+ "--color-brand-content": "#79c0ff",
57
+ "--color-foreground-primary": "#e6edf3",
58
+ "--color-foreground-secondary": "#8b949e",
59
+ "--color-foreground-muted": "#6e7681",
60
+ "--color-foreground-border": "#30363d",
61
+ "--color-sidebar-background": "#0d1117",
62
+ "--color-sidebar-background-border": "#21262d",
63
+ "--color-sidebar-brand-text": "#e6edf3",
64
+ "--color-sidebar-caption-text": "#8b949e",
65
+ "--color-sidebar-link-text": "#c9d1d9",
66
+ "--color-sidebar-link-text--top-level": "#e6edf3",
67
+ "--color-sidebar-item-background--current": "#1f2937",
68
+ "--color-sidebar-item-background--hover": "#1c2333",
69
+ "--color-sidebar-item-expander-background--hover": "#1c2333",
70
+ "--color-inline-code-background": "#1c2333",
71
+ "--color-admonition-background": "#161b27",
72
+ },
73
+ "light_css_variables": {
74
+ "--color-brand-primary": "#0969da",
75
+ "--color-brand-content": "#0969da",
76
+ },
77
+ "navigation_with_keys": True,
78
+ }
79
+
80
+ exclude_patterns = ["_build", "**/_build", "**.ipynb_checkpoints"]
81
+
82
+ # Do not re-execute notebooks during the docs build
83
+ nbsphinx_execute = "never"