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),