A Non-Invasive Macro to Track Submission Metadata in SAS Drug Development

A Non-Invasive Macro to Track Submission Metadata in SAS Drug Development
SAS Global Forum 2011
Posters
Paper 212-2011
A Non-Invasive Macro to Track Submission Metadata in SAS® Drug Development
Katrina E. Canonizado, Celerion, Lincoln, NE
Bradford J. Danner, i3 Statprobe, Lincoln, NE
Matthew J. Wiedel, Celerion, Lincoln, NE
ABSTRACT
To address the concerns of program quality and transparency in the contract research organization (CRO) industry,
program validation plays a central role in data analysis. As an aid to speed up this process, we provide fellow
programmers and reviewers with what we refer as an audit program list. This list contains the current settings of the
SAS® session like the program name, data sets used, etc. In SAS Drug Development, this information is stored in
SDDparms for individual programs within submission. This paper demonstrates briefly the macro %metadata we
have written. The macro primarily utilizes SDDparms in tracking the information to build the audit program list.
INTRODUCTION AND BACKGROUND
An audit program list is what we refer to as a compilation of program names, table and figure titles included in the
clinical study report, permanent datasets used within the program, rundate and runtime, and macros called within
individual programs. This is a part of our program documentation, if requested, submitted to reviewers to ensure the
traceability, reliability and accuracy of the programs and of the outputs that go with every study report. There are
several ways to gather these relevant program components using basic SAS functions such as PROC CONTENTS,
SAS Dictionary Tables, use of reserved SAS macro variables like &sysdate, &systime and &sysdsn. However, in the
SAS Drug Development (SDD) environment, within every run cycle, there is an optional parameters dataset available
to the user and is accessible through a parameter list as illustrated below. This dataset, which contains many of the
items needed to create an audit program list, can be accessed programmatically using the global macro variable
&SDDPARMS.
Most of the standard programs we have, used the information within the SDDParms dataset for a specific purpose.
With the increasing demand of process and program validation demanded by the industry, there was a need to revisit
our current programs and available resources. One of our biggest challenges was how to access resources in a noninvasive way within our existing table and figure programs. Because there are several programs that are currently
being used, our goal was to include a feature within those programs with the capability of capturing the information
required for an audit program list without recoding the programs. To help us with this, we developed a macro called
%metadata.
SAS Global Forum 2011
Posters
The key procedure used in the %metadata macro is PROC SQL. PROC SQL is an effective tool for creating,
modifying, and retrieving data dynamically in relational databases. Moreover, PROC SQL has the capability of
creating macro variables in such a way that the user can:




create several macro variables with a shorter statement;
trace easily the parameters or conditions being set;
store a list and grab values in a macro variable without having to manually enter; and
combine BASE SAS tools without interfering with the initialization of the macro variables.
METHODS AND DISCUSSION
The %metadata macro is invoked at the very end of every table, listing and figure program within a clinical study
report submission. The macro is activated when the output are being finalized to minimize rework and to keep the
most accurate record.
Since all the table and figure programs within a submission are calling the macro, it would be tedious to alter each
individual program to activate this macro. To avoid too much work, the %metadata macro is compiled within a central
setup program, which contains certain processes, macros and formats necessary for all the TFL programs, and is
already included in all the standard programs, therefore, the %metadata macro is available to be called by the user
anytime it is needed.
The code begins with a %LET statement to toggle the running of the macro. While trying to set-up the TFL programs,
initially the macro variable &choice is set to NO (Refer to Appendix). Because there will be continuous updates and
changes in production programs included in a submission, it is a good decision not to activate this macro until the
tables and figures have been approved. When there is indication that the TFLs are finalized, the %metadata macro is
actived by setting the &choice variable to “YES”, and information necessary for the program audit list is compiled by
re-running all the programs.
Most of the information compiled by the macro is accomplished by filtering for relevant record contained in the
SDDPARMS dataset and assigning the values to macro variables using PROC SQL. To create macro variables using
PROC SQL, the syntax is:
SELECT <variable name in a SAS data set>
INTO :<macro variable name>
(and optionally)
SEPARATED BY '<a blank, a character, or a character string>'
Following this format and with a little manipulation using the WHERE statement, as shown below, we were able to
retrieve the program name, programmatically using the global macro variable &SDDPARMS:
proc sql noprint;
select value into :mtdpnam from &SDDPARMS
where (id="<process>" and valtype="filename");
Program
name
It is a common practice in programming to call in several datasets and to use two or more routine macros.
Regardless of how many datasets and how many macros used in the program, all of this information is part of the
audit process and needs to be documented. In the SAS Drug Development environment, dataset names and macros
called within the current program are readily available in the SDDParm dataset. However, by just grabbing all this
information and stacking it, will make the audit list messy and cumbersome. To make it more concise and organized,
the capability of SEPARATED BY in PROC SQL has the ability to compile the values requested into a list contained
within a single macro variable, as illustrated below:
SAS Global Forum 2011
Posters
select value into :mtdids_ separated by ', ' from &SDDPARMS
where ((id="SDTM" or id="INC" or id="CDASH" or id="ADAM" or id="LIB2")
and (index(value,'.sas7bdat')))
order by value;
select value into :mtdmcals_ separated by ', ' from &SDDPARMS
where (index(value,'.sas') and id ne "SETUP" and index(value,'.sas7bdat')=0
and id ne "<process>" and id ne "MNEW")
order by value;
Macros called in the program
Dataset used
Using SEPARATED BY in Proc SQL:
PROC SQL and BASE SAS tools can be used hand in hand to assign macro variables. With this feature of PROC
SQL, values assigned in macro variables are easily transformed depending on the desired format as shown below:
In SDD, the rundate and runtime follow the ISO 8601 format. For clarity purposes, the line of code below reformats
the presentation of the date and time:
select put(input(scan(value,1,'T'),yymmdd10.),date9.)||" "||scan(value,-1,'T')
into :mtdts from &SDDPARMS
where upcase(valtype)="DATE";
Unfortunately, table and figure titles are not available in the SDDParms dataset. However, given the way our
programs are designed, DICTIONARY.TITLES can be used to access table and figure titles presented in the study
report. Sometimes the length of the titles will exceed the allowable report margin, and declaring two or more title
statements is the only way around this problem. Using SEPERATED BY '~'allows combining several lines of titles into
a more readable format, and it can be done using the line of code below.
select text into: mtdtit separated by '~' from dictionary.titles
where(type="T");
SAS Global Forum 2011
Posters
Using Separated by ‘~’in Proc SQL:
Once information is collected from individual programs, the second objective of the macro is to collate the metadata
by using the assigned macro variables. The macro variables that have been declared become handy in creating the
SAS dataset that will subsequently be used to create the audit program list. The advantage of using the macro is that
the code is a little less complicated. Using a simple datastep process or PROC SQL CREATE and INSERT
statement, the dataset is being populated and updated, as shown below.
proc sql;
create table work.metatemp
(runtime Char(30),
progname Char(40),
idata
Char(200),
macros
Char(200),
title
Char(200));
insert into work.metatemp
set runtime="&mtdts.",
progname="&mtdpnam.",
idata="&mtdids_.",
macros="&mtdmcals_.",
title="&mtdtit.";
quit;
data work.metadata_injob;
%if %sysfunc(exist(work.metadata_injob) %then
%do;
update work.metadata_injob work.metatemp;
%end;
%else %do;
set work.metatemp;
%end;
by title;
run;
data mnew.metadata1;
%if %sysfunc(exist(mnew.metadata1)) %then %do;
update mnew.metadata1 work.metadata_injob;
%end;
%else %do;
set work.metadata_injob;
%end;
by title;
run;
Having a permanent and temporary datasets being created and updated seems very redundant. The reason for
having this in the code is because in SAS Drug Development there are two primary methods by which programs are
typically submitted. One method is using the Process Editor where a program is submitted individually while the other
method is using the Job Editor where programs are run in sequence. When programs are submitted using a Job
Editor, the permanent SAS datasets are only updated after the last process has been executed, therefore the
permanent metadata reposiroty will only contain information from the last process. Using both a permanent SAS
dataset, and a temporary SAS dataset, with a „reserved‟ naming convention, we were able to circumvent this difficulty
when using the Job Editor.
Unavoidable difficulties may be encountered with the permanent SAS metadata dataset, when after finalizing the
submission requirements, sudden changes are requested. Changes in the table and figure titles are most often
requested, and while minor, must be accounted for in our audit program list. The code updates by title, thus changing
title will cause the duplication of records – the first record contains the previous title while the second record contains
the most current one. To guarantee that the record stored in the permanent dataset will be the most recent and the
most accurate, a PROC SQL DELETE statement was inserted before updating the permanent dataset to avoid
having duplicate records every time a program runs. This line of code will remove any record in the permanent
dataset that matches the criteria specified in the WHERE statement. In this particular example, the condition is: if the
running program name matches any record in the old file and if the runtime is not the current date and time, the
record will be deleted.
SAS Global Forum 2011
Posters
%if %sysfunc(exist(mnew.metadata1)) %then %do;
proc sql noprint;
delete from mnew.metadata1
where (progname = “&mtdpnam.”) and runtime ne ("&mtdts.");
quit;
run;
%end;
Log:
MPRINT(METADATA):
tables-sig.sas
delete from mnew.metadata1 where (progname = "pc-pk-conc") and runtime ne ("26JAN2011 16:53:50
”);
NOTE: 4 rows were deleted from MNEW.METADATA1.
A few examples of requested changes that could affect all of the submitted programs are renumbering and
rearranging the tables and figures, altering the format of the headings, or rewording of titles. Typically, a programmer
or statistician will use the job editor to generate the desired outputs and together with this, rebuild the metadata of
program settings. Keeping in mind that the job editor only updates the permanent dataset after the execution of the
last program in the list, it is required then to keep track of all the previous program names to make sure that after the
submission of the job, all old records of the previous run programs are also been removed. If there will be no place
holder for the other submitted programs, the only record that will be updated is the one that is related to the last
program in the list. To address this problem, the code above was modified. The code uses SELECT DISTINCT INTO
which is used to pass the unique values of a variable and be declared as a macro variable. By using the QUOTE
function, every value that is passed into a macro variable will be in double quotation so that it will be treated as a
character when called.
%if %sysfunc(exist(work.metadata_injob)) %then %do;
proc sql noprint;
select distinct quote(progname) into: prg separated by ',' from
work.metadata_injob;
quit;
run;
%let prg=&prg;
%end;
%if %sysfunc(exist(mnew.metadata1)) %then %do;
proc sql noprint;
delete from mnew.metadata1
where (progname in (&prg) and runtime ne ("&mtdts."));
quit;
run;
%end;
Log:
MPRINT (METADATA):
delete from mnew.metadata1 where (progname in ("pc-keltables.sas
","pc-pk-conc-tables-sig.sas
","pc-pk-stats.sas
","pc-pk-tables.sas
") and runtime ne ("26JAN2011 17:19:13
“));
NOTE: 9 rows were deleted from MNEW.METADATA1.
The output of the program is a metadata SAS dataset where each row corresponds to the program settings related to
an output included in a clinical study report as shown below. Having this dataset makes the process of program
documentation faster since it is readily available after running all the programs. If there are necessary adjustments to
be made to meet client specification, it can be accessed and retrieved through SAS® for further mining.
5
SAS Global Forum 2011
Posters
Once this metadata SAS dataset has been created, it can easily be transformed into an Excel file, or alternative
format, for delivery to a client. Moreover, the output can effectively be used by non-SAS users for different tasks such
as cross-referencing programs with the output, verifying titles, or generating table of contents.
CONCLUSION
This paper has illustrated a method of tracking submission metadata within the SAS Drug Development environment,
specifically using the SDDPARMS dataset. Using PROC SQL and the SAS DATA step, we were able to write a noninvasive macro that efficiently collates all information necessary to build an audit program list. The code presented
can be easily modified if there are additional items required in the audit program list by merely adding additional subqueries to the SQL procedure.
REFERENCES
SAS 9.1.3 Online Documentation
SAS Drug Development 3.4 User‟s Guides
Shu, Amos. The SAS Programming Experience in the SAS Drug Development (SAS DD) Environment – Comparing
with the Regular SAS Programming Environment. Proceedings of NESUG 2010.
ACKNOWLEDGMENTS
We would like to thank our colleagues in the Biostatistics and Pharmacokinetics groups in Clinical Pharmacological
Sciences department at Celerion who provided comments on earlier drafts. Their insights and guidance are
appreciated.
CONTACT INFORMATION
Your comments and questions are valued and encouraged. Please contact the authors at:
Katrina E. Canonizado
Celerion
621 Rose Street
6
SAS Global Forum 2011
Posters
Lincoln, NE 68502
[email protected]
Bradford J. Danner
i3 Statprobe
[email protected]
Matthew J. Wiedel
Celerion
621 Rose Street
Lincoln, NE 68502
[email protected]
SAS and all other SAS Institute Inc. product or service names are registered trademarks or trademarks of SAS
Institute Inc. in the USA and other countries. ® indicates USA registration.
Other brand and product names are trademarks of their respective companies.
APPENDIX
MACRO CODE
%let choice = YES;
libname mnew "&mnew";
%macro metadata;
%if &choice=YES %then %do;
%global mtdpnam mtdids_ mtdmcals_ mtdtit mtdts;
proc sql noprint;
select value into :mtdpnam from &SDDPARMS where (id="<process>" and
valtype="filename");
select value into :mtdids_ separated by ', ' from &SDDPARMS
where ((id="SDTM" or id="INC" or id="CDASH" or id="ADAM" or id="LIB2") and
(index(value,'.sas7bdat'))) order by value;
select value into :mtdmcals_ separated by ', ' from &SDDPARMS
where (index(value,'.sas') and id ne "SETUP" and index(value,'.sas7bdat')=0 and id
ne "<process>" and id ne "MNEW") order by value;
select text into: mtdtit separated by '~' from dictionary.titles where(type="T");
select put(input(scan(value,1,'T'),yymmdd10.),date9.)||" "||scan(value,-1,'T') into
:mtdts from &SDDPARMS where upcase(valtype)="DATE";
quit;
proc sql noprint;
create table work.metatemp
(runtime Char(30),
progname Char(40),
idata
Char(200),
macros
Char(200),
title
Char(200));
insert into work.metatemp
set runtime="&mtdts.",
progname="&mtdpnam.",
idata="&mtdids_.",
macros="&mtdmcals_.",
title="&mtdtit.";
quit;
7
SAS Global Forum 2011
Posters
data work.metadata_injob;
%if %sysfunc(exist(work.metadata_injob)) %then %do;
update work.metadata_injob work.metatemp;
%end;
%else %do;
set work.metatemp;
%end;
by title;
run;
%if %sysfunc(exist(work.metadata_injob)) %then %do;
proc sql noprint;
select distinct quote(progname) into: prg separated by ',' from
work.metadata_injob;
quit;
run;
%let prg=&prg;
%end;
%if %sysfunc(exist(mnew.metadata1)) %then %do;
proc sql noprint;
delete from mnew.metadata1
where (progname in (&prg.) and runtime ne ("&mtdts."));
quit;
run;
%end;
data mnew.metadata1;
%if %sysfunc(exist(mnew.metadata1)) %then %do;
update mnew.metadata1 work.metadata_injob;
%end;
%else %do;
set work.metadata_injob;
%end;
by title;
run;
%end;
%mend metadata;
8
Was this manual useful for you? yes no
Thank you for your participation!

* Your assessment is very important for improving the work of artificial intelligence, which forms the content of this project

Download PDF

advertisement