Build Signature Map
Generates the 448-entry signature-to-folio concordance from the Aldine collation formula (a-z, A-G).
1"""Build the signature-to-folio mapping table for the 1499 Aldine HP. 2 3The 1499 Aldus Manutius edition uses the standard Aldine collation: 4 Quires a-z (skipping j, u, w) then A-G 5 Each quire has 8 leaves (quaternion format) 6 Each leaf has recto (r) and verso (v) 7 8Collation formula: a-y⁸ z⁴ A-F⁸ G⁴ = 234 leaves = 468 pages 9 10This produces a deterministic lookup: signature "a1r" = folio 1 recto, 11"a1v" = folio 1 verso, "b1r" = folio 9 recto, etc. 12""" 13 14import sqlite3 15from pathlib import Path 16 17BASE_DIR = Path(__file__).resolve().parent.parent 18DB_PATH = BASE_DIR / "db" / "hp.db" 19 20# Standard Aldine quire sequence for the 1499 HP 21# Lowercase quires: a through y, skipping j, u, w 22LOWERCASE_QUIRES = [c for c in 'abcdefghiklmnopqrstxyz'] 23# Uppercase quires (for the second alphabet run): A through G 24UPPERCASE_QUIRES = list('ABCDEFG') 25 26# Leaves per quire - most are 8 (quaternion), but z and G are 4 27QUIRE_SIZES = {} 28for q in LOWERCASE_QUIRES: 29 QUIRE_SIZES[q] = 4 if q == 'z' else 8 30for q in UPPERCASE_QUIRES: 31 QUIRE_SIZES[q] = 4 if q == 'G' else 8 32 33 34def generate_signatures(): 35 """Generate all signatures in order with their sequential folio numbers.""" 36 all_quires = LOWERCASE_QUIRES + UPPERCASE_QUIRES 37 folio_num = 1 38 entries = [] 39 40 for quire in all_quires: 41 leaves = QUIRE_SIZES[quire] 42 for leaf in range(1, leaves + 1): 43 for side in ('r', 'v'): 44 sig = f"{quire}{leaf}{side}" 45 entries.append({ 46 'signature': sig, 47 'folio_number': folio_num, 48 'side': side, 49 'quire': quire, 50 'leaf_in_quire': leaf, 51 }) 52 folio_num += 1 53 54 return entries 55 56 57def main(): 58 entries = generate_signatures() 59 60 conn = sqlite3.connect(DB_PATH) 61 cur = conn.cursor() 62 63 # Clear existing entries 64 cur.execute("DELETE FROM signature_map") 65 66 for e in entries: 67 cur.execute( 68 """INSERT INTO signature_map 69 (signature, folio_number, side, quire, leaf_in_quire) 70 VALUES (?, ?, ?, ?, ?)""", 71 (e['signature'], e['folio_number'], e['side'], e['quire'], e['leaf_in_quire']) 72 ) 73 74 conn.commit() 75 76 # Summary 77 total = len(entries) 78 quire_count = len(LOWERCASE_QUIRES) + len(UPPERCASE_QUIRES) 79 max_folio = entries[-1]['folio_number'] 80 print(f"Built signature map: {total} entries, {quire_count} quires, {max_folio} folios") 81 print(f" First: {entries[0]['signature']} = folio {entries[0]['folio_number']}") 82 print(f" Last: {entries[-1]['signature']} = folio {entries[-1]['folio_number']}") 83 84 # Spot checks 85 print("\nSpot checks:") 86 cur.execute("SELECT signature, folio_number FROM signature_map WHERE signature = 'a1r'") 87 r = cur.fetchone() 88 print(f" a1r -> folio {r[1]}" if r else " a1r NOT FOUND") 89 90 cur.execute("SELECT signature, folio_number FROM signature_map WHERE signature = 'b1r'") 91 r = cur.fetchone() 92 print(f" b1r -> folio {r[1]}" if r else " b1r NOT FOUND") 93 94 cur.execute("SELECT signature, folio_number FROM signature_map WHERE signature = 'e1r'") 95 r = cur.fetchone() 96 print(f" e1r -> folio {r[1]} (Russell's methodology boundary)" if r else " e1r NOT FOUND") 97 98 conn.close() 99 print("\nDone.") 100 101 102if __name__ == "__main__": 103 main()