/*

/ Program   : dosemerge.sas
/ Version   : 1.0
/ Author    : Roland Rashleigh-Berry
/ Date      : 28-Sep-2008
/ Purpose   : Clinical reporting macro to merge dose in with date
/ SubMacros : %lookahead %commas %nlobs
/ Notes     : You should not use this macro blindly. You will need to review the
/             parameter setting to ensure this is working according to your site
/             standards.
/ Usage     : 
/ 
/===============================================================================
/ PARAMETERS:
/-------name------- -------------------------description------------------------
/ dsin=             Input dataset (usually an AE dataset)
/ date=             Name of the date variable in the input dataset
/ subject=          Name of the variable containing the unique subject
/                   identifier in the input dataset.
/ id=               Further identifier in the input dataset that distinguishes
/                   observations having the same date.
/ dsout=            Name of the output dateset with the dose added
/ dsdose=           Dose dataset
/ doselevel=        Name of the numeric variable containing the dose level
/ dosestart=        Date variable for start of dose
/ dosestop=         Date variable for stop of dose. 
/ dosesubject=      Name of the variable containing the unique subject
/                   identifier in the dose dataset. If left blank it will
/                   default to what was defined to subj=.
/ fixgaps=yes       By default, fix any dose gaps by changing the stop date to
/                   the day before the following start date.
/ fixoverlaps=yes   By default, fix any overlaps between a stop date and the 
/                   following start date by changing the stop date to the day
/                   before the following start date. If this is set to "no" then
/                   the lowest non-zero dose will be used.
/===============================================================================
/ AMENDMENT HISTORY:
/ init --date-- mod-id ----------------------description------------------------
/ rrb  13Feb07         "macro called" message added
/ rrb  28Sep08         This is now classed as a "Clinical reporting" macro
/===============================================================================
/ This is public domain software. No guarantee as to suitability or accuracy is
/ given or implied. User uses this code entirely at their own risk.
/=============================================================================*/

%put MACRO CALLED: dosemerge v1.0;

%macro dosemerge(dsin=,
                 date=,
              subject=,
                   id=,
                dsout=,
               dsdose=,
            doselevel=,
            dosestart=,
             dosestop=,
          dosesubject=,
              fixgaps=yes,
          fixoverlaps=yes
               );

%local error nobs nobs2;
%let error=0;


     /*-------------------------------------------------*
        Check we have enough parameters set to continue
      *-------------------------------------------------*/

%if not %length(&dsin) %then %do;
  %let error=1;
  %put ERROR: (dosemerge) dsin= parameter not set;
%end;

%if not %length(&date) %then %do;
  %let error=1;
  %put ERROR: (dosemerge) date= parameter not set;
%end;

%if not %length(&subject) %then %do;
  %let error=1;
  %put ERROR: (dosemerge) subject= parameter not set;
%end;

%if not %length(&dsout) %then %let dsout=%scan(&dsin,1,%str(%());

%if not %length(&dsdose) %then %do;
  %let error=1;
  %put ERROR: (dosemerge) dsdose= parameter not set;
%end;

%if not %length(&doselevel) %then %do;
  %let error=1;
  %put ERROR: (dosemerge) doselevel= parameter not set;
%end;

%if not %length(&dosestart) %then %do;
  %let error=1;
  %put ERROR: (dosemerge) dosestart= parameter not set;
%end;

%if not %length(&dosestop) %then %do;
  %let error=1;
  %put ERROR: (dosemerge) dosestop= parameter not set;
%end;

%if not %length(&dosesubject) %then %let dosesubject=&subject;

%if not %length(&fixgaps) %then %let fixgaps=yes;
%let fixgaps=%upcase(%substr(&fixgaps,1,1));

%if not %length(&fixoverlaps) %then %let fixoverlaps=yes;
%let fixoverlaps=%upcase(%substr(&fixoverlaps,1,1));



     /*-------------------------------------------------*
                  Start processing the data
      *-------------------------------------------------*/

proc sort data=&dsdose out=_dose;
  by &subject &dosestart &dosestop;
run;

%lookahead(dsin=_dose,bygroup=&subject,vars=&dosestart,lookahead=1)

data _dose;
  set _dose;
  %if "&fixgaps" EQ "Y" %then %do;
    if &dosestop<(&dosestart.1-1) then &dosestop=&dosestart.1-1;
  %end;
  %if "&fixoverlaps" EQ "Y" %then %do;
    if (&dosestart.1 NE .) and (&dosestop>=&dosestart.1)
      then &dosestop=&dosestart.1-1;
  %end;
  %else %do;
    if &doselevel=0 then &doselevel=99999;
  %end;
  drop &dosestart.1;
run;


%let nobs=%nlobs(%scan(&dsin,1,%str(%()));

proc sql noprint;
  create table _doseout as
  select a.*, d.&doselevel from &dsin as a
  left join _dose as d
  on a.&subject=d.&dosesubject
  and d.&dosestart<=a.&date<=d.&dosestop
  order by %commas(a.&subject &id a.&date d.&doselevel);
quit;

data &dsout;
  set _doseout;
  by &subject &id &date;
  if first.&date;
  if &doselevel=99999 then &doselevel=0;
run;

%let nobs2=%nlobs(%scan(&dsout,1,%str(%()));

%if &nobs2 NE &nobs %then 
%put ERROR: (dosemerge) Input dataset had &nobs observations but 
output dataset has &nobs2 observations.;


     /*-------------------------------------------------*
                       Tidy up and exit
      *-------------------------------------------------*/

proc datasets nolist;
  delete _dose _doseout;
run;
quit;


%goto skip;
%error:
%put ERROR: (dosemerge) Leaving dosemerge macro due to error(s) listed.;
%skip:
%mend;