def render_bmf_webpage(field_label, level_label, label_suffix): label = "-".join([field_label, level_label, label_suffix]) credit = "John Cremona" info = {} title = "Bianchi cusp forms" data = None properties = [] friends = [] bread = get_bread() try: numeigs = request.args['numeigs'] numeigs = int(numeigs) except: numeigs = 20 info['numeigs'] = numeigs try: data = WebBMF.by_label(label, max_eigs=numeigs) title = "Bianchi cusp form {} over {}".format( data.short_label, field_pretty(data.field_label)) bread = get_bread([(field_pretty(data.field_label), url_for(".render_bmf_field_dim_table_gl2", field_label=data.field_label)), (data.level_label, url_for('.render_bmf_space_webpage', field_label=data.field_label, level_label=data.level_label)), (data.short_label, '')]) properties = data.properties friends = data.friends info['downloads'] = [('Modular form to Magma', url_for(".render_bmf_webpage_download", field_label=field_label, label_suffix=label_suffix, level_label=level_label, download_type='magma')), ('Eigenvalues to Sage', url_for(".render_bmf_webpage_download", field_label=field_label, label_suffix=label_suffix, level_label=level_label, download_type='sage'))] except ValueError: flash_error("No Bianchi modular form in the database has label %s", label) return redirect(url_for(".index")) return render_template( "bmf-newform.html", downloads=info["downloads"], title=title, credit=credit, bread=bread, data=data, properties=properties, friends=friends, info=info, learnmore=learnmore_list(), KNOWL_ID="mf.bianchi.%s" % label, )
def bianchi_modular_form_postprocess(res, info, query): if info['number'] > 0: info['field_pretty_name'] = field_pretty(res[0]['field_label']) else: info['field_pretty_name'] = '' res.sort(key=lambda x: [x['level_norm'], int(x['level_number']), x['label_suffix']]) return res
def bianchi_modular_form_postprocess(res, info, query): if info['number'] > 0: info['field_pretty_name'] = field_pretty(res[0]['field_label']) else: info['field_pretty_name'] = '' res.sort(key=lambda x: [x['level_norm'], int(x['level_number']), x['label_suffix']]) return res
def display_number_field(self): if self.is_simple: if self.nf(): return nf_display_knowl(self.nf(), field_pretty(self.nf())) else: return "The number field of this isogeny class is not in the database." else: return "The class is not simple"
def describe_end_algebra(p, extension_label): # This should eventually be done with a join, but okay for now factor_data = db.av_fq_endalg_data.lookup(extension_label) if factor_data is None: return None center = factor_data["center"] divalg_dim = factor_data["divalg_dim"] places = factor_data["places"] brauer_invariants = factor_data["brauer_invariants"] ans = ["", ""] if center == "1.1.1.1" and divalg_dim == 4: ans[0] = "B" ans[1] = r"the quaternion algebra over {0} ramified at ${1}$ and $\infty$.".format( nf_display_knowl(center, field_pretty(center)), p) elif int(center.split(".")[1]) > 0: ans[0] = "B" if divalg_dim == 4: ans[1] = "the quaternion algebra" else: ans[1] = "the division algebra of dimension " + str(divalg_dim) ans[1] += " over {0} ramified at both real infinite places.".format( nf_display_knowl(center, field_pretty(center))) elif divalg_dim == 1: ans[0] = "K" ans[1] = nf_display_knowl(center, field_pretty(center)) + "." else: ans[0] = "B" if divalg_dim == 4: ans[1] = "the quaternion algebra" else: ans[1] = "the division algebra of dimension " + str(divalg_dim) ans[1] += " over {0} with the following ramification data at primes above ${1}$, and unramified at all archimedean places:".format( nf_display_knowl(center, field_pretty(center)), p) ans[1] += '</td></tr><tr><td><table class = "ntdata"><tr><td>$v$</td>' for prime in places: ans[1] += '<td class="center"> {0} </td>'.format( primeideal_display(p, prime)) ans[1] += r"</tr><tr><td>$\operatorname{inv}_v$</td>" for inv in brauer_invariants: ans[1] += '<td class="center">${0}$</td>'.format(inv) ans[1] += "</tr></table>\n" center_poly = db.nf_fields.lookup(center, 'coeffs') center_poly = latex.latex(ZZ["x"](center_poly)) ans[1] += r"where $\pi$ is a root of ${0}$.\n".format(center_poly) return ans
def render_bmf_webpage(field_label, level_label, label_suffix): label = "-".join([field_label, level_label, label_suffix]) credit = "John Cremona" bread = [] info = {} title = "Bianchi cusp forms" data = None properties = [] friends = [] bread = [('Modular forms', url_for('modular_forms')), ('Bianchi', url_for(".index"))] try: data = WebBMF.by_label(label) title = "Bianchi cusp form {} over {}".format( data.short_label, field_pretty(data.field_label)) bread = [('Modular forms', url_for('modular_forms')), ('Bianchi', url_for(".index")), (field_pretty(data.field_label), url_for(".render_bmf_field_dim_table_gl2", field_label=data.field_label)), (data.level_label, url_for('.render_bmf_space_webpage', field_label=data.field_label, level_label=data.level_label)), (data.short_label, '')] properties = data.properties friends = data.friends except ValueError: raise info[ 'err'] = "No Bianchi modular form in the database has label {}".format( label) return render_template("bmf-newform.html", title=title, credit=credit, bread=bread, data=data, properties=properties, friends=friends, info=info, learnmore=learnmore_list())
def render_bmf_webpage(field_label, level_label, label_suffix): label = "-".join([field_label, level_label, label_suffix]) credit = "John Cremona" bread = [] info = {} title = "Bianchi cusp forms" data = None properties2 = [] friends = [] bread = [('Modular Forms', url_for('mf.modular_form_main_page')), ('Bianchi Modular Forms', url_for(".index"))] try: data = WebBMF.by_label(label) title = "Bianchi cusp form {} over {}".format(data.short_label,field_pretty(data.field_label)) bread = [('Modular Forms', url_for('mf.modular_form_main_page')), ('Bianchi Modular Forms', url_for(".index")), (field_pretty(data.field_label), url_for(".render_bmf_field_dim_table_gl2", field_label=data.field_label)), (data.level_label, url_for('.render_bmf_space_webpage', field_label=data.field_label, level_label=data.level_label)), (data.short_label, '')] properties2 = data.properties2 friends = data.friends except ValueError: raise info['err'] = "No Bianchi modular form in the database has label {}".format(label) return render_template("bmf-newform.html", title=title, credit=credit, bread=bread, data=data, properties2=properties2, friends=friends, info=info)
def av_data(label): abvar = db.av_fq_isog.lookup(label) if abvar is None: return "This isogeny class is not in the database." inf = "<div>Dimension: " + str(abvar["g"]) + "<br />" if abvar["is_simple"]: nf = abvar["number_fields"][0] wnf = WebNumberField(nf) if not wnf.is_null(): inf += ("Number field: " + nf_display_knowl(nf, name=field_pretty(nf)) + "<br />") inf += "Galois group: " + transitive_group_display_knowl( abvar["galois_groups"][0]) + "<br />" inf += "$p$-rank: " + str(abvar["p_rank"]) + "</div>" inf += '<div align="right">' g, q, iso = split_label(label) url = url_for("abvarfq.abelian_varieties_by_gqi", g=g, q=q, iso=iso) inf += '<a href="%s">%s home page</a>' % (url, label) inf += "</div>" return inf
def render_bmf_space_webpage(field_label, level_label): info = {} t = "Bianchi Modular Forms of Level %s over %s" % (level_label, field_label) credit = bianchi_credit bread = [('Modular Forms', url_for('mf.modular_form_main_page')), ('Bianchi Modular Forms', url_for(".index")), (field_pretty(field_label), url_for(".render_bmf_field_dim_table_gl2", field_label=field_label)), (level_label, '')] friends = [] properties2 = [] if not field_label_regex.match(field_label): info['err'] = "%s is not a valid label for an imaginary quadratic field" % field_label else: pretty_field_label = field_pretty(field_label) if not db.bmf_dims.exists({'field_label': field_label}): info['err'] = "no dimension information exists in the database for field %s" % pretty_field_label else: t = "Bianchi Modular Forms of level %s over %s" % (level_label, pretty_field_label) data = db.bmf_dims.lucky({'field_label': field_label, 'level_label': level_label}) if not data: info['err'] = "no dimension information exists in the database for level %s and field %s" % (level_label, pretty_field_label) else: info['label'] = data['label'] info['nf'] = nf = WebNumberField(field_label) info['field_label'] = field_label info['pretty_field_label'] = pretty_field_label info['level_label'] = level_label info['level_norm'] = data['level_norm'] info['field_poly'] = teXify_pol(str(nf.poly())) info['field_knowl'] = nf_display_knowl(field_label, pretty_field_label) w = 'i' if nf.disc()==-4 else 'a' L = nf.K().change_names(w) alpha = L.gen() info['field_gen'] = latex(alpha) I = ideal_from_label(L,level_label) info['level_gen'] = latex(I.gens_reduced()[0]) info['level_fact'] = web_latex_ideal_fact(I.factor(), enclose=False) dim_data = data['gl2_dims'] weights = dim_data.keys() weights.sort(key=lambda w: int(w)) for w in weights: dim_data[w]['dim']=dim_data[w]['cuspidal_dim'] info['dim_data'] = dim_data info['weights'] = weights info['nweights'] = len(weights) newdim = data['gl2_dims']['2']['new_dim'] newforms = db.bmf_forms.search({'field_label':field_label, 'level_label':level_label}) info['nfdata'] = [{ 'label': f['short_label'], 'url': url_for(".render_bmf_webpage",field_label=f['field_label'], level_label=f['level_label'], label_suffix=f['label_suffix']), 'wt': f['weight'], 'dim': f['dimension'], 'sfe': "+1" if f.get('sfe',None)==1 else "-1" if f.get('sfe',None)==-1 else "?", 'bc': bc_info(f['bc']), 'cm': cm_info(f.get('CM','?')), } for f in newforms] info['nnewforms'] = len(info['nfdata']) properties2 = [('Base field', pretty_field_label), ('Level',info['level_label']), ('Norm',str(info['level_norm'])), ('New dimension',str(newdim))] friends = [('Newform {}'.format(f['label']), f['url']) for f in info['nfdata'] ] return render_template("bmf-space.html", info=info, credit=credit, title=t, bread=bread, properties2=properties2, friends=friends)
label.split('-') ))) @search_wrap(template="bmf-search_results.html", table=db.bmf_forms, title='Bianchi modular form search results', err_title='Bianchi modular forms search input error', shortcuts={'jump': bianchi_modular_form_jump}, projection=['label','field_label','short_label','level_label','level_norm','label_suffix','level_ideal','dimension','sfe','bc','CM'], cleaners={"level_number": lambda v: v['level_label'].split(".")[1], "level_ideal": lambda v: teXify_pol(v['level_ideal']), "sfe": lambda v: "+1" if v.get('sfe',None)==1 else ("-1" if v.get('sfe',None)==-1 else "?"), "url": lambda v: url_for('.render_bmf_webpage',field_label=v['field_label'], level_label=v['level_label'], label_suffix=v['label_suffix']), "bc": lambda v: bc_info(v['bc']), "cm": lambda v: cm_info(v.pop('CM', '?')), "field_knowl": lambda e: nf_display_knowl(e['field_label'], field_pretty(e['field_label']))}, bread=lambda:get_bread("Search results"), url_for_label=url_for_label, learnmore=learnmore_list, properties=lambda: []) def bianchi_modular_form_search(info, query): """Function to handle requests from the top page, either jump to one newform or do a search. """ parse_nf_string(info, query, 'field_label', name='base number field') parse_noop(info, query, 'label') parse_ints(info, query, 'dimension') parse_ints(info, query, 'level_norm') parse_primes(info, query, 'field_bad_primes', name='field bad primes', qfield='field_bad_primes',mode=info.get('field_bad_quantifier'))
def bmf_field_dim_table(**args): argsdict = to_dict(args) argsdict.update(to_dict(request.args)) gl_or_sl = argsdict['gl_or_sl'] field_label=argsdict['field_label'] field_label = nf_string_to_label(field_label) start = parse_start(argsdict) info={} info['gl_or_sl'] = gl_or_sl # level_flag controls whether to list all levels ('all'), only # those with positive cuspidal dimension ('cusp'), or only those # with positive new dimension ('new'). Default is 'cusp'. level_flag = argsdict.get('level_flag', 'cusp') info['level_flag'] = level_flag count = parse_count(argsdict, 50) pretty_field_label = field_pretty(field_label) bread = [('Bianchi Modular Forms', url_for(".index")), ( pretty_field_label, ' ')] properties = [] query = {} query['field_label'] = field_label if gl_or_sl=='gl2_dims': info['group'] = 'GL(2)' info['bgroup'] = '\GL(2,\mathcal{O}_K)' else: info['group'] = 'SL(2)' info['bgroup'] = '\SL(2,\mathcal{O}_K)' if level_flag == 'all': query[gl_or_sl] = {'$exists': True} else: # Only get records where the cuspdial/new dimension is positive for some weight totaldim = gl_or_sl.replace('dims', level_flag) + '_totaldim' query[totaldim] = {'$gt': 0} t = ' '.join(['Dimensions of Spaces of {} Bianchi Modular Forms over'.format(info['group']), pretty_field_label]) data = list(db.bmf_dims.search(query, limit=count, offset=start, info=info)) nres = info['number'] if not info['exact_count']: info['number'] = nres = db.bmf_dims.count(query) info['exact_count'] = True if nres > count or start != 0: info['report'] = 'Displaying items %s-%s of %s levels,' % (start + 1, min(nres, start + count), nres) else: info['report'] = 'Displaying all %s levels,' % nres info['field'] = field_label info['field_pretty'] = pretty_field_label nf = WebNumberField(field_label) 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())) weights = set() for dat in data: weights = weights.union(set(dat[gl_or_sl].keys())) weights = list([int(w) for w in weights]) weights.sort() info['weights'] = weights info['nweights'] = len(weights) data.sort(key = lambda x: [int(y) for y in x['level_label'].split(".")]) dims = {} for dat in data: dims[dat['level_label']] = d = {} for w in weights: sw = str(w) if sw in dat[gl_or_sl]: d[w] = {'d': dat[gl_or_sl][sw]['cuspidal_dim'], 'n': dat[gl_or_sl][sw]['new_dim']} else: d[w] = {'d': '?', 'n': '?'} info['nlevels'] = len(data) dimtable = [{'level_label': dat['level_label'], 'level_norm': dat['level_norm'], 'level_space': url_for(".render_bmf_space_webpage", field_label=field_label, level_label=dat['level_label']) if gl_or_sl=='gl2_dims' else "", 'dims': dims[dat['level_label']]} for dat in data] info['dimtable'] = dimtable return render_template("bmf-field_dim_table.html", info=info, title=t, properties=properties, bread=bread)
def display_number_field(self): if self.nf == "": return "The number field of this isogeny class is not in the database." else: return nf_display_knowl(self.nf, field_pretty(self.nf))
lambda v: teXify_pol(v['level_ideal']), "sfe": lambda v: "+1" if v.get('sfe', None) == 1 else ("-1" if v.get('sfe', None) == -1 else "?"), "url": lambda v: url_for('.render_bmf_webpage', field_label=v['field_label'], level_label=v['level_label'], label_suffix=v['label_suffix']), "bc": lambda v: bc_info(v['bc']), "cm": lambda v: cm_info(v.pop('CM', '?')), "field_knowl": lambda e: nf_display_knowl(e['field_label'], field_pretty(e['field_label'])) }, bread=lambda: get_bread("Search results"), url_for_label=url_for_label, learnmore=learnmore_list, properties=lambda: []) def bianchi_modular_form_search(info, query): """Function to handle requests from the top page, either jump to one newform or do a search. """ parse_nf_string(info, query, 'field_label', name='base number field') parse_noop(info, query, 'label') parse_ints(info, query, 'dimension') parse_ints(info, query, 'level_norm') if not 'sfe' in info: info['sfe'] = "any"
def name_and_object_from_url(url, check_existence=False): # the import is here to avoid circular imports from lmfdb import db url_split = url.rstrip('/').lstrip('/').split("/") name = '??' obj_exists = False if url_split[0] == "EllipticCurve": # every EC instance was added from EC obj_exists = True if url_split[1] == 'Q': if len(url_split) == 4: # isogeny class # EllipticCurve/Q/341641/a label_isogeny_class = ".".join(url_split[-2:]) if check_existence: obj_exists = db.ec_curvedata.exists( {"lmfdb_iso": label_isogeny_class}) elif len(url_split) == 5: # curve # EllipticCurve/Q/48/a/6 label_curve = ".".join(url_split[-3:-1]) + url_split[-1] if check_existence: obj_exists = db.ec_curvedata.exists( {"lmfdb_label": label_curve}) else: raise NotImplementedError else: if len(url_split) == 4: # isogeny class # EllipticCurve/2.2.140.1/14.1/a field, cond, isog = url_split[-3:] label_isogeny_class = "-".join([field, cond, isog]) if check_existence: obj_exists = db.ec_nfcurves.exists( {"class_label": label_isogeny_class}) elif len(url_split) == 5: # curve # EllipticCurve/2.0.4.1/1250.3/a/3 field, cond, isog, ind = url_split[-4:] label_curve = "-".join([field, cond, isog]) + ind if check_existence: obj_exists = db.ec_nfcurves.exists({"label": label_curve}) if len(url_split) == 4: # isogeny class #name = 'Isogeny class ' + label_isogeny_class name = 'Elliptic curve ' + label_isogeny_class elif len(url_split) == 5: # curve #name = 'Curve ' + label_curve name = 'Elliptic curve ' + label_curve elif url_split[0] == "Character": # Character/Dirichlet/19/8 assert url_split[1] == "Dirichlet" name = r"Dirichlet character \(\chi_{%s} (%s, \cdot) \)" % tuple( url_split[-2:]) label = ".".join(url_split[-2:]) obj_exists = True if check_existence: obj_exists = db.char_dir_values.exists({"label": label}) elif url_split[0] == "Genus2Curve": obj_exists = True assert url_split[1] == 'Q' if len(url_split) == 4: # isog class # Genus2Curve/Q/310329/a label_isogeny_class = ".".join(url_split[-2:]) if check_existence: obj_exists = db.g2c_curves.exists( {"class": label_isogeny_class}) #name = 'Isogeny class ' + label_isogeny_class name = 'Genus 2 curve ' + label_isogeny_class if len(url_split) == 6: # curve # Genus2Curve/Q/1728/b/442368/1 label_curve = ".".join(url_split[-4:]) if check_existence: obj_exists = db.g2c_curves.exists({"label": label_curve}) #name = 'Curve ' + label_curve name = 'Genus 2 curve ' + label_curve elif url_split[0] == "ModularForm": if url_split[1] == 'GL2': if url_split[2] == 'Q' and url_split[3] == 'holomorphic': if len(url_split) == 10: # ModularForm/GL2/Q/holomorphic/24/2/f/a/11/2 newform_label = ".".join(url_split[-6:-2]) conrey_newform_label = ".".join(url_split[-6:]) name = 'Modular form ' + conrey_newform_label obj_exists = True if check_existence: obj_exists = db.mf_newforms.label_exists(newform_label) elif len(url_split) == 8: # ModularForm/GL2/Q/holomorphic/24/2/f/a newform_label = ".".join(url_split[-4:]) name = 'Modular form ' + newform_label obj_exists = True if check_existence: obj_exists = db.mf_newforms.label_exists(newform_label) elif url_split[2] == 'TotallyReal': # ModularForm/GL2/TotallyReal/2.2.140.1/holomorphic/2.2.140.1-14.1-a label = url_split[-1] name = 'Hilbert modular form ' + label obj_exists = True if check_existence: obj_exists = db.hmf_forms.label_exists(label) elif url_split[2] == 'ImaginaryQuadratic': # ModularForm/GL2/ImaginaryQuadratic/2.0.4.1/98.1/a label = '-'.join(url_split[-3:]) name = 'Bianchi modular form ' + label obj_exists = 'CM' not in label if check_existence: obj_exists = db.bmf_forms.label_exists(label) elif url_split[0] == "ArtinRepresentation": label = url_split[1] name = 'Artin representation ' + label obj_exists = True if check_existence: obj_exists = db.artin_reps.label_exists(label.split('c')[0]) elif url_split[0] == "NumberField": from lmfdb.number_fields.web_number_field import field_pretty label = url_split[1] name = 'Number field ' + field_pretty(label) obj_exists = True if check_existence: obj_exists = db.number_fields.label_exists(label) elif url_split[0] == "SatoTateGroup": from lmfdb.sato_tate_groups.main import get_name name, label = get_name(url_split[1]) if name is None: name = label obj_exists = False else: name = 'Sato Tate group $%s$' % name obj_exists = True else: # FIXME #print("unknown url", url) pass return name, obj_exists
def make_class(self): # Create a list of the curves in the class from the database self.db_curves = list(db.ec_nfcurves.search( {'field_label': self.field_label, 'conductor_norm': self.conductor_norm, 'conductor_label': self.conductor_label, 'iso_nlabel': self.iso_nlabel})) # Rank or bounds try: self.rk = web_latex(self.db_curves[0]['rank']) except KeyError: self.rk = "?" try: self.rk_bnds = "%s...%s" % tuple(self.db_curves[0]['rank_bounds']) except KeyError: self.rank_bounds = [0, Infinity] self.rk_bnds = "not recorded" # Extract the isogeny degree matrix from the database if not hasattr(self, 'isogeny_matrix'): # this would happen if the class is initiated with a curve # which is not #1 in its class: self.isogeny_matrix = self.db_curves[0].isogeny_matrix self.isogeny_matrix = Matrix(self.isogeny_matrix) self.one_deg = ZZ(self.class_deg).is_prime() # Create isogeny graph: self.graph = make_graph(self.isogeny_matrix) P = self.graph.plot(edge_labels=True) self.graph_img = encode_plot(P) self.graph_link = '<img src="%s" width="200" height="150"/>' % self.graph_img self.isogeny_matrix_str = latex(Matrix(self.isogeny_matrix)) self.field = FIELD(self.field_label) self.field_name = field_pretty(self.field_label) self.field_knowl = nf_display_knowl(self.field_label, self.field_name) def curve_url(c): return url_for(".show_ecnf", nf=c['field_label'], conductor_label=c['conductor_label'], class_label=c['iso_label'], number=c['number']) self.curves = [[c['short_label'], curve_url(c), web_ainvs(self.field_label,c['ainvs'])] for c in self.db_curves] self.urls = {} self.urls['class'] = url_for(".show_ecnf_isoclass", nf=self.field_label, conductor_label=self.conductor_label, class_label=self.iso_label) self.urls['conductor'] = url_for(".show_ecnf_conductor", nf=self.field_label, conductor_label=self.conductor_label) self.urls['field'] = url_for('.show_ecnf1', nf=self.field_label) sig = self.signature totally_real = sig[1] == 0 imag_quadratic = sig == [0,1] if totally_real: self.hmf_label = "-".join([self.field_label, self.conductor_label, self.iso_label]) self.urls['hmf'] = url_for('hmf.render_hmf_webpage', field_label=self.field_label, label=self.hmf_label) lfun_url = url_for("l_functions.l_function_ecnf_page", field_label=self.field_label, conductor_label=self.conductor_label, isogeny_class_label=self.iso_label) origin_url = lfun_url.lstrip('/L/').rstrip('/') if sig[0] <= 2 and db.lfunc_instances.exists({'url':origin_url}): self.urls['Lfunction'] = lfun_url elif self.abs_disc ** 2 * self.conductor_norm < 40000: # we shouldn't trust the Lfun computed on the fly for large conductor self.urls['Lfunction'] = url_for("l_functions.l_function_hmf_page", field=self.field_label, label=self.hmf_label, character='0', number='0') if imag_quadratic: self.bmf_label = "-".join([self.field_label, self.conductor_label, self.iso_label]) self.bmf_url = url_for('bmf.render_bmf_webpage', field_label=self.field_label, level_label=self.conductor_label, label_suffix=self.iso_label) lfun_url = url_for("l_functions.l_function_ecnf_page", field_label=self.field_label, conductor_label=self.conductor_label, isogeny_class_label=self.iso_label) origin_url = lfun_url.lstrip('/L/').rstrip('/') if db.lfunc_instances.exists({'url':origin_url}): self.urls['Lfunction'] = lfun_url self.friends = [] if totally_real: self.friends += [('Hilbert Modular Form ' + self.hmf_label, self.urls['hmf'])] if imag_quadratic: if "CM" in self.label: self.friends += [('Bianchi Modular Form is not cuspidal', '')] else: if db.bmf_forms.label_exists(self.bmf_label): self.friends += [('Bianchi Modular Form %s' % self.bmf_label, self.bmf_url)] else: self.friends += [('Bianchi Modular Form %s not available' % self.bmf_label, '')] if 'Lfunction' in self.urls: self.friends += [('L-function', self.urls['Lfunction'])] else: self.friends += [('L-function not available', "")] self.properties = [('Base field', self.field_name), ('Label', self.class_label), (None, self.graph_link), ('Conductor', '%s' % self.conductor_label) ] if self.rk != '?': self.properties += [('Rank', '%s' % self.rk)] else: if self.rk_bnds == 'not recorded': self.properties += [('Rank', '%s' % self.rk_bnds)] else: self.properties += [('Rank bounds', '%s' % self.rk_bnds)] self.bread = [('Elliptic Curves ', url_for(".index")), (self.field_label, self.urls['field']), (self.conductor_label, self.urls['conductor']), ('isogeny class %s' % self.short_label, self.urls['class'])]
def make_class(self): # Create a list of the curves in the class from the database self.db_curves = list(db.ec_nfcurves.search( {'field_label': self.field_label, 'conductor_norm': self.conductor_norm, 'conductor_label': self.conductor_label, 'iso_nlabel': self.iso_nlabel})) # Rank or bounds try: self.rk = web_latex(self.db_curves[0]['rank']) except KeyError: self.rk = "?" try: self.rk_bnds = "%s...%s" % tuple(self.db_curves[0]['rank_bounds']) except KeyError: self.rank_bounds = [0, Infinity] self.rk_bnds = "not recorded" # Extract the isogeny degree matrix from the database if not hasattr(self, 'isogeny_matrix'): # this would happen if the class is initiated with a curve # which is not #1 in its class: self.isogeny_matrix = self.db_curves[0].isogeny_matrix self.isogeny_matrix = Matrix(self.isogeny_matrix) self.one_deg = ZZ(self.class_deg).is_prime() # Create isogeny graph: self.graph = make_graph(self.isogeny_matrix) P = self.graph.plot(edge_labels=True) self.graph_img = encode_plot(P) self.graph_link = '<img src="%s" width="200" height="150"/>' % self.graph_img self.isogeny_matrix_str = latex(Matrix(self.isogeny_matrix)) self.field = FIELD(self.field_label) self.field_name = field_pretty(self.field_label) self.field_knowl = nf_display_knowl(self.field_label, self.field_name) def curve_url(c): return url_for(".show_ecnf", nf=c['field_label'], conductor_label=c['conductor_label'], class_label=c['iso_label'], number=c['number']) self.curves = [[c['short_label'], curve_url(c), web_ainvs(self.field_label,c['ainvs'])] for c in self.db_curves] self.urls = {} self.urls['class'] = url_for(".show_ecnf_isoclass", nf=self.field_label, conductor_label=self.conductor_label, class_label=self.iso_label) self.urls['conductor'] = url_for(".show_ecnf_conductor", nf=self.field_label, conductor_label=self.conductor_label) self.urls['field'] = url_for('.show_ecnf1', nf=self.field_label) sig = self.signature totally_real = sig[1] == 0 imag_quadratic = sig == [0,1] if totally_real: self.hmf_label = "-".join([self.field_label, self.conductor_label, self.iso_label]) self.urls['hmf'] = url_for('hmf.render_hmf_webpage', field_label=self.field_label, label=self.hmf_label) lfun_url = url_for("l_functions.l_function_ecnf_page", field_label=self.field_label, conductor_label=self.conductor_label, isogeny_class_label=self.iso_label) origin_url = lfun_url.lstrip('/L/').rstrip('/') if sig[0] <= 2 and db.lfunc_instances.exists({'url': origin_url}): self.urls['Lfunction'] = lfun_url elif self.abs_disc ** 2 * self.conductor_norm < 40000: # we shouldn't trust the Lfun computed on the fly for large conductor self.urls['Lfunction'] = url_for("l_functions.l_function_hmf_page", field=self.field_label, label=self.hmf_label, character='0', number='0') if imag_quadratic: self.bmf_label = "-".join([self.field_label, self.conductor_label, self.iso_label]) self.bmf_url = url_for('bmf.render_bmf_webpage', field_label=self.field_label, level_label=self.conductor_label, label_suffix=self.iso_label) lfun_url = url_for("l_functions.l_function_ecnf_page", field_label=self.field_label, conductor_label=self.conductor_label, isogeny_class_label=self.iso_label) origin_url = lfun_url.lstrip('/L/').rstrip('/') if db.lfunc_instances.exists({'url':origin_url}): self.urls['Lfunction'] = lfun_url # most of this code is repeated in WebEllipticCurve.py # and should be refactored self.friends = [] if totally_real and 'Lfunction' not in self.urls: self.friends += [('Hilbert modular form ' + self.hmf_label, self.urls['hmf'])] if imag_quadratic: if "CM" in self.label: self.friends += [('Bianchi modular form is not cuspidal', '')] elif 'Lfunction' not in self.urls: if db.bmf_forms.label_exists(self.bmf_label): self.friends += [('Bianchi modular form %s' % self.bmf_label, self.bmf_url)] else: self.friends += [('(Bianchi modular form %s)' % self.bmf_label, '')] if 'Lfunction' in self.urls: Lfun = get_lfunction_by_url(self.urls['Lfunction'].lstrip('/L').rstrip('/'), projection=['degree', 'trace_hash', 'Lhash']) instances = get_instances_by_Lhash_and_trace_hash( Lfun['Lhash'], Lfun['degree'], Lfun.get('trace_hash')) exclude={elt[1].rstrip('/').lstrip('/') for elt in self.friends if elt[1]} exclude.add(lfun_url.lstrip('/L/').rstrip('/')) self.friends += names_and_urls(instances, exclude=exclude) self.friends += [('L-function', self.urls['Lfunction'])] else: self.friends += [('L-function not available', "")] self.properties = [('Base field', self.field_name), ('Label', self.class_label), (None, self.graph_link), ('Conductor', '%s' % self.conductor_label) ] if self.rk != '?': self.properties += [('Rank', '%s' % self.rk)] else: if self.rk_bnds == 'not recorded': self.properties += [('Rank', '%s' % self.rk_bnds)] else: self.properties += [('Rank bounds', '%s' % self.rk_bnds)] self.bread = [('Elliptic curves ', url_for(".index")), (self.field_label, self.urls['field']), (self.conductor_label, self.urls['conductor']), ('isogeny class %s' % self.short_label, self.urls['class'])]
info['field_pretty_name'] = field_pretty(res[0]['field_label']) else: info['field_pretty_name'] = '' res.sort(key=lambda x: [x['level_norm'], int(x['level_number']), x['label_suffix']]) return res def url_for_label(label): return url_for(".render_bmf_webpage", **dict(zip( ['field_label', 'level_label', 'label_suffix'], label.split('-') ))) bmf_columns = SearchColumns([ ProcessedCol("field_label", "nf", "Base field", lambda fld: nf_display_knowl(fld, field_pretty(fld)), default=True), MultiProcessedCol("level", "mf.bianchi.level", "Level", ["field_label", "level_label"], lambda fld, lvl: '<a href="{}">{}</a>'.format( url_for("bmf.render_bmf_space_webpage", field_label=fld, level_label=lvl), lvl), default=True), # teXify_pol(v['level_ideal']) MultiProcessedCol("label", "mf.bianchi.labels", "Label", ["field_label", "level_label", "label_suffix", "short_label"], lambda fld, lvl, suff, short: '<a href="{}">{}</a>'.format( url_for("bmf.render_bmf_webpage", field_label=fld, level_label=lvl, label_suffix=suff), short),
def render_bmf_space_webpage(field_label, level_label): info = {} t = "Bianchi Modular Forms of Level %s over %s" % (level_label, field_label) credit = bianchi_credit bread = [('Modular Forms', url_for('modular_forms')), ('Bianchi Modular Forms', url_for(".index")), (field_pretty(field_label), url_for(".render_bmf_field_dim_table_gl2", field_label=field_label)), (level_label, '')] friends = [] properties = [] if not field_label_regex.match(field_label): info['err'] = "%s is not a valid label for an imaginary quadratic field" % field_label else: pretty_field_label = field_pretty(field_label) if not db.bmf_dims.exists({'field_label': field_label}): info['err'] = "no dimension information exists in the database for field %s" % pretty_field_label else: t = "Bianchi Modular Forms of level %s over %s" % (level_label, pretty_field_label) data = db.bmf_dims.lucky({'field_label': field_label, 'level_label': level_label}) if not data: info['err'] = "no dimension information exists in the database for level %s and field %s" % (level_label, pretty_field_label) else: info['label'] = data['label'] info['nf'] = nf = WebNumberField(field_label) info['field_label'] = field_label info['pretty_field_label'] = pretty_field_label info['level_label'] = level_label info['level_norm'] = data['level_norm'] info['field_poly'] = teXify_pol(str(nf.poly())) info['field_knowl'] = nf_display_knowl(field_label, pretty_field_label) w = 'i' if nf.disc()==-4 else 'a' L = nf.K().change_names(w) alpha = L.gen() info['field_gen'] = latex(alpha) I = ideal_from_label(L,level_label) info['level_gen'] = latex(I.gens_reduced()[0]) info['level_fact'] = web_latex_ideal_fact(I.factor(), enclose=False) dim_data = data['gl2_dims'] weights = dim_data.keys() weights.sort(key=lambda w: int(w)) for w in weights: dim_data[w]['dim']=dim_data[w]['cuspidal_dim'] info['dim_data'] = dim_data info['weights'] = weights info['nweights'] = len(weights) newdim = data['gl2_dims']['2']['new_dim'] newforms = db.bmf_forms.search({'field_label':field_label, 'level_label':level_label}) info['nfdata'] = [{ 'label': f['short_label'], 'url': url_for(".render_bmf_webpage",field_label=f['field_label'], level_label=f['level_label'], label_suffix=f['label_suffix']), 'wt': f['weight'], 'dim': f['dimension'], 'sfe': "+1" if f.get('sfe',None)==1 else "-1" if f.get('sfe',None)==-1 else "?", 'bc': bc_info(f['bc']), 'cm': cm_info(f.get('CM','?')), } for f in newforms] info['nnewforms'] = len(info['nfdata']) # currently we have newforms of dimension 1 and 2 only (mostly dimension 1) info['nnf1'] = sum(1 for f in info['nfdata'] if f['dim']==1) info['nnf2'] = sum(1 for f in info['nfdata'] if f['dim']==2) info['nnf_missing'] = dim_data['2']['new_dim'] - info['nnf1'] - 2*info['nnf2'] properties = [('Base field', pretty_field_label), ('Level',info['level_label']), ('Norm',str(info['level_norm'])), ('New dimension',str(newdim))] friends = [('Newform {}'.format(f['label']), f['url']) for f in info['nfdata'] ] return render_template("bmf-space.html", info=info, credit=credit, title=t, bread=bread, properties=properties, friends=friends, learnmore=learnmore_list())
def field_formatter(label): # Need to accept the output of nf_display_knowl label = field_unformatter(label) return nf_display_knowl(label, field_pretty(label))
def make_form(self): # 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() 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.nap = len(self.hecke_eigs) self.nap0 = min(50, self.nap) 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.nap0])] level = ideal_from_label(K,self.level_label) self.level_ideal2 = web_latex(level) badp = level.prime_factors() 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)] 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 = "\(0\)" if self.Lratio!=0 else "odd" if self.sfe==-1 else "\(\ge2\), even" self.properties2 = [('Base field', pretty_field), ('Weight', str(self.weight)), ('Level norm', str(self.level_norm)), ('Level', self.level_ideal2), ('Label', self.label), ('Dimension', str(self.dimension)) ] try: if self.CM == '?': self.CM = 'not determined' elif self.CM == 0: self.CM = 'no' else: if self.CM%4 in [2,3]: self.CM = 4*self.CM except AttributeError: self.CM = 'not determined' self.properties2.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 = ', of a form over \(\mathbb{Q}\) with coefficients in \(\mathbb{Q}(\sqrt{'+str(self.bcd)+'})\)' elif self.bc == -1: self.bc = 'no' self.bc_extra = ', 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 = ', but is a twist of the base-change of a form over \(\mathbb{Q}\) with coefficients in \(\mathbb{Q}(\sqrt{'+str(self.bcd)+'})\)' self.properties2.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: 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: self.ec_status = 'none' else: self.ec_status = 'missing' self.properties2.append(('Sign', self.sign)) self.properties2.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: # first by Lhash instances = get_instances_by_Lhash(Lfun['Lhash']) # then by trace_hash instances += get_instances_by_trace_hash(Lfun['degree'], Lfun['trace_hash']) # This will also add the EC/G2C, as this how the Lfun was computed self.friends = names_and_urls(instances) # remove itself self.friends.remove( ('Bianchi modular form {}'.format(self.label), '/' + 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_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 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_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 bmf_field_dim_table(**args): argsdict = to_dict(args) argsdict.update(to_dict(request.args)) gl_or_sl = argsdict['gl_or_sl'] field_label=argsdict['field_label'] field_label = nf_string_to_label(field_label) start = parse_start(argsdict) info={} info['gl_or_sl'] = gl_or_sl # level_flag controls whether to list all levels ('all'), only # those with positive cuspidal dimension ('cusp'), or only those # with positive new dimension ('new'). Default is 'cusp'. level_flag = argsdict.get('level_flag', 'cusp') info['level_flag'] = level_flag count = parse_count(argsdict, 50) pretty_field_label = field_pretty(field_label) bread = [('Bianchi Modular Forms', url_for(".index")), ( pretty_field_label, ' ')] properties = [] if gl_or_sl=='gl2_dims': info['group'] = 'GL(2)' info['bgroup'] = '\GL(2,\mathcal{O}_K)' else: info['group'] = 'SL(2)' info['bgroup'] = '\SL(2,\mathcal{O}_K)' t = ' '.join(['Dimensions of Spaces of {} Bianchi Modular Forms over'.format(info['group']), pretty_field_label]) query = {} query['field_label'] = field_label query[gl_or_sl] = {'$exists': True} data = db.bmf_dims.search(query, limit=count, offset=start, info=info) nres = info['number'] if nres > count or start != 0: info['report'] = 'Displaying items %s-%s of %s levels,' % (start + 1, min(nres, start + count), nres) else: info['report'] = 'Displaying all %s levels,' % nres # convert data to a list and eliminate levels where all # new/cuspidal dimensions are 0. (This could be done at the # search stage, but that requires adding new fields to each # record.) def filter(dat, flag): dat1 = dat[gl_or_sl] return any([int(dat1[w][flag])>0 for w in dat1]) flag = 'cuspidal_dim' if level_flag=='cusp' else 'new_dim' data = [dat for dat in data if level_flag == 'all' or filter(dat, flag)] info['field'] = field_label info['field_pretty'] = pretty_field_label nf = WebNumberField(field_label) 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())) weights = set() for dat in data: weights = weights.union(set(dat[gl_or_sl].keys())) weights = list([int(w) for w in weights]) weights.sort() info['weights'] = weights info['nweights'] = len(weights) data.sort(key = lambda x: [int(y) for y in x['level_label'].split(".")]) dims = {} for dat in data: dims[dat['level_label']] = d = {} for w in weights: sw = str(w) if sw in dat[gl_or_sl]: d[w] = {'d': dat[gl_or_sl][sw]['cuspidal_dim'], 'n': dat[gl_or_sl][sw]['new_dim']} else: d[w] = {'d': '?', 'n': '?'} info['nlevels'] = len(data) dimtable = [{'level_label': dat['level_label'], 'level_norm': dat['level_norm'], 'level_space': url_for(".render_bmf_space_webpage", field_label=field_label, level_label=dat['level_label']) if gl_or_sl=='gl2_dims' else "", 'dims': dims[dat['level_label']]} for dat in data] info['dimtable'] = dimtable return render_template("bmf-field_dim_table.html", info=info, title=t, properties=properties, bread=bread)
def render_field_webpage(args): data = None info = {} bread = [('Global Number Fields', url_for(".number_field_render_webpage"))] # 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 global 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['is_abelian'] = nf.is_abelian() if nf.is_abelian(): conductor = nf.conductor() data['conductor'] = conductor dirichlet_chars = nf.dirichlet_group() if len(dirichlet_chars)>0: data['dirichlet_group'] = ['<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] data['dirichlet_group'] = r'$\lbrace$' + ', '.join(data['dirichlet_group']) + r'$\rbrace$' if data['conductor'].is_prime() or data['conductor'] == 1: data['conductor'] = "\(%s\)" % str(data['conductor']) else: factored_conductor = factor_base_factor(data['conductor'], ram_primes) factored_conductor = factor_base_factorization_latex(factored_conductor) data['conductor'] = "\(%s=%s\)" % (str(data['conductor']), factored_conductor) data['galois_group'] = group_pretty_and_nTj(n,t,True) 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'] = "\(%s\)" % str(D) else: data['discriminant'] = "\(%s=%s\)" % (str(D), data['disc_factor']) 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: 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] 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 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 'Not' 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) if nf.degree() > 1: gpK = nf.gpK() rootof1coeff = gpK.nfrootsof1() rootofunityorder = int(rootof1coeff[1]) rootof1coeff = rootof1coeff[2] rootofunity = web_latex(Ra(str(pari("lift(%s)" % gpK.nfbasistoalg(rootof1coeff))).replace('x','a'))) rootofunity += ' (order $%d$)' % rootofunityorder else: rootofunity = web_latex(Ra('-1'))+ ' (order $2$)' info.update({ 'label': pretty_label, 'label_raw': label, 'polynomial': web_latex_split_on_pm(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(), 'grh_label': grh_label, 'loc_alg': loc_alg }) bread.append(('%s' % 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 len(galois_closure[1])>0: resinfo.append(('gc', galois_closure[1])) if len(galois_closure[2]) > 0: 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 len(sextic_twins[1])>0: 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 len(siblings[0])>0: for sibdeg in siblings[0]: if len(sibdeg[2]) ==0: sibdeg[2] = dnc else: sibdeg[2] = ', '.join(sibdeg[2]) if len(sibdeg[2])<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 len(arith_equiv[1])>0: 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 = "Global Number Field %s" % info['label'] if npr == 1: primes = 'prime' else: primes = 'primes' if len(label)>25: label = label[:16]+'...'+label[-6:] properties2 = [('Label', label), ('Degree', '$%s$' % data['degree']), ('Signature', '$%s$' % data['signature']), ('Discriminant', '$%s$' % data['disc_factor']), ('Root discriminant', '%s' % data['rd']), ('Ramified ' + primes + '', '$%s$' % 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 = [] for lang in [["Magma","magma"], ["SageMath","sage"], ["Pari/GP", "gp"]]: downloads.append(('Download {} code'.format(lang[0]), url_for(".nf_code_download", nf=label, download_type=lang[1]))) from lmfdb.artin_representations.math_classes import NumberFieldGaloisGroup try: info["tim_number_field"] = NumberFieldGaloisGroup(nf._data['coeffs']) 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("number_field.html", properties2=properties2, 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)