tomtoolkit 2.30.0a0__py3-none-any.whl
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.
- tom_alerts/__init__.py +0 -0
- tom_alerts/admin.py +7 -0
- tom_alerts/alerts.py +275 -0
- tom_alerts/apps.py +12 -0
- tom_alerts/brokers/__init__.py +0 -0
- tom_alerts/brokers/alerce.py +636 -0
- tom_alerts/brokers/antares.py +50 -0
- tom_alerts/brokers/fink.py +44 -0
- tom_alerts/brokers/gaia.py +197 -0
- tom_alerts/brokers/hermes.py +44 -0
- tom_alerts/brokers/lasair.py +229 -0
- tom_alerts/brokers/scout.py +96 -0
- tom_alerts/brokers/tns.py +240 -0
- tom_alerts/exceptions.py +4 -0
- tom_alerts/management/__init__.py +0 -0
- tom_alerts/management/commands/__init__.py +0 -0
- tom_alerts/management/commands/runbrokerquery.py +33 -0
- tom_alerts/migrations/0001_initial.py +25 -0
- tom_alerts/migrations/0002_auto_20190626_2135.py +23 -0
- tom_alerts/migrations/0003_auto_20190701_2226.py +18 -0
- tom_alerts/migrations/0004_auto_20210204_2300.py +18 -0
- tom_alerts/migrations/0005_alertstreammessage.py +23 -0
- tom_alerts/migrations/0006_alter_alertstreammessage_exchange_status.py +18 -0
- tom_alerts/migrations/0007_alter_alertstreammessage_message_id.py +18 -0
- tom_alerts/migrations/__init__.py +0 -0
- tom_alerts/models.py +83 -0
- tom_alerts/templates/tom_alerts/brokerquery_confirm_delete.html +9 -0
- tom_alerts/templates/tom_alerts/brokerquery_list.html +49 -0
- tom_alerts/templates/tom_alerts/partials/navbar_link.html +3 -0
- tom_alerts/templates/tom_alerts/partials/submit_upstream_form.html +2 -0
- tom_alerts/templates/tom_alerts/query_form.html +7 -0
- tom_alerts/templates/tom_alerts/query_result.html +70 -0
- tom_alerts/templatetags/alerts_extras.py +36 -0
- tom_alerts/tests/__init__.py +0 -0
- tom_alerts/tests/brokers/__init__.py +0 -0
- tom_alerts/tests/brokers/test_alerce.py +569 -0
- tom_alerts/tests/brokers/test_gaia.py +188 -0
- tom_alerts/tests/brokers/test_lasair.py +96 -0
- tom_alerts/tests/tests.py +343 -0
- tom_alerts/urls.py +16 -0
- tom_alerts/views.py +394 -0
- tom_base/__init__.py +2 -0
- tom_base/settings.py +352 -0
- tom_base/wsgi.py +16 -0
- tom_catalogs/__init__.py +0 -0
- tom_catalogs/admin.py +1 -0
- tom_catalogs/apps.py +18 -0
- tom_catalogs/forms.py +41 -0
- tom_catalogs/harvester.py +86 -0
- tom_catalogs/harvesters/__init__.py +0 -0
- tom_catalogs/harvesters/jplhorizons.py +64 -0
- tom_catalogs/harvesters/mpc.py +200 -0
- tom_catalogs/harvesters/ned.py +27 -0
- tom_catalogs/harvesters/simbad.py +52 -0
- tom_catalogs/harvesters/tns.py +78 -0
- tom_catalogs/templates/tom_catalogs/partials/catalog_query_menu.html +4 -0
- tom_catalogs/templates/tom_catalogs/query_form.html +13 -0
- tom_catalogs/templatetags/__init__.py +0 -0
- tom_catalogs/templatetags/dataservices_extras.py +17 -0
- tom_catalogs/tests/__init__.py +0 -0
- tom_catalogs/tests/harvesters/__init__.py +0 -0
- tom_catalogs/tests/harvesters/data/__init__.py +0 -0
- tom_catalogs/tests/harvesters/data/test_65803_mpc_orb.json +284 -0
- tom_catalogs/tests/harvesters/test_jplhorizons.py +72 -0
- tom_catalogs/tests/harvesters/test_mpc.py +421 -0
- tom_catalogs/tests/harvesters/test_simbad.py +61 -0
- tom_catalogs/tests/tests.py +51 -0
- tom_catalogs/urls.py +9 -0
- tom_catalogs/views.py +39 -0
- tom_common/__init__.py +0 -0
- tom_common/admin.py +23 -0
- tom_common/api_router.py +54 -0
- tom_common/api_views.py +15 -0
- tom_common/apps.py +34 -0
- tom_common/exceptions.py +5 -0
- tom_common/forms.py +119 -0
- tom_common/hints.py +14 -0
- tom_common/hooks.py +33 -0
- tom_common/middleware.py +60 -0
- tom_common/migrations/0001_initial.py +25 -0
- tom_common/migrations/0002_usersession.py +25 -0
- tom_common/migrations/__init__.py +0 -0
- tom_common/mixins.py +13 -0
- tom_common/models.py +188 -0
- tom_common/serializers.py +11 -0
- tom_common/session_utils.py +351 -0
- tom_common/signals.py +168 -0
- tom_common/static/font-awesome-4.7.0/HELP-US-OUT.txt +7 -0
- tom_common/static/font-awesome-4.7.0/css/font-awesome.css +2337 -0
- tom_common/static/font-awesome-4.7.0/css/font-awesome.min.css +4 -0
- tom_common/static/font-awesome-4.7.0/fonts/FontAwesome.otf +0 -0
- tom_common/static/font-awesome-4.7.0/fonts/fontawesome-webfont.eot +0 -0
- tom_common/static/font-awesome-4.7.0/fonts/fontawesome-webfont.svg +2671 -0
- tom_common/static/font-awesome-4.7.0/fonts/fontawesome-webfont.ttf +0 -0
- tom_common/static/font-awesome-4.7.0/fonts/fontawesome-webfont.woff +0 -0
- tom_common/static/font-awesome-4.7.0/fonts/fontawesome-webfont.woff2 +0 -0
- tom_common/static/font-awesome-4.7.0/less/animated.less +34 -0
- tom_common/static/font-awesome-4.7.0/less/bordered-pulled.less +25 -0
- tom_common/static/font-awesome-4.7.0/less/core.less +12 -0
- tom_common/static/font-awesome-4.7.0/less/fixed-width.less +6 -0
- tom_common/static/font-awesome-4.7.0/less/font-awesome.less +18 -0
- tom_common/static/font-awesome-4.7.0/less/icons.less +789 -0
- tom_common/static/font-awesome-4.7.0/less/larger.less +13 -0
- tom_common/static/font-awesome-4.7.0/less/list.less +19 -0
- tom_common/static/font-awesome-4.7.0/less/mixins.less +60 -0
- tom_common/static/font-awesome-4.7.0/less/path.less +15 -0
- tom_common/static/font-awesome-4.7.0/less/rotated-flipped.less +20 -0
- tom_common/static/font-awesome-4.7.0/less/screen-reader.less +5 -0
- tom_common/static/font-awesome-4.7.0/less/stacked.less +20 -0
- tom_common/static/font-awesome-4.7.0/less/variables.less +800 -0
- tom_common/static/font-awesome-4.7.0/scss/_animated.scss +34 -0
- tom_common/static/font-awesome-4.7.0/scss/_bordered-pulled.scss +25 -0
- tom_common/static/font-awesome-4.7.0/scss/_core.scss +12 -0
- tom_common/static/font-awesome-4.7.0/scss/_fixed-width.scss +6 -0
- tom_common/static/font-awesome-4.7.0/scss/_icons.scss +789 -0
- tom_common/static/font-awesome-4.7.0/scss/_larger.scss +13 -0
- tom_common/static/font-awesome-4.7.0/scss/_list.scss +19 -0
- tom_common/static/font-awesome-4.7.0/scss/_mixins.scss +60 -0
- tom_common/static/font-awesome-4.7.0/scss/_path.scss +15 -0
- tom_common/static/font-awesome-4.7.0/scss/_rotated-flipped.scss +20 -0
- tom_common/static/font-awesome-4.7.0/scss/_screen-reader.scss +5 -0
- tom_common/static/font-awesome-4.7.0/scss/_stacked.scss +20 -0
- tom_common/static/font-awesome-4.7.0/scss/_variables.scss +800 -0
- tom_common/static/font-awesome-4.7.0/scss/font-awesome.scss +18 -0
- tom_common/static/tom_common/css/dark.css +22 -0
- tom_common/static/tom_common/css/main.css +214 -0
- tom_common/static/tom_common/img/bluespinner.gif +0 -0
- tom_common/static/tom_common/img/favicon-16.ico +0 -0
- tom_common/static/tom_common/img/favicon-16x16.png +0 -0
- tom_common/static/tom_common/img/favicon-32.ico +0 -0
- tom_common/static/tom_common/img/favicon-32x32.png +0 -0
- tom_common/static/tom_common/img/favicon.ico +0 -0
- tom_common/static/tom_common/img/icon.png +0 -0
- tom_common/static/tom_common/img/logo-color-cropped.png +0 -0
- tom_common/static/tom_common/img/logo-color.png +0 -0
- tom_common/static/tom_common/img/logo-text.png +0 -0
- tom_common/static/tom_common/js/htmx.min.js +1 -0
- tom_common/templates/auth/group_confirm_delete.html +9 -0
- tom_common/templates/auth/group_form.html +17 -0
- tom_common/templates/auth/partials/app_user_lists.html +5 -0
- tom_common/templates/auth/partials/group_list.html +23 -0
- tom_common/templates/auth/partials/user_list.html +33 -0
- tom_common/templates/auth/user_confirm_change_password.html +11 -0
- tom_common/templates/auth/user_confirm_delete.html +10 -0
- tom_common/templates/auth/user_list.html +9 -0
- tom_common/templates/bootstrap4_overrides/pagination.html +42 -0
- tom_common/templates/comments/form.html +16 -0
- tom_common/templates/comments/list.html +23 -0
- tom_common/templates/django_comments/comment_confirm_delete.html +11 -0
- tom_common/templates/django_filters/widgets/multiwidget.html +10 -0
- tom_common/templates/registration/login.html +16 -0
- tom_common/templates/tom_common/base.html +76 -0
- tom_common/templates/tom_common/change_user_password.html +14 -0
- tom_common/templates/tom_common/create_user.html +27 -0
- tom_common/templates/tom_common/index.html +50 -0
- tom_common/templates/tom_common/navbar_content.html +41 -0
- tom_common/templates/tom_common/partials/app_profiles.html +23 -0
- tom_common/templates/tom_common/partials/confirm_user_delete.html +24 -0
- tom_common/templates/tom_common/partials/copy_button.html +19 -0
- tom_common/templates/tom_common/partials/include_app_partial.html +7 -0
- tom_common/templates/tom_common/partials/navbar_app_addons.html +4 -0
- tom_common/templates/tom_common/partials/navbar_login.html +18 -0
- tom_common/templates/tom_common/partials/user_data.html +32 -0
- tom_common/templates/tom_common/user_profile.html +16 -0
- tom_common/templatetags/__init__.py +0 -0
- tom_common/templatetags/bootstrap4_overrides.py +36 -0
- tom_common/templatetags/tom_common_extras.py +197 -0
- tom_common/templatetags/user_extras.py +119 -0
- tom_common/tests.py +620 -0
- tom_common/urls.py +74 -0
- tom_common/views.py +335 -0
- tom_dataproducts/__init__.py +0 -0
- tom_dataproducts/admin.py +7 -0
- tom_dataproducts/alertstreams/__init__.py +0 -0
- tom_dataproducts/alertstreams/hermes.py +413 -0
- tom_dataproducts/api_views.py +94 -0
- tom_dataproducts/apps.py +5 -0
- tom_dataproducts/data_processor.py +124 -0
- tom_dataproducts/exceptions.py +2 -0
- tom_dataproducts/filters.py +52 -0
- tom_dataproducts/forms.py +66 -0
- tom_dataproducts/hooks.py +24 -0
- tom_dataproducts/management/__init__.py +0 -0
- tom_dataproducts/management/commands/__init__.py +0 -0
- tom_dataproducts/management/commands/downloaddata.py +19 -0
- tom_dataproducts/management/commands/updatereduceddata.py +49 -0
- tom_dataproducts/migrations/0001_initial.py +77 -0
- tom_dataproducts/migrations/0004_auto_20190626_0904.py +23 -0
- tom_dataproducts/migrations/0005_auto_20190704_1010.py +29 -0
- tom_dataproducts/migrations/0006_auto_20190912_2013.py +18 -0
- tom_dataproducts/migrations/0007_manual_20191016_rename_type.py +37 -0
- tom_dataproducts/migrations/0008_auto_20191205_1952.py +27 -0
- tom_dataproducts/migrations/0009_auto_20210204_2221.py +18 -0
- tom_dataproducts/migrations/0010_manual_20210305_fix_spectroscopy.py +43 -0
- tom_dataproducts/migrations/0011_reduceddatum_message.py +19 -0
- tom_dataproducts/migrations/0012_alter_reduceddatum_data_product_and_more.py +29 -0
- tom_dataproducts/migrations/0013_alter_reduceddatum_message.py +19 -0
- tom_dataproducts/migrations/0014_alter_reduceddatum_timestamp.py +19 -0
- tom_dataproducts/migrations/__init__.py +0 -0
- tom_dataproducts/models.py +420 -0
- tom_dataproducts/processors/__init__.py +0 -0
- tom_dataproducts/processors/atlas_processor.py +92 -0
- tom_dataproducts/processors/data_serializers.py +38 -0
- tom_dataproducts/processors/panstarrs_processor.py +98 -0
- tom_dataproducts/processors/photometry_processor.py +65 -0
- tom_dataproducts/processors/spectroscopy_processor.py +137 -0
- tom_dataproducts/serializers.py +132 -0
- tom_dataproducts/sharing.py +379 -0
- tom_dataproducts/single_target_data_service/__init__.py +0 -0
- tom_dataproducts/single_target_data_service/atlas.py +173 -0
- tom_dataproducts/single_target_data_service/panstarrs_service/__init__.py +0 -0
- tom_dataproducts/single_target_data_service/panstarrs_service/panstarrs.py +235 -0
- tom_dataproducts/single_target_data_service/panstarrs_service/panstarrs_api.py +170 -0
- tom_dataproducts/single_target_data_service/panstarrs_service/tests.py +9 -0
- tom_dataproducts/single_target_data_service/single_target_data_service.py +145 -0
- tom_dataproducts/static/tom_dataproducts/img/placeholder.png +0 -0
- tom_dataproducts/static/tom_dataproducts/photometry_sample.csv +5 -0
- tom_dataproducts/static/tom_dataproducts/spectrum_sample.csv +7 -0
- tom_dataproducts/tasks.py +103 -0
- tom_dataproducts/templates/tom_dataproducts/add_product_to_group.html +12 -0
- tom_dataproducts/templates/tom_dataproducts/dataproduct_confirm_delete.html +12 -0
- tom_dataproducts/templates/tom_dataproducts/dataproduct_list.html +94 -0
- tom_dataproducts/templates/tom_dataproducts/dataproductgroup_confirm_delete.html +11 -0
- tom_dataproducts/templates/tom_dataproducts/dataproductgroup_detail.html +20 -0
- tom_dataproducts/templates/tom_dataproducts/dataproductgroup_form.html +12 -0
- tom_dataproducts/templates/tom_dataproducts/dataproductgroup_list.html +18 -0
- tom_dataproducts/templates/tom_dataproducts/partials/dataproduct_list_for_target.html +75 -0
- tom_dataproducts/templates/tom_dataproducts/partials/js9_button.html +1 -0
- tom_dataproducts/templates/tom_dataproducts/partials/js9_scripts.html +21 -0
- tom_dataproducts/templates/tom_dataproducts/partials/photometry_datalist_for_target.html +125 -0
- tom_dataproducts/templates/tom_dataproducts/partials/photometry_for_target.html +11 -0
- tom_dataproducts/templates/tom_dataproducts/partials/query_single_target_data_service.html +12 -0
- tom_dataproducts/templates/tom_dataproducts/partials/recent_photometry.html +29 -0
- tom_dataproducts/templates/tom_dataproducts/partials/reduceddatum_sparkline.html +3 -0
- tom_dataproducts/templates/tom_dataproducts/partials/saved_dataproduct_list_for_observation.html +37 -0
- tom_dataproducts/templates/tom_dataproducts/partials/spectroscopy_for_target.html +4 -0
- tom_dataproducts/templates/tom_dataproducts/partials/unsaved_dataproduct_list_for_observation.html +27 -0
- tom_dataproducts/templates/tom_dataproducts/partials/update_broker_data_button.html +1 -0
- tom_dataproducts/templates/tom_dataproducts/partials/upload_dataproduct.html +12 -0
- tom_dataproducts/templates/tom_dataproducts/single_target_data_service_form.html +24 -0
- tom_dataproducts/templates/tom_dataproducts/upload_reduced_data.html +12 -0
- tom_dataproducts/templatetags/__init__.py +0 -0
- tom_dataproducts/templatetags/dataproduct_extras.py +520 -0
- tom_dataproducts/tests/__init__.py +0 -0
- tom_dataproducts/tests/test_api.py +197 -0
- tom_dataproducts/tests/test_atlas.py +52 -0
- tom_dataproducts/tests/test_data/test_atlas_fp.csv +33 -0
- tom_dataproducts/tests/test_data/test_lightcurve.csv +4 -0
- tom_dataproducts/tests/test_data/test_spectrum.csv +3 -0
- tom_dataproducts/tests/test_data/test_spectrum.fits +231 -1
- tom_dataproducts/tests/test_sharing.py +173 -0
- tom_dataproducts/tests/tests.py +944 -0
- tom_dataproducts/urls.py +34 -0
- tom_dataproducts/utils.py +34 -0
- tom_dataproducts/views.py +536 -0
- tom_dataservices/__init__.py +0 -0
- tom_dataservices/admin.py +3 -0
- tom_dataservices/apps.py +33 -0
- tom_dataservices/data_services/lsst.py +133 -0
- tom_dataservices/data_services/tns.py +209 -0
- tom_dataservices/dataservices.py +286 -0
- tom_dataservices/forms.py +50 -0
- tom_dataservices/migrations/0001_initial.py +26 -0
- tom_dataservices/migrations/__init__.py +0 -0
- tom_dataservices/models.py +24 -0
- tom_dataservices/templates/tom_dataservices/dataservicequery_confirm_delete.html +9 -0
- tom_dataservices/templates/tom_dataservices/partials/catalog_query_menu.html +11 -0
- tom_dataservices/templates/tom_dataservices/partials/navbar_list.html +14 -0
- tom_dataservices/templates/tom_dataservices/partials/query_results_table.html +21 -0
- tom_dataservices/templates/tom_dataservices/query_form.html +58 -0
- tom_dataservices/templates/tom_dataservices/query_list.html +49 -0
- tom_dataservices/templates/tom_dataservices/query_result.html +45 -0
- tom_dataservices/templates/tom_dataservices/tns/partials/tns_query_results_table.html +24 -0
- tom_dataservices/templates/tom_dataservices/tns/partials/tns_simple_form.html +2 -0
- tom_dataservices/templatetags/dataservices_extras.py +22 -0
- tom_dataservices/tests/__init__.py +0 -0
- tom_dataservices/tests/test_api.py +5 -0
- tom_dataservices/tests/tests.py +113 -0
- tom_dataservices/urls.py +17 -0
- tom_dataservices/views.py +351 -0
- tom_observations/__init__.py +0 -0
- tom_observations/admin.py +26 -0
- tom_observations/api_views.py +186 -0
- tom_observations/apps.py +5 -0
- tom_observations/cadence.py +82 -0
- tom_observations/cadences/__init__.py +0 -0
- tom_observations/cadences/resume_cadence_after_failure.py +115 -0
- tom_observations/cadences/retry_failed_observations.py +66 -0
- tom_observations/facilities/__init__.py +0 -0
- tom_observations/facilities/blanco.py +233 -0
- tom_observations/facilities/gemini.py +523 -0
- tom_observations/facilities/lco.py +1140 -0
- tom_observations/facilities/lco_redirect.py +50 -0
- tom_observations/facilities/lt.py +70 -0
- tom_observations/facilities/manual.py +125 -0
- tom_observations/facilities/ocs.py +1630 -0
- tom_observations/facilities/soar.py +265 -0
- tom_observations/facility.py +635 -0
- tom_observations/forms.py +70 -0
- tom_observations/management/__init__.py +0 -0
- tom_observations/management/commands/__init__.py +0 -0
- tom_observations/management/commands/runcadencestrategies.py +51 -0
- tom_observations/management/commands/updatestatus.py +55 -0
- tom_observations/migrations/0001_initial.py +32 -0
- tom_observations/migrations/0002_auto_20190306_2343.py +23 -0
- tom_observations/migrations/0003_auto_20190503_2318.py +18 -0
- tom_observations/migrations/0004_observationgroup.py +23 -0
- tom_observations/migrations/0005_auto_20191210_0007.py +17 -0
- tom_observations/migrations/0006_observationgroup_cadence_strategy.py +18 -0
- tom_observations/migrations/0007_observationstrategy.py +24 -0
- tom_observations/migrations/0008_observationgroup_cadence_parameters.py +18 -0
- tom_observations/migrations/0009_observationrecord_user.py +21 -0
- tom_observations/migrations/0010_manual_create_dynamic_cadence.py +67 -0
- tom_observations/migrations/0011_auto_20200917_0306.py +26 -0
- tom_observations/migrations/0012_auto_20210205_1819.py +23 -0
- tom_observations/migrations/0013_facility.py +34 -0
- tom_observations/migrations/0014_alter_facility_orbit.py +18 -0
- tom_observations/migrations/0015_remove_facility_mpc_site_code_and_more.py +73 -0
- tom_observations/migrations/0016_alter_facility_options.py +17 -0
- tom_observations/migrations/__init__.py +0 -0
- tom_observations/models.py +335 -0
- tom_observations/observation_template.py +56 -0
- tom_observations/serializers.py +84 -0
- tom_observations/static/tom_observations/css/main.css +24 -0
- tom_observations/templates/tom_observations/existing_observation_confirm.html +7 -0
- tom_observations/templates/tom_observations/facility_status.html +10 -0
- tom_observations/templates/tom_observations/observation_form.html +64 -0
- tom_observations/templates/tom_observations/observation_list.html +89 -0
- tom_observations/templates/tom_observations/observationgroup_confirm_delete.html +12 -0
- tom_observations/templates/tom_observations/observationgroup_form.html +9 -0
- tom_observations/templates/tom_observations/observationgroup_list.html +48 -0
- tom_observations/templates/tom_observations/observationrecord_detail.html +90 -0
- tom_observations/templates/tom_observations/observationtemplate_confirm_delete.html +9 -0
- tom_observations/templates/tom_observations/observationtemplate_form.html +10 -0
- tom_observations/templates/tom_observations/observationtemplate_list.html +50 -0
- tom_observations/templates/tom_observations/observationupdate_form.html +7 -0
- tom_observations/templates/tom_observations/partials/existing_observation_form.html +3 -0
- tom_observations/templates/tom_observations/partials/facility_map.html +1 -0
- tom_observations/templates/tom_observations/partials/facility_observation_form.html +4 -0
- tom_observations/templates/tom_observations/partials/facility_status.html +33 -0
- tom_observations/templates/tom_observations/partials/observation_distribution.html +1 -0
- tom_observations/templates/tom_observations/partials/observation_list.html +25 -0
- tom_observations/templates/tom_observations/partials/observation_plan.html +4 -0
- tom_observations/templates/tom_observations/partials/observation_type_tabs.html +10 -0
- tom_observations/templates/tom_observations/partials/observationtemplate_from_record.html +1 -0
- tom_observations/templates/tom_observations/partials/observationtemplate_run.html +6 -0
- tom_observations/templates/tom_observations/partials/observing_buttons.html +7 -0
- tom_observations/templates/tom_observations/partials/update_observation_id_form.html +2 -0
- tom_observations/templates/tom_observations/partials/update_status_button.html +1 -0
- tom_observations/templatetags/__init__.py +0 -0
- tom_observations/templatetags/observation_extras.py +344 -0
- tom_observations/tests/__init__.py +0 -0
- tom_observations/tests/facilities/__init__.py +0 -0
- tom_observations/tests/facilities/test_gemini.py +32 -0
- tom_observations/tests/facilities/test_lco.py +717 -0
- tom_observations/tests/facilities/test_ocs.py +266 -0
- tom_observations/tests/facilities/test_soar.py +195 -0
- tom_observations/tests/factories.py +92 -0
- tom_observations/tests/test_api.py +295 -0
- tom_observations/tests/test_cadence.py +141 -0
- tom_observations/tests/test_credentials.py +164 -0
- tom_observations/tests/tests.py +493 -0
- tom_observations/tests/utils.py +161 -0
- tom_observations/urls.py +36 -0
- tom_observations/utils.py +186 -0
- tom_observations/views.py +815 -0
- tom_observations/widgets.py +50 -0
- tom_setup/__init__.py +0 -0
- tom_setup/apps.py +5 -0
- tom_setup/management/__init__.py +0 -0
- tom_setup/management/commands/__init__.py +0 -0
- tom_setup/management/commands/tom_setup.py +296 -0
- tom_setup/templates/tom_setup/css.tmpl +26 -0
- tom_setup/templates/tom_setup/models.tmpl +18 -0
- tom_setup/templates/tom_setup/settings.tmpl +383 -0
- tom_setup/templates/tom_setup/urls.tmpl +20 -0
- tom_targets/__init__.py +1 -0
- tom_targets/admin.py +34 -0
- tom_targets/api_views.py +127 -0
- tom_targets/apps.py +9 -0
- tom_targets/base_models.py +609 -0
- tom_targets/fields.py +14 -0
- tom_targets/filters.py +142 -0
- tom_targets/forms.py +307 -0
- tom_targets/groups.py +260 -0
- tom_targets/management/__init__.py +0 -0
- tom_targets/management/commands/__init__.py +0 -0
- tom_targets/management/commands/converttargetextras.py +179 -0
- tom_targets/management/commands/setdefaultextras.py +55 -0
- tom_targets/merge.py +90 -0
- tom_targets/migrations/0001_initial.py +68 -0
- tom_targets/migrations/0002_auto_20190115_2102.py +23 -0
- tom_targets/migrations/0002_auto_20190117_2248.py +23 -0
- tom_targets/migrations/0003_merge_20190123_1754.py +14 -0
- tom_targets/migrations/0004_auto_20190123_2010.py +31 -0
- tom_targets/migrations/0005_auto_20190214_1722.py +28 -0
- tom_targets/migrations/0006_auto_20190403_1659.py +23 -0
- tom_targets/migrations/0007_auto_20190423_1455.py +18 -0
- tom_targets/migrations/0007_auto_20190503_2318.py +18 -0
- tom_targets/migrations/0007_auto_20190515_0047.py +18 -0
- tom_targets/migrations/0008_merge_20190515_0914.py +14 -0
- tom_targets/migrations/0008_merge_20190520_1645.py +14 -0
- tom_targets/migrations/0009_auto_20190605_1656.py +17 -0
- tom_targets/migrations/0010_auto_20190715_1657.py +17 -0
- tom_targets/migrations/0010_merge_20190612_1227.py +14 -0
- tom_targets/migrations/0011_merge_20190731_1821.py +14 -0
- tom_targets/migrations/0012_target_perihdist.py +18 -0
- tom_targets/migrations/0013_manual_20190916_multiple_names.py +74 -0
- tom_targets/migrations/0014_auto_20190923_1827.py +33 -0
- tom_targets/migrations/0015_auto_20190923_2233.py +23 -0
- tom_targets/migrations/0016_auto_20191211_1707.py +18 -0
- tom_targets/migrations/0017_auto_20200130_2350.py +23 -0
- tom_targets/migrations/0018_auto_20200714_1832.py +18 -0
- tom_targets/migrations/0019_auto_20210811_0018.py +17 -0
- tom_targets/migrations/0020_alter_targetname_created_alter_targetname_modified.py +23 -0
- tom_targets/migrations/0021_rename_target_basetarget_alter_basetarget_options.py +23 -0
- tom_targets/migrations/0022_persistentshare.py +30 -0
- tom_targets/migrations/0023_alter_basetarget_created.py +18 -0
- tom_targets/migrations/0024_basetarget_permissions.py +18 -0
- tom_targets/migrations/0025_auto_20250206_2017.py +53 -0
- tom_targets/migrations/0026_alter_basetarget_permissions.py +18 -0
- tom_targets/migrations/0027_alter_basetarget_epoch_of_elements_and_more.py +33 -0
- tom_targets/migrations/0028_basetarget_abs_mag_basetarget_slope_and_more.py +23 -0
- tom_targets/migrations/0029_alter_basetarget_permissions.py +19 -0
- tom_targets/migrations/0030_alter_basetarget_slope.py +18 -0
- tom_targets/migrations/__init__.py +0 -0
- tom_targets/models.py +226 -0
- tom_targets/permissions.py +37 -0
- tom_targets/persistent_sharing_serializers.py +28 -0
- tom_targets/seed.py +123 -0
- tom_targets/serializers.py +181 -0
- tom_targets/sharing.py +123 -0
- tom_targets/signals/__init__.py +0 -0
- tom_targets/signals/handlers.py +23 -0
- tom_targets/static/tom_targets/css/main.css +17 -0
- tom_targets/static/tom_targets/target_import.csv +3 -0
- tom_targets/templates/tom_targets/partials/aladin_finderchart.html +178 -0
- tom_targets/templates/tom_targets/partials/aladin_skymap.html +127 -0
- tom_targets/templates/tom_targets/partials/app_tab_divs.html +6 -0
- tom_targets/templates/tom_targets/partials/app_tabs.html +6 -0
- tom_targets/templates/tom_targets/partials/create_persistent_share.html +90 -0
- tom_targets/templates/tom_targets/partials/module_buttons.html +4 -0
- tom_targets/templates/tom_targets/partials/moon_distance.html +3 -0
- tom_targets/templates/tom_targets/partials/persistent_share_table.html +59 -0
- tom_targets/templates/tom_targets/partials/recent_targets.html +38 -0
- tom_targets/templates/tom_targets/partials/recently_updated_targets.html +23 -0
- tom_targets/templates/tom_targets/partials/target_buttons.html +9 -0
- tom_targets/templates/tom_targets/partials/target_data.html +44 -0
- tom_targets/templates/tom_targets/partials/target_feature.html +17 -0
- tom_targets/templates/tom_targets/partials/target_groups.html +37 -0
- tom_targets/templates/tom_targets/partials/target_merge_fields.html +38 -0
- tom_targets/templates/tom_targets/partials/target_plan.html +11 -0
- tom_targets/templates/tom_targets/partials/target_table.html +61 -0
- tom_targets/templates/tom_targets/partials/target_unknown_statuses.html +5 -0
- tom_targets/templates/tom_targets/partials/targetlist_select.html +55 -0
- tom_targets/templates/tom_targets/target_confirm_delete.html +12 -0
- tom_targets/templates/tom_targets/target_detail.html +133 -0
- tom_targets/templates/tom_targets/target_facility_selection.html +68 -0
- tom_targets/templates/tom_targets/target_form.html +78 -0
- tom_targets/templates/tom_targets/target_group_share.html +70 -0
- tom_targets/templates/tom_targets/target_grouping.html +48 -0
- tom_targets/templates/tom_targets/target_import.html +26 -0
- tom_targets/templates/tom_targets/target_list.html +68 -0
- tom_targets/templates/tom_targets/target_manage_persistent_shares.html +20 -0
- tom_targets/templates/tom_targets/target_merge.html +24 -0
- tom_targets/templates/tom_targets/target_share.html +89 -0
- tom_targets/templates/tom_targets/targetlist_confirm_delete.html +11 -0
- tom_targets/templates/tom_targets/targetlist_form.html +9 -0
- tom_targets/templatetags/__init__.py +0 -0
- tom_targets/templatetags/targets_extras.py +569 -0
- tom_targets/tests/__init__.py +0 -0
- tom_targets/tests/factories.py +63 -0
- tom_targets/tests/test_api.py +303 -0
- tom_targets/tests/tests.py +2066 -0
- tom_targets/urls.py +59 -0
- tom_targets/utils.py +156 -0
- tom_targets/validators.py +23 -0
- tom_targets/views.py +1124 -0
- tom_targets/viewsets.py +49 -0
- tomtoolkit-2.30.0a0.dist-info/METADATA +164 -0
- tomtoolkit-2.30.0a0.dist-info/RECORD +483 -0
- tomtoolkit-2.30.0a0.dist-info/WHEEL +4 -0
- tomtoolkit-2.30.0a0.dist-info/licenses/LICENSE +674 -0
|
@@ -0,0 +1,636 @@
|
|
|
1
|
+
import logging
|
|
2
|
+
import requests
|
|
3
|
+
from urllib.parse import urlencode
|
|
4
|
+
|
|
5
|
+
from astropy.time import Time, TimezoneInfo
|
|
6
|
+
from crispy_forms.layout import Column, Fieldset, HTML, Layout, Row
|
|
7
|
+
from django import forms
|
|
8
|
+
from django.core.cache import cache
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
from tom_alerts.alerts import GenericAlert, GenericBroker, GenericQueryForm
|
|
12
|
+
from tom_targets.models import Target
|
|
13
|
+
from tom_dataproducts.models import ReducedDatum
|
|
14
|
+
|
|
15
|
+
logger = logging.getLogger(__name__)
|
|
16
|
+
|
|
17
|
+
ALERCE_URL = 'https://alerce.online'
|
|
18
|
+
ALERCE_SEARCH_URL = 'https://api.alerce.online/ztf/v1'
|
|
19
|
+
ALERCE_CLASSES_URL = f'{ALERCE_SEARCH_URL}/classifiers'
|
|
20
|
+
|
|
21
|
+
SORT_CHOICES = [(None, 'None'),
|
|
22
|
+
('oid', 'Object ID'),
|
|
23
|
+
('probability', 'Classifier Probability'),
|
|
24
|
+
('ndet', 'Number of Detections'),
|
|
25
|
+
('firstmjd', 'First Detection'),
|
|
26
|
+
('lastmjd', 'Last Detection'),
|
|
27
|
+
('deltamjd', 'Delta MJD (days)')
|
|
28
|
+
]
|
|
29
|
+
|
|
30
|
+
SORT_ORDER = [(None, 'None'),
|
|
31
|
+
('ASC', 'Ascending'),
|
|
32
|
+
('DESC', 'Descending')]
|
|
33
|
+
FILTERS = {1: 'g', 2: 'r', 3: 'i'}
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
class ALeRCEQueryForm(GenericQueryForm):
|
|
37
|
+
|
|
38
|
+
oid = forms.CharField(
|
|
39
|
+
required=False,
|
|
40
|
+
label='Object ID',
|
|
41
|
+
)
|
|
42
|
+
ndet = forms.IntegerField(
|
|
43
|
+
required=False,
|
|
44
|
+
label='Detections Lower',
|
|
45
|
+
widget=forms.TextInput(attrs={'placeholder': 'Min number of detections'})
|
|
46
|
+
)
|
|
47
|
+
ranking = forms.IntegerField(
|
|
48
|
+
required=False,
|
|
49
|
+
label='Ranking',
|
|
50
|
+
widget=forms.TextInput(attrs={'placeholder': 'Class ordering by probability'})
|
|
51
|
+
)
|
|
52
|
+
lc_classifier = forms.ChoiceField(
|
|
53
|
+
required=False,
|
|
54
|
+
label='Light Curve Classifier Class',
|
|
55
|
+
choices=[], # Choices are populated dynamically in the constructor
|
|
56
|
+
)
|
|
57
|
+
p_lc_classifier = forms.FloatField(
|
|
58
|
+
required=False,
|
|
59
|
+
label='Light Curve Classifier Probability'
|
|
60
|
+
)
|
|
61
|
+
lc_classifier_top = forms.ChoiceField(
|
|
62
|
+
required=False,
|
|
63
|
+
label='Light Curve Classifier Top Class',
|
|
64
|
+
choices=[], # Choices are populated dynamically in the constructor
|
|
65
|
+
)
|
|
66
|
+
p_lc_classifier_top = forms.FloatField(
|
|
67
|
+
required=False,
|
|
68
|
+
label='Light Curve Classifier Top Probability'
|
|
69
|
+
)
|
|
70
|
+
lc_classifier_bhrf = forms.ChoiceField(
|
|
71
|
+
required=False,
|
|
72
|
+
label='Light Curve Classifier BHRF Forced Phot Class',
|
|
73
|
+
choices=[], # Choices are populated dynamically in the constructor
|
|
74
|
+
)
|
|
75
|
+
p_lc_classifier_bhrf = forms.FloatField(
|
|
76
|
+
required=False,
|
|
77
|
+
label='Light Curve Classifier BHRF Forced Phot Probability'
|
|
78
|
+
)
|
|
79
|
+
lc_classifier_bhrf_top = forms.ChoiceField(
|
|
80
|
+
required=False,
|
|
81
|
+
label='Light Curve Classifier BHRF Forced Phot Top Class',
|
|
82
|
+
choices=[], # Choices are populated dynamically in the constructor
|
|
83
|
+
)
|
|
84
|
+
p_lc_classifier_bhrf_top = forms.FloatField(
|
|
85
|
+
required=False,
|
|
86
|
+
label='Light Curve Classifier BHRF Forced Phot Top Probability'
|
|
87
|
+
)
|
|
88
|
+
lc_classifier_atat = forms.ChoiceField(
|
|
89
|
+
required=False,
|
|
90
|
+
label='Light Curve Classifier ATAT Forced Phot Beta Class',
|
|
91
|
+
choices=[], # Choices are populated dynamically in the constructor
|
|
92
|
+
)
|
|
93
|
+
p_lc_classifier_atat = forms.FloatField(
|
|
94
|
+
required=False,
|
|
95
|
+
label='Light Curve Classifier ATAT Forced Phot Beta Probability'
|
|
96
|
+
)
|
|
97
|
+
stamp_classifier = forms.ChoiceField(
|
|
98
|
+
required=False,
|
|
99
|
+
label='Stamp Class',
|
|
100
|
+
choices=[], # Choices are populated dynamically in the constructor
|
|
101
|
+
)
|
|
102
|
+
p_stamp_classifier = forms.FloatField(
|
|
103
|
+
required=False,
|
|
104
|
+
label='Stamp Classifier Probability'
|
|
105
|
+
)
|
|
106
|
+
stamp_classifier_beta = forms.ChoiceField(
|
|
107
|
+
required=False,
|
|
108
|
+
label='Stamp Classifier 2025 Beta Class',
|
|
109
|
+
choices=[], # Choices are populated dynamically in the constructor
|
|
110
|
+
)
|
|
111
|
+
p_stamp_classifier_beta = forms.FloatField(
|
|
112
|
+
required=False,
|
|
113
|
+
label='Stamp Classifier 2025 Beta Probability'
|
|
114
|
+
)
|
|
115
|
+
ra = forms.FloatField(
|
|
116
|
+
required=False,
|
|
117
|
+
label='RA',
|
|
118
|
+
widget=forms.TextInput(attrs={'placeholder': 'RA (Degrees)'})
|
|
119
|
+
)
|
|
120
|
+
dec = forms.FloatField(
|
|
121
|
+
required=False,
|
|
122
|
+
label='Dec',
|
|
123
|
+
widget=forms.TextInput(attrs={'placeholder': 'Dec (Degrees)'})
|
|
124
|
+
)
|
|
125
|
+
radius = forms.IntegerField(
|
|
126
|
+
required=False,
|
|
127
|
+
label='Search Radius',
|
|
128
|
+
widget=forms.TextInput(attrs={'placeholder': 'Radius (Arcseconds)'})
|
|
129
|
+
)
|
|
130
|
+
firstmjd__gt = forms.FloatField(
|
|
131
|
+
required=False,
|
|
132
|
+
label='Min date of first detection ',
|
|
133
|
+
widget=forms.TextInput(attrs={'placeholder': 'Date (MJD)'}),
|
|
134
|
+
min_value=0.0
|
|
135
|
+
)
|
|
136
|
+
firstmjd__lt = forms.FloatField(
|
|
137
|
+
required=False,
|
|
138
|
+
label='Max date of first detection ',
|
|
139
|
+
widget=forms.TextInput(attrs={'placeholder': 'Date (MJD)'}),
|
|
140
|
+
min_value=0.0
|
|
141
|
+
)
|
|
142
|
+
lastmjd__gt = forms.FloatField(
|
|
143
|
+
required=False,
|
|
144
|
+
label='Min date of last detection',
|
|
145
|
+
widget=forms.TextInput(attrs={'placeholder': 'Date (MJD)'}),
|
|
146
|
+
min_value=0.0
|
|
147
|
+
)
|
|
148
|
+
lastmjd__lt = forms.FloatField(
|
|
149
|
+
required=False,
|
|
150
|
+
label='Max date of last detection',
|
|
151
|
+
widget=forms.TextInput(attrs={'placeholder': 'Date (MJD)'}),
|
|
152
|
+
min_value=0.0
|
|
153
|
+
)
|
|
154
|
+
order_by = forms.ChoiceField(
|
|
155
|
+
choices=SORT_CHOICES,
|
|
156
|
+
required=False,
|
|
157
|
+
label='Sort By'
|
|
158
|
+
)
|
|
159
|
+
order_mode = forms.ChoiceField(
|
|
160
|
+
choices=SORT_ORDER,
|
|
161
|
+
required=False,
|
|
162
|
+
label='Sort Order'
|
|
163
|
+
)
|
|
164
|
+
max_pages = forms.TypedChoiceField(
|
|
165
|
+
choices=[(1, 1), (5, 5), (10, 10), (20, 20)],
|
|
166
|
+
required=False,
|
|
167
|
+
coerce=int,
|
|
168
|
+
label='Maximum pages to retrieve'
|
|
169
|
+
)
|
|
170
|
+
|
|
171
|
+
def __init__(self, *args, **kwargs):
|
|
172
|
+
super().__init__(*args, **kwargs)
|
|
173
|
+
|
|
174
|
+
self.fields['lc_classifier'].choices = self._get_light_curve_classifier_choices()
|
|
175
|
+
self.fields['lc_classifier_top'].choices = self._get_light_curve_classifier_top_choices()
|
|
176
|
+
self.fields['lc_classifier_bhrf'].choices = self._get_light_curve_classifier_bhrf_choices()
|
|
177
|
+
self.fields['lc_classifier_bhrf_top'].choices = self._get_light_curve_classifier_bhrf_top_choices()
|
|
178
|
+
self.fields['lc_classifier_atat'].choices = self._get_light_curve_classifier_atat_choices()
|
|
179
|
+
self.fields['stamp_classifier'].choices = self._get_stamp_classifier_choices()
|
|
180
|
+
self.fields['stamp_classifier_beta'].choices = self._get_stamp_classifier_beta_choices()
|
|
181
|
+
|
|
182
|
+
self.helper.layout = Layout(
|
|
183
|
+
HTML('''
|
|
184
|
+
<p>
|
|
185
|
+
Please see the <a href="http://alerce.science/" target="_blank">ALeRCE homepage</a> for information
|
|
186
|
+
about the ALeRCE filters.
|
|
187
|
+
'''),
|
|
188
|
+
self.common_layout,
|
|
189
|
+
'oid',
|
|
190
|
+
Fieldset(
|
|
191
|
+
'Classification Filters',
|
|
192
|
+
Row(
|
|
193
|
+
Column('lc_classifier'),
|
|
194
|
+
Column('p_lc_classifier')
|
|
195
|
+
),
|
|
196
|
+
Row(
|
|
197
|
+
Column('lc_classifier_top'),
|
|
198
|
+
Column('p_lc_classifier_top')
|
|
199
|
+
),
|
|
200
|
+
Row(
|
|
201
|
+
Column('lc_classifier_bhrf'),
|
|
202
|
+
Column('p_lc_classifier_bhrf')
|
|
203
|
+
),
|
|
204
|
+
Row(
|
|
205
|
+
Column('lc_classifier_bhrf_top'),
|
|
206
|
+
Column('p_lc_classifier_bhrf_top')
|
|
207
|
+
),
|
|
208
|
+
Row(
|
|
209
|
+
Column('lc_classifier_atat'),
|
|
210
|
+
Column('p_lc_classifier_atat')
|
|
211
|
+
),
|
|
212
|
+
Row(
|
|
213
|
+
Column('stamp_classifier'),
|
|
214
|
+
Column('p_stamp_classifier')
|
|
215
|
+
),
|
|
216
|
+
Row(
|
|
217
|
+
Column('stamp_classifier_beta'),
|
|
218
|
+
Column('p_stamp_classifier_beta')
|
|
219
|
+
)
|
|
220
|
+
),
|
|
221
|
+
Fieldset(
|
|
222
|
+
'Location Filters',
|
|
223
|
+
Row(
|
|
224
|
+
Column('ra'),
|
|
225
|
+
Column('dec'),
|
|
226
|
+
Column('radius'),
|
|
227
|
+
)
|
|
228
|
+
),
|
|
229
|
+
Fieldset(
|
|
230
|
+
'Time Filters',
|
|
231
|
+
Row(
|
|
232
|
+
Column('firstmjd__gt'),
|
|
233
|
+
Column('firstmjd__lt'),
|
|
234
|
+
),
|
|
235
|
+
Row(
|
|
236
|
+
Column('lastmjd__gt'),
|
|
237
|
+
Column('lastmjd__lt'),
|
|
238
|
+
)
|
|
239
|
+
),
|
|
240
|
+
Fieldset(
|
|
241
|
+
'Other Filters',
|
|
242
|
+
Row(
|
|
243
|
+
Column('ranking'),
|
|
244
|
+
Column('ndet')
|
|
245
|
+
)
|
|
246
|
+
),
|
|
247
|
+
Fieldset(
|
|
248
|
+
'General Parameters',
|
|
249
|
+
Row(
|
|
250
|
+
Column('order_by'),
|
|
251
|
+
Column('order_mode'),
|
|
252
|
+
),
|
|
253
|
+
Row(
|
|
254
|
+
Column('max_pages')
|
|
255
|
+
)
|
|
256
|
+
),
|
|
257
|
+
)
|
|
258
|
+
|
|
259
|
+
@staticmethod
|
|
260
|
+
def _get_classifiers():
|
|
261
|
+
cached_classifiers = cache.get('alerce_classifiers')
|
|
262
|
+
|
|
263
|
+
if not cached_classifiers:
|
|
264
|
+
response = requests.get(ALERCE_CLASSES_URL)
|
|
265
|
+
response.raise_for_status()
|
|
266
|
+
cached_classifiers = response.json()
|
|
267
|
+
|
|
268
|
+
return cached_classifiers
|
|
269
|
+
|
|
270
|
+
@staticmethod
|
|
271
|
+
def _get_light_curve_classifier_choices():
|
|
272
|
+
light_curve_classifiers = []
|
|
273
|
+
version = '1.0.0'
|
|
274
|
+
current_version = version
|
|
275
|
+
|
|
276
|
+
# Grab all classifiers available in ALeRCE
|
|
277
|
+
all_classifiers = ALeRCEQueryForm._get_classifiers()
|
|
278
|
+
|
|
279
|
+
for classifier in all_classifiers:
|
|
280
|
+
if classifier['classifier_name'] == 'lc_classifier':
|
|
281
|
+
new_version = classifier['classifier_version'].split('_')[-1]
|
|
282
|
+
if new_version > version:
|
|
283
|
+
light_curve_classifiers = [(c, c) for c in classifier['classes']]
|
|
284
|
+
current_version = new_version
|
|
285
|
+
|
|
286
|
+
if current_version == version:
|
|
287
|
+
for classifier in all_classifiers:
|
|
288
|
+
split_class = classifier['classifier_name'].split('_')
|
|
289
|
+
if len(split_class) == 3 and split_class[0] == 'lc' and split_class[2] != 'top':
|
|
290
|
+
subclass = split_class[2].capitalize()
|
|
291
|
+
light_curve_classifiers += [(c, f'{subclass} - {c}') for c in classifier['classes']]
|
|
292
|
+
|
|
293
|
+
return [(None, '')] + light_curve_classifiers
|
|
294
|
+
|
|
295
|
+
@staticmethod
|
|
296
|
+
def _get_light_curve_classifier_top_choices():
|
|
297
|
+
light_curve_classifiers = []
|
|
298
|
+
version = '1.0.0'
|
|
299
|
+
|
|
300
|
+
# Grab all classifiers available in ALeRCE
|
|
301
|
+
all_classifiers = ALeRCEQueryForm._get_classifiers()
|
|
302
|
+
|
|
303
|
+
for classifier in all_classifiers:
|
|
304
|
+
if classifier['classifier_name'] == 'lc_classifier_top':
|
|
305
|
+
new_version = classifier['classifier_version'].split('_')[-1]
|
|
306
|
+
if new_version > version:
|
|
307
|
+
light_curve_classifiers = [(c, c) for c in classifier['classes']]
|
|
308
|
+
else:
|
|
309
|
+
light_curve_classifiers = [(c, c) for c in classifier['classes']]
|
|
310
|
+
|
|
311
|
+
return [(None, '')] + light_curve_classifiers
|
|
312
|
+
|
|
313
|
+
@staticmethod
|
|
314
|
+
def _get_light_curve_classifier_bhrf_choices():
|
|
315
|
+
light_curve_classifiers = []
|
|
316
|
+
version = '2.1.0'
|
|
317
|
+
current_version = version
|
|
318
|
+
|
|
319
|
+
# Grab all classifiers available in ALeRCE
|
|
320
|
+
all_classifiers = ALeRCEQueryForm._get_classifiers()
|
|
321
|
+
|
|
322
|
+
for classifier in all_classifiers:
|
|
323
|
+
if classifier['classifier_name'] == 'lc_classifier_BHRF_forced_phot':
|
|
324
|
+
new_version = classifier['classifier_version'].split('_')[-1]
|
|
325
|
+
if new_version > version:
|
|
326
|
+
light_curve_classifiers = [(c, c) for c in classifier['classes']]
|
|
327
|
+
current_version = new_version
|
|
328
|
+
|
|
329
|
+
if current_version == version:
|
|
330
|
+
for classifier in all_classifiers:
|
|
331
|
+
split_class = classifier['classifier_name'].split('_')
|
|
332
|
+
if len(split_class) == 3 and split_class[0] == 'lc' and split_class[2] != 'top':
|
|
333
|
+
subclass = split_class[2].capitalize()
|
|
334
|
+
light_curve_classifiers += [(c, f'{subclass} - {c}') for c in classifier['classes']]
|
|
335
|
+
|
|
336
|
+
return [(None, '')] + light_curve_classifiers
|
|
337
|
+
|
|
338
|
+
@staticmethod
|
|
339
|
+
def _get_light_curve_classifier_bhrf_top_choices():
|
|
340
|
+
light_curve_classifiers = []
|
|
341
|
+
version = '1.0.0'
|
|
342
|
+
|
|
343
|
+
# Grab all classifiers available in ALeRCE
|
|
344
|
+
all_classifiers = ALeRCEQueryForm._get_classifiers()
|
|
345
|
+
|
|
346
|
+
for classifier in all_classifiers:
|
|
347
|
+
if classifier['classifier_name'] == 'lc_classifier_BHRF_forced_phot_top':
|
|
348
|
+
new_version = classifier['classifier_version'].split('_')[-1]
|
|
349
|
+
if new_version > version:
|
|
350
|
+
light_curve_classifiers = [(c, c) for c in classifier['classes']]
|
|
351
|
+
else:
|
|
352
|
+
light_curve_classifiers = [(c, c) for c in classifier['classes']]
|
|
353
|
+
|
|
354
|
+
return [(None, '')] + light_curve_classifiers
|
|
355
|
+
|
|
356
|
+
@staticmethod
|
|
357
|
+
def _get_light_curve_classifier_atat_choices():
|
|
358
|
+
version = 'beta'
|
|
359
|
+
light_curve_classifiers = []
|
|
360
|
+
for classifier in ALeRCEQueryForm._get_classifiers():
|
|
361
|
+
if classifier['classifier_name'] == 'LC_classifier_ATAT_forced_phot(beta)':
|
|
362
|
+
new_version = classifier['classifier_version'].split('_')[-1]
|
|
363
|
+
if new_version > version:
|
|
364
|
+
light_curve_classifiers = [(c, c) for c in classifier['classes']]
|
|
365
|
+
else:
|
|
366
|
+
light_curve_classifiers = [(c, c) for c in classifier['classes']]
|
|
367
|
+
|
|
368
|
+
return [(None, '')] + light_curve_classifiers
|
|
369
|
+
|
|
370
|
+
@staticmethod
|
|
371
|
+
def _get_stamp_classifier_choices():
|
|
372
|
+
version = '1.0.4'
|
|
373
|
+
stamp_classifiers = []
|
|
374
|
+
|
|
375
|
+
for classifier in ALeRCEQueryForm._get_classifiers():
|
|
376
|
+
if classifier['classifier_name'] == 'stamp_classifier':
|
|
377
|
+
new_version = classifier['classifier_version'].split('_')[-1]
|
|
378
|
+
if new_version > version:
|
|
379
|
+
stamp_classifiers = [(c, c) for c in classifier['classes']]
|
|
380
|
+
else:
|
|
381
|
+
stamp_classifiers = [(c, c) for c in classifier['classes']]
|
|
382
|
+
|
|
383
|
+
return [(None, '')] + stamp_classifiers
|
|
384
|
+
|
|
385
|
+
@staticmethod
|
|
386
|
+
def _get_stamp_classifier_beta_choices():
|
|
387
|
+
version = 'beta'
|
|
388
|
+
stamp_classifiers = []
|
|
389
|
+
|
|
390
|
+
for classifier in ALeRCEQueryForm._get_classifiers():
|
|
391
|
+
if classifier['classifier_name'] == 'stamp_classifier_2025_beta':
|
|
392
|
+
new_version = classifier['classifier_version'].split('_')[-1]
|
|
393
|
+
if new_version > version:
|
|
394
|
+
stamp_classifiers = [(c, c) for c in classifier['classes']]
|
|
395
|
+
else:
|
|
396
|
+
stamp_classifiers = [(c, c) for c in classifier['classes']]
|
|
397
|
+
|
|
398
|
+
return [(None, '')] + stamp_classifiers
|
|
399
|
+
|
|
400
|
+
def clean_max_pages(self):
|
|
401
|
+
max_pages = self.cleaned_data['max_pages']
|
|
402
|
+
if not max_pages:
|
|
403
|
+
max_pages = 1
|
|
404
|
+
return max_pages
|
|
405
|
+
|
|
406
|
+
def clean(self):
|
|
407
|
+
cleaned_data = super().clean()
|
|
408
|
+
|
|
409
|
+
# Ensure that all cone search fields are present
|
|
410
|
+
if (any(cleaned_data[k] for k in ['ra', 'dec', 'radius'])
|
|
411
|
+
and not all(cleaned_data[k] for k in ['ra', 'dec', 'radius'])):
|
|
412
|
+
raise forms.ValidationError('All of RA, Dec, and Search Radius must be included to execute a cone search.')
|
|
413
|
+
|
|
414
|
+
# Ensure that only one classification set is filled in
|
|
415
|
+
if (any(cleaned_data.get(k) for k in ['lc_classifier', 'p_lc_classifier'])
|
|
416
|
+
and any(cleaned_data.get(k) for k in ['stamp_classifier', 'p_stamp_classifier'])):
|
|
417
|
+
raise forms.ValidationError('Only one of either light curve or stamp classification may be used as a '
|
|
418
|
+
'filter.')
|
|
419
|
+
|
|
420
|
+
return cleaned_data
|
|
421
|
+
|
|
422
|
+
|
|
423
|
+
class ALeRCEBroker(GenericBroker):
|
|
424
|
+
"""
|
|
425
|
+
The ``ALeRCEBroker`` is the interface to the ALeRCE alert broker.
|
|
426
|
+
|
|
427
|
+
To include the ``ALeRCEBroker`` in your TOM, add the broker module location to your `TOM_ALERT_CLASSES` list in
|
|
428
|
+
your ``settings.py``:
|
|
429
|
+
|
|
430
|
+
.. code-block:: python
|
|
431
|
+
|
|
432
|
+
TOM_ALERT_CLASSES = [
|
|
433
|
+
'tom_alerts.brokers.alerce.ALeRCEBroker',
|
|
434
|
+
...
|
|
435
|
+
]
|
|
436
|
+
|
|
437
|
+
For information regarding the ALeRCE objects
|
|
438
|
+
and classification, please see http://alerce.science.
|
|
439
|
+
"""
|
|
440
|
+
|
|
441
|
+
name = 'ALeRCE'
|
|
442
|
+
form = ALeRCEQueryForm
|
|
443
|
+
|
|
444
|
+
def _clean_classifier_parameters(self, parameters):
|
|
445
|
+
"""
|
|
446
|
+
This method returns a parameter list for a given classifier with a
|
|
447
|
+
cleaned up version of the ALeRCE classifier names.
|
|
448
|
+
The function finds the ALeRCE classifier name (predefined here) and
|
|
449
|
+
matches it to the TOM Toolkit ALeRCE broker classifier name. Then it
|
|
450
|
+
appends the classifier_parameter list with the parameters specified in
|
|
451
|
+
the TOM Toolkit ALeRCE broker query definition.
|
|
452
|
+
|
|
453
|
+
List of available classifiers can be seen here: https://api.alerce.online/ztf/v1/classifiers/
|
|
454
|
+
|
|
455
|
+
:param parameters:
|
|
456
|
+
:return: classifier parameters tuple that holds strings with cleaned up versions of
|
|
457
|
+
available classifiers.
|
|
458
|
+
"""
|
|
459
|
+
|
|
460
|
+
classifier_parameters = []
|
|
461
|
+
class_type = ''
|
|
462
|
+
|
|
463
|
+
if parameters['stamp_classifier']:
|
|
464
|
+
class_type = 'stamp_classifier'
|
|
465
|
+
elif parameters.get('stamp_classifier_beta'):
|
|
466
|
+
class_type = 'stamp_classifier_2025_beta'
|
|
467
|
+
elif parameters['lc_classifier']:
|
|
468
|
+
class_type = 'lc_classifier'
|
|
469
|
+
elif parameters.get('lc_classifier_top'):
|
|
470
|
+
class_type = 'lc_classifier_top'
|
|
471
|
+
elif parameters.get('lc_classifier_bhrf'):
|
|
472
|
+
class_type = 'lc_classifier_BHRF_forced_phot'
|
|
473
|
+
elif parameters.get('lc_classifier_bhrf_top'):
|
|
474
|
+
class_type = 'lc_classifier_BHRF_forced_phot_top'
|
|
475
|
+
elif parameters.get('lc_classifier_atat'):
|
|
476
|
+
class_type = 'LC_classifier_ATAT_forced_phot(beta)'
|
|
477
|
+
|
|
478
|
+
if class_type:
|
|
479
|
+
classifier_parameters.append(('classifier', class_type))
|
|
480
|
+
if class_type in parameters and parameters[class_type] is not None:
|
|
481
|
+
classifier_parameters.append(('class', parameters[class_type]))
|
|
482
|
+
if f'p_{class_type}' in parameters and parameters[f'p_{class_type}'] is not None:
|
|
483
|
+
classifier_parameters.append(('probability', parameters[f'p_{class_type}']))
|
|
484
|
+
|
|
485
|
+
return classifier_parameters
|
|
486
|
+
|
|
487
|
+
def _clean_coordinate_parameters(self, parameters):
|
|
488
|
+
if all([parameters['ra'], parameters['dec'], parameters['radius']]):
|
|
489
|
+
return [
|
|
490
|
+
('ra', parameters['ra']),
|
|
491
|
+
('dec', parameters['dec']),
|
|
492
|
+
('radius', parameters['radius'])
|
|
493
|
+
]
|
|
494
|
+
else:
|
|
495
|
+
return []
|
|
496
|
+
|
|
497
|
+
def _clean_date_parameters(self, parameters):
|
|
498
|
+
dates = []
|
|
499
|
+
|
|
500
|
+
dates += [('firstmjd', v) for k, v in parameters.items() if 'firstmjd' in k and v]
|
|
501
|
+
dates += [('lastmjd', v) for k, v in parameters.items() if 'lastmjd' in k and v]
|
|
502
|
+
|
|
503
|
+
return dates
|
|
504
|
+
|
|
505
|
+
def _clean_parameters(self, parameters):
|
|
506
|
+
payload = [
|
|
507
|
+
(k, v) for k, v in parameters.items() if k in ['oid', 'ndet', 'ranking', 'order_by', 'order_mode'] and v
|
|
508
|
+
]
|
|
509
|
+
|
|
510
|
+
payload += [
|
|
511
|
+
('page', parameters.get('page', 1)),
|
|
512
|
+
('page_size', 20),
|
|
513
|
+
]
|
|
514
|
+
|
|
515
|
+
payload += self._clean_classifier_parameters(parameters)
|
|
516
|
+
|
|
517
|
+
payload += self._clean_coordinate_parameters(parameters)
|
|
518
|
+
|
|
519
|
+
payload += self._clean_date_parameters(parameters)
|
|
520
|
+
|
|
521
|
+
return payload
|
|
522
|
+
|
|
523
|
+
def _request_alerts(self, parameters):
|
|
524
|
+
payload = self._clean_parameters(parameters)
|
|
525
|
+
logger.log(msg=f'Fetching alerts from ALeRCE with payload {payload}', level=logging.INFO)
|
|
526
|
+
args = urlencode(payload)
|
|
527
|
+
response = requests.get(f'{ALERCE_SEARCH_URL}/objects/?count=false&{args}')
|
|
528
|
+
response.raise_for_status()
|
|
529
|
+
return response.json()
|
|
530
|
+
|
|
531
|
+
def fetch_alerts(self, parameters):
|
|
532
|
+
"""
|
|
533
|
+
Loop through pages of ALeRCE alerts until we reach the maximum pages requested.
|
|
534
|
+
This simply concatenates all alerts from n pages into a single iterable to be returned.
|
|
535
|
+
"""
|
|
536
|
+
response = self._request_alerts(parameters)
|
|
537
|
+
alerts = response['items']
|
|
538
|
+
broker_feedback = ''
|
|
539
|
+
current_page = parameters.get('page', 1)
|
|
540
|
+
if len(alerts) > 0 and current_page < parameters.get('max_pages', 1):
|
|
541
|
+
# make new request for the next page. (by recursion)
|
|
542
|
+
parameters['page'] = current_page + 1
|
|
543
|
+
alerts += self.fetch_alerts(parameters)[0]
|
|
544
|
+
# Bottom out of recursion and return accumulated alerts
|
|
545
|
+
return iter(alerts), broker_feedback
|
|
546
|
+
|
|
547
|
+
def fetch_alert(self, alert_id):
|
|
548
|
+
"""
|
|
549
|
+
The response for a single alert is as follows:
|
|
550
|
+
|
|
551
|
+
.. code-block:: python
|
|
552
|
+
|
|
553
|
+
{
|
|
554
|
+
'oid':'ZTF20acnsdjd',
|
|
555
|
+
...
|
|
556
|
+
'firstmjd':59149.1119328998,
|
|
557
|
+
...
|
|
558
|
+
}
|
|
559
|
+
|
|
560
|
+
"""
|
|
561
|
+
response = requests.get(f'{ALERCE_SEARCH_URL}/objects/{alert_id}')
|
|
562
|
+
response.raise_for_status()
|
|
563
|
+
return response.json()
|
|
564
|
+
|
|
565
|
+
def fetch_lightcurve(self, oid):
|
|
566
|
+
response = requests.get(f'{ALERCE_SEARCH_URL}/objects/{oid}/lightcurve')
|
|
567
|
+
response.raise_for_status()
|
|
568
|
+
return response.json()
|
|
569
|
+
|
|
570
|
+
def process_reduced_data(self, target, alert=None):
|
|
571
|
+
oid = target.name
|
|
572
|
+
lightcurve = self.fetch_lightcurve(oid)
|
|
573
|
+
|
|
574
|
+
for detection in lightcurve['detections']:
|
|
575
|
+
mjd = Time(detection['mjd'], format='mjd', scale='utc')
|
|
576
|
+
value = {
|
|
577
|
+
'filter': FILTERS[detection['fid']],
|
|
578
|
+
'magnitude': detection['diffmaglim'],
|
|
579
|
+
'error': detection['sigmapsf'],
|
|
580
|
+
'telescope': 'ZTF',
|
|
581
|
+
}
|
|
582
|
+
ReducedDatum.objects.get_or_create(
|
|
583
|
+
timestamp=mjd.to_datetime(TimezoneInfo()),
|
|
584
|
+
value=value,
|
|
585
|
+
source_name=self.name,
|
|
586
|
+
source_location=oid,
|
|
587
|
+
data_type='photometry',
|
|
588
|
+
target=target
|
|
589
|
+
)
|
|
590
|
+
|
|
591
|
+
for non_detection in lightcurve['non_detections']:
|
|
592
|
+
mjd = Time(non_detection['mjd'], format='mjd', scale='utc')
|
|
593
|
+
value = {
|
|
594
|
+
'filter': FILTERS[non_detection['fid']],
|
|
595
|
+
'limit': non_detection['diffmaglim'],
|
|
596
|
+
'telescope': 'ZTF',
|
|
597
|
+
}
|
|
598
|
+
ReducedDatum.objects.get_or_create(
|
|
599
|
+
timestamp=mjd.to_datetime(TimezoneInfo()),
|
|
600
|
+
value=value,
|
|
601
|
+
source_name=self.name,
|
|
602
|
+
source_location=oid,
|
|
603
|
+
data_type='photometry',
|
|
604
|
+
target=target
|
|
605
|
+
)
|
|
606
|
+
|
|
607
|
+
def to_target(self, alert):
|
|
608
|
+
return Target.objects.create(
|
|
609
|
+
name=alert['oid'],
|
|
610
|
+
type='SIDEREAL',
|
|
611
|
+
ra=alert['meanra'],
|
|
612
|
+
dec=alert['meandec']
|
|
613
|
+
)
|
|
614
|
+
|
|
615
|
+
# TODO: the generic alert is clearly not sufficient for ALeRCE's classifications
|
|
616
|
+
def to_generic_alert(self, alert):
|
|
617
|
+
if alert['lastmjd']:
|
|
618
|
+
timestamp = Time(alert['lastmjd'], format='mjd', scale='utc').to_datetime(timezone=TimezoneInfo())
|
|
619
|
+
else:
|
|
620
|
+
timestamp = ''
|
|
621
|
+
url = f'{ALERCE_URL}/object/{alert["oid"]}'
|
|
622
|
+
|
|
623
|
+
mag = None # mag is no longer returned in the object list
|
|
624
|
+
|
|
625
|
+
score = alert['probability']
|
|
626
|
+
|
|
627
|
+
return GenericAlert(
|
|
628
|
+
timestamp=timestamp,
|
|
629
|
+
url=url,
|
|
630
|
+
id=alert['oid'],
|
|
631
|
+
name=alert['oid'],
|
|
632
|
+
ra=alert['meanra'],
|
|
633
|
+
dec=alert['meandec'],
|
|
634
|
+
mag=mag,
|
|
635
|
+
score=score
|
|
636
|
+
)
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
from crispy_forms.layout import Layout, HTML
|
|
2
|
+
|
|
3
|
+
from tom_alerts.alerts import GenericBroker, GenericQueryForm, GenericAlert
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class ANTARESQueryForm(GenericQueryForm):
|
|
7
|
+
def __init__(self, *args, **kwargs):
|
|
8
|
+
super().__init__(*args, **kwargs)
|
|
9
|
+
self.helper.inputs.pop()
|
|
10
|
+
self.helper.layout = Layout(
|
|
11
|
+
HTML('''
|
|
12
|
+
<p>
|
|
13
|
+
This plugin is a stub for the ANTARES plugin. In order to install the full plugin, please see the
|
|
14
|
+
instructions <a href="https://github.com/TOMToolkit/tom_antares" target="_blank">here</a>.
|
|
15
|
+
</p>
|
|
16
|
+
'''),
|
|
17
|
+
HTML('''<a class="btn btn-outline-primary" href={% url 'tom_alerts:list' %}>Back</a>''')
|
|
18
|
+
)
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
class ANTARESBroker(GenericBroker):
|
|
22
|
+
"""
|
|
23
|
+
In order to install the Antares Broker plugin, please see
|
|
24
|
+
these instructions at https://github.com/TOMToolkit/tom_antares.
|
|
25
|
+
|
|
26
|
+
There is a known compatibility issue with antares-client required for the TOM_Antares Broker.
|
|
27
|
+
The antares-client requires the librdkafka library to be installed in order to be compatible with Python 3.10.
|
|
28
|
+
You can learn more about this on the
|
|
29
|
+
antares-client website (https://nsf-noirlab.gitlab.io/csdc/antares/client/installation.html) .
|
|
30
|
+
"""
|
|
31
|
+
name = 'ANTARES'
|
|
32
|
+
form = ANTARESQueryForm
|
|
33
|
+
|
|
34
|
+
def fetch_alerts(self, parameters):
|
|
35
|
+
return iter([]), ''
|
|
36
|
+
|
|
37
|
+
def process_reduced_data(self, target, alert=None):
|
|
38
|
+
return
|
|
39
|
+
|
|
40
|
+
def to_generic_alert(self, alert):
|
|
41
|
+
return GenericAlert(
|
|
42
|
+
timestamp=None,
|
|
43
|
+
url=None,
|
|
44
|
+
id=None,
|
|
45
|
+
name=None,
|
|
46
|
+
ra=None,
|
|
47
|
+
dec=None,
|
|
48
|
+
mag=None,
|
|
49
|
+
score=None
|
|
50
|
+
)
|