Ejemplo n.º 1
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(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
Ejemplo n.º 2
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(
                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
Ejemplo n.º 3
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)
Ejemplo n.º 4
0
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)
    bread = [('Sato-Tate groups', url_for('.index')),('Search Results', '.')]
    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='Sato-Tate groups search input error', bread=bread, credit=credit_string)

    # 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

    # Now lookup other (rational) ST groups in database
    if nres != INFINITY:
        cursor = st_groups().find(query)
        start2 = start - nres if start > nres else 0
        nres += cursor.count()
        if start < nres and len(results) < count:
            res = cursor.sort([('weight',ASCENDING), ('degree', ASCENDING), ('real_dimension', ASCENDING), ('identity_component', ASCENDING), ('name', ASCENDING)]).skip(start2).limit(count-len(results))
            for v in res:
                v_clean = {}
                v_clean['label'] = v['label']
                v_clean['weight'] = v['weight']
                v_clean['degree'] = v['degree']
                v_clean['real_dimension'] = v['real_dimension']
                v_clean['identity_component'] = st0_pretty(v['identity_component'])
                v_clean['name'] = v['name']
                v_clean['pretty'] = v['pretty']
                v_clean['components'] = v['components']
                v_clean['component_group'] = sg_pretty(v['component_group'])
                v_clean['trace_zero_density'] = v['trace_zero_density']
                v_clean['trace_moments'] = trace_moments(v['moments'])
                results.append(v_clean)
    if nres == 0:
        info['report'] = 'no matches'
    elif nres == 1:
        info['report'] = 'unique match'
    else:
        if nres == INFINITY or nres > count or start > 0:
            info['report'] = 'displaying matches %d-%d %s' % (start + 1, start + len(results), "of %d"%nres if nres != INFINITY else "")
        else:
            info['report'] = 'displaying all %s matches' % nres

    info['st0_list'] = st0_list
    info['st0_dict'] = st0_dict
    info['stgroups'] = results
    info['stgroup_url'] = lambda dbc: url_for('.by_label', label=dbc['label'])
    info['start'] = start
    info['count'] = count
    info['more'] = 1 if nres < 0 or nres > start+count else 0
    title = 'Sato-Tate group search results'
    return render_template('st_results.html', info=info, credit=credit_string,learnmore=learnmore_list(), bread=bread, title=title)
Ejemplo n.º 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() != 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)
Ejemplo n.º 6
0
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)
    bread = [('Sato-Tate Groups', url_for('.index')),('Search Results', '.')]
    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='Sato-Tate Groups Search Input Error', bread=bread, credit=credit_string)

    # 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

    # Now lookup other (rational) ST groups in database
    if nres != INFINITY:
        cursor = st_groups().find(query)
        start2 = start - nres if start > nres else 0
        nres += cursor.count()
        if start < nres and len(results) < count:
            res = cursor.sort([('weight',ASCENDING), ('degree', ASCENDING), ('real_dimension', ASCENDING), ('identity_component', ASCENDING), ('name', ASCENDING)]).skip(start2).limit(count-len(results))
            for v in res:
                v_clean = {}
                v_clean['label'] = v['label']
                v_clean['weight'] = v['weight']
                v_clean['degree'] = v['degree']
                v_clean['real_dimension'] = v['real_dimension']
                v_clean['identity_component'] = st0_pretty(v['identity_component'])
                v_clean['name'] = v['name']
                v_clean['pretty'] = v['pretty']
                v_clean['components'] = v['components']
                v_clean['component_group'] = sg_pretty(v['component_group'])
                v_clean['trace_zero_density'] = v['trace_zero_density']
                v_clean['trace_moments'] = trace_moments(v['moments'])
                results.append(v_clean)
    if nres == 0:
        info['report'] = 'no matches'
    elif nres == 1:
        info['report'] = 'unique match'
    else:
        if nres == INFINITY or nres > count or start > 0:
            info['report'] = 'displaying matches %d-%d %s' % (start + 1, start + len(results), "of %d"%nres if nres != INFINITY else "")
        else:
            info['report'] = 'displaying all %s matches' % nres

    info['st0_list'] = st0_list
    info['st0_dict'] = st0_dict
    info['stgroups'] = results
    info['stgroup_url'] = lambda dbc: url_for('.by_label', label=dbc['label'])
    info['start'] = start
    info['count'] = count
    info['more'] = 1 if nres < 0 or nres > start+count else 0
    title = 'Sato-Tate Group Search Results'
    return render_template('st_results.html', info=info, credit=credit_string,learnmore=learnmore_list(), bread=bread, title=title)
Ejemplo n.º 7
0
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)
Ejemplo n.º 8
0
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)