Exemplo n.º 1
0
def render_curve_webpage_by_label(label):
    C = lmfdb.base.getDBConnection()
    data = C.elliptic_curves.curves.find_one({'lmfdb_label': label})
    if data is None:
        return elliptic_curve_jump_error(label, {})
    info = {}
    ainvs = [int(a) for a in data['ainvs']]
    E = EllipticCurve(ainvs)
    cremona_label = data['label']
    lmfdb_label = data['lmfdb_label']
    N = ZZ(data['conductor'])
    cremona_iso_class = data['iso']  # eg '37a'
    lmfdb_iso_class = data['lmfdb_iso']  # eg '37.a'
    rank = data['rank']
    try:
        j_invariant = QQ(str(data['jinv']))
    except KeyError:
        j_invariant = E.j_invariant()
    if j_invariant == 0:
        j_inv_factored = latex(0)
    else:
        j_inv_factored = latex(j_invariant.factor())
    jinv = unicode(str(j_invariant))
    CMD = 0
    CM = "no"
    EndE = "\(\Z\)"
    if E.has_cm():
        CMD = E.cm_discriminant()
        CM = "yes (\(%s\))"%CMD
        if CMD%4==0:
            d4 = ZZ(CMD)//4
            # r = d4.squarefree_part()
            # f = (d4//r).isqrt()
            # f="" if f==1 else str(f)
            # EndE = "\(\Z[%s\sqrt{%s}]\)"%(f,r)
            EndE = "\(\Z[\sqrt{%s}]\)"%(d4)
        else:            
            EndE = "\(\Z[(1+\sqrt{%s})/2]\)"%CMD

    # plot=E.plot()
    discriminant = E.discriminant()
    xintpoints_projective = [E.lift_x(x) for x in xintegral_point(data['x-coordinates_of_integral_points'])]
    xintpoints = proj_to_aff(xintpoints_projective)
    if 'degree' in data:
        modular_degree = data['degree']
    else:
        try:
            modular_degree = E.modular_degree()
        except RuntimeError:
            modular_degree = 0  # invalid, will be displayed nicely

    G = E.torsion_subgroup().gens()
    minq = E.minimal_quadratic_twist()[0]
    if E == minq:
        minq_label = lmfdb_label
    else:
        minq_ainvs = [str(c) for c in minq.ainvs()]
        minq_label = C.elliptic_curves.curves.find_one({'ainvs': minq_ainvs})['lmfdb_label']
# We do not just do the following, as Sage's installed database
# might not have all the curves in the LMFDB database.
# minq_label = E.minimal_quadratic_twist()[0].label()

    if 'gens' in data:
        generator = parse_gens(data['gens'])
    if len(G) == 0:
        tor_struct = '\mathrm{Trivial}'
        tor_group = '\mathrm{Trivial}'
    else:
        tor_group = ' \\times '.join(['\Z/{%s}\Z' % a.order() for a in G])
    if 'torsion_structure' in data:
        info['tor_structure'] = ' \\times '.join(['\Z/{%s}\Z' % int(a) for a in data['torsion_structure']])
    else:
        info['tor_structure'] = tor_group

    info.update(data)
    if rank >= 2:
        lder_tex = "L%s(E,1)" % ("^{(" + str(rank) + ")}")
    elif rank == 1:
        lder_tex = "L%s(E,1)" % ("'" * rank)
    else:
        assert rank == 0
        lder_tex = "L(E,1)"
    info['Gamma0optimal'] = (
        cremona_label[-1] == '1' if cremona_iso_class != '990h' else cremona_label[-1] == '3')
    info['modular_degree'] = modular_degree
    p_adic_data_exists = (C.elliptic_curves.padic_db.find(
        {'lmfdb_iso': lmfdb_iso_class}).count()) > 0 and info['Gamma0optimal']

    # Local data
    local_data = []
    for p in N.prime_factors():
        local_info = E.local_data(p)
        local_data.append({'p': p,
                           'tamagawa_number': local_info.tamagawa_number(),
                           'kodaira_symbol': web_latex(local_info.kodaira_symbol()).replace('$', ''),
                           'reduction_type': local_info.bad_reduction_type()
                           })

    mod_form_iso = lmfdb_label_regex.match(lmfdb_iso_class).groups()[1]

    info.update({
        'conductor': N,
        'disc_factor': latex(discriminant.factor()),
        'j_invar_factor': j_inv_factored,
        'label': lmfdb_label,
        'cremona_label': cremona_label,
        'iso_class': lmfdb_iso_class,
        'cremona_iso_class': cremona_iso_class,
        'equation': web_latex(E),
        #'f': ajax_more(E.q_eigenform, 10, 20, 50, 100, 250),
        'f': web_latex(E.q_eigenform(10)),
        'generators': ', '.join(web_latex(g) for g in generator) if 'gens' in data else ' ',
        'lder': lder_tex,
        'p_adic_primes': [p for p in sage.all.prime_range(5, 100) if E.is_ordinary(p) and not p.divides(N)],
        'p_adic_data_exists': p_adic_data_exists,
        'ainvs': format_ainvs(data['ainvs']),
        'CM': CM,
        'CMD': CMD,
        'EndE': EndE,
        'tamagawa_numbers': r' \cdot '.join(str(sage.all.factor(c)) for c in E.tamagawa_numbers()),
        'local_data': local_data,
        'cond_factor': latex(N.factor()),
        'xintegral_points': ', '.join(web_latex(P) for P in xintpoints),
        'tor_gens': ', '.join(web_latex(eval(g)) for g in data['torsion_generators']) if False else ', '.join(web_latex(P.element().xy()) for P in list(G))
    })
    info['friends'] = [
        ('Isogeny class ' + lmfdb_iso_class, "/EllipticCurve/Q/%s" % lmfdb_iso_class),
        ('Minimal quadratic twist ' + minq_label, "/EllipticCurve/Q/%s" % minq_label),
        ('All twists ', url_for("rational_elliptic_curves", jinv=jinv)),
        ('L-function', url_for("l_functions.l_function_ec_page", label=lmfdb_label)),
        ('Symmetric square L-function', url_for("l_functions.l_function_ec_sym_page", power='2',
                                                label=lmfdb_iso_class)),
        ('Symmetric 4th power L-function', url_for("l_functions.l_function_ec_sym_page", power='4',
                                                   label=lmfdb_iso_class))]

    info['friends'].append(('Modular form ' + lmfdb_iso_class.replace('.', '.2'), url_for(
        "emf.render_elliptic_modular_forms", level=int(N), weight=2, character=0, label=mod_form_iso)))

    info['downloads'] = [('Download coeffients of q-expansion', url_for("download_EC_qexp", label=lmfdb_label, limit=100)),
                         ('Download all stored data', url_for("download_EC_all", label=lmfdb_label))]

    # info['learnmore'] = [('Elliptic Curves', url_for("not_yet_implemented"))]
    # info['plot'] = image_src(plot)
    info['plot'] = url_for('plot_ec', label=lmfdb_label)

    properties2 = [('Label', '%s' % lmfdb_label),
                   (None, '<img src="%s" width="200" height="150"/>' % url_for(
                       'plot_ec', label=lmfdb_label)),
                   ('Conductor', '\(%s\)' % N),
                   ('Discriminant', '\(%s\)' % discriminant),
                   ('j-invariant', '%s' % web_latex(j_invariant)),
                   ('CM', '%s' % CM),
                   ('Rank', '\(%s\)' % rank),
                   ('Torsion Structure', '\(%s\)' % tor_group)
                   ]
    # properties.extend([ "prop %s = %s<br/>" % (_,_*1923) for _ in range(12) ])
    credit = 'John Cremona'
    if info['label'] == info['cremona_label']:
        t = "Elliptic Curve %s" % info['label']
    else:
        t = "Elliptic Curve %s (Cremona label %s)" % (info['label'], info['cremona_label'])

    bread = [('Elliptic Curves ', url_for("rational_elliptic_curves")), ('Elliptic curves %s' %
             lmfdb_label, ' ')]

    return render_template("elliptic_curve/elliptic_curve.html",
                           properties2=properties2, credit=credit, bread=bread, title=t, info=info, friends=info['friends'], downloads=info['downloads'])
Exemplo n.º 2
0
def render_curve_webpage_by_label(label):
    C = lmfdb.base.getDBConnection()
    data = C.elliptic_curves.curves.find_one({'lmfdb_label': label})
    if data is None:
        return elliptic_curve_jump_error(label, {})
    info = {}
    ainvs = [int(a) for a in data['ainvs']]
    E = EllipticCurve(ainvs)
    cremona_label = data['label']
    lmfdb_label = data['lmfdb_label']
    N = ZZ(data['conductor'])
    cremona_iso_class = data['iso']  # eg '37a'
    lmfdb_iso_class = data['lmfdb_iso']  # eg '37.a'
    rank = data['rank']
    try:
        j_invariant = QQ(str(data['jinv']))
    except KeyError:
        j_invariant = E.j_invariant()
    if j_invariant == 0:
        j_inv_factored = latex(0)
    else:
        j_inv_factored = latex(j_invariant.factor())
    jinv = unicode(str(j_invariant))
    CMD = 0
    CM = "no"
    EndE = "\(\Z\)"
    if E.has_cm():
        CMD = E.cm_discriminant()
        CM = "yes (\(%s\))" % CMD
        if CMD % 4 == 0:
            d4 = ZZ(CMD) // 4
            # r = d4.squarefree_part()
            # f = (d4//r).isqrt()
            # f="" if f==1 else str(f)
            # EndE = "\(\Z[%s\sqrt{%s}]\)"%(f,r)
            EndE = "\(\Z[\sqrt{%s}]\)" % (d4)
        else:
            EndE = "\(\Z[(1+\sqrt{%s})/2]\)" % CMD

    # plot=E.plot()
    discriminant = E.discriminant()
    xintpoints_projective = [
        E.lift_x(x)
        for x in xintegral_point(data['x-coordinates_of_integral_points'])
    ]
    xintpoints = proj_to_aff(xintpoints_projective)
    if 'degree' in data:
        modular_degree = data['degree']
    else:
        try:
            modular_degree = E.modular_degree()
        except RuntimeError:
            modular_degree = 0  # invalid, will be displayed nicely

    G = E.torsion_subgroup().gens()
    E_pari = E.pari_curve(prec=200)
    from sage.libs.pari.all import PariError
    try:
        minq = E.minimal_quadratic_twist()[0]
    except PariError:  # this does occur with 164411a1
        print "PariError computing minimal quadratic twist of elliptic curve %s" % lmfdb_label
        minq = E
    if E == minq:
        minq_label = lmfdb_label
    else:
        minq_ainvs = [str(c) for c in minq.ainvs()]
        minq_label = C.elliptic_curves.curves.find_one({'ainvs': minq_ainvs
                                                        })['lmfdb_label']


# We do not just do the following, as Sage's installed database
# might not have all the curves in the LMFDB database.
# minq_label = E.minimal_quadratic_twist()[0].label()

    if 'gens' in data:
        generator = parse_gens(data['gens'])
    if len(G) == 0:
        tor_struct = '\mathrm{Trivial}'
        tor_group = '\mathrm{Trivial}'
    else:
        tor_group = ' \\times '.join(['\Z/{%s}\Z' % a.order() for a in G])
    if 'torsion_structure' in data:
        info['tor_structure'] = ' \\times '.join(
            ['\Z/{%s}\Z' % int(a) for a in data['torsion_structure']])
    else:
        info['tor_structure'] = tor_group

    def trim_galois_image_code(s):
        return s[2:] if s[1].isdigit() else s[1:]

    if 'galois_images' in data:
        galois_images = data['galois_images']
        galois_images = [trim_galois_image_code(s) for s in galois_images]
        non_surjective_primes = data['non-surjective_primes']

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

    info.update(data)
    if rank >= 2:
        lder_tex = "L%s(E,1)" % ("^{(" + str(rank) + ")}")
    elif rank == 1:
        lder_tex = "L%s(E,1)" % ("'" * rank)
    else:
        assert rank == 0
        lder_tex = "L(E,1)"
    info['Gamma0optimal'] = (cremona_label[-1] == '1'
                             if cremona_iso_class != '990h' else
                             cremona_label[-1] == '3')
    info['modular_degree'] = modular_degree
    p_adic_data_exists = (C.elliptic_curves.padic_db.find({
        'lmfdb_iso':
        lmfdb_iso_class
    }).count()) > 0 and info['Gamma0optimal']

    # Local data
    local_data = []
    for p in N.prime_factors():
        local_info = E.local_data(p, algorithm="generic")
        local_data.append({
            'p':
            p,
            'tamagawa_number':
            local_info.tamagawa_number(),
            'kodaira_symbol':
            web_latex(local_info.kodaira_symbol()).replace('$', ''),
            'reduction_type':
            local_info.bad_reduction_type()
        })

    mod_form_iso = lmfdb_label_regex.match(lmfdb_iso_class).groups()[1]

    tamagawa_numbers = [
        E.local_data(p, algorithm="generic").tamagawa_number()
        for p in N.prime_factors()
    ]
    # if we use E.tamagawa_numbers() it calls E.local_data(p) which
    # crashes on some curves e.g. 164411a1
    info.update({
        'conductor':
        N,
        'disc_factor':
        latex(discriminant.factor()),
        'j_invar_factor':
        j_inv_factored,
        'label':
        lmfdb_label,
        'cremona_label':
        cremona_label,
        'iso_class':
        lmfdb_iso_class,
        'cremona_iso_class':
        cremona_iso_class,
        'equation':
        web_latex(E),
        #'f': ajax_more(E.q_eigenform, 10, 20, 50, 100, 250),
        'f':
        web_latex(E.q_eigenform(10)),
        'generators':
        ', '.join(web_latex(g) for g in generator) if 'gens' in data else ' ',
        'lder':
        lder_tex,
        'p_adic_primes': [
            p for p in sage.all.prime_range(5, 100)
            if E.is_ordinary(p) and not p.divides(N)
        ],
        'p_adic_data_exists':
        p_adic_data_exists,
        'ainvs':
        format_ainvs(data['ainvs']),
        'CM':
        CM,
        'CMD':
        CMD,
        'EndE':
        EndE,
        'tamagawa_numbers':
        r' \cdot '.join(str(sage.all.factor(c)) for c in tamagawa_numbers),
        'local_data':
        local_data,
        'cond_factor':
        latex(N.factor()),
        'galois_data':
        galois_data,
        'xintegral_points':
        ', '.join(web_latex(P) for P in xintpoints),
        'tor_gens':
        ', '.join(web_latex(eval(g))
                  for g in data['torsion_generators']) if False else ', '.join(
                      web_latex(P.element().xy()) for P in list(G))
    })
    info['friends'] = [('Isogeny class ' + lmfdb_iso_class,
                        url_for(".by_ec_label", label=lmfdb_iso_class)),
                       ('Minimal quadratic twist ' + minq_label,
                        url_for(".by_ec_label", label=minq_label)),
                       ('All twists ',
                        url_for(".rational_elliptic_curves", jinv=jinv)),
                       ('L-function',
                        url_for("l_functions.l_function_ec_page",
                                label=lmfdb_label)),
                       ('Symmetric square L-function',
                        url_for("l_functions.l_function_ec_sym_page",
                                power='2',
                                label=lmfdb_iso_class)),
                       ('Symmetric 4th power L-function',
                        url_for("l_functions.l_function_ec_sym_page",
                                power='4',
                                label=lmfdb_iso_class))]

    info['friends'].append(
        ('Modular form ' + lmfdb_iso_class.replace('.', '.2'),
         url_for("emf.render_elliptic_modular_forms",
                 level=int(N),
                 weight=2,
                 character=0,
                 label=mod_form_iso)))

    info['downloads'] = [('Download coeffients of q-expansion',
                          url_for(".download_EC_qexp",
                                  label=lmfdb_label,
                                  limit=100)),
                         ('Download all stored data',
                          url_for(".download_EC_all", label=lmfdb_label))]

    # info['learnmore'] = [('Elliptic Curves', url_for(".not_yet_implemented"))]
    # info['plot'] = image_src(plot)
    info['plot'] = url_for('.plot_ec', label=lmfdb_label)

    properties2 = [('Label', '%s' % lmfdb_label),
                   (None, '<img src="%s" width="200" height="150"/>' %
                    url_for('.plot_ec', label=lmfdb_label)),
                   ('Conductor', '\(%s\)' % N),
                   ('Discriminant', '\(%s\)' % discriminant),
                   ('j-invariant', '%s' % web_latex(j_invariant)),
                   ('CM', '%s' % CM), ('Rank', '\(%s\)' % rank),
                   ('Torsion Structure', '\(%s\)' % tor_group)]
    # properties.extend([ "prop %s = %s<br/>" % (_,_*1923) for _ in range(12) ])
    credit = 'John Cremona and Andrew Sutherland'
    if info['label'] == info['cremona_label']:
        t = "Elliptic Curve %s" % info['label']
    else:
        t = "Elliptic Curve %s (Cremona label %s)" % (info['label'],
                                                      info['cremona_label'])

    bread = [('Elliptic Curves ', url_for(".rational_elliptic_curves")),
             ('Elliptic curves %s' % lmfdb_label, ' ')]

    return render_template("curve.html",
                           properties2=properties2,
                           credit=credit,
                           bread=bread,
                           title=t,
                           info=info,
                           friends=info['friends'],
                           downloads=info['downloads'])
Exemplo n.º 3
0
def render_curve_webpage_by_label(label):
    C = lmfdb.base.getDBConnection()
    data = C.elliptic_curves.curves.find_one({"lmfdb_label": label})
    if data is None:
        return elliptic_curve_jump_error(label, {})
    info = {}
    ainvs = [int(a) for a in data["ainvs"]]
    E = EllipticCurve(ainvs)
    cremona_label = data["label"]
    lmfdb_label = data["lmfdb_label"]
    N = ZZ(data["conductor"])
    cremona_iso_class = data["iso"]  # eg '37a'
    lmfdb_iso_class = data["lmfdb_iso"]  # eg '37.a'
    rank = data["rank"]
    try:
        j_invariant = QQ(str(data["jinv"]))
    except KeyError:
        j_invariant = E.j_invariant()
    if j_invariant == 0:
        j_inv_factored = latex(0)
    else:
        j_inv_factored = latex(j_invariant.factor())
    jinv = unicode(str(j_invariant))
    CMD = 0
    CM = "no"
    EndE = "\(\Z\)"
    if E.has_cm():
        CMD = E.cm_discriminant()
        CM = "yes (\(%s\))" % CMD
        if CMD % 4 == 0:
            d4 = ZZ(CMD) // 4
            # r = d4.squarefree_part()
            # f = (d4//r).isqrt()
            # f="" if f==1 else str(f)
            # EndE = "\(\Z[%s\sqrt{%s}]\)"%(f,r)
            EndE = "\(\Z[\sqrt{%s}]\)" % (d4)
        else:
            EndE = "\(\Z[(1+\sqrt{%s})/2]\)" % CMD

    # plot=E.plot()
    discriminant = E.discriminant()
    xintpoints_projective = [E.lift_x(x) for x in xintegral_point(data["x-coordinates_of_integral_points"])]
    xintpoints = proj_to_aff(xintpoints_projective)
    if "degree" in data:
        modular_degree = data["degree"]
    else:
        try:
            modular_degree = E.modular_degree()
        except RuntimeError:
            modular_degree = 0  # invalid, will be displayed nicely

    G = E.torsion_subgroup().gens()
    E_pari = E.pari_curve(prec=200)
    from sage.libs.pari.all import PariError

    try:
        minq = E.minimal_quadratic_twist()[0]
    except PariError:  # this does occur with 164411a1
        print "PariError computing minimal quadratic twist of elliptic curve %s" % lmfdb_label
        minq = E
    if E == minq:
        minq_label = lmfdb_label
    else:
        minq_ainvs = [str(c) for c in minq.ainvs()]
        minq_label = C.elliptic_curves.curves.find_one({"ainvs": minq_ainvs})["lmfdb_label"]
    # We do not just do the following, as Sage's installed database
    # might not have all the curves in the LMFDB database.
    # minq_label = E.minimal_quadratic_twist()[0].label()

    if "gens" in data:
        generator = parse_gens(data["gens"])
    if len(G) == 0:
        tor_struct = "\mathrm{Trivial}"
        tor_group = "\mathrm{Trivial}"
    else:
        tor_group = " \\times ".join(["\Z/{%s}\Z" % a.order() for a in G])
    if "torsion_structure" in data:
        info["tor_structure"] = " \\times ".join(["\Z/{%s}\Z" % int(a) for a in data["torsion_structure"]])
    else:
        info["tor_structure"] = tor_group

    info.update(data)
    if rank >= 2:
        lder_tex = "L%s(E,1)" % ("^{(" + str(rank) + ")}")
    elif rank == 1:
        lder_tex = "L%s(E,1)" % ("'" * rank)
    else:
        assert rank == 0
        lder_tex = "L(E,1)"
    info["Gamma0optimal"] = cremona_label[-1] == "1" if cremona_iso_class != "990h" else cremona_label[-1] == "3"
    info["modular_degree"] = modular_degree
    p_adic_data_exists = (C.elliptic_curves.padic_db.find({"lmfdb_iso": lmfdb_iso_class}).count()) > 0 and info[
        "Gamma0optimal"
    ]

    # Local data
    local_data = []
    for p in N.prime_factors():
        local_info = E.local_data(p, algorithm="generic")
        local_data.append(
            {
                "p": p,
                "tamagawa_number": local_info.tamagawa_number(),
                "kodaira_symbol": web_latex(local_info.kodaira_symbol()).replace("$", ""),
                "reduction_type": local_info.bad_reduction_type(),
            }
        )

    mod_form_iso = lmfdb_label_regex.match(lmfdb_iso_class).groups()[1]

    tamagawa_numbers = [E.local_data(p, algorithm="generic").tamagawa_number() for p in N.prime_factors()]
    # if we use E.tamagawa_numbers() it calls E.local_data(p) which
    # crashes on some curves e.g. 164411a1
    info.update(
        {
            "conductor": N,
            "disc_factor": latex(discriminant.factor()),
            "j_invar_factor": j_inv_factored,
            "label": lmfdb_label,
            "cremona_label": cremona_label,
            "iso_class": lmfdb_iso_class,
            "cremona_iso_class": cremona_iso_class,
            "equation": web_latex(E),
            #'f': ajax_more(E.q_eigenform, 10, 20, 50, 100, 250),
            "f": web_latex(E.q_eigenform(10)),
            "generators": ", ".join(web_latex(g) for g in generator) if "gens" in data else " ",
            "lder": lder_tex,
            "p_adic_primes": [p for p in sage.all.prime_range(5, 100) if E.is_ordinary(p) and not p.divides(N)],
            "p_adic_data_exists": p_adic_data_exists,
            "ainvs": format_ainvs(data["ainvs"]),
            "CM": CM,
            "CMD": CMD,
            "EndE": EndE,
            "tamagawa_numbers": r" \cdot ".join(str(sage.all.factor(c)) for c in tamagawa_numbers),
            "local_data": local_data,
            "cond_factor": latex(N.factor()),
            "xintegral_points": ", ".join(web_latex(P) for P in xintpoints),
            "tor_gens": ", ".join(web_latex(eval(g)) for g in data["torsion_generators"])
            if False
            else ", ".join(web_latex(P.element().xy()) for P in list(G)),
        }
    )
    info["friends"] = [
        ("Isogeny class " + lmfdb_iso_class, "/EllipticCurve/Q/%s" % lmfdb_iso_class),
        ("Minimal quadratic twist " + minq_label, "/EllipticCurve/Q/%s" % minq_label),
        ("All twists ", url_for("rational_elliptic_curves", jinv=jinv)),
        ("L-function", url_for("l_functions.l_function_ec_page", label=lmfdb_label)),
        (
            "Symmetric square L-function",
            url_for("l_functions.l_function_ec_sym_page", power="2", label=lmfdb_iso_class),
        ),
        (
            "Symmetric 4th power L-function",
            url_for("l_functions.l_function_ec_sym_page", power="4", label=lmfdb_iso_class),
        ),
    ]

    info["friends"].append(
        (
            "Modular form " + lmfdb_iso_class.replace(".", ".2"),
            url_for("emf.render_elliptic_modular_forms", level=int(N), weight=2, character=0, label=mod_form_iso),
        )
    )

    info["downloads"] = [
        ("Download coeffients of q-expansion", url_for("download_EC_qexp", label=lmfdb_label, limit=100)),
        ("Download all stored data", url_for("download_EC_all", label=lmfdb_label)),
    ]

    # info['learnmore'] = [('Elliptic Curves', url_for("not_yet_implemented"))]
    # info['plot'] = image_src(plot)
    info["plot"] = url_for("plot_ec", label=lmfdb_label)

    properties2 = [
        ("Label", "%s" % lmfdb_label),
        (None, '<img src="%s" width="200" height="150"/>' % url_for("plot_ec", label=lmfdb_label)),
        ("Conductor", "\(%s\)" % N),
        ("Discriminant", "\(%s\)" % discriminant),
        ("j-invariant", "%s" % web_latex(j_invariant)),
        ("CM", "%s" % CM),
        ("Rank", "\(%s\)" % rank),
        ("Torsion Structure", "\(%s\)" % tor_group),
    ]
    # properties.extend([ "prop %s = %s<br/>" % (_,_*1923) for _ in range(12) ])
    credit = "John Cremona"
    if info["label"] == info["cremona_label"]:
        t = "Elliptic Curve %s" % info["label"]
    else:
        t = "Elliptic Curve %s (Cremona label %s)" % (info["label"], info["cremona_label"])

    bread = [("Elliptic Curves ", url_for("rational_elliptic_curves")), ("Elliptic curves %s" % lmfdb_label, " ")]

    return render_template(
        "elliptic_curve/elliptic_curve.html",
        properties2=properties2,
        credit=credit,
        bread=bread,
        title=t,
        info=info,
        friends=info["friends"],
        downloads=info["downloads"],
    )