Skip to content

Commit

Permalink
Merge pull request #71 from dominodatalab/Interim_01
Browse files Browse the repository at this point in the history
Final Interim 01
  • Loading branch information
ddl-jim-coates authored Oct 10, 2024
2 parents aa5e527 + 93fc83b commit 6dfb77b
Show file tree
Hide file tree
Showing 3 changed files with 1,011 additions and 0 deletions.
371 changes: 371 additions & 0 deletions prod/tfl/t_dm1.sas
Original file line number Diff line number Diff line change
@@ -0,0 +1,371 @@
/*****************************************************************************\
* ____ _
* | _ \ ___ _ __ ___ (_)_ __ ___
* | | | |/ _ \| '_ ` _ \| | '_ \ / _ \
* | |_| | (_) | | | | | | | | | | (_) |
* |____/ \___/|_| |_| |_|_|_| |_|\___/
* ____________________________________________________________________________
* Sponsor : Domino
* Study : CDISC01
* Program : t_ae_rel.sas
* Purpose : Create the Treatment Emergent Adverse Events Table
* ____________________________________________________________________________
* DESCRIPTION
*
* Input files: ADaM.ADSL
* ADaM.ADAE
*
* Output files: t_ae_rel.pdf
* t_ae_rel.sas7bdat
*
* Macros: tfl_metadata.sas
*
* Assumptions: test
*
* ____________________________________________________________________________
* PROGRAM HISTORY
* 24MAY2022 | Jake Tombeur | Original version
* 10MAY2023 | Megan Harries | Updates for CDISC01 ADaMs
* ----------------------------------------------------------------------------
\*****************************************************************************/

*********;
** Setup environment including libraries for this reporting effort;
%include "/mnt/code/domino.sas";
*********;

ods path(prepend) work.templat(update);

*Set the template for the output;
proc template;
define style newstyle;

class Table /
Rules = Groups
Frame = void;

style header
/ just = c
fontweight = medium;

replace Body from Document /
bottommargin = 1.54cm
topmargin = 2.54cm
rightmargin = 2.54cm
leftmargin = 2.54cm;

replace fonts /
'TitleFont2' = ("Courier New",9pt)
'TitleFont' = ("Courier New",9pt/*,Bold*/) /* titles */
'StrongFont' = ("Courier New",9pt/*,Bold*/)
'EmphasisFont' = ("Courier New",9pt,Italic)
'FixedEmphasisFont' = ("Courier New, Courier",9pt,Italic)
'FixedStrongFont' = ("Courier New, Courier",9pt/*,Bold*/)
'FixedHeadingFont' = ("Courier New, Courier",9pt/*,Bold*/)
'BatchFixedFont' = ("SAS Monospace, Courier New, Courier",9pt)
'FixedFont' = ("Courier New, Courier",9pt)
'headingEmphasisFont' = ("Courier New",9pt,Bold Italic)
'headingFont' = ("Courier New",9pt/*,Bold*/) /* header block */
'docFont' = ("Courier New",9pt); /* table cells */

replace color_list
"Colors used in the default style" /
'link' = blue
'bgH' = white /* header background */
'fg' = black
'bg' = _undef_;
end;
run ;

options orientation = landscape nonumber nodate nobyline;

proc format;
picture pctmf (round default = 8) /* Picture format for percentages */
. = ' ' (noedit)
low-0.001 = ' ' (noedit)
0.001-<0.1 = ' (<0.1%)' (noedit)
0.1-<1 = ' (9.9%)' (prefix=' (')
1-<99.90001 = ' (00.0%)' (prefix=' (')
99.90001-<100 = '(>99.9%)' (noedit)
100 = '(100%) ' (noedit)
;
run;

data teae (rename = (actarm = trta));
length relcat $20;
set adam.adae;

if aerel in ('POSSIBLE' 'PROBABLE' 'DEFINITE') then relcat = 'Related';
else relcat = 'Not Related';

if actarm = "Placebo" then trtan = 1;
else if actarm = "Xanomeline Low Dose" then trtan = 2;
else if actarm = "Xanomeline High Dose" then trtan = 3;
run;

** exclude non-treated subjects;
data adsl1 (rename = (actarm = trta) where = (trtan ^= .));
set adam.adsl;

if actarm = "Placebo" then trtan = 1;
else if actarm = "Xanomeline Low Dose" then trtan = 2;
else if actarm = "Xanomeline High Dose" then trtan = 3;
run;

%let indat = teae;
%let trtvarn = trtan;
%let inadsl = adsl1;
%let socvar = aesoc;
%let ptvar = aedecod;
%let totval = 99;
%let trtnord = 99;
%let pctfmt = pctmf.;
%let byvar = relcat;

/* Macro for creating #patients/#events counts */
%macro ne_freq (indat =,outdat =, byvars =, anyvars = );

%let byvars2 = %sysfunc(tranwrd(%quote(&byvars.) ,%str( ),%str( , )));
%if &byvars ^= %then %let sep = %str( , );
%else %let sep = ;

proc sql;
create table &outdat. as
select count(distinct USUBJID) as stat_n,
count(USUBJID) as stat_e
&sep. &byvars2.
%if &anyvars ^= %then %do i = 1 %to %sysfunc(countw(&anyvars));
, 'ANY' as %scan(&anyvars, &i)
%end;
from &indat.
%if &byvars. ^= %then group by &byvars2.;
;
quit;

%mend;

/* All aes (with total column if required) */
data aes;
set &indat
&indat (in = intot);
if intot then &trtvarn = &totval;
run;

/* Adsl with total column if required */
data adslmod;
set &inadsl
&inadsl (in = intot );
if intot then &trtvarn = &totval;
run;

/* Counts including totals (by Severity) */
%ne_freq(indat = aes, outdat = out1, byvars = &byvar &trtvarn, anyvars = &socvar &ptvar);
%ne_freq(indat = aes, outdat = out2, byvars = &byvar &trtvarn &socvar, anyvars = &ptvar);
%ne_freq(indat = aes, outdat = out3, byvars = &byvar &trtvarn &socvar &ptvar, anyvars =);

/* Counts including totals (Any Severity) */
%ne_freq(indat = aes, outdat = out4, byvars = &trtvarn, anyvars = &byvar &socvar &ptvar);
%ne_freq(indat = aes, outdat = out5, byvars = &trtvarn &socvar, anyvars = &byvar &ptvar);
%ne_freq(indat = aes, outdat = out6, byvars = &trtvarn &socvar &ptvar, anyvars = &byvar);

/* N counts for denominators */
%ne_freq(indat = adslmod, outdat = Ncounts, byvars = &trtvarn, anyvars =);

data Ncounts;
set Ncounts (drop = stat_e rename = (stat_n = bigN));
call symputx(cats('N_',&trtvarn), bigN, 'g');
run;

/* Set all ae counts together */
data allcounts;
length &socvar &ptvar $ 200;
set out1-out6;
run;

/* Template dataset */
proc sql;
create table template as
select *, 0 as stat_e, 0 as stat_n
from (select distinct &socvar, &ptvar from &indat
union
select distinct &socvar, 'ANY' as &ptvar from &indat
union
select distinct 'ANY' as &ptvar, 'ANY' as &socvar from &indat),
(select distinct &byvar from &indat
union
select distinct 'ANY' as &byvar from &indat),
Ncounts
order by &trtvarn, &socvar, &ptvar, &byvar;
;
quit;

/* Merge on observed counts to template */
proc sort data = allcounts out = allcounts_s;
by &trtvarn &socvar &ptvar &byvar;
run;
data counts_w0;
length &socvar &ptvar $ 200 statc_n statc_e statc_p $ 30;
merge template allcounts_s;
by &trtvarn &socvar &ptvar &byvar;
/* Create character versions of counts */
statc_n = strip(put(stat_n,5.));
statc_e = strip(put(stat_e,5.));
statc_p = put(stat_n/bigN * 100, &pctfmt);
run;

/* Concatenate n and percent*/
data counts_cat (keep = &socvar &ptvar &trtvarn &byvar npp statc_e);
length npp $ 50;
set counts_w0;
npp = cat(strip(statc_n), ' ', strip(statc_p));
run;

/* Create SOC and PT order variables based on # patients / frequency of event */
proc rank data = counts_w0 (where = (&trtvarn = &trtnord & &ptvar = 'ANY' & &socvar ^= 'ANY' & &byvar = 'ANY')) out = socranks (keep = &socvar SOCord_NP SOCord_EV) ties = low descending;
var stat_n stat_e;
ranks SOCord_NP SOCord_EV;
run;

proc sort data = counts_w0 out = counts_w0s;
by &socvar;
run;

proc rank data = counts_w0s (where = (&trtvarn = &trtnord & &ptvar ^= 'ANY' & &socvar ^= 'ANY' & &byvar = 'ANY')) out = ptranks (keep = &socvar &ptvar PTord_NP PTord_EV) ties = low descending;
by &socvar;
var stat_n stat_e;
ranks PTord_NP PTord_EV;
run;

proc format;
invalue relord 'ANY' = 1
'Related' = 2
'Not Related' = 3
;
run;

proc sql;
create table counts_word as
select a.*,
case when a.&socvar = 'ANY' then 1 else b.SOCord_NP + 1 end as SOCord_NP,
case when a.&socvar = 'ANY' then 1 else b.SOCord_EV + 1 end as SOCord_EV,
case when a.&ptvar = 'ANY' then 1 else c.PTord_NP + 1 end as PTord_NP,
case when a.&ptvar = 'ANY' then 1 else c.PTord_EV + 1 end as PTord_EV,
input(&byvar,relord.) as relord
from counts_cat a left join socranks b
on a.&socvar = b.&socvar
left join ptranks c
on a.&socvar = c.&socvar
and a.&ptvar = c.&ptvar
order by SOCord_NP, &socvar, PTord_NP, &ptvar, relord, &byvar, &trtvarn
;
quit;

/* Transpose into long format */
proc transpose data = counts_word out = counts_T (rename = (_NAME_ = statty COL1 = statval));
by SOCord_NP &socvar PTord_NP &ptvar relord &byvar &trtvarn ;
var npp statc_e;
run;

data counts_T;
set counts_T;
where &trtvarn ^= .;
run;

/* Transpose to trts are cols */
proc transpose delim = _ prefix = trt_ data = counts_T out = counts_TT (drop = _NAME_);
id &trtvarn statty;
by SOCord_NP &socvar PTord_NP &ptvar relord &byvar;
var statval;
run;

data extrow (keep = aesoc aedecod soc_pt_disp &byvar trt_99_npp);
length soc_pt_disp $ 132;
set counts_TT;
by SOCord_NP aesoc;

if first.aesoc & aesoc ^= 'ANY' then do;
soc_pt_disp = aesoc;
output;
end;
if aesoc = 'ANY' then do;
soc_pt_disp = 'Subjects with at least one TEAE';
output;
end;
if aedecod = 'ANY' then aedecod = 'Any event';
soc_pt_disp = aedecod;
if aesoc ^= 'ANY' then output;
run;

data final (drop = i);
set extrow;
array trtcounts $ trt_:;
if aesoc = soc_pt_disp then do i = 1 to dim(trtcounts);
trtcounts[i] = '';
&byvar = ' ';
end;
if aedecod = soc_pt_disp then indent = 'Y';
else indent = 'N';

if &byvar = 'ANY' then &byvar = 'Total';
&byvar = propcase(&byvar);

soc_pt_disp = propcase(soc_pt_disp);
aesoc = propcase(aesoc);
aedecod = propcase(aedecod);

soc_pt_disp = tranwrd(soc_pt_disp, "Teae", "TEAE");
run;

*include metadata;
%tfl_metadata;

** create the table output;

ods pdf file = "/mnt/artifacts/TFL/&__prog_name..pdf"
style = newstyle;

ods noproctitle;
ods escapechar = "^";

** add titles to output;
title1 justify = left "Domino" justify = right "Page ^{thispage} of ^{lastpage}";
title2 "&DisplayName.";
title3 "&DisplayTitle.";
title4 "&Title1.";

** justify contents to decimal places;
proc report data = final headline split = "*"
style(report) = {width = 100%};
** if you also want TFL written to Dataset out = tfl.&__prog_name.;
column aesoc
aedecod
indent soc_pt_disp &byvar trt_99_npp;

** order variables;
define aesoc / order order = data noprint;
define aedecod / order order = data noprint;
define indent / order order = data noprint;
define &byvar / display ''
style(header) = {width = 8% just = l};
define soc_pt_disp / order order = data "System Organ Class* Preferred Term"
style(header) = {width = 60% asis = on just = l};
define trt_99_npp / display "All Treatments*(N=&N_99)*n (%)"
style(header) = {width = 30%} style(column) = {just = d};
compute soc_pt_disp;
if indent = 'Y' then call define(_COL_, "style", "style=[leftmargin = 0.3in]");
endcomp;

compute before aedecod;
line '';
endcomp;

** add footnotes;
footnote1 justify = left "&Footer1.";
footnote2 justify = left "&Footer2.";
footnote3 justify = left "&Footer3.";
footnote4 justify = left "&Footer4.";
footnote5 justify = left "&Footer5.";
run;

ods pdf close;

Loading

0 comments on commit 6dfb77b

Please sign in to comment.