def bianchi_modular_form_by_label(lab): if lab == '': # do nothing: display the top page return redirect(url_for(".index")) if isinstance(lab, basestring): res = db_forms().find_one({'label': lab}) else: res = lab lab = res['label'] if res == None: flash(Markup("No Bianchi modular form in the database has label or name <span style='color:black'>%s</span>" % lab), "error") return redirect(url_for(".index")) else: return redirect(url_for(".render_bmf_webpage", field_label = res['field_label'], level_label = res['level_label'], label_suffix = res['label_suffix']))
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 = [('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_dims().find({'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_dims().find({ 'field_label': field_label, 'level_label': level_label }) nres = data.count() if nres == 0: info[ 'err'] = "no dimension information exists in the database for level %s and field %s" % ( level_label, pretty_field_label) else: data = data.next() info['label'] = data['label'] nf = WebNumberField(field_label) info['base_galois_group'] = nf.galois_string() 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_degree'] = nf.degree() info['field_classno'] = nf.class_number() info['field_disc'] = str(nf.disc()) info['field_poly'] = teXify_pol(str(nf.poly())) info['field_knowl'] = nf_display_knowl(field_label, getDBConnection(), 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'] = latex(I.factor()) 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_forms().find({ 'field_label': field_label, 'level_label': level_label }).sort('label_suffix', ASCENDING) 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['sfe'] == 1 else "-1", 'bc': bc_info(f['bc']), 'cm': cm_info(f['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)
def bianchi_modular_form_search(**args): """Function to handle requests from the top page, either jump to one newform or do a search. """ info = to_dict(args) # what has been entered in the search boxes if 'label' in info: # The Label button has been pressed. return bianchi_modular_form_by_label(info['label']) query = {} for field in ['field_label', 'weight', 'level_norm', 'dimension']: if info.get(field): if field == 'weight': query['weight'] = info[field] elif field == 'field_label': parse_nf_string(info, query, field, 'base number field', field) elif field == 'label': query[field] = info[field] elif field == 'dimension': query['dimension'] = int(info[field]) elif field == 'level_norm': query[field] = parse_range(info[field]) else: query[field] = info[field] if not 'sfe' in info: info['sfe'] = "any" elif info['sfe'] != "any": query['sfe'] = int(info['sfe']) if 'include_cm' in info: if info['include_cm'] == 'exclude': query['CM'] = 0 elif info['include_cm'] == 'only': query['CM'] = {'$nin': [0, '?']} if 'include_base_change' in info and info['include_base_change'] == 'off': query['bc'] = 0 else: info['include_base_change'] = "on" start = 0 if 'start' in request.args: start = int(request.args['start']) count = 50 if 'count' in request.args: count = int(request.args['count']) info['query'] = dict(query) res = db_forms().find(query).sort([('level_norm', ASCENDING), ('label', ASCENDING) ]).skip(start).limit(count) nres = res.count() if nres > 0: info['field_pretty_name'] = field_pretty(res[0]['field_label']) else: info['field_pretty_name'] = '' info['number'] = nres if nres == 1: info['report'] = 'unique match' elif nres == 2: info['report'] = 'displaying both matches' else: if nres > count or start != 0: info['report'] = 'displaying items %s-%s of %s matches' % ( start + 1, min(nres, start + count), nres) else: info['report'] = 'displaying all %s matches' % nres res_clean = [] for v in res: v_clean = {} v_clean['field_label'] = v['field_label'] v_clean['short_label'] = v['short_label'] v_clean['level_label'] = v['level_label'] v_clean['label_suffix'] = v['label_suffix'] v_clean['label'] = v['label'] v_clean['level_ideal'] = teXify_pol(v['level_ideal']) v_clean['dimension'] = v['dimension'] v_clean['sfe'] = "+1" if v['sfe'] == 1 else "-1" v_clean['url'] = url_for('.render_bmf_webpage', field_label=v['field_label'], level_label=v['level_label'], label_suffix=v['label_suffix']) v_clean['bc'] = bc_info(v['bc']) v_clean['cm'] = cm_info(v['CM']) res_clean.append(v_clean) info['forms'] = res_clean info['count'] = count info['start'] = start info['more'] = int(start + count < nres) t = 'Bianchi modular form search results' bread = [('Bianchi Modular Forms', url_for(".index")), ('Search results', ' ')] properties = [] return render_template("bmf-search_results.html", info=info, title=t, properties=properties, bread=bread, learnmore=learnmore_list())
def random_bmf(): # Random Hilbert modular form return bianchi_modular_form_by_label( random_object_from_collection(db_forms()))
def make_E(self): K = self.field.K() # a-invariants self.ainvs = parse_ainvs(K,self.ainvs) self.latex_ainvs = web_latex(self.ainvs) self.numb = str(self.number) # Conductor, discriminant, j-invariant N = ideal_from_string(K,self.conductor_ideal) self.cond = web_latex(N) self.cond_norm = web_latex(self.conductor_norm) local_data = self.local_data # NB badprimes is a list of primes which divide the # discriminant of this model. At most one of these might # actually be a prime of good reduction, if the curve has no # global minimal model. badprimes = [ideal_from_string(K,ld['p']) for ld in local_data] badnorms = [ZZ(ld['normp']) for ld in local_data] mindisc_ords = [ld['ord_disc'] for ld in local_data] # Assumption: the curve models stored in the database are # either global minimal models or minimal at all but one # prime, so the list here has length 0 or 1: self.non_min_primes = [ideal_from_string(K,P) for P in self.non_min_p] self.is_minimal = (len(self.non_min_primes) == 0) self.has_minimal_model = self.is_minimal disc_ords = [ld['ord_disc'] for ld in local_data] if not self.is_minimal: Pmin = self.non_min_primes[0] P_index = badprimes.index(Pmin) self.non_min_prime = web_latex(Pmin) disc_ords[P_index] += 12 if self.conductor_norm == 1: # since the factorization of (1) displays as "1" self.fact_cond = self.cond self.fact_cond_norm = self.cond else: Nfac = Factorization([(P,ld['ord_cond']) for P,ld in zip(badprimes,local_data)]) self.fact_cond = web_latex_ideal_fact(Nfac) Nnormfac = Factorization([(q,ld['ord_cond']) for q,ld in zip(badnorms,local_data)]) self.fact_cond_norm = web_latex(Nnormfac) # D is the discriminant ideal of the model D = prod([P**e for P,e in zip(badprimes,disc_ords)], K.ideal(1)) self.disc = web_latex(D) Dnorm = D.norm() self.disc_norm = web_latex(Dnorm) if Dnorm == 1: # since the factorization of (1) displays as "1" self.fact_disc = self.disc self.fact_disc_norm = self.disc else: Dfac = Factorization([(P,e) for P,e in zip(badprimes,disc_ords)]) self.fact_disc = web_latex_ideal_fact(Dfac) Dnormfac = Factorization([(q,e) for q,e in zip(badnorms,disc_ords)]) self.fact_disc_norm = web_latex(Dnormfac) if not self.is_minimal: Dmin = ideal_from_string(K,self.minD) self.mindisc = web_latex(Dmin) Dmin_norm = Dmin.norm() self.mindisc_norm = web_latex(Dmin_norm) if Dmin_norm == 1: # since the factorization of (1) displays as "1" self.fact_mindisc = self.mindisc self.fact_mindisc_norm = self.mindisc else: Dminfac = Factorization([(P,e) for P,edd in zip(badprimes,mindisc_ords)]) self.fact_mindisc = web_latex_ideal_fact(Dminfac) Dminnormfac = Factorization([(q,e) for q,e in zip(badnorms,mindisc_ords)]) self.fact_mindisc_norm = web_latex(Dminnormfac) j = self.field.parse_NFelt(self.jinv) # if j: # d = j.denominator() # n = d * j # numerator exists for quadratic fields only! # g = GCD(list(n)) # n1 = n / g # self.j = web_latex(n1) # if d != 1: # if n1 > 1: # # self.j = "("+self.j+")\(/\)"+web_latex(d) # self.j = web_latex(r"\frac{%s}{%s}" % (self.j, d)) # else: # self.j = web_latex(d) # if g > 1: # if n1 > 1: # self.j = web_latex(g) + self.j # else: # self.j = web_latex(g) self.j = web_latex(j) self.fact_j = None # See issue 1258: some j factorizations work but take too long # (e.g. EllipticCurve/6.6.371293.1/1.1/a/1). Note that we do # store the factorization of the denominator of j and display # that, which is the most interesting part. # Images of Galois representations if not hasattr(self,'galois_images'): #print "No Galois image data" self.galois_images = "?" self.non_surjective_primes = "?" self.galois_data = [] else: self.galois_data = [{'p': p,'image': im } for p,im in zip(self.non_surjective_primes, self.galois_images)] # CM and End(E) self.cm_bool = "no" self.End = "\(\Z\)" if self.cm: self.rational_cm = K(self.cm).is_square() self.cm_sqf = ZZ(self.cm).squarefree_part() self.cm_bool = "yes (\(%s\))" % self.cm if self.cm % 4 == 0: d4 = ZZ(self.cm) // 4 self.End = "\(\Z[\sqrt{%s}]\)" % (d4) else: self.End = "\(\Z[(1+\sqrt{%s})/2]\)" % self.cm # Galois images in CM case: if self.cm and self.galois_images != '?': self.cm_ramp = [p for p in ZZ(self.cm).support() if not p in self.non_surjective_primes] self.cm_nramp = len(self.cm_ramp) if self.cm_nramp==1: self.cm_ramp = self.cm_ramp[0] else: self.cm_ramp = ", ".join([str(p) for p in self.cm_ramp]) # Sato-Tate: # The lines below will need to change once we have curves over non-quadratic fields # that contain the Hilbert class field of an imaginary quadratic field if self.cm: if self.signature == [0,1] and ZZ(-self.abs_disc*self.cm).is_square(): self.ST = st_link_by_name(1,2,'U(1)') else: self.ST = st_link_by_name(1,2,'N(U(1))') else: self.ST = st_link_by_name(1,2,'SU(2)') # Q-curve / Base change self.qc = self.q_curve if self.qc == "?": self.qc = "not determined" elif self.qc == True: self.qc = "yes" elif self.qc == False: self.qc = "no" else: # just in case self.qc = "not determined" # Torsion self.ntors = web_latex(self.torsion_order) self.tr = len(self.torsion_structure) if self.tr == 0: self.tor_struct_pretty = "Trivial" if self.tr == 1: self.tor_struct_pretty = "\(\Z/%s\Z\)" % self.torsion_structure[0] if self.tr == 2: self.tor_struct_pretty = r"\(\Z/%s\Z\times\Z/%s\Z\)" % tuple(self.torsion_structure) torsion_gens = [parse_point(K,P) for P in self.torsion_gens] self.torsion_gens = ",".join([web_point(P) for P in torsion_gens]) # Rank or bounds try: self.rk = web_latex(self.rank) except AttributeError: self.rk = "?" try: self.rk_bnds = "%s...%s" % tuple(self.rank_bounds) except AttributeError: self.rank_bounds = [0, Infinity] self.rk_bnds = "not available" # Generators try: gens = [parse_point(K,P) for P in self.gens] self.gens = ", ".join([web_point(P) for P in gens]) if self.rk == "?": self.reg = "not available" else: if gens: try: self.reg = self.reg except AttributeError: self.reg = "not available" pass # self.reg already set else: self.reg = 1 # otherwise we only get 1.00000... except AttributeError: self.gens = "not available" self.reg = "not available" try: if self.rank == 0: self.reg = 1 except AttributeError: pass # Local data for P,ld in zip(badprimes,local_data): ld['p'] = web_latex(P) ld['norm'] = P.norm() ld['kod'] = web_latex(ld['kod']).replace('$', '') # URLs of self and related objects: self.urls = {} # It's useful to be able to use this class out of context, when calling url_for will fail: try: self.urls['curve'] = url_for(".show_ecnf", nf=self.field_label, conductor_label=quote(self.conductor_label), class_label=self.iso_label, number=self.number) except RuntimeError: return self.urls['class'] = url_for(".show_ecnf_isoclass", nf=self.field_label, conductor_label=quote(self.conductor_label), class_label=self.iso_label) self.urls['conductor'] = url_for(".show_ecnf_conductor", nf=self.field_label, conductor_label=quote(self.conductor_label)) self.urls['field'] = url_for(".show_ecnf1", nf=self.field_label) # Isogeny information 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: self.isogeny_degrees = " and ".join(isodegs) else: self.isogeny_degrees = " and ".join([", ".join(isodegs[:-1]),isodegs[-1]]) 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) if sig[0] <= 2: self.urls['Lfunction'] = url_for("l_functions.l_function_ecnf_page", field_label=self.field_label, conductor_label=self.conductor_label, isogeny_class_label=self.iso_label) elif self.abs_disc ** 2 * self.conductor_norm < 70000: # 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) self.urls['Lfunction'] = url_for("l_functions.l_function_ecnf_page", field_label=self.field_label, conductor_label=self.conductor_label, isogeny_class_label=self.iso_label) self.friends = [] self.friends += [('Isogeny class ' + self.short_class_label, self.urls['class'])] self.friends += [('Twists', url_for('ecnf.index', field=self.field_label, jinv=rename_j(j)))] 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_forms().find_one({'label':self.bmf_label}) != None: 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.field_pretty()), ('Label', self.label)] # Plot if K.signature()[0]: self.plot = encode_plot(EC_nf_plot(K,self.ainvs, self.field.generator_name())) self.plot_link = '<a href="{0}"><img src="{0}" width="200" height="150"/></a>'.format(self.plot) self.properties += [(None, self.plot_link)] self.properties += [ ('Conductor', self.cond), ('Conductor norm', self.cond_norm), # See issue #796 for why this is hidden (can be very large) # ('j-invariant', self.j), ('CM', self.cm_bool)] if self.base_change: self.properties += [('base-change', 'yes: %s' % ','.join([str(lab) for lab in self.base_change]))] else: self.base_change = [] # in case it was False instead of [] self.properties += [('base-change', 'no')] self.properties += [('Q-curve', self.qc)] r = self.rk if r == "?": r = self.rk_bnds self.properties += [ ('Torsion order', self.ntors), ('Rank', r), ] for E0 in self.base_change: self.friends += [('Base-change of %s /\(\Q\)' % E0, url_for("ec.by_ec_label", label=E0))] self._code = None # will be set if needed by get_code() self.downloads = [('Download all stored data', url_for(".download_ECNF_all", nf=self.field_label, conductor_label=quote(self.conductor_label), class_label=self.iso_label, number=self.number))] for lang in [["Magma","magma"], ["SageMath","sage"], ["GP", "gp"]]: self.downloads.append(('Download {} code'.format(lang[0]), url_for(".ecnf_code_download", nf=self.field_label, conductor_label=quote(self.conductor_label), class_label=self.iso_label, number=self.number, download_type=lang[1])))
def bianchi_modular_form_search(**args): """Function to handle requests from the top page, either jump to one newform or do a search. """ info = to_dict(args) # what has been entered in the search boxes if 'label' in info: # The Label button has been pressed. label = info['label'] dat = label.split("-") if len(dat)==2: # assume field & level, display space return render_bmf_space_webpage(dat[0], dat[1]) else: # assume single newform label; will display an error if invalid return bianchi_modular_form_by_label(label) query = {} for field in ['field_label', 'weight', 'level_norm', 'dimension']: if info.get(field): if field == 'weight': query['weight'] = info[field] elif field == 'field_label': parse_nf_string(info,query,field,'base number field',field) elif field == 'label': query[field] = info[field] elif field == 'dimension': query['dimension'] = int(info[field]) elif field == 'level_norm': query[field] = parse_range(info[field]) else: query[field] = info[field] if not 'sfe' in info: info['sfe'] = "any" elif info['sfe'] != "any": query['sfe'] = int(info['sfe']) if 'include_cm' in info: if info['include_cm'] == 'exclude': query['CM'] = 0 elif info['include_cm'] == 'only': query['CM'] = {'$nin' : [0,'?']} if 'include_base_change' in info and info['include_base_change'] == 'off': query['bc'] = 0 else: info['include_base_change'] = "on" start = 0 if 'start' in request.args: start = int(request.args['start']) count = 50 if 'count' in request.args: count = int(request.args['count']) info['query'] = dict(query) res = db_forms().find(query).sort([('level_norm', ASCENDING), ('label', ASCENDING)]).skip(start).limit(count) nres = res.count() if nres > 0: info['field_pretty_name'] = field_pretty(res[0]['field_label']) else: info['field_pretty_name'] = '' info['number'] = nres if nres == 1: info['report'] = 'unique match' elif nres == 2: info['report'] = 'displaying both matches' else: if nres > count or start != 0: info['report'] = 'displaying items %s-%s of %s matches' % (start + 1, min(nres, start + count), nres) else: info['report'] = 'displaying all %s matches' % nres res_clean = [] for v in res: v_clean = {} v_clean['field_label'] = v['field_label'] v_clean['short_label'] = v['short_label'] v_clean['level_label'] = v['level_label'] v_clean['level_norm'] = v['level_norm'] v_clean['level_number'] = v['level_label'].split(".")[1] v_clean['label_suffix'] = v['label_suffix'] v_clean['label'] = v['label'] v_clean['level_ideal'] = teXify_pol(v['level_ideal']) v_clean['dimension'] = v['dimension'] v_clean['sfe'] = "+1" if v['sfe']==1 else "-1" v_clean['url'] = url_for('.render_bmf_webpage',field_label=v['field_label'], level_label=v['level_label'], label_suffix=v['label_suffix']) v_clean['bc'] = bc_info(v['bc']) v_clean['cm'] = cm_info(v['CM']) res_clean.append(v_clean) res_clean.sort(key=lambda x: [int(x['level_norm']), int(x['level_number']), x['label_suffix']]) info['forms'] = res_clean info['count'] = count info['start'] = start info['more'] = int(start + count < nres) t = 'Bianchi modular form search results' bread = [('Bianchi Modular Forms', url_for(".index")), ( 'Search Results', ' ')] properties = [] return render_template("bmf-search_results.html", info=info, title=t, properties=properties, bread=bread, learnmore=learnmore_list())
def random_bmf(): # Random Hilbert modular form return bianchi_modular_form_by_label( random_object_from_collection( db_forms() ) )
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_dims().find({'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_dims().find({'field_label': field_label, 'level_label': level_label}) nres = data.count() if nres==0: info['err'] = "no dimension information exists in the database for level %s and field %s" % (level_label, pretty_field_label) else: data = data.next() 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, getDBConnection(), 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_forms().find({'field_label':field_label, 'level_label':level_label}).sort('label_suffix', ASCENDING) 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['sfe']==1 else "-1", 'bc': bc_info(f['bc']), 'cm': cm_info(f['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)