Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 10 additions & 1 deletion lmfdb/local_fields/family.py
Original file line number Diff line number Diff line change
Expand Up @@ -177,7 +177,16 @@ def picture(self):
ticklook, ticks, slopeset, meanset, rectangles = self.spread_ticks
hscale = self.e / 18
mindiff = min((ticklook[b]-ticklook[a]) for (a,b) in rectangles)
aspect = min(8, max(0.6 * (self.e + 3*hscale) / (1 + maxslope), self.e/(32*mindiff)))
# The image is displayed with a fixed width, so its rendered height is
# proportional to aspect * maxslope / xwidth. The first term gives a
# pleasant default shape; the second term increases the height when
# needed to keep the closest pair of y-axis labels legibly separated.
xwidth = self.e + 3*hscale
aspect = max(0.6 * xwidth / (1 + maxslope), self.e/(32*mindiff))
# Clamp the height:width ratio of the image to [1/4, 5/4]. A fixed cap
# on the aspect itself (which is measured in data coordinates) would
# vertically compress families with small slopes and large e (#6828).
aspect = min(max(aspect, xwidth/(4*maxslope)), 5*xwidth/(4*maxslope))

# Print the bands
for (a,b), cnt in rectangles.items():
Expand Down
24 changes: 24 additions & 0 deletions lmfdb/local_fields/test_localfields.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
import re
import struct
from base64 import b64decode
from urllib.parse import unquote

from lmfdb.tests import LmfdbTest


Expand Down Expand Up @@ -60,6 +65,25 @@ def test_search_download(self):
mapput(~out, "field", field);
return(out);''' in page

def _eisenstein_diagram_dims(self, label):
# Extract the pixel dimensions of the Eisenstein diagram on a family page
page = self.tc.get(f'/padicField/family/{label}').get_data(as_text=True)
m = re.search(r'id="diagram_eisenstein"[^>]*>\s*<img src="data:image/png;base64,([^"]*)"', page)
assert m is not None
png = b64decode(unquote(m.group(1)))
assert png[:8] == b'\x89PNG\r\n\x1a\n'
return struct.unpack(">II", png[16:24])

def test_family_diagram_scaling(self):
# Families with small slopes and large e used to produce vertically
# compressed Eisenstein diagrams with overlapping labels. Issue #6828.
for label in ['2.1.16.16a', '2.1.32.34a']:
w, h = self._eisenstein_diagram_dims(label)
assert h > 0.3 * w
# A typical family should keep a moderate shape
w, h = self._eisenstein_diagram_dims('2.1.4.6a')
assert 0.25 * w < h < 0.6 * w

def test_families_search_download(self):
# Absolute families: download should produce a file (not just refresh the page). Issue #6829.
r = self.tc.get('/padicField/?Submit=sage&download=1&query=%7B%27n0%27%3A+1%2C+%27p%27%3A+2%2C+%27n%27%3A+2%7D&p=2&n=2&search_type=Families')
Expand Down
Loading