[advanced session]
- scraping data
- building an interactive dashboard to visualize your data
- human-based verification
- running stats (Stata, R, Python...)
You do not need to write code.
Before we start
Your data for this part of the workshop:
- Opinion archive https://nathanReitinger.github.io/cda230-opinion-archive/
The shape of the session
| Step | Description |
|---|---|
| Collect the opinions | PDF collection |
| Visualize information | A dashboard living in your browser |
| Verify party names | A human-verified task |
| Analysis | Stata or Python or R or Claude itself |
Step 0 — Setup
Sample prompts
promptI can code. Give me Python (C, R, Ruby, Go...) files when you help me.
promptI have no idea what code is. I know almost nothing about computers. I can click buttons. Help me with this task, but keep that in mind.
promptI want you to keep detailed logs of everything you do. I want to inspect this information later so that I can make sure it was correct. >>>>>> this slows Claude down
promptAsk me questions when you are stuck or if you need a clarification. >>>>>> this slows Claude down
What does success look like?


Step 1 — Collect the opinions
Tips
- A sample command is all that is needed.
promptGet all PDFs from this website (https://nathanreitinger.github.io/cda230-opinion-archive) and put them in a folder called "data" that I can see. Double-check that you have everything. Keep logs.
Verify: What did you get?Mandatory
- what was on the website? (manual: how many files should there be?)
- is anything facially wrong with the files you downloaded? (manual: do they look the same as the ones on the website?)
- how many files did you get? (ask promptsummarize this information for me in chat: what did we get?)
What does success look like?

A note on scraping data
- check for robots.txt (rules for scrapers)
- Claude may try to slow a scrape down to prevent server overload; there are workarounds (Selenium), but most involve custom scraping code that you would need to build
- If you are heavily or routinely scraping a website, it might make sense to reach out to the website's owners and ask them about preferred procedures
- Many companies that provide access to valuable information (e.g., Westlaw or Lexis) heavily restrict scraping with technical blocks and contractual terms concerning text and data mining. When in doubt, check terms first
Tick “I'm done verifying” first.
Step 2 — Investigating the data
Tips
Think about what you want! What should you focus on? (Some of this may happen automatically.)
- How many cases
- Which plaintiffs
- Which defendants
- What years (histogram)
- Pages of text (per opinion, overall)
- Which courts are represented (specific court, level, circuits)
promptBuild me a single self-contained data dashboard based on the data folder. I need it to be local. I want:
- how many opinions, how many distinct cases
- a histogram of opinions by year
- the distribution of page counts
- the defendants and plaintiffs that appear in the dataset
Improvements: What could be better?
- more aggregate information
- a more interactive website
- a different color theme (fonts, front-facing quibbles)
- different stats (mean opinions per month)
- more interpretation of the information (summaries)
Verify: What did you get?Mandatory
- are the numbers correct?
- correct number of cases represented
- are the years right?
- manually verify by looking at the actual PDFs for comparison
- if applicable, check the page counts for one of the cases
What does success look like?

- Data dashboards like this one, and most websites built fully with LLMs, have certain tells signaling AI creation. That may be fine for your purposes, but it is something to be aware of.
Tick “I'm done verifying” first.
Step 3 — Explicit verification
Tips
A decision about the party name may be a computable task, if the data is found online in a machine-readable format. However, if the party name is pulled from a PDF, then it might have errors.
- This dataset is small, so we might be able to check all PDFs manually, but with larger datasets it might be better to check a random 10% and only keep the AI-assumed names if there is agreement between what you would decide and what the AI decided.
promptNow I want to check that the dashboard correctly logged party names. I want help confirming that the PDFs match what you decided.
I need some type of coding website, integrated into the dashboard, where I go through each of the labels you decided on for the names of the parties and match them with what is actually in the PDF.
I need this website to be persistent so that I can close it and come back to finish the job later.
-
In your own projects, make sure to double-check anything that is not computable, and if you don't know where that line is, ask:
- promptcheck all of your work; in particular, what decisions did you make in your response that were not directly computable or involved higher-level thinking?
-
If your project relies on an area that has this type of non-computable inference, check the work.
What does success look like?

Step 4 — Analysis
Tips
-
Do you have a statistical test in mind, or would you like to brainstorm ideas? If you do not pick something, Claude will make a guess (which might be wrong). Brainstorming (with Claude) before you run the test can be helpful.
-
Do you want to produce figures for a paper or just visualize the results?
promptI want to know if some companies show up more often as a defendant than other companies.
I want a Stata .do file to run this.
Make sure you visualize these results in the dashboard.
What does success look like?


Extra Step n — Bonus Level · HPC
Step n — Bonus Level
Tips
- Break the task up into parts and verify each part. The first part is whether you've downloaded all of the new data.
promptWe are adding in information about the plaintiffs and defendants. A new dataset is at https://nathanReitinger.github.io/harborline-registry/.
I want you to pull down that information, save it somewhere, and then match company names and create a new part of the dashboard that visualizes the results.
Do this in another tab of the existing dashboard.
Verify: Did you capture all of the data?Mandatory
- The second part is: what did you match on? If a defendant company has a different name than that found in the registry, how will Claude handle that?
Verify: How were the matches made? Was it exact or loose?Mandatory
- What exactly was the match requirement (exact or fuzzy)?
Improvements: What could be better?
- maybe you want a way to review matches and approve them yourself
- maybe you would like to resolve all discrepancies and then hide information on the dashboard about matching
- maybe you want to visualize information from the newly added dataset
What does success look like?

Tick “I'm done verifying” first.
HPC
What is it?
- high-performance computing (cluster of resources)
Why use it?
- space (large projects, think 1TB+)
- GPU (ML models)
- persistence (recovery, IT support, load balancing, work-while-you-sleep)
Do I have access to it?
- check the Law School Compute Index (also see below)
- you might, or you might have access to a pool of institutions that does
Caveat: this assessment of HPC resources is a guess. Confirm with your IT or research support.
Preview: Law School Compute Index
How to use it
- SSH (terminal commands to get onto the cluster)
- use Claude to help you get there!
Tips
- Use VS Code. It opens folders on the cluster as if they were on your laptop, with a terminal built in.
promptI want to use VS Code to work on my university's HPC cluster. Walk me through installing the Remote - SSH extension and connecting to the cluster, one step at a time. My username is [your NetID] and the cluster's login address is [the address from IT].
- Get credentials: email IT or research support and ask for an account on the cluster (and an allocation, if they use them). At Northwestern the cluster is Quest: request access at https://coldfront.it.northwestern.edu, or write to quest-help@northwestern.edu.
promptDraft a short email to my university's research computing support asking for an account on the HPC cluster, for a legal research project that needs a GPU.
Example: connect and ask for a GPU
This is Northwestern's cluster, Quest; yours will have its own address. Off campus, turn on the VPN first.
- Connect from the Terminal app, with your NetID in place of abc1234. Your password does not show as you type. Then approve the Duo push.
- Hand the job script (in the next drop-down) to the queue.
- Check on it until it is gone from the list: PD means waiting in line, R means running.
- Read the answer. A table naming a GPU, such as NVIDIA A100, means you got one.
$ ssh abc1234@login.quest.northwestern.edu [abc1234@quser31 ~]$ sbatch gpu_check.sh Submitted batch job 4839201 [abc1234@quser31 ~]$ squeue -u $USER JOBID PARTITION NAME USER ST TIME NODES NODELIST(REASON) 4839201 gengpu gpu_chec abc1234 R 0:04 1 qgpu2008 [abc1234@quser31 ~]$ cat gpu_check_4839201.out ========================================== Job ran on machine: qgpu2008 ========================================== --- Does this machine see a GPU? --- | NVIDIA-SMI 550.54.15 Driver Version: 550.54.15 CUDA Version: 12.4 | | 0 NVIDIA A100-SXM4-80GB On | 00000000:31:00.0 Off | 0 | | N/A 31C P0 61W / 400W | 1MiB / 81920MiB | 0% Default |
Example: a script that asks for a GPU
Save this on the cluster as gpu_check.sh, and change pXXXXX to your allocation.
#!/bin/bash # ============================================================ # A tiny job that just asks: "Do I have a GPU?" # Everything starting with #SBATCH is an instruction to Quest. # Everything starting with plain # is a note to you (ignored). # ============================================================ #SBATCH --account=pXXXXX # your allocation (looked up from Quest) #SBATCH --partition=gengpu # the general-access GPU machines #SBATCH --gres=gpu:1 # "give me 1 GPU" #SBATCH --nodes=1 # 1 computer #SBATCH --ntasks=1 # running 1 thing #SBATCH --cpus-per-task=1 # 1 CPU core alongside the GPU #SBATCH --mem=8G # 8 gigabytes of memory #SBATCH --time=00:05:00 # 5 minutes, max. Then Quest kills it. #SBATCH --job-name=gpu_check #SBATCH --output=gpu_check_%j.out # where the results get written (%j = job number) echo "==========================================" echo "Job ran on machine: $(hostname)" echo "Started at: $(date)" echo "==========================================" echo "" echo "--- Does this machine see a GPU? ---" nvidia-smi echo "" echo "--- Finished at: $(date) ---"
Example: the same check, as a Python program
This is the same check, written as a short Python program. Save it on your laptop as gpu_check.py, copy it to the cluster, ask for a GPU machine, and then run python3 gpu_check.py there.
# gpu_check.py: is there a GPU here? # Run it with: python3 gpu_check.py import shutil import socket import subprocess from datetime import datetime print("Machine:", socket.gethostname()) print("Started:", datetime.now()) if shutil.which("nvidia-smi") is None: print("No GPU here (no nvidia-smi).") else: gpu = subprocess.check_output( ["nvidia-smi", "--query-gpu=name,memory.total", "--format=csv,noheader"], universal_newlines=True) print("GPU:", gpu.strip()) print("Finished:", datetime.now())
# on your Mac: copy the program to Quest $ scp gpu_check.py \ abc1234@login.quest.northwestern.edu: $ ssh abc1234@login.quest.northwestern.edu # on Quest: ask for a GPU machine $ srun --account=pXXXXX --partition=gengpu \ --gres=gpu:1 --mem=8G --time=00:10:00 \ --pty bash # on the GPU machine: run the program $ python3 gpu_check.py Machine: qgpu2008 Started: 2026-10-01 10:42:07.311402 GPU: NVIDIA A100-SXM4-80GB, 81920 MiB Finished: 2026-10-01 10:42:08.026117 $ exit