Example #1
0
    def make_object(self, curve, endo, tama, ratpts, is_curve):
        from lmfdb.genus2_curves.main import url_for_curve_label

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

        # first deal with EC
        ecs = []
        if 'split_labels' in data:
            for friend_label in data['split_labels']:
                if is_curve:
                    ecs.append(("Elliptic curve " + friend_label,
                                url_for_ec(friend_label)))
                else:
                    ecs.append(
                        ("Isogeny class " + ec_label_class(friend_label),
                         url_for_ec_class(friend_label)))

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

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

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

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

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

        # Title
        self.title = "Genus 2 " + ("Curve " if is_curve else
                                   "Isogeny Class ") + data['label']

        # Code snippets (only for curves)
        if not is_curve:
            return
        self.code = code = {}
        code['show'] = {'sage': '', 'magma': ''}  # use default show names
        f, h = fh = data['min_eqn']
        g = simplify_hyperelliptic(fh)
        code['curve'] = {
            'sage':
            'R.<x> = PolynomialRing(QQ); C = HyperellipticCurve(R(%s), R(%s));'
            % (f, h),
            'magma':
            'R<x> := PolynomialRing(Rationals()); C := HyperellipticCurve(R!%s, R!%s);'
            % (f, h)
        }
        code['simple_curve'] = {
            'sage': 'X = HyperellipticCurve(R(%s))' % (g),
            'magma': 'X,pi:= SimplifiedModel(C);'
        }
        if data['abs_disc'] % 4096 == 0:
            ind2 = [a[0] for a in data['bad_lfactors']].index(2)
            bad2 = data['bad_lfactors'][ind2][1]
            magma_cond_option = ': ExcFactors:=[*<2,Valuation(' + str(
                data['cond']) + ',2),R!' + str(bad2) + '>*]'
        else:
            magma_cond_option = ''
        code['cond'] = {
            'magma':
            'Conductor(LSeries(C%s)); Factorization($1);' % magma_cond_option
        }
        code['disc'] = {
            'magma': 'Discriminant(C); Factorization(Integers()!$1);'
        }
        code['geom_inv'] = {
            'sage':
            'C.igusa_clebsch_invariants(); [factor(a) for a in _]',
            'magma':
            'IgusaClebschInvariants(C); IgusaInvariants(C); G2Invariants(C);'
        }
        code['aut'] = {'magma': 'AutomorphismGroup(C); IdentifyGroup($1);'}
        code['autQbar'] = {
            'magma':
            'AutomorphismGroup(ChangeRing(C,AlgebraicClosure(Rationals()))); IdentifyGroup($1);'
        }
        code['num_rat_wpts'] = {
            'magma': '#Roots(HyperellipticPolynomials(SimplifiedModel(C)));'
        }
        if ratpts:
            code['rat_pts'] = {
                'magma':
                '[' + ','.join([
                    "C![%s,%s,%s]" % (p[0], p[1], p[2])
                    for p in ratpts['rat_pts']
                ]) + '];'
            }
        code['mw_group'] = {'magma': 'MordellWeilGroupGenus2(Jacobian(C));'}
        code['two_selmer'] = {
            'magma': 'TwoSelmerGroup(Jacobian(C)); NumberOfGenerators($1);'
        }
        code['has_square_sha'] = {'magma': 'HasSquareSha(Jacobian(C));'}
        code['locally_solvable'] = {
            'magma':
            'f,h:=HyperellipticPolynomials(C); g:=4*f+h^2; HasPointsEverywhereLocally(g,2) and (#Roots(ChangeRing(g,RealField())) gt 0 or LeadingCoefficient(g) gt 0);'
        }
        code['torsion_subgroup'] = {
            'magma':
            'TorsionSubgroup(Jacobian(SimplifiedModel(C))); AbelianInvariants($1);'
        }
Example #2
0
    def make_object(self, curve, endo, tama, ratpts, is_curve):
        from lmfdb.genus2_curves.main import url_for_curve_label

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

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

        # set attributes common to curves and isogeny classes here
        data['Lhash'] = str(curve['Lhash'])
        data['cond'] = ZZ(curve['cond'])
        data['cond_factor_latex'] = web_latex(factor(int(data['cond'])))
        data['analytic_rank'] = ZZ(curve['analytic_rank'])
        data['st_group'] = curve['st_group']
        data['st_group_link'] = st_link_by_name(1,4,data['st_group'])
        data['st0_group_name'] = st0_group_name(curve['real_geom_end_alg'])
        data['is_gl2_type'] = curve['is_gl2_type']
        data['root_number'] = ZZ(curve['root_number'])
        data['lfunc_url'] = url_for("l_functions.l_function_genus2_page", cond=data['slabel'][0], x=data['slabel'][1])
        data['bad_lfactors'] = literal_eval(curve['bad_lfactors'])
        data['bad_lfactors_pretty'] = [ (c[0], list_to_factored_poly_otherorder(c[1])) for c in data['bad_lfactors']]

        if is_curve:
            # invariants specific to curve
            data['class'] = curve['class']
            data['abs_disc'] = ZZ(curve['abs_disc'])
            data['disc'] = curve['disc_sign'] * data['abs_disc']
            data['min_eqn'] = literal_eval(curve['eqn'])
            data['min_eqn_display'] = list_to_min_eqn(data['min_eqn'])
            data['disc_factor_latex'] = web_latex(factor(data['disc']))
            data['igusa_clebsch'] = [ZZ(a) for a in literal_eval(curve['igusa_clebsch_inv'])]
            data['igusa'] = [ZZ(a) for a in literal_eval(curve['igusa_inv'])]
            data['g2'] = [QQ(a) for a in literal_eval(curve['g2_inv'])]
            data['igusa_clebsch_factor_latex'] = [web_latex(zfactor(i)) for i in data['igusa_clebsch']]
            data['igusa_factor_latex'] = [ web_latex(zfactor(j)) for j in data['igusa'] ]
            data['aut_grp_id'] = curve['aut_grp_id']
            data['geom_aut_grp_id'] = curve['geom_aut_grp_id']
            data['num_rat_wpts'] = ZZ(curve['num_rat_wpts'])
            data['two_selmer_rank'] = ZZ(curve['two_selmer_rank'])
            data['has_square_sha'] = "square" if curve['has_square_sha'] else "twice a square"
            P = curve['non_solvable_places']
            if len(P):
                sz = "except over "
                sz += ", ".join([QpName(p) for p in P])
                last = " and"
                if len(P) > 2:
                    last = ", and"
                sz = last.join(sz.rsplit(",",1))
            else:
                sz = "everywhere"
            data['non_solvable_places'] = sz
            data['torsion_order'] = curve['torsion_order']
            data['torsion_factors'] = [ZZ(a) for a in literal_eval(curve['torsion_subgroup'])]
            if len(data['torsion_factors']) == 0:
                data['torsion_subgroup'] = '\mathrm{trivial}'
            else:
                data['torsion_subgroup'] = ' \\times '.join([ '\Z/{%s}\Z' % n for n in data['torsion_factors'] ])
            data['end_ring_base'] = endo['ring_base']
            data['end_ring_geom'] = endo['ring_geom']
            data['tama'] = ''
            for item in tama:
            	if item['tamagawa_number'] > 0:
            	    tamgwnr = str(item['tamagawa_number'])
            	else:
            	    tamgwnr = 'N/A'
            	data['tama'] += tamgwnr + ' (p = ' + str(item['p']) + '), '
            data['tama'] = data['tama'][:-2] # trim last ", "
            if ratpts:
                if len(ratpts['rat_pts']):
                    data['rat_pts'] = ',  '.join(web_latex('(' +' : '.join(map(str, P)) + ')') for P in ratpts['rat_pts'])
                data['rat_pts_v'] =  2 if ratpts['rat_pts_v'] else 1
                # data['mw_rank'] = ratpts['mw_rank']
                # data['mw_rank_v'] = ratpts['mw_rank_v']
            else:
                data['rat_pts_v'] = 0
            if curve['two_torsion_field'][0]:
                data['two_torsion_field_knowl'] = nf_display_knowl (curve['two_torsion_field'][0], field_pretty(curve['two_torsion_field'][0]))
            else:
                t = curve['two_torsion_field']
                data['two_torsion_field_knowl'] = """splitting field of \(%s\) with Galois group %s"""%(intlist_to_poly(t[1]),group_display_knowl(t[2][0],t[2][1]))
        else:
            # invariants specific to isogeny class
            curves_data = list(db.g2c_curves.search({"class" : curve['class']}, ['label','eqn']))
            if not curves_data:
                raise KeyError("No curves found in database for isogeny class %s of genus 2 curve %s." %(curve['class'],curve['label']))
            data['curves'] = [ {"label" : c['label'], "equation_formatted" : list_to_min_eqn(literal_eval(c['eqn'])), "url": url_for_curve_label(c['label'])} for c in curves_data ]
            lfunc_data = db.lfunc_lfunctions.lucky({'Lhash':str(curve['Lhash'])})
            if not lfunc_data:
                raise KeyError("No Lfunction found in database for isogeny class of genus 2 curve %s." %curve['label'])
            if lfunc_data and lfunc_data.get('euler_factors'):
                data['good_lfactors'] = [[nth_prime(n+1),lfunc_data['euler_factors'][n]] for n in range(len(lfunc_data['euler_factors'])) if nth_prime(n+1) < 30 and (data['cond'] % nth_prime(n+1))]
                data['good_lfactors_pretty'] = [ (c[0], list_to_factored_poly_otherorder(c[1])) for c in data['good_lfactors']]
        # Endomorphism data over QQ:
        data['gl2_statement_base'] = gl2_statement_base(endo['factorsRR_base'], r'\(\Q\)')
        data['factorsQQ_base'] = endo['factorsQQ_base']
        data['factorsRR_base'] = endo['factorsRR_base']
        data['end_statement_base'] = """Endomorphism %s over \(\Q\):<br>""" %("ring" if is_curve else "algebra") + \
            end_statement(data['factorsQQ_base'], endo['factorsRR_base'], ring=data['end_ring_base'] if is_curve else None)

        # Field over which all endomorphisms are defined
        data['end_field_label'] = endo['fod_label']
        data['end_field_poly'] = intlist_to_poly(endo['fod_coeffs'])
        data['end_field_statement'] = end_field_statement(data['end_field_label'], data['end_field_poly'])
        
        # Endomorphism data over QQbar:
        data['factorsQQ_geom'] = endo['factorsQQ_geom']
        data['factorsRR_geom'] = endo['factorsRR_geom']
        if data['end_field_label'] != '1.1.1.1':
            data['gl2_statement_geom'] = gl2_statement_base(data['factorsRR_geom'], r'\(\overline{\Q}\)')
            data['end_statement_geom'] = """Endomorphism %s over \(\overline{\Q}\):""" %("ring" if is_curve else "algebra") + \
                end_statement(data['factorsQQ_geom'], data['factorsRR_geom'], field=r'\overline{\Q}', ring=data['end_ring_geom'] if is_curve else None)
        data['real_geom_end_alg_name'] = real_geom_end_alg_name(curve['real_geom_end_alg'])
        data['geom_end_alg_name'] = geom_end_alg_name(curve['geom_end_alg'])

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

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

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

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

            properties += [
                (None, plot_link),
                ('Conductor',str(data['cond'])),
                ('Discriminant', str(data['disc'])),
                ]
        properties += [
            ('Sato-Tate group', data['st_group_link']),
            ('\(\\End(J_{\\overline{\\Q}}) \\otimes \\R\)', '\(%s\)' % data['real_geom_end_alg_name']),
            ('\(\\End(J_{\\overline{\\Q}}) \\otimes \\Q\)', '\(%s\)' % data['geom_end_alg_name']),
            ('\(\\overline{\\Q}\)-simple', bool_pretty(data['is_simple_geom'])),
            ('\(\mathrm{GL}_2\)-type', bool_pretty(data['is_gl2_type'])),
            ]

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

        # first deal with EC
        ecs = []
        if 'split_labels' in data:
            for friend_label in data['split_labels']:
                if is_curve:
                    ecs.append(("Elliptic curve " + friend_label, url_for_ec(friend_label)))
                else:
                    ecs.append(("Isogeny class " + ec_label_class(friend_label), url_for_ec_class(friend_label)))

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

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

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

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

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

        # Title
        self.title = "Genus 2 " + ("Curve " if is_curve else "Isogeny Class ") + data['label']

        # Code snippets (only for curves)
        if not is_curve:
            return
        self.code = code = {}
        code['show'] = {'sage':'','magma':''} # use default show names
        code['curve'] = {'sage':'R.<x> = PolynomialRing(QQ); C = HyperellipticCurve(R(%s), R(%s))'%(data['min_eqn'][0],data['min_eqn'][1]),
                              'magma':'R<x> := PolynomialRing(Rationals()); C := HyperellipticCurve(R!%s, R!%s);'%(data['min_eqn'][0],data['min_eqn'][1])}
        if data['abs_disc'] % 4096 == 0:
            ind2 = [a[0] for a in data['bad_lfactors']].index(2)
            bad2 = data['bad_lfactors'][ind2][1]
            magma_cond_option = ': ExcFactors:=[*<2,Valuation('+str(data['cond'])+',2),R!'+str(bad2)+'>*]'
        else:
            magma_cond_option = ''
        code['cond'] = {'magma': 'Conductor(LSeries(C%s)); Factorization($1);'% magma_cond_option}
        code['disc'] = {'magma':'Discriminant(C); Factorization(Integers()!$1);'}
        code['igusa_clebsch'] = {'sage':'C.igusa_clebsch_invariants(); [factor(a) for a in _]',
                                      'magma':'IgusaClebschInvariants(C); [Factorization(Integers()!a): a in $1];'}
        code['igusa'] = {'magma':'IgusaInvariants(C); [Factorization(Integers()!a): a in $1];'}
        code['g2'] = {'magma':'G2Invariants(C);'}
        code['aut'] = {'magma':'AutomorphismGroup(C); IdentifyGroup($1);'}
        code['autQbar'] = {'magma':'AutomorphismGroup(ChangeRing(C,AlgebraicClosure(Rationals()))); IdentifyGroup($1);'}
        code['num_rat_wpts'] = {'magma':'#Roots(HyperellipticPolynomials(SimplifiedModel(C)));'}
        if ratpts:
            code['rat_pts'] = {'magma': '[' + ','.join(["C![%s,%s,%s]"%(p[0],p[1],p[2]) for p in ratpts['rat_pts']]) + '];' }
        code['two_selmer'] = {'magma':'TwoSelmerGroup(Jacobian(C)); NumberOfGenerators($1);'}
        code['has_square_sha'] = {'magma':'HasSquareSha(Jacobian(C));'}
        code['locally_solvable'] = {'magma':'f,h:=HyperellipticPolynomials(C); g:=4*f+h^2; HasPointsEverywhereLocally(g,2) and (#Roots(ChangeRing(g,RealField())) gt 0 or LeadingCoefficient(g) gt 0);'}
        code['torsion_subgroup'] = {'magma':'TorsionSubgroup(Jacobian(SimplifiedModel(C))); AbelianInvariants($1);'}