Coding Day
Rolls A–I · Calendar of Coroners Rolls of the City of London, 1300–1378
You code. Then the machine codes. Then you check it against the page.
Everything for today, and the reference to keep open while you work.
Four jobs: code a portion of a roll by hand, check whether and how a machine can do it, compare your rows with the machine's (optional), and turn your own rows into a chart. How you ask the machine is up to you; the ready-made prompt is optional. Every prompt you need is on this page, ready to copy, so there is nothing to transcribe. Work straight down it, and come back to it whenever you need it afterward.
Questions? Email Data Science/Analysis Research Librarian Tae Hyun Lim at tlim@hamilton.edu, or ask a Data Science Tutor.
Coding Day
Rolls A–I · Calendar of Coroners Rolls of the City of London, 1300–1378
You code. Then the machine codes. Then you check it against the page.
Four jobs, one session
You are not learning to use AI today. You are learning to check it — and checking it means having done the work yourself first, which you have.
Two tools, and one to avoid
Both are on the LITS AI tools page and both take your Hamilton credentials. Pick one and work in it.
amplify.hamilton.edu — hosted by Hamilton LITS, with models from Anthropic, OpenAI and Mistral to choose from. It does not run Python.gemini.google.com — Google's model. It can run Python, so it can calculate counts and draw charts from a file you upload.The Firefly warning is the one to remember. An image generator does not read your data — it produces a picture of a chart, and any numbers in it are generated, not counted. Do not use one when you are asked to make a figure.
NotebookLM — listed on the LITS page as Gemini Notebook — is useful for asking questions of the roll: which entries mention a church? Since December 2025 it can also build tables from your sources. It is not part of today's workflow, and anything it gives you needs the same check against the page.
Before you prompt anything
amplify.hamilton.edu or gemini.google.com and sign in with your Hamilton account.The point of a new conversation is to start the model with as little extra information or context as possible. It is not a clean slate. Depending on the tool and its settings, a model may still draw on your earlier chats or files, and no setting removes what it absorbed in training — Sharpe's edition has been online for years. A name the model "knows" looks exactly like a name it read. The only check is the page.
If you use the ready-made prompt, send it straight after the two diagnostic messages (slide 9), with nothing else in between: anything else typed before it becomes part of what the model works from and can change what it does with the prompt.
First, what is a PDF?
A PDF records what a page looks like, not what the document is. A Word file knows this is a paragraph, this is a heading, this is a list. A PDF mostly stores draw this character, at this spot, in this font.
And a PDF can be made in three different ways.
| Kind of PDF | What is inside | What you get when you extract the text |
|---|---|---|
| Exported from a word processor | The characters and where each one sits | The text, almost exactly |
| A plain scan | A picture of each page, nothing else | Nothing |
| A scan plus OCR | The picture, with an invisible layer of machine-guessed text laid over it | The guess |
Ours is the third kind. What you see on screen is a scanned image of the 1913 book; what a tool pulls out of the file is an OCR program's guess at that image. Slide 7 shows how we know.
PDF stands for Portable Document Format. "Portable" means it is built to look the same on any screen or printer — which is why it mostly stores where each character goes rather than how the text is organized.
OCR stands for optical character recognition: software that looks at a picture of text and guesses which character each shape is.
A PDF can be read three different ways
You cannot tell which method was used from the output alone.
The last line is the one that matters. The chat window hands you text whichever route the tool took, with no label saying where it came from. Everything else today follows from that.
Our text layer was never typed. It is OCR, in a file made in December 2011.
Here is what the full-volume file reports about itself, with pdfinfo:
Creator: Digitized by the Internet Archive Producer: Recoded by LuraDocument PDF v2.28 CreationDate: Mon Dec 5 06:20:43 2011 UTC ModDate: Mon Dec 5 07:32:45 2011 UTC
pdfinfo shows these times in your computer's time zone, so yours may read differently. A roll file cut from it may show different dates. The full volume has 366 pages.pdffonts lists one font for all of it — Courier, not embedded.pdfimages lists three images on every page: a low-resolution color background (about 133 ppi), a 400 ppi color image, and a one-bit black-and-white mask for that image. Together they are the picture you see.Extracting the text layer does not get you Sharpe's printed text. It gets you a machine's guess at it, in a file made almost fifteen years ago.
The chain between the clerk and you has four links, and every one of them can introduce error: the clerk's Latin roll, Sharpe's 1913 English calendar of it, the scan of Sharpe's book, and the OCR pass. The AI is the fifth link. You are the sixth.
How we know: pdfinfo, pdffonts and pdfimages are command-line tools from the free Poppler package (on a Mac, installed with Homebrew); they report a PDF's metadata, fonts and images. No Python is needed. The invisible text shows in each page's drawing instructions, which qpdf can decompress.
Several fields you code sit where the OCR often fails
| What | Where it sits on the page | What the text layer gives (page reads) |
|---|---|---|
| Marginal note, usually the ward | Outer margin, small italic | Nfiii^aif (Neugate) · Crupiil^^aie (Crupulgate) · iVaiebroke (Walebroke) · ^^''^^^ (Bridge) |
| Money | Figures followed by italic s. and d. | 9^. 6d. (9s. 6d.) · los. 4^. (10s. 4d.) |
| Entry number | Start of each entry | I. (1) · ID. (10) · II. (11) |
| Page number | Top of the page | lOI (101) · Ill (111) |
| Footnotes, where occupations are sometimes glossed | Bottom of the page, smallest type | a maker of labours (tabours) |
| Names in italic headings | At the head of each roll, and at some headings within a roll | Sfnte (Strete) · Bat/eld (Hatfeld) · Sta/'lc (Stable) |
| Names, cause, outcome | Body prose | Mostly accurate, with occasional slips: Ricliard (Richard) |
The pattern is the point. Several fields you code — entry numbers, page numbers, money, and the footnotes that explain occupations — sit in parts of the page where the OCR often fails: italic abbreviations, small numerals, footnotes. Most of the story is in the body prose, which is mostly accurate. The marginal ward notes are often garbled, which is why rule 4 of the prompt takes the ward from the sentence, not the margin.
One counter-intuitive detail: money can be garbled even on cleanly printed pages. It is not faint ink. It is the italic s. and d. — 9s. 6d. comes out as 9^. 6d. The failure is typographic, not damage to the page.
You cannot tell from the answer. So test it.
With your roll uploaded, before anything else, send these two messages.
How did you read the PDF I just uploaded? Answer in one sentence, and say specifically whether you extracted an embedded text layer, ran your own OCR on the page images, or looked at the page images directly. If you are not sure, say you are not sure.
List the headings of entries 1 to 5 in this roll, exactly as they appear, character for character. Do not add or remove spaces, and do not correct spelling. If a heading is unclear, write it as you see it.
Message 1 gets the tool's own account of what it did. Treat it as a claim, not a fact: in a test run, a model said it had extracted the text layer when it had been given only page images.
For message 2, put three versions of each heading side by side: the page as you see it; the text layer, which you get by selecting the heading in your PDF viewer and copying it; and the tool's answer. Compare the letters, not the spaces — different programs put spaces in different places when they pull text out of the same file.
If the tool repeats a misreading that is in the text layer — in Roll D, Friiyter where the page prints Fruyter — it was almost certainly reading the text layer. If it gives a different wrong spelling (the same test model wrote Frayser), it was not simply copying the text layer, and it got the name wrong. If it matches the page exactly, you cannot tell which route it took — only that it got those five right.
Try it your own way
The coding prompt in the next section is one way to do this — organized so that the AI pulls out a defined "right answer" in a fixed format. Use it as a reference, not a rule. What we want is for you to try different ways yourself and see what changes.
Whatever you try, check what comes back against the page.
The ready-made prompt (slides 11–13) shows what it takes to get rows that can be compared and checked: fixed columns, closed lists, rules for the known traps. Trying your own requests first can show you why each of those is there — you can see what the tool does without them.
To keep one attempt from shaping the next, start a new conversation for each and upload the roll again. That gives the model less to go on from before — though, as slide 4 says, not a clean slate.
Five things, or it will improvise
NOT STATED and ILLEGIBLE for anything the entry does not give or you cannot read.This is prompt design, not prompt tricks. Each item closes off one way the output can go wrong. Without closed lists, the same value comes back spelled several ways and cannot be counted without cleaning. Without NOT STATED and ILLEGIBLE, a model has no agreed way to mark a value as missing or unreadable, and may fill the cell with a guess. Without an evidence quote, you have to search the whole entry to see what the model based its answer on.
Fill in two blanks at the top. Paste the whole thing.
If you use it as given, change only ROLL_LETTER and CODER_ID. Edited columns stop lining up with everyone else's rows, and the class dataset breaks.
gemini or amplify. (student is for your own hand-coded rows.)
ROLL_LETTER = {{ROLL_LETTER}}
CODER_ID = {{CODER_ID}}
You are helping code medieval coroners' inquests into a dataset. The PDF I uploaded is one roll from R. R. Sharpe, ed., Calendar of Coroners Rolls of the City of London, A.D. 1300-1378 (1913).
Produce ONE ROW PER NUMBERED ENTRY, in printed order, with these 21 columns in exactly this order:
coder_id, roll, case_number, printed_page, entry_type, inquest_date, date_verbatim, ward, ward_verbatim, within_without, parish_verbatim, victim_name, victim_gender, victim_status, manner_of_death, weapon, weapon_verbatim, perpetrator_name, perpetrator_outcome, chattels_verbatim, evidence_quote
VALUES
entry_type: homicide | accident | death in custody | suicide | cause undetermined | no death recorded
manner_of_death: natural | accident | assault | suicide | undetermined | none
victim_gender: male | female | NOT STATED
victim_status: gentleman/woman | craftsman/woman | servant/laborer | apprentice | prisoner | destitute | cleric/religious | NOT STATED
weapon: bare hands | knife/dagger | club/staff | axe | sword | bow and arrow | stone or thrown object | other | no weapon
perpetrator_outcome: captured | surrendered | abjured the realm | took sanctuary then escaped | fled, never taken | jury found no felony | perpetrator died | outlawed | NOT STATED | no perpetrator
within_without: within | without | NOT STATED | not applicable
RULES
1. coder_id and roll are the same in every row: the two values given at the top. coder_id names who or what did the coding — student, gemini, claude, amplify.
2. entry_type says what kind of RECORD this is. manner_of_death says how the person died. They are not the same question: an entry can be "no death recorded", and then manner_of_death is "none".
3. "lay dead of a death OTHER THAN his rightful death" means the death was NOT natural: choose accident, assault, suicide or undetermined from what the jurors go on to say. "died ... his rightful death" (for example, "died in Neugate his rightful death") means natural. The two phrases differ by a few words and mean opposite things; read them carefully before coding manner_of_death.
4. Take the ward from the SENTENCE that names it, never from the marginal note. Put the raw spelling in ward_verbatim, modernized in ward. within_without applies only to Farringdon, Cripplegate and Aldgate: if that same sentence says Within or Without ("in the Ward of Farndone Without"), write within or without, and keep it out of ward (ward is Farringdon). If it names one of those three wards without saying which, write NOT STATED. For any other ward, or a place that is not a ward, write not applicable. Ignore "within" and "without" anywhere else: in a parish name ("St. Botolph without Aldresgate"), in the list of nearest wards, or in phrases such as "within the tenement of".
5. inquest_date is the date at the head of the entry. That is when the body was viewed, NOT necessarily when the person died. Write it as M/YYYY. Work the month out from the feast and the weekday, using the Julian calendar: "Thursday after the Feast of St. Michael [29 Sept.] ... [A.D. 1324]" is October 4, 1324, so 10/1324. Where Sharpe gives two years, as in [A.D. 1324-5], use the second.
6. date_verbatim: the date exactly as the entry gives it, feast day and regnal year included — for example "Thursday after the Feast of St. Michael [29 Sept.] a° 18 Edward II. [A.D. 1324]".
7. printed_page: the number printed at the top of the page. These are often mis-transcribed (lOI for 101, Ill for 111). If you cannot read it cleanly, write ILLEGIBLE rather than guessing.
8. The five _verbatim columns: copy the words as Sharpe printed them, keeping his spelling (ward_verbatim "Bredstret", not "Breadstreet"). Do not tidy, modernize or correct. If you cannot make out what is printed, write ILLEGIBLE (rule 9); do not copy garbled characters.
9. Any value you cannot read, write exactly: ILLEGIBLE. Any value the entry does not state, write exactly: NOT STATED. Apart from working out the month in rule 5, never infer, never fill a gap from context, never guess a name.
10. evidence_quote: 5 to 15 words from the entry supporting manner_of_death.
OUTPUT
Write the result to a CSV file I can download. Quote every field.
Filename: roll_{{ROLL_LETTER}}_{{CODER_ID}}.csv
If you cannot create a file, say so in one sentence before anything else, then print the rows in the chat as CSV inside a single code block, every field quoted, no commentary between rows. Do not give me a formatted table instead of a file without telling me.
Then, in the chat and not in the file, tell me:
- how many rows you produced
- which case_numbers you could not read
- which fields you most often had to mark ILLEGIBLE
Read rules 3 and 9 twice. Rule 3 is the trap you have already met by hand. Rule 9 is what makes the output checkable: a model that quietly fills gaps gives you a clean-looking CSV with no sign of where it guessed, and a model that marks ILLEGIBLE shows you some of the places to look.
Do not skip the three questions at the end. Compare the row count it reports with the rows you actually received and with the entry numbers in the PDF. The ILLEGIBLE summary shows where the tool says it could not read — not everywhere it misread.
Check these four things before you look at any row
ILLEGIBLE. If none do, be suspicious, not pleased.The last check is counter-intuitive enough to be worth stating twice. No ILLEGIBLE anywhere does not mean everything was read. In a test run on Roll D, a model marked nothing ILLEGIBLE and still misspelled names, misdated an inquest and recorded a killer as the victim.
Ask for a file. If none comes, copy with your eyes open.
The ready-made prompt asks for a downloadable CSV. Amplify cannot make one. Send the prompt anyway and read what comes back instead: how a tool behaves when it cannot do what you asked is part of what you are measuring.
Four ways rows go wrong between the model and your spreadsheet
04 becomes 4) and can turn text such as JAN-1 into a date.| — pastes into a single column, pipes and all, with the |---| line as a row of its own.Either route: check the row count, the first row, the last row, and every name against the page.
Be precise about the cause, because it changes what you should trust. The comma and raw-text problems start in the model's output — a field left without quotes, or a table instead of CSV — and show up when the text is pasted or opened. The Excel problem happens after the model has finished. The fourth is in the model's own output, and so is other damage: in a test run, a model printing CSV left fields out of 23 of its 45 rows. A downloaded file avoids the copying problems and a code block avoids most of them; neither stops a spreadsheet from reformatting values when it opens the file.
The Excel one deserves a second look, because it leaves no visible trace: a reformatted value looks like any other value, and only comparing against the page will catch it. Your inquest_date values are not at risk in Excel, which keeps dates before 1900 as text.
Write down what your tool actually did with the file instruction. Did it tell you it could not make one, or did it quietly hand you a table as though that were what you asked for? Substituting one format for another without saying so is the same habit as filling in a ward name you could not read. You will meet it again on slide 16 as a quiet error, and it is worth writing down while you are there.
Side by side, field by field, by case number
case_number. Do not sort by anything else.Comparing down a column rather than across a row is a small change with a large effect. It keeps one kind of judgment in mind at a time, so patterns appear. In a test run on Roll D, for example, a model coded six of the eight "died … his rightful death" entries as no death at all. A pattern like that is hard to see when you read across a row and meet twenty-one unrelated fields at once.
"Do not fix anything yet" matters because the disagreement rate is itself your result. If you silently correct as you go, you have destroyed your own measurement.
The point of the notes is that you see for yourself how often the machine is wrong, and where. Keep them in whatever form you will actually use while the two files are open in front of you.
Label every disagreement as one of these
| Label | What it looks like |
|---|---|
| Loud | The output is visibly broken — ^^''^^^, Crupiil^^aie, a number where a name should be. |
| Quiet | Fluent, plausible, and wrong. A real ward name in the right slot — just not the one on the page. |
| Rule gap | You and the machine are both defensible. The codebook did not say. |
| You | You were wrong. |
Most of your time goes on quiet, because it is the category you will find nothing in unless you go hunting. Loud errors announce themselves. Quiet ones look exactly like correct answers, and the only way to find them is to have the page open next to the row.
Here is the shape of one. The page says St. Mary atte Naxe, and Sharpe's own footnote identifies it as St. Mary Axe. A model that writes St Mary Axe in a _verbatim column has the right place and the wrong text: fluent, plausible, and not what the page says.
A high count of rule gaps is a good outcome, not a messy one. Those are the amendments that improve the codebook for everyone.
Your CSV, not the machine's
The figure is built on your verified rows, not the machine's raw output. Otherwise you end up charting the machine's errors.
Name the column. Ask for the table. Say n.
Before you send: replace each [ ] with the number of rows in your CSV — that number is n — and replace [ROLL LETTER] with your roll if you did not pick it on slide 12.
The attached CSV is my own hand-verified coding of Roll {{ROLL_LETTER}} of the London coroners' rolls, [ ] rows.
Count the values in the column `manner_of_death` and show me the counts as a plain table. Do not chart anything yet.
Tell me if any rows were excluded from that count and why.
Make a single horizontal bar chart of those counts, with:
- categories sorted from most to least frequent
- the count printed at the end of each bar
- the title: "Manner of death, Roll {{ROLL_LETTER}} (n = [ ])"
- no 3D, no gradient, no drop shadow, no pie chart
- one color for all bars, since the categories are not ranked
Send them one at a time and read each answer before the next. The order is the whole point: counts first, picture last. A chart is a claim about numbers, and once it is a picture the numbers are hard to check. Asking for the table first makes the claim inspectable while it is still text — and sending the third message is how you confirm the counts, so check them against your own before you do.
The second message catches a real failure. Tools can drop blank cells and rows they cannot parse without saying so, so a chart of 34 rows from a 39-row file is a different finding from the one you think you are reporting.
Swap manner_of_death for whichever column suits your question — weapon, perpetrator_outcome, ward — and change the chart title to match. Same structure every time.
Route A depends on your tool. Route B works with any.
.docx. Gemini makes the file. Amplify's documentation lists Word document creation and a download-as-Word option on each message — check the message for it.The chart: save it as an image (a screenshot works if there is no download option), then insert it — in Google Docs, Insert → Image → Upload from computer; in Word, Insert → Pictures. Caption it with the field, the roll and the n.
Route B lets you see and fix the document before it becomes a file. With Route A, open the .docx and check that the chart and its caption made it in.
One rule on captions, and it is a research habit rather than a formatting rule: the caption must name the field, the roll and the n. A figure that does not say what it counted, or how many, cannot be checked by anyone who reads it.
| Symptom | Likely cause | What to try |
|---|---|---|
| The upload is rejected or stalls | The file is larger than the tool accepts, or several files went at once | One roll, one file. Split the PDF first, or use the pre-split rolls. |
| It summarizes instead of coding | Chat happened before the prompt, or the prompt was trimmed | New conversation, re-upload, run the diagnostic, then paste the whole prompt with nothing else in between. |
| Some rows have the wrong number of fields | A column name was edited, or the model left a field out of some rows | Find the short rows (start with the first and last row). Ask the tool to reprint them, or start again with the unedited prompt. Do not repair the file by hand. |
| Names look subtly wrong | The model misread or "corrected" them — a quiet error | Check against the page and note it as a disagreement. |
| The chart's total does not match the file | Blank or unparsed rows dropped silently | Ask what was excluded and why, then re-run the count. |
Common problems and what to try first. Keep this tab open while you work.
Still stuck? Email Tae Hyun Lim at tlim@hamilton.edu, or ask a Data Science Tutor at the Burke Library Research and Production Desk.
ROLL_LETTER and CODER_ID and change nothing else.If you only remember one thing. The text layer is often wrong exactly where several coded fields live — the margins, the footnotes, the numerals, the money — and a model's answer does not tell you when it is working from those places. Your job is not to trust it or to refuse it. Your job is to know where it is weak and go look there.