Ejemplo n.º 1
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.º 2
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','')]
Ejemplo n.º 3
0
    def make_class(self):
        self.ainvs_str = self.ainvs
        self.ainvs = [int(a) for a in self.ainvs_str]
        self.E = EllipticCurve(self.ainvs)
        self.CM = self.E.has_cm()

        try:
            # Extract the isogeny degree matrix from the database
            size = len(self.isogeny_matrix)
            from sage.matrix.all import Matrix
            self.isogeny_matrix = Matrix(self.isogeny_matrix)
        except AttributeError:
            # Failsafe: construct it from scratch
            self.isogeny_matrix = self.E.isogeny_class(order="lmfdb").matrix()
            size = self.isogeny_matrix.nrows()
        self.ncurves = size

        # Create isogeny graph:
        self.graph = make_graph(self.isogeny_matrix)
        P = self.graph.plot(edge_labels=True)
        self.graph_img = encode_plot(P)
        self.graph_link = '<img src="%s" width="200" height="150"/>' % self.graph_img

        # Create a list of the curves in the class from the database
        self.db_curves = [self.E]
        self.optimal_flags = [False] * size
        self.degrees = [0] * size
        if self.degree:
            self.degrees[0] = self.degree
        else:
            try:
                self.degrees[0] = self.E.modular_degree()
            except RuntimeError:
                pass

        # Fill in the curves in the class by looking each one up in the db:

        self.cremona_labels = [self.label] + [0] * (size - 1)
        if self.number == 1:
            self.optimal_flags[0] = True
        for i in range(2, size + 1):
            Edata = db_ec().find_one({'lmfdb_label': self.lmfdb_iso + str(i)})
            Ei = EllipticCurve([int(a) for a in Edata['ainvs']])
            self.cremona_labels[i - 1] = Edata['label']
            if Edata['number'] == 1:
                self.optimal_flags[i - 1] = True
            if 'degree' in Edata:
                self.degrees[i - 1] = Edata['degree']
            else:
                try:
                    self.degrees[i - 1] = Ei.modular_degree()
                except RuntimeError:
                    pass
            self.db_curves.append(Ei)

        if self.iso == '990h':  # this isogeny class is labeled wrong in Cremona's tables
            self.optimal_flags = [False, False, True, False]

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

        N, iso, number = split_lmfdb_label(self.lmfdb_iso)

        self.newform = web_latex(self.E.q_eigenform(10))
        self.newform_label = newform_label(N, 2, 1, iso)
        self.newform_link = url_for("emf.render_elliptic_modular_forms",
                                    level=N,
                                    weight=2,
                                    character=1,
                                    label=iso)
        newform_exists_in_db = is_newform_in_db(self.newform_label)

        self.lfunction_link = url_for("l_functions.l_function_ec_page",
                                      label=self.lmfdb_iso)

        self.curves = [
            dict([('label', self.lmfdb_iso + str(i + 1)),
                  ('url',
                   url_for(".by_triple_label",
                           conductor=N,
                           iso_label=iso,
                           number=i + 1)),
                  ('cremona_label', self.cremona_labels[i]),
                  ('ainvs', str(list(c.ainvs()))),
                  ('torsion', c.torsion_order()), ('degree', self.degrees[i]),
                  ('optimal', self.optimal_flags[i])])
            for i, c in enumerate(self.db_curves)
        ]

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

        self.properties = [('Label', self.lmfdb_iso),
                           ('Number of curves', str(self.ncurves)),
                           ('Conductor', '\(%s\)' % N), ('CM', '%s' % self.CM),
                           ('Rank', '\(%s\)' % self.rank), ('Graph', ''),
                           (None, self.graph_link)]

        self.downloads = [('Download coefficients of newform',
                           url_for(".download_EC_qexp",
                                   label=self.lmfdb_iso,
                                   limit=100)),
                          ('Download stored data for all curves',
                           url_for(".download_EC_all", label=self.lmfdb_iso))]

        if self.lmfdb_iso == self.iso:
            self.title = "Elliptic Curve Isogeny Class %s" % self.lmfdb_iso
        else:
            self.title = "Elliptic Curve Isogeny Class %s (Cremona label %s)" % (
                self.lmfdb_iso, self.iso)

        self.bread = [('Elliptic Curves', url_for("ecnf.index")),
                      ('$\Q$', url_for(".rational_elliptic_curves")),
                      ('%s' % N, url_for(".by_conductor", conductor=N)),
                      ('%s' % iso, ' ')]
Ejemplo n.º 4
0
    def __init__(self, level=1, weight=12, character=1, label='a', prec=0, parent=None, update_from_db=True,**kwargs):
        emf_logger.debug("In WebNewForm {0}".format((level,weight,character,label,parent,update_from_db)))
        if isinstance(level,basestring) or kwargs.has_key('hecke_orbit_label'):
            hecke_orbit_label = kwargs.get('hecke_orbit_label', level)
            level,weight,character,label = parse_newform_label(hecke_orbit_label)
        self._reduction = (type(self),(level,weight,character,label),{'parent':parent,'update_from_db':update_from_db})
        if isinstance(character, WebChar):
            character_number = character.number
        else:
            character_number = character
            character = None if parent is None else parent.character
            if not isinstance(label,basestring):
                if isinstance(label,(int,Integer)):
                    label = cremona_letter_code(label)
                else:
                    raise ValueError,"Need label either string or integer! We got:{0}".format(label)

        emf_logger.debug("Before init properties 0")
        self._properties = WebProperties(
            WebInt('level', value=level),
            WebInt('weight', value=weight),
            WebCharProperty('character', modulus=level,
                            number=character_number,
                            value = character,
                            include_in_update = True if character is None
                            else False),
            WebStr('character_naming_scheme', value='Conrey'),
            WebStr('sage_version', value=''),
            WebStr('hecke_orbit_label', default_value=newform_label(level, weight, character_number, label)),
            WebStr('label', default_value=label),
            WebInt('dimension'),
            WebqExp('q_expansion'),
            WebCoeffs('_coefficients'),
            WebDict('_embeddings'),
            WebInt('prec',value=0, save_to_db=False, save_to_fs=True), 
            WebNumberField('base_ring'),
            WebNumberField('coefficient_field'),
            WebInt('coefficient_field_degree'),
            WebList('twist_info', required = False),
            WebInt('is_cm', required = False),
            WebInt('cm_disc', required = False, default_value=0),
            WebDict('_cm_values',required=False),
            WebBool('is_cuspidal',default_value=True),
            WebDict('satake', required=False),
            WebDict('_atkin_lehner_eigenvalues', required=False),
            WebBool('is_rational'),
            WebPoly('absolute_polynomial'),
            WebFloat('version', value=float(emf_version), save_to_fs=True),
            WebDict('explicit_formulas',required=False),
            WebDate('creation_date',value=None),
            WebModFormSpaceProperty('parent', value=parent,
                                    level = level,
                                    weight = weight,
                                    character = character_number,
                                    update_hecke_orbits=False,
                                    update_from_db=update_from_db)
#                                    include_in_update = True if parent is None
#                                    else False),
            )

        self._add_to_fs_query = {'prec': {'$gt': int(prec-1)}}

        super(WebNewForm, self).__init__(
            update_from_db=update_from_db,
            **kwargs
            )

        self._add_to_fs_query = {'prec': {'$gt': int(self.prec-1)}}
        
        # We're setting the WebEigenvalues property after calling __init__ of the base class
        # because it will set hecke_orbit_label from the db first

        ## 
        ## We don't init the eigenvalues (since E*v is slow)
        ## unless we (later) request a coefficient which is not
        ## in self._coefficients
        
        self.eigenvalues = WebEigenvalues(self.hecke_orbit_label, prec = self.prec, \
                                              init_dynamic_properties=False, \
                                              update_from_db = False)

        self.make_code_snippets()
Ejemplo n.º 5
0
    def __init__(self,
                 level=1,
                 weight=12,
                 character=1,
                 label='a',
                 prec=None,
                 parent=None,
                 update_from_db=True):
        emf_logger.critical("In WebNewForm {0}".format(
            (level, weight, character, label, parent, update_from_db)))
        self._reduction = (type(self), (level, weight, character, label), {
            'parent': parent,
            'update_from_db': update_from_db
        })
        if isinstance(character, WebChar):
            character_number = character.number
        else:
            character_number = character
            character = None if parent is None else parent.character
            if not isinstance(label, basestring):
                if isinstance(label, (int, Integer)):
                    label = orbit_label(label)
                else:
                    raise ValueError, "Need label either string or integer! We got:{0}".format(
                        label)

        emf_logger.critical("Before init properties 0")
        self._properties = WebProperties(
            WebInt('level', value=level), WebInt('weight', value=weight),
            WebCharProperty(
                'character',
                modulus=level,
                number=character_number,
                value=character,
                include_in_update=True if character is None else False),
            WebStr('character_naming_scheme', value='Conrey'),
            WebStr('hecke_orbit_label',
                   default_value=newform_label(level, weight, character_number,
                                               label)),
            WebStr('label', default_value=label), WebInt('dimension'),
            WebqExp('q_expansion'), WebDict('_coefficients'),
            WebDict('_embeddings'), WebInt('prec', value=0),
            WebNumberField('base_ring'), WebNumberField('coefficient_field'),
            WebInt('coefficient_field_degree'),
            WebList('twist_info', required=False),
            WebBool('is_cm', required=False),
            WebDict('_cm_values', required=False),
            WebBool('is_cuspidal', default_value=True),
            WebDict('satake', required=False),
            WebDict('_atkin_lehner_eigenvalues', required=False),
            WebBool('is_rational'), WebPoly('absolute_polynomial'),
            WebFloat('version', value=float(emf_version), save_to_fs=True),
            WebDict('explicit_formulas', required=False),
            WebModFormSpaceProperty('parent',
                                    value=parent,
                                    level=level,
                                    weight=weight,
                                    character=character_number,
                                    update_hecke_orbits=False)
            #                                    include_in_update = True if parent is None
            #                                    else False),
        )
        emf_logger.critical("After init properties 1")
        super(WebNewForm, self).__init__(update_from_db=update_from_db)
        emf_logger.critical("After init properties 2 prec={0}".format(
            self.prec))
        # We're setting the WebEigenvalues property after calling __init__ of the base class
        # because it will set hecke_orbit_label from the db first

        ##
        ## We don't init the eigenvalues (since E*v is slow)
        ## unless we (later) request a coefficient which is not
        ## in self._coefficients

        self.eigenvalues = WebEigenvalues(self.hecke_orbit_label,
                                          prec=self.prec,
                                          init_dynamic_properties=False)
        emf_logger.critical("After init properties 3")
Ejemplo n.º 6
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 = {}
        try:
            data['ainvs'] = [int(c) for c in self.xainvs[1:-1].split(',')]
        except AttributeError:
            data['ainvs'] = [int(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_str'] = unicode(str(data['j_invariant']))
        data['j_inv_latex'] = web_latex(data['j_invariant'])
        mw = self.mw = {}
        mw['rank'] = self.rank
        mw['int_points'] = ''
        if self.xintcoords:
            a1, a2, a3, a4, a6 = [ZZ(a) for a in data['ainvs']]

            def lift_x(x):
                f = ((x + a2) * x + a4) * x + a6
                b = (a1 * x + a3)
                d = (b * b + 4 * f).sqrt()
                return (x, (-b + d) / 2)

            mw['int_points'] = ', '.join(
                web_latex(lift_x(x)) for x in self.xintcoords)

        mw['generators'] = ''
        mw['heights'] = []
        if self.gens:
            mw['generators'] = [
                web_latex(tuple(P)) for P in parse_points(self.gens)
            ]

        mw['tor_order'] = self.torsion
        tor_struct = [int(c) for c in self.torsion_structure]
        if mw['tor_order'] == 1:
            mw['tor_struct'] = '\mathrm{Trivial}'
            mw['tor_gens'] = ''
        else:
            mw['tor_struct'] = ' \\times '.join(
                ['\Z/{%s}\Z' % n for n in tor_struct])
            mw['tor_gens'] = ', '.join(
                web_latex(tuple(P))
                for P in parse_points(self.torsion_generators))

        # try to get all the data we need from the database entry (now in self)
        try:
            data['equation'] = self.equation
            local_data = self.local_data
            D = self.signD * prod(
                [ld['p']**ld['ord_disc'] for ld in local_data])
            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']
            minq_label = self.min_quad_twist['label']
            data['minq_label'] = db_ec().find_one(
                {'label': minq_label}, ['lmfdb_label'])['lmfdb_label']
            data['minq_info'] = '(itself)' if minqD == 1 else '(by %s)' % minqD
            try:
                data['degree'] = self.degree
            except AttributeError:
                data['degree'] = 0  # invalid, but will be displayed nicely
            mw['heights'] = self.heights
            if self.number == 1:
                data['an'] = self.anlist
                data['ap'] = self.aplist
            else:
                r = db_ec().find_one({
                    'lmfdb_iso': self.lmfdb_iso,
                    'number': 1
                }, ['anlist', 'aplist'])
                data['an'] = r['anlist']
                data['ap'] = r['aplist']

        # otherwise fall back to computing it from the curve
        except AttributeError:
            print("Falling back to constructing E")
            self.E = EllipticCurve(data['ainvs'])
            data['equation'] = web_latex(self.E)
            data['disc'] = D = self.E.discriminant()
            Nfac = N.factor()
            Dfac = D.factor()
            bad_primes = [p for p, e in Nfac]
            try:
                data['degree'] = self.degree
            except AttributeError:
                try:
                    data['degree'] = self.E.modular_degree()
                except RuntimeError:
                    data['degree'] = 0  # invalid, but will be displayed nicely
            minq, minqD = self.E.minimal_quadratic_twist()
            data['minq_D'] = minqD
            if minqD == 1:
                data['minq_label'] = self.lmfdb_label
                data['minq_info'] = '(itself)'
            else:
                # This relies on the minimal twist being in the
                # database, which is true when the database only
                # contains the Cremona database.  It would be a good
                # idea if, when the database is extended, we ensured
                # that for any curve included, all twists of smaller
                # conductor are also included.
                minq_ainvs = [str(c) for c in minq.ainvs()]
                data['minq_label'] = db_ec().find_one(
                    {
                        'jinv': str(self.E.j_invariant()),
                        'ainvs': minq_ainvs
                    }, ['lmfdb_label'])['lmfdb_label']
                data['minq_info'] = '(by %s)' % minqD

            if self.gens:
                self.generators = [self.E(g) for g in parse_points(self.gens)]
                mw['heights'] = [P.height() for P in self.generators]

            data['an'] = self.E.anlist(20, python_ints=True)
            data['ap'] = self.E.aplist(100, python_ints=True)
            self.local_data = local_data = []
            for p in bad_primes:
                ld = self.E.local_data(p, algorithm="generic")
                local_data_p = {}
                local_data_p['p'] = p
                local_data_p['cp'] = ld.tamagawa_number()
                local_data_p['kod'] = web_latex(ld.kodaira_symbol()).replace(
                    '$', '')
                local_data_p['red'] = ld.bad_reduction_type()
                rootno = -ld.bad_reduction_type()
                if rootno == 0:
                    rootno = self.E.root_number(p)
                local_data_p['rootno'] = rootno
                local_data_p['ord_cond'] = ld.conductor_valuation()
                local_data_p['ord_disc'] = ld.discriminant_valuation()
                local_data_p['ord_den_j'] = max(
                    0, -self.E.j_invariant().valuation(p))
                local_data.append(local_data_p)

        # If we got the data from the database, the root numbers may
        # not have been stored there, so we have to compute them.  If
        # there are additive primes this means constructing the curve.
        for ld in self.local_data:
            if not 'rootno' in ld:
                rootno = -ld['red']
                if rootno == 0:
                    try:
                        E = self.E
                    except AttributeError:
                        self.E = E = EllipticCurve(data['ainvs'])
                    rootno = E.root_number(ld['p'])
                ld['rootno'] = rootno

        minq_N, minq_iso, minq_number = split_lmfdb_label(data['minq_label'])

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

        data['CMD'] = self.cm
        data['CM'] = "no"
        data['EndE'] = "\(\Z\)"
        if self.cm:
            data['CM'] = "yes (\(D=%s\))" % data['CMD']
            if data['CMD'] % 4 == 0:
                d4 = ZZ(data['CMD']) // 4
                data['EndE'] = "\(\Z[\sqrt{%s}]\)" % d4
            else:
                data['EndE'] = "\(\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
        ]

        try:
            data['galois_images'] = [
                trim_galois_image_code(s) for s in self.galois_images
            ]
            data['non_surjective_primes'] = self.non_surjective_primes
        except AttributeError:
            #print "No Galois image data"
            data['galois_images'] = []
            data['non_surjective_primes'] = []

        data['galois_data'] = [{
            'p': p,
            'image': im
        } for p, im in zip(data['non_surjective_primes'],
                           data['galois_images'])]

        cond, iso, num = split_lmfdb_label(self.lmfdb_label)
        self.class_url = url_for(".by_double_iso_label",
                                 conductor=N,
                                 iso_label=iso)
        self.ncurves = db_ec().count({'lmfdb_iso': self.lmfdb_iso})
        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 & BSD data
        bsd = self.bsd = {}
        r = self.rank
        if r >= 2:
            bsd['lder_name'] = "L^{(%s)}(E,1)/%s!" % (r, r)
        elif r:
            bsd['lder_name'] = "L'(E,1)"
        else:
            bsd['lder_name'] = "L(E,1)"

        bsd['reg'] = self.regulator
        bsd['omega'] = self.real_period
        bsd['sha'] = int(0.1 + self.sha_an)
        bsd['lder'] = self.special_value

        # 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)

        if self.iso == '990h':
            data['Gamma0optimal'] = bool(self.number == 3)
        else:
            data['Gamma0optimal'] = bool(self.number == 1)

        data['p_adic_data_exists'] = False
        if data['Gamma0optimal']:
            data['p_adic_data_exists'] = (padic_db().find({
                'lmfdb_iso':
                self.lmfdb_iso
            }).count()) > 0

        tamagawa_numbers = [ZZ(ld['cp']) for ld in local_data]
        cp_fac = [cp.factor() for cp in tamagawa_numbers]
        cp_fac = [
            latex(cp) if len(cp) < 2 else '(' + latex(cp) + ')'
            for cp in cp_fac
        ]
        bsd['tamagawa_factors'] = r'\cdot'.join(cp_fac)
        bsd['tamagawa_product'] = prod(tamagawa_numbers)

        data['newform'] = web_latex(
            PowerSeriesRing(QQ, 'q')(data['an'], 20, check=True))
        data['newform_label'] = self.newform_label = newform_label(
            cond, 2, 1, iso)
        self.newform_link = url_for("emf.render_elliptic_modular_forms",
                                    level=cond,
                                    weight=2,
                                    character=1,
                                    label=iso)
        self.newform_exists_in_db = is_newform_in_db(self.newform_label)
        self._code = None

        self.class_url = url_for(".by_double_iso_label",
                                 conductor=N,
                                 iso_label=iso)
        self.friends = [('Isogeny class ' + self.lmfdb_iso, self.class_url),
                        ('Minimal quadratic twist %s %s' %
                         (data['minq_info'], data['minq_label']),
                         url_for(".by_triple_label",
                                 conductor=minq_N,
                                 iso_label=minq_iso,
                                 number=minq_number)),
                        ('All twists ',
                         url_for(".rational_elliptic_curves", jinv=self.jinv)),
                        ('L-function',
                         url_for("l_functions.l_function_ec_page",
                                 label=self.lmfdb_label))]
        if not self.cm:
            if N <= 300:
                self.friends += [('Symmetric square L-function',
                                  url_for("l_functions.l_function_ec_sym_page",
                                          power='2',
                                          label=self.lmfdb_iso))]
            if N <= 50:
                self.friends += [('Symmetric cube L-function',
                                  url_for("l_functions.l_function_ec_sym_page",
                                          power='3',
                                          label=self.lmfdb_iso))]
        if self.newform_exists_in_db:
            self.friends += [('Modular form ' + self.newform_label,
                              self.newform_link)]

        self.downloads = [('Download coefficients of q-expansion',
                           url_for(".download_EC_qexp",
                                   label=self.lmfdb_label,
                                   limit=1000)),
                          ('Download all stored data',
                           url_for(".download_EC_all",
                                   label=self.lmfdb_label)),
                          ('Download Magma code',
                           url_for(".ec_code_download",
                                   conductor=cond,
                                   iso=iso,
                                   number=num,
                                   label=self.lmfdb_label,
                                   download_type='magma')),
                          ('Download Sage code',
                           url_for(".ec_code_download",
                                   conductor=cond,
                                   iso=iso,
                                   number=num,
                                   label=self.lmfdb_label,
                                   download_type='sage')),
                          ('Download GP code',
                           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 = '<img src="%s" width="200" height="150"/>' % self.plot
        self.properties = [('Label', self.lmfdb_label), (None, self.plot_link),
                           ('Conductor', '\(%s\)' % data['conductor']),
                           ('Discriminant', '\(%s\)' % data['disc']),
                           ('j-invariant', '%s' % data['j_inv_latex']),
                           ('CM', '%s' % data['CM']),
                           ('Rank', '\(%s\)' % mw['rank']),
                           ('Torsion Structure', '\(%s\)' % mw['tor_struct'])]

        self.title = "Elliptic Curve %s (Cremona label %s)" % (
            self.lmfdb_label, self.label)

        self.bread = [('Elliptic Curves', url_for("ecnf.index")),
                      ('$\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, ' ')]
Ejemplo n.º 7
0
    def make_curve(self):
        # To start with the data fields of self are just those from
        # the database.  We need to reformat these, construct the
        # actual elliptic curve E, and compute some further (easy)
        # data about it.
        #

        # Weierstrass equation

        data = self.data = {}
        data['ainvs'] = [int(ai) for ai in self.ainvs]
        self.E = EllipticCurve(data['ainvs'])
        data['equation'] = web_latex(self.E)

        # conductor, j-invariant and discriminant

        data['conductor'] = N = ZZ(self.conductor)
        bad_primes = N.prime_factors()
        try:
            data['j_invariant'] = QQ(str(self.jinv))
        except KeyError:
            data['j_invariant'] = self.E.j_invariant()
        data['j_inv_factor'] = latex(0)
        if data['j_invariant']:
            data['j_inv_factor'] = latex(data['j_invariant'].factor())
        data['j_inv_str'] = unicode(str(data['j_invariant']))
        data['j_inv_latex'] = web_latex(data['j_invariant'])
        data['disc'] = D = self.E.discriminant()
        data['disc_latex'] = web_latex(data['disc'])
        data['disc_factor'] = latex(data['disc'].factor())
        data['cond_factor'] = latex(N.factor())
        data['cond_latex'] = web_latex(N)

        # CM and endomorphism ring

        data['CMD'] = self.cm
        data['CM'] = "no"
        data['EndE'] = "\(\Z\)"
        if self.cm:
            data['CM'] = "yes (\(D=%s\))" % data['CMD']
            if data['CMD'] % 4 == 0:
                d4 = ZZ(data['CMD']) // 4
                data['EndE'] = "\(\Z[\sqrt{%s}]\)" % d4
            else:
                data['EndE'] = "\(\Z[(1+\sqrt{%s})/2]\)" % data['CMD']
            data['ST'] = '<a href="%s">$%s$</a>' % (url_for(
                'st.by_label', label='1.2.N(U(1))'), 'N(\\mathrm{U}(1))')
        else:
            data['ST'] = '<a href="%s">$%s$</a>' % (url_for(
                'st.by_label', label='1.2.SU(2)'), '\\mathrm{SU}(2)')

        # modular degree

        try:
            data['degree'] = self.degree
        except AttributeError:
            try:
                data['degree'] = self.E.modular_degree()
            except RuntimeError:
                data['degree']  # invalid, but will be displayed nicely

        # Minimal quadratic twist

        E_pari = self.E.pari_curve()
        from sage.libs.pari.all import PariError
        try:
            minq, minqD = self.E.minimal_quadratic_twist()
        except PariError:  # this does occur with 164411a1
            ec.debug(
                "PariError computing minimal quadratic twist of elliptic curve %s"
                % lmfdb_label)
            minq = self.E
            minqD = 1
        data['minq_D'] = minqD
        if self.E == minq:
            data['minq_label'] = self.lmfdb_label
            data['minq_info'] = '(itself)'
        else:
            minq_ainvs = [str(c) for c in minq.ainvs()]
            data['minq_label'] = db_ec().find_one({
                'jinv':
                str(self.E.j_invariant()),
                'ainvs':
                minq_ainvs
            })['lmfdb_label']
            data['minq_info'] = '(by %s)' % minqD

        minq_N, minq_iso, minq_number = split_lmfdb_label(data['minq_label'])

        # rational and integral points

        mw = self.mw = {}

        xintpoints_projective = [self.E.lift_x(x) for x in self.xintcoords]
        xintpoints = [P.xy() for P in xintpoints_projective]
        mw['int_points'] = ', '.join(web_latex(P) for P in xintpoints)

        # Generators of infinite order

        mw['rank'] = self.rank
        try:
            self.generators = [self.E(g) for g in parse_points(self.gens)]
            mw['generators'] = [web_latex(P.xy()) for P in self.generators]
            mw['heights'] = [P.height() for P in self.generators]
        except AttributeError:
            mw['generators'] = ''
            mw['heights'] = []

        # Torsion subgroup: order, structure, generators

        mw['tor_order'] = self.torsion
        tor_struct = [int(c) for c in self.torsion_structure]
        if mw['tor_order'] == 1:
            mw['tor_struct'] = '\mathrm{Trivial}'
            mw['tor_gens'] = ''
        else:
            mw['tor_struct'] = ' \\times '.join(
                ['\Z/{%s}\Z' % n for n in tor_struct])
            mw['tor_gens'] = ', '.join(
                web_latex(self.E(g).xy())
                for g in parse_points(self.torsion_generators))

        # Images of Galois representations

        try:
            data['galois_images'] = [
                trim_galois_image_code(s) for s in self.galois_images
            ]
            data['non_surjective_primes'] = self.non_surjective_primes
        except AttributeError:
            #print "No Galois image data"
            data['galois_images'] = []
            data['non_surjective_primes'] = []

        data['galois_data'] = [{
            'p': p,
            'image': im
        } for p, im in zip(data['non_surjective_primes'],
                           data['galois_images'])]

        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 & BSD data

        bsd = self.bsd = {}

        r = self.rank
        if r >= 2:
            bsd['lder_name'] = "L^{(%s)}(E,1)/%s!" % (r, r)
        elif r:
            bsd['lder_name'] = "L'(E,1)"
        else:
            bsd['lder_name'] = "L(E,1)"

        bsd['reg'] = self.regulator
        bsd['omega'] = self.real_period
        bsd['sha'] = int(0.1 + self.sha_an)
        bsd['lder'] = self.special_value

        # 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)

        if self.iso == '990h':
            data['Gamma0optimal'] = bool(self.number == 3)
        else:
            data['Gamma0optimal'] = bool(self.number == 1)

        data['p_adic_data_exists'] = False
        if data['Gamma0optimal']:
            data['p_adic_data_exists'] = (padic_db().find({
                'lmfdb_iso':
                self.lmfdb_iso
            }).count()) > 0
        data['p_adic_primes'] = [
            p for p in sage.all.prime_range(5, 100)
            if self.E.is_ordinary(p) and not p.divides(N)
        ]

        # Local data

        local_data = self.local_data = []
        # if we use E.tamagawa_numbers() it calls E.local_data(p) which
        # used to crash on some curves e.g. 164411a1
        tamagawa_numbers = []
        for p in bad_primes:
            local_info = self.E.local_data(p, algorithm="generic")
            local_data_p = {}
            local_data_p['p'] = p
            local_data_p['tamagawa_number'] = local_info.tamagawa_number()
            tamagawa_numbers.append(ZZ(local_info.tamagawa_number()))
            local_data_p['kodaira_symbol'] = web_latex(
                local_info.kodaira_symbol()).replace('$', '')
            local_data_p['reduction_type'] = local_info.bad_reduction_type()
            local_data_p['ord_cond'] = local_info.conductor_valuation()
            local_data_p['ord_disc'] = local_info.discriminant_valuation()
            local_data_p['ord_den_j'] = max(0,
                                            -self.E.j_invariant().valuation(p))
            local_data.append(local_data_p)

        cp_fac = [cp.factor() for cp in tamagawa_numbers]
        cp_fac = [
            latex(cp) if len(cp) < 2 else '(' + latex(cp) + ')'
            for cp in cp_fac
        ]
        bsd['tamagawa_factors'] = r'\cdot'.join(cp_fac)
        bsd['tamagawa_product'] = sage.misc.all.prod(tamagawa_numbers)

        cond, iso, num = split_lmfdb_label(self.lmfdb_label)
        data['newform'] = web_latex(self.E.q_eigenform(10))
        self.newform_label = newform_label(cond, 2, 1, iso)
        self.newform_link = url_for("emf.render_elliptic_modular_forms",
                                    level=cond,
                                    weight=2,
                                    character=1,
                                    label=iso)
        newform_exists_in_db = is_newform_in_db(self.newform_label)
        self._code = None

        self.friends = [('Isogeny class ' + self.lmfdb_iso,
                         url_for(".by_double_iso_label",
                                 conductor=N,
                                 iso_label=iso)),
                        ('Minimal quadratic twist %s %s' %
                         (data['minq_info'], data['minq_label']),
                         url_for(".by_triple_label",
                                 conductor=minq_N,
                                 iso_label=minq_iso,
                                 number=minq_number)),
                        ('All twists ',
                         url_for(".rational_elliptic_curves", jinv=self.jinv)),
                        ('L-function',
                         url_for("l_functions.l_function_ec_page",
                                 label=self.lmfdb_label))]
        if not self.cm:
            if N <= 300:
                self.friends += [('Symmetric square L-function',
                                  url_for("l_functions.l_function_ec_sym_page",
                                          power='2',
                                          label=self.lmfdb_iso))]
            if N <= 50:
                self.friends += [('Symmetric cube L-function',
                                  url_for("l_functions.l_function_ec_sym_page",
                                          power='3',
                                          label=self.lmfdb_iso))]
        if newform_exists_in_db:
            self.friends += [('Modular form ' + self.newform_label,
                              self.newform_link)]

        self.downloads = [('Download coefficients of q-expansion',
                           url_for(".download_EC_qexp",
                                   label=self.lmfdb_label,
                                   limit=100)),
                          ('Download all stored data',
                           url_for(".download_EC_all",
                                   label=self.lmfdb_label)),
                          ('Download Magma code',
                           url_for(".ec_code_download",
                                   conductor=cond,
                                   iso=iso,
                                   number=num,
                                   label=self.lmfdb_label,
                                   download_type='magma')),
                          ('Download Sage code',
                           url_for(".ec_code_download",
                                   conductor=cond,
                                   iso=iso,
                                   number=num,
                                   label=self.lmfdb_label,
                                   download_type='sage')),
                          ('Download GP code',
                           url_for(".ec_code_download",
                                   conductor=cond,
                                   iso=iso,
                                   number=num,
                                   label=self.lmfdb_label,
                                   download_type='gp'))]

        self.plot = encode_plot(self.E.plot())
        self.plot_link = '<img src="%s" width="200" height="150"/>' % self.plot
        self.properties = [('Label', self.lmfdb_label), (None, self.plot_link),
                           ('Conductor', '\(%s\)' % data['conductor']),
                           ('Discriminant', '\(%s\)' % data['disc']),
                           ('j-invariant', '%s' % data['j_inv_latex']),
                           ('CM', '%s' % data['CM']),
                           ('Rank', '\(%s\)' % mw['rank']),
                           ('Torsion Structure', '\(%s\)' % mw['tor_struct'])]

        self.title = "Elliptic Curve %s (Cremona label %s)" % (
            self.lmfdb_label, self.label)

        self.bread = [('Elliptic Curves', url_for("ecnf.index")),
                      ('$\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, ' ')]
Ejemplo n.º 8
0
    def make_class(self):
        self.ainvs_str = self.ainvs
        self.ainvs = [int(a) for a in self.ainvs_str]
        self.E = EllipticCurve(self.ainvs)
        self.CM = self.E.has_cm()

        try:
            # Extract the isogeny degree matrix from the database
            size = len(self.isogeny_matrix)
            from sage.matrix.all import Matrix
            self.isogeny_matrix = Matrix(self.isogeny_matrix)
        except AttributeError:
            # Failsafe: construct it from scratch
            self.isogeny_matrix = self.E.isogeny_class(order="lmfdb").matrix()
            size = self.isogeny_matrix.nrows()
        self.ncurves = size

        # Create isogeny graph:
        self.graph = make_graph(self.isogeny_matrix)
        P = self.graph.plot(edge_labels=True)
        self.graph_img = encode_plot(P)
        self.graph_link = '<img src="%s" width="200" height="150"/>' % self.graph_img

        # Create a list of the curves in the class from the database
        self.db_curves = [self.E]
        self.optimal_flags = [False] * size
        self.degrees = [0] * size
        if self.degree:
            self.degrees[0] = self.degree
        else:
            try:
                self.degrees[0] = self.E.modular_degree()
            except RuntimeError:
                pass

        # Fill in the curves in the class by looking each one up in the db:

        self.cremona_labels = [self.label] + [0] * (size - 1)
        if self.number == 1:
            self.optimal_flags[0] = True
        for i in range(2, size + 1):
            Edata = db_ec().find_one({'lmfdb_label': self.lmfdb_iso + str(i)})
            Ei = EllipticCurve([int(a) for a in Edata['ainvs']])
            self.cremona_labels[i - 1] = Edata['label']
            if Edata['number'] == 1:
                self.optimal_flags[i - 1] = True
            if 'degree' in Edata:
                self.degrees[i - 1] = Edata['degree']
            else:
                try:
                    self.degrees[i - 1] = Ei.modular_degree()
                except RuntimeError:
                    pass
            self.db_curves.append(Ei)


        if self.iso == '990h':  # this isogeny class is labeled wrong in Cremona's tables
            self.optimal_flags = [False, False, True, False]

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

        N, iso, number = split_lmfdb_label(self.lmfdb_iso)

        self.newform = web_latex(self.E.q_eigenform(10))
        self.newform_label = newform_label(N,2,1,iso)
        self.newform_link = url_for("emf.render_elliptic_modular_forms", level=N, weight=2, character=1, label=iso)
        self.newform_exists_in_db = is_newform_in_db(self.newform_label)

        self.lfunction_link = url_for("l_functions.l_function_ec_page", label=self.lmfdb_iso)

        self.curves = [dict([('label',self.lmfdb_iso + str(i + 1)),
                             ('url',url_for(".by_triple_label", conductor=N, iso_label=iso, number=i+1)),
                             ('cremona_label',self.cremona_labels[i]),
                             ('ainvs',str(list(c.ainvs()))),
                             ('torsion',c.torsion_order()),
                             ('degree',self.degrees[i]),
                             ('optimal',self.optimal_flags[i])])
                       for i, c in enumerate(self.db_curves)]

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

        self.properties = [('Label', self.lmfdb_iso),
                           ('Number of curves', str(self.ncurves)),
                           ('Conductor', '\(%s\)' % N),
                           ('CM', '%s' % self.CM),
                           ('Rank', '\(%s\)' % self.rank),
                           ('Graph', ''),(None, self.graph_link)
                           ]


        self.downloads = [('Download coefficients of newform', url_for(".download_EC_qexp", label=self.lmfdb_iso, limit=1000)),
                         ('Download stored data for all curves', url_for(".download_EC_all", label=self.lmfdb_iso))]

        if self.lmfdb_iso == self.iso:
            self.title = "Elliptic Curve Isogeny Class %s" % self.lmfdb_iso
        else:
            self.title = "Elliptic Curve Isogeny Class %s (Cremona label %s)" % (self.lmfdb_iso, self.iso)

        self.bread = [('Elliptic Curves', url_for("ecnf.index")),
                      ('$\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)'}
Ejemplo n.º 9
0
def render_elliptic_modular_forms(level=None,
                                  weight=None,
                                  character=None,
                                  label=None,
                                  group=None,
                                  **kwds):
    r"""
    Default input of same type as required. Note that for holomorphic modular forms: level=0 or weight=0 are non-existent.
    """
    emf_logger.debug(
        "In render: level={0},weight={1},character={2},group={3},label={4}".
        format(level, weight, character, group, label))
    emf_logger.debug("args={0}".format(request.args))
    emf_logger.debug("args={0}".format(request.form))
    emf_logger.debug("met={0}".format(request.method))
    keys = ['download', 'jump_to']
    info = get_args(request, level, weight, character, group, label, keys=keys)
    valid = validate_parameters(level, weight, character, label, info)
    if isinstance(valid, basestring):
        return redirect(valid, code=301)
    level = info['level']
    weight = info['weight']
    character = info['character']
    #if info.has_key('error'):
    #    return render_elliptic_modular_form_navigation_wp(error=info['error'])
    emf_logger.debug("info={0}".format(info))
    emf_logger.debug("level=%s, %s" % (level, type(level)))
    emf_logger.debug("label=%s, %s" % (label, type(label)))
    emf_logger.debug("wt=%s, %s" % (weight, type(weight)))
    group = info.get('group', None)
    emf_logger.debug("group=%s, %s" % (group, type(group)))
    if group == 0:
        info[
            'character'] = character = 1  # only trivial character for Gamma_0(N)
    try:
        if 'download' in info:
            return get_downloads(**info)
        emf_logger.debug("info=%s" % info)
        ## Consistency of arguments>
        # if level<=0:  level=None
        # if weight<=0:  weight=None
        if 'jump_to' in info:  # try to find out which form we want to jump
            s = my_get(info, 'jump_to', '', str)
            emf_logger.info("info.keys1={0}".format(info.keys()))
            info.pop('jump_to')
            emf_logger.info("info.keys2={0}".format(info.keys()))
            args = extract_data_from_jump_to(s)
            emf_logger.debug("args=%s" % args)
            return redirect(url_for("emf.render_elliptic_modular_forms",
                                    **args),
                            code=301)
            # return render_elliptic_modular_forms(**args)
        emf_logger.debug("HERE! weight={0} level={1} char={2}".format(
            weight, level, character))
        if level > 0 and weight > 0 and character > 0:
            if label != '' and not label is None:
                return render_web_newform(**info)
            else:
                return render_web_modform_space(**info)
        if level > 0 and weight > 0 and (group != 0 or character == None):
            return render_web_modform_space_gamma1(**info)
        return render_elliptic_modular_form_navigation_wp(**info)
        # Otherwise we go to the main navigation page
    except IndexError as e:  # catch everything here except KeyError below...
        emf_logger.debug("catching exceptions. info={0} e={1}".format(info, e))
        errst = str(e)
        ## Try to customise some of the error messages:
        if 'Character' and 'not exist' in errst:
            errst += " Please choose a character from the table below!"
            flash(errst, 'error')
            return render_elliptic_modular_form_navigation_wp(**info)
        if 'WebNewForm_computing' in errst:
            errst = "The space {0}.{1}.{2} is not in the database!".format(
                level, weight, character)
            flash(errst)
        return render_elliptic_modular_form_navigation_wp()
    except KeyError as e:
        emf_logger.debug("catching exceptions. info={0} e={1}".format(info, e))
        errst = "The orbit {0} is not in the database!".format(
            newform_label(level, weight, character, label))
        flash(errst)
        return render_elliptic_modular_form_navigation_wp()
Ejemplo n.º 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 = {}
        try:
            data['ainvs'] = [int(c) for c in self.xainvs[1:-1].split(',')]
        except AttributeError:
            data['ainvs'] = [int(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_str'] = unicode(str(data['j_invariant']))
        data['j_inv_latex'] = web_latex(data['j_invariant'])
        mw = self.mw = {}
        mw['rank'] = self.rank
        mw['int_points'] = ''
        if self.xintcoords:
            a1, a2, a3, a4, a6 = [ZZ(a) for a in data['ainvs']]

            def lift_x(x):
                f = ((x + a2) * x + a4) * x + a6
                b = (a1 * x + a3)
                d = (b * b + 4 * f).sqrt()
                return (x, (-b + d) / 2)

            mw['int_points'] = ', '.join(
                web_latex(lift_x(x)) for x in self.xintcoords)

        mw['generators'] = ''
        mw['heights'] = []
        if self.gens:
            mw['generators'] = [
                web_latex(tuple(P)) for P in parse_points(self.gens)
            ]

        mw['tor_order'] = self.torsion
        tor_struct = [int(c) for c in self.torsion_structure]
        if mw['tor_order'] == 1:
            mw['tor_struct'] = '\mathrm{Trivial}'
            mw['tor_gens'] = ''
        else:
            mw['tor_struct'] = ' \\times '.join(
                ['\Z/{%s}\Z' % n for n in tor_struct])
            mw['tor_gens'] = ', '.join(
                web_latex(tuple(P))
                for P in parse_points(self.torsion_generators))

        # try to get all the data we need from the database entry (now in self)
        try:
            data['equation'] = self.equation
            local_data = self.local_data
            D = self.signD * prod(
                [ld['p']**ld['ord_disc'] for ld in local_data])
            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']
            minq_label = self.min_quad_twist['label']
            data['minq_label'] = db_ec().find_one(
                {'label': minq_label}, ['lmfdb_label'])['lmfdb_label']
            data['minq_info'] = '(itself)' if minqD == 1 else '(by %s)' % minqD
            try:
                data['degree'] = self.degree
            except AttributeError:
                data['degree'] = 0  # invalid, but will be displayed nicely
            mw['heights'] = self.heights
            if self.number == 1:
                data['an'] = self.anlist
                data['ap'] = self.aplist
            else:
                r = db_ec().find_one({
                    'lmfdb_iso': self.lmfdb_iso,
                    'number': 1
                }, ['anlist', 'aplist'])
                data['an'] = r['anlist']
                data['ap'] = r['aplist']

        # otherwise fall back to computing it from the curve
        except AttributeError:
            self.E = EllipticCurve(data['ainvs'])
            data['equation'] = web_latex(self.E)
            data['disc'] = D = self.E.discriminant()
            Nfac = N.factor()
            Dfac = D.factor()
            bad_primes = [p for p, e in Nfac]
            try:
                data['degree'] = self.degree
            except AttributeError:
                try:
                    data['degree'] = self.E.modular_degree()
                except RuntimeError:
                    data['degree'] = 0  # invalid, but will be displayed nicely
            minq, minqD = self.E.minimal_quadratic_twist()
            data['minq_D'] = minqD
            if minqD == 1:
                data['minq_label'] = self.lmfdb_label
                data['minq_info'] = '(itself)'
            else:
                # This relies on the minimal twist being in the
                # database, which is true when the database only
                # contains the Cremona database.  It would be a good
                # idea if, when the database is extended, we ensured
                # that for any curve included, all twists of smaller
                # conductor are also included.
                minq_ainvs = [str(c) for c in minq.ainvs()]
                data['minq_label'] = db_ec().find_one(
                    {
                        'jinv': str(self.E.j_invariant()),
                        'ainvs': minq_ainvs
                    }, ['lmfdb_label'])['lmfdb_label']
                data['minq_info'] = '(by %s)' % minqD

            if self.gens:
                self.generators = [self.E(g) for g in parse_points(self.gens)]
                mw['heights'] = [P.height() for P in self.generators]

            data['an'] = self.E.anlist(20, python_ints=True)
            data['ap'] = self.E.aplist(100, python_ints=True)
            self.local_data = local_data = []
            for p in bad_primes:
                ld = self.E.local_data(p, algorithm="generic")
                local_data_p = {}
                local_data_p['p'] = p
                local_data_p['cp'] = ld.tamagawa_number()
                local_data_p['kod'] = web_latex(ld.kodaira_symbol()).replace(
                    '$', '')
                local_data_p['red'] = ld.bad_reduction_type()
                rootno = -ld.bad_reduction_type()
                if rootno == 0:
                    rootno = self.E.root_number(p)
                local_data_p['rootno'] = rootno
                local_data_p['ord_cond'] = ld.conductor_valuation()
                local_data_p['ord_disc'] = ld.discriminant_valuation()
                local_data_p['ord_den_j'] = max(
                    0, -self.E.j_invariant().valuation(p))
                local_data.append(local_data_p)

        # If we got the data from the database, the root numbers may
        # not have been stored there, so we have to compute them.  If
        # there are additive primes this means constructing the curve.
        for ld in self.local_data:
            if not 'rootno' in ld:
                rootno = -ld['red']
                if rootno == 0:
                    try:
                        E = self.E
                    except AttributeError:
                        self.E = E = EllipticCurve(data['ainvs'])
                    rootno = E.root_number(ld['p'])
                ld['rootno'] = rootno

        minq_N, minq_iso, minq_number = split_lmfdb_label(data['minq_label'])

        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'] = "\(\Z\)"
        if self.cm:
            data['cm_ramp'] = [
                p for p in ZZ(self.cm).support()
                if not p in self.non_surjective_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'] = "yes (\(D=%s\))" % data['CMD']
            if data['CMD'] % 4 == 0:
                d4 = ZZ(data['CMD']) // 4
                data['EndE'] = "\(\Z[\sqrt{%s}]\)" % d4
            else:
                data['EndE'] = "\(\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.class_url = url_for(".by_double_iso_label",
                                 conductor=N,
                                 iso_label=iso)
        self.one_deg = ZZ(self.class_deg).is_prime()
        self.ncurves = db_ec().count({'lmfdb_iso': self.lmfdb_iso})
        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 & BSD data
        bsd = self.bsd = {}
        r = self.rank
        if r >= 2:
            bsd['lder_name'] = "L^{(%s)}(E,1)/%s!" % (r, r)
        elif r:
            bsd['lder_name'] = "L'(E,1)"
        else:
            bsd['lder_name'] = "L(E,1)"

        bsd['reg'] = self.regulator
        bsd['omega'] = self.real_period
        bsd['sha'] = int(0.1 + self.sha_an)
        bsd['lder'] = self.special_value

        # 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)

        if self.iso == '990h':
            data['Gamma0optimal'] = bool(self.number == 3)
        else:
            data['Gamma0optimal'] = bool(self.number == 1)

        data['p_adic_data_exists'] = False
        if data['Gamma0optimal']:
            data['p_adic_data_exists'] = (padic_db().find({
                'lmfdb_iso':
                self.lmfdb_iso
            }).count()) > 0

        data['iwdata'] = []
        try:
            pp = [int(p) for p in self.iwdata]
            badp = [l['p'] for l in self.local_data]
            rtypes = [l['red'] for l in self.local_data]
            data[
                'iw_missing_flag'] = False  # flags that there is at least one "?" in the table
            data[
                'additive_shown'] = False  # flags that there is at least one additive prime in table
            for p in sorted(pp):
                rtype = ""
                if p in badp:
                    red = rtypes[badp.index(p)]
                    # Additive primes are excluded from the table
                    # if red==0:
                    #    continue
                    #rtype = ["nsmult","add", "smult"][1+red]
                    rtype = ["nonsplit", "add", "split"][1 + red]
                p = str(p)
                pdata = self.iwdata[p]
                if isinstance(pdata, type(u'?')):
                    if not rtype:
                        rtype = "ordinary" if pdata == "o?" else "ss"
                    if rtype == "add":
                        data['iwdata'] += [[p, rtype, "-", "-"]]
                        data['additive_shown'] = True
                    else:
                        data['iwdata'] += [[p, rtype, "?", "?"]]
                        data['iw_missing_flag'] = True
                else:
                    if len(pdata) == 2:
                        if not rtype:
                            rtype = "ordinary"
                        lambdas = str(pdata[0])
                        mus = str(pdata[1])
                    else:
                        rtype = "ss"
                        lambdas = ",".join([str(pdata[0]), str(pdata[1])])
                        mus = str(pdata[2])
                        mus = ",".join([mus, mus])
                    data['iwdata'] += [[p, rtype, lambdas, mus]]
        except AttributeError:
            # For curves with no Iwasawa data
            pass

        tamagawa_numbers = [ZZ(ld['cp']) for ld in local_data]
        cp_fac = [cp.factor() for cp in tamagawa_numbers]
        cp_fac = [
            latex(cp) if len(cp) < 2 else '(' + latex(cp) + ')'
            for cp in cp_fac
        ]
        bsd['tamagawa_factors'] = r'\cdot'.join(cp_fac)
        bsd['tamagawa_product'] = prod(tamagawa_numbers)

        # Torsion growth data

        data['torsion_growth_data_exists'] = False
        try:
            tg = self.tor_gro
            data['torsion_growth_data_exists'] = True
            data['tgx'] = tgextra = []
            # find all base-changes of this curve in the database, if any
            bcs = [
                res['label']
                for res in getDBConnection().elliptic_curves.nfcurves.find(
                    {'base_change': self.lmfdb_label},
                    projection={
                        'label': True,
                        '_id': False
                    })
            ]
            bcfs = [lab.split("-")[0] for lab in bcs]
            for F, T in tg.items():
                tg1 = {}
                tg1['bc'] = "Not in database"
                if ":" in F:
                    F = F.replace(":", ".")
                    field_data = nf_display_knowl(F, getDBConnection(),
                                                  field_pretty(F))
                    deg = int(F.split(".")[0])
                    bcc = [x for x, y in zip(bcs, bcfs) if y == F]
                    if bcc:
                        from lmfdb.ecnf.main import split_full_label
                        F, NN, I, C = split_full_label(bcc[0])
                        tg1['bc'] = bcc[0]
                        tg1['bc_url'] = url_for('ecnf.show_ecnf',
                                                nf=F,
                                                conductor_label=NN,
                                                class_label=I,
                                                number=C)
                else:
                    field_data = web_latex_split_on_pm(
                        coeff_to_poly(string2list(F)))
                    deg = F.count(",")
                tg1['d'] = deg
                tg1['f'] = field_data
                tg1['t'] = '\(' + ' \\times '.join(
                    ['\Z/{}\Z'.format(n) for n in T.split(",")]) + '\)'
                tg1['m'] = 0
                tgextra.append(tg1)

            tgextra.sort(key=lambda x: x['d'])
            data['ntgx'] = len(tgextra)
            lastd = 1
            for tg in tgextra:
                d = tg['d']
                if d != lastd:
                    tg['m'] = len([x for x in tgextra if x['d'] == d])
                    lastd = d
            data['tg_maxd'] = max(db_ecstats().find_one(
                {'_id': 'torsion_growth'})['degrees'])

        except AttributeError:
            pass  # we have no torsion growth data

        data['newform'] = web_latex(
            PowerSeriesRing(QQ, 'q')(data['an'], 20, check=True))
        data['newform_label'] = self.newform_label = newform_label(
            cond, 2, 1, iso)
        self.newform_link = url_for("emf.render_elliptic_modular_forms",
                                    level=cond,
                                    weight=2,
                                    character=1,
                                    label=iso)
        self.newform_exists_in_db = is_newform_in_db(self.newform_label)
        self._code = None

        self.class_url = url_for(".by_double_iso_label",
                                 conductor=N,
                                 iso_label=iso)
        self.friends = [('Isogeny class ' + self.lmfdb_iso, self.class_url),
                        ('Minimal quadratic twist %s %s' %
                         (data['minq_info'], data['minq_label']),
                         url_for(".by_triple_label",
                                 conductor=minq_N,
                                 iso_label=minq_iso,
                                 number=minq_number)),
                        ('All twists ',
                         url_for(".rational_elliptic_curves", jinv=self.jinv)),
                        ('L-function',
                         url_for("l_functions.l_function_ec_page",
                                 conductor_label=N,
                                 isogeny_class_label=iso))]
        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 = [('Download coefficients of q-expansion',
                           url_for(".download_EC_qexp",
                                   label=self.lmfdb_label,
                                   limit=1000)),
                          ('Download all stored data',
                           url_for(".download_EC_all",
                                   label=self.lmfdb_label)),
                          ('Download Magma code',
                           url_for(".ec_code_download",
                                   conductor=cond,
                                   iso=iso,
                                   number=num,
                                   label=self.lmfdb_label,
                                   download_type='magma')),
                          ('Download Sage code',
                           url_for(".ec_code_download",
                                   conductor=cond,
                                   iso=iso,
                                   number=num,
                                   label=self.lmfdb_label,
                                   download_type='sage')),
                          ('Download GP code',
                           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.lmfdb_label), (None, self.plot_link),
                           ('Conductor', '\(%s\)' % data['conductor']),
                           ('Discriminant', '\(%s\)' % data['disc']),
                           ('j-invariant', '%s' % data['j_inv_latex']),
                           ('CM', '%s' % data['CM']),
                           ('Rank', '\(%s\)' % mw['rank']),
                           ('Torsion Structure', '\(%s\)' % mw['tor_struct'])]

        self.title = "Elliptic Curve %s (Cremona label %s)" % (
            self.lmfdb_label, self.label)

        self.bread = [('Elliptic Curves', url_for("ecnf.index")),
                      ('$\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, ' ')]
Ejemplo n.º 11
0
def render_elliptic_modular_forms(level=None, weight=None, character=None, label=None,group=None, **kwds):
    r"""
    Default input of same type as required. Note that for holomorphic modular forms: level=0 or weight=0 are non-existent.
    """
    emf_logger.debug(
        "In render: level={0},weight={1},character={2},group={3},label={4}".format(level, weight, character, group, label))
    emf_logger.debug("args={0}".format(request.args))
    emf_logger.debug("args={0}".format(request.form))
    emf_logger.debug("met={0}".format(request.method))
    keys = ['download', 'jump_to']
    info = get_args(request, level, weight, character, group, label, keys=keys)
    valid = validate_parameters(level,weight,character,label,info)
    if isinstance(valid,basestring):
        return redirect(valid,code=301)
    level = info['level']; weight = info['weight']; character = info['character']
    #if info.has_key('error'):
    #    return render_elliptic_modular_form_navigation_wp(error=info['error'])
    emf_logger.debug("info={0}".format(info))
    emf_logger.debug("level=%s, %s" % (level, type(level)))
    emf_logger.debug("label=%s, %s" % (label, type(label)))
    emf_logger.debug("wt=%s, %s" % (weight, type(weight)))
    group = info.get('group',None)
    emf_logger.debug("group=%s, %s" % (group, type(group)))
    if group == 0:
        info['character'] = character = 1 # only trivial character for Gamma_0(N)
    try:
        if 'download' in info:
            return get_downloads(**info)
        emf_logger.debug("info=%s" % info)
        ## Consistency of arguments>
        # if level<=0:  level=None
        # if weight<=0:  weight=None
        if 'jump_to' in info:  # try to find out which form we want to jump
            s = my_get(info, 'jump_to', '', str)
            emf_logger.info("info.keys1={0}".format(info.keys()))
            info.pop('jump_to')
            emf_logger.info("info.keys2={0}".format(info.keys()))
            args = extract_data_from_jump_to(s)
            emf_logger.debug("args=%s" % args)
            return redirect(url_for("emf.render_elliptic_modular_forms", **args), code=301)
            # return render_elliptic_modular_forms(**args)
        emf_logger.debug("HERE! weight={0} level={1} char={2}".format(weight,level,character))
        if level > 0 and weight > 0 and character > 0:
            if label != '' and not label is None:
                return render_web_newform(**info)
            else:
                return render_web_modform_space(**info)
        if level > 0 and weight > 0 and (group != 0 or character == None):
            return render_web_modform_space_gamma1(**info)
        return render_elliptic_modular_form_navigation_wp(**info)
        # Otherwise we go to the main navigation page
    except IndexError as e: # catch everything here except KeyError below...
        emf_logger.debug("catching exceptions. info={0} e={1}".format(info,e))
        errst = str(e)
        ## Try to customise some of the error messages:
        if 'Character' and 'not exist' in errst:
            errst += " Please choose a character from the table below!"
            flash(errst,'error')
            return render_elliptic_modular_form_navigation_wp(**info)
        if 'WebNewForm_computing' in errst:
            errst = "The space {0}.{1}.{2} is not in the database!".format(level,weight,character)
            flash(errst)
        return render_elliptic_modular_form_navigation_wp()
    except KeyError as e:
        emf_logger.debug("catching exceptions. info={0} e={1}".format(info,e))
        errst = "The orbit {0} is not in the database!".format(newform_label(level,weight,character,label))
        flash(errst)
        return render_elliptic_modular_form_navigation_wp()
Ejemplo n.º 12
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 = {}
        try:
            data['ainvs'] = [int(c) for c in self.xainvs[1:-1].split(',')]
        except AttributeError:
            data['ainvs'] = [int(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_str'] = unicode(str(data['j_invariant']))
        data['j_inv_latex'] = web_latex(data['j_invariant'])
        mw = self.mw = {}
        mw['rank'] = self.rank
        mw['int_points'] = ''
        if self.xintcoords:
            a1, a2, a3, a4, a6 = [ZZ(a) for a in data['ainvs']]
            def lift_x(x):
                f = ((x + a2) * x + a4) * x + a6
                b = (a1*x + a3)
                d = (b*b + 4*f).sqrt()
                return (x, (-b+d)/2)
            mw['int_points'] = ', '.join(web_latex(lift_x(x)) for x in self.xintcoords)

        mw['generators'] = ''
        mw['heights'] = []
        if self.gens:
            mw['generators'] = [web_latex(tuple(P)) for P in parse_points(self.gens)]

        mw['tor_order'] = self.torsion
        tor_struct = [int(c) for c in self.torsion_structure]
        if mw['tor_order'] == 1:
            mw['tor_struct'] = '\mathrm{Trivial}'
            mw['tor_gens'] = ''
        else:
            mw['tor_struct'] = ' \\times '.join(['\Z/{%s}\Z' % n for n in tor_struct])
            mw['tor_gens'] = ', '.join(web_latex(tuple(P)) for P in parse_points(self.torsion_generators))

        # try to get all the data we need from the database entry (now in self)
        try:
            data['equation'] = self.equation
            local_data = self.local_data
            badprimes = [ZZ(ld['p']) for ld in local_data]
            D = self.signD * prod([ld['p']**ld['ord_disc'] for ld in local_data])
            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']
            minq_label = self.min_quad_twist['label']
            data['minq_label'] = db_ec().find_one({'label':minq_label}, ['lmfdb_label'])['lmfdb_label']
            data['minq_info'] = '(itself)' if minqD==1 else '(by %s)' % minqD
            try:
                data['degree'] = self.degree
            except AttributeError:
                data['degree']  =0 # invalid, but will be displayed nicely
            mw['heights'] = self.heights
            if self.number == 1:
                data['an'] = self.anlist
                data['ap'] = self.aplist
            else:
                r = db_ec().find_one({'lmfdb_iso':self.lmfdb_iso, 'number':1}, ['anlist','aplist'])
                data['an'] = r['anlist']
                data['ap'] = r['aplist']

        # otherwise fall back to computing it from the curve
        except AttributeError:
            print("Falling back to constructing E")
            self.E = EllipticCurve(data['ainvs'])
            data['equation'] = web_latex(self.E)
            data['disc'] = D = self.E.discriminant()
            Nfac = N.factor()
            Dfac = D.factor()
            bad_primes = [p for p,e in Nfac]
            try:
                data['degree'] = self.degree
            except AttributeError:
                try:
                    data['degree'] = self.E.modular_degree()
                except RuntimeError:
                    data['degree'] = 0  # invalid, but will be displayed nicely
            minq, minqD = self.E.minimal_quadratic_twist()
            data['minq_D'] = minqD
            if minqD == 1:
                data['minq_label'] = self.lmfdb_label
                data['minq_info'] = '(itself)'
            else:
                # This relies on the minimal twist being in the
                # database, which is true when the database only
                # contains the Cremona database.  It would be a good
                # idea if, when the database is extended, we ensured
                # that for any curve included, all twists of smaller
                # conductor are also included.
                minq_ainvs = [str(c) for c in minq.ainvs()]
                data['minq_label'] = db_ec().find_one({'jinv':str(self.E.j_invariant()),
                                                       'ainvs': minq_ainvs},['lmfdb_label'])['lmfdb_label']
                data['minq_info'] = '(by %s)' % minqD

            if self.gens:
                self.generators = [self.E(g) for g in parse_points(self.gens)]
                mw['heights'] = [P.height() for P in self.generators]

            data['an'] = self.E.anlist(20,python_ints=True)
            data['ap'] = self.E.aplist(100,python_ints=True)
            self.local_data = local_data = []
            for p in bad_primes:
                ld = self.E.local_data(p, algorithm="generic")
                local_data_p = {}
                local_data_p['p'] = p
                local_data_p['cp'] = ld.tamagawa_number()
                local_data_p['kod'] = web_latex(ld.kodaira_symbol()).replace('$', '')
                local_data_p['red'] = ld.bad_reduction_type()
                local_data_p['ord_cond'] = ld.conductor_valuation()
                local_data_p['ord_disc'] = ld.discriminant_valuation()
                local_data_p['ord_den_j'] = max(0,-self.E.j_invariant().valuation(p))
                local_data.append(local_data_p)

        jfac = Factorization([(ZZ(ld['p']),ld['ord_den_j']) for ld in local_data])

        minq_N, minq_iso, minq_number = split_lmfdb_label(data['minq_label'])

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

        data['CMD'] = self.cm
        data['CM'] = "no"
        data['EndE'] = "\(\Z\)"
        if self.cm:
            data['CM'] = "yes (\(D=%s\))" % data['CMD']
            if data['CMD']%4==0:
                d4 = ZZ(data['CMD'])//4
                data['EndE'] = "\(\Z[\sqrt{%s}]\)" % d4
            else:
                data['EndE'] = "\(\Z[(1+\sqrt{%s})/2]\)" % data['CMD']
            data['ST'] = '<a href="%s">$%s$</a>' % (url_for('st.by_label', label='1.2.N(U(1))'),'N(\\mathrm{U}(1))')
        else:
            data['ST'] = '<a href="%s">$%s$</a>' % (url_for('st.by_label', label='1.2.SU(2)'),'\\mathrm{SU}(2)')

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

        try:
            data['galois_images'] = [trim_galois_image_code(s) for s in self.galois_images]
            data['non_surjective_primes'] = self.non_surjective_primes
        except AttributeError:
            #print "No Galois image data"
            data['galois_images'] = []
            data['non_surjective_primes'] = []

        data['galois_data'] = [{'p': p,'image': im }
                               for p,im in zip(data['non_surjective_primes'],
                                               data['galois_images'])]

        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 & BSD data
        bsd = self.bsd = {}
        r = self.rank
        if r >= 2:
            bsd['lder_name'] = "L^{(%s)}(E,1)/%s!" % (r,r)
        elif r:
            bsd['lder_name'] = "L'(E,1)"
        else:
            bsd['lder_name'] = "L(E,1)"

        bsd['reg'] = self.regulator
        bsd['omega'] = self.real_period
        bsd['sha'] = int(0.1+self.sha_an)
        bsd['lder'] = self.special_value

        # 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)

        if self.iso == '990h':
            data['Gamma0optimal'] = bool(self.number == 3)
        else:
            data['Gamma0optimal'] = bool(self.number == 1)


        data['p_adic_data_exists'] = False
        if data['Gamma0optimal']:
            data['p_adic_data_exists'] = (padic_db().find({'lmfdb_iso': self.lmfdb_iso}).count()) > 0

        tamagawa_numbers = [ZZ(ld['cp']) for ld in local_data]
        cp_fac = [cp.factor() for cp in tamagawa_numbers]
        cp_fac = [latex(cp) if len(cp)<2 else '('+latex(cp)+')' for cp in cp_fac]
        bsd['tamagawa_factors'] = r'\cdot'.join(cp_fac)
        bsd['tamagawa_product'] = sage.misc.all.prod(tamagawa_numbers)

        cond, iso, num = split_lmfdb_label(self.lmfdb_label)
        data['newform'] =  web_latex(PowerSeriesRing(QQ, 'q')(data['an'], 20, check=True))
        data['newform_label'] = self.newform_label = newform_label(cond,2,1,iso)
        self.newform_link = url_for("emf.render_elliptic_modular_forms", level=cond, weight=2, character=1, label=iso)
        self.newform_exists_in_db = is_newform_in_db(self.newform_label)
        self._code = None

        self.friends = [
            ('Isogeny class ' + self.lmfdb_iso, url_for(".by_double_iso_label", conductor=N, iso_label=iso)),
            ('Minimal quadratic twist %s %s' % (data['minq_info'], data['minq_label']), url_for(".by_triple_label", conductor=minq_N, iso_label=minq_iso, number=minq_number)),
            ('All twists ', url_for(".rational_elliptic_curves", jinv=self.jinv)),
            ('L-function', url_for("l_functions.l_function_ec_page", label=self.lmfdb_label))]
        if not self.cm:
            if N<=300:
                self.friends += [('Symmetric square L-function', url_for("l_functions.l_function_ec_sym_page", power='2', label=self.lmfdb_iso))]
            if N<=50:
                self.friends += [('Symmetric cube L-function', url_for("l_functions.l_function_ec_sym_page", power='3', label=self.lmfdb_iso))]
        if self.newform_exists_in_db:
            self.friends += [('Modular form ' + self.newform_label, self.newform_link)]

        self.downloads = [('Download coefficients of q-expansion', url_for(".download_EC_qexp", label=self.lmfdb_label, limit=1000)),
                          ('Download all stored data', url_for(".download_EC_all", label=self.lmfdb_label)),
                          ('Download Magma code', url_for(".ec_code_download", conductor=cond, iso=iso, number=num, label=self.lmfdb_label, download_type='magma')),
                          ('Download Sage code', url_for(".ec_code_download", conductor=cond, iso=iso, number=num, label=self.lmfdb_label, download_type='sage')),
                          ('Download GP code', 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 = '<img src="%s" width="200" height="150"/>' % self.plot
        self.properties = [('Label', self.lmfdb_label),
                           (None, self.plot_link),
                           ('Conductor', '\(%s\)' % data['conductor']),
                           ('Discriminant', '\(%s\)' % data['disc']),
                           ('j-invariant', '%s' % data['j_inv_latex']),
                           ('CM', '%s' % data['CM']),
                           ('Rank', '\(%s\)' % mw['rank']),
                           ('Torsion Structure', '\(%s\)' % mw['tor_struct'])
                           ]

        self.title = "Elliptic Curve %s (Cremona label %s)" % (self.lmfdb_label, self.label)

        self.bread = [('Elliptic Curves', url_for("ecnf.index")),
                           ('$\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,' ')]
Ejemplo n.º 13
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'] = 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_str'] = unicode(str(data['j_invariant']))
        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])
        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']
        minq_label = self.min_quad_twist['label']
        data['minq_label'] = db.ec_curves.lucky({'label':minq_label}, 'lmfdb_label')
        data['minq_info'] = '(itself)' if minqD==1 else '(by %s)' % minqD
        if self.degree is None:
            data['degree'] = 0 # invalid, but will be displayed nicely
        else:
            data['degree'] = self.degree
        if self.number == 1:
            data['an'] = self.anlist
            data['ap'] = self.aplist
        else:
            r = db.ec_curves.lucky({'lmfdb_iso':self.lmfdb_iso, 'number':1})
            data['an'] = r['anlist']
            data['ap'] = r['aplist']

        minq_N, minq_iso, minq_number = split_lmfdb_label(data['minq_label'])

        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'] = "\(\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'] = "yes (\(D=%s\))" % data['CMD']
            if data['CMD']%4==0:
                d4 = ZZ(data['CMD'])//4
                data['EndE'] = "\(\Z[\sqrt{%s}]\)" % d4
            else:
                data['EndE'] = "\(\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.class_url = url_for(".by_double_iso_label", conductor=N, iso_label=iso)
        self.one_deg = ZZ(self.class_deg).is_prime()
        self.ncurves = db.ec_curves.count({'lmfdb_iso':self.lmfdb_iso})
        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)

        if self.iso == '990h':
            data['Gamma0optimal'] = bool(self.number == 3)
        else:
            data['Gamma0optimal'] = bool(self.number == 1)


        data['p_adic_data_exists'] = False
        if data['Gamma0optimal']:
            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 = newform_label(cond,2,1,iso)
        self.newform_link = url_for("emf.render_elliptic_modular_forms", level=cond, weight=2, character=1, label=iso)
        self.newform_exists_in_db = is_newform_in_db(self.newform_label)
        self._code = None

        self.class_url = url_for(".by_double_iso_label", conductor=N, iso_label=iso)
        self.friends = [
            ('Isogeny class ' + self.lmfdb_iso, self.class_url),
            ('Minimal quadratic twist %s %s' % (data['minq_info'], data['minq_label']), url_for(".by_triple_label", conductor=minq_N, iso_label=minq_iso, number=minq_number)),
            ('All twists ', url_for(".rational_elliptic_curves", jinv=self.jinv)),
            ('L-function', url_for("l_functions.l_function_ec_page", conductor_label = N, isogeny_class_label = iso))]

        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 = [('Download coefficients of q-expansion', url_for(".download_EC_qexp", label=self.lmfdb_label, limit=1000)),
                          ('Download all stored data', url_for(".download_EC_all", label=self.lmfdb_label)),
                          ('Download Magma code', url_for(".ec_code_download", conductor=cond, iso=iso, number=num, label=self.lmfdb_label, download_type='magma')),
                          ('Download SageMath code', url_for(".ec_code_download", conductor=cond, iso=iso, number=num, label=self.lmfdb_label, download_type='sage')),
                          ('Download GP code', 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.lmfdb_label),
                           (None, self.plot_link),
                           ('Conductor', '\(%s\)' % data['conductor']),
                           ('Discriminant', '\(%s\)' % data['disc']),
                           ('j-invariant', '%s' % data['j_inv_latex']),
                           ('CM', '%s' % data['CM']),
                           ('Rank', '\(%s\)' % self.mw['rank']),
                           ('Torsion Structure', '\(%s\)' % self.mw['tor_struct'])
                           ]

        self.title = "Elliptic Curve %s (Cremona label %s)" % (self.lmfdb_label, self.label)

        self.bread = [('Elliptic Curves', url_for("ecnf.index")),
                           ('$\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,' ')]
Ejemplo n.º 14
0
    def make_class(self):
        self.ainvs_str = self.ainvs
        self.ainvs = [int(a) for a in self.ainvs_str]
        self.E = EllipticCurve(self.ainvs)
        self.CM = self.E.has_cm()

        try:
            # Extract the isogeny degree matrix from the database
            size = len(self.isogeny_matrix)
            from sage.matrix.all import Matrix

            self.isogeny_matrix = Matrix(self.isogeny_matrix)
        except AttributeError:
            # Failsafe: construct it from scratch
            self.isogeny_matrix = self.E.isogeny_class(order="lmfdb").matrix()
            size = self.isogeny_matrix.nrows()
        self.ncurves = size

        # Create isogeny graph:
        self.graph = make_graph(self.isogeny_matrix)
        P = self.graph.plot(edge_labels=True)
        self.graph_img = encode_plot(P)
        self.graph_link = '<img src="%s" width="200" height="150"/>' % self.graph_img

        # Create a list of the curves in the class from the database
        self.db_curves = [self.E]
        self.optimal_flags = [False] * size
        self.degrees = [0] * size
        if self.degree:
            self.degrees[0] = self.degree
        else:
            try:
                self.degrees[0] = self.E.modular_degree()
            except RuntimeError:
                pass

        # Fill in the curves in the class by looking each one up in the db:

        self.cremona_labels = [self.label] + [0] * (size - 1)
        if self.number == 1:
            self.optimal_flags[0] = True
        for i in range(2, size + 1):
            Edata = db_ec().find_one({"lmfdb_label": self.lmfdb_iso + str(i)})
            Ei = EllipticCurve([int(a) for a in Edata["ainvs"]])
            self.cremona_labels[i - 1] = Edata["label"]
            if Edata["number"] == 1:
                self.optimal_flags[i - 1] = True
            if "degree" in Edata:
                self.degrees[i - 1] = Edata["degree"]
            else:
                try:
                    self.degrees[i - 1] = Ei.modular_degree()
                except RuntimeError:
                    pass
            self.db_curves.append(Ei)

        if self.iso == "990h":  # this isogeny class is labeled wrong in Cremona's tables
            self.optimal_flags = [False, False, True, False]

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

        N, iso, number = split_lmfdb_label(self.lmfdb_iso)

        self.newform = web_latex(self.E.q_eigenform(10))
        self.newform_label = newform_label(N, 2, 1, iso)
        self.newform_link = url_for("emf.render_elliptic_modular_forms", level=N, weight=2, character=1, label=iso)
        newform_exists_in_db = is_newform_in_db(self.newform_label)

        self.lfunction_link = url_for("l_functions.l_function_ec_page", label=self.lmfdb_iso)

        self.curves = [
            dict(
                [
                    ("label", self.lmfdb_iso + str(i + 1)),
                    ("url", url_for(".by_triple_label", conductor=N, iso_label=iso, number=i + 1)),
                    ("cremona_label", self.cremona_labels[i]),
                    ("ainvs", str(list(c.ainvs()))),
                    ("torsion", c.torsion_order()),
                    ("degree", self.degrees[i]),
                    ("optimal", self.optimal_flags[i]),
                ]
            )
            for i, c in enumerate(self.db_curves)
        ]

        self.friends = [("L-function", self.lfunction_link)]
        if not self.CM:
            self.friends += [
                (
                    "Symmetric square L-function",
                    url_for("l_functions.l_function_ec_sym_page", power="2", label=self.lmfdb_iso),
                ),
                (
                    "Symmetric 4th power L-function",
                    url_for("l_functions.l_function_ec_sym_page", power="4", label=self.lmfdb_iso),
                ),
            ]
        if newform_exists_in_db:
            self.friends += [("Modular form " + self.newform_label, self.newform_link)]

        self.properties = [
            ("Label", self.lmfdb_iso),
            ("Number of curves", str(self.ncurves)),
            ("Conductor", "\(%s\)" % N),
            ("CM", "%s" % self.CM),
            ("Rank", "\(%s\)" % self.rank),
            ("Graph", ""),
            (None, self.graph_link),
        ]

        self.downloads = [
            ("Download coefficients of newform", url_for(".download_EC_qexp", label=self.lmfdb_iso, limit=100)),
            ("Download stored data for all curves", url_for(".download_EC_all", label=self.lmfdb_iso)),
        ]

        if self.lmfdb_iso == self.iso:
            self.title = "Elliptic Curve Isogeny Class %s" % self.lmfdb_iso
        else:
            self.title = "Elliptic Curve Isogeny Class %s (Cremona label %s)" % (self.lmfdb_iso, self.iso)

        self.bread = [
            ("Elliptic Curves", url_for("ecnf.index")),
            ("$\Q$", url_for(".rational_elliptic_curves")),
            ("%s" % N, url_for(".by_conductor", conductor=N)),
            ("%s" % iso, " "),
        ]
Ejemplo n.º 15
0
def set_info_for_web_newform(level=None,
                             weight=None,
                             character=None,
                             label=None,
                             **kwds):
    r"""
    Set the info for on modular form.

    """
    info = to_dict(kwds)
    info['level'] = level
    info['weight'] = weight
    info['character'] = character
    info['label'] = label
    if level is None or weight is None or character is None or label is None:
        s = "In set info for one form but do not have enough args!"
        s += "level={0},weight={1},character={2},label={3}".format(
            level, weight, character, label)
        emf_logger.critical(s)
    emf_logger.debug("In set_info_for_one_mf: info={0}".format(info))
    prec = my_get(info, 'prec', default_prec, int)
    bprec = my_get(info, 'bprec', default_display_bprec, int)
    emf_logger.debug("PREC: {0}".format(prec))
    emf_logger.debug("BITPREC: {0}".format(bprec))
    try:
        WNF = WebNewForm_cached(level=level,
                                weight=weight,
                                character=character,
                                label=label)
        if not WNF.has_updated():
            raise IndexError(
                "Unfortunately, we do not have this newform in the database.")
        info['character_order'] = WNF.character.order
        info['code'] = WNF.code
        emf_logger.debug("defined webnewform for rendering!")
    except IndexError as e:
        info['error'] = e.message
    url0 = url_for("mf.modular_form_main_page")
    url1 = url_for("emf.render_elliptic_modular_forms")
    url2 = url_for("emf.render_elliptic_modular_forms", level=level)
    url3 = url_for("emf.render_elliptic_modular_forms",
                   level=level,
                   weight=weight)
    url4 = url_for("emf.render_elliptic_modular_forms",
                   level=level,
                   weight=weight,
                   character=character)
    bread = [(MF_TOP, url0), (EMF_TOP, url1)]
    bread.append(("Level %s" % level, url2))
    bread.append(("Weight %s" % weight, url3))
    bread.append(("Character \( %s \)" % (WNF.character.latex_name), url4))
    bread.append(
        ("Newform %d.%d.%d.%s" % (level, weight, int(character), label), ''))
    info['bread'] = bread

    properties2 = list()
    friends = list()
    space_url = url_for('emf.render_elliptic_modular_forms',
                        level=level,
                        weight=weight,
                        character=character)
    friends.append(
        ('\( S_{%s}(%s, %s)\)' %
         (WNF.weight, WNF.level, WNF.character.latex_name), space_url))
    if hasattr(WNF.base_ring, "lmfdb_url") and WNF.base_ring.lmfdb_url:
        friends.append(('Number field ' + WNF.base_ring.lmfdb_pretty,
                        WNF.base_ring.lmfdb_url))
    if hasattr(WNF.coefficient_field,
               "lmfdb_url") and WNF.coefficient_field.lmfdb_label:
        friends.append(('Number field ' + WNF.coefficient_field.lmfdb_pretty,
                        WNF.coefficient_field.lmfdb_url))
    friends = uniq(friends)
    friends.append(("Dirichlet character \(" + WNF.character.latex_name + "\)",
                    WNF.character.url()))

    if WNF.dimension == 0 and not info.has_key('error'):
        info['error'] = "This space is empty!"
    info['title'] = 'Newform ' + WNF.hecke_orbit_label
    info['learnmore'] = [('History of modular forms',
                          url_for('.holomorphic_mf_history'))]
    if 'error' in info:
        return info
    ## Until we have figured out how to do the embeddings correctly we don't display the Satake
    ## parameters for non-trivial characters....

    ## Example to illustrate the different cases
    ## base              = CyclotomicField(n) -- of degree phi(n)
    ## coefficient_field = NumberField( p(x)) for some p in base['x'] of degree m
    ##   we would then have cdeg = m*phi(n) and bdeg = phi(n)
    ##   and rdeg = m
    ## Unfortunately, for e.g. base = coefficient_field = CyclotomicField(6)
    ## we get coefficient_field.relative_degree() == 2 although it should be 1
    cdeg = WNF.coefficient_field.absolute_degree()
    bdeg = WNF.base_ring.absolute_degree()
    if cdeg == 1:
        rdeg = 1
    else:
        ## just setting rdeg = WNF.coefficient_field.relative_degree() does not give correct result...
        ##
        rdeg = QQ(cdeg) / QQ(bdeg)
    cf_is_QQ = (cdeg == 1)
    br_is_QQ = (bdeg == 1)
    if cf_is_QQ:
        info['satake'] = WNF.satake
    if WNF.complexity_of_first_nonvanishing_coefficients(
    ) > default_max_height:
        info['qexp'] = ""
        info['qexp_display'] = ''
        info['hide_qexp'] = True
        n, c = WNF.first_nonvanishing_coefficient()
        info['trace_nv'] = latex(WNF.first_nonvanishing_coefficient_trace())
        info['norm_nv'] = '\\approx ' + latex(
            WNF.first_nonvanishing_coefficient_norm().n())
        info['index_nv'] = n
    else:
        if WNF.prec < prec:
            #get WNF record at larger prec
            WNF.prec = prec
            WNF.update_from_db()
        info['qexp'] = WNF.q_expansion_latex(prec=10, name='\\alpha ')
        info['qexp_display'] = url_for(".get_qexp_latex",
                                       level=level,
                                       weight=weight,
                                       character=character,
                                       label=label)
        info["hide_qexp"] = False
    info['max_cn_qexp'] = WNF.q_expansion.prec()
    ## All combinations should be tested...
    ## 13/4/4/a -> base ring = coefficient_field = QQ(zeta_6)
    ## 13/3/8/a ->  base_ring = QQ(zeta_4), coefficient_field has poly x^2+(2\zeta_4+2x-3\zeta_$ over base_ring
    ## 13/4/3/a ->  base_ring = coefficient_field = QQ(zeta_3)
    ## 13/4/1/a -> all rational
    ## 13/6/1/a/ -> base_ring = QQ, coefficient_field = Q(sqrt(17))
    ## These are variables which needs to be set properly below
    info['polvars'] = {'base_ring': 'x', 'coefficient_field': '\\alpha'}
    if not cf_is_QQ:
        if rdeg > 1:  # not WNF.coefficient_field == WNF.base_ring:
            ## Here WNF.base_ring should be some cyclotomic field and we have an extension over this.
            p1 = WNF.coefficient_field.relative_polynomial()
            c_pol_ltx = web_latex_poly(p1,
                                       '\\alpha')  # make the variable \alpha
            c_pol_ltx_x = web_latex_poly(p1, 'x')
            zeta = p1.base_ring().gens()[0]
            #           p2 = zeta.minpoly() #this is not used anymore
            #           b_pol_ltx = web_latex_poly(p2, latex(zeta)) #this is not used anymore
            z1 = zeta.multiplicative_order()
            info['coeff_field'] = [
                WNF.coefficient_field.absolute_polynomial_latex('x'),
                c_pol_ltx_x, z1
            ]
            if hasattr(WNF.coefficient_field,
                       "lmfdb_url") and WNF.coefficient_field.lmfdb_url:
                info['coeff_field_pretty'] = [
                    WNF.coefficient_field.lmfdb_url,
                    WNF.coefficient_field.lmfdb_pretty,
                    WNF.coefficient_field.lmfdb_label
                ]
            if z1 == 4:
                info[
                    'polynomial_st'] = '<div class="where">where</div> {0}\(\mathstrut=0\) and \(\zeta_4=i\).</div><br/>'.format(
                        c_pol_ltx)
                info['polvars']['base_ring'] = 'i'
            elif z1 <= 2:
                info[
                    'polynomial_st'] = '<div class="where">where</div> {0}\(\mathstrut=0\).</div><br/>'.format(
                        c_pol_ltx)
            else:
                info[
                    'polynomial_st'] = '<div class="where">where</div> %s\(\mathstrut=0\) and \(\zeta_{%s}=e^{\\frac{2\\pi i}{%s}}\) ' % (
                        c_pol_ltx, z1, z1)
                info['polvars']['base_ring'] = '\zeta_{{ {0} }}'.format(z1)
                if z1 == 3:
                    info[
                        'polynomial_st'] += 'is a primitive cube root of unity.'
                else:
                    info[
                        'polynomial_st'] += 'is a primitive {0}-th root of unity.'.format(
                            z1)
        elif not br_is_QQ:
            ## Now we have base and coefficient field being equal, meaning that since the coefficient field is not QQ it is some cyclotomic field
            ## generated by some \zeta_n
            p1 = WNF.coefficient_field.absolute_polynomial()
            z1 = WNF.coefficient_field.gens()[0].multiplicative_order()
            c_pol_ltx = web_latex_poly(p1, '\\zeta_{{{0}}}'.format(z1))
            c_pol_ltx_x = web_latex_poly(p1, 'x')
            info['coeff_field'] = [
                WNF.coefficient_field.absolute_polynomial_latex('x'),
                c_pol_ltx_x
            ]
            if hasattr(WNF.coefficient_field,
                       "lmfdb_url") and WNF.coefficient_field.lmfdb_url:
                info['coeff_field_pretty'] = [
                    WNF.coefficient_field.lmfdb_url,
                    WNF.coefficient_field.lmfdb_pretty,
                    WNF.coefficient_field.lmfdb_label
                ]
            if z1 == 4:
                info[
                    'polynomial_st'] = '<div class="where">where \(\zeta_4=e^{{\\frac{{\\pi i}}{{ 2 }} }}=i \).</div>'.format(
                        c_pol_ltx)
                info['polvars']['coefficient_field'] = 'i'
            elif z1 <= 2:
                info['polynomial_st'] = ''
            else:
                info[
                    'polynomial_st'] = '<div class="where">where \(\zeta_{{{0}}}=e^{{\\frac{{2\\pi i}}{{ {0} }} }}\) '.format(
                        z1)
                info['polvars']['coefficient_field'] = '\zeta_{{{0}}}'.format(
                    z1)
                if z1 == 3:
                    info[
                        'polynomial_st'] += 'is a primitive cube root of unity.</div>'
                else:
                    info[
                        'polynomial_st'] += 'is a primitive {0}-th root of unity.</div>'.format(
                            z1)
    else:
        info['polynomial_st'] = ''
    if info["hide_qexp"]:
        info['polynomial_st'] = ''
    info['degree'] = int(cdeg)
    if cdeg == 1:
        info['is_rational'] = 1
        info['coeff_field_pretty'] = [
            WNF.coefficient_field.lmfdb_url, WNF.coefficient_field.lmfdb_pretty
        ]
    else:
        info['is_rational'] = 0
    emf_logger.debug("PREC2: {0}".format(prec))
    info['embeddings'] = WNF._embeddings[
        'values']  #q_expansion_embeddings(prec, bprec,format='latex')
    info['embeddings_len'] = len(info['embeddings'])
    properties2 = [('Level', str(level)), ('Weight', str(weight)),
                   ('Character', '$' + WNF.character.latex_name + '$'),
                   ('Label', WNF.hecke_orbit_label),
                   ('Dimension of Galois orbit', str(WNF.dimension))]
    if (ZZ(level)).is_squarefree():
        info['twist_info'] = WNF.twist_info
        if isinstance(info['twist_info'],
                      list) and len(info['twist_info']) > 0:
            info['is_minimal'] = info['twist_info'][0]
            if (info['twist_info'][0]):
                s = 'Is minimal<br>'
            else:
                s = 'Is a twist of lower level<br>'
            properties2 += [('Twist info', s)]
    else:
        info['twist_info'] = 'Twist info currently not available.'
        properties2 += [('Twist info', 'not available')]
    args = list()
    for x in range(5, 200, 10):
        args.append({'digits': x})
    alev = None
    CM = WNF._cm_values
    if CM is not None:
        if CM.has_key('tau') and len(CM['tau']) != 0:
            info['CM_values'] = CM
    info['is_cm'] = WNF.is_cm
    if WNF.is_cm == 1:
        info['cm_field'] = "2.0.{0}.1".format(-WNF.cm_disc)
        info['cm_disc'] = WNF.cm_disc
        info['cm_field_knowl'] = nf_display_knowl(
            info['cm_field'], getDBConnection(),
            field_pretty(info['cm_field']))
        info['cm_field_url'] = url_for("number_fields.by_label",
                                       label=info["cm_field"])
    if WNF.is_cm is None or WNF.is_cm == -1:
        s = '- Unknown (insufficient data)<br>'
    elif WNF.is_cm == 1:
        s = 'Yes<br>'
    else:
        s = 'No<br>'
    properties2.append(('CM', s))
    alev = WNF.atkin_lehner_eigenvalues()
    info['atkinlehner'] = None
    if isinstance(alev, dict) and len(alev.keys()) > 0 and level != 1:
        s1 = " Atkin-Lehner eigenvalues "
        s2 = ""
        for Q in alev.keys():
            s2 += "\( \omega_{ %s } \) : %s <br>" % (Q, alev[Q])
        properties2.append((s1, s2))
        emf_logger.debug("properties={0}".format(properties2))
        # alev = WNF.atkin_lehner_eigenvalues_for_all_cusps()
        # if isinstance(alev,dict) and len(alev.keys())>0:
        #     emf_logger.debug("alev={0}".format(alev))
        #     info['atkinlehner'] = list()
        #     for Q in alev.keys():
        #         s = "\(" + latex(c) + "\)"
        #         Q = alev[c][0]
        #         ev = alev[c][1]
        #         info['atkinlehner'].append([Q, c, ev])
    if (level == 1):
        poly = WNF.explicit_formulas.get('as_polynomial_in_E4_and_E6', '')
        if poly != '':
            d, monom, coeffs = poly
            emf_logger.critical("poly={0}".format(poly))
            info['explicit_formulas'] = '\('
            for i in range(len(coeffs)):
                c = QQ(coeffs[i])
                s = ""
                if d > 1 and i > 0 and c > 0:
                    s = "+"
                if c < 0:
                    s = "-"
                if c.denominator() > 1:
                    cc = "\\frac{{ {0} }}{{ {1} }}".format(
                        abs(c.numerator()), c.denominator())
                else:
                    cc = str(abs(c))
                s += "{0} \cdot ".format(cc)
                a = monom[i][0]
                b = monom[i][1]
                if a == 1:
                    a = ""
                if b == 1:
                    b = ""
                if a == 0 and b != 0:
                    s += "E_6^{{ {0} }}(z)".format(b)
                elif b == 0 and a != 0:
                    s += "E_4^{{ {0} }}(z)".format(a)
                else:
                    s += "E_4^{{ {0} }}(z) \cdot E_6^{{ {1} }}(z)".format(a, b)
                info['explicit_formulas'] += s
            info['explicit_formulas'] += " \)"
    # cur_url = '?&level=' + str(level) + '&weight=' + str(weight) + '&character=' + str(character) + '&label=' + str(label) # never used
    if len(WNF.parent.hecke_orbits) > 1:
        for label_other in WNF.parent.hecke_orbits.keys():
            if (label_other != label):
                s = 'Modular form '
                if character:
                    s += newform_label(level, weight, character, label_other)
                else:
                    s += newform_label(level, weight, 1, label_other)

                url = url_for('emf.render_elliptic_modular_forms',
                              level=level,
                              weight=weight,
                              character=character,
                              label=label_other)
                friends.append((s, url))

    s = 'L-Function '
    if character:
        s += newform_label(level, weight, character, label)
    else:
        s += newform_label(level, weight, 1, label)
    # url =
    # "/L/ModularForm/GL2/Q/holomorphic?level=%s&weight=%s&character=%s&label=%s&number=%s"
    # %(level,weight,character,label,0)
    url = '/L' + url_for('emf.render_elliptic_modular_forms',
                         level=level,
                         weight=weight,
                         character=character,
                         label=label)
    if WNF.coefficient_field_degree > 1:
        for h in range(WNF.coefficient_field_degree):
            s0 = s + ".{0}".format(h)
            url0 = url + "{0}/".format(h)
            friends.append((s0, url0))
    else:
        friends.append((s, url))
    # if there is an elliptic curve over Q associated to self we also list that
    if WNF.weight == 2 and WNF.coefficient_field_degree == 1:
        llabel = str(level) + '.' + label
        s = 'Elliptic curve isogeny class ' + llabel
        url = '/EllipticCurve/Q/' + llabel
        friends.append((s, url))
    info['properties2'] = properties2
    info['friends'] = friends
    info['max_cn'] = WNF.max_available_prec()
    return info
Ejemplo n.º 16
0
    def make_curve(self):
        # To start with the data fields of self are just those from
        # the database.  We need to reformat these, construct the
        # actual elliptic curve E, and compute some further (easy)
        # data about it.
        #

        # Weierstrass equation

        data = self.data = {}
        data["ainvs"] = [int(ai) for ai in self.ainvs]
        self.E = EllipticCurve(data["ainvs"])
        data["equation"] = web_latex(self.E)

        # conductor, j-invariant and discriminant

        data["conductor"] = N = ZZ(self.conductor)
        bad_primes = N.prime_factors()
        try:
            data["j_invariant"] = QQ(str(self.jinv))
        except KeyError:
            data["j_invariant"] = self.E.j_invariant()
        data["j_inv_factor"] = latex(0)
        if data["j_invariant"]:
            data["j_inv_factor"] = latex(data["j_invariant"].factor())
        data["j_inv_str"] = unicode(str(data["j_invariant"]))
        data["j_inv_latex"] = web_latex(data["j_invariant"])
        data["disc"] = D = self.E.discriminant()
        data["disc_latex"] = web_latex(data["disc"])
        data["disc_factor"] = latex(data["disc"].factor())
        data["cond_factor"] = latex(N.factor())
        data["cond_latex"] = web_latex(N)

        # CM and endomorphism ring

        data["CMD"] = self.cm
        data["CM"] = "no"
        data["EndE"] = "\(\Z\)"
        if self.cm:
            data["CM"] = "yes (\(D=%s\))" % data["CMD"]
            if data["CMD"] % 4 == 0:
                d4 = ZZ(data["CMD"]) // 4
                data["EndE"] = "\(\Z[\sqrt{%s}]\)" % d4
            else:
                data["EndE"] = "\(\Z[(1+\sqrt{%s})/2]\)" % data["CMD"]
            data["ST"] = '<a href="%s">$%s$</a>' % (url_for("st.by_label", label="1.2.N(U(1))"), "N(\\mathrm{U}(1))")
        else:
            data["ST"] = '<a href="%s">$%s$</a>' % (url_for("st.by_label", label="1.2.SU(2)"), "\\mathrm{SU}(2)")

        # modular degree

        try:
            data["degree"] = self.degree
        except AttributeError:
            try:
                data["degree"] = self.E.modular_degree()
            except RuntimeError:
                data["degree"]  # invalid, but will be displayed nicely

        # Minimal quadratic twist

        E_pari = self.E.pari_curve()
        from sage.libs.pari.all import PariError

        try:
            minq, minqD = self.E.minimal_quadratic_twist()
        except PariError:  # this does occur with 164411a1
            ec.debug("PariError computing minimal quadratic twist of elliptic curve %s" % lmfdb_label)
            minq = self.E
            minqD = 1
        data["minq_D"] = minqD
        if self.E == minq:
            data["minq_label"] = self.lmfdb_label
            data["minq_info"] = "(itself)"
        else:
            minq_ainvs = [str(c) for c in minq.ainvs()]
            data["minq_label"] = db_ec().find_one({"jinv": str(self.E.j_invariant()), "ainvs": minq_ainvs})[
                "lmfdb_label"
            ]
            data["minq_info"] = "(by %s)" % minqD

        minq_N, minq_iso, minq_number = split_lmfdb_label(data["minq_label"])

        # rational and integral points

        mw = self.mw = {}

        xintpoints_projective = [self.E.lift_x(x) for x in self.xintcoords]
        xintpoints = [P.xy() for P in xintpoints_projective]
        mw["int_points"] = ", ".join(web_latex(P) for P in xintpoints)

        # Generators of infinite order

        mw["rank"] = self.rank
        try:
            self.generators = [self.E(g) for g in parse_points(self.gens)]
            mw["generators"] = [web_latex(P.xy()) for P in self.generators]
            mw["heights"] = [P.height() for P in self.generators]
        except AttributeError:
            mw["generators"] = ""
            mw["heights"] = []

        # Torsion subgroup: order, structure, generators

        mw["tor_order"] = self.torsion
        tor_struct = [int(c) for c in self.torsion_structure]
        if mw["tor_order"] == 1:
            mw["tor_struct"] = "\mathrm{Trivial}"
            mw["tor_gens"] = ""
        else:
            mw["tor_struct"] = " \\times ".join(["\Z/{%s}\Z" % n for n in tor_struct])
            mw["tor_gens"] = ", ".join(web_latex(self.E(g).xy()) for g in parse_points(self.torsion_generators))

        # Images of Galois representations

        try:
            data["galois_images"] = [trim_galois_image_code(s) for s in self.galois_images]
            data["non_surjective_primes"] = self.non_surjective_primes
        except AttributeError:
            # print "No Galois image data"
            data["galois_images"] = []
            data["non_surjective_primes"] = []

        data["galois_data"] = [
            {"p": p, "image": im} for p, im in zip(data["non_surjective_primes"], data["galois_images"])
        ]

        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 & BSD data

        bsd = self.bsd = {}

        r = self.rank
        if r >= 2:
            bsd["lder_name"] = "L^{(%s)}(E,1)/%s!" % (r, r)
        elif r:
            bsd["lder_name"] = "L'(E,1)"
        else:
            bsd["lder_name"] = "L(E,1)"

        bsd["reg"] = self.regulator
        bsd["omega"] = self.real_period
        bsd["sha"] = int(0.1 + self.sha_an)
        bsd["lder"] = self.special_value

        # 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)

        if self.iso == "990h":
            data["Gamma0optimal"] = bool(self.number == 3)
        else:
            data["Gamma0optimal"] = bool(self.number == 1)

        data["p_adic_data_exists"] = False
        if data["Gamma0optimal"]:
            data["p_adic_data_exists"] = (padic_db().find({"lmfdb_iso": self.lmfdb_iso}).count()) > 0
        data["p_adic_primes"] = [p for p in sage.all.prime_range(5, 100) if self.E.is_ordinary(p) and not p.divides(N)]

        # Local data

        local_data = self.local_data = []
        # if we use E.tamagawa_numbers() it calls E.local_data(p) which
        # used to crash on some curves e.g. 164411a1
        tamagawa_numbers = []
        for p in bad_primes:
            local_info = self.E.local_data(p, algorithm="generic")
            local_data_p = {}
            local_data_p["p"] = p
            local_data_p["tamagawa_number"] = local_info.tamagawa_number()
            tamagawa_numbers.append(ZZ(local_info.tamagawa_number()))
            local_data_p["kodaira_symbol"] = web_latex(local_info.kodaira_symbol()).replace("$", "")
            local_data_p["reduction_type"] = local_info.bad_reduction_type()
            local_data_p["ord_cond"] = local_info.conductor_valuation()
            local_data_p["ord_disc"] = local_info.discriminant_valuation()
            local_data_p["ord_den_j"] = max(0, -self.E.j_invariant().valuation(p))
            local_data.append(local_data_p)

        cp_fac = [cp.factor() for cp in tamagawa_numbers]
        cp_fac = [latex(cp) if len(cp) < 2 else "(" + latex(cp) + ")" for cp in cp_fac]
        bsd["tamagawa_factors"] = r"\cdot".join(cp_fac)
        bsd["tamagawa_product"] = sage.misc.all.prod(tamagawa_numbers)

        cond, iso, num = split_lmfdb_label(self.lmfdb_label)
        data["newform"] = web_latex(self.E.q_eigenform(10))
        self.newform_label = newform_label(cond, 2, 1, iso)
        self.newform_link = url_for("emf.render_elliptic_modular_forms", level=cond, weight=2, character=1, label=iso)
        newform_exists_in_db = is_newform_in_db(self.newform_label)
        self._code = None

        self.friends = [
            ("Isogeny class " + self.lmfdb_iso, url_for(".by_double_iso_label", conductor=N, iso_label=iso)),
            (
                "Minimal quadratic twist %s %s" % (data["minq_info"], data["minq_label"]),
                url_for(".by_triple_label", conductor=minq_N, iso_label=minq_iso, number=minq_number),
            ),
            ("All twists ", url_for(".rational_elliptic_curves", jinv=self.jinv)),
            ("L-function", url_for("l_functions.l_function_ec_page", label=self.lmfdb_label)),
        ]
        if not self.cm:
            if N <= 300:
                self.friends += [
                    (
                        "Symmetric square L-function",
                        url_for("l_functions.l_function_ec_sym_page", power="2", label=self.lmfdb_iso),
                    )
                ]
            if N <= 50:
                self.friends += [
                    (
                        "Symmetric cube L-function",
                        url_for("l_functions.l_function_ec_sym_page", power="3", label=self.lmfdb_iso),
                    )
                ]
        if newform_exists_in_db:
            self.friends += [("Modular form " + self.newform_label, self.newform_link)]

        self.downloads = [
            ("Download coefficients of q-expansion", url_for(".download_EC_qexp", label=self.lmfdb_label, limit=100)),
            ("Download all stored data", url_for(".download_EC_all", label=self.lmfdb_label)),
            (
                "Download Magma code",
                url_for(
                    ".ec_code_download",
                    conductor=cond,
                    iso=iso,
                    number=num,
                    label=self.lmfdb_label,
                    download_type="magma",
                ),
            ),
            (
                "Download Sage code",
                url_for(
                    ".ec_code_download",
                    conductor=cond,
                    iso=iso,
                    number=num,
                    label=self.lmfdb_label,
                    download_type="sage",
                ),
            ),
            (
                "Download GP code",
                url_for(
                    ".ec_code_download", conductor=cond, iso=iso, number=num, label=self.lmfdb_label, download_type="gp"
                ),
            ),
        ]

        self.plot = encode_plot(self.E.plot())
        self.plot_link = '<img src="%s" width="200" height="150"/>' % self.plot
        self.properties = [
            ("Label", self.lmfdb_label),
            (None, self.plot_link),
            ("Conductor", "\(%s\)" % data["conductor"]),
            ("Discriminant", "\(%s\)" % data["disc"]),
            ("j-invariant", "%s" % data["j_inv_latex"]),
            ("CM", "%s" % data["CM"]),
            ("Rank", "\(%s\)" % mw["rank"]),
            ("Torsion Structure", "\(%s\)" % mw["tor_struct"]),
        ]

        self.title = "Elliptic Curve %s (Cremona label %s)" % (self.lmfdb_label, self.label)

        self.bread = [
            ("Elliptic Curves", url_for("ecnf.index")),
            ("$\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, " "),
        ]
Ejemplo n.º 17
0
    def make_class(self):
        self.CM = self.cm
        N, iso, number = split_lmfdb_label(self.lmfdb_iso)

        # Extract the size of the isogeny class from the database
        ncurves = self.class_size
        # Create a list of the curves in the class from the database
        self.curves = [db_ec().find_one({'iso':self.iso, 'lmfdb_number': i+1})
                          for i in range(ncurves)]

        # Set optimality flags.  The optimal curve is number 1 except
        # in one case which is labeled differently in the Cremona tables
        for c in self.curves:
            c['optimal'] = (c['number']==(3 if self.label == '990h' else 1))
            c['ai'] = parse_ainvs(c['xainvs'])
            c['url'] = url_for(".by_triple_label", conductor=N, iso_label=iso, number=c['lmfdb_number'])

        from sage.matrix.all import Matrix
        self.isogeny_matrix = Matrix(self.isogeny_matrix)
        self.isogeny_matrix_str = latex(matrix(self.isogeny_matrix))

        # Create isogeny graph:
        self.graph = make_graph(self.isogeny_matrix)
        P = self.graph.plot(edge_labels=True)
        self.graph_img = encode_plot(P)
        self.graph_link = '<img src="%s" width="200" height="150"/>' % self.graph_img


        self.newform =  web_latex(PowerSeriesRing(QQ, 'q')(self.anlist, 20, check=True))
        self.newform_label = newform_label(N,2,1,iso)
        self.newform_link = url_for("emf.render_elliptic_modular_forms", level=N, weight=2, character=1, label=iso)
        self.newform_exists_in_db = is_newform_in_db(self.newform_label)

        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)]

        self.properties = [('Label', self.lmfdb_iso),
                           ('Number of curves', str(ncurves)),
                           ('Conductor', '\(%s\)' % N),
                           ('CM', '%s' % self.CM),
                           ('Rank', '\(%s\)' % self.rank),
                           ('Graph', ''),(None, self.graph_link)
                           ]


        self.downloads = [('Download coefficients of newform', url_for(".download_EC_qexp", label=self.lmfdb_iso, limit=1000)),
                         ('Download stored data for all curves', url_for(".download_EC_all", label=self.lmfdb_iso))]

        if self.lmfdb_iso == self.iso:
            self.title = "Elliptic Curve Isogeny Class %s" % self.lmfdb_iso
        else:
            self.title = "Elliptic Curve Isogeny Class %s (Cremona label %s)" % (self.lmfdb_iso, self.iso)

        self.bread = [('Elliptic Curves', url_for("ecnf.index")),
                      ('$\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)'}
Ejemplo n.º 18
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'] = 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_str'] = unicode(str(data['j_invariant']))
        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])
        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']
        minq_label = self.min_quad_twist['label']
        data['minq_label'] = db.ec_curves.lucky({'label': minq_label},
                                                'lmfdb_label')
        data['minq_info'] = '(itself)' if minqD == 1 else '(by %s)' % minqD
        if self.degree is None:
            data['degree'] = 0  # invalid, but will be displayed nicely
        else:
            data['degree'] = self.degree
        if self.number == 1:
            data['an'] = self.anlist
            data['ap'] = self.aplist
        else:
            r = db.ec_curves.lucky({'lmfdb_iso': self.lmfdb_iso, 'number': 1})
            data['an'] = r['anlist']
            data['ap'] = r['aplist']

        minq_N, minq_iso, minq_number = split_lmfdb_label(data['minq_label'])

        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'] = "\(\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'] = "yes (\(D=%s\))" % data['CMD']
            if data['CMD'] % 4 == 0:
                d4 = ZZ(data['CMD']) // 4
                data['EndE'] = "\(\Z[\sqrt{%s}]\)" % d4
            else:
                data['EndE'] = "\(\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.class_url = url_for(".by_double_iso_label",
                                 conductor=N,
                                 iso_label=iso)
        self.one_deg = ZZ(self.class_deg).is_prime()
        self.ncurves = db.ec_curves.count({'lmfdb_iso': self.lmfdb_iso})
        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)

        if self.iso == '990h':
            data['Gamma0optimal'] = bool(self.number == 3)
        else:
            data['Gamma0optimal'] = bool(self.number == 1)

        data['p_adic_data_exists'] = False
        if data['Gamma0optimal']:
            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 = newform_label(
            cond, 2, 1, iso)
        self.newform_link = url_for("emf.render_elliptic_modular_forms",
                                    level=cond,
                                    weight=2,
                                    character=1,
                                    label=iso)
        self.newform_exists_in_db = is_newform_in_db(self.newform_label)
        self._code = None

        self.class_url = url_for(".by_double_iso_label",
                                 conductor=N,
                                 iso_label=iso)
        self.friends = [('Isogeny class ' + self.lmfdb_iso, self.class_url),
                        ('Minimal quadratic twist %s %s' %
                         (data['minq_info'], data['minq_label']),
                         url_for(".by_triple_label",
                                 conductor=minq_N,
                                 iso_label=minq_iso,
                                 number=minq_number)),
                        ('All twists ',
                         url_for(".rational_elliptic_curves", jinv=self.jinv)),
                        ('L-function',
                         url_for("l_functions.l_function_ec_page",
                                 conductor_label=N,
                                 isogeny_class_label=iso))]

        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 = [('Download coefficients of q-expansion',
                           url_for(".download_EC_qexp",
                                   label=self.lmfdb_label,
                                   limit=1000)),
                          ('Download all stored data',
                           url_for(".download_EC_all",
                                   label=self.lmfdb_label)),
                          ('Download Magma code',
                           url_for(".ec_code_download",
                                   conductor=cond,
                                   iso=iso,
                                   number=num,
                                   label=self.lmfdb_label,
                                   download_type='magma')),
                          ('Download SageMath code',
                           url_for(".ec_code_download",
                                   conductor=cond,
                                   iso=iso,
                                   number=num,
                                   label=self.lmfdb_label,
                                   download_type='sage')),
                          ('Download GP code',
                           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.lmfdb_label), (None, self.plot_link),
                           ('Conductor', '\(%s\)' % data['conductor']),
                           ('Discriminant', '\(%s\)' % data['disc']),
                           ('j-invariant', '%s' % data['j_inv_latex']),
                           ('CM', '%s' % data['CM']),
                           ('Rank', '\(%s\)' % self.mw['rank']),
                           ('Torsion Structure',
                            '\(%s\)' % self.mw['tor_struct'])]

        self.title = "Elliptic Curve %s (Cremona label %s)" % (
            self.lmfdb_label, self.label)

        self.bread = [('Elliptic Curves', url_for("ecnf.index")),
                      ('$\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, ' ')]
Ejemplo n.º 19
0
def set_info_for_web_newform(level=None, weight=None, character=None, label=None, **kwds):
    r"""
    Set the info for on modular form.

    """
    info = to_dict(kwds)
    info['level'] = level
    info['weight'] = weight
    info['character'] = character
    info['label'] = label
    if level is None or weight is None or character is None or label is None:
        s = "In set info for one form but do not have enough args!"
        s += "level={0},weight={1},character={2},label={3}".format(level, weight, character, label)
        emf_logger.critical(s)
    emf_logger.debug("In set_info_for_one_mf: info={0}".format(info))
    prec = my_get(info, 'prec', default_prec, int)
    bprec = my_get(info, 'bprec', default_display_bprec, int)
    emf_logger.debug("PREC: {0}".format(prec))
    emf_logger.debug("BITPREC: {0}".format(bprec))    
    try:
        WNF = WebNewForm_cached(level=level, weight=weight, character=character, label=label)
        if not WNF.has_updated():
            raise IndexError("Unfortunately, we do not have this newform in the database.")
        info['character_order'] = WNF.character.order
        info['code'] = WNF.code
        emf_logger.debug("defined webnewform for rendering!")
    except IndexError as e:
        info['error'] = e.message
    url0 = url_for("mf.modular_form_main_page")
    url1 = url_for("emf.render_elliptic_modular_forms")
    url2 = url_for("emf.render_elliptic_modular_forms", level=level)
    url3 = url_for("emf.render_elliptic_modular_forms", level=level, weight=weight)
    url4 = url_for("emf.render_elliptic_modular_forms", level=level, weight=weight, character=character)
    bread = [(MF_TOP, url0), (EMF_TOP, url1)]
    bread.append(("Level %s" % level, url2))
    bread.append(("Weight %s" % weight, url3))
    bread.append(("Character \( %s \)" % (WNF.character.latex_name), url4))
    bread.append(("Newform %d.%d.%d.%s" % (level, weight, int(character), label),''))
    info['bread'] = bread
    
    properties2 = list()
    friends = list()
    space_url = url_for('emf.render_elliptic_modular_forms',level=level, weight=weight, character=character)
    friends.append(('\( S_{%s}(%s, %s)\)'%(WNF.weight, WNF.level, WNF.character.latex_name), space_url))
    if hasattr(WNF.base_ring, "lmfdb_url") and WNF.base_ring.lmfdb_url:
        friends.append(('Number field ' + WNF.base_ring.lmfdb_pretty, WNF.base_ring.lmfdb_url))
    if hasattr(WNF.coefficient_field, "lmfdb_url") and WNF.coefficient_field.lmfdb_label:
        friends.append(('Number field ' + WNF.coefficient_field.lmfdb_pretty, WNF.coefficient_field.lmfdb_url))
    friends = uniq(friends)
    friends.append(("Dirichlet character \(" + WNF.character.latex_name + "\)", WNF.character.url()))
    
    if WNF.dimension==0 and not info.has_key('error'):
        info['error'] = "This space is empty!"
    info['title'] = 'Newform ' + WNF.hecke_orbit_label
    info['learnmore'] = [('History of modular forms', url_for('.holomorphic_mf_history'))]    
    if 'error' in info:
        return info
    ## Until we have figured out how to do the embeddings correctly we don't display the Satake
    ## parameters for non-trivial characters....

    ## Example to illustrate the different cases
    ## base              = CyclotomicField(n) -- of degree phi(n) 
    ## coefficient_field = NumberField( p(x)) for some p in base['x'] of degree m
    ##   we would then have cdeg = m*phi(n) and bdeg = phi(n)
    ##   and rdeg = m
    ## Unfortunately, for e.g. base = coefficient_field = CyclotomicField(6)
    ## we get coefficient_field.relative_degree() == 2 although it should be 1
    cdeg = WNF.coefficient_field.absolute_degree()
    bdeg = WNF.base_ring.absolute_degree()
    if cdeg == 1:
        rdeg = 1
    else:
        ## just setting rdeg = WNF.coefficient_field.relative_degree() does not give correct result...
        ## 
        rdeg = QQ(cdeg)/QQ(bdeg)
    cf_is_QQ = (cdeg == 1)
    br_is_QQ = (bdeg == 1)
    if cf_is_QQ:
        info['satake'] = WNF.satake
    if WNF.complexity_of_first_nonvanishing_coefficients() > default_max_height:
        info['qexp'] = ""
        info['qexp_display'] = ''
        info['hide_qexp'] = True
        n,c = WNF.first_nonvanishing_coefficient()
        info['trace_nv'] = latex(WNF.first_nonvanishing_coefficient_trace())
        info['norm_nv'] = '\\approx ' + latex(WNF.first_nonvanishing_coefficient_norm().n())
        info['index_nv'] = n
    else:
        if WNF.prec < prec:
            #get WNF record at larger prec
            WNF.prec = prec
            WNF.update_from_db()
        info['qexp'] = WNF.q_expansion_latex(prec=10, name='\\alpha ')
        info['qexp_display'] = url_for(".get_qexp_latex", level=level, weight=weight, character=character, label=label)
        info["hide_qexp"] = False
    info['max_cn_qexp'] = WNF.q_expansion.prec()
    ## All combinations should be tested...
    ## 13/4/4/a -> base ring = coefficient_field = QQ(zeta_6)
    ## 13/3/8/a ->  base_ring = QQ(zeta_4), coefficient_field has poly x^2+(2\zeta_4+2x-3\zeta_$ over base_ring
    ## 13/4/3/a ->  base_ring = coefficient_field = QQ(zeta_3) 
    ## 13/4/1/a -> all rational
    ## 13/6/1/a/ -> base_ring = QQ, coefficient_field = Q(sqrt(17))
    ## These are variables which needs to be set properly below
    info['polvars'] = {'base_ring':'x','coefficient_field':'\\alpha'}
    if not cf_is_QQ:
        if rdeg>1: # not WNF.coefficient_field == WNF.base_ring:
            ## Here WNF.base_ring should be some cyclotomic field and we have an extension over this.
            p1 = WNF.coefficient_field.relative_polynomial()
            c_pol_ltx = web_latex_poly(p1, '\\alpha')  # make the variable \alpha
            c_pol_ltx_x = web_latex_poly(p1, 'x')
            zeta = p1.base_ring().gens()[0]
#           p2 = zeta.minpoly() #this is not used anymore
#           b_pol_ltx = web_latex_poly(p2, latex(zeta)) #this is not used anymore
            z1 = zeta.multiplicative_order() 
            info['coeff_field'] = [ WNF.coefficient_field.absolute_polynomial_latex('x'),c_pol_ltx_x, z1]
            if hasattr(WNF.coefficient_field, "lmfdb_url") and WNF.coefficient_field.lmfdb_url:
                info['coeff_field_pretty'] = [ WNF.coefficient_field.lmfdb_url, WNF.coefficient_field.lmfdb_pretty, WNF.coefficient_field.lmfdb_label]
            if z1==4:
                info['polynomial_st'] = '<div class="where">where</div> {0}\(\mathstrut=0\) and \(\zeta_4=i\).</div><br/>'.format(c_pol_ltx)
                info['polvars']['base_ring']='i'
            elif z1<=2:
                info['polynomial_st'] = '<div class="where">where</div> {0}\(\mathstrut=0\).</div><br/>'.format(c_pol_ltx)
            else:
                info['polynomial_st'] = '<div class="where">where</div> %s\(\mathstrut=0\) and \(\zeta_{%s}=e^{\\frac{2\\pi i}{%s}}\) '%(c_pol_ltx, z1,z1)
                info['polvars']['base_ring']='\zeta_{{ {0} }}'.format(z1)
                if z1==3:
                    info['polynomial_st'] += 'is a primitive cube root of unity.'
                else:
                    info['polynomial_st'] += 'is a primitive {0}-th root of unity.'.format(z1)
        elif not br_is_QQ:
            ## Now we have base and coefficient field being equal, meaning that since the coefficient field is not QQ it is some cyclotomic field
            ## generated by some \zeta_n 
            p1 = WNF.coefficient_field.absolute_polynomial()
            z1 = WNF.coefficient_field.gens()[0].multiplicative_order()
            c_pol_ltx = web_latex_poly(p1, '\\zeta_{{{0}}}'.format(z1))
            c_pol_ltx_x = web_latex_poly(p1, 'x')
            info['coeff_field'] = [ WNF.coefficient_field.absolute_polynomial_latex('x'), c_pol_ltx_x]
            if hasattr(WNF.coefficient_field, "lmfdb_url") and WNF.coefficient_field.lmfdb_url:
                info['coeff_field_pretty'] = [ WNF.coefficient_field.lmfdb_url, WNF.coefficient_field.lmfdb_pretty, WNF.coefficient_field.lmfdb_label]
            if z1==4:
                info['polynomial_st'] = '<div class="where">where \(\zeta_4=e^{{\\frac{{\\pi i}}{{ 2 }} }}=i \).</div>'.format(c_pol_ltx)
                info['polvars']['coefficient_field']='i'
            elif z1<=2:
                info['polynomial_st'] = '' 
            else:
                info['polynomial_st'] = '<div class="where">where \(\zeta_{{{0}}}=e^{{\\frac{{2\\pi i}}{{ {0} }} }}\) '.format(z1)
                info['polvars']['coefficient_field']='\zeta_{{{0}}}'.format(z1)
                if z1==3:
                    info['polynomial_st'] += 'is a primitive cube root of unity.</div>'
                else:
                    info['polynomial_st'] += 'is a primitive {0}-th root of unity.</div>'.format(z1)
    else:
        info['polynomial_st'] = ''
    if info["hide_qexp"]:
        info['polynomial_st'] = ''
    info['degree'] = int(cdeg)
    if cdeg==1:
        info['is_rational'] = 1
        info['coeff_field_pretty'] = [ WNF.coefficient_field.lmfdb_url, WNF.coefficient_field.lmfdb_pretty ]
    else:
        info['is_rational'] = 0
    emf_logger.debug("PREC2: {0}".format(prec))
    info['embeddings'] = WNF._embeddings['values'] #q_expansion_embeddings(prec, bprec,format='latex')
    info['embeddings_len'] = len(info['embeddings'])
    properties2 = [('Level', str(level)),
                       ('Weight', str(weight)),
                       ('Character', '$' + WNF.character.latex_name + '$'),
                       ('Label', WNF.hecke_orbit_label),
                       ('Dimension of Galois orbit', str(WNF.dimension))]
    if (ZZ(level)).is_squarefree():
        info['twist_info'] = WNF.twist_info
        if isinstance(info['twist_info'], list) and len(info['twist_info'])>0:
            info['is_minimal'] = info['twist_info'][0]
            if(info['twist_info'][0]):
                s = 'Is minimal<br>'
            else:
                s = 'Is a twist of lower level<br>'
            properties2 += [('Twist info', s)]
    else:
        info['twist_info'] = 'Twist info currently not available.'
        properties2 += [('Twist info', 'not available')]
    args = list()
    for x in range(5, 200, 10):
        args.append({'digits': x})
    alev = None
    CM = WNF._cm_values
    if CM is not None:
        if CM.has_key('tau') and len(CM['tau']) != 0:
            info['CM_values'] = CM
    info['is_cm'] = WNF.is_cm
    if WNF.is_cm == 1:
        info['cm_field'] = "2.0.{0}.1".format(-WNF.cm_disc)
        info['cm_disc'] = WNF.cm_disc
        info['cm_field_knowl'] = nf_display_knowl(info['cm_field'], getDBConnection(), field_pretty(info['cm_field']))
        info['cm_field_url'] = url_for("number_fields.by_label", label=info["cm_field"])
    if WNF.is_cm is None or WNF.is_cm==-1:
        s = '- Unknown (insufficient data)<br>'
    elif WNF.is_cm == 1:
        s = 'Yes<br>'
    else:
        s = 'No<br>'
    properties2.append(('CM', s))
    alev = WNF.atkin_lehner_eigenvalues()
    info['atkinlehner'] = None
    if isinstance(alev,dict) and len(alev.keys())>0 and level != 1:
        s1 = " Atkin-Lehner eigenvalues "
        s2 = ""
        for Q in alev.keys():
            s2 += "\( \omega_{ %s } \) : %s <br>" % (Q, alev[Q])
        properties2.append((s1, s2))
        emf_logger.debug("properties={0}".format(properties2))
        # alev = WNF.atkin_lehner_eigenvalues_for_all_cusps() 
        # if isinstance(alev,dict) and len(alev.keys())>0:
        #     emf_logger.debug("alev={0}".format(alev))
        #     info['atkinlehner'] = list()
        #     for Q in alev.keys():
        #         s = "\(" + latex(c) + "\)"
        #         Q = alev[c][0]
        #         ev = alev[c][1]
        #         info['atkinlehner'].append([Q, c, ev])
    if(level == 1):
        poly = WNF.explicit_formulas.get('as_polynomial_in_E4_and_E6','')
        if poly != '':
            d,monom,coeffs = poly
            emf_logger.critical("poly={0}".format(poly))
            info['explicit_formulas'] = '\('
            for i in range(len(coeffs)):
                c = QQ(coeffs[i])
                s = ""
                if d>1 and i >0 and c>0:
                    s="+"
                if c<0:
                    s="-"
                if c.denominator()>1:
                    cc = "\\frac{{ {0} }}{{ {1} }}".format(abs(c.numerator()),c.denominator())
                else:
                    cc = str(abs(c))
                s += "{0} \cdot ".format(cc)
                a = monom[i][0]; b = monom[i][1]
                if a == 0 and b != 0:
                    s+="E_6^{{ {0} }}".format(b)
                elif b ==0 and a != 0:
                    s+="E_4^{{ {0} }}".format(a)
                else:
                    s+="E_4^{{ {0} }}E_6^{{ {1} }}".format(a,b)
                info['explicit_formulas'] += s
            info['explicit_formulas'] += " \)"            
    # cur_url = '?&level=' + str(level) + '&weight=' + str(weight) + '&character=' + str(character) + '&label=' + str(label) # never used
    if len(WNF.parent.hecke_orbits) > 1:
        for label_other in WNF.parent.hecke_orbits.keys():
            if(label_other != label):
                s = 'Modular form '
                if character:
                    s += newform_label(level,weight,character,label_other)
                else:
                    s += newform_label(level,weight,1,label_other)

                url = url_for('emf.render_elliptic_modular_forms', level=level,
                              weight=weight, character=character, label=label_other)
                friends.append((s, url))

    s = 'L-Function '
    if character:
        s += newform_label(level,weight,character,label)
    else:
        s += newform_label(level,weight,1,label)
    # url =
    # "/L/ModularForm/GL2/Q/holomorphic?level=%s&weight=%s&character=%s&label=%s&number=%s"
    # %(level,weight,character,label,0)
    url = '/L' + url_for(
        'emf.render_elliptic_modular_forms', level=level, weight=weight, character=character, label=label)
    if WNF.coefficient_field_degree > 1:
        for h in range(WNF.coefficient_field_degree):
            s0 = s + ".{0}".format(h)
            url0 = url + "{0}/".format(h)
            friends.append((s0, url0))
    else:
        friends.append((s, url))
    # if there is an elliptic curve over Q associated to self we also list that
    if WNF.weight == 2 and WNF.coefficient_field_degree == 1:
        llabel = str(level) + '.' + label
        s = 'Elliptic curve isogeny class ' + llabel
        url = '/EllipticCurve/Q/' + llabel
        friends.append((s, url))
    info['properties2'] = properties2
    info['friends'] = friends
    info['max_cn'] = WNF.max_available_prec()
    return info
Ejemplo n.º 20
0
    def make_curve(self):
        # To start with the data fields of self are just those from
        # the database.  We need to reformat these, construct the
        # actual elliptic curve E, and compute some further (easy)
        # data about it.
        #

        # Weierstrass equation

        data = self.data = {}
        data['ainvs'] = [int(ai) for ai in self.ainvs]
        self.E = EllipticCurve(data['ainvs'])
        data['equation'] = web_latex(self.E)

        # conductor, j-invariant and discriminant

        data['conductor'] = N = ZZ(self.conductor)
        bad_primes = N.prime_factors()
        try:
            data['j_invariant'] = QQ(str(self.jinv))
        except KeyError:
            data['j_invariant'] = self.E.j_invariant()
        data['j_inv_factor'] = latex(0)
        if data['j_invariant']:
            data['j_inv_factor'] = latex(data['j_invariant'].factor())
        data['j_inv_str'] = unicode(str(data['j_invariant']))
        data['j_inv_latex'] = web_latex(data['j_invariant'])
        data['disc'] = D = self.E.discriminant()
        data['disc_latex'] = web_latex(data['disc'])
        data['disc_factor'] = latex(data['disc'].factor())
        data['cond_factor'] =latex(N.factor())
        data['cond_latex'] = web_latex(N)

        # CM and endomorphism ring

        data['CMD'] = self.cm
        data['CM'] = "no"
        data['EndE'] = "\(\Z\)"
        if self.cm:
            data['CM'] = "yes (\(D=%s\))" % data['CMD']
            if data['CMD']%4==0:
                d4 = ZZ(data['CMD'])//4
                data['EndE'] = "\(\Z[\sqrt{%s}]\)" % d4
            else:
                data['EndE'] = "\(\Z[(1+\sqrt{%s})/2]\)" % data['CMD']
            data['ST'] = '<a href="%s">$%s$</a>' % (url_for('st.by_label', label='1.2.N(U(1))'),'N(\\mathrm{U}(1))')
        else:
            data['ST'] = '<a href="%s">$%s$</a>' % (url_for('st.by_label', label='1.2.SU(2)'),'\\mathrm{SU}(2)')

        # modular degree

        try:
            data['degree'] = self.degree
        except AttributeError:
            try:
                data['degree'] = self.E.modular_degree()
            except RuntimeError:
                data['degree']  # invalid, but will be displayed nicely

        # Minimal quadratic twist

        E_pari = self.E.pari_curve()
        from sage.libs.pari.all import PariError
        try:
            minq, minqD = self.E.minimal_quadratic_twist()
        except PariError:  # this does occur with 164411a1
            ec.debug("PariError computing minimal quadratic twist of elliptic curve %s" % lmfdb_label)
            minq = self.E
            minqD = 1
        data['minq_D'] = minqD
        if self.E == minq:
            data['minq_label'] = self.lmfdb_label
            data['minq_info'] = '(itself)'
        else:
            minq_ainvs = [str(c) for c in minq.ainvs()]
            data['minq_label'] = db_ec().find_one({'ainvs': minq_ainvs})['lmfdb_label']
            data['minq_info'] = '(by %s)' % minqD

        minq_N, minq_iso, minq_number = split_lmfdb_label(data['minq_label'])

        # rational and integral points

        mw = self.mw = {}

        xintpoints_projective = [self.E.lift_x(x) for x in self.xintcoords]
        xintpoints = [P.xy() for P in xintpoints_projective]
        mw['int_points'] = ', '.join(web_latex(P) for P in xintpoints)

        # Generators of infinite order

        mw['rank'] = self.rank
        try:
            self.generators = [self.E(g) for g in parse_points(self.gens)]
            mw['generators'] = [web_latex(P.xy()) for P in self.generators]
            mw['heights'] = [P.height() for P in self.generators]
        except AttributeError:
            mw['generators'] = ''
            mw['heights'] = []

        # Torsion subgroup: order, structure, generators

        mw['tor_order'] = self.torsion
        tor_struct = [int(c) for c in self.torsion_structure]
        if mw['tor_order'] == 1:
            mw['tor_struct'] = '\mathrm{Trivial}'
            mw['tor_gens'] = ''
        else:
            mw['tor_struct'] = ' \\times '.join(['\Z/{%s}\Z' % n
                                                 for n in tor_struct])
            mw['tor_gens'] = ', '.join(web_latex(self.E(g).xy()) for g in parse_points(self.torsion_generators))

        # Images of Galois representations

        try:
            data['galois_images'] = [trim_galois_image_code(s) for s in self.galois_images]
            data['non_surjective_primes'] = self.non_surjective_primes
        except AttributeError:
            #print "No Galois image data"
            data['galois_images'] = []
            data['non_surjective_primes'] = []

        data['galois_data'] = [{'p': p,'image': im }
                               for p,im in zip(data['non_surjective_primes'],
                                               data['galois_images'])]

        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 & BSD data

        bsd = self.bsd = {}

        r = self.rank
        if r >= 2:
            bsd['lder_name'] = "L^{(%s)}(E,1)/%s!" % (r,r)
        elif r:
            bsd['lder_name'] = "L'(E,1)"
        else:
            bsd['lder_name'] = "L(E,1)"

        bsd['reg'] = self.regulator
        bsd['omega'] = self.real_period
        bsd['sha'] = int(0.1+self.sha_an)
        bsd['lder'] = self.special_value

        # 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)

        if self.iso == '990h':
            data['Gamma0optimal'] = bool(self.number == 3)
        else:
            data['Gamma0optimal'] = bool(self.number == 1)


        data['p_adic_data_exists'] = False
        if data['Gamma0optimal']:
            data['p_adic_data_exists'] = (padic_db().find({'lmfdb_iso': self.lmfdb_iso}).count()) > 0
        data['p_adic_primes'] = [p for p in sage.all.prime_range(5, 100)
                                 if self.E.is_ordinary(p) and not p.divides(N)]

        # Local data

        local_data = self.local_data = []
        # if we use E.tamagawa_numbers() it calls E.local_data(p) which
        # used to crash on some curves e.g. 164411a1
        tamagawa_numbers = []
        for p in bad_primes:
            local_info = self.E.local_data(p, algorithm="generic")
            local_data_p = {}
            local_data_p['p'] = p
            local_data_p['tamagawa_number'] = local_info.tamagawa_number()
            tamagawa_numbers.append(ZZ(local_info.tamagawa_number()))
            local_data_p['kodaira_symbol'] = web_latex(local_info.kodaira_symbol()).replace('$', '')
            local_data_p['reduction_type'] = local_info.bad_reduction_type()
            local_data_p['ord_cond'] = local_info.conductor_valuation()
            local_data_p['ord_disc'] = local_info.discriminant_valuation()
            local_data_p['ord_den_j'] = max(0,-self.E.j_invariant().valuation(p))
            local_data.append(local_data_p)

        cp_fac = [cp.factor() for cp in tamagawa_numbers]
        cp_fac = [latex(cp) if len(cp)<2 else '('+latex(cp)+')' for cp in cp_fac]
        bsd['tamagawa_factors'] = r'\cdot'.join(cp_fac)
        bsd['tamagawa_product'] = sage.misc.all.prod(tamagawa_numbers)

        cond, iso, num = split_lmfdb_label(self.lmfdb_label)
        data['newform'] =  web_latex(self.E.q_eigenform(10))
        self.newform_label = newform_label(cond,2,1,iso)
        self.newform_link = url_for("emf.render_elliptic_modular_forms", level=cond, weight=2, character=1, label=iso)
        newform_exists_in_db = is_newform_in_db(self.newform_label)
        self._code = None

        self.friends = [
            ('Isogeny class ' + self.lmfdb_iso, url_for(".by_double_iso_label", conductor=N, iso_label=iso)),
            ('Minimal quadratic twist %s %s' % (data['minq_info'], data['minq_label']), url_for(".by_triple_label", conductor=minq_N, iso_label=minq_iso, number=minq_number)),
            ('All twists ', url_for(".rational_elliptic_curves", jinv=self.jinv)),
            ('L-function', url_for("l_functions.l_function_ec_page", label=self.lmfdb_label))]
        if not self.cm:
            if N<=300:
                self.friends += [('Symmetric square L-function', url_for("l_functions.l_function_ec_sym_page", power='2', label=self.lmfdb_iso))]
            if N<=50:
                self.friends += [('Symmetric cube L-function', url_for("l_functions.l_function_ec_sym_page", power='3', label=self.lmfdb_iso))]
        if newform_exists_in_db:
            self.friends += [('Modular form ' + self.newform_label, self.newform_link)]

        self.downloads = [('Download coefficients of q-expansion', url_for(".download_EC_qexp", label=self.lmfdb_label, limit=100)),
                          ('Download all stored data', url_for(".download_EC_all", label=self.lmfdb_label)),
                          ('Download Magma code', url_for(".ec_code_download", conductor=cond, iso=iso, number=num, label=self.lmfdb_label, download_type='magma')),
                          ('Download Sage code', url_for(".ec_code_download", conductor=cond, iso=iso, number=num, label=self.lmfdb_label, download_type='sage')),
                          ('Download GP code', url_for(".ec_code_download", conductor=cond, iso=iso, number=num, label=self.lmfdb_label, download_type='gp'))
        ]

        self.plot = encode_plot(self.E.plot())
        self.plot_link = '<img src="%s" width="200" height="150"/>' % self.plot
        self.properties = [('Label', self.lmfdb_label),
                           (None, self.plot_link),
                           ('Conductor', '\(%s\)' % data['conductor']),
                           ('Discriminant', '\(%s\)' % data['disc']),
                           ('j-invariant', '%s' % data['j_inv_latex']),
                           ('CM', '%s' % data['CM']),
                           ('Rank', '\(%s\)' % mw['rank']),
                           ('Torsion Structure', '\(%s\)' % mw['tor_struct'])
                           ]

        self.title = "Elliptic Curve %s (Cremona label %s)" % (self.lmfdb_label, self.label)

        self.bread = [('Elliptic Curves', url_for("ecnf.index")),
                           ('$\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,' ')]