def init_g2c_stats(self): if self._stats: return curves = g2c_db_curves() counts = self._counts total = counts["ncurves"] stats = {} dists = [] # TODO use aggregate $group to speed this up and/or just store these counts in the database for attr in stats_attribute_list: counts = attribute_value_counts(curves, attr['name']) vcounts = [] rows = [] avg = 0 for value,n in counts: prop = format_percentage(n,total) if 'avg' in attr and attr['avg']: avg += n*value value_string = attr['format'](value) if 'format' in attr else value vcounts.append({'value': value_string, 'curves': n, 'query':url_for(".index_Q")+'?'+attr['name']+'='+str(value),'proportion': prop}) if len(vcounts) == 10: rows.append(vcounts) vcounts = [] if len(vcounts): rows.append(vcounts) if 'avg' in attr and attr['avg']: vcounts.append({'value':'\(\\mathrm{avg}\\ %.2f\)'%(float(avg)/total), 'curves':total, 'query':url_for(".index_Q") +'?'+attr['name'],'proportion':format_percentage(1,1)}) dists.append({'attribute':attr,'rows':rows}) stats["distributions"] = dists self._stats = stats
def download_search(info): lang = info.get('language','text').strip() filename = 'genus2_curves' + download_file_suffix[lang] mydate = time.strftime("%d %B %Y") # reissue query here try: res = g2c_db_curves().find(literal_eval(info.get('query','{}')),{'_id':False,'eqn':True}) except Exception as err: return "Unable to parse query: %s"%err c = download_comment_prefix[lang] s = '\n' s += c + ' Genus 2 curves downloaded from the LMFDB downloaded on %s.\n'% mydate s += c + ' Query "%s" returned %d curves.\n\n' %(str(info.get('query')), res.count()) s += c + ' Below is a list called data. Each entry has the form:\n' s += c + ' [[f coeffs],[h coeffs]]\n' s += c + ' defining the hyperelliptic curve y^2+h(x)y=f(x)\n' s += c + '\n' s += c + ' ' + download_make_data_comment[lang] + '\n' s += '\n' s += download_assignment_start[lang] + '\\\n' s += str(',\n'.join([str(r['eqn']) for r in res])) # list of curve equations s += download_assignment_end[lang] s += '\n\n' s += download_make_data[lang] strIO = StringIO.StringIO() strIO.write(s) strIO.seek(0) return send_file(strIO, attachment_filename=filename, as_attachment=True, add_etags=False)
def by_url_isogeny_class_discriminant(cond, alpha, disc): data = to_dict(request.args) clabel = str(cond) + "." + alpha # if the isogeny class is not present in the database, return a 404 (otherwise title and bread crumbs refer to a non-existent isogeny class) if not g2c_db_curves().find_one({'class': clabel}, {'_id': True}): return abort( 404, 'Genus 2 isogeny class %s not found in database.' % clabel) data['title'] = 'Genus 2 curves in isogeny class %s of discriminant %s' % ( clabel, disc) data['bread'] = [('Genus 2 Curves', url_for(".index")), ('$\Q$', url_for(".index_Q")), ('%s' % cond, url_for(".by_conductor", cond=cond)), ('%s' % alpha, url_for(".by_url_isogeny_class_label", cond=cond, alpha=alpha)), ('%s' % disc, url_for(".by_url_isogeny_class_discriminant", cond=cond, alpha=alpha, disc=disc))] if len(request.args) > 0: # if conductor or discriminant changed, fall back to a general search if ('cond' in request.args and request.args['cond'] != str(cond)) or \ ('abs_disc' in request.args and request.args['abs_disc'] != str(disc)): return redirect(url_for(".index", **request.args), 307) data['title'] += ' search results' data['bread'].append(('search results', '')) data['cond'] = cond data['class'] = clabel data['abs_disc'] = disc return genus2_curve_search(data)
def init_g2c_count(self): if self._counts: return curves = g2c_db_curves() counts = {} ncurves = curves.count() counts['ncurves'] = ncurves counts['ncurves_c'] = comma(ncurves) nclasses = g2c_db_isogeny_classes_count() counts['nclasses'] = nclasses counts['nclasses_c'] = comma(nclasses) max_D = curves.find().sort('abs_disc', DESCENDING).limit(1)[0]['abs_disc'] counts['max_D'] = max_D counts['max_D_c'] = comma(max_D) self._counts = counts
def by_url_isogeny_class_discriminant(cond, alpha, disc): data = to_dict(request.args) clabel = str(cond)+"."+alpha # if the isogeny class is not present in the database, return a 404 (otherwise title and bread crumbs refer to a non-existent isogeny class) if not g2c_db_curves().find_one({'class':clabel},{'_id':True}): return abort(404, 'Genus 2 isogeny class %s not found in database.'%clabel) data['title'] = 'Genus 2 curves in isogeny class %s of discriminant %s' % (clabel,disc) data['bread'] = [('Genus 2 Curves', url_for(".index")), ('$\Q$', url_for(".index_Q")), ('%s' % cond, url_for(".by_conductor", cond=cond)), ('%s' % alpha, url_for(".by_url_isogeny_class_label", cond=cond, alpha=alpha)), ('%s' % disc, url_for(".by_url_isogeny_class_discriminant", cond=cond, alpha=alpha, disc=disc))] if len(request.args) > 0: # if conductor or discriminant changed, fall back to a general search if ('cond' in request.args and request.args['cond'] != str(cond)) or \ ('abs_disc' in request.args and request.args['abs_disc'] != str(disc)): return redirect (url_for(".index", **request.args), 307) data['title'] += ' search results' data['bread'].append(('search results','')) data['cond'] = cond data['class'] = clabel data['abs_disc'] = disc return genus2_curve_search(data)
def download_search(info): lang = info.get('language','').strip() if not lang in download_languages: return "Please specify a language in %s"%download_languages filename = 'genus2_curves' + download_file_suffix[lang] mydate = time.strftime("%d %B %Y") # reissue query here try: res = g2c_db_curves().find(literal_eval(info.get('query','{}')),{'_id':int(0),'eqn':int(1)}) except Exception as err: return "Unable to parse query: %s"%err c = download_comment_prefix[lang] s = '\n' s += c + ' Genus 2 curves downloaded from the LMFDB downloaded on %s. Found %s curves.\n'%(mydate, res.count()) s += c + ' Below is a list called data. Each entry has the form:\n' s += c + ' [[f coeffs],[h coeffs]]\n' s += c + ' defining the hyperelliptic curve y^2+h(x)y=f(x)\n' s += c + '\n' s += c + ' ' + download_make_data_comment[lang] + '\n' s += '\n' s += download_assignment_start[lang] + '\\\n' # loop through all search results and grab the curve equations for r in res: entry = str(r['eqn']) entry = entry.replace('u','') entry = entry.replace('\'','') entry = entry.replace('\"','') s += entry + ',\\\n' s = s[:-3] s += download_assignment_end[lang] s += '\n\n' s += download_make_data[lang] strIO = StringIO.StringIO() strIO.write(s) strIO.seek(0) return send_file(strIO, attachment_filename=filename, as_attachment=True)
def genus2_curve_search(info): if 'jump' in info: jump = info["jump"].strip() if re.match(r'^\d+\.[a-z]+\.\d+\.\d+$', jump): return redirect(url_for_curve_label(jump), 301) else: if re.match(r'^\d+\.[a-z]+$', jump): return redirect(url_for_isogeny_class_label(jump), 301) else: # Handle direct Lhash input if re.match(r'^\#\d+$', jump) and ZZ(jump[1:]) < 2**61: c = g2c_db_curves().find_one({'Lhash': jump[1:].strip()}) if c: return redirect( url_for_isogeny_class_label(c["class"]), 301) else: errmsg = "hash %s not found" else: errmsg = "%s is not a valid genus 2 curve or isogeny class label" flash_error(errmsg, jump) return redirect(url_for(".index")) if info.get('download', '').strip() == '1': return download_search(info) info["st_group_list"] = st_group_list info["st_group_dict"] = st_group_dict info["real_geom_end_alg_list"] = real_geom_end_alg_list info["real_geom_end_alg_to_ST0_dict"] = real_geom_end_alg_to_ST0_dict info["aut_grp_list"] = aut_grp_list info["aut_grp_dict"] = aut_grp_dict info["geom_aut_grp_list"] = geom_aut_grp_list info["geom_aut_grp_dict"] = geom_aut_grp_dict bread = info.get('bread', (('Genus 2 Curves', url_for(".index")), ('$\Q$', url_for(".index_Q")), ('Search Results', '.'))) query = {} try: parse_ints(info, query, 'abs_disc', 'absolute discriminant') parse_bool(info, query, 'is_gl2_type', 'is of GL2-type') parse_bool(info, query, 'has_square_sha', 'has square Sha') parse_bool(info, query, 'locally_solvable', 'is locally solvable') parse_bool(info, query, 'is_simple_geom', 'is geometrically simple') parse_ints(info, query, 'cond', 'conductor') parse_ints(info, query, 'num_rat_wpts', 'rational Weierstrass points') parse_bracketed_posints(info, query, 'torsion', 'torsion structure', maxlength=4, check_divisibility="increasing") parse_ints(info, query, 'torsion_order', 'torsion order') if 'torsion' in query and not 'torsion_order' in query: query['torsion_order'] = reduce(mul, [int(n) for n in query['torsion']], 1) if 'torsion' in query: query['torsion_subgroup'] = str(query['torsion']).replace(" ", "") query.pop('torsion') # search using string key, not array of ints parse_ints(info, query, 'two_selmer_rank', '2-Selmer rank') parse_ints(info, query, 'analytic_rank', 'analytic rank') # G2 invariants and drop-list items don't require parsing -- they are all strings (supplied by us, not the user) if 'g20' in info and 'g21' in info and 'g22' in info: query['g2_inv'] = "['%s','%s','%s']" % (info['g20'], info['g21'], info['g22']) if 'class' in info: query['class'] = info['class'] for fld in ('st_group', 'real_geom_end_alg', 'aut_grp_id', 'geom_aut_grp_id'): if info.get(fld): query[fld] = info[fld] except ValueError as err: info['err'] = str(err) return render_template("g2c_search_results.html", info=info, title='Genus 2 Curves Search Input Error', bread=bread, credit=credit_string) # Database query happens here info["query"] = query # save query for reuse in download_search cursor = g2c_db_curves().find( query, { '_id': False, 'label': True, 'eqn': True, 'st_group': True, 'is_gl2_type': True, 'is_simple_geom': True, 'analytic_rank': True }) count = parse_count(info, 50) start = parse_start(info) nres = cursor.count() if (start >= nres): start -= (1 + (start - nres) / count) * count if (start < 0): start = 0 res = cursor.sort([("cond", ASCENDING), ("class", ASCENDING), ("disc_key", ASCENDING), ("label", ASCENDING)]).skip(start).limit(count) nres = res.count() if nres == 1: info["report"] = "unique match" else: if nres > count or start != 0: info['report'] = 'displaying matches %s-%s of %s' % ( start + 1, min(nres, start + count), nres) else: info['report'] = 'displaying all %s matches' % nres res_clean = [] for v in res: v_clean = {} v_clean["label"] = v["label"] v_clean["class"] = class_from_curve_label(v["label"]) v_clean["is_gl2_type"] = v["is_gl2_type"] v_clean["is_simple_geom"] = v["is_simple_geom"] v_clean["equation_formatted"] = list_to_min_eqn(literal_eval(v["eqn"])) v_clean["st_group_link"] = st_link_by_name(1, 4, v['st_group']) v_clean["analytic_rank"] = v["analytic_rank"] res_clean.append(v_clean) info["curves"] = res_clean info["curve_url"] = lambda label: url_for_curve_label(label) info["class_url"] = lambda label: url_for_isogeny_class_label(label) info["start"] = start info["count"] = count info["more"] = int(start + count < nres) title = info.get('title', 'Genus 2 Curve search results') credit = credit_string return render_template("g2c_search_results.html", info=info, credit=credit, learnmore=learnmore_list(), bread=bread, title=title)
def random_curve(): label = random_value_from_collection(g2c_db_curves(), 'label') return redirect(url_for_curve_label(label), 307)
def genus2_curve_search(info): if 'jump' in info: jump = info["jump"].strip() if re.match(r'^\d+\.[a-z]+\.\d+\.\d+$',jump): return redirect(url_for_curve_label(jump), 301) else: if re.match(r'^\d+\.[a-z]+$', jump): return redirect(url_for_isogeny_class_label(jump), 301) else: # Handle direct Lhash input if re.match(r'^\#\d+$',jump) and ZZ(jump[1:]) < 2**61: c = g2c_db_curves().find_one({'Lhash': jump[1:].strip()}) if c: return redirect(url_for_isogeny_class_label(c["class"]), 301) else: errmsg = "hash %s not found" else: errmsg = "%s is not a valid genus 2 curve or isogeny class label" flash_error (errmsg, jump) return redirect(url_for(".index")) if info.get('download','').strip() == '1': return download_search(info) info["st_group_list"] = st_group_list info["st_group_dict"] = st_group_dict info["real_geom_end_alg_list"] = real_geom_end_alg_list info["real_geom_end_alg_to_ST0_dict"] = real_geom_end_alg_to_ST0_dict info["aut_grp_list"] = aut_grp_list info["aut_grp_dict"] = aut_grp_dict info["geom_aut_grp_list"] = geom_aut_grp_list info["geom_aut_grp_dict"] = geom_aut_grp_dict bread = info.get('bread',(('Genus 2 Curves', url_for(".index")), ('$\Q$', url_for(".index_Q")), ('Search Results', '.'))) query = {} try: parse_ints(info,query,'abs_disc','absolute discriminant') parse_bool(info,query,'is_gl2_type','is of GL2-type') parse_bool(info,query,'has_square_sha','has square Sha') parse_bool(info,query,'locally_solvable','is locally solvable') parse_bool(info,query,'is_simple_geom','is geometrically simple') parse_ints(info,query,'cond','conductor') parse_ints(info,query,'num_rat_wpts','rational Weierstrass points') parse_bracketed_posints(info, query, 'torsion', 'torsion structure', maxlength=4,check_divisibility="increasing") parse_ints(info,query,'torsion_order','torsion order') if 'torsion' in query and not 'torsion_order' in query: query['torsion_order'] = reduce(mul,[int(n) for n in query['torsion']],1) if 'torsion' in query: query['torsion_subgroup'] = str(query['torsion']).replace(" ","") query.pop('torsion') # search using string key, not array of ints parse_ints(info,query,'two_selmer_rank','2-Selmer rank') parse_ints(info,query,'analytic_rank','analytic rank') # G2 invariants and drop-list items don't require parsing -- they are all strings (supplied by us, not the user) if 'g20' in info and 'g21' in info and 'g22' in info: query['g2_inv'] = "['%s','%s','%s']"%(info['g20'], info['g21'], info['g22']) if 'class' in info: query['class'] = info['class'] for fld in ('st_group', 'real_geom_end_alg', 'aut_grp_id', 'geom_aut_grp_id'): if info.get(fld): query[fld] = info[fld] except ValueError as err: info['err'] = str(err) return render_template("g2c_search_results.html", info=info, title='Genus 2 Curves Search Input Error', bread=bread, credit=credit_string) # Database query happens here info["query"] = query # save query for reuse in download_search cursor = g2c_db_curves().find(query, {'_id':False, 'label':True, 'eqn':True, 'st_group':True, 'is_gl2_type':True, 'is_simple_geom':True, 'analytic_rank':True}) count = parse_count(info, 50) start = parse_start(info) nres = cursor.count() if(start >= nres): start -= (1 + (start - nres) / count) * count if(start < 0): start = 0 res = cursor.sort([("cond", ASCENDING), ("class", ASCENDING), ("disc_key", ASCENDING), ("label", ASCENDING)]).skip(start).limit(count) nres = res.count() if nres == 1: info["report"] = "unique match" else: if nres > count or start != 0: info['report'] = 'displaying matches %s-%s of %s' % (start + 1, min(nres, start + count), nres) else: info['report'] = 'displaying all %s matches' % nres res_clean = [] for v in res: v_clean = {} v_clean["label"] = v["label"] v_clean["class"] = class_from_curve_label(v["label"]) v_clean["is_gl2_type"] = v["is_gl2_type"] v_clean["is_simple_geom"] = v["is_simple_geom"] v_clean["equation_formatted"] = list_to_min_eqn(literal_eval(v["eqn"])) v_clean["st_group_link"] = st_link_by_name(1,4,v['st_group']) v_clean["analytic_rank"] = v["analytic_rank"] res_clean.append(v_clean) info["curves"] = res_clean info["curve_url"] = lambda label: url_for_curve_label(label) info["class_url"] = lambda label: url_for_isogeny_class_label(label) info["start"] = start info["count"] = count info["more"] = int(start+count<nres) title = info.get('title','Genus 2 Curve search results') credit = credit_string return render_template("g2c_search_results.html", info=info, credit=credit,learnmore=learnmore_list(), bread=bread, title=title)