diff --git a/lmfdb/hypergm/templates/hgm_family.html b/lmfdb/hypergm/templates/hgm_family.html
index 61d6d8f8b4..dc16a0bbef 100644
--- a/lmfdb/hypergm/templates/hgm_family.html
+++ b/lmfdb/hypergm/templates/hgm_family.html
@@ -37,7 +37,15 @@
{{KNOWL('hgm.levelt_matrices', title="Levelt matrices")}}: | ${h_{\infty}={{family.hinf_latex}},\;}$ ${h_0={{family.h0_latex}},\;}$ $ {h_1={{family.h1_latex}}}$
+
+
+ {{ KNOWL('hgm.zigzagplot', title='Zigzag plot') }}
+
+
+
+
{{ KNOWL('hgm.defining_parameter_ppart', title='$p$-parts of defining parameters') }}
+
$p$ | {{ KNOWL('hgm.defining_parameter_ppart', title='$A_p$') }} | {{ KNOWL('hgm.defining_parameter_ppart', title='$B_p$') }} | {{ KNOWL('hgm.defining_parameter_ppart', title='$C_p$') }}
diff --git a/lmfdb/hypergm/web_family.py b/lmfdb/hypergm/web_family.py
index 329120d1fb..498508ab42 100644
--- a/lmfdb/hypergm/web_family.py
+++ b/lmfdb/hypergm/web_family.py
@@ -1,10 +1,11 @@
import re
from flask import url_for
-from collections import defaultdict
+from collections import defaultdict, Counter
from sage.all import (ZZ, QQ, cached_method, ceil, gcd, lcm,
latex, lazy_attribute,
- matrix, valuation)
+ matrix, valuation, I)
+from sage.rings.complex_mpfr import ComplexField
from sage.geometry.newton_polygon import NewtonPolygon
from lmfdb import db
@@ -13,7 +14,9 @@
make_bigint, web_latex, integer_divisors, integer_prime_divisors)
from lmfdb.groups.abstract.main import abstract_group_display_knowl
from lmfdb.galois_groups.transitive_group import transitive_group_display_knowl_C1_as_trivial
-from .plot import circle_image, piecewise_constant_image, piecewise_linear_image
+# from .plot import circle_image, piecewise_constant_image, piecewise_linear_image
+from sage.plot.all import line, text, point, circle, polygon, Graphics
+from sage.functions.log import exp
HMF_LABEL_RE = re.compile(r'^A(\d+\.)*\d+_B(\d+\.)*\d+$')
@@ -176,15 +179,35 @@ def ppart(self):
row.append(AB_to_url(A,B))
return p_data
+ @cached_method
+ def circle_image(self):
+ alpha = self.alpha
+ beta = self.beta
+ alpha_counter = dict(Counter(alpha))
+ beta_counter = dict(Counter(beta))
+ G = Graphics()
+ G += circle((0, 0), 1, color='gray', thickness=2, zorder=3)
+ G += circle((0, 0), 1.4, color='black', alpha=0, zorder=2) # Adds invisible framing circle, which protects the aspect ratio from being skewed.
+ C = ComplexField()
+ for a in alpha_counter.keys():
+ P = exp(C(2*3.14159*I*a))
+ P1 = exp(C(2*3.14159*(a + 0.007)*I))
+ P2 = exp(C(2*3.14159*(a - 0.007)*I))
+ P3 = (1+alpha_counter[a]/30)*exp(C(2*3.14159*I*a))
+ G += polygon([P1,P2,P3], color="red", thickness=1)
+ G += line([P,1.3*P], color="red", zorder=1)
+ for b in beta_counter.keys():
+ P = exp(C(2*3.14159*I*b))
+ P1 = exp(C(2*3.14159*(b + 0.007)*I))
+ P2 = exp(C(2*3.14159*(b - 0.007)*I))
+ P3 = (1-beta_counter[b]/30)*exp(C(2*3.14159*I*b))
+ G += polygon([P1,P2,P3], color="blue", thickness=1)
+ G += line([P,0.7*P], color="blue", zorder=1)
+ return G
+
@cached_method
def plot(self, typ="circle"):
- assert typ in ['circle', 'linear', 'constant']
- if typ == 'circle':
- G = circle_image(self.A, self.B)
- elif typ == 'linear':
- G = piecewise_linear_image(self.A, self.B)
- else:
- G = piecewise_constant_image(self.A, self.B)
+ G = self.circle_image()
return encode_plot(
G.plot(),
@@ -198,6 +221,67 @@ def plot(self, typ="circle"):
def plot_link(self):
return ''.format(self.plot())
+ @lazy_attribute
+ def zigzag(self):
+ # alpha is color red
+ # beta is color blue
+ alpha = self.alpha
+ beta = self.beta
+ alpha_dicts = [dict(value=entry,color="red") for entry in alpha]
+ beta_dicts = [dict(value=entry,color="blue") for entry in beta]
+ zigzag_dicts = sorted(alpha_dicts + beta_dicts, key=lambda d: d["value"])
+ y = 0
+ y_values = [y] # zigzag graph will start at (0,0)
+ colors = [entry["color"] for entry in zigzag_dicts]
+ for entry in zigzag_dicts:
+ if entry["color"] == "red":
+ y += 1
+ y_values.append(y)
+ elif entry["color"] == "blue":
+ y += -1
+ y_values.append(y)
+ return [y_values, colors, zigzag_dicts]
+
+ @cached_method
+ def zigzag_plot(self):
+ zz = self.zigzag
+ y_values = zz[0]
+ colors = zz[1]
+ x_labels = zz[2]
+ y_max = max(y_values)
+ y_min = min(y_values)
+ x_values = list(range(0,len(y_values)))
+ x_max = len(y_values)
+ pts = [(i, y_values[i]) for i in x_values]
+ L = Graphics()
+ # grid
+ for x in x_values:
+ L += line([(x, y_min), (x, y_max)], color="grey", zorder=1, thickness=0.4)
+ for y in y_values:
+ L += line([(0, y), (x_max-1, y)], color="grey", zorder=1, thickness=0.4)
+ # zigzag
+ L += line(pts, thickness=1, color="black", zorder=2)
+ # points
+ x_values.pop()
+ for x in x_values:
+ L += point((x, y_values[x]), marker='o', size = 36, color=colors[x], zorder=3)
+
+ j = 0
+ for label in x_labels:
+ if label["color"] == "red":
+ L += text("$"+latex(QQ(label["value"]))+"$", (j,y_max + 0.4), color=label["color"])
+ j += 1
+ else:
+ L += text("$"+latex(QQ(label["value"]))+"$", (j,y_min - 0.4), color=label["color"])
+ j += 1
+ L.axes(False)
+ L.set_aspect_ratio(1)
+ return encode_plot(L, pad=0, pad_inches=0, bbox_inches="tight")
+
+ @lazy_attribute
+ def zigzag_plot_link(self):
+ return ''.format(self.zigzag_plot())
+
@lazy_attribute
def properties(self):
return [('Label', self.label),
| |