From e6a841e09a63faccaac7de1f9aeb5762520edbae Mon Sep 17 00:00:00 2001 From: Markus Rosenstihl Date: Thu, 27 Mar 2025 22:22:35 +0100 Subject: [PATCH] migrated to bokeh --- isotables/isotopapp/templates/result.html | 27 ++++++-- isotables/isotopapp/views.py | 82 ++++++++++++----------- requirements.txt | 3 +- 3 files changed, 66 insertions(+), 46 deletions(-) diff --git a/isotables/isotopapp/templates/result.html b/isotables/isotopapp/templates/result.html index f76db64..13782e3 100644 --- a/isotables/isotopapp/templates/result.html +++ b/isotables/isotopapp/templates/result.html @@ -1,9 +1,13 @@ + + +
+

Isotopes

Table downloaded from easyspin.org @@ -29,17 +33,26 @@ {% endfor %} {% endfor %} +
-
- somealt -
+ {{ div| safe }} + +
+ + + + + + + {{ script| safe }} +
- Go Back - +Go Back
+ diff --git a/isotables/isotopapp/views.py b/isotables/isotopapp/views.py index b8e52d4..f5100cb 100644 --- a/isotables/isotopapp/views.py +++ b/isotables/isotopapp/views.py @@ -4,20 +4,18 @@ import base64 from django.shortcuts import render from django.utils.safestring import mark_safe import re -import numpy as np -import matplotlib -from setuptools.command.rotate import rotate -matplotlib.use('Agg') -from matplotlib.patches import Wedge, FancyArrowPatch -import matplotlib.pyplot as plt +from bokeh.plotting import figure as bokehfig +from bokeh.embed import components +from bokeh.models import Label, Node, MathML + from isotopapp.models import Isotope # Create your views here. def home(request): isotopes = [i for i in Isotope.objects.all() if (i.gamma != 0 or i.stable)] - return render(request, 'home.html', {'isotopes': [[f"{i.n_nucleons}{i.symbol}", mark_safe(f"{i.n_nucleons}{i.symbol}")] for i in isotopes]}) + return render(request, 'home.html', {'isotopes': [[f"{i.n_nucleons}{i.symbol}", mark_safe(f"{i.n_nucleons}{i.symbol}")] for i in isotopes],}) def extract_isotope_parts(isotope_str): """Extracts the number and element from an isotope string (e.g., '23Na').""" @@ -49,7 +47,9 @@ def result(request): field_T = freq / isotope1.gamma - figure=None + script = None + div = None + print(request.GET) if request.GET.get('range_search') == "": close_isotopes = [isotope_info(isotope1, field_T)] @@ -65,24 +65,14 @@ def result(request): ans = sorted(close_isotopes, key=lambda x: -float(x[3])) elif request.GET.get('gradient_search') == "": - fig, ax = plt.subplots(1, 1) - theta1, theta2 = 0, 360 - radius = 2.5 - center = (0, 0) - w = Wedge(center, radius, theta1, theta2, fc='#D5D9FFB2', edgecolor='black') - w_upper = Wedge((0,2.5), radius, theta1, theta2, fc='#D5D9FF42', edgecolor='black') - w_lower = Wedge((0,-2.5), radius, theta1, theta2, fc='#D5D9FF42', edgecolor='black') - - ax.set_xlim([-5.5, 5.5]) - ax.set_ylim([-5.5, 5.5]) - ax.grid(True) - - ax.add_patch(w_upper) - ax.add_patch(w_lower) - ax.add_patch(w) - sample_diameter = 5e-3 gradient = float(request.GET.get('gradient')) + # create a plot (bokeh) + plot = bokehfig(outer_width=400, outer_height=400, match_aspect=True) + plot.ellipse(x=[0], y=[0], width=5, height=5, color="#D5D9FF", alpha=0.8, line_width=1, line_color="black") + plot.ellipse(x=[0], y= [2.5], width=5, height=5, color="#D5D9FF", alpha=0.4, line_width=1, line_color="black") + plot.ellipse(x=[0], y=[-2.5], width=5, height=5, color="#D5D9FF", alpha=0.4, line_width=1, line_color="black") + close_isotopes = [] for isotope in Isotope.objects.all(): @@ -93,22 +83,36 @@ def result(request): i_info = isotope_info(isotope, field_T) #i_info[3] = f"{z*1e3:.1f} mm" close_isotopes.append(i_info) + mathml = f""" + + + {isotope.n_nucleons} + + {isotope.symbol} + + """ + plot.rect(x=[0], y=[z*1e3], width=5, height=0.2, color="black", alpha=0.6) + label = Label(x=2.6, y=z*1e3, text=f"{isotope.n_nucleons}{isotope.symbol}", text_baseline="middle", text_align="left", text_font_size="16pt") + #label = Label(x=2.6, y=z*1e3, text=MathML(mathml), text_baseline="middle", text_align="left", text_font_size="16pt") + plot.add_layout(label) - arr = FancyArrowPatch((-2.5,z*1e3), (2.5, z*1e3), - arrowstyle='-', mutation_scale=20, linewidth=2) - ax.add_patch(arr) - ax.annotate(f"{isotope.n_nucleons}{isotope.symbol}", (1.1, 0), xycoords=arr, ha='left', va='center',fontsize=8) - ax.annotate(f"{isotope1.n_nucleons}{isotope1.symbol}: {freq:.1f}MHz\ng={gradient:.1f}T/m", - (0.91, -0.45), xycoords=w, - ha='left', va='center',fontsize=11) + frame_left = Node(target="frame", symbol="left", offset=5) + frame_bottom = Node(target="frame", symbol="bottom", offset=-5) + citation = Label( + x=frame_left, + y=frame_bottom, + anchor="bottom_left", + #text=MathML(text=f"{isotope1.n_nucleons}{isotope1.symbol}: {freq:.1f} MHz\ng={gradient:.1f} T/m\n5 mm sample dia."), + text=f"{isotope1.n_nucleons}{isotope1.symbol}: {freq:.1f} MHz\ng={gradient:.1f} T/m\n5 mm sample dia.", + #text=MathML("tewt"), + padding=10, + border_radius=5, + border_line_color="black", background_fill_color="white", + ) + plot.add_layout(citation) - ax.set_aspect('equal') - ax.set_ylabel('z (mm)') - - buf = BytesIO() - plt.savefig(buf, format='png', dpi=120) - figure = base64.b64encode(buf.getvalue()).decode('utf-8').replace('\n', '') - buf.close() + # boke plot + script, div = components(plot) ans = sorted(close_isotopes, key=lambda x: float(x[3])) elif request.GET.get('transform') == "": @@ -118,4 +122,4 @@ def result(request): ans = [isotope_info(isotope2, field_T)] else: ans = [] - return render(request, 'result.html', {'ans': ans, 'figure': figure}) + return render(request, 'result.html', {'ans': ans, 'script': script, 'div': div}) diff --git a/requirements.txt b/requirements.txt index 5238dc0..895be74 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,2 +1,3 @@ Django==5.1.6 -matplotlib==3.10.1 +#matplotlib==3.10.1 +bokeh==3.7.1