
Create ADAE in R with admiral: the Adverse-Events Analysis Dataset
Derive a CDISC-conformant ADAE — the OCCDS occurrence structure, the treatment-emergent flag TRTEMFL, and occurrence flags — from SDTM with admiral, then summarize adverse events by treatment arm and system organ class
A complete, runnable tutorial for ADAE, the adverse-events analysis dataset. Learn the ADaM OCCDS occurrence structure (one row per adverse-event record, not one per subject), derive a conformant ADAE in R from a pre-built ADSL and the SDTM AE domain with admiral: merge treatment variables with derive_vars_merged(), impute analysis dates with derive_vars_dt(), build the treatment-emergent flag TRTEMFL with derive_var_trtemfl(), add on-treatment and first-occurrence flags, and produce a basic adverse-event summary by treatment arm and system organ class — on public pharmaverse data, so every line runs.
- ADAE is the dataset behind every adverse-event table. It holds one row per adverse-event record — the OCCDS occurrence structure — so a subject who reports three events has three rows, unlike ADSL’s one-row-per-subject backbone.
- You build it from SDTM AE plus ADSL. The raw AE domain supplies the events; ADSL supplies treatment dates and analysis variables, merged onto every AE record with
derive_vars_merged(). TRTEMFLis the variable that matters most. The treatment-emergent flag marks the AEs that started on or after first dose — the ones safety tables actually count.derive_var_trtemfl()derives it from the analysis date and the treatment window.- Occurrence flags pick one row to count.
derive_var_extreme_flag()flags the first treatment-emergent event per subject (AOCCFL) and per system organ class (AOCCSFL), so a “subjects with ≥1 AE” table counts each subject once. - The system organ class and preferred term are already coded. ADAE reads
AEBODSYS(SOC) andAEDECOD(preferred term) straight from the SDTM AE domain — no MedDRA dictionary lookup is needed to summarize events by body system.
Introduction
Every safety read-out in a clinical study report — which adverse events occurred, in whom, how often, and on which arm — is computed from one analysis dataset: ADAE, the adverse-events ADaM (Analysis Data Model) dataset. Before a single AE summary table or treatment-emergent listing can be produced, someone has to turn the raw, messy AE domain into an analysis-ready ADAE: real analysis dates, a treatment-emergent flag, occurrence flags, and the treatment variables every table splits by.
ADAE is the first dataset where the occurrence structure shows up: unlike ADSL, which carries exactly one row per subject, ADAE carries one row per adverse-event record. That single structural difference drives everything — how you flag treatment emergence, how you count “subjects with an event” without double-counting, and how you summarize by body system. This lesson builds a conformant ADAE in R with admiral, the pharmaverse package for ADaM derivation, working on public pharmaverse example data so every line runs as written. The build follows admiral’s official OCCDS / ADAE vignette, re-authored into a single guided walkthrough.
Here is where we are headed — treatment-emergent adverse events by system organ class and arm, computed straight from the ADAE we derive:
That figure reads off three ADAE columns — AEBODSYS, TRT01A, and TRTEMFL — plus one row per event. By the end of this lesson you will have derived the flags it depends on. If “ADaM”, “OCCDS”, or “SDTM” are new, start with the CDISC standards, which maps where ADAE sits; this lesson assumes you have a built ADSL, the subject-level backbone the ADSL lesson produces.
What ADAE is
ADAE is built on the OCCDS structure — the ADaM Structure for Occurrence Data defined by CDISC for events that occur rather than being measured: adverse events (ADAE), concomitant medications (ADCM), medical history (ADMH). Its defining rule is the one that catches people moving over from ADSL:
- ADSL is one row per subject.
- OCCDS / ADAE is one row per record — one row per adverse event. A subject with five adverse events has five rows.
- BDS (the structure of ADTTE, ADLB, ADVS) is one row per subject per parameter per analysis timepoint, keyed by
PARAMCD.
That structural choice is why ADAE needs flags rather than a single value per subject: with many rows per subject, you flag the rows that count (treatment-emergent, on-treatment) and the row to count once (first occurrence), instead of collapsing to one number.
The columns fall into a few groups. These are the load-bearing ones this lesson derives or carries:
| Group | Variables | What they hold |
|---|---|---|
| Subject & treatment (from ADSL) | STUDYID, USUBJID, TRT01A, TRTA, TRTSDT, TRTEDT |
Subject keys plus the treatment variables and dates merged from ADSL. |
| The event (from SDTM AE) | AETERM, AEDECOD, AEBODSYS, AESEV, AESER, AESEQ |
Reported term, the coded preferred term (AEDECOD) and system organ class (AEBODSYS), severity, seriousness. |
| Analysis dates | ASTDT, AENDT, ASTDY, AENDY, ADURN, ADURU |
The AE start/end as real analysis dates, the study day relative to first dose, and the event duration. |
| Timing flags | TRTEMFL, ONTRTFL |
"Y"/NA flags marking treatment-emergent and on-treatment events. |
| Occurrence flags | AOCCFL, AOCCSFL |
"Y"/NA flags marking the first treatment-emergent event per subject and per system organ class. |
| Analysis values | ASEV, AREL |
Analysis copies of severity and relationship, kept distinct from the SDTM source so SDTM stays untouched. |
Two conventions are worth fixing up front:
AEDECODandAEBODSYSarrive already coded. In the SDTM AE domain the preferred term (AEDECOD) and system organ class (AEBODSYS) are populated by the study’s MedDRA (Medical Dictionary for Regulatory Activities) coding step before ADaM. ADAE reads them as ordinary columns — so you can summarize by body system without a dictionary on hand, and this lesson ships no licensed MedDRA terminology.- A flag is
"Y"or missing, not"Y"/"N". ADaM occurrence and timing flags are populated"Y"for the records that qualify and leftNAotherwise (the OCCDS convention), so downstream code filters withTRTEMFL == "Y"and a count of"Y"is the count that matters.
The trial we use is the CDISC pilot study shipped in pharmaversesdtm and pharmaverseadam — a synthetic, license-free parallel-arm study comparing placebo against two doses of Xanomeline, delivered as a transdermal patch.
The source data
admiral builds ADAE from two inputs: the raw AE domain (the events) and a pre-built ADSL (the subject-level treatment and date backbone). We take ADSL ready-made from pharmaverseadam so this lesson stays focused on the AE side; the ADSL lesson shows how that backbone is built.
library(admiral)
library(dplyr, warn.conflicts = FALSE)
library(pharmaversesdtm)
library(pharmaverseadam)
library(lubridate)
library(stringr)
# ADSL — one row per subject, the treatment + date backbone
adsl <- pharmaverseadam::adsl
# AE — the raw adverse-event domain, one row per reported event.
# convert_blanks_to_na() turns SDTM's empty strings "" into proper NA.
ae <- pharmaversesdtm::ae %>% convert_blanks_to_na()
ae %>%
select(USUBJID, AETERM, AEDECOD, AEBODSYS, AESEV, AESTDTC) %>%
head(5)# A tibble: 5 × 6
USUBJID AETERM AEDECOD AEBODSYS AESEV AESTDTC
<chr> <chr> <chr> <chr> <chr> <chr>
1 01-701-1015 APPLICATION SITE ERYTHEMA APPLIC… GENERAL… MILD 2014-0…
2 01-701-1015 APPLICATION SITE PRURITUS APPLIC… GENERAL… MILD 2014-0…
3 01-701-1015 DIARRHOEA DIARRH… GASTROI… MILD 2014-0…
4 01-701-1023 ATRIOVENTRICULAR BLOCK SECOND DEGR… ATRIOV… CARDIAC… MILD 2012-0…
5 01-701-1023 ERYTHEMA ERYTHE… SKIN AN… MILD 2012-0…
Each AE row is one reported event: a verbatim AETERM, its coded AEDECOD/AEBODSYS, a severity, and a character start date AESTDTC (an ISO string that may be partial). convert_blanks_to_na() is the essential first step — SDTM uses empty strings for missing values, and admiral’s date and merge functions expect a real NA.
Merge the ADSL treatment variables onto each AE
ADAE needs each subject’s treatment dates and treatment arm on every one of their AE rows, because treatment emergence is defined relative to first dose. derive_vars_merged() copies the chosen ADSL variables onto each matching AE record by subject.
adsl_vars <- exprs(TRTSDT, TRTEDT, TRT01A, TRT01P, DTHDT, EOSDT, AGE, SEX, RACE)
adae <- ae %>%
derive_vars_merged(
dataset_add = adsl,
new_vars = adsl_vars,
by_vars = exprs(STUDYID, USUBJID)
)
adae %>%
select(USUBJID, AEDECOD, TRT01A, TRTSDT, TRTEDT) %>%
head(5)# A tibble: 5 × 5
USUBJID AEDECOD TRT01A TRTSDT TRTEDT
<chr> <chr> <chr> <date> <date>
1 01-701-1015 APPLICATION SITE ERYTHEMA Placebo 2014-01-02 2014-07-02
2 01-701-1015 APPLICATION SITE PRURITUS Placebo 2014-01-02 2014-07-02
3 01-701-1015 DIARRHOEA Placebo 2014-01-02 2014-07-02
4 01-701-1023 ATRIOVENTRICULAR BLOCK SECOND DEGREE Placebo 2012-08-05 2012-09-01
5 01-701-1023 ERYTHEMA Placebo 2012-08-05 2012-09-01
Because ADSL has one row per subject and AE has many, this is a one-to-many merge: the single ADSL record fans out onto all of a subject’s AE rows. TRTSDT (first dose) and TRTEDT (last dose) are the two dates that define the treatment window we need next.
Derive the analysis dates
The AE start and end arrive as character strings (AESTDTC, AEENDTC) that may be partial — a value like 2014-01 has no day. derive_vars_dt() imputes the missing parts and converts each to a real R date. derive_vars_dy() then computes the study day relative to first dose, and derive_vars_duration() the event’s length.
adae <- adae %>%
# AESTDTC -> ASTDT, imputing a missing day/month to the first; never before first dose
derive_vars_dt(
new_vars_prefix = "AST", dtc = AESTDTC,
highest_imputation = "M", min_dates = exprs(TRTSDT)
) %>%
# AEENDTC -> AENDT, imputing a missing day/month to the last; never after death / end of study
derive_vars_dt(
new_vars_prefix = "AEN", dtc = AEENDTC,
highest_imputation = "M", date_imputation = "last", max_dates = exprs(DTHDT, EOSDT)
) %>%
# ASTDY / AENDY: AE start/end as a study day relative to first dose (TRTSDT = day 1)
derive_vars_dy(reference_date = TRTSDT, source_vars = exprs(ASTDT, AENDT)) %>%
# ADURN / ADURU: how many days the event lasted, with its unit
derive_vars_duration(new_var = ADURN, new_var_unit = ADURU, start_date = ASTDT, end_date = AENDT)
adae %>%
select(USUBJID, AESTDTC, ASTDT, ASTDY, AENDT, ADURN, ADURU) %>%
head(5)# A tibble: 5 × 7
USUBJID AESTDTC ASTDT ASTDY AENDT ADURN ADURU
<chr> <chr> <date> <dbl> <date> <dbl> <chr>
1 01-701-1015 2014-01-03 2014-01-03 2 NA NA <NA>
2 01-701-1015 2014-01-03 2014-01-03 2 NA NA <NA>
3 01-701-1015 2014-01-09 2014-01-09 8 2014-01-11 3 DAYS
4 01-701-1023 2012-08-26 2012-08-26 22 NA NA <NA>
5 01-701-1023 2012-08-07 2012-08-07 3 2012-08-30 24 DAYS
Two imputation choices encode clinical rules. A start date imputes to the first of the period and is bounded below by TRTSDT (min_dates), so an AE recorded as 2014-01 for a subject dosed on 2014-01-15 is read as 2014-01-15, never before first dose. An end date imputes to the last of the period and is bounded above by death or end of study (max_dates), so it never runs past the point the subject left the study. ASTDY is the AE’s study day — day 1 is first dose — and ADURN is its duration in days. None of this is date arithmetic by hand.
Derive the treatment-emergent flag (TRTEMFL)
This is the variable ADAE exists for. A treatment-emergent adverse event (TEAE) is one that started on or after first dose (and, by convention, up to a window after last dose) — the events plausibly attributable to study drug, and the ones safety tables count. derive_var_trtemfl() compares each AE’s analysis dates against the treatment window and sets TRTEMFL to "Y" for the emergent ones.
adae <- adae %>%
derive_var_trtemfl(
start_date = ASTDT,
end_date = AENDT,
trt_start_date = TRTSDT,
trt_end_date = TRTEDT,
end_window = 30
)
adae %>%
select(USUBJID, ASTDT, TRTSDT, TRTEDT, TRTEMFL) %>%
head(5)# A tibble: 5 × 5
USUBJID ASTDT TRTSDT TRTEDT TRTEMFL
<chr> <date> <date> <date> <chr>
1 01-701-1015 2014-01-03 2014-01-02 2014-07-02 Y
2 01-701-1015 2014-01-03 2014-01-02 2014-07-02 Y
3 01-701-1015 2014-01-09 2014-01-02 2014-07-02 Y
4 01-701-1023 2012-08-26 2012-08-05 2012-09-01 Y
5 01-701-1023 2012-08-07 2012-08-05 2012-09-01 Y
adae %>% count(TRTEMFL)# A tibble: 2 × 2
TRTEMFL n
<chr> <int>
1 Y 1122
2 <NA> 69
end_window = 30 extends the treatment-emergent period to 30 days after last dose — a common choice so a late-onset event still counts as drug-related; your statistical analysis plan sets the exact window. Of the 1191 AE records, 1122 are treatment-emergent and 69 are not (they started before first dose — pre-treatment events that belong in a medical-history listing, not a TEAE table). From here on, TRTEMFL == "Y" is the filter for every safety summary.
Add the on-treatment and occurrence flags
Two more flags finish the analysis-ready ADAE. The on-treatment flag (ONTRTFL) marks events that fall strictly inside the treatment window — a stricter cut than treatment-emergent, used for on-treatment analyses. The occurrence flags solve the counting problem the OCCDS structure creates: with many rows per subject, which row do you count for a “subjects with ≥1 AE” table? derive_var_extreme_flag() flags the first qualifying record, and restrict_derivation() limits the flag to the treatment-emergent rows.
adae <- adae %>%
# ONTRTFL: events within the treatment window (first dose to last dose + 30 days)
derive_var_ontrtfl(
start_date = ASTDT,
ref_start_date = TRTSDT,
ref_end_date = TRTEDT,
ref_end_window = 30
) %>%
# AOCCFL: first treatment-emergent AE per subject (count each subject once overall)
restrict_derivation(
derivation = derive_var_extreme_flag,
args = params(
by_vars = exprs(USUBJID),
order = exprs(ASTDT, AESEQ),
new_var = AOCCFL,
mode = "first"
),
filter = TRTEMFL == "Y"
) %>%
# AOCCSFL: first treatment-emergent AE per subject within each system organ class
restrict_derivation(
derivation = derive_var_extreme_flag,
args = params(
by_vars = exprs(USUBJID, AEBODSYS),
order = exprs(ASTDT, AESEQ),
new_var = AOCCSFL,
mode = "first"
),
filter = TRTEMFL == "Y"
)
adae %>% count(AOCCFL)# A tibble: 2 × 2
AOCCFL n
<chr> <int>
1 Y 217
2 <NA> 974
adae %>% count(AOCCSFL)# A tibble: 2 × 2
AOCCSFL n
<chr> <int>
1 Y 549
2 <NA> 642
AOCCFL == "Y" on 217 rows means 217 subjects had at least one treatment-emergent AE — flag the first event per subject, count the flag, and each subject is counted exactly once. AOCCSFL does the same within each AEBODSYS, so a “subjects affected, by system organ class” table reads off AOCCSFL == "Y" without double-counting a subject who had three events in the same class. The restrict_derivation() wrapper is what keeps the flags on treatment-emergent rows only — flagging a pre-treatment event as a subject’s “first occurrence” would be wrong.
Summarize the adverse events
With the flags in place, the standard safety summaries are short filters and counts. Start with the overall extent of exposure to AEs — how many subjects on each arm had at least one treatment-emergent event — using the per-subject occurrence flag.
teae <- adae %>% filter(TRTEMFL == "Y", TRT01A != "Screen Failure")
# subjects with >=1 TEAE per arm (AOCCFL counts each subject once)
teae %>%
filter(AOCCFL == "Y") %>%
count(TRT01A, name = "subjects_with_teae")# A tibble: 3 × 2
TRT01A subjects_with_teae
<chr> <int>
1 Placebo 65
2 Xanomeline High Dose 68
3 Xanomeline Low Dose 84
Sixty-five placebo subjects had a treatment-emergent AE, against 68 and 84 on the two Xanomeline arms — the active arms affect more subjects, as expected for an active drug. Next, the most frequent system organ classes, counting subjects once per class with AOCCSFL:
teae %>%
filter(AOCCSFL == "Y") %>%
count(AEBODSYS, sort = TRUE, name = "n_subjects") %>%
head(8)# A tibble: 8 × 2
AEBODSYS n_subjects
<chr> <int>
1 GENERAL DISORDERS AND ADMINISTRATION SITE CONDITIONS 108
2 SKIN AND SUBCUTANEOUS TISSUE DISORDERS 98
3 NERVOUS SYSTEM DISORDERS 53
4 GASTROINTESTINAL DISORDERS 51
5 CARDIAC DISORDERS 40
6 INFECTIONS AND INFESTATIONS 38
7 PSYCHIATRIC DISORDERS 28
8 RESPIRATORY, THORACIC AND MEDIASTINAL DISORDERS 27
And the most frequent preferred terms, counting events (every TEAE row, not just first occurrences):
teae %>%
count(AEDECOD, sort = TRUE, name = "n_events") %>%
head(8)# A tibble: 8 × 2
AEDECOD n_events
<chr> <int>
1 PRURITUS 78
2 APPLICATION SITE PRURITUS 77
3 ERYTHEMA 56
4 APPLICATION SITE ERYTHEMA 46
5 APPLICATION SITE IRRITATION 41
6 RASH 40
7 APPLICATION SITE DERMATITIS 36
8 DIZZINESS 31
The picture is coherent and clinically obvious: general disorders and administration-site conditions and skin and subcutaneous tissue disorders dominate, and the top preferred terms are pruritus and application-site pruritus/erythema. Xanomeline in this study is a transdermal patch, so skin and application-site reactions are exactly the expected safety signal — and the derived ADAE surfaces it directly. That is the whole point of the dataset: once the flags are right, the adverse-event story falls out of a few count() calls.
Ask Prova “how do I add a maximum-severity flag to my ADAE so I can build an AE table by worst severity grade per subject with admiral?” — it answers grounded in this pillar’s lessons, with runnable admiral code you can try on the example pharmaverse data. The runtime is the judge. Ask Prova →
Common issues
Your TEAE counts are too high — pre-treatment events are sneaking in. You filtered on the AE domain but not on TRTEMFL. An AE table must filter TRTEMFL == "Y"; without it, events that started before first dose (medical history captured as AEs) inflate every count. Derive the flag, then filter on it for every safety summary.
A “subjects with an AE” count is larger than the number of subjects. You counted AE rows, not subjects. Because ADAE has many rows per subject, count(TRT01A) on the raw rows counts events. To count subjects once, filter on the occurrence flag (AOCCFL == "Y" overall, AOCCSFL == "Y" per system organ class) — that is exactly what the occurrence flags are for.
derive_var_trtemfl() errors that ASTDTM/AENDTM are missing. Its defaults expect datetime variables. If you derived date variables with derive_vars_dt() (as here), pass them explicitly: start_date = ASTDT, end_date = AENDT. The datetime route (derive_vars_dtm() → ASTDTM/AENDTM) is the alternative when you need the time component.
Every comparison against an SDTM character variable behaves oddly. You skipped convert_blanks_to_na(). SDTM uses empty strings "" for missing values, so is.na() returns FALSE on them and date imputation chokes. Always run convert_blanks_to_na() on the AE domain first.
Frequently asked questions
ADAE is the adverse-events analysis dataset — the ADaM dataset behind every adverse-event summary, listing, and treatment-emergent table. It follows the OCCDS occurrence structure, which is one row per adverse-event record (a subject with three events has three rows), and it carries treatment variables merged from ADSL plus analysis dates and the flags — TRTEMFL, AOCCFL — that safety analyses filter on.
A treatment-emergent adverse event is one that started on or after the first dose of study drug (commonly extended to a window after the last dose). It separates events plausibly related to treatment from pre-existing conditions recorded before dosing. In ADAE it is marked by the TRTEMFL flag ("Y" for emergent events), which admiral derives with derive_var_trtemfl() by comparing each AE’s analysis date to the treatment window. Safety tables count treatment-emergent events only.
Start from the SDTM AE domain and a pre-built ADSL. Merge ADSL’s treatment dates onto each AE record with derive_vars_merged(), convert the partial AE dates to real dates with derive_vars_dt(), derive the treatment-emergent flag with derive_var_trtemfl(), add the on-treatment flag with derive_var_ontrtfl(), and flag first occurrences with derive_var_extreme_flag() inside restrict_derivation(). The full sequence is worked through above and follows admiral’s OCCDS vignette.
Because ADAE uses the OCCDS occurrence structure: one row per event, not per subject. A subject who reports five adverse events contributes five rows. This is the opposite of ADSL, which is one row per subject. To count subjects (for a “subjects with ≥1 AE” table) you flag the first qualifying event per subject with an occurrence flag (AOCCFL) and count the flag — counting raw rows would count events, not subjects.
No — not to build or summarize it from the pilot data here. The system organ class (AEBODSYS) and preferred term (AEDECOD) are coded in the SDTM AE domain during the study’s MedDRA coding step, before ADaM. ADAE reads them as ordinary columns, so you can summarize events by body system or preferred term with no dictionary. MedDRA (and the licensed terminology) matters when you perform the coding upstream of SDTM, which is outside ADAE derivation.
TRTEMFL flags treatment-emergent events — those that started on or after first dose, usually including a window after last dose, so a late-onset event still counts. ONTRTFL flags on-treatment events — those falling strictly inside the treatment window. On-treatment is the stricter cut: every on-treatment event is treatment-emergent, but a treatment-emergent event in the post-treatment follow-up window is not on-treatment. Which one an analysis uses depends on the statistical analysis plan.
Test your understanding
Using the adae object built in this lesson, count how many subjects had at least one serious treatment-emergent adverse event, by treatment arm. Serious AEs are flagged by AESER == "Y" in the data. Count each subject once per arm.
You need treatment-emergent and serious and each subject counted once. Filter TRTEMFL == "Y" and AESER == "Y", then count distinct subjects per arm — distinct(USUBJID, TRT01A) before count(TRT01A) collapses each subject to one row. (You cannot reuse AOCCFL here: it flags the first AE of any kind, which may not be a serious one.)
adae %>%
filter(TRTEMFL == "Y", AESER == "Y", TRT01A != "Screen Failure") %>%
distinct(USUBJID, TRT01A) %>%
count(TRT01A, name = "subjects_with_serious_teae")Serious AEs are far rarer than AEs overall, so expect small counts in each arm. The key idea is that AOCCFL will not help: it flags a subject’s first treatment-emergent event regardless of seriousness, so to count subjects with a serious event you must filter on AESER and then reduce to distinct subjects yourself. In a production ADAE you would derive a dedicated serious-occurrence flag (derive_var_extreme_flag() restricted to TRTEMFL == "Y" & AESER == "Y") so the table is a single flag-count.
A. One row per subject B. One row per subject per parameter C. One row per adverse-event record (OCCDS)
C. ADAE uses the OCCDS occurrence structure — one row per adverse-event record, so a subject with several events has several rows. A describes ADSL (the subject-level dataset) and B describes the Basic Data Structure (BDS) used by ADTTE and ADLB. The occurrence structure is the reason ADAE relies on flags (TRTEMFL, AOCCFL) to mark which rows to count.
Conclusion
ADAE turns a raw stack of adverse-event records into an analysis-ready dataset by answering three questions per row: when did the event happen (the analysis dates ASTDT/AENDT and study day ASTDY), does it count as treatment-emergent (TRTEMFL, and the stricter ONTRTFL), and is it the one to count once (the occurrence flags AOCCFL/AOCCSFL). admiral turns each into a declarative step — derive_vars_merged(), derive_vars_dt(), derive_var_trtemfl(), derive_var_extreme_flag() — that is readable and traceable back to the SDTM AE source. Get the flags right and every safety summary is a short filter() plus count(), with the system organ class and preferred term already coded in the data. ADAE is the dataset that makes the adverse-event tables of a clinical study report a few lines of code instead of a maze of date logic.
This lesson is reproducible: every result on this page was produced by the code shown — copy any block and run it to reproduce them. The runtime is the judge.
Reuse
Citation
@online{2026,
author = {},
title = {Create {ADAE} in {R} with Admiral: The {Adverse-Events}
{Analysis} {Dataset}},
date = {2026-06-30},
url = {https://www.datanovia.com/learn/pharma-clinical/03-adam-admiral/adae-adverse-events-admiral},
langid = {en}
}