csrlite 0.2.1__py3-none-any.whl → 0.3.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,109 @@
1
+ # pyre-strict
2
+ """
3
+ Inclusion/Exclusion (IE) Listing Analysis Functions
4
+ """
5
+
6
+ from pathlib import Path
7
+
8
+ import polars as pl
9
+
10
+ from ..common.parse import StudyPlanParser
11
+ from ..common.plan import StudyPlan
12
+ from ..common.rtf import create_rtf_listing
13
+ from ..common.utils import apply_common_filters
14
+
15
+
16
+ def study_plan_to_ie_listing(
17
+ study_plan: StudyPlan,
18
+ ) -> list[str]:
19
+ """
20
+ Generate IE Listing outputs.
21
+ """
22
+ # Meta data
23
+ analysis_type = "ie_listing"
24
+ output_dir = study_plan.output_dir
25
+ title = "Listing of Protocol Deviations"
26
+
27
+ # Ensure output directory exists
28
+ Path(output_dir).mkdir(parents=True, exist_ok=True)
29
+
30
+ # Initialize parser
31
+ parser = StudyPlanParser(study_plan)
32
+
33
+ # Get expanded plan (Manually expansion to avoid AttributeError)
34
+ plans = study_plan.study_data.get("plans", [])
35
+ all_specs = []
36
+ for plan_data in plans:
37
+ expanded = study_plan.expander.expand_plan(plan_data)
38
+ for p in expanded:
39
+ all_specs.append(study_plan.expander.create_analysis_spec(p))
40
+
41
+ plan_df = pl.DataFrame(all_specs)
42
+
43
+ if "analysis" in plan_df.columns:
44
+ listing_plans = plan_df.filter(pl.col("analysis") == analysis_type)
45
+ else:
46
+ listing_plans = pl.DataFrame()
47
+
48
+ generated_files = []
49
+
50
+ # If listing_plans is empty, create a dummy row to force generation
51
+ if listing_plans.height == 0:
52
+ listing_plans = pl.DataFrame([{"population": "enrolled", "analysis": analysis_type}])
53
+
54
+ for analysis in listing_plans.iter_rows(named=True):
55
+ # Load ADSL
56
+ pop_name = analysis.get("population", "enrolled")
57
+
58
+ try:
59
+ (adsl_raw,) = parser.get_datasets("adsl")
60
+ pop_filter = parser.get_population_filter(pop_name)
61
+
62
+ adsl, _ = apply_common_filters(
63
+ population=adsl_raw,
64
+ observation=None,
65
+ population_filter=pop_filter,
66
+ observation_filter=None,
67
+ )
68
+
69
+ except ValueError as e:
70
+ print(f"Error loading population: {e}")
71
+ continue
72
+
73
+ # Output filename
74
+ filename = f"{analysis_type}_{pop_name}.rtf".lower()
75
+ output_path = f"{output_dir}/{filename}"
76
+
77
+ # Generate DF
78
+ df = ie_listing_df(adsl)
79
+
80
+ # Generate RTF
81
+ ie_listing_rtf(df, output_path, title=title)
82
+
83
+ generated_files.append(output_path)
84
+
85
+ return generated_files
86
+
87
+
88
+ def ie_listing_df(adsl: pl.DataFrame) -> pl.DataFrame:
89
+ """Select columns for Listing."""
90
+ # Check if DCSREAS exists
91
+ cols = ["USUBJID", "DCSREAS"]
92
+ available = [c for c in cols if c in adsl.columns]
93
+ return adsl.select(available)
94
+
95
+
96
+ def ie_listing_rtf(df: pl.DataFrame, output_path: str, title: str | list[str] = "") -> None:
97
+ """Generate RTF Listing."""
98
+ col_widths = [1.5, 3.5] # Approximate ratio
99
+
100
+ rtf_doc = create_rtf_listing(
101
+ df=df,
102
+ col_header=list(df.columns),
103
+ col_widths=col_widths,
104
+ title=title,
105
+ footnote=[],
106
+ source=[],
107
+ )
108
+
109
+ rtf_doc.write_rtf(output_path)