Repository: LMFDB/lmfdb

Issue:
Confusion about notation for signatures, and seemingly missing entries for higher genus curves
From the feedback page:

> Actually, I'm confused about the signature of the entry I just submitted about.
> 
> It's an automorphism of a genus 3 surface of order 2. 
> 
> http://www.lmfdb.org/HigherGenus/C/Aut/?start=0&paging=0&genus=3&count=200
> 
> Or to see it in a shorter list:
> 
> http://www.lmfdb.org/HigherGenus/C/Aut/?start=0&paging=0&genus=3&group_order=2&count=200
> 
> The signature says [2;2]. But shouldn't it be [2; -], or some other notation for no branch points? This should be a free action on a genus 3 curve, with quotient a genus 2 curve.
> 
> I feel like this may be an issue throughout the database. For instance here:
> 
> http://www.lmfdb.org/HigherGenus/C/Aut/?start=0&paging=0&genus=4&group_order=3&count=200
> 
> The [2;2] entry should be [2; -]
> 
> And I was going to say here, next:
> 
> http://www.lmfdb.org/HigherGenus/C/Aut/?start=0&paging=0&genus=7&group_order=3&count=200
> 
> There should be a [3; -] entry. But it doesn't even appear, despite the fact that there are genus 7 curves with an order 3 automorphisms acting freely and with a genus 3 quotient. 
> 
> If I'm mistaken or if some other convention I'm unfamiliar with is being used, please let me know.
> 
> Thanks!
> Justin Lanier
> 

Reply to jlanier8@gatech.edu


Discussion:
I'll write to Justin about all of these issues but the gist of the problem is that the quotient genus >0 data wasn't ready for "prime time" (basically I thought this data had all vanished in the switch from Mongo to Postgres since it didn't show up on searches as Justin points out).  I am aware of the issues (Dave Roberts and Kiran Kedlaya also pointed them out to me recently) and my students and I are just about done fixing all of them.    

Jen
Just to clarify, it looks like there are pages with quotient genus > 0 in the database, e.g. http://www.lmfdb.org/HigherGenus/C/Aut/3.2-1.1.2-2-2-2.1.  Should these be removed?

Regarding the issues that Dave Roberts and Kiran Kedlaya pointed out, is there already a github issue for this (in which case perhaps this issue is a duplicate), or should this issue serve that purpose (and if so, does it adequately describe the problem)?
No! Please don't remove them.  We've got fixes for this coming soon.   

The issues Dave and Kiran brought up are encompassed in one of the multiple issues posted yesterday. 



@jenpaulhus Got it, thanks!

Resolving patch:
diff --git a/lmfdb/higher_genus_w_automorphisms/main.py b/lmfdb/higher_genus_w_automorphisms/main.py
--- a/lmfdb/higher_genus_w_automorphisms/main.py
+++ b/lmfdb/higher_genus_w_automorphisms/main.py
@@ -1,6 +1,6 @@
 # -*- coding: utf-8 -*-
 # This Blueprint is about Higher Genus Curves
-# Authors: Jen Paulhus, Lex Martin, David Neill Asanza
+# Authors: Jen Paulhus, Lex Martin, David Neill Asanza, Nhi Ngo, Albert Ford
 # (initial code copied from John Jones Local Fields)
 
 import ast, os, re, StringIO, yaml
@@ -19,7 +19,7 @@
 
 
 # Determining what kind of label
-family_label_regex = re.compile(r'(\d+)\.(\d+-\d+)\.(\d+\.\d+-[^\.]*$)')
+family_label_regex = re.compile(r'(\d+)\.(\d+-\d+)\.(\d+\.\d+-?[^\.]*$)')
 passport_label_regex = re.compile(r'((\d+)\.(\d+-\d+)\.(\d+\.\d+.*))\.(\d+)')
 cc_label_regex = re.compile(r'((\d+)\.(\d+-\d+)\.(\d+)\.(\d+.*))\.(\d+)')
 
@@ -56,15 +56,19 @@ def tfTOyn(bool):
 
 def sign_display(L):
     sizeL = len(L)
-    signL = "[ " + str(L[0]) + "; "
-    for i in range(1,sizeL-1):
-        signL= signL + str(L[i]) + ", "
-
-    signL=signL + str(L[sizeL-1]) + " ]"
+    if sizeL == 1:
+        signL = "[ " + str(L[0]) + "; -]"
+    else:
+        signL = "[ " + str(L[0]) + "; "
+        for i in range(1,sizeL-1):
+            signL= signL + str(L[i]) + ", "
+        signL=signL + str(L[sizeL-1]) + " ]"    
     return signL
 
 def cc_display(L):
     sizeL = len(L)
+    if sizeL == 0:
+        return
     if sizeL == 1:
         return str(L[0])
     stg = str(L[0])+ ", "
@@ -90,12 +94,14 @@ def sort_sign(L):
     return [L[0]] +L1
 
 def label_to_breadcrumbs(L):
-    newsig = '['
-    for i in range(0,len(L)):
+    newsig = '['+L[0]
+    for i in range(1,len(L)):
         if (L[i] == '-'):
             newsig += ","
         elif (L[i] == '.'):
             newsig += ';'
+        elif (L[i] == '0'):  # The case where there is no ramification gives a 0 in signature
+            newsig += '-'
         else:
             newsig += L[i]
 
@@ -353,6 +359,7 @@ def higher_genus_w_automorphisms_search(info, query):
         if query.get('signature'):
             query['signature'] = info['signature'] = str(sort_sign(ast.literal_eval(query['signature']))).replace(' ','')
     parse_gap_id(info,query,'group',name='Group',qfield='group')
+    parse_ints(info,query,'g0',name='Quotient Genus')
     parse_ints(info,query,'genus',name='Genus')
     parse_ints(info,query,'dim',name='Dimension of the family')
     parse_ints(info,query,'group_order', name='Group orders')
@@ -387,6 +394,7 @@ def render_family(args):
             return redirect(url_for(".index"))
         data=dataz[0]
         g = data['genus']
+        g0=data['g0']
         GG = ast.literal_eval(data['group'])
         gn = GG[0]
         gt = GG[1]
@@ -403,6 +411,7 @@ def render_family(args):
 
         prop2 = [
             ('Genus', '\(%d\)' % g),
+             ('Quotient Genus', '\(%d\)' %  g0),
             ('Group', '\(%s\)' %  pretty_group),
             ('Signature', '\(%s\)' % sign_display(ast.literal_eval(data['signature'])))
         ]
@@ -471,6 +480,7 @@ def render_passport(args):
             return redirect(url_for(".index"))
         data=dataz[0]
         g = data['genus']
+        g0=data['g0']
         GG = ast.literal_eval(data['group'])
         gn = GG[0]
         gt = GG[1]
@@ -497,7 +507,8 @@ def render_passport(args):
 
         prop2 = [
             ('Genus', '\(%d\)' % g),
-            ('Small Group', '\(%s\)' %  pretty_group),
+            ('Quotient Genus', '\(%d\)' % g0),
+            ('Group', '\(%s\)' %  pretty_group),
             ('Signature', '\(%s\)' % sign_display(ast.literal_eval(data['signature']))),
             ('Generating Vectors','\(%d\)' % numb)
         ]
@@ -507,7 +518,8 @@ def render_passport(args):
                      'group': pretty_group,
                      'gpid': smallgroup,
                      'numb':numb,
-                     'disp_numb':min(numb,numgenvecs)
+                     'disp_numb':min(numb,numgenvecs),
+                     'g0': data ['g0']
                    })
 
         if spname:
@@ -533,11 +545,19 @@ def render_passport(args):
                 x3=' '
 
             x4=[]
-            for perm in dat['gen_vectors']:
-                cycperm=Permutation(perm).cycle_string()
-
-                x4.append(sep.join(split_perm(cycperm)))
-
+            if dat['g0'] == 0:
+                for perm in dat['gen_vectors']:
+                    cycperm=Permutation(perm).cycle_string()
+                    x4.append(sep.join(split_perm(cycperm)))
+
+            elif dat['g0'] > 0:
+                for perm in dat['gen_vectors']:
+                    cycperm =Permutation(perm).cycle_string()
+                    #if display_perm == '()':
+                    if cycperm == '()':
+                        x4.append('Id(G)')
+                    else:
+                        x4.append(sep.join(split_perm(cycperm)))
             Ldata.append([x1,x2,x3,x4])
 
 
@@ -752,7 +772,7 @@ def hgcwa_code_download(**args):
     nhypcycstr += code_list['add_to_total_basic'][lang] + '\n'
 
     start = time.time()
-    lines = [(startstr + (signHfmt if dataz.get('signH') is not None else stdfmt).format(**dataz) + ((hypfmt.format(**dataz) if dataz['hyperelliptic'] else cyctrigfmt.format(**dataz) if dataz['cyclic_trigonal'] else nhypcycstr) if dataz.get('hyperelliptic') else '')) for dataz in data]
+    lines = [(startstr + (signHfmt if 'signH' in dataz else (stdfmt + (hypfmt if (dataz.get('hyperelliptic') and dataz['hyperelliptic']) else cyctrigfmt if (dataz.get('cyclic_trigonal') and dataz['cyclic_trigonal']) else nhypcycstr)))).format(**dataz) for dataz in data]
     code += '\n'.join(lines)
     print "%s seconds for %d bytes" %(time.time() - start,len(code))
     strIO = StringIO.StringIO()
@@ -762,8 +782,6 @@ def hgcwa_code_download(**args):
 
 
 
-
-#JEN TEST FUNCTION
 @higher_genus_w_automorphisms_page.route("/download/<download_type>")
 #def hgcwa_code_download_search(**args):
 def hgcwa_code_download_search(res,download_type):
@@ -831,7 +849,7 @@ def hgcwa_code_download_search(res,download_type):
             nhypcycstr += code_list['add_to_total_basic'][lang] + '\n'
     
             start = time.time()
-            lines = [(startstr + (signHfmt if 'signH' in dataz else stdfmt).format(**dataz) + ((hypfmt.format(**dataz) if dataz['hyperelliptic'] else cyctrigfmt.format(**dataz) if dataz['cyclic_trigonal'] else nhypcycstr) if 'hyperelliptic' in dataz else '')) for dataz in data]
+            lines = [(startstr + (signHfmt if 'signH' in dataz else (stdfmt + (hypfmt if (dataz.get('hyperelliptic') and dataz['hyperelliptic']) else cyctrigfmt if (dataz.get('cyclic_trigonal') and dataz['cyclic_trigonal']) else nhypcycstr)))).format(**dataz) for dataz in data]
             code += '\n'.join(lines)
 
 


Test patch:
diff --git a/lmfdb/higher_genus_w_automorphisms/test_hgcwa.py b/lmfdb/higher_genus_w_automorphisms/test_hgcwa.py
--- a/lmfdb/higher_genus_w_automorphisms/test_hgcwa.py
+++ b/lmfdb/higher_genus_w_automorphisms/test_hgcwa.py
@@ -50,3 +50,16 @@ def test_unique_groups_pages(self):
         assert 'Distribution of groups in curves of genus 5' in L.data
 
         
+    def test_quo_genus_gt_0(self):
+        L = self.tc.get('/HigherGenus/C/Aut/3.2-1.2.0.1')
+        assert '[2;-]' in L.data
+
+    def test_quo_genus_search(self):
+        L = self.tc.get('/HigherGenus/C/Aut/?genus=3&g0=1..3')
+        assert 'displaying all 10 matches' in L.data
+
+    def idG_showing(self):
+        L = self.tc.get('/HigherGenus/C/Aut/2.2-1.1.2-2.1')
+        assert 'Id(G)' in L.data
+
+