migrated to bokeh

This commit is contained in:
Markus Rosenstihl 2025-03-27 22:22:35 +01:00
parent 3e24987f05
commit e6a841e09a
3 changed files with 66 additions and 46 deletions

View File

@ -1,9 +1,13 @@
<head>
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css" rel="stylesheet"
integrity="sha384-QWTKZyjpPEjISv5WaRU9OFeRpok6YctnYmDr5pNlyT2bRjXh0JMhjY6hW+ALEwIH" crossorigin="anonymous">
<link href=”https://cdn.pydata.org/bokeh/release/bokeh-3.7.1.min.css" rel=”stylesheet” type=”text/css”>
<link href=”https://cdn.pydata.org/bokeh/release/bokeh-widgets-3.7.1.min.css" rel=”stylesheet” type=”text/css”>
</head>
<body>
<div class="center">
<h1>Isotopes</h1>
<table class="table w-auto table-responsive-sm table-striped table-hover table-bordered">
<caption>
Table downloaded from <a href="https://easyspin.org/documentation/isotopetable.html">easyspin.org</a>
@ -29,17 +33,26 @@
{% endfor %}
</tr>
{% endfor %}
</tbody>
</table>
{{ div| safe }}
<div>
<img src="data:image/png;base64, {{ figure }}" alt="somealt" />
<script src="https://cdn.bokeh.org/bokeh/release/bokeh-3.7.1.min.js"></script>
<script src="https://cdn.bokeh.org/bokeh/release/bokeh-widgets-3.7.1.min.js"></script>
<script src="https://cdn.bokeh.org/bokeh/release/bokeh-tables-3.7.1.min.js"></script>
<script src="https://cdn.bokeh.org/bokeh/release/bokeh-api-3.7.1.min.js"></script>
<script src="https://cdn.bokeh.org/bokeh/release/bokeh-mathjax-3.7.1.min.js"></script>
{{ script| safe }}
</div>
<a href="{% url 'home' %}">Go Back</a>
</div>
</body>
<style>
.center {
margin: auto;
@ -55,6 +68,8 @@
text-align: left;
}
.table-striped {--bs-table-striped-bg: rgba(213, 217, 255, 0.7);}
.table-striped {
--bs-table-striped-bg: rgba(213, 217, 255, 0.7);
}
</style>

View File

@ -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"<sup>{i.n_nucleons}</sup>{i.symbol}")] for i in isotopes]})
return render(request, 'home.html', {'isotopes': [[f"{i.n_nucleons}{i.symbol}", mark_safe(f"<sup>{i.n_nucleons}</sup>{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"""
<math>
<msup>
{isotope.n_nucleons}
</msup>
{isotope.symbol}
</math>
"""
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"<math><msup>{isotope1.n_nucleons}</msup>{isotope1.symbol}: {freq:.1f} MHz\ng={gradient:.1f} T/m\n5 mm sample dia.</math>"),
text=f"{isotope1.n_nucleons}{isotope1.symbol}: {freq:.1f} MHz\ng={gradient:.1f} T/m\n5 mm sample dia.",
#text=MathML("<math>tewt</math>"),
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})

View File

@ -1,2 +1,3 @@
Django==5.1.6
matplotlib==3.10.1
#matplotlib==3.10.1
bokeh==3.7.1