Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 8 additions & 4 deletions data/compounds/retatrutide.json
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
{
"type": "compound",
"preferred_name": "Retatrutide",
Expand Down Expand Up @@ -489,7 +489,7 @@
}
},
{
"value": "Randomized controlled trial, humans, n=534, 2025: Percent reduction from baseline in total fat mass was 4路9% (SE 1路4%) with retatrutide 0路5 mg, 15路2% (3路2%) with retatrutide 4 mg (pooled), 26路1% (2路5%) with retatrutide 8 mg (pooled), 23路2% (3路0%) with retatrutide 12 mg, 2路6% (1路6%) with dulaglutide, and 4路5% (1路2%) with placebo.",
"value": "Randomized controlled trial, humans, n=281, 2025: Percent reduction from baseline in total fat mass was 4路9% (SE 1路4%) with retatrutide 0路5 mg, 15路2% (3路2%) with retatrutide 4 mg (pooled), 26路1% (2路5%) with retatrutide 8 mg (pooled), 23路2% (3路0%) with retatrutide 12 mg, 2路6% (1路6%) with dulaglutide, and 4路5% (1路2%) with placebo.",
"evidence_label": "human-clinical-trial",
"source_ids": [
"pmid-40609566"
Expand All @@ -500,7 +500,7 @@
"study": "Coskun 2025",
"year": "2025",
"design": "Randomized controlled trial",
"n": 534,
"n": 281,
"species": "Humans",
"dose": "0路5 mg; 4 mg",
"route": "subcutaneous",
Expand Down Expand Up @@ -649,7 +649,7 @@
}
},
{
"value": "Human study, humans, n=367, 2026: Background and hypothesis Retatrutide is an agonist of the glucose-dependent insulinotropic polypeptide, glucagon-like peptide-1 and glucagon receptors that reduced weight and hemoglobin A1c (HbA1c) in individuals with obesity and type 2 diabetes (T2D).",
"value": "Human study, humans, n=146, 2026: Background and hypothesis Retatrutide is an agonist of the glucose-dependent insulinotropic polypeptide, glucagon-like peptide-1 and glucagon receptors that reduced weight and hemoglobin A1c (HbA1c) in individuals with obesity and type 2 diabetes (T2D).",
"evidence_label": "observational-human",
"source_ids": [
"pmid-41160422"
Expand All @@ -660,7 +660,7 @@
"study": "Heerspink 2026",
"year": "2026",
"design": "Human study",
"n": 367,
"n": 146,
"species": "Humans",
"dose": "12 mg",
"route": "not stated in abstract",
Expand Down Expand Up @@ -1204,6 +1204,10 @@
{
"date": "2026-09-29",
"change": "Reviewed by Adam Mirando, PharmD, on 2026-09-29."
},
{
"date": "2026-09-29",
"change": "Corrected two more sample sizes that had stored the screening count: the body-composition substudy from 534 to 281 enrolled, and the cardiovascular trial from 367 screened to 146 randomised."
}
],
"guide": [
Expand Down
14 changes: 12 additions & 2 deletions scripts/draft_claims.py
Original file line number Diff line number Diff line change
Expand Up @@ -90,10 +90,14 @@
r"\b" + NUM + r"\s+(?:\([^)]{0,40}\)\s*)?(?:\w+\s+){0,3}?"
r"(?:were|was)\s+(?:randomly\s+assigned|randomi[sz]ed|allocated|enrolled)\b", re.IGNORECASE)
SCREENED_AFTER = re.compile(r"^[^.]{0,40}?\b(?:were|was)\s+screened\b", re.IGNORECASE)
# "randomized 1:1", "randomised 1:1:1:1:1" is an allocation ratio, not a count.
# The bare verb pattern reads it as a sample of 1, which is why it sits below
# the noun pattern and refuses a number followed by a colon.
RATIO_AFTER = re.compile(r"^\s*:")
N_RE = [
ASSIGNED,
re.compile(r"\b(?:enrolled|randomi[sz]ed|included|analy[sz]ed|recruited)\s+" + NUM + r"\b", re.IGNORECASE),
re.compile(r"\b" + NUM + r"\s+(?:patients|participants|subjects|volunteers|adults|individuals|people|men|women|children|infants|rats|mice|rabbits|dogs|pigs|animals)\b", re.IGNORECASE),
re.compile(r"\b(?:enrolled|randomi[sz]ed|included|analy[sz]ed|recruited)\s+" + NUM + r"\b", re.IGNORECASE),
re.compile(r"\b[nN]\s?=\s?" + NUM + r"\b"),
]
DESIGN_FROM_TITLE = [
Expand Down Expand Up @@ -227,9 +231,15 @@ def sample_size(abstract: str) -> int | None:
n = int(re.sub(r"[ ,\u00a0\u202f]", "", m.group(1)))
if not 1 <= n <= 2_000_000:
continue
# Both look at what follows the number itself, not the whole match:
# ASSIGNED ends after "randomly assigned", and the colon in
# "assigned: 134 to retatrutide 4 mg" is not an allocation ratio.
after = abstract[m.end(1):]
# "930 participants were screened and 537 were randomly assigned":
# the screening count is not the trial's size.
if rx is not ASSIGNED and SCREENED_AFTER.match(abstract[m.end():]):
if rx is not ASSIGNED and SCREENED_AFTER.match(after):
continue
if RATIO_AFTER.match(after):
continue
return n
return None
Expand Down
23 changes: 23 additions & 0 deletions scripts/test_drafter.py
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,29 @@ def test_screened_then_randomised_short_form(self):
def test_plain_enrolment_still_wins(self):
self.assertEqual(dc.sample_size("We enrolled 338 adults, 51.8% of whom were men."), 338)

def test_allocation_ratio_is_not_a_count(self):
# "randomized 1:1" put n=1 on kisspeptin, survodutide, semax, tesamorelin
# and thymosin-alpha-1 rows when the noun pattern lost precedence.
self.assertEqual(dc.sample_size(
"Of these, 194 patients have been randomized 1:1 to either Group A or Group B."), 194)
self.assertEqual(dc.sample_size(
"Totally 387 people (aged 18-75 years) were randomized 1:1:1:1:1 to once-weekly "
"subcutaneous survodutide or placebo."), 387)

def test_colon_after_assignment_is_not_a_ratio(self):
# The colon in "assigned: 134 to retatrutide 4 mg" introduces the arms,
# so it must not disqualify the number that precedes the verb.
self.assertEqual(dc.sample_size(
"930 participants were screened and 537 (296 [55%] female) were randomly assigned: "
"134 to retatrutide 4 mg, 133 to retatrutide 9 mg"), 537)

def test_screened_participants_phrasing(self):
self.assertEqual(dc.sample_size(
"Of 367 participants screened, 146 were randomized to study interventions."), 146)
self.assertEqual(dc.sample_size(
"534 participants were screened for inclusion into the main study; 253 were excluded "
"and 281 participants were enrolled and randomly assigned to the main study."), 281)

def test_enrolment_beats_subgroup_n(self):
text = "The renal impairment study included 33 participants (normal function, n = 14; mild impairment, n = 7)."
self.assertEqual(dc.sample_size(text), 33)
Expand Down
Loading