Exemple #1
0
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,
    )
Exemple #2
0
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
Exemple #4
0
 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"
Exemple #5
0
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
Exemple #6
0
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)
Exemple #8
0
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'))
Exemple #11
0
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)
Exemple #12
0
 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))
Exemple #13
0
                 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"
Exemple #14
0
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
Exemple #15
0
    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'])]
Exemple #16
0
    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),
Exemple #18
0
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))
Exemple #20
0
    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','')]
Exemple #21
0
    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)'
        }
Exemple #22
0
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,&middot;)$</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)
Exemple #23
0
    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)
Exemple #25
0
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,&middot;)$</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)