Ejemplo n.º 1
0
def EllipticCurve_to_ecnf_dict(E):
    """
    Make the dict that should be fed to `make_curves_line` in `lmfdb/scripts/ecnf/import_utils.py`.

    It sets `iso_label`, 'a' and `number` to '1' and `cm` and `base_change` to '?'

    INPUT:

    * E - A sage elliptic curve over a number field
    """
    E = EllipticCurve_polredabs(E)
    K = E.base_field()
    WNF = WebNumberField.from_polredabs(K.polynomial())
    ainvs = [map(str,ai) for ai in map(list,E.a_invariants())]
    conductor = E.conductor()
    conductor_str = "".join(str([conductor.norm()]+list(conductor.gens_two())).split())
    ec = {'field_label':WNF.label,
          'conductor_label':ideal_label(conductor),
          'iso_label':'a',
          'number':'1',
          'conductor_ideal':conductor_str,
          'conductor_norm':str(conductor.norm()),
          'ainvs':ainvs,
          'cm':'?',
          'base_change':'?'}
    return ec
Ejemplo n.º 2
0
def convert_ideal_label(K, lab):
    """An ideal label of the form N.c.d is converted to N.i.  Here N.c.d
    defines the ideal I with Z-basis [a, c+d*w] where w is the standard
    generator of K, N=N(I) and a=N/d.  The standard label is N.i where I is the i'th ideal of norm N in the standard ordering.

    NB Only intended for use in coverting IQF labels!  To get the standard label from any ideal I just use ideal_label(I).
    """
    global the_labels
    if K in the_labels:
        if lab in the_labels[K]:
            return the_labels[K][lab]
        else:
            pass
    else:
        the_labels[K] = {}

    comps = lab.split(".")
    # test for labels which do not need any conversion
    if len(comps)==2:
        return lab
    assert len(comps)==3
    N, c, d = [int(x) for x in comps]
    a = N//d
    I = K.ideal(a, c+d*K.gen())
    newlab = ideal_label(I)
    #print("Ideal label converted from {} to {} over {}".format(lab,newlab,K))
    the_labels[K][lab] = newlab
    return newlab
Ejemplo n.º 3
0
def convert_ideal_label(K, lab):
    """An ideal label of the form N.c.d is converted to N.i.  Here N.c.d
    defines the ideal I with Z-basis [a, c+d*w] where w is the standard
    generator of K, N=N(I) and a=N/d.  The standard label is N.i where I is the i'th ideal of norm N in the standard ordering.

    NB Only intended for use in coverting IQF labels!  To get the standard label from any ideal I just use ideal_label(I).
    """
    global the_labels
    if K in the_labels:
        if lab in the_labels[K]:
            return the_labels[K][lab]
        else:
            pass
    else:
        the_labels[K] = {}

    comps = lab.split(".")
    # test for labels which do not need any conversion
    if len(comps) == 2:
        return lab
    assert len(comps) == 3
    N, c, d = [int(x) for x in comps]
    a = N // d
    I = K.ideal(a, c + d * K.gen())
    newlab = ideal_label(I)
    #print("Ideal label converted from {} to {} over {}".format(lab,newlab,K))
    the_labels[K][lab] = newlab
    return newlab
Ejemplo n.º 4
0
def EllipticCurve_to_ecnf_dict(E):
    """
    Make the dict that should be fed to `make_curves_line` in `lmfdb/scripts/ecnf/import_utils.py`.

    It sets `iso_label`, 'a' and `number` to '1' and `cm` and `base_change` to '?'

    INPUT:

    * E - A sage elliptic curve over a number field
    """
    E = EllipticCurve_polredabs(E)
    K = E.base_field()
    WNF = WebNumberField.from_polredabs(K.polynomial())
    ainvs = [map(str, ai) for ai in map(list, E.a_invariants())]
    conductor = E.conductor()
    conductor_str = "".join(
        str([conductor.norm()] + list(conductor.gens_two())).split())
    ec = {
        'field_label': WNF.label,
        'conductor_label': ideal_label(conductor),
        'iso_label': 'a',
        'number': '1',
        'conductor_ideal': conductor_str,
        'conductor_norm': str(conductor.norm()),
        'ainvs': ainvs,
        'cm': '?',
        'base_change': '?'
    }
    return ec
Ejemplo n.º 5
0
 def ideal2label(ideal):
     return ideal_label(ideal)
Ejemplo n.º 6
0
    def make_form(self):
        # To start with the data fields of self are just those from
        # the database.  We need to reformat these and compute some
        # further (easy) data about it.
        #
        from lmfdb.ecnf.WebEllipticCurve import FIELD
        self.field = FIELD(self.field_label)
        pretty_field = field_pretty(self.field_label)
        self.field_knowl = nf_display_knowl(self.field_label, pretty_field)
        try:
            dims = db.bmf_dims.lucky({'field_label':self.field_label, 'level_label':self.level_label}, projection='gl2_dims')
            self.newspace_dimension = dims[str(self.weight)]['new_dim']
        except TypeError:
            self.newspace_dimension = 'not available'
        self.newspace_label = "-".join([self.field_label,self.level_label])
        self.newspace_url = url_for(".render_bmf_space_webpage", field_label=self.field_label, level_label=self.level_label)
        K = self.field.K()

        if self.dimension>1:
            Qx = PolynomialRing(QQ,'x')
            self.hecke_poly = Qx(str(self.hecke_poly))
            F = NumberField(self.hecke_poly,'z')
            self.hecke_poly = web_latex(self.hecke_poly)
            def conv(ap):
                if '?' in ap:
                    return 'not known'
                else:
                    return F(str(ap))
            self.hecke_eigs = [conv(str(ap)) for ap in self.hecke_eigs]

        self.nap = len(self.hecke_eigs)
        self.nap0 = min(50, self.nap)
        self.hecke_table = [[web_latex(p.norm()),
                             ideal_label(p),
                             web_latex(p.gens_reduced()[0]),
                             web_latex(ap)] for p,ap in zip(primes_iter(K), self.hecke_eigs[:self.nap0])]
        level = ideal_from_label(K,self.level_label)
        self.level_ideal2 = web_latex(level)
        badp = level.prime_factors()
        self.have_AL = self.AL_eigs[0]!='?'
        if self.have_AL:
            self.AL_table = [[web_latex(p.norm()),
                             ideal_label(p),
                              web_latex(p.gens_reduced()[0]),
                              web_latex(ap)] for p,ap in zip(badp, self.AL_eigs)]
        self.sign = 'not determined'
        
        try:
            if self.sfe == 1:
                self.sign = "+1"
            elif self.sfe == -1:
                self.sign = "-1"
        except AttributeError:
            self.sfe = '?'

        if self.Lratio == '?':
            self.Lratio = "not determined"
            self.anrank = "not determined"
        else:
            self.Lratio = QQ(self.Lratio)
            self.anrank = "\(0\)" if self.Lratio!=0 else "odd" if self.sfe==-1 else "\(\ge2\), even"

        self.properties2 = [('Base field', pretty_field),
                            ('Weight', str(self.weight)),
                            ('Level norm', str(self.level_norm)),
                            ('Level', self.level_ideal2),
                            ('Label', self.label),
                            ('Dimension', str(self.dimension))
        ]

        try:
            if self.CM == '?':
                self.CM = 'not determined'
            elif self.CM == 0:
                self.CM = 'no'
            else:
                if self.CM%4 in [2,3]:
                    self.CM = 4*self.CM
        except AttributeError:
            self.CM = 'not determined'
        self.properties2.append(('CM', str(self.CM)))

        self.bc_extra = ''
        self.bcd = 0
        self.bct = self.bc!='?' and self.bc!=0
        if self.bc == '?':
            self.bc = 'not determined'
        elif self.bc == 0:
            self.bc = 'no'
        elif self.bc == 1:
            self.bcd = self.bc
            self.bc = 'yes'
        elif self.bc >1:
            self.bcd = self.bc
            self.bc = 'yes'
            self.bc_extra = ', of a form over \(\mathbb{Q}\) with coefficients in \(\mathbb{Q}(\sqrt{'+str(self.bcd)+'})\)'
        elif self.bc == -1:
            self.bc = 'no'
            self.bc_extra = ', but is a twist of the base-change of a form over \(\mathbb{Q}\)'
        elif self.bc < -1:
            self.bcd = -self.bc
            self.bc = 'no'
            self.bc_extra = ', but is a twist of the base-change of a form over \(\mathbb{Q}\) with coefficients in \(\mathbb{Q}(\sqrt{'+str(self.bcd)+'})\)'
        self.properties2.append(('Base-change', str(self.bc)))

        curve_bc = db.ec_nfcurves.lucky({'class_label':self.label}, projection="base_change")
        if curve_bc is not None:
            self.ec_status = 'exists'
            self.ec_url = url_for("ecnf.show_ecnf_isoclass", nf=self.field_label, conductor_label=self.level_label, class_label=self.label_suffix)
            curve_bc_parts = [split_lmfdb_label(lab) for lab in curve_bc]
            bc_urls = [url_for("cmf.by_url_newform_label", level=cond, weight=2, char_orbit_label='a', hecke_orbit=iso) for cond, iso, num in curve_bc_parts]
            bc_labels = [".".join( [str(cond), str(2), 'a', iso] ) for cond,iso,_ in curve_bc_parts]
            bc_exists = [db.mf_newforms.label_exists(lab) for lab in bc_labels]
            self.bc_forms = [{'exists':ex, 'label':lab, 'url':url} for ex,lab,url in zip(bc_exists, bc_labels, bc_urls)]
        else:
            self.bc_forms = []
            if self.bct:
                self.ec_status = 'none'
            else:
                self.ec_status = 'missing'

        self.properties2.append(('Sign', self.sign))
        self.properties2.append(('Analytic rank', self.anrank))

        self.friends = []
        self.friends += [('Newspace {}'.format(self.newspace_label),self.newspace_url)]
        url = 'ModularForm/GL2/ImaginaryQuadratic/{}'.format(
                self.label.replace('-', '/'))
        Lfun = get_lfunction_by_url(url)
        if Lfun:
            # first by Lhash
            instances = get_instances_by_Lhash(Lfun['Lhash'])
            # then by trace_hash
            instances += get_instances_by_trace_hash(Lfun['degree'], Lfun['trace_hash'])

            # This will also add the EC/G2C, as this how the Lfun was computed
            self.friends = names_and_urls(instances)
            # remove itself
            self.friends.remove(
                    ('Bianchi modular form {}'.format(self.label), '/' + url))
            self.friends.append(('L-function', '/L/'+url))
            
        else:
            # old code
            if self.dimension == 1:
                if self.ec_status == 'exists':
                    self.friends += [('Isogeny class {}'.format(self.label), self.ec_url)]
                elif self.ec_status == 'missing':
                    self.friends += [('Isogeny class {} missing'.format(self.label), "")]
                else:
                    self.friends += [('No elliptic curve', "")]

            self.friends += [ ('L-function not available','')]
Ejemplo n.º 7
0
    def make_form(self):
        # To start with the data fields of self are just those from
        # the database.  We need to reformat these and compute some
        # further (easy) data about it.
        #
        from lmfdb.ecnf.WebEllipticCurve import FIELD
        self.field = FIELD(self.field_label)
        pretty_field = field_pretty(self.field_label)
        self.field_knowl = nf_display_knowl(self.field_label, pretty_field)
        try:
            dims = db.bmf_dims.lucky(
                {
                    'field_label': self.field_label,
                    'level_label': self.level_label
                },
                projection='gl2_dims')
            self.newspace_dimension = dims[str(self.weight)]['new_dim']
        except TypeError:
            self.newspace_dimension = 'not available'
        self.newspace_label = "-".join([self.field_label, self.level_label])
        self.newspace_url = url_for(".render_bmf_space_webpage",
                                    field_label=self.field_label,
                                    level_label=self.level_label)
        K = self.field.K()

        if self.dimension > 1:
            Qx = PolynomialRing(QQ, 'x')
            self.hecke_poly = Qx(str(self.hecke_poly))
            F = NumberField(self.hecke_poly, 'z')
            self.hecke_poly = web_latex(self.hecke_poly)

            def conv(ap):
                if '?' in ap:
                    return 'not known'
                else:
                    return F(str(ap))

            self.hecke_eigs = [conv(str(ap)) for ap in self.hecke_eigs]

        self.nap = len(self.hecke_eigs)
        self.nap0 = min(50, self.nap)
        self.hecke_table = [[
            web_latex(p.norm()),
            ideal_label(p),
            web_latex(p.gens_reduced()[0]),
            web_latex(ap)
        ] for p, ap in zip(primes_iter(K), self.hecke_eigs[:self.nap0])]
        level = ideal_from_label(K, self.level_label)
        self.level_ideal2 = web_latex(level)
        badp = level.prime_factors()
        self.have_AL = self.AL_eigs[0] != '?'
        if self.have_AL:
            self.AL_table = [[
                web_latex(p.norm()),
                ideal_label(p),
                web_latex(p.gens_reduced()[0]),
                web_latex(ap)
            ] for p, ap in zip(badp, self.AL_eigs)]
        self.sign = 'not determined'
        if self.sfe == 1:
            self.sign = "+1"
        elif self.sfe == -1:
            self.sign = "-1"

        if self.Lratio == '?':
            self.Lratio = "not determined"
            self.anrank = "not determined"
        else:
            self.Lratio = QQ(self.Lratio)
            self.anrank = "\(0\)" if self.Lratio != 0 else "odd" if self.sfe == -1 else "\(\ge2\), even"

        self.properties2 = [('Base field', pretty_field),
                            ('Weight', str(self.weight)),
                            ('Level norm', str(self.level_norm)),
                            ('Level', self.level_ideal2),
                            ('Label', self.label),
                            ('Dimension', str(self.dimension))]

        if self.CM == '?':
            self.CM = 'not determined'
        elif self.CM == 0:
            self.CM = 'no'
        self.properties2.append(('CM', str(self.CM)))

        self.bc_extra = ''
        self.bcd = 0
        self.bct = self.bc != '?' and self.bc != 0
        if self.bc == '?':
            self.bc = 'not determined'
        elif self.bc == 0:
            self.bc = 'no'
        elif self.bc == 1:
            self.bcd = self.bc
            self.bc = 'yes'
        elif self.bc > 1:
            self.bcd = self.bc
            self.bc = 'yes'
            self.bc_extra = ', of a form over \(\mathbb{Q}\) with coefficients in \(\mathbb{Q}(\sqrt{' + str(
                self.bcd) + '})\)'
        elif self.bc == -1:
            self.bc = 'no'
            self.bc_extra = ', but is a twist of the base-change of a form over \(\mathbb{Q}\)'
        elif self.bc < -1:
            self.bcd = -self.bc
            self.bc = 'no'
            self.bc_extra = ', but is a twist of the base-change of a form over \(\mathbb{Q}\) with coefficients in \(\mathbb{Q}(\sqrt{' + str(
                self.bcd) + '})\)'
        self.properties2.append(('Base-change', str(self.bc)))

        curve_bc = db.ec_nfcurves.lucky({'class_label': self.label},
                                        projection="base_change")
        if curve_bc is not None:
            self.ec_status = 'exists'
            self.ec_url = url_for("ecnf.show_ecnf_isoclass",
                                  nf=self.field_label,
                                  conductor_label=self.level_label,
                                  class_label=self.label_suffix)
            curve_bc_parts = [split_lmfdb_label(lab) for lab in curve_bc]
            bc_urls = [
                url_for("emf.render_elliptic_modular_forms",
                        level=cond,
                        weight=2,
                        character=1,
                        label=iso) for cond, iso, num in curve_bc_parts
            ]
            bc_labels = [
                newform_label(cond, 2, 1, iso)
                for cond, iso, num in curve_bc_parts
            ]
            bc_exists = [is_newform_in_db(lab) for lab in bc_labels]
            self.bc_forms = [{
                'exists': ex,
                'label': lab,
                'url': url
            } for ex, lab, url in zip(bc_exists, bc_labels, bc_urls)]
        else:
            self.bc_forms = []
            if self.bct:
                self.ec_status = 'none'
            else:
                self.ec_status = 'missing'

        self.properties2.append(('Sign', self.sign))
        self.properties2.append(('Analytic rank', self.anrank))

        self.friends = []
        if self.dimension == 1:
            if self.ec_status == 'exists':
                self.friends += [
                    ('Elliptic curve isogeny class {}'.format(self.label),
                     self.ec_url)
                ]
            elif self.ec_status == 'missing':
                self.friends += [
                    ('Elliptic curve {} missing'.format(self.label), "")
                ]
            else:
                self.friends += [('No elliptic curve', "")]

        self.friends += [('Newspace {}'.format(self.newspace_label),
                          self.newspace_url)]
        self.friends += [('L-function not available', '')]
Ejemplo n.º 8
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', '')]
Ejemplo n.º 9
0
    def make_form(self):
        # To start with the data fields of self are just those from
        # the database.  We need to reformat these and compute some
        # further (easy) data about it.
        #
        from lmfdb.ecnf.WebEllipticCurve import FIELD
        self.field = FIELD(self.field_label)
        pretty_field = field_pretty(self.field_label)
        self.field_knowl = nf_display_knowl(self.field_label, getDBConnection(), pretty_field)
        try:
            dims = db_dims().find_one({'field_label':self.field_label, 'level_label':self.level_label})['gl2_dims']
            self.newspace_dimension = dims[str(self.weight)]['new_dim']
        except TypeError:
            self.newspace_dimension = 'not available'
        self.newspace_label = "-".join([self.field_label,self.level_label])
        self.newspace_url = url_for(".render_bmf_space_webpage", field_label=self.field_label, level_label=self.level_label)
        K = self.field.K()

        if self.dimension>1:
            Qx = PolynomialRing(QQ,'x')
            self.hecke_poly = Qx(str(self.hecke_poly))
            F = NumberField(self.hecke_poly,'z')
            self.hecke_poly = web_latex(self.hecke_poly)
            def conv(ap):
                if '?' in ap:
                    return 'not known'
                else:
                    return F(str(ap))
            self.hecke_eigs = [conv(str(ap)) for ap in self.hecke_eigs]

        self.nap = len(self.hecke_eigs)
        self.nap0 = min(50, self.nap)
        self.hecke_table = [[web_latex(p.norm()),
                             ideal_label(p),
                             web_latex(p.gens_reduced()[0]),
                             web_latex(ap)] for p,ap in zip(primes_iter(K), self.hecke_eigs[:self.nap0])]
        level = ideal_from_label(K,self.level_label)
        self.level_ideal2 = web_latex(level)
        badp = level.prime_factors()
        self.have_AL = self.AL_eigs[0]!='?'
        if self.have_AL:
            self.AL_table = [[web_latex(p.norm()),
                             ideal_label(p),
                              web_latex(p.gens_reduced()[0]),
                              web_latex(ap)] for p,ap in zip(badp, self.AL_eigs)]
        self.sign = 'not determined'
        if self.sfe == 1:
            self.sign = "+1"
        elif self.sfe == -1:
            self.sign = "-1"

        if self.Lratio == '?':
            self.Lratio = "not determined"
            self.anrank = "not determined"
        else:
            self.Lratio = QQ(self.Lratio)
            self.anrank = "\(0\)" if self.Lratio!=0 else "odd" if self.sfe==-1 else "\(\ge2\), even"

        self.properties2 = [('Base field', pretty_field),
                            ('Weight', str(self.weight)),
                            ('Level norm', str(self.level_norm)),
                            ('Level', self.level_ideal2),
                            ('Label', self.label),
                            ('Dimension', str(self.dimension))
        ]

        if self.CM == '?':
            self.CM = 'not determined'
        elif self.CM == 0:
            self.CM = 'no'
        self.properties2.append(('CM', str(self.CM)))

        self.bc_extra = ''
        self.bcd = 0
        self.bct = self.bc!='?' and self.bc!=0
        if self.bc == '?':
            self.bc = 'not determined'
        elif self.bc == 0:
            self.bc = 'no'
        elif self.bc == 1:
            self.bcd = self.bc
            self.bc = 'yes'
        elif self.bc >1:
            self.bcd = self.bc
            self.bc = 'yes'
            self.bc_extra = ', of a form over \(\mathbb{Q}\) with coefficients in \(\mathbb{Q}(\sqrt{'+str(self.bcd)+'})\)'
        elif self.bc == -1:
            self.bc = 'no'
            self.bc_extra = ', but is a twist of the base-change of a form over \(\mathbb{Q}\)'
        elif self.bc < -1:
            self.bcd = -self.bc
            self.bc = 'no'
            self.bc_extra = ', but is a twist of the base-change of a form over \(\mathbb{Q}\) with coefficients in \(\mathbb{Q}(\sqrt{'+str(self.bcd)+'})\)'
        self.properties2.append(('Base-change', str(self.bc)))

        curve = db_ecnf().find_one({'class_label':self.label})
        if curve:
            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 = curve['base_change']
            curve_bc_parts = [split_lmfdb_label(lab) for lab in curve_bc]
            bc_urls = [url_for("emf.render_elliptic_modular_forms", level=cond, weight=2, character=1, label=iso) for cond, iso, num in curve_bc_parts]
            bc_labels = [newform_label(cond,2,1,iso) for cond,iso,num in curve_bc_parts]
            bc_exists = [is_newform_in_db(lab) for lab in bc_labels]
            self.bc_forms = [{'exists':ex, 'label':lab, 'url':url} for ex,lab,url in zip(bc_exists, bc_labels, bc_urls)]
        else:
            self.bc_forms = []
            if self.bct:
                self.ec_status = 'none'
            else:
                self.ec_status = 'missing'

        self.properties2.append(('Sign', self.sign))
        self.properties2.append(('Analytic rank', self.anrank))

        self.friends = []
        if self.dimension==1:
            if self.ec_status == 'exists':
                self.friends += [('Elliptic curve isogeny class {}'.format(self.label), self.ec_url)]
            elif self.ec_status == 'missing':
                self.friends += [('Elliptic curve {} missing'.format(self.label), "")]
            else:
                self.friends += [('No elliptic curve', "")]

        self.friends += [ ('Newspace {}'.format(self.newspace_label),self.newspace_url)]
        self.friends += [ ('L-function not available','')]