Пример #1
0
def url_for_ec_class(ec_label):
    if not '-' in ec_label:
        (cond, iso, num) = split_lmfdb_label(ec_label)
        return url_for('ec.by_double_iso_label', conductor=cond, iso_label=iso)
    else:
        (nf, cond, iso, num) = split_full_label(ec_label)
        return url_for('ecnf.show_ecnf_isoclass', nf=nf, conductor_label=cond, class_label=iso)
Пример #2
0
def url_for_ec(label):
    if not '-' in label:
        return url_for('ec.by_ec_label', label = label)
    else:
        (nf, conductor_label, class_label, number) = split_full_label(label)
        return url_for('ecnf.show_ecnf', nf = nf, conductor_label =
                conductor_label, class_label = class_label, number = number)
Пример #3
0
def url_for_ec(label):
    if not '-' in label:
        return url_for('ec.by_ec_label', label = label)
    else:
        (nf, conductor_label, class_label, number) = split_full_label(label)
        return url_for('ecnf.show_ecnf', nf = nf, conductor_label =
                conductor_label, class_label = class_label, number = number)
Пример #4
0
def url_for_ec_class(ec_label):
    if not '-' in ec_label:
        (cond, iso, num) = split_lmfdb_label(ec_label)
        return url_for('ec.by_double_iso_label', conductor=cond, iso_label=iso)
    else:
        (nf, cond, iso, num) = split_full_label(ec_label)
        return url_for('ecnf.show_ecnf_isoclass', nf=nf, conductor_label=cond, class_label=iso)
Пример #5
0
    def make_torsion_growth(self):
        try:
            tor_gro = self.tor_gro
            self.torsion_growth_data_exists = True
        except AttributeError:
            self.torsion_growth_data_exists = False
            return

        self.tg = tg = {}
        tg['data'] = tgextra = []
        # find all base-changes of this curve in the database, if any
        from lmfdb.ecnf.WebEllipticCurve import db_ecnf
        bcs = [
            res['label']
            for res in db_ecnf().find({'base_change': self.lmfdb_label},
                                      projection={
                                          'label': True,
                                          '_id': False
                                      })
        ]
        bcfs = [lab.split("-")[0] for lab in bcs]
        for F, T in tor_gro.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'])
        tg['n'] = len(tgextra)
        lastd = 1
        for tg1 in tgextra:
            d = tg1['d']
            if d != lastd:
                tg1['m'] = len([x for x in tgextra if x['d'] == d])
                lastd = d
        tg['maxd'] = max(db_ecstats().find_one({'_id':
                                                'torsion_growth'})['degrees'])
Пример #6
0
def url_for_ec(label):
    if not '-' in label:
        # Convert to LMFDB label on next run:
        (conductor_label, class_label, number) = split_cremona_label(label)
        return url_for('ecnf.show_ecnf', nf = 'Q', conductor_label =
                conductor_label, class_label = class_label, number = number)
    else:
        (nf, conductor_label, class_label, number) = split_full_label(label)
        return url_for('ecnf.show_ecnf', nf = nf, conductor_label =
                conductor_label, class_label = class_label, number = number)
Пример #7
0
def url_for_ec(label):
    if not '-' in label:
        return url_for('ec.by_ec_label', label = label)
    else:
        (nf, conductor_label, class_label, number) = split_full_label(label)
        url = url_for('ecnf.show_ecnf', nf = nf, conductor_label = conductor_label, class_label = class_label, number = number)
        # fixup conductor norm labels for the form "[a,b,c]" that have been converted to urls to ensure friend matching works
        url.replace("%5B","[")
        url.replace("%2C",".")
        url.replace("%5D","]")
        return url
Пример #8
0
def url_for_ec(label):
    if not '-' in label:
        return url_for('ec.by_ec_label', label = label)
    else:
        (nf, conductor_label, class_label, number) = split_full_label(label)
        url = url_for('ecnf.show_ecnf', nf = nf, conductor_label = conductor_label, class_label = class_label, number = number)
        # fixup conductor norm labels for the form "[a,b,c]" that have been converted to urls to ensure friend matching works
        url.replace("%5B","[")
        url.replace("%2C",".")
        url.replace("%5D","]")
        return url
Пример #9
0
    def make_torsion_growth(self):
        if self.tor_gro is None:
            self.torsion_growth_data_exists = False
            return
        tor_gro = self.tor_gro
        self.torsion_growth_data_exists = True
        self.tg = tg = {}
        tg['data'] = tgextra = []
        # find all base-changes of this curve in the database, if any
        bcs = list(db.ec_nfcurves.search({'base_change': {'$contains': [self.lmfdb_label]}}, projection='label'))
        bcfs = [lab.split("-")[0] for lab in bcs]
        for F, T in tor_gro.items():
            tg1 = {}
            tg1['bc'] = "Not in database"
            if ":" in F:
                F = F.replace(":",".")
                field_data = nf_display_knowl(F, 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'])
        tg['n'] = len(tgextra)
        lastd = 1
        for tg1 in tgextra:
            d = tg1['d']
            if d!=lastd:
                tg1['m'] = len([x for x in tgextra if x['d']==d])
                lastd = d

        ## Hard-code this for now.  While something like
        ## max(db.ec_curves.search({},projection='tor_degs')) might
        ## work, since 'tor_degs' is in the extra table it is very
        ## slow.  Note that the *only* place where this number is used
        ## is in the ec-curve template where it says "The number
        ## fields ... of degree up to {{data.tg.maxd}} such that...".
        
        tg['maxd'] = 7
Пример #10
0
    def make_torsion_growth(self):
        try:
            tor_gro = self.tor_gro
            self.torsion_growth_data_exists = True
        except AttributeError:
            self.torsion_growth_data_exists = False
            return

        self.tg = tg = {}
        tg['data'] = tgextra = []
        # find all base-changes of this curve in the database, if any
        from lmfdb.ecnf.WebEllipticCurve import db_ecnf
        bcs = [res['label'] for res in  db_ecnf().find({'base_change': self.lmfdb_label}, projection={'label': True, '_id': False})]
        bcfs = [lab.split("-")[0] for lab in bcs]
        for F, T in tor_gro.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'])
        tg['n'] = len(tgextra)
        lastd = 1
        for tg1 in tgextra:
            d = tg1['d']
            if d!=lastd:
                tg1['m'] = len([x for x in tgextra if x['d']==d])
                lastd = d
        tg['maxd'] = max(db_ecstats().find_one({'_id': 'torsion_growth'})['degrees'])
Пример #11
0
    def make_torsion_growth(self):
        if self.tor_gro is None:
            self.torsion_growth_data_exists = False
            return
        tor_gro = self.tor_gro
        self.torsion_growth_data_exists = True
        self.tg = tg = {}
        tg['data'] = tgextra = []
        # find all base-changes of this curve in the database, if any
        bcs = list(db.ec_nfcurves.search({'base_change': {'$contains': [self.lmfdb_label]}}, projection='label'))
        bcfs = [lab.split("-")[0] for lab in bcs]
        for F, T in tor_gro.items():
            tg1 = {}
            tg1['bc'] = "Not in database"
            if ":" in F:
                F = F.replace(":",".")
                field_data = nf_display_knowl(F, 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'])
        tg['n'] = len(tgextra)
        lastd = 1
        for tg1 in tgextra:
            d = tg1['d']
            if d!=lastd:
                tg1['m'] = len([x for x in tgextra if x['d']==d])
                lastd = d
        ## Hard code for now
        #tg['maxd'] = max(db.ec_curves.stats.get_oldstat('torsion_growth')['degrees'])
        tg['maxd'] = 7
Пример #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
            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, ' ')]