themisim 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 (36) hide show
  1. themisim-0.1.0/LICENSE +21 -0
  2. themisim-0.1.0/PKG-INFO +196 -0
  3. themisim-0.1.0/README.md +155 -0
  4. themisim-0.1.0/pyproject.toml +62 -0
  5. themisim-0.1.0/setup.cfg +4 -0
  6. themisim-0.1.0/src/themisim/__init__.py +73 -0
  7. themisim-0.1.0/src/themisim/catalog.py +220 -0
  8. themisim-0.1.0/src/themisim/cli/__init__.py +1 -0
  9. themisim-0.1.0/src/themisim/cli/build_index.py +96 -0
  10. themisim-0.1.0/src/themisim/cli/download.py +86 -0
  11. themisim-0.1.0/src/themisim/cli/query.py +93 -0
  12. themisim-0.1.0/src/themisim/concat.py +374 -0
  13. themisim-0.1.0/src/themisim/config.py +62 -0
  14. themisim-0.1.0/src/themisim/download.py +289 -0
  15. themisim-0.1.0/src/themisim/embed.py +1346 -0
  16. themisim-0.1.0/src/themisim/export.py +79 -0
  17. themisim-0.1.0/src/themisim/index.py +429 -0
  18. themisim-0.1.0/src/themisim/inventory.py +167 -0
  19. themisim-0.1.0/src/themisim/model.py +66 -0
  20. themisim-0.1.0/src/themisim/pipeline.py +206 -0
  21. themisim-0.1.0/src/themisim/preprocess.py +80 -0
  22. themisim-0.1.0/src/themisim/query.py +245 -0
  23. themisim-0.1.0/src/themisim/search.py +713 -0
  24. themisim-0.1.0/src/themisim/viz.py +173 -0
  25. themisim-0.1.0/src/themisim/weights.py +114 -0
  26. themisim-0.1.0/src/themisim.egg-info/PKG-INFO +196 -0
  27. themisim-0.1.0/src/themisim.egg-info/SOURCES.txt +34 -0
  28. themisim-0.1.0/src/themisim.egg-info/dependency_links.txt +1 -0
  29. themisim-0.1.0/src/themisim.egg-info/entry_points.txt +4 -0
  30. themisim-0.1.0/src/themisim.egg-info/requires.txt +20 -0
  31. themisim-0.1.0/src/themisim.egg-info/top_level.txt +1 -0
  32. themisim-0.1.0/tests/test_catalog.py +71 -0
  33. themisim-0.1.0/tests/test_embed_grouping.py +64 -0
  34. themisim-0.1.0/tests/test_export.py +61 -0
  35. themisim-0.1.0/tests/test_query.py +75 -0
  36. themisim-0.1.0/tests/test_search.py +109 -0
themisim-0.1.0/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Jeremiah Johnson
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,196 @@
1
+ Metadata-Version: 2.4
2
+ Name: themisim
3
+ Version: 0.1.0
4
+ Summary: Similarity search over THEMIS all-sky imager imagery using SimCLR encoder features and a FAISS index
5
+ Author: Jeremiah Johnson
6
+ License-Expression: MIT
7
+ Project-URL: Homepage, https://github.com/jwjohnson314/themisim
8
+ Project-URL: Documentation, https://jwjohnson314.github.io/themisim/
9
+ Project-URL: Source, https://github.com/jwjohnson314/themisim
10
+ Project-URL: Issues, https://github.com/jwjohnson314/themisim/issues
11
+ Keywords: aurora,THEMIS,all-sky-imager,similarity-search,faiss,self-supervised
12
+ Classifier: Development Status :: 4 - Beta
13
+ Classifier: Intended Audience :: Science/Research
14
+ Classifier: Programming Language :: Python :: 3
15
+ Classifier: Programming Language :: Python :: 3.11
16
+ Classifier: Programming Language :: Python :: 3.12
17
+ Classifier: Operating System :: OS Independent
18
+ Classifier: Topic :: Scientific/Engineering :: Astronomy
19
+ Classifier: Topic :: Scientific/Engineering :: Image Processing
20
+ Requires-Python: >=3.11
21
+ Description-Content-Type: text/markdown
22
+ License-File: LICENSE
23
+ Requires-Dist: torch>=2.0
24
+ Requires-Dist: torchvision>=0.15
25
+ Requires-Dist: numpy<2,>=1.24
26
+ Requires-Dist: pandas>=2.0
27
+ Requires-Dist: pyarrow>=11
28
+ Requires-Dist: Pillow>=9.4
29
+ Requires-Dist: cdflib>=1.2
30
+ Requires-Dist: faiss-cpu>=1.8
31
+ Provides-Extra: dev
32
+ Requires-Dist: pytest>=7.4; extra == "dev"
33
+ Requires-Dist: pytest-cov>=4; extra == "dev"
34
+ Provides-Extra: notebook
35
+ Requires-Dist: jupyter; extra == "notebook"
36
+ Requires-Dist: matplotlib; extra == "notebook"
37
+ Provides-Extra: docs
38
+ Requires-Dist: sphinx>=7; extra == "docs"
39
+ Requires-Dist: furo>=2024.1; extra == "docs"
40
+ Dynamic: license-file
41
+
42
+ # THEMISim
43
+
44
+ Similarity search over [THEMIS](https://themis.ssl.berkeley.edu) all-sky imager
45
+ (ASI) auroral imagery. A SimCLR-trained ResNet-18 encoder turns each 256×256
46
+ frame into a 512-D feature vector where proximity as measured by cosine similarity corresponds to visual and morphological similarity rather than pixel-level identity; ~1 billion of these are indexed with FAISS (OPQ-IVF-PQ). Given any indexed frame, the library quickly and efficiently returns the most visually similar frames across the whole archive.
47
+
48
+ This software does three things:
49
+
50
+ 1. **Download** THEMIS ASI CDFs from the Berkeley archive and encoder weights from HuggingFace.
51
+ 2. **Build** a FAISS index from the pretrained encoder weights.
52
+ 3. **Query** the index by `(site, datetime, frame)`, returning a tidy
53
+ `DataFrame`/CSV.
54
+
55
+ ## Install
56
+
57
+ ```bash
58
+ pip install themisim
59
+ ```
60
+
61
+ `faiss-cpu` is pulled in as a dependency (the query path is CPU-only). If you
62
+ already have a GPU `faiss` from conda, install with `--no-deps` to keep it.
63
+ A CUDA-enabled PyTorch makes index building much faster but is optional — every
64
+ stage falls back to CPU.
65
+
66
+ ## Quick start — querying an existing index
67
+
68
+ ```python
69
+ from themisim import query
70
+
71
+ df = query("fsmi", "2015-03-18T06", 412, artifacts="data/artifacts")
72
+ df.head()
73
+ # site datetime score source_cdf
74
+ # 0 fsmi 2015-03-18 06:20:36 1.000000 http://themis.ssl.berkeley.edu/.../thg_l1_asf_fsmi_2015031806_v01.cdf
75
+ # ...
76
+ ```
77
+
78
+ - `datetime` names the **hourly** CDF (`YYYY-MM-DDTHH`); sub-hour fields are
79
+ ignored. `2015-03-18 06`, `2015031806`, and a `datetime` object also work.
80
+ - `frame` is the 0-based frame index within that hour (THEMIS runs at a
81
+ 3-second cadence, ~1200 frames/hour).
82
+ - The top result is normally the query frame itself (`score ≈ 1.0`).
83
+
84
+ Search parameters:
85
+
86
+ | arg | default | meaning |
87
+ |-----|---------|---------|
88
+ | `results` | 24 | count mode: number of results to return |
89
+ | `min_score` | `None` | threshold mode: return *every* match scoring ≥ this cutoff (overrides `results`) |
90
+ | `prefilter` | 500 | FAISS candidates pulled before exact cosine rerank |
91
+ | `nprobe` | 64 | IVF cells inspected per query |
92
+ | `diversify_seconds` | 30 | drop near-duplicate frames within ±N s at the same site (0 disables) |
93
+
94
+ ### Bounding the result set: count vs. threshold
95
+
96
+ There are two ways to decide how many results come back:
97
+
98
+ - **Count** (default) — return the top `results` matches.
99
+ - **Threshold** — pass `min_score` (a cosine similarity in `[0, 1]`) and the
100
+ search ignores `results`, returning *every* (temporally diversified) match
101
+ scoring at or above the cutoff, best first. The result set is capped at 2000
102
+ for safety. Because the candidate pool is the top `prefilter` FAISS matches,
103
+ raise `prefilter` to surface more low-cutoff hits.
104
+
105
+ ```python
106
+ # every frame at least 0.9 cosine-similar to the query, not just the top 24
107
+ df = query("fsmi", "2015-03-18T06", 412, artifacts="data/artifacts",
108
+ min_score=0.9)
109
+ ```
110
+
111
+ ### From the command line
112
+
113
+ ```bash
114
+ themis-query --site fsmi --datetime 2015-03-18T06 --frame 412 \
115
+ --artifacts data/artifacts --output results.csv
116
+
117
+ # threshold mode: every match scoring >= 0.9, instead of a fixed --results count
118
+ themis-query --site fsmi --datetime 2015-03-18T06 --frame 412 \
119
+ --artifacts data/artifacts --min-score 0.9 --output results.csv
120
+ ```
121
+
122
+ Output columns are `site, datetime, score, source_cdf` — identical to the
123
+ dashboard's CSV export.
124
+
125
+ ## Build an index from scratch
126
+
127
+ Note that the full THEMIS ASI archive is ~1M CDFs (over 100 TB) and building the index takes on the order of GPU-days; the
128
+ prebuilt index (about 72 GB) is **not** currently downloadable. If you are interested in obtaining it please email me to discuss.
129
+
130
+
131
+ ```bash
132
+ # 1. fetch the encoder weights (44 MB)
133
+ python -c "from themisim import fetch_weights; print(fetch_weights())"
134
+
135
+ # 2. one-shot pipeline (download + build)
136
+ SITES=fsmi START=2015-03 END=2015-03 ./scripts/run_pipeline.sh
137
+ ```
138
+
139
+ or step by step:
140
+
141
+ ```bash
142
+ themis-download --data-root data/cdf --sites fsmi --start 2015-03 --end 2015-03
143
+ themis-build-index --data-root data/cdf --artifacts data/artifacts \
144
+ --checkpoint weights/aurora-fm-no-finetune.tar
145
+ ```
146
+
147
+ The equivalent Python API:
148
+
149
+ ```python
150
+ from themisim import download_archive, build_index
151
+
152
+ download_archive("data/cdf", sites=["fsmi"], start="2015-03", end="2015-03")
153
+ build_index("data/cdf", "data/artifacts",
154
+ "weights/aurora-fm-no-finetune.tar")
155
+ ```
156
+
157
+ `build_index` runs inventory → embed → concat → train/build, resuming cleanly
158
+ if interrupted (already-embedded hours are skipped). `--nlist auto` scales the
159
+ IVF cell count to the dataset size.
160
+
161
+ ## Model weights
162
+
163
+ `fetch_weights()` downloads and SHA-256-verifies the ~44 MB SimCLR checkpoint
164
+ into `./weights` (override with `$THEMIS_ASI_WEIGHTS`). It is pulled from the
165
+ public Hugging Face repo
166
+ [`Jwjohnson314/Aurora-FM`](https://huggingface.co/Jwjohnson314/Aurora-FM); override
167
+ the URL via `$THEMIS_ASI_WEIGHTS_URL` or pass `url=`. If you already have the
168
+ `.tar`, drop it in the weights directory and it will be verified and reused
169
+ without a network call.
170
+
171
+ ## Paths / configuration
172
+
173
+ Resolved from explicit arguments, then environment variables, then defaults:
174
+
175
+ | what | env var | default |
176
+ |------|---------|---------|
177
+ | downloaded CDFs | `THEMIS_ASI_DATA_ROOT` | `./data/cdf` |
178
+ | index artifacts | `THEMIS_ASI_ARTIFACTS` | `./data/artifacts` |
179
+ | model weights | `THEMIS_ASI_WEIGHTS` | `./weights` |
180
+
181
+ An artifacts directory contains `index.faiss`, `manifest.parquet`,
182
+ `vectors.f16.dat`, and `vectors.meta.json`.
183
+
184
+ ## License, data & citation
185
+
186
+ The **code** in this repository is MIT-licensed — see [LICENSE](LICENSE).
187
+
188
+ The assets this tool downloads carry their own terms, which you must honor when
189
+ publishing results:
190
+
191
+ - **Model weights** (`Jwjohnson314/Aurora-FM`) are released under
192
+ **CC-BY-4.0** — attribution required.
193
+ - **THEMIS ASI data** is provided by the THEMIS mission (UC Berkeley / NASA) and
194
+ is subject to the
195
+ [THEMIS data use & citation policy](https://themis.ssl.berkeley.edu/roadrules.shtml).
196
+ Acknowledge the mission and instrument teams in any publication.
@@ -0,0 +1,155 @@
1
+ # THEMISim
2
+
3
+ Similarity search over [THEMIS](https://themis.ssl.berkeley.edu) all-sky imager
4
+ (ASI) auroral imagery. A SimCLR-trained ResNet-18 encoder turns each 256×256
5
+ frame into a 512-D feature vector where proximity as measured by cosine similarity corresponds to visual and morphological similarity rather than pixel-level identity; ~1 billion of these are indexed with FAISS (OPQ-IVF-PQ). Given any indexed frame, the library quickly and efficiently returns the most visually similar frames across the whole archive.
6
+
7
+ This software does three things:
8
+
9
+ 1. **Download** THEMIS ASI CDFs from the Berkeley archive and encoder weights from HuggingFace.
10
+ 2. **Build** a FAISS index from the pretrained encoder weights.
11
+ 3. **Query** the index by `(site, datetime, frame)`, returning a tidy
12
+ `DataFrame`/CSV.
13
+
14
+ ## Install
15
+
16
+ ```bash
17
+ pip install themisim
18
+ ```
19
+
20
+ `faiss-cpu` is pulled in as a dependency (the query path is CPU-only). If you
21
+ already have a GPU `faiss` from conda, install with `--no-deps` to keep it.
22
+ A CUDA-enabled PyTorch makes index building much faster but is optional — every
23
+ stage falls back to CPU.
24
+
25
+ ## Quick start — querying an existing index
26
+
27
+ ```python
28
+ from themisim import query
29
+
30
+ df = query("fsmi", "2015-03-18T06", 412, artifacts="data/artifacts")
31
+ df.head()
32
+ # site datetime score source_cdf
33
+ # 0 fsmi 2015-03-18 06:20:36 1.000000 http://themis.ssl.berkeley.edu/.../thg_l1_asf_fsmi_2015031806_v01.cdf
34
+ # ...
35
+ ```
36
+
37
+ - `datetime` names the **hourly** CDF (`YYYY-MM-DDTHH`); sub-hour fields are
38
+ ignored. `2015-03-18 06`, `2015031806`, and a `datetime` object also work.
39
+ - `frame` is the 0-based frame index within that hour (THEMIS runs at a
40
+ 3-second cadence, ~1200 frames/hour).
41
+ - The top result is normally the query frame itself (`score ≈ 1.0`).
42
+
43
+ Search parameters:
44
+
45
+ | arg | default | meaning |
46
+ |-----|---------|---------|
47
+ | `results` | 24 | count mode: number of results to return |
48
+ | `min_score` | `None` | threshold mode: return *every* match scoring ≥ this cutoff (overrides `results`) |
49
+ | `prefilter` | 500 | FAISS candidates pulled before exact cosine rerank |
50
+ | `nprobe` | 64 | IVF cells inspected per query |
51
+ | `diversify_seconds` | 30 | drop near-duplicate frames within ±N s at the same site (0 disables) |
52
+
53
+ ### Bounding the result set: count vs. threshold
54
+
55
+ There are two ways to decide how many results come back:
56
+
57
+ - **Count** (default) — return the top `results` matches.
58
+ - **Threshold** — pass `min_score` (a cosine similarity in `[0, 1]`) and the
59
+ search ignores `results`, returning *every* (temporally diversified) match
60
+ scoring at or above the cutoff, best first. The result set is capped at 2000
61
+ for safety. Because the candidate pool is the top `prefilter` FAISS matches,
62
+ raise `prefilter` to surface more low-cutoff hits.
63
+
64
+ ```python
65
+ # every frame at least 0.9 cosine-similar to the query, not just the top 24
66
+ df = query("fsmi", "2015-03-18T06", 412, artifacts="data/artifacts",
67
+ min_score=0.9)
68
+ ```
69
+
70
+ ### From the command line
71
+
72
+ ```bash
73
+ themis-query --site fsmi --datetime 2015-03-18T06 --frame 412 \
74
+ --artifacts data/artifacts --output results.csv
75
+
76
+ # threshold mode: every match scoring >= 0.9, instead of a fixed --results count
77
+ themis-query --site fsmi --datetime 2015-03-18T06 --frame 412 \
78
+ --artifacts data/artifacts --min-score 0.9 --output results.csv
79
+ ```
80
+
81
+ Output columns are `site, datetime, score, source_cdf` — identical to the
82
+ dashboard's CSV export.
83
+
84
+ ## Build an index from scratch
85
+
86
+ Note that the full THEMIS ASI archive is ~1M CDFs (over 100 TB) and building the index takes on the order of GPU-days; the
87
+ prebuilt index (about 72 GB) is **not** currently downloadable. If you are interested in obtaining it please email me to discuss.
88
+
89
+
90
+ ```bash
91
+ # 1. fetch the encoder weights (44 MB)
92
+ python -c "from themisim import fetch_weights; print(fetch_weights())"
93
+
94
+ # 2. one-shot pipeline (download + build)
95
+ SITES=fsmi START=2015-03 END=2015-03 ./scripts/run_pipeline.sh
96
+ ```
97
+
98
+ or step by step:
99
+
100
+ ```bash
101
+ themis-download --data-root data/cdf --sites fsmi --start 2015-03 --end 2015-03
102
+ themis-build-index --data-root data/cdf --artifacts data/artifacts \
103
+ --checkpoint weights/aurora-fm-no-finetune.tar
104
+ ```
105
+
106
+ The equivalent Python API:
107
+
108
+ ```python
109
+ from themisim import download_archive, build_index
110
+
111
+ download_archive("data/cdf", sites=["fsmi"], start="2015-03", end="2015-03")
112
+ build_index("data/cdf", "data/artifacts",
113
+ "weights/aurora-fm-no-finetune.tar")
114
+ ```
115
+
116
+ `build_index` runs inventory → embed → concat → train/build, resuming cleanly
117
+ if interrupted (already-embedded hours are skipped). `--nlist auto` scales the
118
+ IVF cell count to the dataset size.
119
+
120
+ ## Model weights
121
+
122
+ `fetch_weights()` downloads and SHA-256-verifies the ~44 MB SimCLR checkpoint
123
+ into `./weights` (override with `$THEMIS_ASI_WEIGHTS`). It is pulled from the
124
+ public Hugging Face repo
125
+ [`Jwjohnson314/Aurora-FM`](https://huggingface.co/Jwjohnson314/Aurora-FM); override
126
+ the URL via `$THEMIS_ASI_WEIGHTS_URL` or pass `url=`. If you already have the
127
+ `.tar`, drop it in the weights directory and it will be verified and reused
128
+ without a network call.
129
+
130
+ ## Paths / configuration
131
+
132
+ Resolved from explicit arguments, then environment variables, then defaults:
133
+
134
+ | what | env var | default |
135
+ |------|---------|---------|
136
+ | downloaded CDFs | `THEMIS_ASI_DATA_ROOT` | `./data/cdf` |
137
+ | index artifacts | `THEMIS_ASI_ARTIFACTS` | `./data/artifacts` |
138
+ | model weights | `THEMIS_ASI_WEIGHTS` | `./weights` |
139
+
140
+ An artifacts directory contains `index.faiss`, `manifest.parquet`,
141
+ `vectors.f16.dat`, and `vectors.meta.json`.
142
+
143
+ ## License, data & citation
144
+
145
+ The **code** in this repository is MIT-licensed — see [LICENSE](LICENSE).
146
+
147
+ The assets this tool downloads carry their own terms, which you must honor when
148
+ publishing results:
149
+
150
+ - **Model weights** (`Jwjohnson314/Aurora-FM`) are released under
151
+ **CC-BY-4.0** — attribution required.
152
+ - **THEMIS ASI data** is provided by the THEMIS mission (UC Berkeley / NASA) and
153
+ is subject to the
154
+ [THEMIS data use & citation policy](https://themis.ssl.berkeley.edu/roadrules.shtml).
155
+ Acknowledge the mission and instrument teams in any publication.
@@ -0,0 +1,62 @@
1
+ [build-system]
2
+ requires = ["setuptools>=77", "wheel"]
3
+ build-backend = "setuptools.build_meta"
4
+
5
+ [project]
6
+ name = "themisim"
7
+ version = "0.1.0"
8
+ description = "Similarity search over THEMIS all-sky imager imagery using SimCLR encoder features and a FAISS index"
9
+ readme = "README.md"
10
+ requires-python = ">=3.11"
11
+ license = "MIT"
12
+ license-files = ["LICENSE"]
13
+ authors = [{ name = "Jeremiah Johnson" }]
14
+ keywords = ["aurora", "THEMIS", "all-sky-imager", "similarity-search", "faiss", "self-supervised"]
15
+ classifiers = [
16
+ "Development Status :: 4 - Beta",
17
+ "Intended Audience :: Science/Research",
18
+ "Programming Language :: Python :: 3",
19
+ "Programming Language :: Python :: 3.11",
20
+ "Programming Language :: Python :: 3.12",
21
+ "Operating System :: OS Independent",
22
+ "Topic :: Scientific/Engineering :: Astronomy",
23
+ "Topic :: Scientific/Engineering :: Image Processing",
24
+ ]
25
+ dependencies = [
26
+ "torch>=2.0",
27
+ "torchvision>=0.15",
28
+ "numpy>=1.24,<2",
29
+ "pandas>=2.0",
30
+ "pyarrow>=11",
31
+ "Pillow>=9.4",
32
+ "cdflib>=1.2",
33
+ # CPU FAISS is sufficient: the query path is CPU-only (the index is
34
+ # memory-mapped and disk-paged). GPU users who already have a conda
35
+ # faiss build can install with --no-deps to keep it.
36
+ "faiss-cpu>=1.8",
37
+ ]
38
+
39
+ [project.optional-dependencies]
40
+ dev = ["pytest>=7.4", "pytest-cov>=4"]
41
+ notebook = ["jupyter", "matplotlib"]
42
+ docs = ["sphinx>=7", "furo>=2024.1"]
43
+
44
+ [project.scripts]
45
+ themis-download = "themisim.cli.download:main"
46
+ themis-build-index = "themisim.cli.build_index:main"
47
+ themis-query = "themisim.cli.query:main"
48
+
49
+ [project.urls]
50
+ Homepage = "https://github.com/jwjohnson314/themisim"
51
+ Documentation = "https://jwjohnson314.github.io/themisim/"
52
+ Source = "https://github.com/jwjohnson314/themisim"
53
+ Issues = "https://github.com/jwjohnson314/themisim/issues"
54
+
55
+ [tool.setuptools.packages.find]
56
+ where = ["src"]
57
+
58
+ [tool.pytest.ini_options]
59
+ testpaths = ["tests"]
60
+ python_files = ["test_*.py"]
61
+ addopts = "-ra"
62
+ pythonpath = ["src"]
@@ -0,0 +1,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+
@@ -0,0 +1,73 @@
1
+ """THEMIS all-sky imager similarity search.
2
+
3
+ A standalone, pip-installable extraction of the THEMIS similarity-search
4
+ engine: download the archive, build a FAISS index from the pretrained SimCLR
5
+ encoder, and query it by ``(site, datetime, frame)``.
6
+
7
+ Quick start (query an existing index)::
8
+
9
+ from themisim import query
10
+ df = query("fsmi", "2015-03-18T06", 412, artifacts="data/artifacts")
11
+
12
+ Build an index from scratch::
13
+
14
+ from themisim import download_archive, build_index
15
+ download_archive("data/cdf", sites=["fsmi"], start="2015-03", end="2015-03")
16
+ build_index("data/cdf", "data/artifacts", "weights/<checkpoint>.tar")
17
+ """
18
+ from __future__ import annotations
19
+
20
+ # Establish the torch-before-faiss import order before anything pulls in faiss
21
+ # (the query stack imports faiss). torch and faiss ship conflicting CUDA libs
22
+ # and break each other's loader if faiss is imported first; importing torch
23
+ # here (when present) is a no-op safety net. Absent torch (query-only installs)
24
+ # this is simply skipped and faiss loads alone, which is fine.
25
+ try: # pragma: no cover - environment dependent
26
+ import torch as _torch # noqa: F401
27
+ except Exception: # pragma: no cover
28
+ pass
29
+
30
+ from themisim.export import ( # noqa: E402
31
+ hits_to_dataframe,
32
+ results_csv_filename,
33
+ )
34
+ from themisim.query import query, resolve_global_id # noqa: E402
35
+ from themisim.search import Hit, SearchEngine # noqa: E402
36
+
37
+ __version__ = "0.1.0"
38
+
39
+ __all__ = [
40
+ "query",
41
+ "resolve_global_id",
42
+ "SearchEngine",
43
+ "Hit",
44
+ "hits_to_dataframe",
45
+ "results_csv_filename",
46
+ "download_archive",
47
+ "build_index",
48
+ "fetch_weights",
49
+ "visualize_results",
50
+ "__version__",
51
+ ]
52
+
53
+
54
+ def __getattr__(name: str):
55
+ """Lazily expose the build pipeline + weights helper.
56
+
57
+ Kept out of the eager import path so ``import themisim`` stays
58
+ cheap (and torch-free) for query-only use; ``build_index`` /
59
+ ``download_archive`` pull in the embed/index stack only when first used.
60
+ """
61
+ if name in ("build_index", "download_archive"):
62
+ from themisim import pipeline
63
+
64
+ return getattr(pipeline, name)
65
+ if name == "fetch_weights":
66
+ from themisim.weights import fetch_weights
67
+
68
+ return fetch_weights
69
+ if name == "visualize_results":
70
+ from themisim.viz import visualize_results
71
+
72
+ return visualize_results
73
+ raise AttributeError(f"module {__name__!r} has no attribute {name!r}")