def render_st_group(info, portrait=None): """ render html page for Sato-Tate group described by info """ prop2 = [('Label', '%s' % info['label'])] if portrait: prop2 += [ (None, ' <img src="%s" width="220" height="124"/>' % portrait) ] prop2 += [ ('Name', r'\(%s\)' % info['pretty']), ('Weight', prop_int_pretty(info['weight'])), ('Degree', prop_int_pretty(info['degree'])), ('Real dimension', prop_int_pretty(info['real_dimension'])), ('Components', prop_int_pretty(info['components'])), ('Contained in', r'\(%s\)' % info['ambient']), ('Identity Component', r'\(%s\)' % info['identity_component']), ('Component group', r'\(%s\)' % info['component_group']), ] bread = get_bread([ ('Weight %d' % info['weight'], url_for('.index') + '?weight=' + str(info['weight'])), ('Degree %d' % info['degree'], url_for('.index') + '?weight=' + str(info['weight']) + '°ree=' + str(info['degree'])), (info['name'], '') ]) title = r'Sato-Tate group \(' + info['pretty'] + r'\) of Weight %d' % info[ 'weight'] + ' and Degree %d' % info['degree'] return render_template('st_display.html', properties=prop2, credit=credit_string, info=info, bread=bread, learnmore=learnmore_list(), title=title, KNOWL_ID='st_group.%s' % (info['label']))
def properties(self): f = [("Label", [self.label])] f.extend([("Modulus", [prop_int_pretty(self.modulus)]), ("Conductor", [prop_int_pretty(self.conductor)]), ("Order", [prop_int_pretty(self.order)]), ("Real", [self.isreal]), ("Primitive", [self.isprimitive])]) if self.isminimal: f.append(("Minimal", [self.isminimal])) if self.parity: f.append(("Parity", [self.parity])) return f
def properties(self): props = [ (None, '<img src="{0}" width="200" height="150" style="margin:10px;"/>'. format(self.portrait)) ] if self.portrait is not None else [] props += [ ('Level', prop_int_pretty(self.level)), ('Weight', prop_int_pretty(self.weight)), ('Character', self.character_label), ('Symmetry', self.symmetry_pretty), ] if self.conrey_index == 1: props.append(('Fricke sign', self.fricke_pretty)) return props
def render_hmf_webpage(**args): if 'data' in args: data = args['data'] label = data['label'] else: label = str(args['label']) data = get_hmf(label) if data is None: flash_error( "%s is not a valid Hilbert modular form label. It must be of the form (number field label) - (level label) - (orbit label) separated by dashes, such as 2.2.5.1-31.1-a", args['label']) return search_input_error() info = {} try: info['count'] = args['count'] except KeyError: info['count'] = 50 hmf_field = get_hmf_field(data['field_label']) gen_name = findvar(hmf_field['ideals']) nf = WebNumberField(data['field_label'], gen_name=gen_name) info['hmf_field'] = hmf_field info['field'] = nf info['base_galois_group'] = nf.galois_string() info['field_degree'] = nf.degree() info['field_disc'] = str(nf.disc()) info['field_poly'] = teXify_pol(str(nf.poly())) info.update(data) info['downloads'] = [('Modular form to Magma', url_for(".render_hmf_webpage_download", field_label=info['field_label'], label=info['label'], download_type='magma')), ('Eigenvalues to Sage', url_for(".render_hmf_webpage_download", field_label=info['field_label'], label=info['label'], download_type='sage'))] # figure out friends # first try to see if there is an instance of this HMF on Lfun db url = 'ModularForm/GL2/TotallyReal/{}/holomorphic/{}'.format( info['field_label'], info['label']) Lfun = get_lfunction_by_url(url) if Lfun: instances = get_instances_by_Lhash_and_trace_hash( Lfun['Lhash'], Lfun['degree'], Lfun['trace_hash']) # This will also add the EC/G2C, as this how the Lfun was computed info['friends'] = names_and_urls(instances, exclude={url}) info['friends'] += [('L-function', url_for("l_functions.l_function_hmf_page", field=info['field_label'], label=info['label'], character='0', number='0'))] else: # if there is no instance # old code if hmf_field['narrow_class_no'] == 1 and nf.disc( )**2 * data['level_norm'] < 40000: info['friends'] = [('L-function', url_for("l_functions.l_function_hmf_page", field=info['field_label'], label=info['label'], character='0', number='0'))] else: info['friends'] = [('L-function not available', "")] if data['dimension'] == 1: # Try to attach associated elliptic curve lab = split_class_label(info['label']) ec_from_hmf = db.ec_nfcurves.lookup(label + '1') if ec_from_hmf is None: info['friends'] += [('Elliptic curve not available', "")] else: info['friends'] += [('Isogeny class ' + info['label'], url_for("ecnf.show_ecnf_isoclass", nf=lab[0], conductor_label=lab[1], class_label=lab[2]))] bread = get_bread(data["label"]) t = "Hilbert cusp form %s" % info['label'] forms_dims = db.hmf_forms.search( { 'field_label': data['field_label'], 'level_ideal': data['level_ideal'] }, projection='dimension') info['newspace_dimension'] = sum(forms_dims) # Get hecke_polynomial, hecke_eigenvalues and AL_eigenvalues try: numeigs = request.args['numeigs'] numeigs = int(numeigs) except: numeigs = 20 info['numeigs'] = numeigs hecke_pol = data['hecke_polynomial'] eigs = [str(eig) for eig in data['hecke_eigenvalues']] eigs = eigs[:min(len(eigs), numeigs)] AL_eigs = data['AL_eigenvalues'] primes = hmf_field['primes'] n = min(len(eigs), len(primes)) info['eigs'] = [{ 'eigenvalue': add_space_if_positive(teXify_pol(eigs[i])), 'prime_ideal': teXify_pol(primes[i]), 'prime_norm': primes[i][1:primes[i].index(',')] } for i in range(n)] try: display_eigs = request.args['display_eigs'] if display_eigs in ['True', 'true', '1', 'yes']: display_eigs = True else: display_eigs = False except KeyError: display_eigs = False if 'numeigs' in request.args: display_eigs = True info['hecke_polynomial'] = r"\(" + teXify_pol(hecke_pol) + r"\)" if not AL_eigs: # empty list if data['level_norm'] == 1: # OK, no bad primes info['AL_eigs'] = 'none' else: # not OK, AL eigs are missing info['AL_eigs'] = 'missing' else: info['AL_eigs'] = [{ 'eigenvalue': teXify_pol(al[1]), 'prime_ideal': teXify_pol(al[0]), 'prime_norm': al[0][1:al[0].index(',')] } for al in data['AL_eigenvalues']] max_eig_len = max([len(eig['eigenvalue']) for eig in info['eigs']]) display_eigs = display_eigs or (max_eig_len <= 300) info['display_eigs'] = display_eigs if not display_eigs: for eig in info['eigs']: if len(eig['eigenvalue']) > 300: eig['eigenvalue'] = '...' info['level_ideal'] = teXify_pol(info['level_ideal']) if 'is_CM' in data: is_CM = data['is_CM'] else: is_CM = '?' info['is_CM'] = is_CM if 'is_base_change' in data: is_base_change = data['is_base_change'] else: is_base_change = '?' info['is_base_change'] = is_base_change if 'q_expansions' in data: info['q_expansions'] = data['q_expansions'] properties = [('Label', '%s' % data['label']), ('Base field', '%s' % info['field'].field_pretty()), ('Weight', '$%s$' % data['weight']), ('Level norm', prop_int_pretty(data['level_norm'])), ('Level', '$' + teXify_pol(data['level_ideal']) + '$'), ('Dimension', prop_int_pretty(data['dimension'])), ('CM', is_CM), ('Base change', is_base_change)] return render_template( "hilbert_modular_form.html", downloads=info["downloads"], info=info, properties=properties, credit=hmf_credit, title=t, bread=bread, friends=info['friends'], learnmore=learnmore_list(), KNOWL_ID="mf.hilbert.%s" % label, )
def render_sample_page(family, sam, args, bread): info = { 'args': to_dict(args), 'sam': sam, 'latex': latex, 'type': sam.type(), 'name': sam.name(), 'full_name': sam.full_name(), 'weight': sam.weight(), 'fdeg': sam.degree_of_field(), 'is_eigenform': sam.is_eigenform(), 'field_poly': sam.field_poly() } if sam.is_integral() is not None: info['is_integral'] = sam.is_integral() if 'Sp4Z' in sam.collection(): info['space_url'] = url_for('.Sp4Z_j_space', k=info['weight'], j=0) if 'Sp4Z_2' in sam.collection(): info['space_url'] = url_for('.Sp4Z_j_space', k=info['weight'], j=2) info['space'] = '$' + family.latex_name.replace( 'k', '{' + str(sam.weight()) + '}') + '$' if 'space_url' in info: bread.append((info['space'], info['space_url'])) info['space_href'] = '<a href="%s">%s</d>' % ( info['space_url'], info['space']) if 'space_url' in info else info['space'] if info['field_poly'].disc() < 10**10: label = poly_to_field_label(info['field_poly']) if label: info['field_label'] = label info['field_url'] = url_for('number_fields.by_label', label=label) info['field_href'] = '<a href="%s">%s</a>' % (info['field_url'], field_pretty(label)) bread.append((info['name'], '')) title = 'Siegel modular forms sample ' + info['full_name'] properties = [('Space', info['space_href']), ('Name', info['name']), ('Type', '<br>'.join(info['type'].split(','))), ('Weight', prop_int_pretty(info['weight'])), ('Hecke eigenform', "yes" if info['is_eigenform'] else "no"), ('Field degree', prop_int_pretty(info['fdeg']))] try: evs_to_show = parse_ints_to_list_flash(args.get('ev_index'), 'list of $l$') fcs_to_show = parse_ints_to_list_flash(args.get('fc_det'), 'list of $\\det(F)$') except ValueError: evs_to_show = [] fcs_to_show = [] info['evs_to_show'] = sorted([ n for n in (evs_to_show if len(evs_to_show) else sam.available_eigenvalues()[:10]) ]) info['fcs_to_show'] = sorted([ n for n in (fcs_to_show if len(fcs_to_show) else sam. available_Fourier_coefficients()[1:6]) ]) info['evs_avail'] = [n for n in sam.available_eigenvalues()] info['fcs_avail'] = [n for n in sam.available_Fourier_coefficients()] # Do not attempt to constuct a modulus ideal unless the field has a reasonably small discriminant # otherwise sage may not even be able to factor the discriminant info['field'] = sam.field() if info['field_poly'].disc() < 10**80: null_ideal = sam.field().ring_of_integers().ideal(0) info['modulus'] = null_ideal modulus = args.get('modulus', '').strip() m = 0 if modulus: try: O = sam.field().ring_of_integers() m = O.ideal([O(str(b)) for b in modulus.split(',')]) except Exception: info['error'] = True flash_error( "Unable to construct modulus ideal from specified generators %s.", modulus) if m == 1: info['error'] = True flash_error( "The ideal %s is the unit ideal, please specify a different modulus.", '(' + modulus + ')') m = 0 info['modulus'] = m # Hack to reduce polynomials and to handle non integral stuff def redc(c): return m.reduce(c * c.denominator()) / m.reduce(c.denominator()) def redp(f): c = f.dict() return f.parent()(dict((e, redc(c[e])) for e in c)) def safe_reduce(f): if not m: return latex(f) try: if f in sam.field(): return latex(redc(f)) else: return latex(redp(f)) except ZeroDivisionError: return '\\textrm{Unable to reduce} \\bmod\\mathfrak{m}' info['reduce'] = safe_reduce else: info['reduce'] = latex # check that explicit formula is not ridiculously big if sam.explicit_formula(): info['explicit_formula_bytes'] = len(sam.explicit_formula()) if len(sam.explicit_formula()) < 100000: info['explicit_formula'] = sam.explicit_formula() return render_template("ModularForm_GSp4_Q_sample.html", title=title, bread=bread, properties=properties, info=info)
def render_lattice_webpage(**args): f = None if 'label' in args: lab = clean_input(args.get('label')) if lab != args.get('label'): return redirect(url_for('.render_lattice_webpage', label=lab), 301) f = db.lat_lattices.lucky({'$or':[{'label': lab }, {'name': {'$contains': [lab]}}]}) if f is None: t = "Integral lattice search error" bread = get_bread() flash_error("%s is not a valid label or name for an integral lattice in the database.", lab) return render_template("lattice-error.html", title=t, properties=[], bread=bread, learnmore=learnmore_list()) info = {} info.update(f) info['friends'] = [] bread = get_bread(f['label']) info['dim']= int(f['dim']) info['det']= int(f['det']) info['level']=int(f['level']) info['gram']=vect_to_matrix(f['gram']) info['density']=str(f['density']) info['hermite']=str(f['hermite']) info['minimum']=int(f['minimum']) info['kissing']=int(f['kissing']) info['aut']=int(f['aut']) if f['shortest']=="": info['shortest']==f['shortest'] else: if f['dim']==1: info['shortest']=str(f['shortest']).strip('[').strip(']') else: if info['dim']*info['kissing']<100: info['shortest']=[str([tuple(v)]).strip('[').strip(']').replace('),', '), ') for v in f['shortest']] else: max_vect_num=min(int(round(100/(info['dim']))), int(round(info['kissing']/2))-1) info['shortest']=[str([tuple(f['shortest'][i])]).strip('[').strip(']').replace('),', '), ') for i in range(max_vect_num+1)] info['all_shortest']="no" info['download_shortest'] = [ (i, url_for(".render_lattice_webpage_download", label=info['label'], lang=i, obj='shortest_vectors')) for i in ['gp', 'magma','sage']] if f['name']==['Leech']: info['shortest']=[str([1,-2,-2,-2,2,-1,-1,3,3,0,0,2,2,-1,-1,-2,2,-2,-1,-1,0,0,-1,2]), str([1,-2,-2,-2,2,-1,0,2,3,0,0,2,2,-1,-1,-2,2,-1,-1,-2,1,-1,-1,3]), str([1,-2,-2,-1,1,-1,-1,2,2,0,0,2,2,0,0,-2,2,-1,-1,-1,0,-1,-1,2])] info['all_shortest']="no" info['download_shortest'] = [ (i, url_for(".render_lattice_webpage_download", label=info['label'], lang=i, obj='shortest_vectors')) for i in ['gp', 'magma','sage']] ncoeff=20 if f['theta_series'] != "": coeff=[f['theta_series'][i] for i in range(ncoeff+1)] info['theta_series']=my_latex(print_q_expansion(coeff)) info['theta_display'] = url_for(".theta_display", label=f['label'], number="") info['class_number']=int(f['class_number']) if f['dim']==1: info['genus_reps']=str(f['genus_reps']).strip('[').strip(']') else: if info['dim']*info['class_number']<50: info['genus_reps']=[vect_to_matrix(n) for n in f['genus_reps']] else: max_matrix_num=min(int(round(25/(info['dim']))), info['class_number']) info['all_genus_rep']="no" info['genus_reps']=[vect_to_matrix(f['genus_reps'][i]) for i in range(max_matrix_num+1)] info['download_genus_reps'] = [ (i, url_for(".render_lattice_webpage_download", label=info['label'], lang=i, obj='genus_reps')) for i in ['gp', 'magma','sage']] if f['name'] != "": if f['name']==str(f['name']): info['name']= str(f['name']) else: info['name']=str(", ".join(str(i) for i in f['name'])) else: info['name'] == "" info['comments']=str(f['comments']) if 'Leech' in info['comments']: # no need to duplicate as it is in the name info['comments'] = '' if info['name'] == "": t = "Integral lattice %s" % info['label'] else: t = "Integral lattice "+info['label']+" ("+info['name']+")" #This part code was for the dynamic knowl with comments, since the test is displayed this is redundant # if info['name'] != "" or info['comments'] !="": # info['knowl_args']= "name=%s&report=%s" %(info['name'], info['comments'].replace(' ', '-space-')) info['properties'] = [ ('Dimension', prop_int_pretty(info['dim'])), ('Determinant', prop_int_pretty(info['det'])), ('Level', prop_int_pretty(info['level']))] if info['class_number'] == 0: info['properties']=[('Class number', 'not available')]+info['properties'] else: info['properties']=[('Class number', prop_int_pretty(info['class_number']))]+info['properties'] info['properties']=[('Label', '%s' % info['label'])]+info['properties'] if info['name'] != "" : info['properties']=[('Name','%s' % info['name'] )]+info['properties'] # friends = [('L-series (not available)', ' ' ),('Half integral weight modular forms (not available)', ' ')] return render_template("lattice-single.html", info=info, title=t, bread=bread, properties=info['properties'], learnmore=learnmore_list(), KNOWL_ID="lattice.%s"%info['label'])
def make_form(self, nap0=50): # To start with the data fields of self are just those from # the database. We need to reformat these and compute some # further (easy) data about it. # from lmfdb.ecnf.WebEllipticCurve import FIELD self.field = FIELD(self.field_label) pretty_field = field_pretty(self.field_label) self.field_knowl = nf_display_knowl(self.field_label, pretty_field) try: dims = db.bmf_dims.lucky( { 'field_label': self.field_label, 'level_label': self.level_label }, projection='gl2_dims') self.newspace_dimension = dims[str(self.weight)]['new_dim'] except TypeError: self.newspace_dimension = 'not available' self.newspace_label = "-".join([self.field_label, self.level_label]) self.newspace_url = url_for(".render_bmf_space_webpage", field_label=self.field_label, level_label=self.level_label) K = self.field.K() # 'hecke_poly_obj' is the non-LaTeX version of hecke_poly self.hecke_poly_obj = self.hecke_poly if self.dimension > 1: Qx = PolynomialRing(QQ, 'x') self.hecke_poly = Qx(str(self.hecke_poly)) F = NumberField(self.hecke_poly, 'z') self.hecke_poly = web_latex(self.hecke_poly) def conv(ap): if '?' in ap: return 'not known' else: return F(str(ap)) self.hecke_eigs = [conv(str(ap)) for ap in self.hecke_eigs] self.level = ideal_from_label(K, self.level_label) self.level_ideal2 = web_latex(self.level) badp = self.level.prime_factors() self.nap = len(self.hecke_eigs) self.nap0 = min(nap0, self.nap) self.neigs = self.nap0 + len(badp) self.hecke_table = [[ web_latex(p.norm()), ideal_label(p), web_latex(p.gens_reduced()[0]), web_latex(ap) ] for p, ap in zip(primes_iter(K), self.hecke_eigs[:self.neigs]) if not p in badp] self.have_AL = self.AL_eigs[0] != '?' if self.have_AL: self.AL_table = [[ web_latex(p.norm()), ideal_label(p), web_latex(p.gens_reduced()[0]), web_latex(ap) ] for p, ap in zip(badp, self.AL_eigs)] # The following helps to create Sage download data self.AL_table_data = [[p.gens_reduced(), ap] for p, ap in zip(badp, self.AL_eigs)] self.sign = 'not determined' try: if self.sfe == 1: self.sign = "$+1$" elif self.sfe == -1: self.sign = "$-1$" except AttributeError: self.sfe = '?' if self.Lratio == '?': self.Lratio = "not determined" self.anrank = "not determined" else: self.Lratio = QQ(self.Lratio) self.anrank = r"\(0\)" if self.Lratio != 0 else "odd" if self.sfe == -1 else r"\(\ge2\), even" self.properties = [('Label', self.label), ('Base field', pretty_field), ('Weight', prop_int_pretty(self.weight)), ('Level norm', prop_int_pretty(self.level_norm)), ('Level', self.level_ideal2), ('Dimension', prop_int_pretty(self.dimension))] try: if self.CM == '?': self.CM = 'not determined' elif self.CM == 0: self.CM = 'no' else: if int(self.CM) % 4 in [2, 3]: self.CM = 4 * int(self.CM) self.CM = "$%s$" % self.CM except AttributeError: self.CM = 'not determined' self.properties.append(('CM', str(self.CM))) self.bc_extra = '' self.bcd = 0 self.bct = self.bc != '?' and self.bc != 0 if self.bc == '?': self.bc = 'not determined' elif self.bc == 0: self.bc = 'no' elif self.bc == 1: self.bcd = self.bc self.bc = 'yes' elif self.bc > 1: self.bcd = self.bc self.bc = 'yes' self.bc_extra = r', of a form over \(\mathbb{Q}\) with coefficients in \(\mathbb{Q}(\sqrt{' + str( self.bcd) + r'})\)' elif self.bc == -1: self.bc = 'no' self.bc_extra = r', but is a twist of the base change of a form over \(\mathbb{Q}\)' elif self.bc < -1: self.bcd = -self.bc self.bc = 'no' self.bc_extra = r', but is a twist of the base change of a form over \(\mathbb{Q}\) with coefficients in \(\mathbb{Q}(\sqrt{' + str( self.bcd) + r'})\)' self.properties.append(('Base change', str(self.bc))) curve_bc = db.ec_nfcurves.lucky({'class_label': self.label}, projection="base_change") if curve_bc is not None: if curve_bc and "." not in curve_bc[0]: curve_bc = [ cremona_label_to_lmfdb_label(lab) for lab in curve_bc ] self.ec_status = 'exists' self.ec_url = url_for("ecnf.show_ecnf_isoclass", nf=self.field_label, conductor_label=self.level_label, class_label=self.label_suffix) curve_bc_parts = [split_lmfdb_label(lab) for lab in curve_bc] bc_urls = [ url_for("cmf.by_url_newform_label", level=cond, weight=2, char_orbit_label='a', hecke_orbit=iso) for cond, iso, num in curve_bc_parts ] bc_labels = [ ".".join([str(cond), str(2), 'a', iso]) for cond, iso, _ in curve_bc_parts ] bc_exists = [db.mf_newforms.label_exists(lab) for lab in bc_labels] self.bc_forms = [{ 'exists': ex, 'label': lab, 'url': url } for ex, lab, url in zip(bc_exists, bc_labels, bc_urls)] else: self.bc_forms = [] if self.bct or self.label in bmfs_with_no_curve: self.ec_status = 'none' else: self.ec_status = 'missing' self.properties.append(('Sign', self.sign)) self.properties.append(('Analytic rank', self.anrank)) self.friends = [] self.friends += [('Newspace {}'.format(self.newspace_label), self.newspace_url)] url = 'ModularForm/GL2/ImaginaryQuadratic/{}'.format( self.label.replace('-', '/')) Lfun = get_lfunction_by_url(url) if Lfun: instances = get_instances_by_Lhash_and_trace_hash( Lfun['Lhash'], Lfun['degree'], Lfun['trace_hash']) # This will also add the EC/G2C, as this how the Lfun was computed # and not add itself self.friends = names_and_urls(instances, exclude={url}) self.friends.append(('L-function', '/L/' + url)) else: # old code if self.dimension == 1: if self.ec_status == 'exists': self.friends += [('Isogeny class {}'.format(self.label), self.ec_url)] elif self.ec_status == 'missing': self.friends += [ ('Isogeny class {} missing'.format(self.label), "") ] else: self.friends += [('No elliptic curve', "")] self.friends += [('L-function not available', '')]
def make_galmap_object(self, galmap): from lmfdb.belyi.main import url_for_belyi_passport_label # all information about the map goes in the data dictionary # most of the data from the database gets polished/formatted before we put it in the data dictionary data = self.data = {} # the stuff that does not need to be polished for elt in ("label", "plabel", "triples_cyc", "orbit_size", "g", "abc", "deg"): data[elt] = galmap[elt] nt = galmap["group"].split("T") data["group"] = group_display_knowl(int(nt[0]), int(nt[1])) data["geomtype"] = geomtypelet_to_geomtypename_dict[galmap["geomtype"]] data["lambdas"] = [str(c)[1:-1] for c in galmap["lambdas"]] data["isQQ"] = False data["in_LMFDB"] = False F = belyi_base_field(galmap) if F._data is None: fld_coeffs = galmap["base_field"] pol = PolynomialRing(QQ, "x")(fld_coeffs) data["base_field"] = latex(pol) else: data["in_LMFDB"] = True if F.poly().degree() == 1: data["isQQ"] = True F.latex_poly = web_latex(F.poly()) data["base_field"] = F crv_str = galmap["curve"] if crv_str == "PP1": data["curve"] = r"\mathbb{P}^1" else: data["curve"] = make_curve_latex(crv_str) #if galmap['curve_label']: # data['curve_label'] = galmap['curve_label'] # change pairs of floats to complex numbers embeds = galmap["embeddings"] embed_strs = [] for el in embeds: if el[1] < 0: el_str = str(el[0]) + str(el[1]) + r"\sqrt{-1}" else: el_str = str(el[0]) + "+" + str(el[1]) + r"\sqrt{-1}" embed_strs.append(el_str) data["map"] = make_map_latex(galmap["map"]) data["embeddings_and_triples"] = [] if data["isQQ"]: for i in range(0, len(data["triples_cyc"])): triple_cyc = data["triples_cyc"][i] data["embeddings_and_triples"].append([ r"\text{not applicable (over $\mathbb{Q}$)}", triple_cyc[0], triple_cyc[1], triple_cyc[2], ]) else: for i in range(0, len(data["triples_cyc"])): triple_cyc = data["triples_cyc"][i] data["embeddings_and_triples"].append([ embed_strs[i], triple_cyc[0], triple_cyc[1], triple_cyc[2] ]) data["lambdas"] = [str(c)[1:-1] for c in galmap["lambdas"]] # Properties self.plot = db.belyi_galmap_portraits.lucky({"label": galmap['label']}, projection="portrait") plot_link = '<a href="{0}"><img src="{0}" width="200" height="200" style="background-color: white;"/></a>'.format( self.plot) properties = [("Label", galmap["label"])] if self.plot: properties += [(None, plot_link)] properties += [ ("Group", str(galmap["group"])), ("Orders", "$%s$" % (galmap["abc"])), ("Genus", prop_int_pretty(galmap["g"])), ("Size", prop_int_pretty(galmap["orbit_size"])), ] self.properties = properties # Friends self.friends = [("Passport", url_for_belyi_passport_label(galmap["plabel"]))] self.friends.extend(names_and_urls(galmap['friends'])) # Downloads if galmap["g"] <= 2: self.downloads = [ ( "Code to Magma", url_for(".belyi_galmap_magma_download", label=data["label"]), ), ( "Code to SageMath", url_for(".belyi_galmap_sage_download", label=data["label"]), ), ( "All data to text", url_for(".belyi_galmap_text_download", label=data["label"]), ), ] else: self.downloads = [] # Breadcrumbs label_spl = data["label"].split("-") groupstr = label_spl[0] letnum = label_spl[2] gstr = str(data['g']) sigmas = label_spl[1] sigma0, sigma1, sigmaoo = sigmas.split("_") abcstr = str(data['abc']).replace(' ', '') # does lambdasstr need to be updated? lambdasstr = "%s-%s-%s" % (sigma0, sigma1, sigmaoo) lambdasgstr = lambdasstr + "-" + gstr self.bread = [ ("Belyi Maps", url_for(".index")), (groupstr, url_for(".by_url_belyi_search_group", group=groupstr)), ( abcstr, url_for(".by_url_belyi_search_group_triple", group=groupstr, abc=abcstr), ), ( lambdasgstr, url_for( ".by_url_belyi_passport_label", group=groupstr, abc=abcstr, sigma0=sigma0, sigma1=sigma1, sigmaoo=sigmaoo, g=gstr, ), ), ( letnum, url_for( ".by_url_belyi_galmap_label", group=groupstr, abc=abcstr, sigma0=sigma0, sigma1=sigma1, sigmaoo=sigmaoo, g=gstr, letnum=letnum, ), ), ] # Title self.title = "Belyi map orbit " + data["label"] # Code snippets (only for curves) self.code = {} return
def render_group_webpage(args): data = {} if 'label' in args: label = clean_input(args['label']) label = label.replace('t', 'T') data = db.gps_transitive.lookup(label) if data is None: if re.match(r'^\d+T\d+$', label): flash_error("Group %s was not found in the database.", label) else: flash_error("%s is not a valid label for a Galois group.", label) return redirect(url_for(".index")) title = 'Galois group: ' + label wgg = WebGaloisGroup.from_nt(data['n'], data['t']) data['wgg'] = wgg n = data['n'] t = data['t'] data['yesno'] = yesno order = data['order'] data['orderfac'] = latex(ZZ(order).factor()) orderfac = latex(ZZ(order).factor()) data['ordermsg'] = "$%s=%s$" % (order, latex(orderfac)) if order == 1: data['ordermsg'] = "$1$" if ZZ(order).is_prime(): data['ordermsg'] = "$%s$ (is prime)" % order pgroup = len(ZZ(order).prime_factors()) < 2 if wgg.num_conjclasses() < 50: data['cclasses'] = wgg.conjclasses() if ZZ(order) < ZZ(10000000) and wgg.num_conjclasses() < 21: data['chartable'] = chartable(n, t) data['gens'] = wgg.generator_string() if n == 1 and t == 1: data['gens'] = 'None needed' data['num_cc'] = comma(wgg.num_conjclasses()) data['parity'] = "$%s$" % data['parity'] data['subinfo'] = subfield_display(n, data['subfields']) data['resolve'] = resolve_display(data['quotients']) if data['gapid'] == 0: data['gapid'] = "not available" else: data['gapid'] = small_group_display_knowl( int(data['order']), int(data['gapid']), str([int(data['order']), int(data['gapid'])])) data['otherreps'] = wgg.otherrep_list() ae = data['arith_equiv'] if ae > 0: if ae > 1: data[ 'arith_equiv'] = r'A number field with this Galois group has %d <a knowl="nf.arithmetically_equivalent", title="arithmetically equivalent">arithmetically equivalent</a> fields.' % ae else: data[ 'arith_equiv'] = r'A number field with this Galois group has exactly one <a knowl="nf.arithmetically_equivalent", title="arithmetically equivalent">arithmetically equivalent</a> field.' elif ae > -1: data[ 'arith_equiv'] = r'A number field with this Galois group has no <a knowl="nf.arithmetically_equivalent", title="arithmetically equivalent">arithmetically equivalent</a> fields.' else: data[ 'arith_equiv'] = r'Data on whether or not a number field with this Galois group has <a knowl="nf.arithmetically_equivalent", title="arithmetically equivalent">arithmetically equivalent</a> fields has not been computed.' intreps = list(db.gps_gmodules.search({'n': n, 't': t})) if len(intreps) > 0: data['int_rep_classes'] = [str(z[0]) for z in intreps[0]['gens']] for onerep in intreps: onerep['gens'] = [ list_to_latex_matrix(z[1]) for z in onerep['gens'] ] data['int_reps'] = intreps data['int_reps_complete'] = int_reps_are_complete(intreps) dcq = data['moddecompuniq'] if dcq[0] == 0: data['decompunique'] = 0 else: data['decompunique'] = dcq[0] data['isoms'] = [[mult2mult(z[0]), mult2mult(z[1])] for z in dcq[1]] data['isoms'] = [[ modules2string(n, t, z[0]), modules2string(n, t, z[1]) ] for z in data['isoms']] #print dcq[1] #print data['isoms'] friends = [] if db.nf_fields.exists({'galois_label': "%dT%d" % (n, t)}): friends.append( ('Number fields with this Galois group', url_for('number_fields.number_field_render_webpage') + "?galois_group=%dT%d" % (n, t))) prop2 = [ ('Label', label), ('Degree', prop_int_pretty(data['n'])), ('Order', prop_int_pretty(order)), ('Cyclic', yesno(data['cyc'])), ('Abelian', yesno(data['ab'])), ('Solvable', yesno(data['solv'])), ('Primitive', yesno(data['prim'])), ('$p$-group', yesno(pgroup)), ] pretty = group_display_short(n, t, emptyifnotpretty=True) if len(pretty) > 0: prop2.extend([('Group:', pretty)]) data['pretty_name'] = pretty data['name'] = re.sub(r'_(\d+)', r'_{\1}', data['name']) data['name'] = re.sub(r'\^(\d+)', r'^{\1}', data['name']) data['nilpotency'] = '$%s$' % data['nilpotency'] if data['nilpotency'] == '$-1$': data['nilpotency'] += ' (not nilpotent)' bread = get_bread([(label, ' ')]) return render_template("gg-show-group.html", credit=GG_credit, title=title, bread=bread, info=data, properties=prop2, friends=friends, KNOWL_ID="gg.%s" % label, learnmore=learnmore_list())
def make_curve(self): # To start with the data fields of self are just those from # the database. We need to reformat these. # Old version: required constructing the actual elliptic curve # E, and computing some further data about it. # New version (May 2016): extra data fields now in the # database so we do not have to construct the curve or do any # computation with it on the fly. As a failsafe the old way # is still included. data = self.data = {} data['ainvs'] = [ZZ(ai) for ai in self.ainvs] data['conductor'] = N = ZZ(self.conductor) data['j_invariant'] = QQ(str(self.jinv)) data['j_inv_factor'] = latex(0) if data['j_invariant']: # don't factor 0 data['j_inv_factor'] = latex(data['j_invariant'].factor()) data['j_inv_latex'] = web_latex(data['j_invariant']) # extract data about MW rank, generators, heights and torsion: self.make_mw() # get more data from the database entry data['equation'] = self.equation local_data = self.local_data D = self.signD * prod([ld['p']**ld['ord_disc'] for ld in local_data]) for ld in local_data: ld['kod'] = ld['kod'].replace("\\\\", "\\") data['disc'] = D Nfac = Factorization([(ZZ(ld['p']), ld['ord_cond']) for ld in local_data]) Dfac = Factorization([(ZZ(ld['p']), ld['ord_disc']) for ld in local_data], unit=ZZ(self.signD)) data['minq_D'] = minqD = self.min_quad_twist['disc'] data['minq_label'] = self.min_quad_twist[ 'lmfdb_label'] if self.label_type == 'LMFDB' else self.min_quad_twist[ 'label'] data['minq_info'] = '(itself)' if minqD == 1 else '(by {})'.format( minqD) if self.degree is None: data['degree'] = 0 # invalid, but will be displayed nicely else: data['degree'] = self.degree try: data['an'] = self.anlist data['ap'] = self.aplist except AttributeError: r = db.ec_curves.lucky({'lmfdb_iso': self.lmfdb_iso, 'number': 1}) data['an'] = r['anlist'] data['ap'] = r['aplist'] data['disc_factor'] = latex(Dfac) data['cond_factor'] = latex(Nfac) data['disc_latex'] = web_latex(D) data['cond_latex'] = web_latex(N) data['galois_images'] = [ trim_galois_image_code(s) for s in self.mod_p_images ] data['non_maximal_primes'] = self.non_maximal_primes data['galois_data'] = [{ 'p': p, 'image': im } for p, im in zip(data['non_maximal_primes'], data['galois_images'])] data['CMD'] = self.cm data['CM'] = "no" data['EndE'] = r"\(\Z\)" if self.cm: data['cm_ramp'] = [ p for p in ZZ(self.cm).support() if not p in self.non_maximal_primes ] data['cm_nramp'] = len(data['cm_ramp']) if data['cm_nramp'] == 1: data['cm_ramp'] = data['cm_ramp'][0] else: data['cm_ramp'] = ", ".join([str(p) for p in data['cm_ramp']]) data['cm_sqf'] = ZZ(self.cm).squarefree_part() data['CM'] = r"yes (\(D=%s\))" % data['CMD'] if data['CMD'] % 4 == 0: d4 = ZZ(data['CMD']) // 4 data['EndE'] = r"\(\Z[\sqrt{%s}]\)" % d4 else: data['EndE'] = r"\(\Z[(1+\sqrt{%s})/2]\)" % data['CMD'] data['ST'] = st_link_by_name(1, 2, 'N(U(1))') else: data['ST'] = st_link_by_name(1, 2, 'SU(2)') data['p_adic_primes'] = [ p for i, p in enumerate(prime_range(5, 100)) if (N * data['ap'][i]) % p != 0 ] cond, iso, num = split_lmfdb_label(self.lmfdb_label) self.one_deg = ZZ(self.class_deg).is_prime() isodegs = [str(d) for d in self.isogeny_degrees if d > 1] if len(isodegs) < 3: data['isogeny_degrees'] = " and ".join(isodegs) else: data['isogeny_degrees'] = " and ".join( [", ".join(isodegs[:-1]), isodegs[-1]]) if self.twoadic_gens: from sage.matrix.all import Matrix data['twoadic_gen_matrices'] = ','.join( [latex(Matrix(2, 2, M)) for M in self.twoadic_gens]) data[ 'twoadic_rouse_url'] = ROUSE_URL_PREFIX + self.twoadic_label + ".html" # Leading term of L-function & other BSD data self.make_bsd() # Optimality (the optimal curve in the class is the curve # whose Cremona label ends in '1' except for '990h' which was # labelled wrongly long ago): this is proved for N up to # OPTIMALITY_BOUND (and when there is only one curve in an # isogeny class, obviously) and expected for all N. # Column 'optimality' is 1 for certainly optimal curves, 0 for # certainly non-optimal curves, and is n>1 if the curve is one # of n in the isogeny class which may be optimal given current # knowledge. # Column "manin_constant' is the correct Manin constant # assuming that the optimal curve in the class is known, or # otherwise if it is the curve with (Cremona) number 1. # The code here allows us to update the display correctly by # changing one line in this file (defining OPTIMALITY_BOUND) # without changing the data. data['optimality_bound'] = OPTIMALITY_BOUND data[ 'manin_constant'] = self.manin_constant # (conditional on data['optimality_known']) if N < OPTIMALITY_BOUND: data['optimality_code'] = int( self.number == (3 if self.iso == '990h' else 1)) data['optimality_known'] = True data['manin_known'] = True if self.label_type == 'Cremona': data[ 'optimal_label'] = '990h3' if self.iso == '990h' else self.iso + '1' else: data[ 'optimal_label'] = '990.i3' if self.lmfdb_iso == '990.i' else self.lmfdb_iso + '1' else: data['optimality_code'] = self.optimality data['optimality_known'] = (self.optimality < 2) if self.optimality == 1: data['manin_known'] = True data[ 'optimal_label'] = self.label if self.label_type == 'Cremona' else self.lmfdb_label else: if self.number == 1: data['manin_known'] = False data[ 'optimal_label'] = self.label if self.label_type == 'Cremona' else self.lmfdb_label else: # find curve #1 in this class and its optimailty code: opt_curve = db.ec_curves.lucky( { 'iso': self.iso, 'number': 1 }, projection=['label', 'lmfdb_label', 'optimality']) data['manin_known'] = (opt_curve['optimality'] == 1) data['optimal_label'] = opt_curve[ 'label' if self.label_type == 'Cremona' else 'lmfdb_label'] data['p_adic_data_exists'] = False if data['optimality_code'] == 1: data['p_adic_data_exists'] = db.ec_padic.exists( {'lmfdb_iso': self.lmfdb_iso}) # Iwasawa data (where present) self.make_iwasawa() # Torsion growth data (where present) self.make_torsion_growth() data['newform'] = web_latex( PowerSeriesRing(QQ, 'q')(data['an'], 20, check=True)) data['newform_label'] = self.newform_label = ".".join( [str(cond), str(2), 'a', iso]) self.newform_link = url_for("cmf.by_url_newform_label", level=cond, weight=2, char_orbit_label='a', hecke_orbit=iso) self.newform_exists_in_db = db.mf_newforms.label_exists( self.newform_label) self._code = None if self.label_type == 'Cremona': self.class_url = url_for(".by_ec_label", label=self.iso) self.class_name = self.iso else: self.class_url = url_for(".by_double_iso_label", conductor=N, iso_label=iso) self.class_name = self.lmfdb_iso data['class_name'] = self.class_name data['number'] = self.number self.friends = [('Isogeny class ' + self.class_name, self.class_url), ('Minimal quadratic twist %s %s' % (data['minq_info'], data['minq_label']), url_for(".by_ec_label", label=data['minq_label'])), ('All twists ', url_for(".rational_elliptic_curves", jinv=self.jinv))] lfun_url = url_for("l_functions.l_function_ec_page", conductor_label=N, isogeny_class_label=iso) origin_url = lfun_url.lstrip('/L/').rstrip('/') if db.lfunc_instances.exists({'url': origin_url}): self.friends += [('L-function', lfun_url)] else: self.friends += [('L-function not available', "")] if not self.cm: if N <= 300: self.friends += [('Symmetric square L-function', url_for("l_functions.l_function_ec_sym_page", power='2', conductor=N, isogeny=iso))] if N <= 50: self.friends += [('Symmetric cube L-function', url_for("l_functions.l_function_ec_sym_page", power='3', conductor=N, isogeny=iso))] if self.newform_exists_in_db: self.friends += [('Modular form ' + self.newform_label, self.newform_link)] self.downloads = [('q-expansion to text', url_for(".download_EC_qexp", label=self.lmfdb_label, limit=1000)), ('All stored data to text', url_for(".download_EC_all", label=self.lmfdb_label)), ('Code to Magma', url_for(".ec_code_download", conductor=cond, iso=iso, number=num, label=self.lmfdb_label, download_type='magma')), ('Code to SageMath', url_for(".ec_code_download", conductor=cond, iso=iso, number=num, label=self.lmfdb_label, download_type='sage')), ('Code to GP', url_for(".ec_code_download", conductor=cond, iso=iso, number=num, label=self.lmfdb_label, download_type='gp'))] try: self.plot = encode_plot(self.E.plot()) except AttributeError: self.plot = encode_plot(EllipticCurve(data['ainvs']).plot()) self.plot_link = '<a href="{0}"><img src="{0}" width="200" height="150"/></a>'.format( self.plot) self.properties = [ ('Label', self.label if self.label_type == 'Cremona' else self.lmfdb_label), (None, self.plot_link), ('Conductor', prop_int_pretty(data['conductor'])), ('Discriminant', prop_int_pretty(data['disc'])), ('j-invariant', '%s' % data['j_inv_latex']), ('CM', '%s' % data['CM']), ('Rank', prop_int_pretty(self.mw['rank'])), ('Torsion structure', (r'\(%s\)' % self.mw['tor_struct']) if self.mw['tor_struct'] else 'trivial'), ] if self.label_type == 'Cremona': self.title = "Elliptic curve with Cremona label {} (LMFDB label {})".format( self.label, self.lmfdb_label) else: self.title = "Elliptic curve with LMFDB label {} (Cremona label {})".format( self.lmfdb_label, self.label) self.bread = [('Elliptic curves', url_for("ecnf.index")), (r'$\Q$', url_for(".rational_elliptic_curves")), ('%s' % N, url_for(".by_conductor", conductor=N)), ('%s' % iso, url_for(".by_double_iso_label", conductor=N, iso_label=iso)), ('%s' % num, ' ')]
def __init__(self, data): # Need to set mf_dim, eis_dim, cusp_dim, new_dim, old_dim self.__dict__.update(data) self.factored_level = web_latex_factored_integer(self.level, equals=True) self.has_projective_image_types = all(typ + '_dim' in data for typ in ('dihedral', 'a4', 's4', 'a5')) # The following can be removed once we change the behavior of lucky to include Nones self.num_forms = data.get('num_forms') self.trace_bound = data.get('trace_bound') self.has_trace_form = (data.get('traces') is not None) self.char_conrey = self.conrey_indexes[0] self.char_conrey_str = r'\chi_{%s}(%s,\cdot)' % (self.level, self.char_conrey) self.newforms = list( db.mf_newforms.search({'space_label': self.label}, projection=2)) oldspaces = db.mf_subspaces.search( { 'label': self.label, 'sub_level': { '$ne': self.level } }, [ 'sub_level', 'sub_char_orbit_index', 'sub_conrey_indexes', 'sub_mult' ]) self.oldspaces = [(old['sub_level'], old['sub_char_orbit_index'], old['sub_conrey_indexes'][0], old['sub_mult']) for old in oldspaces] self.dim_grid = DimGrid.from_db(data) self.plot = db.mf_newspace_portraits.lookup(self.label, projection="portrait") # Properties self.properties = [('Label', self.label)] if self.plot is not None and self.dim > 0: self.properties += [ (None, '<img src="{0}" width="200" height="200"/>'.format(self.plot)) ] self.properties += [ ('Level', prop_int_pretty(self.level)), ('Weight', prop_int_pretty(self.weight)), ('Character orbit', '%s.%s' % (self.level, self.char_orbit_label)), ('Rep. character', '$%s$' % self.char_conrey_str), ('Character field', r'$\Q%s$' % ('' if self.char_degree == 1 else r'(\zeta_{%s})' % self.char_order)), ('Dimension', prop_int_pretty(self.dim)), ] if self.num_forms is not None: self.properties.append( ('Newform subspaces', prop_int_pretty(self.num_forms))) self.properties.append( ('Sturm bound', prop_int_pretty(self.sturm_bound))) if data.get('trace_bound') is not None: self.properties.append( ('Trace bound', prop_int_pretty(self.trace_bound))) # Work around search results not including None if data.get('num_forms') is None: self.num_forms = None # Breadcrumbs self.bread = get_bread(level=self.level, weight=self.weight, char_orbit_label=self.char_orbit_label) # Downloads self.downloads = [ ('Trace form to text', url_for('cmf.download_traces', label=self.label)), ('All stored data to text', url_for('.download_newspace', label=self.label)), ] if self.conrey_indexes[0] == 1: self.trivial_character = True character_str = "trivial character" if self.dim == 0: self.dim_str = r"\(%s\)" % (self.dim) else: self.minus_dim = self.dim - self.plus_dim self.dim_str = r"\(%s + %s\)" % (self.plus_dim, self.minus_dim) else: self.trivial_character = False character_str = r"Character {level}.{orbit_label}".format( level=self.level, orbit_label=self.char_orbit_label) # character_str = r"Character \(\chi_{{{level}}}({conrey}, \cdot)\)".format(level=self.level, conrey=self.conrey_indexes[0]) self.dim_str = r"\(%s\)" % (self.dim) self.title = r"Space of modular forms of level %s, weight %s, and %s" % ( self.level, self.weight, character_str) gamma1_link = '/ModularForm/GL2/Q/holomorphic/%d/%d' % (self.level, self.weight) self.friends = [('Newspace %d.%d' % (self.level, self.weight), gamma1_link)]
def __init__(self, galmap, triple=None): from lmfdb.belyi.main import url_for_belyi_passport_label, url_for_belyi_galmap_label # all information about the map goes in the data dictionary # most of the data from the database gets polished/formatted before we put it in the data dictionary data = self.data = {} # the stuff that does not need to be polished for elt in ("label", "plabel", "triples_cyc", "orbit_size", "g", "abc", "deg", "primitivization", "is_primitive"): data[elt] = galmap[elt] if triple: data["label"] += '-' + (triple).replace(' ', '') data["triple"] = triple data["group"] = transitive_group_display_knowl(galmap["group"]) data["geomtype"] = geomtypelet_to_geomtypename_dict[galmap["geomtype"]] data["lambdas"] = [str(c)[1:-1] for c in galmap["lambdas"]] data["primitivization_url"] = url_for_belyi_galmap_label( data['primitivization']) data["isQQ"] = False data["in_LMFDB"] = False F = belyi_base_field(galmap) if F._data is None: fld_coeffs = galmap["base_field"] pol = PolynomialRing(QQ, "t")(fld_coeffs) data["base_field"] = latex(pol) else: data["in_LMFDB"] = True if F.poly().degree() == 1: data["isQQ"] = True F.latex_poly = web_latex(F.poly(var="t")) data["base_field"] = F data['embeddings'] = galmap['embeddings'] # change pairs of floats to complex numbers embed_strs = [] for el in galmap["embeddings"]: if el[1] < 0: el_str = str(el[0]) + str(el[1]) + r"\sqrt{-1}" else: el_str = str(el[0]) + "+" + str(el[1]) + r"\sqrt{-1}" embed_strs.append(el_str) data["embeddings_and_triples"] = [] self.triple = None self.embedding = None for i in range(0, len(data["triples_cyc"])): my_dict = {} triple_str = ', '.join(data['triples_cyc'][i]) triple_link = triple_str.replace(' ', '') if triple_link == triple: self.triple = data['triples_cyc'][i] self.embedding = CC(data['embeddings'][i]) my_dict['triple'] = triple_str my_dict['triple_link'] = triple_link if data["isQQ"]: my_dict[ 'embedding'] = r"\text{not applicable (over $\mathbb{Q}$)}" else: my_dict['embedding'] = embed_strs[i] data['embeddings_and_triples'].append(my_dict) crv_str = galmap["curve"] if crv_str == "PP1": data["curve"] = r"\mathbb{P}^1" else: data["curve"] = make_curve_latex(crv_str, nu=self.embedding) data["map"] = make_map_latex(galmap["map"], nu=self.embedding) data["lambdas"] = [str(c)[1:-1] for c in galmap["lambdas"]] # Properties self.plot = db.belyi_galmap_portraits.lucky({"label": galmap['label']}, projection="portrait") plot_link = '<a href="{0}"><img src="{0}" width="200" height="200" style="background-color: white;"/></a>'.format( self.plot) properties = [("Label", galmap["label"])] if triple: properties += [("Triple", "$%s$" % triple)] if self.plot: properties += [(None, plot_link)] properties += [ ("Group", str(galmap["group"])), ("Orders", "$%s$" % (data["abc"])), ("Genus", prop_int_pretty(data["g"])), ("Size", prop_int_pretty(data["orbit_size"])), ] self.properties = properties # Friends self.friends = [("Passport", url_for_belyi_passport_label(galmap["plabel"]))] if galmap['label'] != galmap['primitivization']: self.friends.append( ("Primitivization", url_for_belyi_galmap_label(galmap["primitivization"]))) self.friends.extend(names_and_urls(galmap['friends'])) #add curve link, if in LMFDB if 'curve_label' in galmap.keys(): data['curve_label'] = galmap['curve_label'] for name, url in self.friends: if "curve" in name.lower() and data['curve_label'] in name: data["curve_url"] = url # Downloads if galmap["g"] <= 2: data_label = data["label"] if triple: spl = data_label.split("-") data_label = "-".join(spl[0:-1]) self.downloads = [ ( "Code to Magma", url_for(".belyi_galmap_magma_download", label=data_label), ), ( "Code to SageMath", url_for(".belyi_galmap_sage_download", label=data_label), ), ( "All data to text", url_for(".belyi_galmap_text_download", label=data_label), ), ] else: self.downloads = [] # Breadcrumbs label_spl = data["label"].split("-") groupstr = label_spl[0] letnum = label_spl[2] gstr = str(data['g']) sigmas = label_spl[1] sigma0, sigma1, sigmaoo = sigmas.split("_") abcstr = str(data['abc']).replace(' ', '') # does lambdasstr need to be updated? lambdasstr = "%s-%s-%s" % (sigma0, sigma1, sigmaoo) lambdasgstr = lambdasstr + "-" + gstr self.bread = [ ("Belyi Maps", url_for(".index")), (groupstr, url_for(".by_url_belyi_search_group", group=groupstr)), ( abcstr, url_for(".by_url_belyi_search_group_triple", group=groupstr, abc=abcstr), ), ( lambdasgstr, url_for( ".by_url_belyi_passport_label", group=groupstr, abc=abcstr, sigma0=sigma0, sigma1=sigma1, sigmaoo=sigmaoo, g=gstr, ), ), ( letnum, url_for( ".by_url_belyi_galmap_label", group=groupstr, abc=abcstr, sigma0=sigma0, sigma1=sigma1, sigmaoo=sigmaoo, g=gstr, letnum=letnum, ), ), ] # Title if self.triple: self.title = "Embedded Belyi map " + data["label"] else: self.title = "Belyi map orbit " + data["label"] # Code snippets (only for curves) self.code = {} self.__dict__.update(data) return
def make_object(self, curve, endo, tama, ratpts, clus, is_curve): from lmfdb.genus2_curves.main import url_for_curve_label # all information about the curve, its Jacobian, isogeny class, and endomorphisms goes in the data dictionary # most of the data from the database gets polished/formatted before we put it in the data dictionary data = self.data = {} data['label'] = curve['label'] if is_curve else curve['class'] data['slabel'] = data['label'].split('.') # set attributes common to curves and isogeny classes here data['Lhash'] = str(curve['Lhash']) data['cond'] = ZZ(curve['cond']) data['cond_factor_latex'] = web_latex_factored_integer(data['cond']) data['analytic_rank'] = ZZ(curve['analytic_rank']) data['mw_rank'] = ZZ(0) if curve.get('mw_rank') is None else ZZ(curve['mw_rank']) # 0 will be marked as a lower bound data['mw_rank_proved'] = curve['mw_rank_proved'] data['analytic_rank_proved'] = curve['analytic_rank_proved'] data['hasse_weil_proved'] = curve['hasse_weil_proved'] data['st_group'] = curve['st_group'] data['st_group_link'] = st_link_by_name(1,4,data['st_group']) data['st0_group_name'] = st0_group_name(curve['real_geom_end_alg']) data['is_gl2_type'] = curve['is_gl2_type'] data['root_number'] = ZZ(curve['root_number']) data['lfunc_url'] = url_for("l_functions.l_function_genus2_page", cond=data['slabel'][0], x=data['slabel'][1]) data['bad_lfactors'] = literal_eval(curve['bad_lfactors']) data['bad_lfactors_pretty'] = [ (c[0], list_to_factored_poly_otherorder(c[1])) for c in data['bad_lfactors']] if is_curve: # invariants specific to curve data['class'] = curve['class'] data['abs_disc'] = ZZ(curve['abs_disc']) data['disc'] = curve['disc_sign'] * data['abs_disc'] data['min_eqn'] = literal_eval(curve['eqn']) data['min_eqn_display'] = min_eqns_pretty(data['min_eqn']) data['disc_factor_latex'] = web_latex_factored_integer(data['disc']) data['igusa_clebsch'] = [ZZ(a) for a in literal_eval(curve['igusa_clebsch_inv'])] data['igusa'] = [ZZ(a) for a in literal_eval(curve['igusa_inv'])] data['g2'] = [QQ(a) for a in literal_eval(curve['g2_inv'])] data['igusa_clebsch_factor_latex'] = [web_latex_factored_integer(i) for i in data['igusa_clebsch']] data['igusa_factor_latex'] = [ web_latex_factored_integer(j) for j in data['igusa'] ] data['aut_grp'] = small_group_label_display_knowl('%d.%d' % tuple(literal_eval(curve['aut_grp_id']))) data['geom_aut_grp'] = small_group_label_display_knowl('%d.%d' % tuple(literal_eval(curve['geom_aut_grp_id']))) data['num_rat_wpts'] = ZZ(curve['num_rat_wpts']) data['has_square_sha'] = "square" if curve['has_square_sha'] else "twice a square" P = curve['non_solvable_places'] if len(P): sz = "except over " sz += ", ".join([QpName(p) for p in P]) last = " and" if len(P) > 2: last = ", and" sz = last.join(sz.rsplit(",",1)) else: sz = "everywhere" data['non_solvable_places'] = sz data['two_selmer_rank'] = ZZ(curve['two_selmer_rank']) data['torsion_order'] = curve['torsion_order'] data['end_ring_base'] = endo['ring_base'] data['end_ring_geom'] = endo['ring_geom'] data['real_period'] = decimal_pretty(str(curve['real_period'])) data['regulator'] = decimal_pretty(str(curve['regulator'])) if curve['regulator'] > -0.5 else 'unknown' if data['mw_rank'] == 0 and data['mw_rank_proved']: data['regulator'] = '1' # display an exact 1 when we know this data['tamagawa_product'] = ZZ(curve['tamagawa_product']) if curve.get('tamagawa_product') else 0 data['analytic_sha'] = ZZ(curve['analytic_sha']) if curve.get('analytic_sha') else 0 data['leading_coeff'] = decimal_pretty(str(curve['leading_coeff'])) if curve['leading_coeff'] else 'unknown' data['rat_pts'] = ratpts['rat_pts'] data['rat_pts_v'] = ratpts['rat_pts_v'] data['rat_pts_table'] = ratpts_table(ratpts['rat_pts'],ratpts['rat_pts_v']) data['rat_pts_simple_table'] = ratpts_simpletable(ratpts['rat_pts'],ratpts['rat_pts_v'],data['min_eqn']) data['mw_gens_v'] = ratpts['mw_gens_v'] lower = len([n for n in ratpts['mw_invs'] if n == 0]) upper = data['analytic_rank'] invs = ratpts['mw_invs'] if data['mw_gens_v'] or lower >= upper else [0 for n in range(upper-lower)] + ratpts['mw_invs'] if len(invs) == 0: data['mw_group'] = 'trivial' else: data['mw_group'] = r'\(' + r' \times '.join([ (r'\Z' if n == 0 else r'\Z/{%s}\Z' % n) for n in invs]) + r'\)' if lower >= upper: data['mw_gens_table'] = mw_gens_table (ratpts['mw_invs'], ratpts['mw_gens'], ratpts['mw_heights'], ratpts['rat_pts']) data['mw_gens_simple_table'] = mw_gens_simple_table (ratpts['mw_invs'], ratpts['mw_gens'], ratpts['mw_heights'], ratpts['rat_pts'], data['min_eqn']) if curve['two_torsion_field'][0]: data['two_torsion_field_knowl'] = nf_display_knowl (curve['two_torsion_field'][0], field_pretty(curve['two_torsion_field'][0])) else: t = curve['two_torsion_field'] data['two_torsion_field_knowl'] = r"splitting field of \(%s\) with Galois group %s" % (intlist_to_poly(t[1]),group_display_knowl(t[2][0],t[2][1])) tamalist = [[item['p'],item['tamagawa_number']] for item in tama] data['local_table'] = local_table (data['cond'],data['abs_disc'],tamalist,data['bad_lfactors_pretty'],clus) else: # invariants specific to isogeny class curves_data = list(db.g2c_curves.search({"class" : curve['class']}, ['label','eqn'])) if not curves_data: raise KeyError("No curves found in database for isogeny class %s of genus 2 curve %s." %(curve['class'],curve['label'])) data['curves'] = [ {"label" : c['label'], "equation_formatted" : min_eqn_pretty(literal_eval(c['eqn'])), "url": url_for_curve_label(c['label'])} for c in curves_data ] lfunc_data = db.lfunc_lfunctions.lucky({'Lhash':str(curve['Lhash'])}) if not lfunc_data: raise KeyError("No Lfunction found in database for isogeny class of genus 2 curve %s." %curve['label']) if lfunc_data and lfunc_data.get('euler_factors'): data['good_lfactors'] = [[nth_prime(n+1),lfunc_data['euler_factors'][n]] for n in range(len(lfunc_data['euler_factors'])) if nth_prime(n+1) < 30 and (data['cond'] % nth_prime(n+1))] data['good_lfactors_pretty'] = [ (c[0], list_to_factored_poly_otherorder(c[1])) for c in data['good_lfactors']] # Endomorphism data over QQ: data['gl2_statement_base'] = gl2_statement_base(endo['factorsRR_base'], r'\(\Q\)') data['factorsQQ_base'] = endo['factorsQQ_base'] data['factorsRR_base'] = endo['factorsRR_base'] data['end_statement_base'] = (r"Endomorphism %s over \(\Q\):<br>" %("ring" if is_curve else "algebra") + end_statement(data['factorsQQ_base'], endo['factorsRR_base'], ring=data['end_ring_base'] if is_curve else None)) # Field over which all endomorphisms are defined data['end_field_label'] = endo['fod_label'] data['end_field_poly'] = intlist_to_poly(endo['fod_coeffs']) data['end_field_statement'] = end_field_statement(data['end_field_label'], data['end_field_poly']) # Endomorphism data over QQbar: data['factorsQQ_geom'] = endo['factorsQQ_geom'] data['factorsRR_geom'] = endo['factorsRR_geom'] if data['end_field_label'] != '1.1.1.1': data['gl2_statement_geom'] = gl2_statement_base(data['factorsRR_geom'], r'\(\overline{\Q}\)') data['end_statement_geom'] = (r"Endomorphism %s over \(\overline{\Q}\):" %("ring" if is_curve else "algebra") + end_statement(data['factorsQQ_geom'], data['factorsRR_geom'], field=r'\overline{\Q}', ring=data['end_ring_geom'] if is_curve else None)) data['real_geom_end_alg_name'] = real_geom_end_alg_name(curve['real_geom_end_alg']) data['geom_end_alg_name'] = geom_end_alg_name(curve['geom_end_alg']) data['end_alg_name'] = end_alg_name(curve['end_alg']) # Endomorphism data over intermediate fields not already treated (only for curves, not necessarily isogeny invariant): if is_curve: data['end_lattice'] = (endo['lattice'])[1:-1] if data['end_lattice']: data['end_lattice_statement'] = end_lattice_statement(data['end_lattice']) # Field over which the Jacobian decomposes (base field if Jacobian is geometrically simple) data['is_simple_geom'] = endo['is_simple_geom'] data['split_field_label'] = endo['spl_fod_label'] data['split_field_poly'] = intlist_to_poly(endo['spl_fod_coeffs']) data['split_field_statement'] = split_field_statement(data['is_simple_geom'], data['split_field_label'], data['split_field_poly']) # Elliptic curve factors for non-simple Jacobians if not data['is_simple_geom']: data['split_coeffs'] = endo['spl_facs_coeffs'] if 'spl_facs_labels' in endo and len(endo['spl_facs_labels']) == len(endo['spl_facs_coeffs']): data['split_labels'] = endo['spl_facs_labels'] data['split_condnorms'] = endo['spl_facs_condnorms'] data['split_statement'] = split_statement(data['split_coeffs'], data.get('split_labels'), data['split_condnorms']) # Properties self.properties = properties = [('Label', data['label'])] if is_curve: plot_from_db = db.g2c_plots.lucky({"label": curve['label']}) if (plot_from_db is None): self.plot = encode_plot(eqn_list_to_curve_plot(data['min_eqn'], ratpts['rat_pts'] if ratpts else [])) else: self.plot = plot_from_db['plot'] plot_link = '<a href="{0}"><img src="{0}" width="200" height="150"/></a>'.format(self.plot) properties += [ (None, plot_link), ('Conductor', prop_int_pretty(data['cond'])), ('Discriminant', prop_int_pretty(data['disc'])), ] if data['mw_rank_proved']: properties += [('Mordell-Weil group', data['mw_group'])] else: properties += [('Conductor', prop_int_pretty(data['cond']))] properties += [ ('Sato-Tate group', data['st_group_link']), (r'\(\End(J_{\overline{\Q}}) \otimes \R\)', r'\(%s\)' % data['real_geom_end_alg_name']), (r'\(\End(J_{\overline{\Q}}) \otimes \Q\)', r'\(%s\)' % data['geom_end_alg_name']), (r'\(\End(J) \otimes \Q\)', r'\(%s\)' % data['end_alg_name']), (r'\(\overline{\Q}\)-simple', bool_pretty(data['is_simple_geom'])), (r'\(\mathrm{GL}_2\)-type', bool_pretty(data['is_gl2_type'])), ] # Friends self.friends = friends = [] if is_curve: friends.append(('Genus 2 curve %s.%s' % (data['slabel'][0], data['slabel'][1]), url_for(".by_url_isogeny_class_label", cond=data['slabel'][0], alpha=data['slabel'][1]))) # first deal with ECs and MFs ecs = [] mfs = [] if 'split_labels' in data: for friend_label in data['split_labels']: if is_curve: ecs.append(("Elliptic curve " + friend_label, url_for_ec(friend_label))) else: ecs.append(("Elliptic curve " + ec_label_class(friend_label), url_for_ec_class(friend_label))) try: cond, iso = ec_label_class(friend_label).split(".") newform_label = ".".join([cond, str(2), 'a', iso]) mfs.append(("Modular form " + newform_label, url_for("cmf.by_url_newform_label", level=cond, weight=2, char_orbit_label='a', hecke_orbit=iso))) except ValueError: # means the friend isn't an elliptic curve over Q; adding Hilbert/Bianchi modular forms # is dealt with via the L-functions instances below pass ecs.sort(key=lambda x: key_for_numerically_sort(x[0])) mfs.sort(key=lambda x: key_for_numerically_sort(x[0])) # then again EC from lfun instances = [] for elt in db.lfunc_instances.search({'Lhash':data['Lhash'], 'type' : 'ECQP'}, 'url'): instances.extend(elt.split('|')) # and then the other isogeny friends instances.extend([ elt['url'] for elt in get_instances_by_Lhash_and_trace_hash(data["Lhash"], 4, int(data["Lhash"]) ) ]) exclude = {elt[1].rstrip('/').lstrip('/') for elt in self.friends if elt[1]} exclude.add(data['lfunc_url'].lstrip('/L/').rstrip('/')) for elt in ecs + mfs + names_and_urls(instances, exclude=exclude): # because of the splitting we must use G2C specific code add_friend(friends, elt) if is_curve: friends.append(('Twists', url_for(".index_Q", g20=str(data['g2'][0]), g21=str(data['g2'][1]), g22=str(data['g2'][2])))) friends.append(('L-function', data['lfunc_url'])) # Breadcrumbs self.bread = bread = [ ('Genus 2 curves', url_for(".index")), (r'$\Q$', url_for(".index_Q")), ('%s' % data['slabel'][0], url_for(".by_conductor", cond=data['slabel'][0])), ('%s' % data['slabel'][1], url_for(".by_url_isogeny_class_label", cond=data['slabel'][0], alpha=data['slabel'][1])) ] if is_curve: bread += [ ('%s' % data['slabel'][2], url_for(".by_url_isogeny_class_discriminant", cond=data['slabel'][0], alpha=data['slabel'][1], disc=data['slabel'][2])), ('%s' % data['slabel'][3], url_for(".by_url_curve_label", cond=data['slabel'][0], alpha=data['slabel'][1], disc=data['slabel'][2], num=data['slabel'][3])) ] # Title self.title = "Genus 2 " + ("curve " if is_curve else "isogeny class ") + data['label'] # Code snippets (only for curves) if not is_curve: return self.code = code = {} code['show'] = {'sage':'','magma':''} # use default show names f,h = fh = data['min_eqn'] g = simplify_hyperelliptic(fh) code['curve'] = {'sage':'R.<x> = PolynomialRing(QQ); C = HyperellipticCurve(R(%s), R(%s));'%(f,h), 'magma':'R<x> := PolynomialRing(Rationals()); C := HyperellipticCurve(R!%s, R!%s);'%(f,h) } code['simple_curve'] = {'sage':'X = HyperellipticCurve(R(%s))'%(g), 'magma':'X,pi:= SimplifiedModel(C);' } if data['abs_disc'] % 4096 == 0: ind2 = [a[0] for a in data['bad_lfactors']].index(2) bad2 = data['bad_lfactors'][ind2][1] magma_cond_option = ': ExcFactors:=[*<2,Valuation('+str(data['cond'])+',2),R!'+str(bad2)+'>*]' else: magma_cond_option = '' code['cond'] = {'magma': 'Conductor(LSeries(C%s)); Factorization($1);'% magma_cond_option} code['disc'] = {'magma':'Discriminant(C); Factorization(Integers()!$1);'} code['geom_inv'] = {'sage':'C.igusa_clebsch_invariants(); [factor(a) for a in _]', 'magma':'IgusaClebschInvariants(C); IgusaInvariants(C); G2Invariants(C);'} code['aut'] = {'magma':'AutomorphismGroup(C); IdentifyGroup($1);'} code['autQbar'] = {'magma':'AutomorphismGroup(ChangeRing(C,AlgebraicClosure(Rationals()))); IdentifyGroup($1);'} code['num_rat_wpts'] = {'magma':'#Roots(HyperellipticPolynomials(SimplifiedModel(C)));'} if ratpts: code['rat_pts'] = {'magma': '[' + ','.join(["C![%s,%s,%s]"%(p[0],p[1],p[2]) for p in ratpts['rat_pts']]) + ']; // minimal model'} code['rat_pts_simp'] = {'magma': '[' + ','.join(["C![%s,%s,%s]"%(p[0],p[1],p[2]) for p in [simplify_hyperelliptic_point(data['min_eqn'], pt) for pt in ratpts['rat_pts']]]) + ']; // simplified model'} code['mw_group'] = {'magma':'MordellWeilGroupGenus2(Jacobian(C));'} code['two_selmer'] = {'magma':'TwoSelmerGroup(Jacobian(C)); NumberOfGenerators($1);'} code['has_square_sha'] = {'magma':'HasSquareSha(Jacobian(C));'} code['locally_solvable'] = {'magma':'f,h:=HyperellipticPolynomials(C); g:=4*f+h^2; HasPointsEverywhereLocally(g,2) and (#Roots(ChangeRing(g,RealField())) gt 0 or LeadingCoefficient(g) gt 0);'} code['torsion_subgroup'] = {'magma':'TorsionSubgroup(Jacobian(SimplifiedModel(C))); AbelianInvariants($1);'}
def properties(self): return [("Modulus", [prop_int_pretty(self.modulus)]), ("Structure", [self.structure]), ("Order", [prop_int_pretty(self.order)]), ]
def render_artin_representation_webpage(label): if re.compile(r'^\d+$').match(label): return artin_representation_search(**{'dimension': label, 'search_array': ArtinSearchArray()}) # label=dim.cond.nTt.indexcj, c is literal, j is index in conj class # Should we have a big try around this to catch bad labels? clean_label = clean_input(label) if clean_label != label: return redirect(url_for('.render_artin_representation_webpage', label=clean_label), 301) # We could have a single representation or a Galois orbit case = parse_any(label) if case[0] == 'malformed': try: raise ValueError except Exception: flash_error("%s is not in a valid form for the label for an Artin representation or a Galois orbit of Artin representations", label) return redirect(url_for(".index")) # Do this twice to customize error messages newlabel = case[1] case = case[0] if case == 'rep': try: the_rep = ArtinRepresentation(newlabel) except Exception: newlabel = parse_artin_label(label) flash_error("Artin representation %s is not in database", label) return redirect(url_for(".index")) else: # it is an orbit try: the_rep = ArtinRepresentation(newlabel+'.a') except Exception: newlabel = parse_artin_orbit_label(newlabel) flash_error("Galois orbit of Artin representations %s is not in database", label) return redirect(url_for(".index")) # in this case we want all characters num_conj = the_rep.galois_conjugacy_size() allchars = [ ArtinRepresentation(newlabel+'.'+num2letters(j)).character_formatted() for j in range(1,num_conj+1)] label = newlabel bread = get_bread([(artin_label_pretty(label), ' ')]) #artin_logger.info("Found %s" % (the_rep._data)) if case=='rep': title = "Artin representation %s" % label else: title = "Galois orbit of Artin representations %s" % label the_nf = the_rep.number_field_galois_group() if the_rep.sign() == 0: processed_root_number = "not computed" else: processed_root_number = '$%s$' % the_rep.sign() properties = [("Label", artin_label_pretty(label)), ("Dimension", prop_int_pretty(the_rep.dimension())), ("Group", the_rep.group()), ("Conductor", prop_int_pretty(the_rep.conductor()))] if case == 'rep': properties.append( ("Root number", processed_root_number) ) properties.append( ("Indicator", prop_int_pretty(the_rep.indicator())) ) friends = [] wnf = None proj_wnf = None nf_url = the_nf.url_for() if nf_url: friends.append(("Field {}".format(the_nf.label()), nf_url)) wnf = the_nf.wnf() proj_wnf = WebNumberField.from_coeffs(the_rep._data['Proj_Polynomial']) if proj_wnf.is_in_db(): proj_coefs = [int(z) for z in proj_wnf.coeffs()] if proj_coefs != the_nf.polynomial(): friends.append(("Field {}".format(proj_wnf.get_label()), str(url_for("number_fields.by_label", label=proj_wnf.get_label())))) if case == 'rep': cc = the_rep.central_character() if cc is not None: if the_rep.dimension()==1: if cc.order == 2: cc_name = cc.symbol else: cc_name = cc.texname friends.append(("Dirichlet character "+cc_name, url_for("characters.render_Dirichletwebpage", modulus=cc.modulus, number=cc.number))) else: detrep = the_rep.central_character_as_artin_rep() friends.append(("Determinant "+detrep.label(), detrep.url_for())) add_lfunction_friends(friends,label) # once the L-functions are in the database, the link can always be shown #if the_rep.dimension() <= 6: if the_rep.dimension() == 1: # Zeta is loaded differently if cc.modulus == 1 and cc.number == 1: friends.append(("L-function", url_for("l_functions.l_function_dirichlet_page", modulus=cc.modulus, number=cc.number))) else: # looking for Lhash dirichlet_L_modulus.number mylhash = 'dirichlet_L_%d.%d'%(cc.modulus,cc.number) lres = db.lfunc_instances.lucky({'Lhash': mylhash}) if lres is not None: friends.append(("L-function", url_for("l_functions.l_function_dirichlet_page", modulus=cc.modulus, number=cc.number))) # Dimension > 1 elif int(the_rep.conductor())**the_rep.dimension() <= 729000000000000: friends.append(("L-function", url_for("l_functions.l_function_artin_page", label=the_rep.label()))) orblabel = re.sub(r'\.[a-z]+$', '', label) friends.append(("Galois orbit " + artin_label_pretty(orblabel), url_for(".render_artin_representation_webpage", label=orblabel))) else: add_lfunction_friends(friends,label) friends.append(("L-function", url_for("l_functions.l_function_artin_page", label=the_rep.label()))) for j in range(1,1+the_rep.galois_conjugacy_size()): newlabel = label+'.'+num2letters(j) friends.append(("Artin representation " + artin_label_pretty(newlabel), url_for(".render_artin_representation_webpage", label=newlabel))) info={} # for testing if case == 'rep': return render_template( "artin-representation-show.html", title=title, bread=bread, friends=friends, object=the_rep, cycle_string=cycle_string, wnf=wnf, proj_wnf=proj_wnf, properties=properties, info=info, learnmore=learnmore_list(), KNOWL_ID="artin.%s" % label, ) # else we have an orbit return render_template( "artin-representation-galois-orbit.html", title=title, bread=bread, allchars=allchars, friends=friends, object=the_rep, cycle_string=cycle_string, wnf=wnf, proj_wnf=proj_wnf, properties=properties, info=info, learnmore=learnmore_list(), KNOWL_ID="artin.%s" % label, )
def render_field_webpage(args): data = None info = {} bread = bread_prefix() # This function should not be called unless label is set. label = clean_input(args['label']) nf = WebNumberField(label) data = {} if nf.is_null(): if re.match(r'^\d+\.\d+\.\d+\.\d+$', label): flash_error("Number field %s was not found in the database.", label) else: flash_error("%s is not a valid label for a number field.", label) return redirect(url_for(".number_field_render_webpage")) info['wnf'] = nf data['degree'] = nf.degree() data['class_number'] = nf.class_number_latex() ram_primes = nf.ramified_primes() t = nf.galois_t() n = nf.degree() data['is_galois'] = nf.is_galois() data['autstring'] = r'\Gal' if data['is_galois'] else r'\Aut' data['is_abelian'] = nf.is_abelian() if nf.is_abelian(): conductor = nf.conductor() data['conductor'] = conductor dirichlet_chars = nf.dirichlet_group() if dirichlet_chars: data['dirichlet_group'] = [ r'<a href = "%s">$\chi_{%s}(%s,·)$</a>' % (url_for('characters.render_Dirichletwebpage', modulus=data['conductor'], number=j), data['conductor'], j) for j in dirichlet_chars ] if len(data['dirichlet_group']) == 1: data[ 'dirichlet_group'] = r'<span style="white-space:nowrap">$\lbrace$' + data[ 'dirichlet_group'][0] + r'$\rbrace$</span>' else: data['dirichlet_group'] = r'$\lbrace$' + ', '.join( data['dirichlet_group'] [:-1]) + '<span style="white-space:nowrap">' + data[ 'dirichlet_group'][-1] + r'$\rbrace$</span>' if data['conductor'].is_prime() or data['conductor'] == 1: data['conductor'] = r"\(%s\)" % str(data['conductor']) else: factored_conductor = factor_base_factor(data['conductor'], ram_primes) factored_conductor = factor_base_factorization_latex( factored_conductor) data['conductor'] = r"\(%s=%s\)" % (str( data['conductor']), factored_conductor) data['galois_group'] = group_pretty_and_nTj(n, t, True) data['auts'] = db.gps_transitive.lookup(r'{}T{}'.format(n, t))['auts'] data['cclasses'] = cclasses_display_knowl(n, t) data['character_table'] = character_table_display_knowl(n, t) data['class_group'] = nf.class_group() data['class_group_invs'] = nf.class_group_invariants() data['signature'] = nf.signature() data['coefficients'] = nf.coeffs() nf.make_code_snippets() D = nf.disc() data['disc_factor'] = nf.disc_factored_latex() if D.abs().is_prime() or D == 1: data['discriminant'] = bigint_knowl(D, cutoff=60, sides=3) else: data['discriminant'] = bigint_knowl( D, cutoff=60, sides=3) + r"\(\medspace = %s\)" % data['disc_factor'] if nf.frobs(): data['frob_data'], data['seeram'] = see_frobs(nf.frobs()) else: # fallback in case we haven't computed them in a case data['frob_data'], data['seeram'] = frobs(nf) # This could put commas in the rd, we don't want to trigger spaces data['rd'] = ('$%s$' % fixed_prec(nf.rd(), 2)).replace(',', '{,}') # Bad prime information npr = len(ram_primes) ramified_algebras_data = nf.ramified_algebras_data() if isinstance(ramified_algebras_data, str): loc_alg = '' else: # [label, latex, e, f, c, gal] loc_alg = '' for j in range(npr): if ramified_algebras_data[j] is None: loc_alg += '<tr><td>%s<td colspan="7">Data not computed' % str( ram_primes[j]).rstrip('L') else: from lmfdb.local_fields.main import show_slope_content mydat = ramified_algebras_data[j] p = ram_primes[j] loc_alg += '<tr><td rowspan="%d">$%s$</td>' % (len(mydat), str(p)) mm = mydat[0] myurl = url_for('local_fields.by_label', label=mm[0]) lab = mm[0] if mm[3] * mm[2] == 1: lab = r'$\Q_{%s}$' % str(p) loc_alg += '<td><a href="%s">%s</a><td>$%s$<td>$%d$<td>$%d$<td>$%d$<td>%s<td>$%s$' % ( myurl, lab, mm[1], mm[2], mm[3], mm[4], mm[5], show_slope_content(mm[8], mm[6], mm[7])) for mm in mydat[1:]: lab = mm[0] myurl = url_for('local_fields.by_label', label=lab) if mm[3] * mm[2] == 1: lab = r'$\Q_{%s}$' % str(p) loc_alg += '<tr><td><a href="%s">%s</a><td>$%s$<td>$%d$<td>$%d$<td>$%d$<td>%s<td>$%s$' % ( myurl, lab, mm[1], mm[2], mm[3], mm[4], mm[5], show_slope_content(mm[8], mm[6], mm[7])) loc_alg += '</tbody></table>' ram_primes = str(ram_primes)[1:-1] # Get rid of python L for big numbers ram_primes = ram_primes.replace('L', '') if not ram_primes: ram_primes = r'\textrm{None}' data['phrase'] = group_phrase(n, t) zk = nf.zk() Ra = PolynomialRing(QQ, 'a') zk = [latex(Ra(x)) for x in zk] zk = ['$%s$' % x for x in zk] zk = ', '.join(zk) grh_label = '<small>(<a title="assuming GRH" knowl="nf.assuming_grh">assuming GRH</a>)</small>' if nf.used_grh( ) else '' # Short version for properties grh_lab = nf.short_grh_string() if 'computed' in str(data['class_number']): grh_lab = '' grh_label = '' pretty_label = field_pretty(label) if label != pretty_label: pretty_label = "%s: %s" % (label, pretty_label) info.update(data) rootofunity = '%s (order $%d$)' % (nf.root_of_1_gen(), nf.root_of_1_order()) info.update({ 'label': pretty_label, 'label_raw': label, 'polynomial': web_latex(nf.poly()), 'ram_primes': ram_primes, 'integral_basis': zk, 'regulator': web_latex(nf.regulator()), 'unit_rank': nf.unit_rank(), 'root_of_unity': rootofunity, 'fund_units': nf.units_safe(), 'cnf': nf.cnf(), 'grh_label': grh_label, 'loc_alg': loc_alg }) bread.append(('%s' % nf_label_pretty(info['label_raw']), ' ')) info['downloads_visible'] = True info['downloads'] = [('worksheet', '/')] info['friends'] = [] if nf.can_class_number(): # hide ones that take a lond time to compute on the fly # note that the first degree 4 number field missed the zero of the zeta function if abs(D**n) < 50000000: info['friends'].append(('L-function', "/L/NumberField/%s" % label)) info['friends'].append(('Galois group', "/GaloisGroup/%dT%d" % (n, t))) if 'dirichlet_group' in info: info['friends'].append(('Dirichlet character group', url_for("characters.dirichlet_group_table", modulus=int(conductor), char_number_list=','.join( str(a) for a in dirichlet_chars), poly=info['polynomial']))) resinfo = [] galois_closure = nf.galois_closure() if galois_closure[0] > 0: if galois_closure[1]: resinfo.append(('gc', galois_closure[1])) if galois_closure[2]: info['friends'].append(('Galois closure', url_for(".by_label", label=galois_closure[2][0]))) else: resinfo.append(('gc', [dnc])) sextic_twins = nf.sextic_twin() if sextic_twins[0] > 0: if sextic_twins[1]: resinfo.append(('sex', r' $\times$ '.join(sextic_twins[1]))) else: resinfo.append(('sex', dnc)) siblings = nf.siblings() # [degsib list, label list] # first is list of [deg, num expected, list of knowls] if siblings[0]: for sibdeg in siblings[0]: if not sibdeg[2]: sibdeg[2] = dnc else: nsibs = len(sibdeg[2]) sibdeg[2] = ', '.join(sibdeg[2]) if nsibs < sibdeg[1]: sibdeg[2] += ', some ' + dnc resinfo.append(('sib', siblings[0])) for lab in siblings[1]: if lab: labparts = lab.split('.') info['friends'].append(("Degree %s sibling" % labparts[0], url_for(".by_label", label=lab))) arith_equiv = nf.arith_equiv() if arith_equiv[0] > 0: if arith_equiv[1]: resinfo.append( ('ae', ', '.join(arith_equiv[1]), len(arith_equiv[1]))) for aelab in arith_equiv[2]: info['friends'].append(('Arithmetically equivalent sibling', url_for(".by_label", label=aelab))) else: resinfo.append(('ae', dnc, len(arith_equiv[1]))) info['resinfo'] = resinfo learnmore = learnmore_list() title = "Number field %s" % info['label'] if npr == 1: primes = 'prime' else: primes = 'primes' if len(ram_primes) > 30: ram_primes = 'see page' else: ram_primes = '$%s$' % ram_primes properties = [('Label', nf_label_pretty(label)), ('Degree', prop_int_pretty(data['degree'])), ('Signature', '$%s$' % data['signature']), ('Discriminant', prop_int_pretty(D)), ('Root discriminant', '%s' % data['rd']), ('Ramified ' + primes + '', ram_primes), ('Class number', '%s %s' % (data['class_number'], grh_lab)), ('Class group', '%s %s' % (data['class_group_invs'], grh_lab)), ('Galois group', group_pretty_and_nTj(data['degree'], t))] downloads = [('Stored data to gp', url_for('.nf_download', nf=label, download_type='data'))] for lang in [["Magma", "magma"], ["SageMath", "sage"], ["Pari/GP", "gp"]]: downloads.append(('Download {} code'.format(lang[0]), url_for(".nf_download", nf=label, download_type=lang[1]))) from lmfdb.artin_representations.math_classes import NumberFieldGaloisGroup from lmfdb.artin_representations.math_classes import artin_label_pretty try: info["tim_number_field"] = NumberFieldGaloisGroup(nf._data['coeffs']) arts = [ z.label() for z in info["tim_number_field"].artin_representations() ] #print arts for ar in arts: info['friends'].append(( 'Artin representation ' + artin_label_pretty(ar), url_for( "artin_representations.render_artin_representation_webpage", label=ar))) v = nf.factor_perm_repn(info["tim_number_field"]) def dopow(m): if m == 0: return '' if m == 1: return '*' return '*<sup>%d</sup>' % m info["mydecomp"] = [dopow(x) for x in v] except AttributeError: pass return render_template("nf-show-field.html", properties=properties, credit=NF_credit, title=title, bread=bread, code=nf.code, friends=info.pop('friends'), downloads=downloads, learnmore=learnmore, info=info, KNOWL_ID="nf.%s" % label)
def make_class(self): # Extract the size of the isogeny class from the database classdata = db.ec_classdata.lucky({'lmfdb_iso': self.lmfdb_iso}) self.class_size = ncurves = classdata['class_size'] # Create a list of the curves in the class from the database number_key = 'Cnumber' if self.label_type == 'Cremona' else 'lmfdb_number' self.curves = [ db.ec_curvedata.lucky({ 'lmfdb_iso': self.lmfdb_iso, number_key: i + 1 }) for i in range(ncurves) ] # Set optimality flags. The optimal curve is conditionally # number 1 except in one case which is labeled differently in # the Cremona tables. We know which curve is optimal iff the # optimality code for curve #1 is 1 (except for class 990h). # Note that self is actually an elliptic curve, with number=1. # The code here allows us to update the display correctly by # changing one line in this file (defining OPTIMALITY_BOUND) # without changing the data. self.cremona_bound = CREMONA_BOUND self.optimality_bound = OPTIMALITY_BOUND self.optimality_known = (self.conductor < OPTIMALITY_BOUND) or ( (self.conductor < CREMONA_BOUND) and ((self.optimality == 1) or (self.Ciso == '990h'))) self.optimal_label = self.Clabel if self.label_type == 'Cremona' else self.lmfdb_label if self.conductor < OPTIMALITY_BOUND: for c in self.curves: c['optimal'] = (c['Cnumber'] == (3 if self.Ciso == '990h' else 1)) c['optimality_known'] = True elif self.conductor < CREMONA_BOUND: for c in self.curves: c['optimal'] = (c['optimality'] > 0 ) # this curve possibly optimal c['optimality_known'] = (c['optimality'] == 1 ) # this curve certainly optimal else: for c in self.curves: c['optimal'] = None c['optimality_known'] = False for c in self.curves: c['ai'] = c['ainvs'] c['curve_url_lmfdb'] = url_for(".by_triple_label", conductor=self.conductor, iso_label=self.iso_label, number=c['lmfdb_number']) c['curve_url_cremona'] = url_for( ".by_ec_label", label=c['Clabel']) if self.conductor < CREMONA_BOUND else "N/A" if self.label_type == 'Cremona': c['curve_label'] = c['Clabel'] _, c_iso, c_number = split_cremona_label(c['Clabel']) else: c['curve_label'] = c['lmfdb_label'] _, c_iso, c_number = split_lmfdb_label(c['lmfdb_label']) c['short_label'] = "{}{}".format(c_iso, c_number) from sage.matrix.all import Matrix M = classdata['isogeny_matrix'] # permute rows/cols to match labelling: the rows/cols in the # ec_classdata table are with respect to LMFDB ordering. if self.label_type == 'Cremona': perm = lambda i: next(c for c in self.curves if c['Cnumber'] == i + 1)['lmfdb_number'] - 1 M = [[M[perm(i)][perm(j)] for i in range(ncurves)] for j in range(ncurves)] M = Matrix(M) self.isogeny_matrix_str = latex(M) # Create isogeny graph with appropriate vertex labels: self.graph = make_graph(M, [c['short_label'] for c in self.curves]) P = self.graph.plot(edge_labels=True, vertex_size=1000) self.graph_img = encode_plot(P) self.graph_link = '<img src="%s" width="200" height="150"/>' % self.graph_img self.newform = raw_typeset( PowerSeriesRing(QQ, 'q')(classdata['anlist'], 20, check=True)) self.newform_label = ".".join( [str(self.conductor), str(2), 'a', self.iso_label]) self.newform_exists_in_db = db.mf_newforms.label_exists( self.newform_label) if self.newform_exists_in_db: char_orbit, hecke_orbit = self.newform_label.split('.')[2:] self.newform_link = url_for("cmf.by_url_newform_label", level=self.conductor, weight=2, char_orbit_label=char_orbit, hecke_orbit=hecke_orbit) self.lfunction_link = url_for("l_functions.l_function_ec_page", conductor_label=self.conductor, isogeny_class_label=self.iso_label) self.friends = [('L-function', self.lfunction_link)] if self.cm: # set CM field for Properties box. D = ZZ(self.cm).squarefree_part() coeffs = [(1 - D) // 4, -1, 1] if D % 4 == 1 else [-D, 0, 1] lab = db.nf_fields.lucky({'coeffs': coeffs}, projection='label') self.CMfield = field_pretty(lab) else: self.CMfield = "no" if self.conductor <= 300: self.friends += [('Symmetric square L-function', url_for("l_functions.l_function_ec_sym_page", power='2', conductor=self.conductor, isogeny=self.iso_label))] if self.conductor <= 50: self.friends += [('Symmetric cube L-function', url_for("l_functions.l_function_ec_sym_page", power='3', conductor=self.conductor, isogeny=self.iso_label))] if self.newform_exists_in_db: self.friends += [('Modular form ' + self.newform_label, self.newform_link)] if self.label_type == 'Cremona': self.title = "Elliptic curve isogeny class with Cremona label {} (LMFDB label {})".format( self.Ciso, self.lmfdb_iso) elif self.conductor < CREMONA_BOUND: self.title = "Elliptic curve isogeny class with LMFDB label {} (Cremona label {})".format( self.lmfdb_iso, self.Ciso) else: self.title = "Elliptic curve isogeny class with LMFDB label {}".format( self.lmfdb_iso) self.properties = [ ('Label', self.Ciso if self.label_type == 'Cremona' else self.lmfdb_iso), ('Number of curves', prop_int_pretty(ncurves)), ('Conductor', prop_int_pretty(self.conductor)), ('CM', '%s' % self.CMfield), ('Rank', prop_int_pretty(self.rank)) ] if ncurves > 1: self.properties += [('Graph', ''), (None, self.graph_link)] self.downloads = [('q-expansion to text', url_for(".download_EC_qexp", label=self.iso_label, limit=1000)), ('All stored data to text', url_for(".download_EC_all", label=self.iso_label))] self.bread = [('Elliptic curves', url_for("ecnf.index")), (r'$\Q$', url_for(".rational_elliptic_curves")), ('%s' % self.conductor, url_for(".by_conductor", conductor=self.conductor)), ('%s' % self.iso_label, ' ')] self.code = {} self.code['show'] = {'sage': ''} # use default show names self.code['class'] = { 'sage': 'E = EllipticCurve("%s1")\n' % (self.iso_label) + 'E.isogeny_class()\n' } self.code['curves'] = {'sage': 'E.isogeny_class().curves'} self.code['rank'] = {'sage': 'E.rank()'} self.code['q_eigenform'] = {'sage': 'E.q_eigenform(10)'} self.code['matrix'] = {'sage': 'E.isogeny_class().matrix()'} self.code['plot'] = { 'sage': 'E.isogeny_graph().plot(edge_labels=True)' }
def make_curve(self): data = self.data = {} lmfdb_label = self.lmfdb_label # Some data fields of self are just those from the database. # These only need some reformatting. data['ainvs'] = self.ainvs data['conductor'] = N = self.conductor data['j_invariant'] = QQ(tuple(self.jinv)) data['j_inv_factor'] = latex(0) if data['j_invariant']: # don't factor 0 data['j_inv_factor'] = latex(data['j_invariant'].factor()) data['j_inv_latex'] = web_latex(data['j_invariant']) # retrieve local reduction data from table ec_localdata: self.local_data = local_data = list( db.ec_localdata.search({"lmfdb_label": lmfdb_label})) for ld in local_data: if ld['kodaira_symbol'] <= -14: # Work around bug in Sage's latex ld['kod'] = 'I_{%s}^{*}' % (-ld['kodaira_symbol'] - 4) else: ld['kod'] = latex(KodairaSymbol(ld['kodaira_symbol'])) Nfac = Factorization([(ZZ(ld['prime']), ld['conductor_valuation']) for ld in local_data]) Dfac = Factorization([(ZZ(ld['prime']), ld['discriminant_valuation']) for ld in local_data], unit=ZZ(self.signD)) data['disc_factor'] = latex(Dfac) data['disc'] = D = Dfac.value() data['cond_factor'] = latex(Nfac) data['disc_latex'] = web_latex(D) data['cond_latex'] = web_latex(N) # retrieve data about MW rank, generators, heights and # torsion, leading term of L-function & other BSD data from # table ec_mwbsd: self.make_mwbsd() # latex equation: latexeqn = latex_equation(self.ainvs) data['equation'] = raw_typeset(unlatex(latexeqn), latexeqn) # minimal quadratic twist: data['minq_D'] = minqD = self.min_quad_twist_disc data['minq_label'] = db.ec_curvedata.lucky( {'ainvs': self.min_quad_twist_ainvs}, projection='lmfdb_label' if self.label_type == 'LMFDB' else 'Clabel') data['minq_info'] = '(itself)' if minqD == 1 else '(by {})'.format( minqD) # modular degree: try: data['degree'] = ZZ(self.degree) # convert None to 0 except AttributeError: # if not computed, db has Null and the attribute is missing data['degree'] = 0 # invalid, but will be displayed nicely # coefficients of modular form / L-series: classdata = db.ec_classdata.lookup(self.lmfdb_iso) data['an'] = classdata['anlist'] data['ap'] = classdata['aplist'] # mod-p Galois images: data['galois_data'] = list( db.ec_galrep.search({'lmfdb_label': lmfdb_label})) for gd in data[ 'galois_data']: # remove the prime prefix from each image code gd['image'] = trim_galois_image_code(gd['image']) # CM and Endo ring: data['CMD'] = self.cm data['CM'] = "no" data['EndE'] = r"\(\Z\)" if self.cm: data['cm_ramp'] = [ p for p in ZZ(self.cm).support() if not p in self.nonmax_primes ] data['cm_nramp'] = len(data['cm_ramp']) if data['cm_nramp'] == 1: data['cm_ramp'] = data['cm_ramp'][0] else: data['cm_ramp'] = ", ".join(str(p) for p in data['cm_ramp']) data['cm_sqf'] = ZZ(self.cm).squarefree_part() data['CM'] = r"yes (\(D=%s\))" % data['CMD'] if data['CMD'] % 4 == 0: d4 = ZZ(data['CMD']) // 4 data['EndE'] = r"\(\Z[\sqrt{%s}]\)" % d4 else: data['EndE'] = r"\(\Z[(1+\sqrt{%s})/2]\)" % data['CMD'] data['ST'] = st_link_by_name(1, 2, 'N(U(1))') else: data['ST'] = st_link_by_name(1, 2, 'SU(2)') # Isogeny degrees: cond, iso, num = split_lmfdb_label(lmfdb_label) self.class_deg = classdata['class_deg'] self.one_deg = ZZ(self.class_deg).is_prime() isodegs = [str(d) for d in self.isogeny_degrees if d > 1] if len(isodegs) < 3: data['isogeny_degrees'] = " and ".join(isodegs) else: data['isogeny_degrees'] = " and ".join( [", ".join(isodegs[:-1]), isodegs[-1]]) self.make_twoadic_data() # Optimality # The optimal curve in the class is the curve whose Cremona # label ends in '1' except for '990h' which was labelled # wrongly long ago. This is proved for N up to # OPTIMALITY_BOUND (and when there is only one curve in an # isogeny class, obviously) and expected for all N. # Column 'optimality' is 1 for certainly optimal curves, 0 for # certainly non-optimal curves, and is n>1 if the curve is one # of n in the isogeny class which may be optimal given current # knowledge. # Column "manin_constant' is the correct Manin constant # assuming that the optimal curve in the class is known, or # otherwise if it is the curve with (Cremona) number 1. # The code here allows us to update the display correctly by # changing one line in this file (defining OPTIMALITY_BOUND) # without changing the data. data['optimality_bound'] = OPTIMALITY_BOUND self.cremona_bound = CREMONA_BOUND if N < CREMONA_BOUND: data[ 'manin_constant'] = self.manin_constant # (conditional on data['optimality_known']) else: data['manin_constant'] = 0 # (meaning not available) if N < OPTIMALITY_BOUND: data['optimality_code'] = int( self.Cnumber == (3 if self.Ciso == '990h' else 1)) data['optimality_known'] = True data['manin_known'] = True if self.label_type == 'Cremona': data[ 'optimal_label'] = '990h3' if self.Ciso == '990h' else self.Ciso + '1' else: data[ 'optimal_label'] = '990.i3' if self.lmfdb_iso == '990.i' else self.lmfdb_iso + '1' elif N < CREMONA_BOUND: data['optimality_code'] = self.optimality data['optimality_known'] = (self.optimality < 2) if self.optimality == 1: data['manin_known'] = True data[ 'optimal_label'] = self.Clabel if self.label_type == 'Cremona' else self.lmfdb_label else: if self.Cnumber == 1: data['manin_known'] = False data[ 'optimal_label'] = self.Clabel if self.label_type == 'Cremona' else self.lmfdb_label else: # find curve #1 in this class and its optimailty code: opt_curve = db.ec_curvedata.lucky( { 'Ciso': self.Ciso, 'Cnumber': 1 }, projection=['Clabel', 'lmfdb_label', 'optimality']) data['manin_known'] = (opt_curve['optimality'] == 1) data['optimal_label'] = opt_curve[ 'Clabel' if self.label_type == 'Cremona' else 'lmfdb_label'] else: data['optimality_code'] = None data['optimality_known'] = False data['manin_known'] = False data['optimal_label'] = '' # p-adic data: data['p_adic_primes'] = [ p for i, p in enumerate(prime_range(5, 100)) if (N * data['ap'][i]) % p != 0 ] data['p_adic_data_exists'] = False if data['optimality_code'] == 1: data['p_adic_data_exists'] = db.ec_padic.exists( {'lmfdb_iso': self.lmfdb_iso}) # Iwasawa data (where present) self.make_iwasawa() # Torsion growth data (where present) self.make_torsion_growth() # Newform rawnewform = str(PowerSeriesRing(QQ, 'q')(data['an'], 20, check=True)) data['newform'] = raw_typeset( rawnewform, web_latex(PowerSeriesRing(QQ, 'q')(data['an'], 20, check=True))) data['newform_label'] = self.newform_label = ".".join( [str(cond), str(2), 'a', iso]) self.newform_link = url_for("cmf.by_url_newform_label", level=cond, weight=2, char_orbit_label='a', hecke_orbit=iso) self.newform_exists_in_db = db.mf_newforms.label_exists( self.newform_label) self._code = None if self.label_type == 'Cremona': self.class_url = url_for(".by_ec_label", label=self.Ciso) self.class_name = self.Ciso else: self.class_url = url_for(".by_ec_label", label=self.lmfdb_iso) self.class_name = self.lmfdb_iso data['class_name'] = self.class_name data['Cnumber'] = self.Cnumber if N < CREMONA_BOUND else None self.friends = [('Isogeny class ' + self.class_name, self.class_url), ('Minimal quadratic twist %s %s' % (data['minq_info'], data['minq_label']), url_for(".by_ec_label", label=data['minq_label'])), ('All twists ', url_for(".rational_elliptic_curves", jinv=data['j_invariant']))] lfun_url = url_for("l_functions.l_function_ec_page", conductor_label=N, isogeny_class_label=iso) origin_url = lfun_url.lstrip('/L/').rstrip('/') if db.lfunc_instances.exists({'url': origin_url}): self.friends += [('L-function', lfun_url)] else: self.friends += [('L-function not available', "")] if not self.cm: if N <= 300: self.friends += [('Symmetric square L-function', url_for("l_functions.l_function_ec_sym_page", power='2', conductor=N, isogeny=iso))] if N <= 50: self.friends += [('Symmetric cube L-function', url_for("l_functions.l_function_ec_sym_page", power='3', conductor=N, isogeny=iso))] if self.newform_exists_in_db: self.friends += [('Modular form ' + self.newform_label, self.newform_link)] self.downloads = [('q-expansion to text', url_for(".download_EC_qexp", label=self.lmfdb_label, limit=1000)), ('All stored data to text', url_for(".download_EC_all", label=self.lmfdb_label)), ('Code to Magma', url_for(".ec_code_download", conductor=cond, iso=iso, number=num, label=self.lmfdb_label, download_type='magma')), ('Code to SageMath', url_for(".ec_code_download", conductor=cond, iso=iso, number=num, label=self.lmfdb_label, download_type='sage')), ('Code to GP', url_for(".ec_code_download", conductor=cond, iso=iso, number=num, label=self.lmfdb_label, download_type='gp'))] try: self.plot = encode_plot(self.E.plot()) except AttributeError: self.plot = encode_plot(EllipticCurve(data['ainvs']).plot()) self.plot_link = '<a href="{0}"><img src="{0}" width="200" height="150"/></a>'.format( self.plot) self.properties = [ ('Label', self.Clabel if self.label_type == 'Cremona' else self.lmfdb_label), (None, self.plot_link), ('Conductor', prop_int_pretty(data['conductor'])), ('Discriminant', prop_int_pretty(data['disc'])), ('j-invariant', '%s' % data['j_inv_latex']), ('CM', '%s' % data['CM']), ('Rank', 'unknown' if self.mwbsd['rank'] == '?' else prop_int_pretty(self.mwbsd['rank'])), ('Torsion structure', (r'\(%s\)' % self.mwbsd['tor_struct']) if self.mwbsd['tor_struct'] else 'trivial'), ] if self.label_type == 'Cremona': self.title = "Elliptic curve with Cremona label {} (LMFDB label {})".format( self.Clabel, self.lmfdb_label) elif N < CREMONA_BOUND: self.title = "Elliptic curve with LMFDB label {} (Cremona label {})".format( self.lmfdb_label, self.Clabel) else: self.title = "Elliptic curve with LMFDB label {}".format( self.lmfdb_label) self.bread = [('Elliptic curves', url_for("ecnf.index")), (r'$\Q$', url_for(".rational_elliptic_curves")), ('%s' % N, url_for(".by_conductor", conductor=N)), ('%s' % iso, url_for(".by_double_iso_label", conductor=N, iso_label=iso)), ('%s' % num, ' ')]
def make_class(self): self.CM = self.cm N, iso, number = split_lmfdb_label(self.lmfdb_iso) self.conductor = N = int(N) # Extract the size of the isogeny class from the database self.ncurves = ncurves = self.class_size # Create a list of the curves in the class from the database number_key = 'number' if self.label_type == 'Cremona' else 'lmfdb_number' self.curves = [ db.ec_curves.lucky({ 'iso': self.iso, number_key: i + 1 }) for i in range(ncurves) ] # Set optimality flags. The optimal curve is conditionally # number 1 except in one case which is labeled differently in # the Cremona tables. We know which curve is optimal iff the # optimality code for curve #1 is 1 (except for class 990h). # Note that self is actually an elliptic curve, with number=1. # The code here allows us to update the display correctly by # changing one line in this file (defining OPTIMALITY_BOUND) # without changing the data. self.optimality_bound = OPTIMALITY_BOUND self.optimality_known = (N < OPTIMALITY_BOUND) or (self.optimality == 1) or (self.iso == '990h') self.optimal_label = self.label if self.label_type == 'Cremona' else self.lmfdb_label if N < OPTIMALITY_BOUND: for c in self.curves: c['optimal'] = (c['number'] == (3 if self.iso == '990h' else 1)) c['optimality_known'] = True else: for c in self.curves: c['optimal'] = (c['optimality'] > 0 ) # this curve possibly optimal c['optimality_known'] = (c['optimality'] == 1 ) # this curve certainly optimal for c in self.curves: c['ai'] = c['ainvs'] c['curve_url_lmfdb'] = url_for(".by_triple_label", conductor=N, iso_label=iso, number=c['lmfdb_number']) c['curve_url_cremona'] = url_for(".by_ec_label", label=c['label']) if self.label_type == 'Cremona': c['curve_label'] = c['label'] _, c_iso, c_number = split_cremona_label(c['label']) else: c['curve_label'] = c['lmfdb_label'] _, c_iso, c_number = split_lmfdb_label(c['lmfdb_label']) c['short_label'] = "{}{}".format(c_iso, c_number) from sage.matrix.all import Matrix if self.label_type == 'Cremona': # permute rows/cols perm = lambda i: next(c for c in self.curves if c['number'] == i + 1)['lmfdb_number'] - 1 self.isogeny_matrix = [[ self.isogeny_matrix[perm(i)][perm(j)] for i in range(ncurves) ] for j in range(ncurves)] self.isogeny_matrix = Matrix(self.isogeny_matrix) self.isogeny_matrix_str = latex(matrix(self.isogeny_matrix)) # Create isogeny graph with appropriate vertex labels: self.graph = make_graph(self.isogeny_matrix, [c['short_label'] for c in self.curves]) P = self.graph.plot(edge_labels=True, vertex_size=1000) self.graph_img = encode_plot(P) self.graph_link = '<img src="%s" width="200" height="150"/>' % self.graph_img self.newform = web_latex( PowerSeriesRing(QQ, 'q')(self.anlist, 20, check=True)) self.newform_label = ".".join([str(N), str(2), 'a', iso]) # self.newform_label = db.mf_newforms.lucky({'level':N, 'weight':2, 'related_objects':{'$contains':'EllipticCurve/Q/%s/%s' % (N, iso)}},'label') # self.newform_exists_in_db = self.newform_label is not None self.newform_exists_in_db = db.mf_newforms.label_exists( self.newform_label) # if self.newform_label is not None: if self.newform_exists_in_db: char_orbit, hecke_orbit = self.newform_label.split('.')[2:] self.newform_link = url_for("cmf.by_url_newform_label", level=N, weight=2, char_orbit_label=char_orbit, hecke_orbit=hecke_orbit) self.lfunction_link = url_for("l_functions.l_function_ec_page", conductor_label=N, isogeny_class_label=iso) self.friends = [('L-function', self.lfunction_link)] if not self.CM: self.CM = "no" if int(N) <= 300: self.friends += [('Symmetric square L-function', url_for("l_functions.l_function_ec_sym_page", power='2', conductor=N, isogeny=iso))] if int(N) <= 50: self.friends += [('Symmetric cube L-function', url_for("l_functions.l_function_ec_sym_page", power='3', conductor=N, isogeny=iso))] if self.newform_exists_in_db: self.friends += [('Modular form ' + self.newform_label, self.newform_link)] if self.label_type == 'Cremona': self.title = "Elliptic curve isogeny class with Cremona label {} (LMFDB label {})".format( self.iso, self.lmfdb_iso) self.iso_label = self.iso else: self.title = "Elliptic curve isogeny class with LMFDB label {} (Cremona label {})".format( self.lmfdb_iso, self.iso) self.iso_label = self.lmfdb_iso self.properties = [ ('Label', self.iso if self.label_type == 'Cremona' else self.lmfdb_iso), ('Number of curves', prop_int_pretty(ncurves)), ('Conductor', prop_int_pretty(N)), ('CM', '%s' % self.CM), ('Rank', prop_int_pretty(self.rank)) ] if self.ncurves > 1: self.properties += [('Graph', ''), (None, self.graph_link)] self.downloads = [('q-expansion to text', url_for(".download_EC_qexp", label=self.lmfdb_iso, limit=1000)), ('All stored data to text', url_for(".download_EC_all", label=self.lmfdb_iso))] self.bread = [('Elliptic curves', url_for("ecnf.index")), (r'$\Q$', url_for(".rational_elliptic_curves")), ('%s' % N, url_for(".by_conductor", conductor=N)), ('%s' % iso, ' ')] self.code = {} self.code['show'] = {'sage': ''} # use default show names self.code['class'] = { 'sage': 'E = EllipticCurve("%s1")\n' % (self.lmfdb_iso) + 'E.isogeny_class()\n' } self.code['curves'] = {'sage': 'E.isogeny_class().curves'} self.code['rank'] = {'sage': 'E.rank()'} self.code['q_eigenform'] = {'sage': 'E.q_eigenform(10)'} self.code['matrix'] = {'sage': 'E.isogeny_class().matrix()'} self.code['plot'] = { 'sage': 'E.isogeny_graph().plot(edge_labels=True)' }