roman-snpit-snappl 0.20.0__tar.gz → 0.21.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.
Potentially problematic release.
This version of roman-snpit-snappl might be problematic. Click here for more details.
- {roman_snpit_snappl-0.20.0/roman_snpit_snappl.egg-info → roman_snpit_snappl-0.21.0}/PKG-INFO +1 -1
- roman_snpit_snappl-0.21.0/changes/98.docs.rst +1 -0
- roman_snpit_snappl-0.21.0/changes/99.feature.rst +1 -0
- {roman_snpit_snappl-0.20.0 → roman_snpit_snappl-0.21.0}/docs/usage.rst +53 -4
- {roman_snpit_snappl-0.20.0 → roman_snpit_snappl-0.21.0/roman_snpit_snappl.egg-info}/PKG-INFO +1 -1
- {roman_snpit_snappl-0.20.0 → roman_snpit_snappl-0.21.0}/roman_snpit_snappl.egg-info/SOURCES.txt +4 -0
- {roman_snpit_snappl-0.20.0 → roman_snpit_snappl-0.21.0}/snappl/_version.py +3 -3
- roman_snpit_snappl-0.21.0/snappl/db/baseview.py +266 -0
- {roman_snpit_snappl-0.20.0 → roman_snpit_snappl-0.21.0}/snappl/db/db.py +11 -1
- roman_snpit_snappl-0.21.0/snappl/db/migrations/20251028_segmap.sql +45 -0
- {roman_snpit_snappl-0.20.0 → roman_snpit_snappl-0.21.0}/snappl/db/webserver.py +114 -58
- {roman_snpit_snappl-0.20.0 → roman_snpit_snappl-0.21.0}/snappl/diaobject.py +14 -0
- roman_snpit_snappl-0.21.0/snappl/segmap.py +184 -0
- roman_snpit_snappl-0.20.0/snappl/db/baseview.py +0 -88
- {roman_snpit_snappl-0.20.0 → roman_snpit_snappl-0.21.0}/.cruft.json +0 -0
- {roman_snpit_snappl-0.20.0 → roman_snpit_snappl-0.21.0}/.github/CODEOWNERS +0 -0
- {roman_snpit_snappl-0.20.0 → roman_snpit_snappl-0.21.0}/.github/ISSUE_TEMPLATE/FEATURE_REQUEST.md +0 -0
- {roman_snpit_snappl-0.20.0 → roman_snpit_snappl-0.21.0}/.github/ISSUE_TEMPLATE/ISSUE_TEMPLATE.md +0 -0
- {roman_snpit_snappl-0.20.0 → roman_snpit_snappl-0.21.0}/.github/ISSUE_TEMPLATE/PR_TEMPLATE.md +0 -0
- {roman_snpit_snappl-0.20.0 → roman_snpit_snappl-0.21.0}/.github/dependabot.yml +0 -0
- {roman_snpit_snappl-0.20.0 → roman_snpit_snappl-0.21.0}/.github/labeler.yml +0 -0
- {roman_snpit_snappl-0.20.0 → roman_snpit_snappl-0.21.0}/.github/workflows/changelog.yml +0 -0
- {roman_snpit_snappl-0.20.0 → roman_snpit_snappl-0.21.0}/.github/workflows/run_labeler.yml +0 -0
- {roman_snpit_snappl-0.20.0 → roman_snpit_snappl-0.21.0}/.github/workflows/run_snappl_tests.yml +0 -0
- {roman_snpit_snappl-0.20.0 → roman_snpit_snappl-0.21.0}/.github/workflows/sphinx-deploy.yml +0 -0
- {roman_snpit_snappl-0.20.0 → roman_snpit_snappl-0.21.0}/.github/workflows/sub_package_update.yml +0 -0
- {roman_snpit_snappl-0.20.0 → roman_snpit_snappl-0.21.0}/.gitignore +0 -0
- {roman_snpit_snappl-0.20.0 → roman_snpit_snappl-0.21.0}/.pre-commit-config.yaml +0 -0
- {roman_snpit_snappl-0.20.0 → roman_snpit_snappl-0.21.0}/CHANGES.rst +0 -0
- {roman_snpit_snappl-0.20.0 → roman_snpit_snappl-0.21.0}/CITATION.cff +0 -0
- {roman_snpit_snappl-0.20.0 → roman_snpit_snappl-0.21.0}/CODE_OF_CONDUCT.md +0 -0
- {roman_snpit_snappl-0.20.0 → roman_snpit_snappl-0.21.0}/CONTRIBUTING.md +0 -0
- {roman_snpit_snappl-0.20.0 → roman_snpit_snappl-0.21.0}/LICENSE +0 -0
- {roman_snpit_snappl-0.20.0 → roman_snpit_snappl-0.21.0}/MANIFEST.in +0 -0
- {roman_snpit_snappl-0.20.0 → roman_snpit_snappl-0.21.0}/README.rst +0 -0
- {roman_snpit_snappl-0.20.0 → roman_snpit_snappl-0.21.0}/changes/.gitkeep +0 -0
- {roman_snpit_snappl-0.20.0 → roman_snpit_snappl-0.21.0}/changes/10.snappl.rst +0 -0
- {roman_snpit_snappl-0.20.0 → roman_snpit_snappl-0.21.0}/changes/13.bugfix.rst +0 -0
- {roman_snpit_snappl-0.20.0 → roman_snpit_snappl-0.21.0}/changes/14.snappl.rst +0 -0
- {roman_snpit_snappl-0.20.0 → roman_snpit_snappl-0.21.0}/changes/15.feature.rst +0 -0
- {roman_snpit_snappl-0.20.0 → roman_snpit_snappl-0.21.0}/changes/16.feature.rst +0 -0
- {roman_snpit_snappl-0.20.0 → roman_snpit_snappl-0.21.0}/changes/18.feature.rst +0 -0
- {roman_snpit_snappl-0.20.0 → roman_snpit_snappl-0.21.0}/changes/20.bugfix.rst +0 -0
- {roman_snpit_snappl-0.20.0 → roman_snpit_snappl-0.21.0}/changes/23.snappl.rst +0 -0
- {roman_snpit_snappl-0.20.0 → roman_snpit_snappl-0.21.0}/changes/26.feature.rst +0 -0
- {roman_snpit_snappl-0.20.0 → roman_snpit_snappl-0.21.0}/changes/29.feature.rst +0 -0
- {roman_snpit_snappl-0.20.0 → roman_snpit_snappl-0.21.0}/changes/3.snappl.rst +0 -0
- {roman_snpit_snappl-0.20.0 → roman_snpit_snappl-0.21.0}/changes/31.feature.rst +0 -0
- {roman_snpit_snappl-0.20.0 → roman_snpit_snappl-0.21.0}/changes/35.snappl.rst +0 -0
- {roman_snpit_snappl-0.20.0 → roman_snpit_snappl-0.21.0}/changes/36.snappl.rst +0 -0
- {roman_snpit_snappl-0.20.0 → roman_snpit_snappl-0.21.0}/changes/37.snappl.rst +0 -0
- {roman_snpit_snappl-0.20.0 → roman_snpit_snappl-0.21.0}/changes/40.snappl.rst +0 -0
- {roman_snpit_snappl-0.20.0 → roman_snpit_snappl-0.21.0}/changes/41.snappl.rst +0 -0
- {roman_snpit_snappl-0.20.0 → roman_snpit_snappl-0.21.0}/changes/43.snappl.rst +0 -0
- {roman_snpit_snappl-0.20.0 → roman_snpit_snappl-0.21.0}/changes/47.feature.rst +0 -0
- {roman_snpit_snappl-0.20.0 → roman_snpit_snappl-0.21.0}/changes/49.docs.rst +0 -0
- {roman_snpit_snappl-0.20.0 → roman_snpit_snappl-0.21.0}/changes/5.snappl.rst +0 -0
- {roman_snpit_snappl-0.20.0 → roman_snpit_snappl-0.21.0}/changes/54.snappl.rst +0 -0
- {roman_snpit_snappl-0.20.0 → roman_snpit_snappl-0.21.0}/changes/57.snappl.rst +0 -0
- {roman_snpit_snappl-0.20.0 → roman_snpit_snappl-0.21.0}/changes/58.snappl.rst +0 -0
- {roman_snpit_snappl-0.20.0 → roman_snpit_snappl-0.21.0}/changes/61.bugfix.rst +0 -0
- {roman_snpit_snappl-0.20.0 → roman_snpit_snappl-0.21.0}/changes/62.snappl.rst +0 -0
- {roman_snpit_snappl-0.20.0 → roman_snpit_snappl-0.21.0}/changes/63.snappl.rst +0 -0
- {roman_snpit_snappl-0.20.0 → roman_snpit_snappl-0.21.0}/changes/65.bugfix.rst +0 -0
- {roman_snpit_snappl-0.20.0 → roman_snpit_snappl-0.21.0}/changes/68.feature.rst +0 -0
- {roman_snpit_snappl-0.20.0 → roman_snpit_snappl-0.21.0}/changes/72.snappl.rst +0 -0
- {roman_snpit_snappl-0.20.0 → roman_snpit_snappl-0.21.0}/changes/73.feature.rst +0 -0
- {roman_snpit_snappl-0.20.0 → roman_snpit_snappl-0.21.0}/changes/74.bugfix.rst +0 -0
- {roman_snpit_snappl-0.20.0 → roman_snpit_snappl-0.21.0}/changes/79.snappl.rst +0 -0
- {roman_snpit_snappl-0.20.0 → roman_snpit_snappl-0.21.0}/changes/8.snappl.rst +0 -0
- {roman_snpit_snappl-0.20.0 → roman_snpit_snappl-0.21.0}/changes/81.snappl.rst +0 -0
- {roman_snpit_snappl-0.20.0 → roman_snpit_snappl-0.21.0}/changes/82.snappl.rst +0 -0
- {roman_snpit_snappl-0.20.0 → roman_snpit_snappl-0.21.0}/changes/83.snappl.rst +0 -0
- {roman_snpit_snappl-0.20.0 → roman_snpit_snappl-0.21.0}/changes/84.feature.rst +0 -0
- {roman_snpit_snappl-0.20.0 → roman_snpit_snappl-0.21.0}/changes/85.feature.rst +0 -0
- {roman_snpit_snappl-0.20.0 → roman_snpit_snappl-0.21.0}/changes/86.snappl.rst +0 -0
- {roman_snpit_snappl-0.20.0 → roman_snpit_snappl-0.21.0}/changes/87.docs.rst +0 -0
- {roman_snpit_snappl-0.20.0 → roman_snpit_snappl-0.21.0}/changes/89.feature.rst +0 -0
- {roman_snpit_snappl-0.20.0 → roman_snpit_snappl-0.21.0}/changes/9.snappl.rst +0 -0
- {roman_snpit_snappl-0.20.0 → roman_snpit_snappl-0.21.0}/changes/91.feature.rst +0 -0
- {roman_snpit_snappl-0.20.0 → roman_snpit_snappl-0.21.0}/changes/92.docs.rst +0 -0
- {roman_snpit_snappl-0.20.0 → roman_snpit_snappl-0.21.0}/changes/94.snappl.rst +0 -0
- {roman_snpit_snappl-0.20.0 → roman_snpit_snappl-0.21.0}/codespell-ignore.txt +0 -0
- {roman_snpit_snappl-0.20.0 → roman_snpit_snappl-0.21.0}/docker/postgres/Dockerfile +0 -0
- {roman_snpit_snappl-0.20.0 → roman_snpit_snappl-0.21.0}/docker/postgres/postgresql.conf +0 -0
- {roman_snpit_snappl-0.20.0 → roman_snpit_snappl-0.21.0}/docker/postgres/run_postgres.sh +0 -0
- {roman_snpit_snappl-0.20.0 → roman_snpit_snappl-0.21.0}/docker/webserver/Dockerfile +0 -0
- {roman_snpit_snappl-0.20.0 → roman_snpit_snappl-0.21.0}/docker/webserver/cert.pem +0 -0
- {roman_snpit_snappl-0.20.0 → roman_snpit_snappl-0.21.0}/docker/webserver/config-test.yaml +0 -0
- {roman_snpit_snappl-0.20.0 → roman_snpit_snappl-0.21.0}/docker/webserver/key.pem +0 -0
- {roman_snpit_snappl-0.20.0 → roman_snpit_snappl-0.21.0}/docker/webserver/roman-snpit-server.py +0 -0
- {roman_snpit_snappl-0.20.0 → roman_snpit_snappl-0.21.0}/docs/Makefile +0 -0
- {roman_snpit_snappl-0.20.0 → roman_snpit_snappl-0.21.0}/docs/_static/logo_black_filled.png +0 -0
- {roman_snpit_snappl-0.20.0 → roman_snpit_snappl-0.21.0}/docs/api.rst +0 -0
- {roman_snpit_snappl-0.20.0 → roman_snpit_snappl-0.21.0}/docs/changes.rst +0 -0
- {roman_snpit_snappl-0.20.0 → roman_snpit_snappl-0.21.0}/docs/conf.py +0 -0
- {roman_snpit_snappl-0.20.0 → roman_snpit_snappl-0.21.0}/docs/database_schema.rst +0 -0
- {roman_snpit_snappl-0.20.0 → roman_snpit_snappl-0.21.0}/docs/index.rst +0 -0
- {roman_snpit_snappl-0.20.0 → roman_snpit_snappl-0.21.0}/docs/installation.rst +0 -0
- {roman_snpit_snappl-0.20.0 → roman_snpit_snappl-0.21.0}/docs/make.bat +0 -0
- {roman_snpit_snappl-0.20.0 → roman_snpit_snappl-0.21.0}/experimentation/README.md +0 -0
- {roman_snpit_snappl-0.20.0 → roman_snpit_snappl-0.21.0}/experimentation/ap_phot_simulated_images.py +0 -0
- {roman_snpit_snappl-0.20.0 → roman_snpit_snappl-0.21.0}/experimentation/play_with_photutils.py +0 -0
- {roman_snpit_snappl-0.20.0 → roman_snpit_snappl-0.21.0}/licenses/.DS_Store +0 -0
- {roman_snpit_snappl-0.20.0 → roman_snpit_snappl-0.21.0}/licenses/LICENSE.rst +0 -0
- {roman_snpit_snappl-0.20.0 → roman_snpit_snappl-0.21.0}/licenses/README.rst +0 -0
- {roman_snpit_snappl-0.20.0 → roman_snpit_snappl-0.21.0}/licenses/TEMPLATE_LICENSE.rst +0 -0
- {roman_snpit_snappl-0.20.0 → roman_snpit_snappl-0.21.0}/pyproject.toml +0 -0
- {roman_snpit_snappl-0.20.0 → roman_snpit_snappl-0.21.0}/roman_snpit_snappl.egg-info/dependency_links.txt +0 -0
- {roman_snpit_snappl-0.20.0 → roman_snpit_snappl-0.21.0}/roman_snpit_snappl.egg-info/not-zip-safe +0 -0
- {roman_snpit_snappl-0.20.0 → roman_snpit_snappl-0.21.0}/roman_snpit_snappl.egg-info/requires.txt +0 -0
- {roman_snpit_snappl-0.20.0 → roman_snpit_snappl-0.21.0}/roman_snpit_snappl.egg-info/top_level.txt +0 -0
- {roman_snpit_snappl-0.20.0 → roman_snpit_snappl-0.21.0}/setup.cfg +0 -0
- {roman_snpit_snappl-0.20.0 → roman_snpit_snappl-0.21.0}/setup.py +0 -0
- {roman_snpit_snappl-0.20.0 → roman_snpit_snappl-0.21.0}/snappl/__init__.py +0 -0
- {roman_snpit_snappl-0.20.0 → roman_snpit_snappl-0.21.0}/snappl/_dev/__init__.py +0 -0
- {roman_snpit_snappl-0.20.0 → roman_snpit_snappl-0.21.0}/snappl/_dev/scm_version.py +0 -0
- {roman_snpit_snappl-0.20.0 → roman_snpit_snappl-0.21.0}/snappl/admin/load_ou2024_l2images.py +0 -0
- {roman_snpit_snappl-0.20.0 → roman_snpit_snappl-0.21.0}/snappl/admin/load_snana_ou2024_diaobject.py +0 -0
- {roman_snpit_snappl-0.20.0 → roman_snpit_snappl-0.21.0}/snappl/config.py +0 -0
- {roman_snpit_snappl-0.20.0 → roman_snpit_snappl-0.21.0}/snappl/data/README.rst +0 -0
- {roman_snpit_snappl-0.20.0 → roman_snpit_snappl-0.21.0}/snappl/db/migrations/20251008_init.sql +0 -0
- {roman_snpit_snappl-0.20.0 → roman_snpit_snappl-0.21.0}/snappl/db/migrations/20251017_objdetcount.sql +0 -0
- {roman_snpit_snappl-0.20.0 → roman_snpit_snappl-0.21.0}/snappl/db/migrations/20251024_l2image_mjd.sql +0 -0
- {roman_snpit_snappl-0.20.0 → roman_snpit_snappl-0.21.0}/snappl/db/migrations/20251025_lightcurve.sql +0 -0
- {roman_snpit_snappl-0.20.0 → roman_snpit_snappl-0.21.0}/snappl/db/migrations/apply_migrations.py +0 -0
- {roman_snpit_snappl-0.20.0 → roman_snpit_snappl-0.21.0}/snappl/db/migrations/schema_to_rst.py +0 -0
- {roman_snpit_snappl-0.20.0 → roman_snpit_snappl-0.21.0}/snappl/db/migrations/scorched_earth.py +0 -0
- {roman_snpit_snappl-0.20.0 → roman_snpit_snappl-0.21.0}/snappl/db/migrations/wipe_all_data.py +0 -0
- {roman_snpit_snappl-0.20.0 → roman_snpit_snappl-0.21.0}/snappl/db/static/romansnpit.css +0 -0
- {roman_snpit_snappl-0.20.0 → roman_snpit_snappl-0.21.0}/snappl/db/static/romansnpit.js +0 -0
- {roman_snpit_snappl-0.20.0 → roman_snpit_snappl-0.21.0}/snappl/db/static/romansnpit_start.js +0 -0
- {roman_snpit_snappl-0.20.0 → roman_snpit_snappl-0.21.0}/snappl/db/templates/base.html +0 -0
- {roman_snpit_snappl-0.20.0 → roman_snpit_snappl-0.21.0}/snappl/db/templates/romansnpitdb.html +0 -0
- {roman_snpit_snappl-0.20.0 → roman_snpit_snappl-0.21.0}/snappl/dbclient.py +0 -0
- {roman_snpit_snappl-0.20.0 → roman_snpit_snappl-0.21.0}/snappl/http.py +0 -0
- {roman_snpit_snappl-0.20.0 → roman_snpit_snappl-0.21.0}/snappl/image.py +0 -0
- {roman_snpit_snappl-0.20.0 → roman_snpit_snappl-0.21.0}/snappl/image_simulator.py +0 -0
- {roman_snpit_snappl-0.20.0 → roman_snpit_snappl-0.21.0}/snappl/imagecollection.py +0 -0
- {roman_snpit_snappl-0.20.0 → roman_snpit_snappl-0.21.0}/snappl/lightcurve.py +0 -0
- {roman_snpit_snappl-0.20.0 → roman_snpit_snappl-0.21.0}/snappl/logger.py +0 -0
- {roman_snpit_snappl-0.20.0 → roman_snpit_snappl-0.21.0}/snappl/provenance.py +0 -0
- {roman_snpit_snappl-0.20.0 → roman_snpit_snappl-0.21.0}/snappl/psf.py +0 -0
- {roman_snpit_snappl-0.20.0 → roman_snpit_snappl-0.21.0}/snappl/sed.py +0 -0
- {roman_snpit_snappl-0.20.0 → roman_snpit_snappl-0.21.0}/snappl/utils.py +0 -0
- {roman_snpit_snappl-0.20.0 → roman_snpit_snappl-0.21.0}/snappl/wcs.py +0 -0
- {roman_snpit_snappl-0.20.0 → roman_snpit_snappl-0.21.0}/tox.ini +0 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
Add lightcurve reading and writing to the nov 2025 primer in the usage docs
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
Add storage and database tracking of segmentation maps
|
|
@@ -145,6 +145,14 @@ However, we recommend against that. While 4500 is perhaps not an overwhelming n
|
|
|
145
145
|
Finding Objects
|
|
146
146
|
===============
|
|
147
147
|
|
|
148
|
+
You may just be given an diaobject id. In that case, all you have to do is::
|
|
149
|
+
|
|
150
|
+
from snappl.diaobject import DiaObject
|
|
151
|
+
|
|
152
|
+
obj = DiaObject.get_object( diaobject_id=<id> )
|
|
153
|
+
|
|
154
|
+
where ``<id>`` is the diaobject id you were given. ``obj`` will be a ``DiaObject`` object.
|
|
155
|
+
|
|
148
156
|
There is also an interface that lets you find objects. For instance, if you want to find all objects within 100 arcseconds of a given location, you could run::
|
|
149
157
|
|
|
150
158
|
from snappl.diaobject import DiaObject
|
|
@@ -158,7 +166,7 @@ Here, you can use ``ou2024`` for ``TAG`` and ``load_ou2024_diaobject`` for ``PRO
|
|
|
158
166
|
Getting Better Object Positions
|
|
159
167
|
===============================
|
|
160
168
|
|
|
161
|
-
``DiaObject
|
|
169
|
+
The ``DiaObject`` you got from ``DiaObject.get_object`` or ``DiaObject.find_object`` include properties ``ra`` and ``dec``. **However, the positions in the DiaObject object should be viewed as approximate.** They will be the position it had when the object was first discovered. For objects loaded from truth tables, they will be perfect, but of course we won't have truth tables for the real survey. Often, the first discovery will be a relatively low S/N point, and much better positions can be determined; doing so will be one of the jobs of ``phrosty``.
|
|
162
170
|
|
|
163
171
|
To get an improved position for an object, assume you have the object in the variable ``diaobj``. You can then call::
|
|
164
172
|
|
|
@@ -181,10 +189,36 @@ See :ref:`nov2025-provtags` below to figure out what ``TAG`` and ``PROCESS`` sho
|
|
|
181
189
|
**Important**: if you use an updated DiaObject position, then the provenance of that position should be one of your upstream provenances; see :ref:`nov2025-making-prov`.
|
|
182
190
|
|
|
183
191
|
|
|
184
|
-
|
|
192
|
+
Reading Lightcurves
|
|
185
193
|
===================
|
|
186
194
|
|
|
187
|
-
|
|
195
|
+
To read a lightcurve, you need three or four things:
|
|
196
|
+
|
|
197
|
+
* The ``diaobject_id`` of the object whose lightcurve you want
|
|
198
|
+
* The ``provenance_tag`` of the provenance you want to get lightcurves from
|
|
199
|
+
* The ``process`` to go with the provenance tag
|
|
200
|
+
* (Optional) The ``band`` of the lightcurve
|
|
201
|
+
|
|
202
|
+
The ``provenance_tag`` and ``process`` will be given to you through our fake orchestration process, and may possibly be found in :ref:`nov2025-provtags`. The ``diaobject_id`` will be given to you through the fake orchestration process.
|
|
203
|
+
|
|
204
|
+
To get the lightcurves::
|
|
205
|
+
|
|
206
|
+
from snappl.lightcurve import Lightcurve
|
|
207
|
+
|
|
208
|
+
ltcvs = Lightcurve.find_lightcurves( <diaobject_id>, provenance_tag=<tag>, process=<proc>, dbclient=dbclient )
|
|
209
|
+
|
|
210
|
+
That will return a list of lightcurves. If you also specify ``band=<band>``, that will be a 1-element list with the lightcurve just for that band. (Or a 0-element list if it's not found.)
|
|
211
|
+
|
|
212
|
+
Each element of the list will be a ``Lightcurve`` object. You can find the actual lightcurve data in the ``.lightcurve`` property as an astropy QTable. You can find the metadata dictionary either in the ``.lightcurve.meta`` or in the ``.meta`` property (though the latter will intially be ``None`` until you access the ``.lightcurve`` property). Guaranteed metadata can be found in the `lightcurve schema specification on the PIT wiki <https://github.com/Roman-Supernova-PIT/Roman-Supernova-PIT/wiki/lightcurve>`_. You should probably ignore the ``filepath`` in the metadata, because ``snappl`` has already read the file for you (and put it in the ``.lightcurve`` property).
|
|
213
|
+
|
|
214
|
+
|
|
215
|
+
Finding Segmentation Maps
|
|
216
|
+
=========================
|
|
217
|
+
|
|
218
|
+
You will need to ``from snappl.segmap import SegmentationMap`` and then call ``SegmentationMap.find_segmaps``. You need to pass a provenance tag and a process to ``find_segmaps``; you will be given these (see :ref:`nov2025-provtags`). Beyond that, look at the docstring for that function to see what you can search on.
|
|
219
|
+
|
|
220
|
+
You will get back a list of ``SegmentationMap`` objects. A ``SegmentationMap`` object has several attributes, including ``band``, and eight attributes ``ra_corner_00``, ``dec_corner_00``, etc., where ``00`` is the lower-left pixel, ``01`` upper-left pixel, ``10`` is the lower-right pixel, and ``11`` is the upper-right pixel. The most important field is ``.image``. This is a ``snappl.image.Image`` object. You can get the 2d numpy array of the image data of the segmentaton map from the ``.data`` property of the ``Image`` object.
|
|
221
|
+
|
|
188
222
|
|
|
189
223
|
.. _nov2025-making-prov:
|
|
190
224
|
|
|
@@ -250,9 +284,24 @@ This will (I believe) return a dictionary that's the same as what you'd get back
|
|
|
250
284
|
Saving Lightcurves
|
|
251
285
|
==================
|
|
252
286
|
|
|
253
|
-
|
|
287
|
+
Lightcurves saved to the database are for only a single band. If you have a multiband lightcurve, from the point of view of the database that's several different lightcurves.
|
|
288
|
+
|
|
289
|
+
To write a Lightcurve, first create a ``Lightcurve`` object::
|
|
290
|
+
|
|
291
|
+
from snappl.lightcurve import Lightcurve
|
|
292
|
+
|
|
293
|
+
ltcv = Lightcurve( data=<data>, meta=<meta> )
|
|
294
|
+
|
|
295
|
+
where ``<meta>`` is a dictionary with metadata, and ``<data>`` is one of an astropy Table, a pandas DataFrame, or a dictionary of lists. On the `lightcurve schema specification on the PIT wiki <https://github.com/Roman-Supernova-PIT/Roman-Supernova-PIT/wiki/lightcurve>`_ you can find the mandatory fields in the metadata dictionary; it's allowed to have additional ones as well. Likewise, there you can find the mandatory columns (and the order of those columns) in the data array. You may also have additional columns in that data array.
|
|
296
|
+
|
|
297
|
+
In order to create a lightcurve, you will need to make a provenance for it; see :ref:`nov2025-making-prov`. Make sure to include the ``diaobject position`` provenance as an upstream provenance if you used a position other than the cheesy approximate one that comes with the ``DiaObject``.
|
|
298
|
+
|
|
299
|
+
Once you have your lightcurve object, do two things::
|
|
254
300
|
|
|
301
|
+
ltcv.write()
|
|
302
|
+
ltcv.save_to_db( dbclient=dbclient )
|
|
255
303
|
|
|
304
|
+
The first one writes the actual file; it will write it in the standard location, and will populate the ``.filepath`` property with the location of the file *relative to the configured base directory for lightcurves* (which is in config option ``system.paths.lightcurves``). The second call saves a record to the database with information about your lightcurve.
|
|
256
305
|
|
|
257
306
|
.. _nov2025-provtags:
|
|
258
307
|
|
{roman_snpit_snappl-0.20.0 → roman_snpit_snappl-0.21.0}/roman_snpit_snappl.egg-info/SOURCES.txt
RENAMED
|
@@ -70,6 +70,8 @@ changes/9.snappl.rst
|
|
|
70
70
|
changes/91.feature.rst
|
|
71
71
|
changes/92.docs.rst
|
|
72
72
|
changes/94.snappl.rst
|
|
73
|
+
changes/98.docs.rst
|
|
74
|
+
changes/99.feature.rst
|
|
73
75
|
docker/postgres/Dockerfile
|
|
74
76
|
docker/postgres/postgresql.conf
|
|
75
77
|
docker/postgres/run_postgres.sh
|
|
@@ -115,6 +117,7 @@ snappl/logger.py
|
|
|
115
117
|
snappl/provenance.py
|
|
116
118
|
snappl/psf.py
|
|
117
119
|
snappl/sed.py
|
|
120
|
+
snappl/segmap.py
|
|
118
121
|
snappl/utils.py
|
|
119
122
|
snappl/wcs.py
|
|
120
123
|
snappl/_dev/__init__.py
|
|
@@ -129,6 +132,7 @@ snappl/db/migrations/20251008_init.sql
|
|
|
129
132
|
snappl/db/migrations/20251017_objdetcount.sql
|
|
130
133
|
snappl/db/migrations/20251024_l2image_mjd.sql
|
|
131
134
|
snappl/db/migrations/20251025_lightcurve.sql
|
|
135
|
+
snappl/db/migrations/20251028_segmap.sql
|
|
132
136
|
snappl/db/migrations/apply_migrations.py
|
|
133
137
|
snappl/db/migrations/schema_to_rst.py
|
|
134
138
|
snappl/db/migrations/scorched_earth.py
|
|
@@ -28,7 +28,7 @@ version_tuple: VERSION_TUPLE
|
|
|
28
28
|
commit_id: COMMIT_ID
|
|
29
29
|
__commit_id__: COMMIT_ID
|
|
30
30
|
|
|
31
|
-
__version__ = version = '0.
|
|
32
|
-
__version_tuple__ = version_tuple = (0,
|
|
31
|
+
__version__ = version = '0.21.0'
|
|
32
|
+
__version_tuple__ = version_tuple = (0, 21, 0)
|
|
33
33
|
|
|
34
|
-
__commit_id__ = commit_id = '
|
|
34
|
+
__commit_id__ = commit_id = 'g7a9941597'
|
|
@@ -0,0 +1,266 @@
|
|
|
1
|
+
from types import SimpleNamespace
|
|
2
|
+
import simplejson
|
|
3
|
+
|
|
4
|
+
import flask
|
|
5
|
+
import flask.views
|
|
6
|
+
from psycopg import sql
|
|
7
|
+
|
|
8
|
+
from snappl.db import db
|
|
9
|
+
from snappl.logger import SNLogger
|
|
10
|
+
from snappl.utils import SNPITJsonEncoder
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
# ======================================================================
|
|
14
|
+
|
|
15
|
+
class BaseView( flask.views.View ):
|
|
16
|
+
"""A BaseView that all other views can be based on.
|
|
17
|
+
|
|
18
|
+
If the view doesn't override dispatch_request, then it must define a
|
|
19
|
+
function do_the_things. That should return a dict, list, string,
|
|
20
|
+
tuple, or ...something else.
|
|
21
|
+
|
|
22
|
+
If it returns a dict or a list, the web server will send to the
|
|
23
|
+
client application/json with status 200. If the result is a string,
|
|
24
|
+
it the web server will send to the client text/plain with status
|
|
25
|
+
200. If it's a tuple, just let Flask deal with that tuple to figure
|
|
26
|
+
out what the web server should send to the client. Otherwise, the
|
|
27
|
+
web server will send to the client application/octet-stream with
|
|
28
|
+
status 200.
|
|
29
|
+
|
|
30
|
+
Subclasses that do not override dispatch_request do not need to call
|
|
31
|
+
check_auth. However, if they do override it, they should call that
|
|
32
|
+
if the results shouldn't be sent back to an unauthenticated user.
|
|
33
|
+
|
|
34
|
+
"""
|
|
35
|
+
|
|
36
|
+
_admin_required = False
|
|
37
|
+
|
|
38
|
+
def __init__( self, *args, **kwargs ):
|
|
39
|
+
super().__init__( *args, **kwargs )
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
def check_json_keys( self, needed_keys, allowed_keys, minmax_keys=set() ):
|
|
43
|
+
if not flask.request.is_json:
|
|
44
|
+
raise RuntimeError( "Expected json POST data, didn't get any." )
|
|
45
|
+
|
|
46
|
+
all_allowed_keys = allowed_keys.copy()
|
|
47
|
+
for kw in minmax_keys:
|
|
48
|
+
for edge in [ 'min', 'max' ]:
|
|
49
|
+
all_allowed_keys.add( f"{kw}_{edge}" )
|
|
50
|
+
|
|
51
|
+
data = flask.request.json
|
|
52
|
+
passed_keys = set( data.keys() )
|
|
53
|
+
if not needed_keys.issubset( passed_keys ):
|
|
54
|
+
raise RuntimeError( f"Missing required keys: {needed_keys - passed_keys}" )
|
|
55
|
+
if not passed_keys.issubset( all_allowed_keys ):
|
|
56
|
+
raise RuntimeError( f"Unknown keys: {passed_keys - all_allowed_keys}" )
|
|
57
|
+
return data
|
|
58
|
+
|
|
59
|
+
def get_provenance_id( self, data, dbcon=None ):
|
|
60
|
+
with db.DBCon( dictcursor=True ) as dbcon:
|
|
61
|
+
provid = None
|
|
62
|
+
if 'provenance' in data:
|
|
63
|
+
provid = data['provenance']
|
|
64
|
+
del data['provenance']
|
|
65
|
+
elif ( 'provenance_tag' in data ) and ( 'process' in data ):
|
|
66
|
+
rows = dbcon.execute( "SELECT provenance_id FROM provenance_tag "
|
|
67
|
+
"WHERE tag=%(tag)s AND process=%(proc)s",
|
|
68
|
+
{'tag': data['provenance_tag'], 'proc': data['process'] } )
|
|
69
|
+
if len(rows) == 0:
|
|
70
|
+
raise RuntimeError( f"Unknown provenance with tag {data['provenance_tag']} "
|
|
71
|
+
f"and process {data['process']}" )
|
|
72
|
+
if len(rows) > 1:
|
|
73
|
+
raise RuntimeError ( f"Database corruption: multiple provenances with tag {data['provenance_tag']}"
|
|
74
|
+
f"and process {data['process']}; this should never happen." )
|
|
75
|
+
provid = db.Provenance.get( rows[0]['provenance_id'] ).id
|
|
76
|
+
del data['provenance_tag']
|
|
77
|
+
del data['process']
|
|
78
|
+
else:
|
|
79
|
+
raise RuntimeError( "Must give either provenance_id, or both of provenance_tag and process" )
|
|
80
|
+
|
|
81
|
+
return data, provid
|
|
82
|
+
|
|
83
|
+
|
|
84
|
+
# Warning : only call this next one if you've made sure that there is no SQL injection in keys!
|
|
85
|
+
def build_sql_insert( self, keys ):
|
|
86
|
+
keysql = None
|
|
87
|
+
subs = None
|
|
88
|
+
for key in keys:
|
|
89
|
+
if keysql is None:
|
|
90
|
+
keysql = sql.SQL( "{key}" ).format( key=sql.Identifier( key ) )
|
|
91
|
+
else:
|
|
92
|
+
keysql += sql.SQL( ", {key}" ).format( key=sql.Identifier( key ) )
|
|
93
|
+
if subs is None:
|
|
94
|
+
subs = f"%({key})s"
|
|
95
|
+
else:
|
|
96
|
+
subs += f", %({key})s"
|
|
97
|
+
return keysql, subs
|
|
98
|
+
|
|
99
|
+
|
|
100
|
+
# WARNING. Do not use this unless you're sure that everything in
|
|
101
|
+
# the passed arrays have no SQL injection attacks.
|
|
102
|
+
def make_sql_conditions( self, data, equalses=[], minmaxes=[],
|
|
103
|
+
q3ctriplets=[], cornerpolypairs=[],
|
|
104
|
+
conditions=[], subdict={} ):
|
|
105
|
+
finalclause = None
|
|
106
|
+
|
|
107
|
+
if any( i in data for i in [ 'order_by', 'limit', 'offset' ] ):
|
|
108
|
+
orderbyclause = None
|
|
109
|
+
limitclause = None
|
|
110
|
+
offsetclause = None
|
|
111
|
+
|
|
112
|
+
if 'order_by' in data:
|
|
113
|
+
orderby = data['order_by']
|
|
114
|
+
if not isinstance( orderby, list ):
|
|
115
|
+
orderby = [ orderby ]
|
|
116
|
+
orderbyclause = sql.SQL( " ORDER BY " )
|
|
117
|
+
comma = ""
|
|
118
|
+
for o in orderby:
|
|
119
|
+
orderbyclause += sql.SQL( f"{comma}{{orderby}}" ).format( orderby=sql.Identifier(o) )
|
|
120
|
+
comma = ","
|
|
121
|
+
del data['order_by']
|
|
122
|
+
finalclause = orderbyclause
|
|
123
|
+
|
|
124
|
+
if 'limit' in data:
|
|
125
|
+
limitclause = sql.SQL( " LIMIT %(finalclause_limit)s" )
|
|
126
|
+
subdict['finalclause_limit'] = data['limit']
|
|
127
|
+
del data['limit']
|
|
128
|
+
if finalclause is None:
|
|
129
|
+
finalclause = limitclause
|
|
130
|
+
else:
|
|
131
|
+
finalclause += limitclause
|
|
132
|
+
|
|
133
|
+
if 'offset' in data:
|
|
134
|
+
offsetclause = sql.SQL( " OFFSET %(finalclause_offset)s" )
|
|
135
|
+
subdict['finalclause_offset'] = data['offset']
|
|
136
|
+
del data['offset']
|
|
137
|
+
if finalclause is None:
|
|
138
|
+
finalclause = offsetclause
|
|
139
|
+
else:
|
|
140
|
+
finalclause += offsetclause
|
|
141
|
+
|
|
142
|
+
finalclause = sql.SQL("") if finalclause is None else finalclause
|
|
143
|
+
|
|
144
|
+
for i, triplet in enumerate(q3ctriplets):
|
|
145
|
+
presencecheck = [ ( i in data and data[i] is not None ) for i in triplet ]
|
|
146
|
+
if any( presencecheck ):
|
|
147
|
+
if not all( presencecheck ):
|
|
148
|
+
raise RuntimeError( f"Must include all or none of {triplet}" )
|
|
149
|
+
barf = f"q3c_triplet_{i}"
|
|
150
|
+
formatsubs = { f"{barf}_0": sql.Identifier( triplet[0] ),
|
|
151
|
+
f"{barf}_1": sql.Identifier( triplet[1] ) }
|
|
152
|
+
conditions.append( sql.SQL( f"q3c_radial_query({{{barf}_0}},{{{barf}_1}},"
|
|
153
|
+
f"%({barf}_0)s,%({barf}_1)s,%({barf}_2)s)"
|
|
154
|
+
).format( **formatsubs ) )
|
|
155
|
+
subdict.update( { f"{barf}_0": data[triplet[0]],
|
|
156
|
+
f"{barf}_1": data[triplet[1]],
|
|
157
|
+
f"{barf}_2": data[triplet[2]] / 3600. } )
|
|
158
|
+
del data[triplet[0]]
|
|
159
|
+
del data[triplet[1]]
|
|
160
|
+
del data[triplet[2]]
|
|
161
|
+
|
|
162
|
+
for i, pair in enumerate(cornerpolypairs):
|
|
163
|
+
presencecheck = [ ( i in data and data[i] is not None ) for i in pair ]
|
|
164
|
+
if any( presencecheck ):
|
|
165
|
+
if not all( presencecheck ):
|
|
166
|
+
raise RuntimeError( f"Must include both or neither of {pair}" )
|
|
167
|
+
barf = f"corner_pair_{i}"
|
|
168
|
+
# THINKING AHEAD : this poly query doesn't use the q3c index
|
|
169
|
+
# As the number of database rows get large, we should look
|
|
170
|
+
# at performance. We many need to do this in two steps,
|
|
171
|
+
# which would mean using a temp table. First step would use
|
|
172
|
+
# regular indexes on the eight corner variables and use
|
|
173
|
+
# LEAST and GREATEST with ra and dec. Then, a second query
|
|
174
|
+
# would use the poly query on the temp table resulting from
|
|
175
|
+
# that first query. (Or maybe you can do it all with clever
|
|
176
|
+
# nested queries.) This becomes very complicated.
|
|
177
|
+
conditions.append( sql.SQL( f"q3c_poly_query(%({barf}_0)s, %({barf}_1)s, "
|
|
178
|
+
f"ARRAY[ ra_corner_00, dec_corner_00, ra_corner_01, dec_corner_01, "
|
|
179
|
+
f" ra_corner_11, dec_corner_11, ra_corner_10, dec_corner_10 ] )"
|
|
180
|
+
) )
|
|
181
|
+
subdict.update( { f"{barf}_0": data[pair[0]],
|
|
182
|
+
f"{barf}_1": data[pair[1]] } )
|
|
183
|
+
del data[pair[0]]
|
|
184
|
+
del data[pair[1]]
|
|
185
|
+
|
|
186
|
+
for kw in equalses:
|
|
187
|
+
if ( kw in data ) and ( data[kw] is not None ):
|
|
188
|
+
conditions.append( sql.SQL( f"{kw}=%({kw})s" ) )
|
|
189
|
+
# I hate that we're doing str here, but we have a legacy of diaobject names
|
|
190
|
+
# being either strings or integers
|
|
191
|
+
subdict[kw] = str( data[kw] )
|
|
192
|
+
del data[kw]
|
|
193
|
+
|
|
194
|
+
for kw in minmaxes:
|
|
195
|
+
if kw in data:
|
|
196
|
+
if data['kw'] is not None:
|
|
197
|
+
conditions.append( sql.SQL( f"{kw}=%({kw})s" ) )
|
|
198
|
+
subdict[kw] = data[kw]
|
|
199
|
+
del data[kw]
|
|
200
|
+
for edge, op in zip( [ 'min', 'max' ], [ '>=', '<=' ] ):
|
|
201
|
+
if f'{kw}_{edge}' in data:
|
|
202
|
+
if data[f'{kw}_{edge}'] is not None:
|
|
203
|
+
conditions.append( sql.SQL( f"{kw} {op} %({kw}_{edge})s" ) )
|
|
204
|
+
subdict[f'{kw}_{edge}'] = data[f'{kw}_{edge}']
|
|
205
|
+
del data[f'{kw}_{edge}']
|
|
206
|
+
|
|
207
|
+
_and = None
|
|
208
|
+
for condition in conditions:
|
|
209
|
+
if _and is None:
|
|
210
|
+
condstr = condition
|
|
211
|
+
else:
|
|
212
|
+
_and = " AND "
|
|
213
|
+
condstr += sql.SQL(_and) + condition
|
|
214
|
+
|
|
215
|
+
return data, condstr, subdict, finalclause
|
|
216
|
+
|
|
217
|
+
|
|
218
|
+
def check_auth( self ):
|
|
219
|
+
self.username = flask.session['username'] if 'username' in flask.session else '(None)'
|
|
220
|
+
self.displayname = flask.session['userdisplayname'] if 'userdisplayname' in flask.session else '(None)'
|
|
221
|
+
self.authenticated = ( 'authenticated' in flask.session ) and flask.session['authenticated']
|
|
222
|
+
self.user = None
|
|
223
|
+
if self.authenticated:
|
|
224
|
+
with db.DB() as conn:
|
|
225
|
+
cursor = conn.cursor()
|
|
226
|
+
cursor.execute( "SELECT id,username,displayname,email FROM authuser WHERE username=%(username)s",
|
|
227
|
+
{'username': self.username } )
|
|
228
|
+
rows = cursor.fetchall()
|
|
229
|
+
if len(rows) > 1:
|
|
230
|
+
self.authenticated = False
|
|
231
|
+
raise RuntimeError( f"Error, more than one {self.username} in database, "
|
|
232
|
+
f"this should never happen." )
|
|
233
|
+
if len(rows) == 0:
|
|
234
|
+
self.authenticated = False
|
|
235
|
+
raise ValueError( f"Error, failed to find user {self.username} in database" )
|
|
236
|
+
row = rows[0]
|
|
237
|
+
self.user = SimpleNamespace( id=row[0], username=row[1], displayname=row[2], email=row[3] )
|
|
238
|
+
# Verify that session displayname and database displayname match? Eh. Whatevs.
|
|
239
|
+
return self.authenticated
|
|
240
|
+
|
|
241
|
+
def dispatch_request( self, *args, **kwargs ):
|
|
242
|
+
if not self.check_auth():
|
|
243
|
+
return "Not logged in", 500
|
|
244
|
+
if ( self._admin_required ) and ( not self.user.isadmin ):
|
|
245
|
+
return "Action requires admin", 500
|
|
246
|
+
try:
|
|
247
|
+
retval = self.do_the_things( *args, **kwargs )
|
|
248
|
+
# Can't just use the default JSON handling, because it
|
|
249
|
+
# writes out NaN which is not standard JSON and which
|
|
250
|
+
# the javascript JSON parser chokes on. Sigh.
|
|
251
|
+
if isinstance( retval, dict ) or isinstance( retval, list ):
|
|
252
|
+
# SNLogger.warning( f"Dumping to json: {retval}" )
|
|
253
|
+
return ( simplejson.dumps( retval, ignore_nan=True, cls=SNPITJsonEncoder ),
|
|
254
|
+
200, { 'Content-Type': 'application/json' } )
|
|
255
|
+
elif isinstance( retval, str ):
|
|
256
|
+
return retval, 200, { 'Content-Type': 'text/plain; charset=utf-8' }
|
|
257
|
+
elif isinstance( retval, tuple ):
|
|
258
|
+
return retval
|
|
259
|
+
else:
|
|
260
|
+
return retval, 200, { 'Content-Type': 'application/octet-stream' }
|
|
261
|
+
except Exception as ex:
|
|
262
|
+
# sio = io.StringIO()
|
|
263
|
+
# traceback.print_exc( file=sio )
|
|
264
|
+
# SNLogger.debug( sio.getvalue() )
|
|
265
|
+
SNLogger.exception( str(ex) )
|
|
266
|
+
return str(ex), 500
|
|
@@ -13,6 +13,7 @@ from contextlib import contextmanager
|
|
|
13
13
|
|
|
14
14
|
import numpy as np
|
|
15
15
|
import psycopg
|
|
16
|
+
from psycopg import sql
|
|
16
17
|
|
|
17
18
|
from snappl.config import Config
|
|
18
19
|
from snappl.logger import SNLogger
|
|
@@ -266,7 +267,8 @@ class DBCon:
|
|
|
266
267
|
|
|
267
268
|
"""
|
|
268
269
|
if self.echoqueries and not silent:
|
|
269
|
-
|
|
270
|
+
qprint = q.as_string() if isinstance( q, sql.Composable ) else q
|
|
271
|
+
SNLogger.debug( f"Sending query\n{qprint}\nwith substitutions: {subdict}" )
|
|
270
272
|
|
|
271
273
|
if self.alwaysexplain and not silent:
|
|
272
274
|
self.cursor.execute( f"EXPLAIN {q}", subdict )
|
|
@@ -1074,6 +1076,14 @@ class SummedImage( DBBase ):
|
|
|
1074
1076
|
_pk = [ 'id' ]
|
|
1075
1077
|
|
|
1076
1078
|
|
|
1079
|
+
# ======================================================================
|
|
1080
|
+
|
|
1081
|
+
class SegMap( DBBase ):
|
|
1082
|
+
__tablename__ = "segmap"
|
|
1083
|
+
_tablemeta = None
|
|
1084
|
+
_pk = [ 'id' ]
|
|
1085
|
+
|
|
1086
|
+
|
|
1077
1087
|
# ======================================================================
|
|
1078
1088
|
|
|
1079
1089
|
class Lightcurve( DBBase ):
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
CREATE TABLE segmap(
|
|
2
|
+
id UUID PRIMARY KEY,
|
|
3
|
+
provenance_id UUID NOT NULL,
|
|
4
|
+
band text NOT NULL,
|
|
5
|
+
ra double precision NOT NULL,
|
|
6
|
+
dec double precision NOT NULL,
|
|
7
|
+
ra_corner_00 real NOT NULL,
|
|
8
|
+
ra_corner_01 real NOT NULL,
|
|
9
|
+
ra_corner_10 real NOT NULL,
|
|
10
|
+
ra_corner_11 real NOT NULL,
|
|
11
|
+
dec_corner_00 real NOT NULL,
|
|
12
|
+
dec_corner_01 real NOT NULL,
|
|
13
|
+
dec_corner_10 real NOT NULL,
|
|
14
|
+
dec_corner_11 real NOT NULL,
|
|
15
|
+
filepath text NOT NULL,
|
|
16
|
+
width smallint,
|
|
17
|
+
height smallint,
|
|
18
|
+
format smallint NOT NULL DEFAULT 0,
|
|
19
|
+
l2image_id UUID DEFAULT NULL
|
|
20
|
+
);
|
|
21
|
+
CREATE INDEX ix_segmap_band ON segmap (band);
|
|
22
|
+
CREATE INDEX ix_segmap_q3c ON segmap (q3c_ang2ipix(ra,dec));
|
|
23
|
+
CREATE INDEX ix_segmap_ra00 ON segmap (ra_corner_00);
|
|
24
|
+
CREATE INDEX ix_segmap_ra01 ON segmap (ra_corner_01);
|
|
25
|
+
CREATE INDEX ix_segmap_ra10 ON segmap (ra_corner_10);
|
|
26
|
+
CREATE INDEX ix_segmap_ra11 ON segmap (ra_corner_11);
|
|
27
|
+
CREATE INDEX ix_segmap_dec00 ON segmap (dec_corner_00);
|
|
28
|
+
CREATE INDEX ix_segmap_dec01 ON segmap (dec_corner_01);
|
|
29
|
+
CREATE INDEX ix_segmap_dec10 ON segmap (dec_corner_10);
|
|
30
|
+
CREATE INDEX ix_segmap_dec11 ON segmap (dec_corner_11);
|
|
31
|
+
CREATE UNIQUE INDEX ix_segmap_filepath ON segmap (filepath);
|
|
32
|
+
CREATE INDEX iX_segmap_l2image ON segmap (l2image_id);
|
|
33
|
+
ALTER TABLE segmap ADD CONSTRAINT fk_segmap_l2image
|
|
34
|
+
FOREIGN KEY(l2image_id) REFERENCES l2image(id) ON DELETE RESTRICT;
|
|
35
|
+
COMMENT ON TABLE segmap IS 'Segmentation maps';
|
|
36
|
+
COMMENT ON COLUMN segmap.ra_corner_00 IS 'RA of pixel (0,0)';
|
|
37
|
+
COMMENT ON COLUMN segmap.ra_corner_01 IS 'RA of pixel (0,height-1)';
|
|
38
|
+
COMMENT ON COLUMN segmap.ra_corner_10 IS 'RA of pixel (width-1,0)';
|
|
39
|
+
COMMENT ON COLUMN segmap.ra_corner_11 IS 'RA of pixel (width-1,height-1)';
|
|
40
|
+
COMMENT ON COLUMN segmap.dec_corner_00 IS 'Dec of pixel (0,0)';
|
|
41
|
+
COMMENT ON COLUMN segmap.dec_corner_01 IS 'Dec of pixel (0,height-1)';
|
|
42
|
+
COMMENT ON COLUMN segmap.dec_corner_10 IS 'Dec of pixel (width-1,0)';
|
|
43
|
+
COMMENT ON COLUMN segmap.dec_corner_11 IS 'Dec of pixel (width-1,height-1)';
|
|
44
|
+
COMMENT ON COLUMN segmap.l2image_id IS 'This segmentation map is for this image';
|
|
45
|
+
COMMENT ON COLUMN segmap.format IS '0=Unknown, 1=OpenUniverse2024FITSImage';
|