示例#1
0
文件: main.py 项目: rbommel/lmfdb
def make_cm_query(cm_disc_str):
    cm_list = parse_ints_to_list_flash(cm_disc_str, "CM discriminant", max_val=None)
    for d in cm_list:
        if not ((d < 0) and (d % 4 in [0,1])):
            raise ValueError("A CM discriminant must be a fundamental discriminant of an imaginary quadratic field.")
    cm_list += [-el for el in cm_list]
    return cm_list
示例#2
0
文件: dimensions.py 项目: LMFDB/lmfdb
def parse_dim_args(dim_args, default_dim_args):
    res={}
    for v in ['k','j']:
        arg = dim_args.get(v) if dim_args else None
        if not arg:
            arg = default_dim_args.get(v) if default_dim_args else None
        if arg:
            res[v] = parse_ints_to_list_flash(arg, "$"+v+"$")
    args={}
    if 'k' in res:
        if res['k'][-1] > MAXWT:
            flash(Markup("Error: <span style='color:black'>$k$</span> cannot exceed <span style='color:black'>%s</span>." % MAXWT), "error")
            raise ValueError("dim_args")
        if len(res['k']) > MAXWTRANGE:
            flash(Markup("Error: range for <span style='color:black'>$k$</span> cannot include more than %s</span> values." % MAXWTRANGE), "error")
            raise ValueError("dim_args")
        args = {'k_range':res['k']}
    if 'j' in res:
        if res['j'][-1] > MAXJ:
            flash(Markup("Error: <span style='color:black'>$j$</span> cannot exceed <span style='color:black'>%s</span>." % MAXJ), "error")
            raise ValueError("dim_args")
        args['j_range'] = [j for j in res['j'] if j%2 == 0]
        if not args['j_range']:
            flash(Markup("Error: <span style='color:black'>$j$</span> should be a nonnegative even integer."), "error")
            raise ValueError("dim_args")
    return args
示例#3
0
def parse_dim_args(dim_args, default_dim_args):
    res = {}
    for v in ['k', 'j']:
        arg = dim_args.get(v) if dim_args else None
        if not arg:
            arg = default_dim_args.get(v) if default_dim_args else None
        if arg:
            res[v] = parse_ints_to_list_flash(arg, "$" + v + "$")
    args = {}
    if 'k' in res:
        if res['k'][-1] > MAXWT:
            flash_error(
                "<span style='color:black'>$k$</span> cannot exceed %s.",
                MAXWT)
            raise ValueError("dim_args")
        if len(res['k']) > MAXWTRANGE:
            flash_error(
                "range for <span style='color:black'>$k$</span> cannot include more than %s values.",
                MAXWTRANGE)
            raise ValueError("dim_args")
        args = {'k_range': res['k']}
    if 'j' in res:
        if res['j'][-1] > MAXJ:
            flash_error(
                "<span style='color:black'>$j$</span> cannot exceed %s.", MAXJ)
            raise ValueError("dim_args")
        args['j_range'] = [j for j in res['j'] if j % 2 == 0]
        if not args['j_range']:
            flash_error(
                "<span style='color:black'>$j$</span> should be a nonnegative even integer."
            )
            raise ValueError("dim_args")
    return args
示例#4
0
def search(info):
    """ query processing for Sato-Tate groups -- returns rendered results page """
    if 'jump' in info:
        return redirect(url_for('.by_label', label=info['jump']), 301)
    if 'label' in info:
        return redirect(url_for('.by_label', label=info['label']), 301)
    search_type = info.get("search_type", info.get("hst", "List"))
    template_kwds = {
        'bread': [('Sato-Tate Groups', url_for('.index')),
                  ('Search Results', '.')],
        'credit': credit_string,
        'learnmore': learnmore_list()
    }
    title = 'Sato-Tate Group Search Results'
    err_title = 'Sato-Tate Groups Search Input Error'
    count = parse_count(info, 50)
    start = parse_start(info)
    # if user clicked refine search always restart at 0
    if 'refine' in info:
        start = 0
    ratonly = (info.get('include_irrational', 'no').strip().lower() == 'no')
    if search_type == "Random" and not ratonly:
        info['err'] = err = 'Cannot select random irrational Sato-Tate group'
        flash_error(err)
        return render_template('st_results.html',
                               info=info,
                               title=err_title,
                               **template_kwds)
    query = {'rational': True} if ratonly else {}
    try:
        parse_ints(info, query, 'weight', 'weight')
        if 'weight' in query:
            weight_list = parse_ints_to_list_flash(info.get('weight'),
                                                   'weight')
        parse_ints(info, query, 'degree', 'degree')
        if 'degree' in query:
            degree_list = parse_ints_to_list_flash(info.get('degree'),
                                                   'degree')
        if info.get('identity_component'):
            query['identity_component'] = info['identity_component']
        parse_ints(info, query, 'components', 'components')
        if 'components' in query:
            components_list = parse_ints_to_list_flash(info.get('components'),
                                                       'components')
        parse_rational(info, query, 'trace_zero_density', 'trace zero density')
    except ValueError as err:
        info['err'] = str(err)
        return render_template('st_results.html',
                               info=info,
                               title=err_title,
                               **template_kwds)

    # Check mu(n) groups first (these are not stored in the database)
    results = []
    if ((not 'weight' in query or 0 in weight_list)
            and (not 'degree' in query or 1 in degree_list)
            and (not 'identity_component' in query
                 or query['identity_component'] == 'SO(1)')
            and (not 'trace_zero_density' in query
                 or query['trace_zero_density'] == '0')):
        if not 'components' in query:
            components_list = range(1, 3 if ratonly else start + count + 1)
        elif ratonly:
            components_list = [n for n in range(1, 3) if n in components_list]
        nres = len(
            components_list) if 'components' in query or ratonly else INFINITY
        if search_type == "Random" and nres > 0:
            # Need to return mu(1) and mu(2) sometimes
            otherlen = db.gps_sato_tate.count(query)
            r = ZZ.random_element(nres + otherlen)
            if r < nres:
                return redirect(
                    url_for(".by_label", label="0.1.%d" % components_list[r]),
                    307)
        for n in itertools.islice(components_list, start, start + count):
            results.append(mu_info(n))
    else:
        nres = 0

    if 'result_count' in info:
        nres += db.gps_sato_tate.count(query)
        return jsonify({"nres": str(nres)})
    if search_type == "Random":
        label = db.gps_sato_tate.random(query, "label")
        if label is not None:
            return redirect(url_for(".by_label", label=label), 307)

    # Now lookup other (rational) ST groups in database
    if nres != INFINITY:
        start2 = start - nres if start > nres else 0
        proj = [
            'label', 'weight', 'degree', 'real_dimension',
            'identity_component', 'name', 'pretty', 'components',
            'component_group', 'trace_zero_density', 'moments'
        ]
        try:
            res = db.gps_sato_tate.search(query,
                                          proj,
                                          limit=max(count - len(results), 0),
                                          offset=start2,
                                          info=info)
        except QueryCanceledError as err:
            ctx = ctx_proc_userdata()
            flash_error(
                'The search query took longer than expected! Please help us improve by reporting this error  <a href="%s" target=_blank>here</a>.'
                % ctx['feedbackpage'])
            info['err'] = str(err)
            return render_template('st_results.html',
                                   info=info,
                                   title=err_title,
                                   **template_kwds)
        info['number'] += nres
        if start < info['number'] and len(results) < count:
            for v in res:
                v['identity_component'] = st0_pretty(v['identity_component'])
                v['component_group'] = sg_pretty(v['component_group'])
                v['trace_moments'] = trace_moments(v['moments'])
                results.append(v)
    else:
        info['number'] = 'infinity'
    info['start'] = start
    info['count'] = count

    info['st0_list'] = st0_list
    info['st0_dict'] = st0_dict
    info['results'] = results
    info['stgroup_url'] = lambda dbc: url_for('.by_label', label=dbc['label'])
    return render_template('st_results.html',
                           info=info,
                           title=title,
                           **template_kwds)
示例#5
0
def render_sample_page(family, sam, args, bread):
    info = {
        'args': to_dict(args),
        'sam': sam,
        'latex': latex,
        'type': sam.type(),
        'name': sam.name(),
        'full_name': sam.full_name(),
        'weight': sam.weight(),
        'fdeg': sam.degree_of_field(),
        'is_eigenform': sam.is_eigenform(),
        'field_poly': sam.field_poly()
    }
    if sam.is_integral() is not None:
        info['is_integral'] = sam.is_integral()
    if 'Sp4Z' in sam.collection():
        info['space_url'] = url_for('.Sp4Z_j_space', k=info['weight'], j=0)
    if 'Sp4Z_2' in sam.collection():
        info['space_url'] = url_for('.Sp4Z_j_space', k=info['weight'], j=2)
    info['space'] = '$' + family.latex_name.replace(
        'k', '{' + str(sam.weight()) + '}') + '$'
    if 'space_url' in info:
        bread.append((info['space'], info['space_url']))
    info['space_href'] = '<a href="%s">%s</d>' % (
        info['space_url'],
        info['space']) if 'space_url' in info else info['space']
    if info['field_poly'].disc() < 10**10:
        label = poly_to_field_label(info['field_poly'])
        if label:
            info['field_label'] = label
            info['field_url'] = url_for('number_fields.by_label', label=label)
            info['field_href'] = '<a href="%s">%s</a>' % (info['field_url'],
                                                          field_pretty(label))

    bread.append((info['name'], ''))
    title = 'Siegel modular forms sample ' + info['full_name']
    properties = [('Space', info['space_href']), ('Name', info['name']),
                  ('Type', '<br>'.join(info['type'].split(','))),
                  ('Weight', prop_int_pretty(info['weight'])),
                  ('Hecke eigenform', "yes" if info['is_eigenform'] else "no"),
                  ('Field degree', prop_int_pretty(info['fdeg']))]
    try:
        evs_to_show = parse_ints_to_list_flash(args.get('ev_index'),
                                               'list of $l$')
        fcs_to_show = parse_ints_to_list_flash(args.get('fc_det'),
                                               'list of $\\det(F)$')
    except ValueError:
        evs_to_show = []
        fcs_to_show = []
    info['evs_to_show'] = sorted([
        n for n in
        (evs_to_show if len(evs_to_show) else sam.available_eigenvalues()[:10])
    ])
    info['fcs_to_show'] = sorted([
        n for n in (fcs_to_show if len(fcs_to_show) else sam.
                    available_Fourier_coefficients()[1:6])
    ])
    info['evs_avail'] = [n for n in sam.available_eigenvalues()]
    info['fcs_avail'] = [n for n in sam.available_Fourier_coefficients()]

    # Do not attempt to constuct a modulus ideal unless the field has a reasonably small discriminant
    # otherwise sage may not even be able to factor the discriminant
    info['field'] = sam.field()
    if info['field_poly'].disc() < 10**80:
        null_ideal = sam.field().ring_of_integers().ideal(0)
        info['modulus'] = null_ideal
        modulus = args.get('modulus', '').strip()
        m = 0
        if modulus:
            try:
                O = sam.field().ring_of_integers()
                m = O.ideal([O(str(b)) for b in modulus.split(',')])
            except Exception:
                info['error'] = True
                flash_error(
                    "Unable to construct modulus ideal from specified generators %s.",
                    modulus)
            if m == 1:
                info['error'] = True
                flash_error(
                    "The ideal %s is the unit ideal, please specify a different modulus.",
                    '(' + modulus + ')')
                m = 0
        info['modulus'] = m

        # Hack to reduce polynomials and to handle non integral stuff
        def redc(c):
            return m.reduce(c * c.denominator()) / m.reduce(c.denominator())

        def redp(f):
            c = f.dict()
            return f.parent()(dict((e, redc(c[e])) for e in c))

        def safe_reduce(f):
            if not m:
                return latex(f)
            try:
                if f in sam.field():
                    return latex(redc(f))
                else:
                    return latex(redp(f))
            except ZeroDivisionError:
                return '\\textrm{Unable to reduce} \\bmod\\mathfrak{m}'

        info['reduce'] = safe_reduce
    else:
        info['reduce'] = latex

    # check that explicit formula is not ridiculously big
    if sam.explicit_formula():
        info['explicit_formula_bytes'] = len(sam.explicit_formula())
        if len(sam.explicit_formula()) < 100000:
            info['explicit_formula'] = sam.explicit_formula()

    return render_template("ModularForm_GSp4_Q_sample.html",
                           title=title,
                           bread=bread,
                           properties=properties,
                           info=info)
示例#6
0
文件: main.py 项目: jenpaulhus/lmfdb
def search(**args):
    """ query processing for Sato-Tate groups -- returns rendered results page """
    info = to_dict(args)
    if 'jump' in info:
        return redirect(url_for('.by_label', label=info['jump']), 301)
    if 'label' in info:
        return redirect(url_for('.by_label', label=info['label']), 301)
    template_kwds = {'bread':[('Sato-Tate Groups', url_for('.index')),('Search Results', '.')],
                     'credit':credit_string,
                     'learnmore':learnmore_list()}
    title = 'Sato-Tate Group Search Results'
    err_title = 'Sato-Tate Groups Search Input Error'
    count = parse_count(info, 25)
    start = parse_start(info)
    # if user clicked refine search always restart at 0
    if 'refine' in info:
        start = 0
    ratonly = True if info.get('rational_only','no').strip().lower() == 'yes' else False
    query = {'rational':True} if ratonly else {}
    try:
        parse_ints(info,query,'weight','weight')
        if 'weight' in query:
            weight_list = parse_ints_to_list_flash(info.get('weight'),'weight')
        parse_ints(info,query,'degree','degree')
        if 'degree' in query:
            degree_list = parse_ints_to_list_flash(info.get('degree'),'degree')
        if info.get('identity_component'):
            query['identity_component'] = info['identity_component']
        parse_ints(info,query,'components','components')
        if 'components' in query:
            components_list = parse_ints_to_list_flash(info.get('components'), 'components')
        parse_rational(info,query,'trace_zero_density','trace zero density')
    except ValueError as err:
        info['err'] = str(err)
        return render_template('st_results.html', info=info, title=err_title, **template_kwds)

    # Check mu(n) groups first (these are not stored in the database)
    results = []
    if (not 'weight' in query or 0 in weight_list) and \
       (not 'degree' in query or 1 in degree_list) and \
       (not 'identity_component' in query or query['identity_component'] == 'SO(1)') and \
       (not 'trace_zero_density' in query or query['trace_zero_density'] == '0'):
        if not 'components' in query:
            components_list = xrange(1,3 if ratonly else start+count+1)
        elif ratonly:
            components_list = [n for n in range(1,3) if n in components_list]
        nres = len(components_list) if 'components' in query or ratonly else INFINITY
        for n in itertools.islice(components_list,start,start+count):
            results.append(mu_info(n))
    else:
        nres = 0

    if 'result_count' in info:
        nres += db.gps_sato_tate.count(query)
        return jsonify({"nres":str(nres)})

    # Now lookup other (rational) ST groups in database
    if nres != INFINITY:
        start2 = start - nres if start > nres else 0
        proj = ['label','weight','degree','real_dimension','identity_component','name','pretty','components','component_group','trace_zero_density','moments']
        try:
            res = db.gps_sato_tate.search(query, proj, limit=max(count - len(results), 0), offset=start2, info=info)
        except QueryCanceledError as err:
            ctx = ctx_proc_userdata()
            flash_error('The search query took longer than expected! Please help us improve by reporting this error  <a href="%s" target=_blank>here</a>.' % ctx['feedbackpage'])
            info['err'] = str(err)
            return render_template('st_results.html', info=info, title=err_title, **template_kwds)
        info['number'] += nres
        if start < info['number'] and len(results) < count:
            for v in res:
                v['identity_component'] = st0_pretty(v['identity_component'])
                v['component_group'] = sg_pretty(v['component_group'])
                v['trace_moments'] = trace_moments(v['moments'])
                results.append(v)
    else:
        info['number'] = 'infinity'
        info['start'] = start
        info['count'] = count

    info['st0_list'] = st0_list
    info['st0_dict'] = st0_dict
    info['results'] = results
    info['stgroup_url'] = lambda dbc: url_for('.by_label', label=dbc['label'])
    return render_template('st_results.html', info=info, title=title, **template_kwds)
示例#7
0
文件: main.py 项目: tahulse/lmfdb
def search(info):
    """ query processing for Sato-Tate groups -- returns rendered results page """
    if 'jump' in info:
        return redirect(url_for('.by_label', label=info['jump']), 301)
    if 'label' in info:
        return redirect(url_for('.by_label', label=info['label']), 301)
    search_type = info.get("search_type", info.get("hst", "List"))
    template_kwds = {
        'bread': get_bread("Search results"),
        'credit': credit_string,
        'learnmore': learnmore_list()
    }
    title = 'Sato-Tate group search results'
    err_title = 'Sato-Tate group search input error'
    count = parse_count(info, 50)
    start = parse_start(info)
    # if user clicked refine search always restart at 0
    if 'refine' in info:
        start = 0
    ratonly = (info.get('include_irrational', 'no').strip().lower() == 'no')
    if search_type == "Random" and not ratonly:
        info['err'] = err = 'Cannot select random irrational Sato-Tate group'
        flash_error(err)
        return render_template('st_results.html',
                               info=info,
                               title=err_title,
                               **template_kwds)
    query = {'rational': True} if ratonly else {}
    try:
        parse_ints(info, query, 'weight', 'weight')
        if 'weight' in query:
            weight_list = parse_ints_to_list_flash(info.get('weight'),
                                                   'weight')
        parse_ints(info, query, 'degree', 'degree')
        if 'degree' in query:
            degree_list = parse_ints_to_list_flash(info.get('degree'),
                                                   'degree')
        if info.get('identity_component'):
            query['identity_component'] = info['identity_component']
        parse_ints(info, query, 'components', 'components')

        def refine_components(current, condition):
            if current is None:
                return condition
            return [x for x in condition if x in current]

        # The following are used to constraint which mu(n) will show up in search results
        components_list = None
        ommitted = set()
        if 'components' in query:
            components_list = parse_ints_to_list_flash(info.get('components'),
                                                       'components')
        parse_component_group(info, query)
        gps = query.get("component_group")
        if gps:
            if isinstance(gps, dict):
                gps = gps["$in"]
            else:
                gps = [gps]
            if not ratonly:
                cyclic_labels = set(
                    db.gps_small.search({"cyclic": True}, "label"))
            irrat = []
            for code in gps:
                if code in cyclics:
                    irrat.append(cyclics[code])
                elif re.match(cyclicre, code):
                    irrat.append(int(code[1:]))
                elif not ratonly and code in cyclic_labels:
                    irrat.append(int(code.split(".")[0]))
            components_list = refine_components(components_list, irrat)
        parse_rational(info, query, 'trace_zero_density', 'trace zero density')
        parse_ints(info, query, 'second_trace_moment')
        parse_ints(info, query, 'fourth_trace_moment')
        for name, ones in [('second_trace_moment', [1, 2]),
                           ('fourth_trace_moment', [1, 2, 4])]:
            if name in query:
                # E(x^2) for mu(1) and mu(2) are 1; others are 0
                # E(x^4) for mu(1), mu(2) and mu(4) are 1; others are 0
                E = parse_ints_to_list_flash(info.get(name),
                                             name.replace("_", " "))
                if 0 not in E:
                    components_list = refine_components(components_list, ones)
                if 1 not in E:
                    ommitted.update(ones)
        parse_ints(info, query, 'first_a2_moment')
        parse_bool(info, query, 'maximal')
        if "first_a2_moment" in query or query.get("maximal"):
            # mu(n) do not have a2 moments and none are maximal
            components_list = []
    except ValueError as err:
        info['err'] = str(err)
        return render_template('st_results.html',
                               info=info,
                               title=err_title,
                               **template_kwds)

    # Check mu(n) groups first (these are not stored in the database)
    results = []
    if ((not 'weight' in query or 0 in weight_list)
            and (not 'degree' in query or 1 in degree_list)
            and (not 'identity_component' in query
                 or query['identity_component'] == 'SO(1)')
            and (not 'trace_zero_density' in query
                 or query['trace_zero_density'] == '0')):
        nres = None
        if components_list is None:
            components_list = range(
                1, 3 if ratonly else (start + count + 1 + len(ommitted)))
            nres = None if ratonly else INFINITY
        elif ratonly:
            components_list = [n for n in range(1, 3) if n in components_list]
        components_list = [n for n in components_list if n not in ommitted]
        if nres is None:
            nres = len(components_list)
        if search_type == "Random" and nres > 0:
            # Need to return mu(1), mu(2) or mu(4) sometimes
            otherlen = db.gps_sato_tate.count(query)
            r = ZZ.random_element(nres + otherlen)
            if r < nres:
                return redirect(
                    url_for(".by_label", label="0.1.%d" % components_list[r]),
                    307)
        for n in itertools.islice(components_list, start, start + count):
            results.append(mu_info(n))
    else:
        nres = 0

    if 'result_count' in info:
        nres += db.gps_sato_tate.count(query)
        return jsonify({"nres": str(nres)})
    if search_type == "Random":
        label = db.gps_sato_tate.random(query, "label")
        if label is not None:
            return redirect(url_for(".by_label", label=label), 307)

    # Now lookup other (rational) ST groups in database
    if nres != INFINITY:
        start2 = start - nres if start > nres else 0
        proj = [
            'label', 'weight', 'degree', 'real_dimension',
            'identity_component', 'name', 'pretty', 'components',
            'component_group', 'trace_zero_density', 'moments'
        ]
        try:
            res = db.gps_sato_tate.search(query,
                                          proj,
                                          limit=max(count - len(results), 0),
                                          offset=start2,
                                          info=info)
        except QueryCanceledError as err:
            ctx = ctx_proc_userdata()
            flash_error(
                'The search query took longer than expected! Please help us improve by reporting this error  <a href="%s" target=_blank>here</a>.'
                % ctx['feedbackpage'])
            info['err'] = str(err)
            return render_template('st_results.html',
                                   info=info,
                                   title=err_title,
                                   **template_kwds)
        info['number'] += nres
        if start < info['number'] and len(results) < count:
            for v in res:
                v['identity_component'] = st0_pretty(v['identity_component'])
                v['component_group'] = sg_pretty(v['component_group'])
                v['trace_moments'] = trace_moments(v['moments'])
                results.append(v)
    else:
        info['number'] = 'infinity'
    info['start'] = start
    info['count'] = count

    info['st0_list'] = st0_list
    info['st0_dict'] = st0_dict
    info['results'] = results
    info['stgroup_url'] = lambda dbc: url_for('.by_label', label=dbc['label'])
    return render_template('st_results.html',
                           info=info,
                           title=title,
                           **template_kwds)
示例#8
0
def render_sample_page(family, sam, args, bread):
    info = { 'args': to_dict(args), 'sam': sam, 'latex': latex, 'type':sam.type(), 'name':sam.name(), 'full_name': sam.full_name(), 'weight':sam.weight(), 'fdeg':sam.degree_of_field(), 'is_eigenform':sam.is_eigenform(), 'field_poly': sam.field_poly()}
    if sam.is_integral() != None:
        info['is_integral'] = sam.is_integral()
    if 'Sp4Z' in sam.collection():
        info['space_url'] = url_for('.Sp4Z_j_space', k=info['weight'], j=0)
    if 'Sp4Z_2' in sam.collection():
        info['space_url'] = url_for('.Sp4Z_j_space', k=info['weight'], j=2)
    info['space'] = '$'+family.latex_name.replace('k', '{' + str(sam.weight()) + '}')+'$'
    if 'space_url' in info:
        bread.append((info['space'], info['space_url']))
    info['space_href'] = '<a href="%s">%s</d>'%(info['space_url'],info['space']) if 'space_url' in info else info['space']
    if info['field_poly'].disc() < 10**10:
        label = poly_to_field_label(info['field_poly'])
        if label:
            info['field_label'] = label
            info['field_url'] = url_for('number_fields.by_label', label=label)
            info['field_href'] = '<a href="%s">%s</a>'%(info['field_url'], field_pretty(label))
    
    bread.append((info['name'], ''))
    title='Siegel Modular Forms Sample ' + info['full_name']
    properties = [('Space', info['space_href']),
                  ('Name', info['name']),
                  ('Type', '<br>'.join(info['type'].split(','))),
                  ('Weight', str(info['weight'])),
                  ('Hecke eigenform', str(info['is_eigenform'])),
                  ('Field degree', str(info['fdeg']))]
    try:
        evs_to_show = parse_ints_to_list_flash(args.get('ev_index'), 'list of $l$')
        fcs_to_show = parse_ints_to_list_flash(args.get('fc_det'), 'list of $\\det(F)$')
    except ValueError:
        evs_to_show = []
        fcs_to_show = []
    info['evs_to_show'] = sorted([n for n in (evs_to_show if len(evs_to_show) else sam.available_eigenvalues()[:10])])
    info['fcs_to_show'] = sorted([n for n in (fcs_to_show if len(fcs_to_show) else sam.available_Fourier_coefficients()[1:6])])
    info['evs_avail'] = [n for n in sam.available_eigenvalues()]
    info['fcs_avail'] = [n for n in sam.available_Fourier_coefficients()]

    # Do not attempt to constuct a modulus ideal unless the field has a reasonably small discriminant
    # otherwise sage may not even be able to factor the discriminant
    info['field'] = sam.field()
    if info['field_poly'].disc() < 10**80:
        null_ideal = sam.field().ring_of_integers().ideal(0)
        info['modulus'] = null_ideal
        modulus = args.get('modulus','').strip()
        m = 0
        if modulus:
            try:
                O = sam.field().ring_of_integers()
                m = O.ideal([O(str(b)) for b in modulus.split(',')])
            except Exception:
                info['error'] = True
                flash_error("Unable to construct modulus ideal from specified generators %s.", modulus)
            if m == 1:
                info['error'] = True
                flash_error("The ideal %s is the unit ideal, please specify a different modulus.", '('+modulus+')')
                m = 0
        info['modulus'] = m
        # Hack to reduce polynomials and to handle non integral stuff
        def redc(c):
            return m.reduce(c*c.denominator())/m.reduce(c.denominator())
        def redp(f):
            c = f.dict()
            return f.parent()(dict((e,redc(c[e])) for e in c))
        def safe_reduce(f):
            if not m:
                return latex(f)
            try:
                if f in sam.field():
                    return latex(redc(f))
                else:
                    return latex(redp(f))
            except ZeroDivisionError:
                return '\\textrm{Unable to reduce} \\bmod\\mathfrak{m}'
        info['reduce'] = safe_reduce
    else:
        info['reduce'] = latex
        
    # check that explicit formula is not ridiculously big
    if sam.explicit_formula():
        info['explicit_formula_bytes'] = len(sam.explicit_formula())
        if len(sam.explicit_formula()) < 100000:
            info['explicit_formula'] = sam.explicit_formula()
        
    return render_template("ModularForm_GSp4_Q_sample.html", title=title, bread=bread, properties2=properties, info=info)