Example #1
0
def render_st_group(info, portrait=None):
    """ render html page for Sato-Tate group described by info """
    prop2 = [('Label', '%s' % info['label'])]
    if portrait:
        prop2 += [
            (None,
             '&nbsp;&nbsp;<img src="%s" width="220" height="124"/>' % portrait)
        ]
    prop2 += [
        ('Name', r'\(%s\)' % info['pretty']),
        ('Weight', prop_int_pretty(info['weight'])),
        ('Degree', prop_int_pretty(info['degree'])),
        ('Real dimension', prop_int_pretty(info['real_dimension'])),
        ('Components', prop_int_pretty(info['components'])),
        ('Contained in', r'\(%s\)' % info['ambient']),
        ('Identity Component', r'\(%s\)' % info['identity_component']),
        ('Component group', r'\(%s\)' % info['component_group']),
    ]
    bread = get_bread([
        ('Weight %d' % info['weight'],
         url_for('.index') + '?weight=' + str(info['weight'])),
        ('Degree %d' % info['degree'], url_for('.index') + '?weight=' +
         str(info['weight']) + '&degree=' + str(info['degree'])),
        (info['name'], '')
    ])
    title = r'Sato-Tate group \(' + info['pretty'] + r'\) of Weight %d' % info[
        'weight'] + ' and Degree %d' % info['degree']
    return render_template('st_display.html',
                           properties=prop2,
                           credit=credit_string,
                           info=info,
                           bread=bread,
                           learnmore=learnmore_list(),
                           title=title,
                           KNOWL_ID='st_group.%s' % (info['label']))
Example #2
0
 def properties(self):
     f = [("Label", [self.label])]
     f.extend([("Modulus", [prop_int_pretty(self.modulus)]),
               ("Conductor", [prop_int_pretty(self.conductor)]),
               ("Order", [prop_int_pretty(self.order)]),
               ("Real", [self.isreal]), ("Primitive", [self.isprimitive])])
     if self.isminimal:
         f.append(("Minimal", [self.isminimal]))
     if self.parity:
         f.append(("Parity", [self.parity]))
     return f
Example #3
0
 def properties(self):
     props = [
         (None,
          '<img src="{0}" width="200" height="150" style="margin:10px;"/>'.
          format(self.portrait))
     ] if self.portrait is not None else []
     props += [
         ('Level', prop_int_pretty(self.level)),
         ('Weight', prop_int_pretty(self.weight)),
         ('Character', self.character_label),
         ('Symmetry', self.symmetry_pretty),
     ]
     if self.conrey_index == 1:
         props.append(('Fricke sign', self.fricke_pretty))
     return props
Example #4
0
def render_hmf_webpage(**args):
    if 'data' in args:
        data = args['data']
        label = data['label']
    else:
        label = str(args['label'])
        data = get_hmf(label)
    if data is None:
        flash_error(
            "%s is not a valid Hilbert modular form label. It must be of the form (number field label) - (level label) - (orbit label) separated by dashes, such as 2.2.5.1-31.1-a",
            args['label'])
        return search_input_error()
    info = {}
    try:
        info['count'] = args['count']
    except KeyError:
        info['count'] = 50

    hmf_field = get_hmf_field(data['field_label'])
    gen_name = findvar(hmf_field['ideals'])
    nf = WebNumberField(data['field_label'], gen_name=gen_name)
    info['hmf_field'] = hmf_field
    info['field'] = nf
    info['base_galois_group'] = nf.galois_string()
    info['field_degree'] = nf.degree()
    info['field_disc'] = str(nf.disc())
    info['field_poly'] = teXify_pol(str(nf.poly()))

    info.update(data)

    info['downloads'] = [('Modular form to Magma',
                          url_for(".render_hmf_webpage_download",
                                  field_label=info['field_label'],
                                  label=info['label'],
                                  download_type='magma')),
                         ('Eigenvalues to Sage',
                          url_for(".render_hmf_webpage_download",
                                  field_label=info['field_label'],
                                  label=info['label'],
                                  download_type='sage'))]

    # figure out friends
    # first try to see if there is an instance of this HMF on Lfun db
    url = 'ModularForm/GL2/TotallyReal/{}/holomorphic/{}'.format(
        info['field_label'], info['label'])
    Lfun = get_lfunction_by_url(url)
    if Lfun:
        instances = get_instances_by_Lhash_and_trace_hash(
            Lfun['Lhash'], Lfun['degree'], Lfun['trace_hash'])

        # This will also add the EC/G2C, as this how the Lfun was computed
        info['friends'] = names_and_urls(instances, exclude={url})

        info['friends'] += [('L-function',
                             url_for("l_functions.l_function_hmf_page",
                                     field=info['field_label'],
                                     label=info['label'],
                                     character='0',
                                     number='0'))]

    else:
        # if there is no instance
        # old code
        if hmf_field['narrow_class_no'] == 1 and nf.disc(
        )**2 * data['level_norm'] < 40000:
            info['friends'] = [('L-function',
                                url_for("l_functions.l_function_hmf_page",
                                        field=info['field_label'],
                                        label=info['label'],
                                        character='0',
                                        number='0'))]
        else:
            info['friends'] = [('L-function not available', "")]

        if data['dimension'] == 1:  # Try to attach associated elliptic curve
            lab = split_class_label(info['label'])
            ec_from_hmf = db.ec_nfcurves.lookup(label + '1')
            if ec_from_hmf is None:
                info['friends'] += [('Elliptic curve not available', "")]
            else:
                info['friends'] += [('Isogeny class ' + info['label'],
                                     url_for("ecnf.show_ecnf_isoclass",
                                             nf=lab[0],
                                             conductor_label=lab[1],
                                             class_label=lab[2]))]

    bread = get_bread(data["label"])
    t = "Hilbert cusp form %s" % info['label']

    forms_dims = db.hmf_forms.search(
        {
            'field_label': data['field_label'],
            'level_ideal': data['level_ideal']
        },
        projection='dimension')

    info['newspace_dimension'] = sum(forms_dims)

    # Get hecke_polynomial, hecke_eigenvalues and AL_eigenvalues
    try:
        numeigs = request.args['numeigs']
        numeigs = int(numeigs)
    except:
        numeigs = 20
    info['numeigs'] = numeigs

    hecke_pol = data['hecke_polynomial']
    eigs = [str(eig) for eig in data['hecke_eigenvalues']]
    eigs = eigs[:min(len(eigs), numeigs)]
    AL_eigs = data['AL_eigenvalues']

    primes = hmf_field['primes']
    n = min(len(eigs), len(primes))
    info['eigs'] = [{
        'eigenvalue': add_space_if_positive(teXify_pol(eigs[i])),
        'prime_ideal': teXify_pol(primes[i]),
        'prime_norm': primes[i][1:primes[i].index(',')]
    } for i in range(n)]

    try:
        display_eigs = request.args['display_eigs']
        if display_eigs in ['True', 'true', '1', 'yes']:
            display_eigs = True
        else:
            display_eigs = False
    except KeyError:
        display_eigs = False

    if 'numeigs' in request.args:
        display_eigs = True

    info['hecke_polynomial'] = r"\(" + teXify_pol(hecke_pol) + r"\)"

    if not AL_eigs:  # empty list
        if data['level_norm'] == 1:  # OK, no bad primes
            info['AL_eigs'] = 'none'
        else:  # not OK, AL eigs are missing
            info['AL_eigs'] = 'missing'
    else:
        info['AL_eigs'] = [{
            'eigenvalue': teXify_pol(al[1]),
            'prime_ideal': teXify_pol(al[0]),
            'prime_norm': al[0][1:al[0].index(',')]
        } for al in data['AL_eigenvalues']]

    max_eig_len = max([len(eig['eigenvalue']) for eig in info['eigs']])
    display_eigs = display_eigs or (max_eig_len <= 300)
    info['display_eigs'] = display_eigs
    if not display_eigs:
        for eig in info['eigs']:
            if len(eig['eigenvalue']) > 300:
                eig['eigenvalue'] = '...'

    info['level_ideal'] = teXify_pol(info['level_ideal'])

    if 'is_CM' in data:
        is_CM = data['is_CM']
    else:
        is_CM = '?'
    info['is_CM'] = is_CM

    if 'is_base_change' in data:
        is_base_change = data['is_base_change']
    else:
        is_base_change = '?'
    info['is_base_change'] = is_base_change

    if 'q_expansions' in data:
        info['q_expansions'] = data['q_expansions']

    properties = [('Label', '%s' % data['label']),
                  ('Base field', '%s' % info['field'].field_pretty()),
                  ('Weight', '$%s$' % data['weight']),
                  ('Level norm', prop_int_pretty(data['level_norm'])),
                  ('Level', '$' + teXify_pol(data['level_ideal']) + '$'),
                  ('Dimension', prop_int_pretty(data['dimension'])),
                  ('CM', is_CM), ('Base change', is_base_change)]

    return render_template(
        "hilbert_modular_form.html",
        downloads=info["downloads"],
        info=info,
        properties=properties,
        credit=hmf_credit,
        title=t,
        bread=bread,
        friends=info['friends'],
        learnmore=learnmore_list(),
        KNOWL_ID="mf.hilbert.%s" % label,
    )
Example #5
0
def render_sample_page(family, sam, args, bread):
    info = {
        'args': to_dict(args),
        'sam': sam,
        'latex': latex,
        'type': sam.type(),
        'name': sam.name(),
        'full_name': sam.full_name(),
        'weight': sam.weight(),
        'fdeg': sam.degree_of_field(),
        'is_eigenform': sam.is_eigenform(),
        'field_poly': sam.field_poly()
    }
    if sam.is_integral() is not None:
        info['is_integral'] = sam.is_integral()
    if 'Sp4Z' in sam.collection():
        info['space_url'] = url_for('.Sp4Z_j_space', k=info['weight'], j=0)
    if 'Sp4Z_2' in sam.collection():
        info['space_url'] = url_for('.Sp4Z_j_space', k=info['weight'], j=2)
    info['space'] = '$' + family.latex_name.replace(
        'k', '{' + str(sam.weight()) + '}') + '$'
    if 'space_url' in info:
        bread.append((info['space'], info['space_url']))
    info['space_href'] = '<a href="%s">%s</d>' % (
        info['space_url'],
        info['space']) if 'space_url' in info else info['space']
    if info['field_poly'].disc() < 10**10:
        label = poly_to_field_label(info['field_poly'])
        if label:
            info['field_label'] = label
            info['field_url'] = url_for('number_fields.by_label', label=label)
            info['field_href'] = '<a href="%s">%s</a>' % (info['field_url'],
                                                          field_pretty(label))

    bread.append((info['name'], ''))
    title = 'Siegel modular forms sample ' + info['full_name']
    properties = [('Space', info['space_href']), ('Name', info['name']),
                  ('Type', '<br>'.join(info['type'].split(','))),
                  ('Weight', prop_int_pretty(info['weight'])),
                  ('Hecke eigenform', "yes" if info['is_eigenform'] else "no"),
                  ('Field degree', prop_int_pretty(info['fdeg']))]
    try:
        evs_to_show = parse_ints_to_list_flash(args.get('ev_index'),
                                               'list of $l$')
        fcs_to_show = parse_ints_to_list_flash(args.get('fc_det'),
                                               'list of $\\det(F)$')
    except ValueError:
        evs_to_show = []
        fcs_to_show = []
    info['evs_to_show'] = sorted([
        n for n in
        (evs_to_show if len(evs_to_show) else sam.available_eigenvalues()[:10])
    ])
    info['fcs_to_show'] = sorted([
        n for n in (fcs_to_show if len(fcs_to_show) else sam.
                    available_Fourier_coefficients()[1:6])
    ])
    info['evs_avail'] = [n for n in sam.available_eigenvalues()]
    info['fcs_avail'] = [n for n in sam.available_Fourier_coefficients()]

    # Do not attempt to constuct a modulus ideal unless the field has a reasonably small discriminant
    # otherwise sage may not even be able to factor the discriminant
    info['field'] = sam.field()
    if info['field_poly'].disc() < 10**80:
        null_ideal = sam.field().ring_of_integers().ideal(0)
        info['modulus'] = null_ideal
        modulus = args.get('modulus', '').strip()
        m = 0
        if modulus:
            try:
                O = sam.field().ring_of_integers()
                m = O.ideal([O(str(b)) for b in modulus.split(',')])
            except Exception:
                info['error'] = True
                flash_error(
                    "Unable to construct modulus ideal from specified generators %s.",
                    modulus)
            if m == 1:
                info['error'] = True
                flash_error(
                    "The ideal %s is the unit ideal, please specify a different modulus.",
                    '(' + modulus + ')')
                m = 0
        info['modulus'] = m

        # Hack to reduce polynomials and to handle non integral stuff
        def redc(c):
            return m.reduce(c * c.denominator()) / m.reduce(c.denominator())

        def redp(f):
            c = f.dict()
            return f.parent()(dict((e, redc(c[e])) for e in c))

        def safe_reduce(f):
            if not m:
                return latex(f)
            try:
                if f in sam.field():
                    return latex(redc(f))
                else:
                    return latex(redp(f))
            except ZeroDivisionError:
                return '\\textrm{Unable to reduce} \\bmod\\mathfrak{m}'

        info['reduce'] = safe_reduce
    else:
        info['reduce'] = latex

    # check that explicit formula is not ridiculously big
    if sam.explicit_formula():
        info['explicit_formula_bytes'] = len(sam.explicit_formula())
        if len(sam.explicit_formula()) < 100000:
            info['explicit_formula'] = sam.explicit_formula()

    return render_template("ModularForm_GSp4_Q_sample.html",
                           title=title,
                           bread=bread,
                           properties=properties,
                           info=info)
Example #6
0
def render_lattice_webpage(**args):
    f = None
    if 'label' in args:
        lab = clean_input(args.get('label'))
        if lab != args.get('label'):
            return redirect(url_for('.render_lattice_webpage', label=lab), 301)
        f = db.lat_lattices.lucky({'$or':[{'label': lab }, {'name': {'$contains': [lab]}}]})
    if f is None:
        t = "Integral lattice search error"
        bread = get_bread()
        flash_error("%s is not a valid label or name for an integral lattice in the database.", lab)
        return render_template("lattice-error.html", title=t, properties=[], bread=bread, learnmore=learnmore_list())
    info = {}
    info.update(f)

    info['friends'] = []

    bread = get_bread(f['label'])
    info['dim']= int(f['dim'])
    info['det']= int(f['det'])
    info['level']=int(f['level'])
    info['gram']=vect_to_matrix(f['gram'])
    info['density']=str(f['density'])
    info['hermite']=str(f['hermite'])
    info['minimum']=int(f['minimum'])
    info['kissing']=int(f['kissing'])
    info['aut']=int(f['aut'])

    if f['shortest']=="":
        info['shortest']==f['shortest']
    else:
        if f['dim']==1:
            info['shortest']=str(f['shortest']).strip('[').strip(']')
        else:
            if info['dim']*info['kissing']<100:
                info['shortest']=[str([tuple(v)]).strip('[').strip(']').replace('),', '), ') for v in f['shortest']]
            else:
                max_vect_num=min(int(round(100/(info['dim']))), int(round(info['kissing']/2))-1)
                info['shortest']=[str([tuple(f['shortest'][i])]).strip('[').strip(']').replace('),', '), ') for i in range(max_vect_num+1)]
                info['all_shortest']="no"
        info['download_shortest'] = [
            (i, url_for(".render_lattice_webpage_download", label=info['label'], lang=i, obj='shortest_vectors')) for i in ['gp', 'magma','sage']]

    if f['name']==['Leech']:
        info['shortest']=[str([1,-2,-2,-2,2,-1,-1,3,3,0,0,2,2,-1,-1,-2,2,-2,-1,-1,0,0,-1,2]), 
str([1,-2,-2,-2,2,-1,0,2,3,0,0,2,2,-1,-1,-2,2,-1,-1,-2,1,-1,-1,3]), str([1,-2,-2,-1,1,-1,-1,2,2,0,0,2,2,0,0,-2,2,-1,-1,-1,0,-1,-1,2])]
        info['all_shortest']="no"
        info['download_shortest'] = [
            (i, url_for(".render_lattice_webpage_download", label=info['label'], lang=i, obj='shortest_vectors')) for i in ['gp', 'magma','sage']]

    ncoeff=20
    if f['theta_series'] != "":
        coeff=[f['theta_series'][i] for i in range(ncoeff+1)]
        info['theta_series']=my_latex(print_q_expansion(coeff))
        info['theta_display'] = url_for(".theta_display", label=f['label'], number="")

    info['class_number']=int(f['class_number'])

    if f['dim']==1:
        info['genus_reps']=str(f['genus_reps']).strip('[').strip(']')
    else:
        if info['dim']*info['class_number']<50:
            info['genus_reps']=[vect_to_matrix(n) for n in f['genus_reps']]
        else:
            max_matrix_num=min(int(round(25/(info['dim']))), info['class_number'])
            info['all_genus_rep']="no"
            info['genus_reps']=[vect_to_matrix(f['genus_reps'][i]) for i in range(max_matrix_num+1)]
    info['download_genus_reps'] = [
        (i, url_for(".render_lattice_webpage_download", label=info['label'], lang=i, obj='genus_reps')) for i in ['gp', 'magma','sage']]

    if f['name'] != "":
        if f['name']==str(f['name']):
            info['name']= str(f['name'])
        else:
            info['name']=str(", ".join(str(i) for i in f['name']))
    else:
        info['name'] == ""
    info['comments']=str(f['comments'])
    if 'Leech' in info['comments']: # no need to duplicate as it is in the name
        info['comments'] = ''
    if info['name'] == "":
        t = "Integral lattice %s" % info['label']
    else:
        t = "Integral lattice "+info['label']+" ("+info['name']+")"
#This part code was for the dynamic knowl with comments, since the test is displayed this is redundant
#    if info['name'] != "" or info['comments'] !="":
#        info['knowl_args']= "name=%s&report=%s" %(info['name'], info['comments'].replace(' ', '-space-'))
    info['properties'] = [
        ('Dimension', prop_int_pretty(info['dim'])),
        ('Determinant', prop_int_pretty(info['det'])),
        ('Level', prop_int_pretty(info['level']))]
    if info['class_number'] == 0:
        info['properties']=[('Class number', 'not available')]+info['properties']
    else:
        info['properties']=[('Class number', prop_int_pretty(info['class_number']))]+info['properties']
    info['properties']=[('Label', '%s' % info['label'])]+info['properties']

    if info['name'] != "" :
        info['properties']=[('Name','%s' % info['name'] )]+info['properties']
#    friends = [('L-series (not available)', ' ' ),('Half integral weight modular forms (not available)', ' ')]
    return render_template("lattice-single.html", info=info, title=t, bread=bread, properties=info['properties'], learnmore=learnmore_list(), KNOWL_ID="lattice.%s"%info['label'])
Example #7
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', '')]
Example #8
0
    def make_galmap_object(self, galmap):
        from lmfdb.belyi.main import url_for_belyi_passport_label

        # all information about the map goes in the data dictionary
        # most of the data from the database gets polished/formatted before we put it in the data dictionary
        data = self.data = {}
        # the stuff that does not need to be polished
        for elt in ("label", "plabel", "triples_cyc", "orbit_size", "g", "abc",
                    "deg"):
            data[elt] = galmap[elt]
        nt = galmap["group"].split("T")
        data["group"] = group_display_knowl(int(nt[0]), int(nt[1]))

        data["geomtype"] = geomtypelet_to_geomtypename_dict[galmap["geomtype"]]
        data["lambdas"] = [str(c)[1:-1] for c in galmap["lambdas"]]

        data["isQQ"] = False
        data["in_LMFDB"] = False
        F = belyi_base_field(galmap)
        if F._data is None:
            fld_coeffs = galmap["base_field"]
            pol = PolynomialRing(QQ, "x")(fld_coeffs)
            data["base_field"] = latex(pol)
        else:
            data["in_LMFDB"] = True
            if F.poly().degree() == 1:
                data["isQQ"] = True
            F.latex_poly = web_latex(F.poly())
            data["base_field"] = F
        crv_str = galmap["curve"]
        if crv_str == "PP1":
            data["curve"] = r"\mathbb{P}^1"
        else:
            data["curve"] = make_curve_latex(crv_str)
        #if galmap['curve_label']:
        #    data['curve_label'] = galmap['curve_label']

        # change pairs of floats to complex numbers
        embeds = galmap["embeddings"]
        embed_strs = []
        for el in embeds:
            if el[1] < 0:
                el_str = str(el[0]) + str(el[1]) + r"\sqrt{-1}"
            else:
                el_str = str(el[0]) + "+" + str(el[1]) + r"\sqrt{-1}"
            embed_strs.append(el_str)

        data["map"] = make_map_latex(galmap["map"])
        data["embeddings_and_triples"] = []
        if data["isQQ"]:
            for i in range(0, len(data["triples_cyc"])):
                triple_cyc = data["triples_cyc"][i]
                data["embeddings_and_triples"].append([
                    r"\text{not applicable (over $\mathbb{Q}$)}",
                    triple_cyc[0],
                    triple_cyc[1],
                    triple_cyc[2],
                ])
        else:
            for i in range(0, len(data["triples_cyc"])):
                triple_cyc = data["triples_cyc"][i]
                data["embeddings_and_triples"].append([
                    embed_strs[i], triple_cyc[0], triple_cyc[1], triple_cyc[2]
                ])

        data["lambdas"] = [str(c)[1:-1] for c in galmap["lambdas"]]

        # Properties
        self.plot = db.belyi_galmap_portraits.lucky({"label": galmap['label']},
                                                    projection="portrait")
        plot_link = '<a href="{0}"><img src="{0}" width="200" height="200" style="background-color: white;"/></a>'.format(
            self.plot)
        properties = [("Label", galmap["label"])]
        if self.plot:
            properties += [(None, plot_link)]
        properties += [
            ("Group", str(galmap["group"])),
            ("Orders", "$%s$" % (galmap["abc"])),
            ("Genus", prop_int_pretty(galmap["g"])),
            ("Size", prop_int_pretty(galmap["orbit_size"])),
        ]
        self.properties = properties

        # Friends
        self.friends = [("Passport",
                         url_for_belyi_passport_label(galmap["plabel"]))]
        self.friends.extend(names_and_urls(galmap['friends']))

        # Downloads
        if galmap["g"] <= 2:
            self.downloads = [
                (
                    "Code to Magma",
                    url_for(".belyi_galmap_magma_download",
                            label=data["label"]),
                ),
                (
                    "Code to SageMath",
                    url_for(".belyi_galmap_sage_download",
                            label=data["label"]),
                ),
                (
                    "All data to text",
                    url_for(".belyi_galmap_text_download",
                            label=data["label"]),
                ),
            ]
        else:
            self.downloads = []

        # Breadcrumbs
        label_spl = data["label"].split("-")
        groupstr = label_spl[0]
        letnum = label_spl[2]
        gstr = str(data['g'])
        sigmas = label_spl[1]
        sigma0, sigma1, sigmaoo = sigmas.split("_")
        abcstr = str(data['abc']).replace(' ', '')
        # does lambdasstr need to be updated?
        lambdasstr = "%s-%s-%s" % (sigma0, sigma1, sigmaoo)
        lambdasgstr = lambdasstr + "-" + gstr
        self.bread = [
            ("Belyi Maps", url_for(".index")),
            (groupstr, url_for(".by_url_belyi_search_group", group=groupstr)),
            (
                abcstr,
                url_for(".by_url_belyi_search_group_triple",
                        group=groupstr,
                        abc=abcstr),
            ),
            (
                lambdasgstr,
                url_for(
                    ".by_url_belyi_passport_label",
                    group=groupstr,
                    abc=abcstr,
                    sigma0=sigma0,
                    sigma1=sigma1,
                    sigmaoo=sigmaoo,
                    g=gstr,
                ),
            ),
            (
                letnum,
                url_for(
                    ".by_url_belyi_galmap_label",
                    group=groupstr,
                    abc=abcstr,
                    sigma0=sigma0,
                    sigma1=sigma1,
                    sigmaoo=sigmaoo,
                    g=gstr,
                    letnum=letnum,
                ),
            ),
        ]

        # Title
        self.title = "Belyi map orbit " + data["label"]

        # Code snippets (only for curves)
        self.code = {}
        return
Example #9
0
File: main.py Project: cscmnu/lmfdb
def render_group_webpage(args):
    data = {}
    if 'label' in args:
        label = clean_input(args['label'])
        label = label.replace('t', 'T')
        data = db.gps_transitive.lookup(label)
        if data is None:
            if re.match(r'^\d+T\d+$', label):
                flash_error("Group %s was not found in the database.", label)
            else:
                flash_error("%s is not a valid label for a Galois group.",
                            label)
            return redirect(url_for(".index"))
        title = 'Galois group: ' + label
        wgg = WebGaloisGroup.from_nt(data['n'], data['t'])
        data['wgg'] = wgg
        n = data['n']
        t = data['t']
        data['yesno'] = yesno
        order = data['order']
        data['orderfac'] = latex(ZZ(order).factor())
        orderfac = latex(ZZ(order).factor())
        data['ordermsg'] = "$%s=%s$" % (order, latex(orderfac))
        if order == 1:
            data['ordermsg'] = "$1$"
        if ZZ(order).is_prime():
            data['ordermsg'] = "$%s$ (is prime)" % order
        pgroup = len(ZZ(order).prime_factors()) < 2
        if wgg.num_conjclasses() < 50:
            data['cclasses'] = wgg.conjclasses()
        if ZZ(order) < ZZ(10000000) and wgg.num_conjclasses() < 21:
            data['chartable'] = chartable(n, t)
        data['gens'] = wgg.generator_string()
        if n == 1 and t == 1:
            data['gens'] = 'None needed'
        data['num_cc'] = comma(wgg.num_conjclasses())
        data['parity'] = "$%s$" % data['parity']
        data['subinfo'] = subfield_display(n, data['subfields'])
        data['resolve'] = resolve_display(data['quotients'])
        if data['gapid'] == 0:
            data['gapid'] = "not available"
        else:
            data['gapid'] = small_group_display_knowl(
                int(data['order']), int(data['gapid']),
                str([int(data['order']),
                     int(data['gapid'])]))
        data['otherreps'] = wgg.otherrep_list()
        ae = data['arith_equiv']
        if ae > 0:
            if ae > 1:
                data[
                    'arith_equiv'] = r'A number field with this Galois group has %d <a knowl="nf.arithmetically_equivalent", title="arithmetically equivalent">arithmetically equivalent</a> fields.' % ae
            else:
                data[
                    'arith_equiv'] = r'A number field with this Galois group has exactly one <a knowl="nf.arithmetically_equivalent", title="arithmetically equivalent">arithmetically equivalent</a> field.'
        elif ae > -1:
            data[
                'arith_equiv'] = r'A number field with this Galois group has no <a knowl="nf.arithmetically_equivalent", title="arithmetically equivalent">arithmetically equivalent</a> fields.'
        else:
            data[
                'arith_equiv'] = r'Data on whether or not a number field with this Galois group has <a knowl="nf.arithmetically_equivalent", title="arithmetically equivalent">arithmetically equivalent</a> fields has not been computed.'
        intreps = list(db.gps_gmodules.search({'n': n, 't': t}))
        if len(intreps) > 0:
            data['int_rep_classes'] = [str(z[0]) for z in intreps[0]['gens']]
            for onerep in intreps:
                onerep['gens'] = [
                    list_to_latex_matrix(z[1]) for z in onerep['gens']
                ]
            data['int_reps'] = intreps
            data['int_reps_complete'] = int_reps_are_complete(intreps)
            dcq = data['moddecompuniq']
            if dcq[0] == 0:
                data['decompunique'] = 0
            else:
                data['decompunique'] = dcq[0]
                data['isoms'] = [[mult2mult(z[0]),
                                  mult2mult(z[1])] for z in dcq[1]]
                data['isoms'] = [[
                    modules2string(n, t, z[0]),
                    modules2string(n, t, z[1])
                ] for z in data['isoms']]
                #print dcq[1]
                #print data['isoms']

        friends = []
        if db.nf_fields.exists({'galois_label': "%dT%d" % (n, t)}):
            friends.append(
                ('Number fields with this Galois group',
                 url_for('number_fields.number_field_render_webpage') +
                 "?galois_group=%dT%d" % (n, t)))
        prop2 = [
            ('Label', label),
            ('Degree', prop_int_pretty(data['n'])),
            ('Order', prop_int_pretty(order)),
            ('Cyclic', yesno(data['cyc'])),
            ('Abelian', yesno(data['ab'])),
            ('Solvable', yesno(data['solv'])),
            ('Primitive', yesno(data['prim'])),
            ('$p$-group', yesno(pgroup)),
        ]
        pretty = group_display_short(n, t, emptyifnotpretty=True)
        if len(pretty) > 0:
            prop2.extend([('Group:', pretty)])
            data['pretty_name'] = pretty
        data['name'] = re.sub(r'_(\d+)', r'_{\1}', data['name'])
        data['name'] = re.sub(r'\^(\d+)', r'^{\1}', data['name'])
        data['nilpotency'] = '$%s$' % data['nilpotency']
        if data['nilpotency'] == '$-1$':
            data['nilpotency'] += ' (not nilpotent)'

        bread = get_bread([(label, ' ')])
        return render_template("gg-show-group.html",
                               credit=GG_credit,
                               title=title,
                               bread=bread,
                               info=data,
                               properties=prop2,
                               friends=friends,
                               KNOWL_ID="gg.%s" % label,
                               learnmore=learnmore_list())
Example #10
0
    def make_curve(self):
        # To start with the data fields of self are just those from
        # the database.  We need to reformat these.

        # Old version: required constructing the actual elliptic curve
        # E, and computing some further data about it.

        # New version (May 2016): extra data fields now in the
        # database so we do not have to construct the curve or do any
        # computation with it on the fly.  As a failsafe the old way
        # is still included.

        data = self.data = {}
        data['ainvs'] = [ZZ(ai) for ai in self.ainvs]
        data['conductor'] = N = ZZ(self.conductor)
        data['j_invariant'] = QQ(str(self.jinv))
        data['j_inv_factor'] = latex(0)
        if data['j_invariant']:  # don't factor 0
            data['j_inv_factor'] = latex(data['j_invariant'].factor())
        data['j_inv_latex'] = web_latex(data['j_invariant'])

        # extract data about MW rank, generators, heights and torsion:
        self.make_mw()

        # get more data from the database entry

        data['equation'] = self.equation
        local_data = self.local_data
        D = self.signD * prod([ld['p']**ld['ord_disc'] for ld in local_data])
        for ld in local_data:
            ld['kod'] = ld['kod'].replace("\\\\", "\\")
        data['disc'] = D
        Nfac = Factorization([(ZZ(ld['p']), ld['ord_cond'])
                              for ld in local_data])
        Dfac = Factorization([(ZZ(ld['p']), ld['ord_disc'])
                              for ld in local_data],
                             unit=ZZ(self.signD))

        data['minq_D'] = minqD = self.min_quad_twist['disc']
        data['minq_label'] = self.min_quad_twist[
            'lmfdb_label'] if self.label_type == 'LMFDB' else self.min_quad_twist[
                'label']
        data['minq_info'] = '(itself)' if minqD == 1 else '(by {})'.format(
            minqD)

        if self.degree is None:
            data['degree'] = 0  # invalid, but will be displayed nicely
        else:
            data['degree'] = self.degree

        try:
            data['an'] = self.anlist
            data['ap'] = self.aplist
        except AttributeError:
            r = db.ec_curves.lucky({'lmfdb_iso': self.lmfdb_iso, 'number': 1})
            data['an'] = r['anlist']
            data['ap'] = r['aplist']

        data['disc_factor'] = latex(Dfac)
        data['cond_factor'] = latex(Nfac)
        data['disc_latex'] = web_latex(D)
        data['cond_latex'] = web_latex(N)

        data['galois_images'] = [
            trim_galois_image_code(s) for s in self.mod_p_images
        ]
        data['non_maximal_primes'] = self.non_maximal_primes
        data['galois_data'] = [{
            'p': p,
            'image': im
        } for p, im in zip(data['non_maximal_primes'], data['galois_images'])]

        data['CMD'] = self.cm
        data['CM'] = "no"
        data['EndE'] = r"\(\Z\)"
        if self.cm:
            data['cm_ramp'] = [
                p for p in ZZ(self.cm).support()
                if not p in self.non_maximal_primes
            ]
            data['cm_nramp'] = len(data['cm_ramp'])
            if data['cm_nramp'] == 1:
                data['cm_ramp'] = data['cm_ramp'][0]
            else:
                data['cm_ramp'] = ", ".join([str(p) for p in data['cm_ramp']])
            data['cm_sqf'] = ZZ(self.cm).squarefree_part()

            data['CM'] = r"yes (\(D=%s\))" % data['CMD']
            if data['CMD'] % 4 == 0:
                d4 = ZZ(data['CMD']) // 4
                data['EndE'] = r"\(\Z[\sqrt{%s}]\)" % d4
            else:
                data['EndE'] = r"\(\Z[(1+\sqrt{%s})/2]\)" % data['CMD']
            data['ST'] = st_link_by_name(1, 2, 'N(U(1))')
        else:
            data['ST'] = st_link_by_name(1, 2, 'SU(2)')

        data['p_adic_primes'] = [
            p for i, p in enumerate(prime_range(5, 100))
            if (N * data['ap'][i]) % p != 0
        ]

        cond, iso, num = split_lmfdb_label(self.lmfdb_label)
        self.one_deg = ZZ(self.class_deg).is_prime()
        isodegs = [str(d) for d in self.isogeny_degrees if d > 1]
        if len(isodegs) < 3:
            data['isogeny_degrees'] = " and ".join(isodegs)
        else:
            data['isogeny_degrees'] = " and ".join(
                [", ".join(isodegs[:-1]), isodegs[-1]])

        if self.twoadic_gens:
            from sage.matrix.all import Matrix
            data['twoadic_gen_matrices'] = ','.join(
                [latex(Matrix(2, 2, M)) for M in self.twoadic_gens])
            data[
                'twoadic_rouse_url'] = ROUSE_URL_PREFIX + self.twoadic_label + ".html"

        # Leading term of L-function & other BSD data
        self.make_bsd()

        # Optimality (the optimal curve in the class is the curve
        # whose Cremona label ends in '1' except for '990h' which was
        # labelled wrongly long ago): this is proved for N up to
        # OPTIMALITY_BOUND (and when there is only one curve in an
        # isogeny class, obviously) and expected for all N.

        # Column 'optimality' is 1 for certainly optimal curves, 0 for
        # certainly non-optimal curves, and is n>1 if the curve is one
        # of n in the isogeny class which may be optimal given current
        # knowledge.

        # Column "manin_constant' is the correct Manin constant
        # assuming that the optimal curve in the class is known, or
        # otherwise if it is the curve with (Cremona) number 1.

        # The code here allows us to update the display correctly by
        # changing one line in this file (defining OPTIMALITY_BOUND)
        # without changing the data.

        data['optimality_bound'] = OPTIMALITY_BOUND
        data[
            'manin_constant'] = self.manin_constant  # (conditional on data['optimality_known'])

        if N < OPTIMALITY_BOUND:

            data['optimality_code'] = int(
                self.number == (3 if self.iso == '990h' else 1))
            data['optimality_known'] = True
            data['manin_known'] = True
            if self.label_type == 'Cremona':
                data[
                    'optimal_label'] = '990h3' if self.iso == '990h' else self.iso + '1'
            else:
                data[
                    'optimal_label'] = '990.i3' if self.lmfdb_iso == '990.i' else self.lmfdb_iso + '1'

        else:

            data['optimality_code'] = self.optimality
            data['optimality_known'] = (self.optimality < 2)

            if self.optimality == 1:
                data['manin_known'] = True
                data[
                    'optimal_label'] = self.label if self.label_type == 'Cremona' else self.lmfdb_label
            else:
                if self.number == 1:
                    data['manin_known'] = False
                    data[
                        'optimal_label'] = self.label if self.label_type == 'Cremona' else self.lmfdb_label
                else:
                    # find curve #1 in this class and its optimailty code:
                    opt_curve = db.ec_curves.lucky(
                        {
                            'iso': self.iso,
                            'number': 1
                        },
                        projection=['label', 'lmfdb_label', 'optimality'])
                    data['manin_known'] = (opt_curve['optimality'] == 1)
                    data['optimal_label'] = opt_curve[
                        'label' if self.label_type ==
                        'Cremona' else 'lmfdb_label']

        data['p_adic_data_exists'] = False
        if data['optimality_code'] == 1:
            data['p_adic_data_exists'] = db.ec_padic.exists(
                {'lmfdb_iso': self.lmfdb_iso})

        # Iwasawa data (where present)

        self.make_iwasawa()

        # Torsion growth data (where present)

        self.make_torsion_growth()

        data['newform'] = web_latex(
            PowerSeriesRing(QQ, 'q')(data['an'], 20, check=True))
        data['newform_label'] = self.newform_label = ".".join(
            [str(cond), str(2), 'a', iso])
        self.newform_link = url_for("cmf.by_url_newform_label",
                                    level=cond,
                                    weight=2,
                                    char_orbit_label='a',
                                    hecke_orbit=iso)
        self.newform_exists_in_db = db.mf_newforms.label_exists(
            self.newform_label)
        self._code = None

        if self.label_type == 'Cremona':
            self.class_url = url_for(".by_ec_label", label=self.iso)
            self.class_name = self.iso
        else:
            self.class_url = url_for(".by_double_iso_label",
                                     conductor=N,
                                     iso_label=iso)
            self.class_name = self.lmfdb_iso
        data['class_name'] = self.class_name
        data['number'] = self.number

        self.friends = [('Isogeny class ' + self.class_name, self.class_url),
                        ('Minimal quadratic twist %s %s' %
                         (data['minq_info'], data['minq_label']),
                         url_for(".by_ec_label", label=data['minq_label'])),
                        ('All twists ',
                         url_for(".rational_elliptic_curves", jinv=self.jinv))]

        lfun_url = url_for("l_functions.l_function_ec_page",
                           conductor_label=N,
                           isogeny_class_label=iso)
        origin_url = lfun_url.lstrip('/L/').rstrip('/')

        if db.lfunc_instances.exists({'url': origin_url}):
            self.friends += [('L-function', lfun_url)]
        else:
            self.friends += [('L-function not available', "")]

        if not self.cm:
            if N <= 300:
                self.friends += [('Symmetric square L-function',
                                  url_for("l_functions.l_function_ec_sym_page",
                                          power='2',
                                          conductor=N,
                                          isogeny=iso))]
            if N <= 50:
                self.friends += [('Symmetric cube L-function',
                                  url_for("l_functions.l_function_ec_sym_page",
                                          power='3',
                                          conductor=N,
                                          isogeny=iso))]
        if self.newform_exists_in_db:
            self.friends += [('Modular form ' + self.newform_label,
                              self.newform_link)]

        self.downloads = [('q-expansion to text',
                           url_for(".download_EC_qexp",
                                   label=self.lmfdb_label,
                                   limit=1000)),
                          ('All stored data to text',
                           url_for(".download_EC_all",
                                   label=self.lmfdb_label)),
                          ('Code to Magma',
                           url_for(".ec_code_download",
                                   conductor=cond,
                                   iso=iso,
                                   number=num,
                                   label=self.lmfdb_label,
                                   download_type='magma')),
                          ('Code to SageMath',
                           url_for(".ec_code_download",
                                   conductor=cond,
                                   iso=iso,
                                   number=num,
                                   label=self.lmfdb_label,
                                   download_type='sage')),
                          ('Code to GP',
                           url_for(".ec_code_download",
                                   conductor=cond,
                                   iso=iso,
                                   number=num,
                                   label=self.lmfdb_label,
                                   download_type='gp'))]

        try:
            self.plot = encode_plot(self.E.plot())
        except AttributeError:
            self.plot = encode_plot(EllipticCurve(data['ainvs']).plot())

        self.plot_link = '<a href="{0}"><img src="{0}" width="200" height="150"/></a>'.format(
            self.plot)
        self.properties = [
            ('Label',
             self.label if self.label_type == 'Cremona' else self.lmfdb_label),
            (None, self.plot_link),
            ('Conductor', prop_int_pretty(data['conductor'])),
            ('Discriminant', prop_int_pretty(data['disc'])),
            ('j-invariant', '%s' % data['j_inv_latex']),
            ('CM', '%s' % data['CM']),
            ('Rank', prop_int_pretty(self.mw['rank'])),
            ('Torsion structure',
             (r'\(%s\)' %
              self.mw['tor_struct']) if self.mw['tor_struct'] else 'trivial'),
        ]

        if self.label_type == 'Cremona':
            self.title = "Elliptic curve with Cremona label {} (LMFDB label {})".format(
                self.label, self.lmfdb_label)
        else:
            self.title = "Elliptic curve with LMFDB label {} (Cremona label {})".format(
                self.lmfdb_label, self.label)

        self.bread = [('Elliptic curves', url_for("ecnf.index")),
                      (r'$\Q$', url_for(".rational_elliptic_curves")),
                      ('%s' % N, url_for(".by_conductor", conductor=N)),
                      ('%s' % iso,
                       url_for(".by_double_iso_label",
                               conductor=N,
                               iso_label=iso)), ('%s' % num, ' ')]
Example #11
0
    def __init__(self, data):
        # Need to set mf_dim, eis_dim, cusp_dim, new_dim, old_dim
        self.__dict__.update(data)
        self.factored_level = web_latex_factored_integer(self.level,
                                                         equals=True)
        self.has_projective_image_types = all(typ + '_dim' in data
                                              for typ in ('dihedral', 'a4',
                                                          's4', 'a5'))
        # The following can be removed once we change the behavior of lucky to include Nones
        self.num_forms = data.get('num_forms')
        self.trace_bound = data.get('trace_bound')
        self.has_trace_form = (data.get('traces') is not None)
        self.char_conrey = self.conrey_indexes[0]
        self.char_conrey_str = r'\chi_{%s}(%s,\cdot)' % (self.level,
                                                         self.char_conrey)
        self.newforms = list(
            db.mf_newforms.search({'space_label': self.label}, projection=2))
        oldspaces = db.mf_subspaces.search(
            {
                'label': self.label,
                'sub_level': {
                    '$ne': self.level
                }
            }, [
                'sub_level', 'sub_char_orbit_index', 'sub_conrey_indexes',
                'sub_mult'
            ])
        self.oldspaces = [(old['sub_level'], old['sub_char_orbit_index'],
                           old['sub_conrey_indexes'][0], old['sub_mult'])
                          for old in oldspaces]
        self.dim_grid = DimGrid.from_db(data)
        self.plot = db.mf_newspace_portraits.lookup(self.label,
                                                    projection="portrait")

        # Properties
        self.properties = [('Label', self.label)]
        if self.plot is not None and self.dim > 0:
            self.properties += [
                (None,
                 '<img src="{0}" width="200" height="200"/>'.format(self.plot))
            ]
        self.properties += [
            ('Level', prop_int_pretty(self.level)),
            ('Weight', prop_int_pretty(self.weight)),
            ('Character orbit', '%s.%s' % (self.level, self.char_orbit_label)),
            ('Rep. character', '$%s$' % self.char_conrey_str),
            ('Character field',
             r'$\Q%s$' % ('' if self.char_degree == 1 else r'(\zeta_{%s})' %
                          self.char_order)),
            ('Dimension', prop_int_pretty(self.dim)),
        ]
        if self.num_forms is not None:
            self.properties.append(
                ('Newform subspaces', prop_int_pretty(self.num_forms)))
        self.properties.append(
            ('Sturm bound', prop_int_pretty(self.sturm_bound)))
        if data.get('trace_bound') is not None:
            self.properties.append(
                ('Trace bound', prop_int_pretty(self.trace_bound)))
        # Work around search results not including None
        if data.get('num_forms') is None:
            self.num_forms = None

        # Breadcrumbs
        self.bread = get_bread(level=self.level,
                               weight=self.weight,
                               char_orbit_label=self.char_orbit_label)

        # Downloads
        self.downloads = [
            ('Trace form to text',
             url_for('cmf.download_traces', label=self.label)),
            ('All stored data to text',
             url_for('.download_newspace', label=self.label)),
        ]

        if self.conrey_indexes[0] == 1:
            self.trivial_character = True
            character_str = "trivial character"
            if self.dim == 0:
                self.dim_str = r"\(%s\)" % (self.dim)
            else:
                self.minus_dim = self.dim - self.plus_dim
                self.dim_str = r"\(%s + %s\)" % (self.plus_dim, self.minus_dim)
        else:
            self.trivial_character = False
            character_str = r"Character {level}.{orbit_label}".format(
                level=self.level, orbit_label=self.char_orbit_label)
            # character_str = r"Character \(\chi_{{{level}}}({conrey}, \cdot)\)".format(level=self.level, conrey=self.conrey_indexes[0])
            self.dim_str = r"\(%s\)" % (self.dim)
        self.title = r"Space of modular forms of level %s, weight %s, and %s" % (
            self.level, self.weight, character_str)
        gamma1_link = '/ModularForm/GL2/Q/holomorphic/%d/%d' % (self.level,
                                                                self.weight)
        self.friends = [('Newspace %d.%d' % (self.level, self.weight),
                         gamma1_link)]
Example #12
0
    def __init__(self, galmap, triple=None):
        from lmfdb.belyi.main import url_for_belyi_passport_label, url_for_belyi_galmap_label

        # all information about the map goes in the data dictionary
        # most of the data from the database gets polished/formatted before we put it in the data dictionary
        data = self.data = {}
        # the stuff that does not need to be polished
        for elt in ("label", "plabel", "triples_cyc", "orbit_size", "g", "abc",
                    "deg", "primitivization", "is_primitive"):
            data[elt] = galmap[elt]
        if triple:
            data["label"] += '-' + (triple).replace(' ', '')
            data["triple"] = triple
        data["group"] = transitive_group_display_knowl(galmap["group"])

        data["geomtype"] = geomtypelet_to_geomtypename_dict[galmap["geomtype"]]
        data["lambdas"] = [str(c)[1:-1] for c in galmap["lambdas"]]
        data["primitivization_url"] = url_for_belyi_galmap_label(
            data['primitivization'])

        data["isQQ"] = False
        data["in_LMFDB"] = False
        F = belyi_base_field(galmap)
        if F._data is None:
            fld_coeffs = galmap["base_field"]
            pol = PolynomialRing(QQ, "t")(fld_coeffs)
            data["base_field"] = latex(pol)
        else:
            data["in_LMFDB"] = True
            if F.poly().degree() == 1:
                data["isQQ"] = True
            F.latex_poly = web_latex(F.poly(var="t"))
            data["base_field"] = F

        data['embeddings'] = galmap['embeddings']
        # change pairs of floats to complex numbers
        embed_strs = []
        for el in galmap["embeddings"]:
            if el[1] < 0:
                el_str = str(el[0]) + str(el[1]) + r"\sqrt{-1}"
            else:
                el_str = str(el[0]) + "+" + str(el[1]) + r"\sqrt{-1}"
            embed_strs.append(el_str)
        data["embeddings_and_triples"] = []
        self.triple = None
        self.embedding = None
        for i in range(0, len(data["triples_cyc"])):
            my_dict = {}
            triple_str = ', '.join(data['triples_cyc'][i])
            triple_link = triple_str.replace(' ', '')
            if triple_link == triple:
                self.triple = data['triples_cyc'][i]
                self.embedding = CC(data['embeddings'][i])
            my_dict['triple'] = triple_str
            my_dict['triple_link'] = triple_link
            if data["isQQ"]:
                my_dict[
                    'embedding'] = r"\text{not applicable (over $\mathbb{Q}$)}"
            else:
                my_dict['embedding'] = embed_strs[i]
            data['embeddings_and_triples'].append(my_dict)

        crv_str = galmap["curve"]
        if crv_str == "PP1":
            data["curve"] = r"\mathbb{P}^1"
        else:
            data["curve"] = make_curve_latex(crv_str, nu=self.embedding)

        data["map"] = make_map_latex(galmap["map"], nu=self.embedding)
        data["lambdas"] = [str(c)[1:-1] for c in galmap["lambdas"]]

        # Properties
        self.plot = db.belyi_galmap_portraits.lucky({"label": galmap['label']},
                                                    projection="portrait")
        plot_link = '<a href="{0}"><img src="{0}" width="200" height="200" style="background-color: white;"/></a>'.format(
            self.plot)
        properties = [("Label", galmap["label"])]
        if triple:
            properties += [("Triple", "$%s$" % triple)]
        if self.plot:
            properties += [(None, plot_link)]
        properties += [
            ("Group", str(galmap["group"])),
            ("Orders", "$%s$" % (data["abc"])),
            ("Genus", prop_int_pretty(data["g"])),
            ("Size", prop_int_pretty(data["orbit_size"])),
        ]
        self.properties = properties

        # Friends
        self.friends = [("Passport",
                         url_for_belyi_passport_label(galmap["plabel"]))]
        if galmap['label'] != galmap['primitivization']:
            self.friends.append(
                ("Primitivization",
                 url_for_belyi_galmap_label(galmap["primitivization"])))
        self.friends.extend(names_and_urls(galmap['friends']))

        #add curve link, if in LMFDB
        if 'curve_label' in galmap.keys():
            data['curve_label'] = galmap['curve_label']
            for name, url in self.friends:
                if "curve" in name.lower() and data['curve_label'] in name:
                    data["curve_url"] = url

        # Downloads
        if galmap["g"] <= 2:
            data_label = data["label"]
            if triple:
                spl = data_label.split("-")
                data_label = "-".join(spl[0:-1])
            self.downloads = [
                (
                    "Code to Magma",
                    url_for(".belyi_galmap_magma_download", label=data_label),
                ),
                (
                    "Code to SageMath",
                    url_for(".belyi_galmap_sage_download", label=data_label),
                ),
                (
                    "All data to text",
                    url_for(".belyi_galmap_text_download", label=data_label),
                ),
            ]
        else:
            self.downloads = []

        # Breadcrumbs
        label_spl = data["label"].split("-")
        groupstr = label_spl[0]
        letnum = label_spl[2]
        gstr = str(data['g'])
        sigmas = label_spl[1]
        sigma0, sigma1, sigmaoo = sigmas.split("_")
        abcstr = str(data['abc']).replace(' ', '')
        # does lambdasstr need to be updated?
        lambdasstr = "%s-%s-%s" % (sigma0, sigma1, sigmaoo)
        lambdasgstr = lambdasstr + "-" + gstr
        self.bread = [
            ("Belyi Maps", url_for(".index")),
            (groupstr, url_for(".by_url_belyi_search_group", group=groupstr)),
            (
                abcstr,
                url_for(".by_url_belyi_search_group_triple",
                        group=groupstr,
                        abc=abcstr),
            ),
            (
                lambdasgstr,
                url_for(
                    ".by_url_belyi_passport_label",
                    group=groupstr,
                    abc=abcstr,
                    sigma0=sigma0,
                    sigma1=sigma1,
                    sigmaoo=sigmaoo,
                    g=gstr,
                ),
            ),
            (
                letnum,
                url_for(
                    ".by_url_belyi_galmap_label",
                    group=groupstr,
                    abc=abcstr,
                    sigma0=sigma0,
                    sigma1=sigma1,
                    sigmaoo=sigmaoo,
                    g=gstr,
                    letnum=letnum,
                ),
            ),
        ]

        # Title
        if self.triple:
            self.title = "Embedded Belyi map " + data["label"]
        else:
            self.title = "Belyi map orbit " + data["label"]

        # Code snippets (only for curves)
        self.code = {}
        self.__dict__.update(data)
        return
Example #13
0
    def make_object(self, curve, endo, tama, ratpts, clus, is_curve):
        from lmfdb.genus2_curves.main import url_for_curve_label

        # all information about the curve, its Jacobian, isogeny class, and endomorphisms goes in the data dictionary
        # most of the data from the database gets polished/formatted before we put it in the data dictionary
        data = self.data = {}

        data['label'] = curve['label'] if is_curve else curve['class']
        data['slabel'] = data['label'].split('.')

        # set attributes common to curves and isogeny classes here
        data['Lhash'] = str(curve['Lhash'])
        data['cond'] = ZZ(curve['cond'])
        data['cond_factor_latex'] = web_latex_factored_integer(data['cond'])
        data['analytic_rank'] = ZZ(curve['analytic_rank'])
        data['mw_rank'] = ZZ(0) if curve.get('mw_rank') is None else ZZ(curve['mw_rank']) # 0 will be marked as a lower bound
        data['mw_rank_proved'] = curve['mw_rank_proved']
        data['analytic_rank_proved'] = curve['analytic_rank_proved']
        data['hasse_weil_proved'] = curve['hasse_weil_proved']
        data['st_group'] = curve['st_group']
        data['st_group_link'] = st_link_by_name(1,4,data['st_group'])
        data['st0_group_name'] = st0_group_name(curve['real_geom_end_alg'])
        data['is_gl2_type'] = curve['is_gl2_type']
        data['root_number'] = ZZ(curve['root_number'])
        data['lfunc_url'] = url_for("l_functions.l_function_genus2_page", cond=data['slabel'][0], x=data['slabel'][1])
        data['bad_lfactors'] = literal_eval(curve['bad_lfactors'])
        data['bad_lfactors_pretty'] = [ (c[0], list_to_factored_poly_otherorder(c[1])) for c in data['bad_lfactors']]
        if is_curve:
            # invariants specific to curve
            data['class'] = curve['class']
            data['abs_disc'] = ZZ(curve['abs_disc'])
            data['disc'] = curve['disc_sign'] * data['abs_disc']
            data['min_eqn'] = literal_eval(curve['eqn'])
            data['min_eqn_display'] = min_eqns_pretty(data['min_eqn'])
            data['disc_factor_latex'] = web_latex_factored_integer(data['disc'])
            data['igusa_clebsch'] = [ZZ(a) for a in literal_eval(curve['igusa_clebsch_inv'])]
            data['igusa'] = [ZZ(a) for a in literal_eval(curve['igusa_inv'])]
            data['g2'] = [QQ(a) for a in literal_eval(curve['g2_inv'])]
            data['igusa_clebsch_factor_latex'] = [web_latex_factored_integer(i) for i in data['igusa_clebsch']]
            data['igusa_factor_latex'] = [ web_latex_factored_integer(j) for j in data['igusa'] ]
            data['aut_grp'] = small_group_label_display_knowl('%d.%d' % tuple(literal_eval(curve['aut_grp_id'])))
            data['geom_aut_grp'] = small_group_label_display_knowl('%d.%d' % tuple(literal_eval(curve['geom_aut_grp_id'])))
            data['num_rat_wpts'] = ZZ(curve['num_rat_wpts'])
            data['has_square_sha'] = "square" if curve['has_square_sha'] else "twice a square"
            P = curve['non_solvable_places']
            if len(P):
                sz = "except over "
                sz += ", ".join([QpName(p) for p in P])
                last = " and"
                if len(P) > 2:
                    last = ", and"
                sz = last.join(sz.rsplit(",",1))
            else:
                sz = "everywhere"
            data['non_solvable_places'] = sz
            data['two_selmer_rank'] = ZZ(curve['two_selmer_rank'])
            data['torsion_order'] = curve['torsion_order']

            data['end_ring_base'] = endo['ring_base']
            data['end_ring_geom'] = endo['ring_geom']
            data['real_period'] = decimal_pretty(str(curve['real_period']))
            data['regulator'] = decimal_pretty(str(curve['regulator'])) if curve['regulator'] > -0.5 else 'unknown'
            if data['mw_rank'] == 0 and data['mw_rank_proved']:
                data['regulator'] = '1' # display an exact 1 when we know this

            data['tamagawa_product'] = ZZ(curve['tamagawa_product']) if curve.get('tamagawa_product') else 0
            data['analytic_sha'] = ZZ(curve['analytic_sha']) if curve.get('analytic_sha') else 0
            data['leading_coeff'] = decimal_pretty(str(curve['leading_coeff'])) if curve['leading_coeff'] else 'unknown'

            data['rat_pts'] = ratpts['rat_pts']
            data['rat_pts_v'] =  ratpts['rat_pts_v']
            data['rat_pts_table'] = ratpts_table(ratpts['rat_pts'],ratpts['rat_pts_v'])
            data['rat_pts_simple_table'] = ratpts_simpletable(ratpts['rat_pts'],ratpts['rat_pts_v'],data['min_eqn'])

            data['mw_gens_v'] = ratpts['mw_gens_v']
            lower = len([n for n in ratpts['mw_invs'] if n == 0])
            upper = data['analytic_rank']
            invs = ratpts['mw_invs'] if data['mw_gens_v'] or lower >= upper else [0 for n in range(upper-lower)] + ratpts['mw_invs']
            if len(invs) == 0:
                data['mw_group'] = 'trivial'
            else:
                data['mw_group'] = r'\(' + r' \times '.join([ (r'\Z' if n == 0 else r'\Z/{%s}\Z' % n) for n in invs]) + r'\)'
            if lower >= upper:
                data['mw_gens_table'] = mw_gens_table (ratpts['mw_invs'], ratpts['mw_gens'], ratpts['mw_heights'], ratpts['rat_pts'])
                data['mw_gens_simple_table'] = mw_gens_simple_table (ratpts['mw_invs'], ratpts['mw_gens'], ratpts['mw_heights'], ratpts['rat_pts'], data['min_eqn'])

            if curve['two_torsion_field'][0]:
                data['two_torsion_field_knowl'] = nf_display_knowl (curve['two_torsion_field'][0], field_pretty(curve['two_torsion_field'][0]))
            else:
                t = curve['two_torsion_field']
                data['two_torsion_field_knowl'] = r"splitting field of \(%s\) with Galois group %s" % (intlist_to_poly(t[1]),group_display_knowl(t[2][0],t[2][1]))

            tamalist = [[item['p'],item['tamagawa_number']] for item in tama]
            data['local_table'] = local_table (data['cond'],data['abs_disc'],tamalist,data['bad_lfactors_pretty'],clus)

        else:
            # invariants specific to isogeny class
            curves_data = list(db.g2c_curves.search({"class" : curve['class']}, ['label','eqn']))
            if not curves_data:
                raise KeyError("No curves found in database for isogeny class %s of genus 2 curve %s." %(curve['class'],curve['label']))
            data['curves'] = [ {"label" : c['label'], "equation_formatted" : min_eqn_pretty(literal_eval(c['eqn'])), "url": url_for_curve_label(c['label'])} for c in curves_data ]
            lfunc_data = db.lfunc_lfunctions.lucky({'Lhash':str(curve['Lhash'])})
            if not lfunc_data:
                raise KeyError("No Lfunction found in database for isogeny class of genus 2 curve %s." %curve['label'])
            if lfunc_data and lfunc_data.get('euler_factors'):
                data['good_lfactors'] = [[nth_prime(n+1),lfunc_data['euler_factors'][n]] for n in range(len(lfunc_data['euler_factors'])) if nth_prime(n+1) < 30 and (data['cond'] % nth_prime(n+1))]
                data['good_lfactors_pretty'] = [ (c[0], list_to_factored_poly_otherorder(c[1])) for c in data['good_lfactors']]

        # Endomorphism data over QQ:
        data['gl2_statement_base'] = gl2_statement_base(endo['factorsRR_base'], r'\(\Q\)')
        data['factorsQQ_base'] = endo['factorsQQ_base']
        data['factorsRR_base'] = endo['factorsRR_base']
        data['end_statement_base'] = (r"Endomorphism %s over \(\Q\):<br>" %("ring" if is_curve else "algebra") +
            end_statement(data['factorsQQ_base'], endo['factorsRR_base'], ring=data['end_ring_base'] if is_curve else None))

        # Field over which all endomorphisms are defined
        data['end_field_label'] = endo['fod_label']
        data['end_field_poly'] = intlist_to_poly(endo['fod_coeffs'])
        data['end_field_statement'] = end_field_statement(data['end_field_label'], data['end_field_poly'])

        # Endomorphism data over QQbar:
        data['factorsQQ_geom'] = endo['factorsQQ_geom']
        data['factorsRR_geom'] = endo['factorsRR_geom']
        if data['end_field_label'] != '1.1.1.1':
            data['gl2_statement_geom'] = gl2_statement_base(data['factorsRR_geom'], r'\(\overline{\Q}\)')
            data['end_statement_geom'] = (r"Endomorphism %s over \(\overline{\Q}\):" %("ring" if is_curve else "algebra") +
                end_statement(data['factorsQQ_geom'], data['factorsRR_geom'], field=r'\overline{\Q}', ring=data['end_ring_geom'] if is_curve else None))
        data['real_geom_end_alg_name'] = real_geom_end_alg_name(curve['real_geom_end_alg'])
        data['geom_end_alg_name'] = geom_end_alg_name(curve['geom_end_alg'])
        data['end_alg_name'] = end_alg_name(curve['end_alg'])

        # Endomorphism data over intermediate fields not already treated (only for curves, not necessarily isogeny invariant):
        if is_curve:
            data['end_lattice'] = (endo['lattice'])[1:-1]
            if data['end_lattice']:
                data['end_lattice_statement'] = end_lattice_statement(data['end_lattice'])

        # Field over which the Jacobian decomposes (base field if Jacobian is geometrically simple)
        data['is_simple_geom'] = endo['is_simple_geom']
        data['split_field_label'] = endo['spl_fod_label']
        data['split_field_poly'] = intlist_to_poly(endo['spl_fod_coeffs'])
        data['split_field_statement'] = split_field_statement(data['is_simple_geom'], data['split_field_label'], data['split_field_poly'])

        # Elliptic curve factors for non-simple Jacobians
        if not data['is_simple_geom']:
            data['split_coeffs'] = endo['spl_facs_coeffs']
            if 'spl_facs_labels' in endo and len(endo['spl_facs_labels']) == len(endo['spl_facs_coeffs']):
                data['split_labels'] = endo['spl_facs_labels']
            data['split_condnorms'] = endo['spl_facs_condnorms']
            data['split_statement'] = split_statement(data['split_coeffs'], data.get('split_labels'), data['split_condnorms'])

        # Properties
        self.properties = properties = [('Label', data['label'])]
        if is_curve:
            plot_from_db = db.g2c_plots.lucky({"label": curve['label']})
            if (plot_from_db is None):
                self.plot = encode_plot(eqn_list_to_curve_plot(data['min_eqn'], ratpts['rat_pts'] if ratpts else []))
            else:
                self.plot = plot_from_db['plot']
            plot_link = '<a href="{0}"><img src="{0}" width="200" height="150"/></a>'.format(self.plot)

            properties += [
                (None, plot_link),
                ('Conductor', prop_int_pretty(data['cond'])),
                ('Discriminant', prop_int_pretty(data['disc'])),
                ]
            if data['mw_rank_proved']:
                properties += [('Mordell-Weil group', data['mw_group'])]
        else:
            properties += [('Conductor', prop_int_pretty(data['cond']))]
        properties += [
            ('Sato-Tate group', data['st_group_link']),
            (r'\(\End(J_{\overline{\Q}}) \otimes \R\)', r'\(%s\)' % data['real_geom_end_alg_name']),
            (r'\(\End(J_{\overline{\Q}}) \otimes \Q\)', r'\(%s\)' % data['geom_end_alg_name']),
            (r'\(\End(J) \otimes \Q\)', r'\(%s\)' % data['end_alg_name']),
            (r'\(\overline{\Q}\)-simple', bool_pretty(data['is_simple_geom'])),
            (r'\(\mathrm{GL}_2\)-type', bool_pretty(data['is_gl2_type'])),
            ]

        # Friends
        self.friends = friends = []
        if is_curve:
            friends.append(('Genus 2 curve %s.%s' % (data['slabel'][0], data['slabel'][1]), url_for(".by_url_isogeny_class_label", cond=data['slabel'][0], alpha=data['slabel'][1])))

        # first deal with ECs and MFs
        ecs = []
        mfs = []
        if 'split_labels' in data:
            for friend_label in data['split_labels']:
                if is_curve:
                    ecs.append(("Elliptic curve " + friend_label, url_for_ec(friend_label)))
                else:
                    ecs.append(("Elliptic curve " + ec_label_class(friend_label), url_for_ec_class(friend_label)))
                try:
                    cond, iso = ec_label_class(friend_label).split(".")
                    newform_label = ".".join([cond, str(2), 'a', iso])
                    mfs.append(("Modular form " + newform_label, url_for("cmf.by_url_newform_label", level=cond, weight=2, char_orbit_label='a', hecke_orbit=iso)))
                except ValueError:
                    # means the friend isn't an elliptic curve over Q; adding Hilbert/Bianchi modular forms
                    # is dealt with via the L-functions instances below
                    pass

        ecs.sort(key=lambda x: key_for_numerically_sort(x[0]))
        mfs.sort(key=lambda x: key_for_numerically_sort(x[0]))

        # then again EC from lfun
        instances = []
        for elt in db.lfunc_instances.search({'Lhash':data['Lhash'], 'type' : 'ECQP'}, 'url'):
            instances.extend(elt.split('|'))

        # and then the other isogeny friends
        instances.extend([
            elt['url'] for elt in
            get_instances_by_Lhash_and_trace_hash(data["Lhash"],
                                                  4,
                                                  int(data["Lhash"])
                                                  )
            ])

        exclude = {elt[1].rstrip('/').lstrip('/') for elt in self.friends
                   if elt[1]}
        exclude.add(data['lfunc_url'].lstrip('/L/').rstrip('/'))
        for elt in ecs + mfs + names_and_urls(instances, exclude=exclude):
            # because of the splitting we must use G2C specific code
            add_friend(friends, elt)
        if is_curve:
            friends.append(('Twists', url_for(".index_Q",
                                              g20=str(data['g2'][0]),
                                              g21=str(data['g2'][1]),
                                              g22=str(data['g2'][2]))))

        friends.append(('L-function', data['lfunc_url']))

        # Breadcrumbs
        self.bread = bread = [
             ('Genus 2 curves', url_for(".index")),
             (r'$\Q$', url_for(".index_Q")),
             ('%s' % data['slabel'][0], url_for(".by_conductor", cond=data['slabel'][0])),
             ('%s' % data['slabel'][1], url_for(".by_url_isogeny_class_label", cond=data['slabel'][0], alpha=data['slabel'][1]))
             ]
        if is_curve:
            bread += [
                ('%s' % data['slabel'][2], url_for(".by_url_isogeny_class_discriminant", cond=data['slabel'][0], alpha=data['slabel'][1], disc=data['slabel'][2])),
                ('%s' % data['slabel'][3], url_for(".by_url_curve_label", cond=data['slabel'][0], alpha=data['slabel'][1], disc=data['slabel'][2], num=data['slabel'][3]))
                ]

        # Title
        self.title = "Genus 2 " + ("curve " if is_curve else "isogeny class ") + data['label']

        # Code snippets (only for curves)
        if not is_curve:
            return
        self.code = code = {}
        code['show'] = {'sage':'','magma':''} # use default show names
        f,h = fh = data['min_eqn']
        g = simplify_hyperelliptic(fh)
        code['curve'] = {'sage':'R.<x> = PolynomialRing(QQ); C = HyperellipticCurve(R(%s), R(%s));'%(f,h),
                         'magma':'R<x> := PolynomialRing(Rationals()); C := HyperellipticCurve(R!%s, R!%s);'%(f,h) }
        code['simple_curve'] = {'sage':'X = HyperellipticCurve(R(%s))'%(g), 'magma':'X,pi:= SimplifiedModel(C);' }
        if data['abs_disc'] % 4096 == 0:
            ind2 = [a[0] for a in data['bad_lfactors']].index(2)
            bad2 = data['bad_lfactors'][ind2][1]
            magma_cond_option = ': ExcFactors:=[*<2,Valuation('+str(data['cond'])+',2),R!'+str(bad2)+'>*]'
        else:
            magma_cond_option = ''
        code['cond'] = {'magma': 'Conductor(LSeries(C%s)); Factorization($1);'% magma_cond_option}
        code['disc'] = {'magma':'Discriminant(C); Factorization(Integers()!$1);'}
        code['geom_inv'] = {'sage':'C.igusa_clebsch_invariants(); [factor(a) for a in _]',
                            'magma':'IgusaClebschInvariants(C); IgusaInvariants(C); G2Invariants(C);'}
        code['aut'] = {'magma':'AutomorphismGroup(C); IdentifyGroup($1);'}
        code['autQbar'] = {'magma':'AutomorphismGroup(ChangeRing(C,AlgebraicClosure(Rationals()))); IdentifyGroup($1);'}
        code['num_rat_wpts'] = {'magma':'#Roots(HyperellipticPolynomials(SimplifiedModel(C)));'}
        if ratpts:
            code['rat_pts'] = {'magma': '[' + ','.join(["C![%s,%s,%s]"%(p[0],p[1],p[2]) for p in ratpts['rat_pts']]) + ']; // minimal model'}
            code['rat_pts_simp'] = {'magma': '[' + ','.join(["C![%s,%s,%s]"%(p[0],p[1],p[2]) for p in [simplify_hyperelliptic_point(data['min_eqn'], pt) for pt in ratpts['rat_pts']]]) + ']; // simplified model'}
        code['mw_group'] = {'magma':'MordellWeilGroupGenus2(Jacobian(C));'}
        code['two_selmer'] = {'magma':'TwoSelmerGroup(Jacobian(C)); NumberOfGenerators($1);'}
        code['has_square_sha'] = {'magma':'HasSquareSha(Jacobian(C));'}
        code['locally_solvable'] = {'magma':'f,h:=HyperellipticPolynomials(C); g:=4*f+h^2; HasPointsEverywhereLocally(g,2) and (#Roots(ChangeRing(g,RealField())) gt 0 or LeadingCoefficient(g) gt 0);'}
        code['torsion_subgroup'] = {'magma':'TorsionSubgroup(Jacobian(SimplifiedModel(C))); AbelianInvariants($1);'}
Example #14
0
 def properties(self):
     return [("Modulus", [prop_int_pretty(self.modulus)]),
             ("Structure", [self.structure]),
             ("Order", [prop_int_pretty(self.order)]),
             ]
Example #15
0
def render_artin_representation_webpage(label):
    if re.compile(r'^\d+$').match(label):
        return artin_representation_search(**{'dimension': label, 'search_array': ArtinSearchArray()})

    # label=dim.cond.nTt.indexcj, c is literal, j is index in conj class
    # Should we have a big try around this to catch bad labels?
    clean_label = clean_input(label)
    if clean_label != label:
        return redirect(url_for('.render_artin_representation_webpage', label=clean_label), 301)
    # We could have a single representation or a Galois orbit
    case = parse_any(label)
    if case[0] == 'malformed':
        try:
            raise ValueError
        except Exception:
            flash_error("%s is not in a valid form for the label for an Artin representation or a Galois orbit of Artin representations", label)
            return redirect(url_for(".index"))
    # Do this twice to customize error messages
    newlabel = case[1]
    case = case[0]
    if case == 'rep':
        try:
            the_rep = ArtinRepresentation(newlabel)
        except Exception:
            newlabel = parse_artin_label(label)
            flash_error("Artin representation %s is not in database", label)
            return redirect(url_for(".index"))
    else: # it is an orbit
        try:
            the_rep = ArtinRepresentation(newlabel+'.a')
        except Exception:
            newlabel = parse_artin_orbit_label(newlabel)
            flash_error("Galois orbit of Artin representations %s is not in database", label)
            return redirect(url_for(".index"))
        # in this case we want all characters
        num_conj = the_rep.galois_conjugacy_size()
        allchars = [ ArtinRepresentation(newlabel+'.'+num2letters(j)).character_formatted() for j in range(1,num_conj+1)]

    label = newlabel
    bread = get_bread([(artin_label_pretty(label), ' ')])

    #artin_logger.info("Found %s" % (the_rep._data))

    if case=='rep':
        title = "Artin representation %s" % label
    else:
        title = "Galois orbit of Artin representations %s" % label
    the_nf = the_rep.number_field_galois_group()
    if the_rep.sign() == 0:
        processed_root_number = "not computed"
    else:
        processed_root_number = '$%s$' % the_rep.sign()
    properties = [("Label", artin_label_pretty(label)),
                  ("Dimension", prop_int_pretty(the_rep.dimension())),
                  ("Group", the_rep.group()),
                  ("Conductor", prop_int_pretty(the_rep.conductor()))]
    if case == 'rep':
        properties.append( ("Root number", processed_root_number) )
    properties.append( ("Indicator", prop_int_pretty(the_rep.indicator())) )

    friends = []
    wnf = None
    proj_wnf = None
    nf_url = the_nf.url_for()
    if nf_url:
        friends.append(("Field {}".format(the_nf.label()), nf_url))
        wnf = the_nf.wnf()
    proj_wnf = WebNumberField.from_coeffs(the_rep._data['Proj_Polynomial'])
    if proj_wnf.is_in_db():
        proj_coefs = [int(z) for z in proj_wnf.coeffs()]
        if proj_coefs != the_nf.polynomial():
            friends.append(("Field {}".format(proj_wnf.get_label()), 
                str(url_for("number_fields.by_label", label=proj_wnf.get_label()))))
    if case == 'rep':
        cc = the_rep.central_character()
        if cc is not None:
            if the_rep.dimension()==1:
                if cc.order == 2:
                    cc_name = cc.symbol
                else:
                    cc_name = cc.texname
                friends.append(("Dirichlet character "+cc_name, url_for("characters.render_Dirichletwebpage", modulus=cc.modulus, number=cc.number)))
            else:
                detrep = the_rep.central_character_as_artin_rep()
                friends.append(("Determinant "+detrep.label(), detrep.url_for()))
        add_lfunction_friends(friends,label)

        # once the L-functions are in the database, the link can always be shown
        #if the_rep.dimension() <= 6:
        if the_rep.dimension() == 1:
            # Zeta is loaded differently
            if cc.modulus == 1 and cc.number == 1:
                friends.append(("L-function", url_for("l_functions.l_function_dirichlet_page", modulus=cc.modulus, number=cc.number)))
            else:
                # looking for Lhash dirichlet_L_modulus.number
                mylhash = 'dirichlet_L_%d.%d'%(cc.modulus,cc.number)
                lres = db.lfunc_instances.lucky({'Lhash': mylhash})
                if lres is not None:
                    friends.append(("L-function", url_for("l_functions.l_function_dirichlet_page", modulus=cc.modulus, number=cc.number)))

        # Dimension > 1
        elif int(the_rep.conductor())**the_rep.dimension() <= 729000000000000:
            friends.append(("L-function", url_for("l_functions.l_function_artin_page",
                                              label=the_rep.label())))
        orblabel = re.sub(r'\.[a-z]+$', '', label)
        friends.append(("Galois orbit " + artin_label_pretty(orblabel),
            url_for(".render_artin_representation_webpage", label=orblabel)))
    else:
        add_lfunction_friends(friends,label)
        friends.append(("L-function", url_for("l_functions.l_function_artin_page", label=the_rep.label())))
        for j in range(1,1+the_rep.galois_conjugacy_size()):
            newlabel = label+'.'+num2letters(j)
            friends.append(("Artin representation " + artin_label_pretty(newlabel),
                url_for(".render_artin_representation_webpage", label=newlabel)))

    info={} # for testing

    if case == 'rep':
        return render_template(
            "artin-representation-show.html",
            title=title,
            bread=bread,
            friends=friends,
            object=the_rep,
            cycle_string=cycle_string,
            wnf=wnf,
            proj_wnf=proj_wnf,
            properties=properties,
            info=info,
            learnmore=learnmore_list(),
            KNOWL_ID="artin.%s" % label,
        )
    # else we have an orbit
    return render_template(
        "artin-representation-galois-orbit.html",
        title=title,
        bread=bread,
        allchars=allchars,
        friends=friends,
        object=the_rep,
        cycle_string=cycle_string,
        wnf=wnf,
        proj_wnf=proj_wnf,
        properties=properties,
        info=info,
        learnmore=learnmore_list(),
        KNOWL_ID="artin.%s" % label,
    )
Example #16
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)
Example #17
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)'
        }
Example #18
0
    def make_curve(self):
        data = self.data = {}
        lmfdb_label = self.lmfdb_label

        # Some data fields of self are just those from the database.
        # These only need some reformatting.

        data['ainvs'] = self.ainvs
        data['conductor'] = N = self.conductor
        data['j_invariant'] = QQ(tuple(self.jinv))
        data['j_inv_factor'] = latex(0)
        if data['j_invariant']:  # don't factor 0
            data['j_inv_factor'] = latex(data['j_invariant'].factor())
        data['j_inv_latex'] = web_latex(data['j_invariant'])

        # retrieve local reduction data from table ec_localdata:

        self.local_data = local_data = list(
            db.ec_localdata.search({"lmfdb_label": lmfdb_label}))
        for ld in local_data:
            if ld['kodaira_symbol'] <= -14:
                # Work around bug in Sage's latex
                ld['kod'] = 'I_{%s}^{*}' % (-ld['kodaira_symbol'] - 4)
            else:
                ld['kod'] = latex(KodairaSymbol(ld['kodaira_symbol']))

        Nfac = Factorization([(ZZ(ld['prime']), ld['conductor_valuation'])
                              for ld in local_data])
        Dfac = Factorization([(ZZ(ld['prime']), ld['discriminant_valuation'])
                              for ld in local_data],
                             unit=ZZ(self.signD))
        data['disc_factor'] = latex(Dfac)
        data['disc'] = D = Dfac.value()
        data['cond_factor'] = latex(Nfac)
        data['disc_latex'] = web_latex(D)
        data['cond_latex'] = web_latex(N)

        # retrieve data about MW rank, generators, heights and
        # torsion, leading term of L-function & other BSD data from
        # table ec_mwbsd:

        self.make_mwbsd()

        # latex equation:

        latexeqn = latex_equation(self.ainvs)
        data['equation'] = raw_typeset(unlatex(latexeqn), latexeqn)

        # minimal quadratic twist:

        data['minq_D'] = minqD = self.min_quad_twist_disc
        data['minq_label'] = db.ec_curvedata.lucky(
            {'ainvs': self.min_quad_twist_ainvs},
            projection='lmfdb_label'
            if self.label_type == 'LMFDB' else 'Clabel')
        data['minq_info'] = '(itself)' if minqD == 1 else '(by {})'.format(
            minqD)

        # modular degree:

        try:
            data['degree'] = ZZ(self.degree)  # convert None to 0
        except AttributeError:  # if not computed, db has Null and the attribute is missing
            data['degree'] = 0  # invalid, but will be displayed nicely

        # coefficients of modular form / L-series:

        classdata = db.ec_classdata.lookup(self.lmfdb_iso)
        data['an'] = classdata['anlist']
        data['ap'] = classdata['aplist']

        # mod-p Galois images:

        data['galois_data'] = list(
            db.ec_galrep.search({'lmfdb_label': lmfdb_label}))
        for gd in data[
                'galois_data']:  # remove the prime prefix from each image code
            gd['image'] = trim_galois_image_code(gd['image'])

        # CM and Endo ring:

        data['CMD'] = self.cm
        data['CM'] = "no"
        data['EndE'] = r"\(\Z\)"
        if self.cm:
            data['cm_ramp'] = [
                p for p in ZZ(self.cm).support() if not p in self.nonmax_primes
            ]
            data['cm_nramp'] = len(data['cm_ramp'])
            if data['cm_nramp'] == 1:
                data['cm_ramp'] = data['cm_ramp'][0]
            else:
                data['cm_ramp'] = ", ".join(str(p) for p in data['cm_ramp'])
            data['cm_sqf'] = ZZ(self.cm).squarefree_part()

            data['CM'] = r"yes (\(D=%s\))" % data['CMD']
            if data['CMD'] % 4 == 0:
                d4 = ZZ(data['CMD']) // 4
                data['EndE'] = r"\(\Z[\sqrt{%s}]\)" % d4
            else:
                data['EndE'] = r"\(\Z[(1+\sqrt{%s})/2]\)" % data['CMD']
            data['ST'] = st_link_by_name(1, 2, 'N(U(1))')
        else:
            data['ST'] = st_link_by_name(1, 2, 'SU(2)')

        # Isogeny degrees:

        cond, iso, num = split_lmfdb_label(lmfdb_label)
        self.class_deg = classdata['class_deg']
        self.one_deg = ZZ(self.class_deg).is_prime()
        isodegs = [str(d) for d in self.isogeny_degrees if d > 1]
        if len(isodegs) < 3:
            data['isogeny_degrees'] = " and ".join(isodegs)
        else:
            data['isogeny_degrees'] = " and ".join(
                [", ".join(isodegs[:-1]), isodegs[-1]])

        self.make_twoadic_data()

        # Optimality

        # The optimal curve in the class is the curve whose Cremona
        # label ends in '1' except for '990h' which was labelled
        # wrongly long ago. This is proved for N up to
        # OPTIMALITY_BOUND (and when there is only one curve in an
        # isogeny class, obviously) and expected for all N.

        # Column 'optimality' is 1 for certainly optimal curves, 0 for
        # certainly non-optimal curves, and is n>1 if the curve is one
        # of n in the isogeny class which may be optimal given current
        # knowledge.

        # Column "manin_constant' is the correct Manin constant
        # assuming that the optimal curve in the class is known, or
        # otherwise if it is the curve with (Cremona) number 1.

        # The code here allows us to update the display correctly by
        # changing one line in this file (defining OPTIMALITY_BOUND)
        # without changing the data.

        data['optimality_bound'] = OPTIMALITY_BOUND
        self.cremona_bound = CREMONA_BOUND
        if N < CREMONA_BOUND:
            data[
                'manin_constant'] = self.manin_constant  # (conditional on data['optimality_known'])
        else:
            data['manin_constant'] = 0  # (meaning not available)

        if N < OPTIMALITY_BOUND:

            data['optimality_code'] = int(
                self.Cnumber == (3 if self.Ciso == '990h' else 1))
            data['optimality_known'] = True
            data['manin_known'] = True
            if self.label_type == 'Cremona':
                data[
                    'optimal_label'] = '990h3' if self.Ciso == '990h' else self.Ciso + '1'
            else:
                data[
                    'optimal_label'] = '990.i3' if self.lmfdb_iso == '990.i' else self.lmfdb_iso + '1'

        elif N < CREMONA_BOUND:

            data['optimality_code'] = self.optimality
            data['optimality_known'] = (self.optimality < 2)

            if self.optimality == 1:
                data['manin_known'] = True
                data[
                    'optimal_label'] = self.Clabel if self.label_type == 'Cremona' else self.lmfdb_label
            else:
                if self.Cnumber == 1:
                    data['manin_known'] = False
                    data[
                        'optimal_label'] = self.Clabel if self.label_type == 'Cremona' else self.lmfdb_label
                else:
                    # find curve #1 in this class and its optimailty code:
                    opt_curve = db.ec_curvedata.lucky(
                        {
                            'Ciso': self.Ciso,
                            'Cnumber': 1
                        },
                        projection=['Clabel', 'lmfdb_label', 'optimality'])
                    data['manin_known'] = (opt_curve['optimality'] == 1)
                    data['optimal_label'] = opt_curve[
                        'Clabel' if self.label_type ==
                        'Cremona' else 'lmfdb_label']

        else:
            data['optimality_code'] = None
            data['optimality_known'] = False
            data['manin_known'] = False
            data['optimal_label'] = ''

        # p-adic data:

        data['p_adic_primes'] = [
            p for i, p in enumerate(prime_range(5, 100))
            if (N * data['ap'][i]) % p != 0
        ]

        data['p_adic_data_exists'] = False
        if data['optimality_code'] == 1:
            data['p_adic_data_exists'] = db.ec_padic.exists(
                {'lmfdb_iso': self.lmfdb_iso})

        # Iwasawa data (where present)

        self.make_iwasawa()

        # Torsion growth data (where present)

        self.make_torsion_growth()

        # Newform

        rawnewform = str(PowerSeriesRing(QQ, 'q')(data['an'], 20, check=True))
        data['newform'] = raw_typeset(
            rawnewform,
            web_latex(PowerSeriesRing(QQ, 'q')(data['an'], 20, check=True)))
        data['newform_label'] = self.newform_label = ".".join(
            [str(cond), str(2), 'a', iso])
        self.newform_link = url_for("cmf.by_url_newform_label",
                                    level=cond,
                                    weight=2,
                                    char_orbit_label='a',
                                    hecke_orbit=iso)
        self.newform_exists_in_db = db.mf_newforms.label_exists(
            self.newform_label)
        self._code = None

        if self.label_type == 'Cremona':
            self.class_url = url_for(".by_ec_label", label=self.Ciso)
            self.class_name = self.Ciso
        else:
            self.class_url = url_for(".by_ec_label", label=self.lmfdb_iso)
            self.class_name = self.lmfdb_iso
        data['class_name'] = self.class_name
        data['Cnumber'] = self.Cnumber if N < CREMONA_BOUND else None

        self.friends = [('Isogeny class ' + self.class_name, self.class_url),
                        ('Minimal quadratic twist %s %s' %
                         (data['minq_info'], data['minq_label']),
                         url_for(".by_ec_label", label=data['minq_label'])),
                        ('All twists ',
                         url_for(".rational_elliptic_curves",
                                 jinv=data['j_invariant']))]

        lfun_url = url_for("l_functions.l_function_ec_page",
                           conductor_label=N,
                           isogeny_class_label=iso)
        origin_url = lfun_url.lstrip('/L/').rstrip('/')

        if db.lfunc_instances.exists({'url': origin_url}):
            self.friends += [('L-function', lfun_url)]
        else:
            self.friends += [('L-function not available', "")]

        if not self.cm:
            if N <= 300:
                self.friends += [('Symmetric square L-function',
                                  url_for("l_functions.l_function_ec_sym_page",
                                          power='2',
                                          conductor=N,
                                          isogeny=iso))]
            if N <= 50:
                self.friends += [('Symmetric cube L-function',
                                  url_for("l_functions.l_function_ec_sym_page",
                                          power='3',
                                          conductor=N,
                                          isogeny=iso))]
        if self.newform_exists_in_db:
            self.friends += [('Modular form ' + self.newform_label,
                              self.newform_link)]

        self.downloads = [('q-expansion to text',
                           url_for(".download_EC_qexp",
                                   label=self.lmfdb_label,
                                   limit=1000)),
                          ('All stored data to text',
                           url_for(".download_EC_all",
                                   label=self.lmfdb_label)),
                          ('Code to Magma',
                           url_for(".ec_code_download",
                                   conductor=cond,
                                   iso=iso,
                                   number=num,
                                   label=self.lmfdb_label,
                                   download_type='magma')),
                          ('Code to SageMath',
                           url_for(".ec_code_download",
                                   conductor=cond,
                                   iso=iso,
                                   number=num,
                                   label=self.lmfdb_label,
                                   download_type='sage')),
                          ('Code to GP',
                           url_for(".ec_code_download",
                                   conductor=cond,
                                   iso=iso,
                                   number=num,
                                   label=self.lmfdb_label,
                                   download_type='gp'))]

        try:
            self.plot = encode_plot(self.E.plot())
        except AttributeError:
            self.plot = encode_plot(EllipticCurve(data['ainvs']).plot())

        self.plot_link = '<a href="{0}"><img src="{0}" width="200" height="150"/></a>'.format(
            self.plot)
        self.properties = [
            ('Label', self.Clabel
             if self.label_type == 'Cremona' else self.lmfdb_label),
            (None, self.plot_link),
            ('Conductor', prop_int_pretty(data['conductor'])),
            ('Discriminant', prop_int_pretty(data['disc'])),
            ('j-invariant', '%s' % data['j_inv_latex']),
            ('CM', '%s' % data['CM']),
            ('Rank', 'unknown' if self.mwbsd['rank'] == '?' else
             prop_int_pretty(self.mwbsd['rank'])),
            ('Torsion structure', (r'\(%s\)' % self.mwbsd['tor_struct'])
             if self.mwbsd['tor_struct'] else 'trivial'),
        ]

        if self.label_type == 'Cremona':
            self.title = "Elliptic curve with Cremona label {} (LMFDB label {})".format(
                self.Clabel, self.lmfdb_label)
        elif N < CREMONA_BOUND:
            self.title = "Elliptic curve with LMFDB label {} (Cremona label {})".format(
                self.lmfdb_label, self.Clabel)
        else:
            self.title = "Elliptic curve with LMFDB label {}".format(
                self.lmfdb_label)

        self.bread = [('Elliptic curves', url_for("ecnf.index")),
                      (r'$\Q$', url_for(".rational_elliptic_curves")),
                      ('%s' % N, url_for(".by_conductor", conductor=N)),
                      ('%s' % iso,
                       url_for(".by_double_iso_label",
                               conductor=N,
                               iso_label=iso)), ('%s' % num, ' ')]
Example #19
0
    def make_class(self):
        self.CM = self.cm
        N, iso, number = split_lmfdb_label(self.lmfdb_iso)
        self.conductor = N = int(N)
        # Extract the size of the isogeny class from the database
        self.ncurves = ncurves = self.class_size
        # Create a list of the curves in the class from the database
        number_key = 'number' if self.label_type == 'Cremona' else 'lmfdb_number'
        self.curves = [
            db.ec_curves.lucky({
                'iso': self.iso,
                number_key: i + 1
            }) for i in range(ncurves)
        ]

        # Set optimality flags.  The optimal curve is conditionally
        # number 1 except in one case which is labeled differently in
        # the Cremona tables.  We know which curve is optimal iff the
        # optimality code for curve #1 is 1 (except for class 990h).

        # Note that self is actually an elliptic curve, with number=1.

        # The code here allows us to update the display correctly by
        # changing one line in this file (defining OPTIMALITY_BOUND)
        # without changing the data.

        self.optimality_bound = OPTIMALITY_BOUND
        self.optimality_known = (N < OPTIMALITY_BOUND) or (self.optimality
                                                           == 1) or (self.iso
                                                                     == '990h')
        self.optimal_label = self.label if self.label_type == 'Cremona' else self.lmfdb_label

        if N < OPTIMALITY_BOUND:
            for c in self.curves:
                c['optimal'] = (c['number'] == (3
                                                if self.iso == '990h' else 1))
                c['optimality_known'] = True
        else:
            for c in self.curves:
                c['optimal'] = (c['optimality'] > 0
                                )  # this curve possibly optimal
                c['optimality_known'] = (c['optimality'] == 1
                                         )  # this curve certainly optimal

        for c in self.curves:
            c['ai'] = c['ainvs']
            c['curve_url_lmfdb'] = url_for(".by_triple_label",
                                           conductor=N,
                                           iso_label=iso,
                                           number=c['lmfdb_number'])
            c['curve_url_cremona'] = url_for(".by_ec_label", label=c['label'])
            if self.label_type == 'Cremona':
                c['curve_label'] = c['label']
                _, c_iso, c_number = split_cremona_label(c['label'])
            else:
                c['curve_label'] = c['lmfdb_label']
                _, c_iso, c_number = split_lmfdb_label(c['lmfdb_label'])
            c['short_label'] = "{}{}".format(c_iso, c_number)

        from sage.matrix.all import Matrix
        if self.label_type == 'Cremona':
            # permute rows/cols
            perm = lambda i: next(c for c in self.curves
                                  if c['number'] == i + 1)['lmfdb_number'] - 1
            self.isogeny_matrix = [[
                self.isogeny_matrix[perm(i)][perm(j)] for i in range(ncurves)
            ] for j in range(ncurves)]

        self.isogeny_matrix = Matrix(self.isogeny_matrix)

        self.isogeny_matrix_str = latex(matrix(self.isogeny_matrix))

        # Create isogeny graph with appropriate vertex labels:

        self.graph = make_graph(self.isogeny_matrix,
                                [c['short_label'] for c in self.curves])
        P = self.graph.plot(edge_labels=True, vertex_size=1000)
        self.graph_img = encode_plot(P)
        self.graph_link = '<img src="%s" width="200" height="150"/>' % self.graph_img

        self.newform = web_latex(
            PowerSeriesRing(QQ, 'q')(self.anlist, 20, check=True))
        self.newform_label = ".".join([str(N), str(2), 'a', iso])
        #        self.newform_label = db.mf_newforms.lucky({'level':N, 'weight':2, 'related_objects':{'$contains':'EllipticCurve/Q/%s/%s' % (N, iso)}},'label')
        #        self.newform_exists_in_db = self.newform_label is not None
        self.newform_exists_in_db = db.mf_newforms.label_exists(
            self.newform_label)
        #        if self.newform_label is not None:
        if self.newform_exists_in_db:
            char_orbit, hecke_orbit = self.newform_label.split('.')[2:]
            self.newform_link = url_for("cmf.by_url_newform_label",
                                        level=N,
                                        weight=2,
                                        char_orbit_label=char_orbit,
                                        hecke_orbit=hecke_orbit)

        self.lfunction_link = url_for("l_functions.l_function_ec_page",
                                      conductor_label=N,
                                      isogeny_class_label=iso)

        self.friends = [('L-function', self.lfunction_link)]
        if not self.CM:
            self.CM = "no"
            if int(N) <= 300:
                self.friends += [('Symmetric square L-function',
                                  url_for("l_functions.l_function_ec_sym_page",
                                          power='2',
                                          conductor=N,
                                          isogeny=iso))]
            if int(N) <= 50:
                self.friends += [('Symmetric cube L-function',
                                  url_for("l_functions.l_function_ec_sym_page",
                                          power='3',
                                          conductor=N,
                                          isogeny=iso))]
        if self.newform_exists_in_db:
            self.friends += [('Modular form ' + self.newform_label,
                              self.newform_link)]

        if self.label_type == 'Cremona':
            self.title = "Elliptic curve isogeny class with Cremona label {} (LMFDB label {})".format(
                self.iso, self.lmfdb_iso)
            self.iso_label = self.iso
        else:
            self.title = "Elliptic curve isogeny class with LMFDB label {} (Cremona label {})".format(
                self.lmfdb_iso, self.iso)
            self.iso_label = self.lmfdb_iso

        self.properties = [
            ('Label',
             self.iso if self.label_type == 'Cremona' else self.lmfdb_iso),
            ('Number of curves', prop_int_pretty(ncurves)),
            ('Conductor', prop_int_pretty(N)), ('CM', '%s' % self.CM),
            ('Rank', prop_int_pretty(self.rank))
        ]
        if self.ncurves > 1:
            self.properties += [('Graph', ''), (None, self.graph_link)]

        self.downloads = [('q-expansion to text',
                           url_for(".download_EC_qexp",
                                   label=self.lmfdb_iso,
                                   limit=1000)),
                          ('All stored data to text',
                           url_for(".download_EC_all", label=self.lmfdb_iso))]

        self.bread = [('Elliptic curves', url_for("ecnf.index")),
                      (r'$\Q$', url_for(".rational_elliptic_curves")),
                      ('%s' % N, url_for(".by_conductor", conductor=N)),
                      ('%s' % iso, ' ')]
        self.code = {}
        self.code['show'] = {'sage': ''}  # use default show names
        self.code['class'] = {
            'sage':
            'E = EllipticCurve("%s1")\n' % (self.lmfdb_iso) +
            'E.isogeny_class()\n'
        }
        self.code['curves'] = {'sage': 'E.isogeny_class().curves'}
        self.code['rank'] = {'sage': 'E.rank()'}
        self.code['q_eigenform'] = {'sage': 'E.q_eigenform(10)'}
        self.code['matrix'] = {'sage': 'E.isogeny_class().matrix()'}
        self.code['plot'] = {
            'sage': 'E.isogeny_graph().plot(edge_labels=True)'
        }