Alchemical Hands in the Hypnerotomachia Poliphili

Marginalia, Scholarship & Reception

← All Scripts

Add Annotator Hands

add_hands.py — 443 lines

Creates 11 annotator hand profiles and attributes dissertation references to specific hands.

1"""Add annotator hands table and tag dissertation references with hand attributions.
2
3Based on James Russell's PhD thesis analysis of six annotated copies of the HP.
4"""
5
6import sqlite3
7from pathlib import Path
8
9BASE_DIR = Path(__file__).resolve().parent.parent
10DB_PATH = BASE_DIR / "db" / "hp.db"
11
12
13HANDS_SCHEMA = """
14CREATE TABLE IF NOT EXISTS annotator_hands (
15    id INTEGER PRIMARY KEY,
16    hand_label TEXT NOT NULL,
17    manuscript_shelfmark TEXT NOT NULL,
18    attribution TEXT,
19    language TEXT,
20    ink_color TEXT,
21    date_range TEXT,
22    school TEXT,
23    interests TEXT,
24    description TEXT,
25    is_alchemist BOOLEAN DEFAULT 0,
26    chapter_num INTEGER,
27    UNIQUE(hand_label, manuscript_shelfmark)
28);
29
30-- Add hand_id column to dissertation_refs if not exists
31"""
32
33ALTER_REFS = """
34ALTER TABLE dissertation_refs ADD COLUMN hand_id INTEGER REFERENCES annotator_hands(id);
35"""
36
37
38# All annotator hands identified by Russell across the six copies
39HANDS = [
40    # BL C.60.o.12 (Ch. 6) — 1545 edition
41    {
42        'hand_label': 'A',
43        'manuscript_shelfmark': 'C.60.o.12',
44        'attribution': 'Ben Jonson',
45        'language': 'English, Latin',
46        'ink_color': None,
47        'date_range': 'c.1600-1637',
48        'school': None,
49        'interests': 'stagecraft, linguistic technicalities, inventio, visual stage design',
50        'description': (
51            'First hand in the BL copy, convincingly attributed to Ben Jonson. '
52            'Composed a selective summary foregrounding large-scale visual monuments '
53            'and vehicles suitable for stage design. Extensive grammatical parsing '
54            'through underlining (simple, double, bracket). Interested in architectural '
55            'vocabulary and natural forms (snails, acanthus, seashells) as column models. '
56            'Mining the HP for ideas for masque stagecraft (inventio).'
57        ),
58        'is_alchemist': False,
59        'chapter_num': 6,
60    },
61    {
62        'hand_label': 'B',
63        'manuscript_shelfmark': 'C.60.o.12',
64        'attribution': 'Anonymous (possibly Royal Society circle)',
65        'language': 'Latin, English',
66        'ink_color': None,
67        'date_range': 'post-1641, late 17th century',
68        'school': "Jean d'Espagnet (Enchiridion Physicae Restitutae)",
69        'interests': 'alchemical allegory, Master Mercury, ideographic vocabulary, prisca sapientia',
70        'description': (
71            "Anonymous second hand in the BL copy. Inferred alchemical formulae beneath "
72            "the narrative surface. Labelled passages and woodcuts with alchemical signs "
73            "(gold, silver, mercury, Venus, Jupiter). Follower of Jean d'Espagnet's "
74            "emphasis on mercury as catalytic bearer of solar energy. Used extensive "
75            "alchemical ideograms with Latin inflections (e.g. sun-symbol + '-ra' for "
76            "'aurata'). Consistency with Newton's Keynes MSS vocabulary suggests possible "
77            "connection to Royal Society or Cambridge. Wrote programmatic summary on "
78            "flyleaf verso: 'verus sensus intentionis huius libri est 3um' — threefold "
79            "meaning centering on 'Master Mercury'. Notes decline in Book II but alchemical "
80            "symbols persist. Also an Englishman ('frogg green')."
81        ),
82        'is_alchemist': True,
83        'chapter_num': 6,
84    },
85
86    # Buffalo (Ch. 7) — 1499 edition
87    {
88        'hand_label': 'A',
89        'manuscript_shelfmark': 'Buffalo RBR',
90        'attribution': 'Anonymous (possibly Jesuit, St. Omer)',
91        'language': 'French',
92        'ink_color': 'black',
93        'date_range': 'pre-1739',
94        'school': None,
95        'interests': 'narrative summary',
96        'description': (
97            'First French hand in black ink. Wrote summary of HP narrative on page '
98            'following dedicatory letter. If the book was at St. Omer before 1739 '
99            '(as Jesuit ex libris suggests), this may be a Jesuit annotator.'
100        ),
101        'is_alchemist': False,
102        'chapter_num': 7,
103    },
104    {
105        'hand_label': 'B',
106        'manuscript_shelfmark': 'Buffalo RBR',
107        'attribution': 'Anonymous (possibly Jesuit, St. Omer)',
108        'language': 'French',
109        'ink_color': 'light brown',
110        'date_range': 'pre-1739',
111        'school': None,
112        'interests': 'Greek etymologies, Hebrew roots, Plinian sources',
113        'description': (
114            'Second French hand in light brown ink. Primary interest in etymologies '
115            'of Greek terms. Only annotator in the study to identify Hebrew roots. '
116            'Also traces Plinian sources (Naturalis historia) for wines, laws, '
117            'architecture. Similar ductus to Hand A suggests common origin, possibly '
118            'another Jesuit of St. Omer.'
119        ),
120        'is_alchemist': False,
121        'chapter_num': 7,
122    },
123    {
124        'hand_label': 'C',
125        'manuscript_shelfmark': 'Buffalo RBR',
126        'attribution': 'Anonymous',
127        'language': 'Latin',
128        'ink_color': 'brown',
129        'date_range': None,
130        'school': None,
131        'interests': 'narrative signposting',
132        'description': 'Latin hand in brown ink. Primarily interested in signposting the narrative, summarising major passages.',
133        'is_alchemist': False,
134        'chapter_num': 7,
135    },
136    {
137        'hand_label': 'D',
138        'manuscript_shelfmark': 'Buffalo RBR',
139        'attribution': 'Anonymous',
140        'language': 'Italian, Latin',
141        'ink_color': None,
142        'date_range': None,
143        'school': None,
144        'interests': 'architecture',
145        'description': (
146            'Italian hand responding to Hand A. In one instance crosses off A\'s comments '
147            'and offers abbreviated summary. Primary interest in architecture. Switches to '
148            'Latin when labelling architectural features.'
149        ),
150        'is_alchemist': False,
151        'chapter_num': 7,
152    },
153    {
154        'hand_label': 'E',
155        'manuscript_shelfmark': 'Buffalo RBR',
156        'attribution': 'Anonymous',
157        'language': 'Latin',
158        'ink_color': None,
159        'date_range': 'late 17th-early 18th century',
160        'school': 'pseudo-Geber (Jabir ibn Hayyan)',
161        'interests': 'alchemical allegory, Sol/Luna, sulphur, chemical wedding',
162        'description': (
163            "Final distinguishable hand. Applies alchemical reading. Overwrites Hand D "
164            "(latest hand). Follower of pseudo-Geber school emphasizing sulphur and "
165            "Sol/Luna pairings. Unlike BL alchemist, uses minimal ideograms — writes "
166            "out element names in full (e.g. 'sulphur naturae'). Labels passages with "
167            "alchemical stages. Praises Geber's 'ingenium subtile'. Reads male-female "
168            "pairings as alchemical weddings. Identifies chess match results as "
169            "silver/gold transmutation."
170        ),
171        'is_alchemist': True,
172        'chapter_num': 7,
173    },
174
175    # Modena (Ch. 4) — 1499 edition
176    {
177        'hand_label': 'Primary',
178        'manuscript_shelfmark': 'Modena (Panini)',
179        'attribution': 'Benedetto Giovio',
180        'language': 'Italian, Latin',
181        'ink_color': None,
182        'date_range': 'early 16th century',
183        'school': None,
184        'interests': 'Plinian natural history, etymology, botany, music, medicine',
185        'description': (
186            'Primary hand attributed to Benedetto Giovio (1471-1545). Plinian '
187            'encyclopedic reading: extracts etymologies, botanical identifications, '
188            'medical terms, musical modes, mineralogy, and literary cross-references '
189            '(Boccaccio, Erasmus, Homer). Over 150 sources identified by Stichel. '
190            'Also modified woodcuts with coloring and shading.'
191        ),
192        'is_alchemist': False,
193        'chapter_num': 4,
194    },
195
196    # Como (Ch. 5) — 1499 edition
197    {
198        'hand_label': 'Primary',
199        'manuscript_shelfmark': 'INCUN A.5.13',
200        'attribution': 'Benedetto Giovio',
201        'language': 'Italian, Latin',
202        'ink_color': None,
203        'date_range': 'early 16th century',
204        'school': None,
205        'interests': 'Plinian botany, botanical vocabulary extraction',
206        'description': (
207            'Also attributed to Benedetto Giovio. Same hand as Modena copy. '
208            'Focuses specifically on botanical vocabulary extraction, treating '
209            'the HP as a Plinian encyclopedia. Identifies plants with Plinian '
210            'cross-references.'
211        ),
212        'is_alchemist': False,
213        'chapter_num': 5,
214    },
215
216    # Vatican (Ch. 8) — 1499 edition
217    {
218        'hand_label': 'Primary',
219        'manuscript_shelfmark': 'Inc.Stam.Chig.II.610',
220        'attribution': 'Pope Alexander VII (Fabio Chigi)',
221        'language': 'Latin, Italian',
222        'ink_color': None,
223        'date_range': 'c.1630s-1667',
224        'school': None,
225        'interests': 'acutezze (verbal wit), architecture, Rome topography',
226        'description': (
227            'Attributed to Fabio Chigi, later Pope Alexander VII (1599-1667). '
228            'Combed text for examples of verbal wit (acutezze). Compared '
229            "Poliphilo's architectural journeys with his own passages through "
230            "Rome. Interest in orthographic diagrams and textual emendation."
231        ),
232        'is_alchemist': False,
233        'chapter_num': 8,
234    },
235
236    # Siena (Ch. 9) — 1499 edition
237    {
238        'hand_label': 'Primary',
239        'manuscript_shelfmark': 'O.III.38',
240        'attribution': 'Anonymous',
241        'language': 'Latin, Italian',
242        'ink_color': None,
243        'date_range': 'early modern',
244        'school': None,
245        'interests': 'calligraphic annotation, textual emendation, educative marginalia',
246        'description': (
247            'Painstaking calligraphic marginalia. Multiple hands (A-D) including '
248            "ownership marks by Francisci Fini and Friedrich Schaller. Hand C wrote "
249            "'Ad lectorem' note. Hand D engaged with dating and literary analysis."
250        ),
251        'is_alchemist': False,
252        'chapter_num': 9,
253    },
254]
255
256
257# Rules for attributing dissertation references to hands
258# Based on thesis content analysis: signature refs that Russell explicitly
259# discusses in connection with specific hands.
260HAND_ATTRIBUTION_RULES = {
261    # BL C.60.o.12 — Ch. 6
262    # Hand A (Jonson): stagecraft, grammatical parsing, architectural vocabulary
263    ('C.60.o.12', 'A'): {
264        'signatures': {
265            'a4r',  # underlining techniques (p.147)
266            'e7r',  # hatching technique for shadow (p.150)
267            'b4v',  # Corinthian order identification (p.151)
268            'm7v',  # Corinthian column base (p.152)
269            'd4r',  # snail metaphor (p.152)
270            't7v',  # seashell form (p.152)
271        },
272        'pages': range(123, 156),
273    },
274    # Hand B (Alchemist): ideograms, mercury, elemental signs
275    ('C.60.o.12', 'B'): {
276        'signatures': {
277            'b6v',  # Elephant and Obelisk ideograms (p.157)
278            'E8v',  # Venus symbol replacing name (p.157)
279            'y7r',  # Fons Heptagonis labeled (p.136)
280            'e1r',  # Panton Tokadi / vials labeled (p.163-164)
281            'd8v',  # mercury/vas references (p.164)
282            'a1r',  # dawn scene alchemical annotation (p.165)
283            'a3r',  # alchemical context (p.155)
284            'k5r',  # alchemical labeling (p.131)
285        },
286        'pages': range(155, 170),
287    },
288    # Buffalo — Ch. 7
289    # Hand E (Alchemist): Geberian school, sulphur, Sol/Luna
290    ('Buffalo RBR', 'E'): {
291        'signatures': {
292            'b7r',  # Geberian schema, ingenium subtile (p.187)
293            'c6v',  # Venus/Bacchus/Ceres (p.187-188)
294            'h1r',  # chess match/hermaphrodite (p.189-190)
295            'b5r',  # alchemical context (p.190)
296        },
297        'pages': range(185, 200),
298    },
299    # Hand B (Etymologist): Plinian sources, etymologies
300    ('Buffalo RBR', 'B'): {
301        'signatures': {
302            'b8v',  # Hebrew roots (p.172)
303            'g8r',  # Plinian sources for laws (p.176)
304            'h7r',  # serpent wreath correction (p.183)
305        },
306        'pages': range(172, 185),
307    },
308    # Hand D (Architect)
309    ('Buffalo RBR', 'D'): {
310        'signatures': {
311            'b1r',  # architectural labels (p.173, 181)
312        },
313    },
314    # Hand A (French narrative)
315    ('Buffalo RBR', 'A'): {
316        'signatures': {
317            'A2r',  # Polia name origin (p.179)
318        },
319    },
320}
321
322
323def main():
324    conn = sqlite3.connect(DB_PATH)
325    cur = conn.cursor()
326
327    # Create hands table
328    print("Creating annotator_hands table...")
329    cur.executescript(HANDS_SCHEMA)
330
331    # Add hand_id column if not exists
332    try:
333        cur.execute(ALTER_REFS)
334        print("  Added hand_id column to dissertation_refs")
335    except sqlite3.OperationalError as e:
336        if 'duplicate column' in str(e).lower():
337            print("  hand_id column already exists")
338        else:
339            raise
340
341    # Insert hands
342    print("Inserting annotator hands...")
343    for h in HANDS:
344        cur.execute(
345            """INSERT OR REPLACE INTO annotator_hands
346               (hand_label, manuscript_shelfmark, attribution, language,
347                ink_color, date_range, school, interests, description,
348                is_alchemist, chapter_num)
349               VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)""",
350            (h['hand_label'], h['manuscript_shelfmark'], h['attribution'],
351             h['language'], h['ink_color'], h['date_range'], h['school'],
352             h['interests'], h['description'], h['is_alchemist'],
353             h['chapter_num'])
354        )
355    conn.commit()
356    print(f"  Inserted {len(HANDS)} hands")
357
358    # Attribute refs to hands based on rules
359    print("\nAttributing dissertation references to hands...")
360    attributed = 0
361    for (shelfmark, hand_label), rule in HAND_ATTRIBUTION_RULES.items():
362        # Get hand_id
363        cur.execute(
364            "SELECT id FROM annotator_hands WHERE manuscript_shelfmark=? AND hand_label=?",
365            (shelfmark, hand_label)
366        )
367        row = cur.fetchone()
368        if not row:
369            print(f"  WARNING: hand not found: {shelfmark} / {hand_label}")
370            continue
371        hand_id = row[0]
372
373        sigs = rule.get('signatures', set())
374        pages = rule.get('pages')
375
376        for sig in sigs:
377            # Find matching refs
378            if pages:
379                cur.execute(
380                    """UPDATE dissertation_refs SET hand_id = ?
381                       WHERE signature_ref = ? AND manuscript_shelfmark = ?
382                       AND thesis_page BETWEEN ? AND ?""",
383                    (hand_id, sig, shelfmark, pages.start, pages.stop)
384                )
385            else:
386                cur.execute(
387                    """UPDATE dissertation_refs SET hand_id = ?
388                       WHERE signature_ref = ? AND manuscript_shelfmark = ?""",
389                    (hand_id, sig, shelfmark)
390                )
391            attributed += cur.rowcount
392
393    # Also attribute by chapter for copies with single known hands
394    single_hand_chapters = {
395        4: ('Modena (Panini)', 'Primary'),
396        5: ('INCUN A.5.13', 'Primary'),
397        8: ('Inc.Stam.Chig.II.610', 'Primary'),
398        9: ('O.III.38', 'Primary'),
399    }
400    for ch, (shelfmark, hand_label) in single_hand_chapters.items():
401        cur.execute(
402            "SELECT id FROM annotator_hands WHERE manuscript_shelfmark=? AND hand_label=?",
403            (shelfmark, hand_label)
404        )
405        row = cur.fetchone()
406        if not row:
407            continue
408        hand_id = row[0]
409        cur.execute(
410            "UPDATE dissertation_refs SET hand_id = ? WHERE chapter_num = ? AND hand_id IS NULL",
411            (hand_id, ch)
412        )
413        attributed += cur.rowcount
414
415    conn.commit()
416    print(f"  Attributed {attributed} references to hands")
417
418    # Summary
419    print("\nHand attribution summary:")
420    cur.execute("""
421        SELECT h.hand_label, h.manuscript_shelfmark, h.attribution, h.is_alchemist,
422               COUNT(r.id) as ref_count
423        FROM annotator_hands h
424        LEFT JOIN dissertation_refs r ON r.hand_id = h.id
425        GROUP BY h.id
426        ORDER BY h.chapter_num, h.hand_label
427    """)
428    for row in cur.fetchall():
429        label, shelf, attr, alch, count = row
430        alch_tag = " [ALCHEMIST]" if alch else ""
431        print(f"  {shelf} Hand {label} ({attr}){alch_tag}: {count} refs")
432
433    # Show unattributed
434    cur.execute("SELECT COUNT(*) FROM dissertation_refs WHERE hand_id IS NULL")
435    unattr = cur.fetchone()[0]
436    print(f"\n  Unattributed references: {unattr}")
437
438    conn.close()
439    print("\nDone.")
440
441
442if __name__ == "__main__":
443    main()