clinical_trials_citation_generator
Graphical tool designed for batch citing clinical trial records from ClinicalTrials.gov using NCT numbers. It retrieves trial metadata via the ClinicalTrials.gov REST API and generates citations in BibTeX and RIS formats, making it easy to import references into citation managers like Zotero.
https://github.com/drew-hirsch/clinical_trials_citation_generator
Science Score: 31.0%
This score indicates how likely this project is to be science-related based on various indicators:
-
✓CITATION.cff file
Found CITATION.cff file -
✓codemeta.json file
Found codemeta.json file -
○.zenodo.json file
-
○DOI references
-
○Academic publication links
-
○Academic email domains
-
○Institutional organization owner
-
○JOSS paper metadata
-
○Scientific vocabulary similarity
Low similarity (11.5%) to scientific vocabulary
Repository
Graphical tool designed for batch citing clinical trial records from ClinicalTrials.gov using NCT numbers. It retrieves trial metadata via the ClinicalTrials.gov REST API and generates citations in BibTeX and RIS formats, making it easy to import references into citation managers like Zotero.
Basic Info
Statistics
- Stars: 0
- Watchers: 1
- Forks: 0
- Open Issues: 0
- Releases: 0
Metadata Files
README.md
ClinicalTrials.gov BibTeX and RIS Citation Generator
This repository contains a graphical tool for batch citing clinical trial records from ClinicalTrials.gov using NCT numbers. The tool fetches metadata via the ClinicalTrials.gov REST API and outputs citations in BibTeX and RIS formats for easy import into citation managers (i.e. Zotero).

Features
- Uses the ClinicalTrials.gov REST API to retrieve trial data
- Graphical User Interface (GUI) (No terminal required)
- Supports CSV and TXT files containing NCT numbers
- Outputs formatted citations in BibTeX (
citations.bib) and RIS (citations.ris) - Displays real-time progress updates
Prepare Your Input File
Create a TXT or CSV file listing all ClinicalTrials.gov NCT identifier numbers (e.g., NCT12345678). Each NCT number should be on a separate line or in separate cells.
How to Use
Using the Mac Application
A macOS application ClinicalTrialCiter.app is available for ease of use.
- Open ClinicalTrialCiter.app
- Click "Select CSV/TXT File" and choose a .CSV or .TXT file with NCT numbers inside.
- The tool extracts valid NCT numbers and fetches trial data using the ClinicalTrials.gov REST API.
- Citations are saved as citations.bib and citations.ris in the same directory.
Using the Python Script
If you prefer running the script manually, use the following command in terminal or command prompt:
bash
python citations.py
- Or type "python", then drag and drop the citations.py into the terminal window.
- Click "Select CSV/TXT File" and choose a file with NCT numbers.
- The tool extracts valid NCT numbers and fetches trial data using the ClinicalTrials.gov REST API.
- Citations are saved as citations.bib and citations.ris.
Citation Format
Note: The format and fields in RIS and BibTeX files do not always perfectly match all citation styles. Depending on the chosen style and author preferences, generated citations may not contain all necessary information.
BibTeX Example:
bibtex
@article{NCT04052568,
title = {Effects of Psilocybin in Anorexia Nervosa. ClinicalTrials.gov Identifier: NCT04052568},
year = {2023},
note = {Updated 2023-05-06. Retrieved 2025-03-02.},
url = {https://clinicaltrials.gov/ct2/show/NCT04052568}
}
RIS Example:
ris
TY - JOUR
TI - Effects of Psilocybin in Anorexia Nervosa. ClinicalTrials.gov Identifier: NCT04052568
DA - 2023/05/06
UR - https://clinicaltrials.gov/ct2/show/NCT04052568
PY - 2023
RD - 2025/03/02
ER -
Notes
- Make sure your input file contains valid NCT numbers (e.g.,
NCT12345678). - Ensure an internet connection to fetch data via the ClinicalTrials.gov REST API.
Owner
- Name: Drew Hirsch
- Login: drew-hirsch
- Kind: user
- Company: UCLA / CSMC
- Repositories: 1
- Profile: https://github.com/drew-hirsch
Citation (citations.py)
import requests
import re
import time
import json
import tkinter as tk
from tkinter import filedialog, messagebox, scrolledtext
from datetime import datetime
API_URL = "https://clinicaltrials.gov/api/v2/studies/"
def fetch_trial_data(nct_number):
"""Fetches clinical trial metadata from ClinicalTrials.gov API."""
url = f"{API_URL}{nct_number}?format=json"
response = requests.get(url, headers={"Accept": "application/json"})
if response.status_code != 200:
return None
data = response.json()
try:
protocol_section = data.get("protocolSection", {})
id_module = protocol_section.get("identificationModule", {})
status_module = protocol_section.get("statusModule", {})
title = id_module.get("briefTitle", "Unknown Title")
last_update_date = status_module.get("lastUpdatePostDateStruct", {}).get("date", "Unknown Date")
return {
"nct": nct_number,
"title": f"{title}. ClinicalTrials.gov Identifier: {nct_number}",
"last_update": last_update_date,
"url": f"https://clinicaltrials.gov/ct2/show/{nct_number}"
}
except Exception:
return None
def format_bibtex_entry(trial_data):
"""Generates a BibTeX entry for a clinical trial."""
retrieved_date = datetime.today().strftime("%Y-%m-%d")
try:
update_datetime = datetime.strptime(trial_data['last_update'], "%Y-%m-%d")
year = update_datetime.year
month = update_datetime.strftime("%B")
day = update_datetime.day
except ValueError:
year, month, day = "Unknown", "Unknown", "Unknown"
return f"""@article{{{trial_data['nct']},
title = {{{trial_data['title']}}},
year = {{{year}}},
month = {{{month}}},
day = {{{day}}},
note = {{Retrieved on {retrieved_date}}},
url = {{{trial_data['url']}}}
}}
"""
def format_ris_entry(trial_data):
"""Generates an RIS entry for a clinical trial."""
retrieved_date = datetime.today().strftime("%Y-%m-%d")
try:
update_datetime = datetime.strptime(trial_data['last_update'], "%Y-%m-%d")
update_date_formatted = update_datetime.strftime("%Y/%m/%d")
except ValueError:
update_date_formatted = "Unknown"
return f"""TY - JOUR
TI - {trial_data['title']}
DA - {update_date_formatted}
UR - {trial_data['url']}
PY - {update_date_formatted.split('/')[0]}
RD - {retrieved_date}
ER -
"""
def extract_nct_numbers(filepath):
"""Extracts all NCT numbers from a given CSV or TXT file."""
nct_numbers = set()
try:
with open(filepath, "r", encoding="utf-8") as file:
for line in file:
matches = re.findall(r"NCT\d{8}", line, re.IGNORECASE)
nct_numbers.update(matches)
except Exception as e:
messagebox.showerror("Error", f"Could not read file: {e}")
return []
return list(nct_numbers)
def process_trials():
"""Handles file selection, data fetching, and exporting citations."""
file_path = filedialog.askopenfilename(
title="Select a CSV or TXT file containing NCT numbers",
filetypes=[("CSV files", "*.csv"), ("Text files", "*.txt"), ("All files", "*.*")]
)
if not file_path:
return
progress_text.insert(tk.END, f"📄 Processing file: {file_path}\n")
root.update()
nct_list = extract_nct_numbers(file_path)
if not nct_list:
progress_text.insert(tk.END, "❌ No valid NCT numbers found.\n")
return
output_bib = "citations.bib"
output_ris = "citations.ris"
bib_entries = []
ris_entries = []
progress_text.insert(tk.END, f"🔎 Found {len(nct_list)} NCT numbers. Fetching data...\n")
root.update()
for i, nct in enumerate(nct_list, 1):
progress_text.insert(tk.END, f"📡 [{i}/{len(nct_list)}] Fetching {nct}...\n")
root.update()
trial = fetch_trial_data(nct)
if trial:
bib_entries.append(format_bibtex_entry(trial))
ris_entries.append(format_ris_entry(trial))
progress_text.insert(tk.END, "✅ Success\n")
else:
progress_text.insert(tk.END, "❌ Failed\n")
time.sleep(0.5)
if bib_entries:
with open(output_bib, "w", encoding="utf-8") as f:
f.writelines(bib_entries)
if ris_entries:
with open(output_ris, "w", encoding="utf-8") as f:
f.writelines(ris_entries)
progress_text.insert(tk.END, "\n🎉 Done! Citations saved.\n")
messagebox.showinfo("Success", "Citations saved as 'citations.bib' and 'citations.ris'.")
root.update()
# Create GUI Window
root = tk.Tk()
root.title("ClinicalTrials.gov Citation Generator")
root.geometry("500x400")
# Title Label
title_label = tk.Label(root, text="Generate BibTeX and RIS Citations from ClinicalTrials.gov NCT Identifiers", font=("Arial", 14, "bold"))
title_label.pack(pady=10)
# Select File Button
select_button = tk.Button(root, text="Select CSV or TXT File", command=process_trials, font=("Arial", 12))
select_button.pack(pady=5)
# Progress Display
progress_text = scrolledtext.ScrolledText(root, height=15, width=60)
progress_text.pack(pady=10)
# Run the application
root.mainloop()
GitHub Events
Total
- Push event: 17
- Create event: 2
Last Year
- Push event: 17
- Create event: 2