TOMToolkit / tom_base

The base Django project for a Target and Observation Manager
https://tom-toolkit.readthedocs.io
GNU General Public License v3.0
23 stars 42 forks source link

Incorporate SNEx2 Dash Spectra Plotting #861

Open jchate6 opened 4 months ago

jchate6 commented 4 months ago

From Craig

Hi all, I'm very close to having a working tom toolkit app that allows users to interactively plot spectra using Dash. This is something that I had originally written into SNEx2, but I'm now refactoring that code because at least one other tom user (Griffin) said he'd appreciate having it. I also think it would be pretty broadly applicable to other toms out there. Once it's done, is this app something that I could contribute back to the tom toolkit? And if so, what's the best way to go about that? Thanks!


hey Lindy, here's the snex2 branch with the dash spectra app: https://github.com/crpellegrino/snex2/tree/feature/dash_spectra_app It's still a work in progress but I think it's ready for another set of eyes. Most of the new features are in the snex2/dash_spectra/ directory but there's still some functionality tied to other SNEx2-specific code elsewhere. Let me know if you have any questions or if you'd like a demo. thanks!

griffin-h commented 1 month ago

@cmccully and I tried installing this into a clean TOM from the make-tom repo, and we could not get it to fully work. Here are the steps we followed (this was already two weeks ago, so forgive me if I forget a step):

  1. Copy the dash spectra app out of snex2 (after the changes in crpellegrino/snex2#1) to some external directory, and add that directory to your $PYTHONPATH
  2. Install django_plotly_dash==1.4.2 and dpd-static-support in the Python virtual environment
  3. Add the following to your settings.py:
    
    INSTALLED_APPS = [
    ...
    'django_plotly_dash.apps.DjangoPlotlyDashConfig',
    'dash_spectra',
    ]

MIDDLEWARE = [ ... 'django_plotly_dash.middleware.BaseMiddleware', 'django_plotly_dash.middleware.ExternalRedirectionMiddleware', ]

STATICFILES_FINDERS = [ 'django.contrib.staticfiles.finders.FileSystemFinder', 'django.contrib.staticfiles.finders.AppDirectoriesFinder', 'django_plotly_dash.finders.DashAssetFinder', 'django_plotly_dash.finders.DashComponentFinder', 'django_plotly_dash.finders.DashAppDirectoryFinder', ]

PLOTLY_COMPONENTS = [ 'dash_bootstrap_components', 'dpd_components', 'dpd_static_support', ]

PLOTLY_DASH = { "ws_route": "ws/channel", "insert_demo_migrations": True, # Insert model instances used by the demo "http_poke_enabled": True, # Flag controlling availability of direct-to-messaging http endpoint "view_decorator": None, # Specify a function to be used to wrap each of the dpd view functions "cache_arguments": True, # True for cache, False for session-based argument propagation

"serve_locally": True, # True to serve assets locally, False to use their unadulterated urls (eg a CDN)

"stateless_loader": "dash_spectra.loader.loader",

}

Default Plotly theme setting, can set to any valid theme:

'plotly', 'plotly_white', 'plotly_dark', 'ggplot2', 'seaborn', 'simple_white', 'none'

PLOTLY_THEME = 'plotly_white' DASH_SPECTRA_PLOTS = { 'elements': { 'H': {'color': '#ff0000', 'waves': [3970, 4102, 4341, 4861, 6563]}, 'He': {'color': '#002157', 'waves': [4472, 5876, 6678, 7065]}, 'He II': {'color': '#003b99', 'waves': [3203, 4686]}, 'O': {'color': '#007236', 'waves': [7774, 7775, 8447, 9266]}, 'O II': {'color': '#00a64d', 'waves': [3727]}, 'O III': {'color': '#00bf59', 'waves': [4959, 5007]}, 'Na': {'color': '#aba000', 'waves': [5890, 5896, 8183, 8195]}, 'Mg': {'color': '#8c6239', 'waves': [2780, 2852, 3829, 3832, 3838, 4571, 5167, 5173, 5184]}, 'Mg II': {'color': '#bf874e', 'waves': [2791, 2796, 2803, 4481]}, 'Si II': {'color': '#5674b9', 'waves': [3856, 5041, 5056, 5670, 6347, 6371]}, 'S II': {'color': '#a38409', 'waves': [5433, 5454, 5606, 5640, 5647, 6715]}, 'Ca II': {'color': '#005050', 'waves': [3934, 3969, 7292, 7324, 8498, 8542, 8662]}, 'Fe II': {'color': '#f26c4f', 'waves': [5018, 5169]}, 'Fe III': {'color': '#f9917b', 'waves': [4397, 4421, 4432, 5129, 5158]}, 'C II': {'color': '#303030', 'waves': [4267, 4745, 6580, 7234]}, 'Galaxy': {'color': '#000000', 'waves': [4341, 4861, 6563, 6548, 6583, 6300, 3727, 4959, 5007, 2798, 6717, 6731]}, 'Tellurics': {'color': '#b7b7b7', 'waves': [6867, 6884, 7594, 7621]}, 'Flash CNO': {'color': '#0064c8', 'waves': [4648, 5696, 5801, 4640, 4058, 4537, 5047, 7109, 7123, 4604, 4946, 3410, 5597, 3811, 3835]}, 'SN Ia': {'color': '#ff9500', 'waves': [3856, 5041, 5056, 5670, 6347, 6371, 5433, 5454, 5606, 5640, 5647, 6715, 3934, 3969, 7292, 7324, 8498, 8542, 8662]}, }, 'custom_lines': { 'custom1': {'color': '#c7b299'}, 'custom2': {'color': '#837565'}, }, }

4. Add django-plotly-dash to `urls.py` as follows (note that the second import must be there even though it is not used):

from django.urls import path, include from dash_spectra import spectra_class_individual, spectra_class

urlpatterns = [ path('', include('tom_common.urls')), path('django_plotly_dash', include('django_plotly_dash.urls')), ]

5. Create a custom `target_detail.html`, add `{% load ... dash_spectra_tags %}`, and change `{% spectroscopy_for_target target %}` to `{% dash_spectra target %}`

The final error I got before giving up was:

Internal Server Error: /targets/2/ Traceback (most recent call last): File "/Users/griffin/PycharmProjects/make-tom/AAS243_tom/env/lib/python3.10/site-packages/django/core/handlers/exception.py", line 55, in inner response = get_response(request) File "/Users/griffin/PycharmProjects/make-tom/AAS243_tom/env/lib/python3.10/site-packages/django/core/handlers/base.py", line 222, in _get_response response = self.process_exception_by_middleware(e, request) File "/Users/griffin/PycharmProjects/make-tom/AAS243_tom/env/lib/python3.10/site-packages/django/core/handlers/base.py", line 362, in process_exception_by_middleware response = middleware_method(request, exception) File "/Users/griffin/PycharmProjects/make-tom/AAS243_tom/env/lib/python3.10/site-packages/tom_common/middleware.py", line 29, in process_exception raise exception File "/Users/griffin/PycharmProjects/make-tom/AAS243_tom/env/lib/python3.10/site-packages/django/core/handlers/base.py", line 220, in _get_response response = response.render() File "/Users/griffin/PycharmProjects/make-tom/AAS243_tom/env/lib/python3.10/site-packages/django/template/response.py", line 114, in render self.content = self.rendered_content File "/Users/griffin/PycharmProjects/make-tom/AAS243_tom/env/lib/python3.10/site-packages/django/template/response.py", line 92, in rendered_content return template.render(context, self._request) File "/Users/griffin/PycharmProjects/make-tom/AAS243_tom/env/lib/python3.10/site-packages/django/template/backends/django.py", line 61, in render return self.template.render(context) File "/Users/griffin/PycharmProjects/make-tom/AAS243_tom/env/lib/python3.10/site-packages/django/template/base.py", line 175, in render return self._render(context) File "/Users/griffin/PycharmProjects/make-tom/AAS243_tom/env/lib/python3.10/site-packages/django/template/base.py", line 167, in _render return self.nodelist.render(context) File "/Users/griffin/PycharmProjects/make-tom/AAS243_tom/env/lib/python3.10/site-packages/django/template/base.py", line 1005, in render return SafeString("".join([node.render_annotated(context) for node in self])) File "/Users/griffin/PycharmProjects/make-tom/AAS243_tom/env/lib/python3.10/site-packages/django/template/base.py", line 1005, in return SafeString("".join([node.render_annotated(context) for node in self])) File "/Users/griffin/PycharmProjects/make-tom/AAS243_tom/env/lib/python3.10/site-packages/django/template/base.py", line 966, in render_annotated return self.render(context) File "/Users/griffin/PycharmProjects/make-tom/AAS243_tom/env/lib/python3.10/site-packages/django/template/loader_tags.py", line 157, in render return compiled_parent._render(context) File "/Users/griffin/PycharmProjects/make-tom/AAS243_tom/env/lib/python3.10/site-packages/django/template/base.py", line 167, in _render return self.nodelist.render(context) File "/Users/griffin/PycharmProjects/make-tom/AAS243_tom/env/lib/python3.10/site-packages/django/template/base.py", line 1005, in render return SafeString("".join([node.render_annotated(context) for node in self])) File "/Users/griffin/PycharmProjects/make-tom/AAS243_tom/env/lib/python3.10/site-packages/django/template/base.py", line 1005, in return SafeString("".join([node.render_annotated(context) for node in self])) File "/Users/griffin/PycharmProjects/make-tom/AAS243_tom/env/lib/python3.10/site-packages/django/template/base.py", line 966, in render_annotated return self.render(context) File "/Users/griffin/PycharmProjects/make-tom/AAS243_tom/env/lib/python3.10/site-packages/django/template/loader_tags.py", line 63, in render result = block.nodelist.render(context) File "/Users/griffin/PycharmProjects/make-tom/AAS243_tom/env/lib/python3.10/site-packages/django/template/base.py", line 1005, in render return SafeString("".join([node.render_annotated(context) for node in self])) File "/Users/griffin/PycharmProjects/make-tom/AAS243_tom/env/lib/python3.10/site-packages/django/template/base.py", line 1005, in return SafeString("".join([node.render_annotated(context) for node in self])) File "/Users/griffin/PycharmProjects/make-tom/AAS243_tom/env/lib/python3.10/site-packages/django/template/base.py", line 966, in render_annotated return self.render(context) File "/Users/griffin/PycharmProjects/make-tom/AAS243_tom/env/lib/python3.10/site-packages/django/template/library.py", line 278, in render return t.render(new_context) File "/Users/griffin/PycharmProjects/make-tom/AAS243_tom/env/lib/python3.10/site-packages/django/template/base.py", line 177, in render return self._render(context) File "/Users/griffin/PycharmProjects/make-tom/AAS243_tom/env/lib/python3.10/site-packages/django/template/base.py", line 167, in _render return self.nodelist.render(context) File "/Users/griffin/PycharmProjects/make-tom/AAS243_tom/env/lib/python3.10/site-packages/django/template/base.py", line 1005, in render return SafeString("".join([node.render_annotated(context) for node in self])) File "/Users/griffin/PycharmProjects/make-tom/AAS243_tom/env/lib/python3.10/site-packages/django/template/base.py", line 1005, in return SafeString("".join([node.render_annotated(context) for node in self])) File "/Users/griffin/PycharmProjects/make-tom/AAS243_tom/env/lib/python3.10/site-packages/django/template/base.py", line 966, in render_annotated return self.render(context) File "/Users/griffin/PycharmProjects/make-tom/AAS243_tom/env/lib/python3.10/site-packages/django/template/library.py", line 258, in render _dict = self.func(*resolved_args, **resolved_kwargs) File "/Users/griffin/PycharmProjects/make-tom/AAS243_tom/env/lib/python3.10/site-packages/django_plotly_dash/templatetags/plotly_dash.py", line 76, in plotly_app da, app = _locate_daapp(name, slug, da, cache_id=cache_id) File "/Users/griffin/PycharmProjects/make-tom/AAS243_tom/env/lib/python3.10/site-packages/django_plotly_dash/templatetags/plotly_dash.py", line 43, in _locate_daapp da, app = DashApp.locate_item(name, stateless=True, cache_id=cache_id) File "/Users/griffin/PycharmProjects/make-tom/AAS243_tom/env/lib/python3.10/site-packages/django_plotly_dash/models.py", line 232, in locate_item app = dash_app.as_dash_instance(cache_id=cache_id) File "/Users/griffin/PycharmProjects/make-tom/AAS243_tom/env/lib/python3.10/site-packages/django_plotly_dash/dash_wrapper.py", line 226, in as_dash_instance return self.do_form_dash_instance(cache_id=cache_id) File "/Users/griffin/PycharmProjects/make-tom/AAS243_tom/env/lib/python3.10/site-packages/django_plotly_dash/dash_wrapper.py", line 262, in do_form_dash_instance return self.form_dash_instance(replacements, ndid, base_pathname) File "/Users/griffin/PycharmProjects/make-tom/AAS243_tom/env/lib/python3.10/site-packages/django_plotly_dash/dash_wrapper.py", line 270, in form_dash_instance rd = WrappedDash(base_pathname=base_pathname, File "/Users/griffin/PycharmProjects/make-tom/AAS243_tom/env/lib/python3.10/site-packages/django_plotly_dash/dash_wrapper.py", line 374, in init super(WrappedDash, self).init(name, File "/Users/griffin/PycharmProjects/make-tom/AAS243_tom/env/lib/python3.10/site-packages/dash/dash.py", line 504, in init self.init_app() File "/Users/griffin/PycharmProjects/make-tom/AAS243_tom/env/lib/python3.10/site-packages/dash/dash.py", line 568, in init_app self.server.before_request(self._setup_server) File "/Users/griffin/PycharmProjects/make-tom/AAS243_tom/env/lib/python3.10/site-packages/flask/sansio/scaffold.py", line 46, in wrapper_func self._check_setup_finished(f_name) File "/Users/griffin/PycharmProjects/make-tom/AAS243_tom/env/lib/python3.10/site-packages/flask/sansio/app.py", line 414, in _check_setup_finished if self._got_first_request: AttributeError: 'PseudoFlask' object has no attribute '_got_first_request'