import os
import sys
import polars as pl
from pathlib import Path
sys.path.insert(0, 'src')
from rtflite import LibreOfficeConverter
try:
converter = LibreOfficeConverter()
except Exception:
converter = None
print("WARNING: LibreOffice not found. PDF conversion will be skipped.")
from csrlite import load_plan, study_plan_to_cm_listing
from csrlite.cm.cm_listing import cm_listing10 CM Listing
Objectives
This guide demonstrates Concomitant Medications (CM) listing showing detailed individual medication records.
10.1 Setup
10.2 Concomitant Medications Listing
Shows detailed individual concomitant medications with categories, terms, and dosing information.
10.3 StudyPlan-Driven Workflow
study_plan = load_plan("studies/xyz123/yaml/plan_xyz123.yaml")
study_plan.get_plan_df().filter(pl.col("analysis") == "cm_listing")2026-02-03 15:27:14,679 - csrlite.common.plan - INFO - Successfully loaded dataset 'adsl' from 'studies/xyz123/yaml/../../../data/adsl.parquet'
2026-02-03 15:27:14,682 - csrlite.common.plan - INFO - Successfully loaded dataset 'adae' from 'studies/xyz123/yaml/../../../data/adae.parquet'
2026-02-03 15:27:14,684 - csrlite.common.plan - INFO - Successfully loaded dataset 'adie' from 'studies/xyz123/yaml/../../../data/adie.parquet'
2026-02-03 15:27:14,685 - csrlite.common.plan - INFO - Successfully loaded dataset 'adpd' from 'studies/xyz123/yaml/../../../data/adpd.parquet'
shape: (0, 5)
| analysis | population | observation | parameter | group |
|---|---|---|---|---|
| str | str | str | str | str |
output_files = study_plan_to_cm_listing(study_plan)10.4 Complete Pipeline
# Load data
data_path = Path("data") if Path("data").exists() else Path("../data")
adsl = pl.read_parquet(data_path / "adsl.parquet")
adcm = pl.read_parquet(data_path / "adcm.parquet")
# Define output path
output_rtf = "studies/xyz123/rtf/cm_listing_manual.rtf"
# Ensure directory exists
Path(output_rtf).parent.mkdir(parents=True, exist_ok=True)
pd_listing_path = cm_listing(
population=adsl,
observation=adcm,
population_filter="SAFFL = 'Y'",
observation_filter="CONFL = 'Y'", # On-treatment/Concomitant
parameter_filter=None,
id=("USUBJID", "Subject ID"),
title=[
"Listing of Concomitant Medications",
"(Safety Population)"
],
footnote=["Medications are sorted by treatment and subject ID."],
source=["Source: ADSL and ADCM datasets"],
output_file=output_rtf,
population_columns=[
("TRT01A", "Treatment"),
("AGE", "Age"),
("SEX", "Sex")
],
observation_columns=[
("CMSEQ", "Sequence"),
("CMTRT", "Medication"),
("CMDECOD", "Standardized Name"),
("ASTDT", "Start Date"),
("AENDT", "End Date"),
("CMDOSE", "Dose"),
("CMDOSU", "Unit"),
("CMROUTE", "Route"),
("CMFREQ", "Frequency"),
("CMINDC", "Indication")
],
sort_columns=["TRT01A", "USUBJID", "ASTDT", "CMSEQ"],
group_by=["USUBJID"],
page_by=["TRT01A"],
)
print(f"Generated: {pd_listing_path}")studies/xyz123/rtf/cm_listing_manual.rtf
Generated: studies/xyz123/rtf/cm_listing_manual.rtf