Spectre at Work

(Author: Roland Rashleigh-Berry                                                                     Date: 27 Sep 2011)

Introduction

Although Spectre has many components (especially scripts) it is a very easy system to use. Spectre is a "back end" system and currently has no front end so you have to issue all its commands from a terminal window. The terminal window might be a Unix window or a Cygwin window (the latter if you are using it on a PC). You might not be familiar with using back end systems directly using commands so you will see how it is done on this page. It's not so bad when you get used to it. You might end up preferring to do it that way. Just because it is a "back end" system doesn't mean that there are no utilities to help you. There could be a lot of help utilities and indeed there are. You will see some of Spectre's help utilities in action.

What you will see on this page is a study reported all the way through from empty directories through dataset build, report code developed and tested through to reports produced in a final run. To keep it simple, there will only be two derived datasets and two tables produced. After this has been done, it will be demonstrated how to convert your reporting code into macros so that you can use Spectre as a "push-button" reporting system. Being a "push button" reporting system is the ultimate goal of Spectre. Once CDISC data standards have all been defined and tables and listings content and layouts have all been defined for these CDISC datasets then you will be able to have a set of macros to do all your reporting, called from the "titles members", and the ultimate goal of Spectre will have been achieved. There will be more explanation of this later.

Firstly, I will show you the directory structure I am going to use that I have set upon my PC.

Directory Structure

You need to know my directory structure to make sense of my autoexec.sas member and my allocation macros %allocr and %allocw (which will be explained later). I have Spectre set up on my PC using Cygwin and for all my clinical reporting work I have a directory named "pharma" that sits under the "C:" drive. The client, their office, the drug, protocol and increment directories hang underneath. This is not a recommendation as to how to set up your directories but I have seen this system in use at two pharmas and I think it is a good system. I will show you the directory structure below "C:\pharma". I will navigate to that directory in Cygwin and use the script dirtree (a Spectre script) to show you the directory structure. This is what I get.
 
Roland@DELL1 ~
$ cd /cygdrive/c/pharma

Roland@DELL1 /cygdrive/c/pharma
$ dirtree

xenuyama
    formats
    macros
    tokyo
        DRUG001
            DRUG001C3001
                24weeks
                    data
                        analysis
                        derived
                        raw
                    formats
                    macros
                    progs
                formats
                macros
            formats
            macros
        formats
        macros

Roland@DELL1 /cygdrive/c/pharma

If you look at the directory structure above you will see "formats" and "macros" directories existing at each level. When I assign macros to the sasautos path I want the macros at the lowest level earlier in the path than those at the higher levels. Last but one I want the Spectre macros and last of all the SASAUTOS that come with sas. The same applies to the formats in the sense that the lower level formats should be earlier in the fmtsearch= path.

Note the "progs" and "macros" directory under "24weeks". That is where I will be doing most of my coding. I have set up a shortcut in my .bashrc member (might be .bashrc_own for you) so that I can jump to the 24weeks progs directly using "cd $xyprogs". Here is the command in my .bashrc to set up this variable.
 
xyprogs=/cygdrive/c/pharma/xenuyama/tokyo/DRUG001/DRUG001C3001/24weeks/progs

If you are not allowed to edit your .bashrc file and are not allowed to have a .bashrc_own file then it does not matter. You can always create your own command files in your home directory with all your shortcuts and other things you need and "source" it. You might have different command files for the different studies you are working on. How to "source" a command file is explained here.

Starting from empty directories

I have told you that I will use Spectre to report a study from beginning to end, starting out with empty directories. I wil show you the evidence so you can decide. I will put one silly_sas_program in the lowest level "progs" directory, where I will do most of my coding, so you can see it. I will leave it there throughout the study reporting phase as it will play no role since it does not match Spectre naming conventions. I will do a "find ." from the "pharma" directory downwards and show you what is in my directories. Look for "silly_sas_program.sas". That is the only member in all these directories. Here goes and I hope you are convinced when you see "silly_sas_program.sas" as the only entry in all these directories. I am truly reporting from empty directories. I will run this "find ." command from time to time to give you an update on what has appeared in my directories.
 
Roland@DELL1 ~
$ cd /cygdrive/c/pharma

Roland@DELL1 /cygdrive/c/pharma
$ find .
.
./xenuyama
./xenuyama/formats
./xenuyama/macros
./xenuyama/tokyo
./xenuyama/tokyo/DRUG001
./xenuyama/tokyo/DRUG001/DRUG001C3001
./xenuyama/tokyo/DRUG001/DRUG001C3001/24weeks
./xenuyama/tokyo/DRUG001/DRUG001C3001/24weeks/data
./xenuyama/tokyo/DRUG001/DRUG001C3001/24weeks/data/analysis
./xenuyama/tokyo/DRUG001/DRUG001C3001/24weeks/data/derived
./xenuyama/tokyo/DRUG001/DRUG001C3001/24weeks/data/raw
./xenuyama/tokyo/DRUG001/DRUG001C3001/24weeks/formats
./xenuyama/tokyo/DRUG001/DRUG001C3001/24weeks/macros
./xenuyama/tokyo/DRUG001/DRUG001C3001/24weeks/progs
./xenuyama/tokyo/DRUG001/DRUG001C3001/24weeks/progs/silly_sas_program.sas
./xenuyama/tokyo/DRUG001/DRUG001C3001/formats
./xenuyama/tokyo/DRUG001/DRUG001C3001/macros
./xenuyama/tokyo/DRUG001/formats
./xenuyama/tokyo/DRUG001/macros
./xenuyama/tokyo/formats
./xenuyama/tokyo/macros

Roland@DELL1 /cygdrive/c/pharma

So there it is! Empty directories apart from "silly_sas_program.sas". You will see Spectre at work from nothing through to final reports production.

autoexec.sas

First I shall deal with autoexec.sas and the assignment of macros to the sasautos path. Study macros should only be assigned if I am starting sas from below the "pharma" directory otherwise I just want the Spectre macros and SASAUTOS. I keep my autoexec.sas stored in the same directory as the sas executable and below is what it contains. You will see how sasautos is set up. I could call another code member to set up sasautos but whatever method I use, when autoexec.sas ends, Spectre must have sufficient macros defined to it so that it can call all needed macros directly. To make it clear what macro directories have been assigned, I display the contents of the sasautos path at the end in the sas log and I recommend you do the same.
 
*- Note that this is a WINDOWS autoexec member meant to be   -;
*- stored at a high level location such as the folder that contains  -;
*- the sas executable or the C: drive. You can have simpler autoexec -;
*- members stored in the study programs folders but what they SHOULD -;
*- ALWAYS DO is assign all needed macro directories in the correct   -;
*- order if you are initiating sas from the pharmaceutical area. You -;
*- should NOT allocate any study datasets in this member.            -;

*- these options are always needed for Spectre (center optional) -;
options noovp nodate nonumber center xsync noxwait;

*- assign spectre macros to sasautos -;
options sasautos=("C:\spectre\macros" SASAUTOS);

%*- Allocate study reporting macros if in the reporting area -;
%*- (second part of the path name will be "pharma" if so).   -; 
%macro allocmac;
  %local path bitpath macros3 macros4 macros5 macros6 macros7;
  %let path=%readpipe(cd);
  %if "%scan(&path,2,\)"="pharma" %then %do;
    %let bitpath=C:\pharma;
    %*- CLIENT MACROS -;
    %if %length(%scan(&path,3,\)) %then %do;
      %let bitpath=&bitpath.\%scan(&path,3,\);
      %let macros3="&bitpath.\macros";
    %end;
    %*- OFFICE MACROS -;
    %if %length(%scan(&path,4,\)) %then %do;
      %let bitpath=&bitpath.\%scan(&path,4,\);
      %let macros4="&bitpath.\macros";
    %end;
    %*- DRUG MACROS -;
    %if %length(%scan(&path,5,\)) %then %do;
      %let bitpath=&bitpath.\%scan(&path,5,\);
      %let macros5="&bitpath.\macros";
    %end;
    %*- PROTOCOL MACROS -;
    %if %length(%scan(&path,6,\)) %then %do;
      %let bitpath=&bitpath.\%scan(&path,6,\);
      %let macros6="&bitpath.\macros";
    %end;
    %*- INCREMENT MACROS -;
    %if %length(%scan(&path,7,\)) %then %do;
      %let bitpath=&bitpath.\%scan(&path,7,\);
      %let macros7="&bitpath.\macros";
    %end;
    %*- Reset sasautos to include extra macro libraries with -;
    %*- the lowest level macros defined first in the path.   -;
    options sasautos=(&macros7 &macros6 &macros5 &macros4 &macros3
"C:\spectre\macros" SASAUTOS);
  %end;
%mend allocmac;
%allocmac;

%*- Put an entry in the log so the user has a record -;
%*- of what macros are on their sasautos path and    -;
%*- what order they will be called in.               -;
%put NOTE: sasautos=%sysfunc(getoption(sasautos));
 

If I go to the 24weeks "progs" directory and start up sas interactively then this is the final "note" statement from autoexec.sas in my log window showing the sasautos path.
 
NOTE: sasautos=("C:\pharma\xenuyama\tokyo\DRUG001\DRUG001C3001\24weeks\macros"
"C:\pharma\xenuyama\tokyo\DRUG001\DRUG001C3001\macros" "C:\pharma\xenuyama\tokyo\DRUG001\macros"
"C:\pharma\xenuyama\tokyo\macros" "C:\pharma\xenuyama\macros" "C:\spectre\macros" SASAUTOS)

NOTE: AUTOEXEC processing completed.

%allocr and %allocw

%allocr and %allocw are the allocation macros for read and write access, respectively. The Spectre scripts that use sas require these two macros so you must set them up. They must be on the sasautos= path set up by autoexec.sas. For the study I am working on they are in the first of the macro directories defined to sasautos= that you can see above. You should set up your formats libraries as well as the dataset libraries. Also, and very importantly, you must set up the global macro variable _ptlibref_ set to the libref where the "protocol" and "titles" datasets will be stored. These datasets will contain details about the protocol and also the titles of all the reporting programs. They have to go somewhere and it is up to you where you choose to put them. I will put them in the "der" directory.

You will see my code members below but since I am starting from empty directories so I am going to start by creating the local macro header for %allocr using the lmhdr script (short for "local macro header"). If you look in the script you will see it is pulling out details from the directory path, namely the client, office, drug, protocol and increment. It has been coded to match my directory structure. You will likely have to change it to match yours. Watch me jump to the "progs" directory from my home directory, navigate to the "macros" directory, set up the variable "prog" and export it having set it to the program "allocr", generate the header and then "cat" it to the terminal. Last I will copy it over as "allocw.sas" and will edit any changes I need.
 
Roland@DELL1 ~
$ cd $xyprogs

Roland@DELL1 /cygdrive/c/pharma/xenuyama/tokyo/DRUG001/DRUG001C3001/24weeks/progs
$ cd ../macros

Roland@DELL1 /cygdrive/c/pharma/xenuyama/tokyo/DRUG001/DRUG001C3001/24weeks/macros
$ prog=allocr

Roland@DELL1 /cygdrive/c/pharma/xenuyama/tokyo/DRUG001/DRUG001C3001/24weeks/macros
$ export prog

Roland@DELL1 /cygdrive/c/pharma/xenuyama/tokyo/DRUG001/DRUG001C3001/24weeks/macros
$ lmhdr $prog
Enter program purpose: Allocate data libraries and formats in read mode
created allocr.sas

Roland@DELL1 /cygdrive/c/pharma/xenuyama/tokyo/DRUG001/DRUG001C3001/24weeks/macros
$ cat allocr.sas
/*
/ Program      : allocr.sas
/ Version      : 1.0
/ Author       : Roland
/ Date         : 03-Mar-2007
/ SAS version  : 9.1.3
/ Client       : xenuyama
/ Office       : tokyo
/ Drug         : DRUG001
/ Protocol     : DRUG001C3001
/ Increment    : 24weeks
/ Purpose      : Allocate data libraries and formats in read mode
/ SubMacros    : none
/ Notes        : 
/ Usage        : 

/===============================================================================
/ PARAMETERS:
/-------name------- -------------------------description------------------------

/===============================================================================
/ AMENDMENT HISTORY:
/ init --date-- mod-id ----------------------description------------------------

/=============================================================================*/
 

Roland@DELL1 /cygdrive/c/pharma/xenuyama/tokyo/DRUG001/DRUG001C3001/24weeks/macros
$ cp allocr.sas allocw.sas

Next I add the code to each macro. The %allocw macro will be a copy of the code in the %allocr macro except the libraries will be allocated in write mode and it will have access to the "raw" directory in read mode. I didn't allocate the "raw" directory in %allocr because I don't want the possibility of a report being produced from raw data. This suits my standards but maybe not yours.

Time to code up these two macros. I will use Wordpad as my editor on the Windows side to make changes and add the code. Here they are.
 
/*
/ Program      : allocr.sas
/ Version      : 1.0
/ Author       : Roland
/ Date         : 03-Mar-2007
/ SAS version  : 9.1.3
/ Client       : xenuyama
/ Office       : tokyo
/ Drug         : DRUG001
/ Protocol     : DRUG001C3001
/ Increment    : 24weeks
/ Purpose      : Allocate data libraries and formats in read mode
/ SubMacros    : none
/ Notes        : NOT A SPECTRE MACRO
/ Usage        : %allocr

/===============================================================================
/ PARAMETERS:
/-------name------- -------------------------description------------------------

/===============================================================================
/ AMENDMENT HISTORY:
/ init --date-- mod-id ----------------------description------------------------

/=============================================================================*/

%*- declare which libref to use for the "protocol" and "titles" dataset -;
%global _ptlibref_;
%let _ptlibref_=der;

libname der "C:\pharma\xenuyama\tokyo\DRUG001\DRUG001C3001\24weeks\data\derived"
access=readonly;
libname stats "C:\pharma\xenuyama\tokyo\DRUG001\DRUG001C3001\24weeks\data\analysis"
access=readonly;

*- assign format libraries for increment, protocol, drug, office and client -;
libname iformats "C:\pharma\xenuyama\tokyo\DRUG001\DRUG001C3001\24weeks\formats"
access=readonly;
libname pformats "C:\pharma\xenuyama\tokyo\DRUG001\DRUG001C3001\formats"
access=readonly;
libname dformats "C:\pharma\xenuyama\tokyo\DRUG001\formats" access=readonly;
libname oformats "C:\pharma\xenuyama\tokyo\formats" access=readonly;
libname cformats "C:\pharma\xenuyama\formats" access=readonly;

options fmtsearch=(iformats.formats pformats.formats dformats.formats
 oformats.formats cformats.formats);
run;

%put NOTE: fmtsearch=%sysfunc(getoption(fmtsearch));


 
/*
/ Program      : allocr.sas
/ Version      : 1.0
/ Author       : Roland
/ Date         : 03-Mar-2007
/ SAS version  : 9.1.3
/ Client       : xenuyama
/ Office       : tokyo
/ Drug         : DRUG001
/ Protocol     : DRUG001C3001
/ Increment    : 24weeks
/ Purpose      : Allocate data libraries and formats in read mode
/ SubMacros    : none
/ Notes        : NOT A SPECTRE MACRO
/ Usage        : %allocw

/===============================================================================
/ PARAMETERS:
/-------name------- -------------------------description------------------------

/===============================================================================
/ AMENDMENT HISTORY:
/ init --date-- mod-id ----------------------description------------------------

/=============================================================================*/

%*- declare which libref to use for the "protocol" and "titles" dataset -;
%global _ptlibref_;
%let _ptlibref_=der;

libname raw "C:\pharma\xenuyama\tokyo\DRUG001\DRUG001C3001\24weeks\data\raw"
access=readonly;
libname der "C:\pharma\xenuyama\tokyo\DRUG001\DRUG001C3001\24weeks\data\derived";
libname stats "C:\pharma\xenuyama\tokyo\DRUG001\DRUG001C3001\24weeks\data\analysis";

*- assign format libraries for increment, protocol, drug, office and client -;
libname iformats "C:\pharma\xenuyama\tokyo\DRUG001\DRUG001C3001\24weeks\formats";
libname pformats "C:\pharma\xenuyama\tokyo\DRUG001\DRUG001C3001\formats";
libname dformats "C:\pharma\xenuyama\tokyo\DRUG001\formats";
libname oformats "C:\pharma\xenuyama\tokyo\formats";
libname cformats "C:\pharma\xenuyama\formats";

options fmtsearch=(iformats.formats pformats.formats dformats.formats
 oformats.formats cformats.formats);
run;

%put NOTE: fmtsearch=%sysfunc(getoption(fmtsearch));

I will run "find ." again from the "pharma" directory to show you what now exists. You will see that these two macros are listed.
 
Roland@DELL1 /cygdrive/c/pharma/xenuyama/tokyo/DRUG001/DRUG001C3001/24weeks/macros
$ cd /cygdrive/c/pharma

Roland@DELL1 /cygdrive/c/pharma
$ find .
.
./xenuyama
./xenuyama/formats
./xenuyama/macros
./xenuyama/tokyo
./xenuyama/tokyo/DRUG001
./xenuyama/tokyo/DRUG001/DRUG001C3001
./xenuyama/tokyo/DRUG001/DRUG001C3001/24weeks
./xenuyama/tokyo/DRUG001/DRUG001C3001/24weeks/data
./xenuyama/tokyo/DRUG001/DRUG001C3001/24weeks/data/analysis
./xenuyama/tokyo/DRUG001/DRUG001C3001/24weeks/data/derived
./xenuyama/tokyo/DRUG001/DRUG001C3001/24weeks/data/raw
./xenuyama/tokyo/DRUG001/DRUG001C3001/24weeks/formats
./xenuyama/tokyo/DRUG001/DRUG001C3001/24weeks/macros
./xenuyama/tokyo/DRUG001/DRUG001C3001/24weeks/macros/allocr.sas
./xenuyama/tokyo/DRUG001/DRUG001C3001/24weeks/macros/allocw.sas
./xenuyama/tokyo/DRUG001/DRUG001C3001/24weeks/progs
./xenuyama/tokyo/DRUG001/DRUG001C3001/24weeks/progs/silly_sas_program.sas
./xenuyama/tokyo/DRUG001/DRUG001C3001/formats
./xenuyama/tokyo/DRUG001/DRUG001C3001/macros
./xenuyama/tokyo/DRUG001/formats
./xenuyama/tokyo/DRUG001/macros
./xenuyama/tokyo/formats
./xenuyama/tokyo/macros

Roland@DELL1 /cygdrive/c/pharma

Creating the stored formats

Next I will create the formats. It will not be done as part of a Spectre full run but you may choose otherwise. I will create the program in the "progs" directory and call it "mk_ifmts.sas". Before I create the header you will see me call the script showfmts to list out all formats that get assigned using the %allocr macro. There are none listed as none exist at this stage. To create the program header, I use the script hdr rather than "lmhdr" because this is an ordinary code member and not a local macro. You will see that the generated header is simpler.
 
Roland@DELL1 /cygdrive/c/pharma/xenuyama/tokyo/DRUG001/DRUG001C3001/24weeks/progs
$ showfmts

Roland@DELL1 /cygdrive/c/pharma/xenuyama/tokyo/DRUG001/DRUG001C3001/24weeks/progs
$ prog=mk_ifmts

Roland@DELL1 /cygdrive/c/pharma/xenuyama/tokyo/DRUG001/DRUG001C3001/24weeks/progs
$ hdr $prog
Enter program purpose: Create the increment formats
created mk_ifmts.sas

Roland@DELL1 /cygdrive/c/pharma/xenuyama/tokyo/DRUG001/DRUG001C3001/24weeks/progs
$ cat mk_ifmts.sas 
/*
/ Program      : mk_ifmts.sas
/ Author       : Roland (Roland)
/ Date         : 03-Mar-2007
/ SAS version  : 9.1.3
/ Client       : xenuyama
/ Office       : tokyo
/ Drug         : DRUG001
/ Protocol     : DRUG001C3001
/ Increment    : 24weeks
/ Purpose      : Create the increment formats
/ Notes        : 
/===============================================================================
/ Modification History:
/ -user-id --date-- --mod-id--- ---------------------purpose--------------------

/=============================================================================*/
 

Next I edit using Wordpad to add the sas code.
 
/*
/ Program      : mk_ifmts.sas
/ Author       : Roland (Roland)
/ Date         : 25-Feb-2007
/ SAS version  : 9.1.3
/ Client       : xenuyama
/ Office       : tokyo
/ Drug         : DRUG001
/ Protocol     : DRUG001C3001
/ Increment    : 24weeks
/ Purpose      : Create the increment formats
/ Notes        : 
/===============================================================================
/ Modification History:
/ -user-id --date-- --mod-id--- ---------------------purpose--------------------

/=============================================================================*/

%allocw

proc format lib=iformats; 
value $country
  "F"="France"
  "D"="Germany"
  "CH"="Switzerland"
  "J"="Japan"
  ;
value racecd 
  1="CAUCASIAN" 
  2="BLACK" 
  3="ASIAN" 
  4="HISPANIC" 
  5="OTHER" 
  ; 
value sexcd 
  1="MALE" 
  2="FEMALE" 
  ; 
value trtcd 
  1="Ambicor (1g/day)" 
  2="Betamaxin (500mg/day)" 
  3="No treatment" 
  ; 
value trtnarr 
  1="Ambicor@(1g/day)" 
  2="Betamaxin@(500mg/day)" 
  3="No@treatment" 
  ; 
value NY 
  0="NO" 
  1="YES" 
  ; 
run; 
 

Now it is time to run the code. Spectre does all its important runs in batch and sas is invoked using the script sasb and you are expected to do all your code development in batch using this same script. The reason for this is that sasb identifies what it thinks might be wrong with your code and you are expected to check on its findings. It writes its findings to a file that has the extension ".chk". Note that "sasb" will recognise your exported variable "prog" so I don't have to supply a program name as a parameter to the sasb script.

I've already debugged the code so I know it will run without errors or warnings. Watch me run the code and use "showfmts" again to see what formats have been created.
 
Roland@DELL1 /cygdrive/c/pharma/xenuyama/tokyo/DRUG001/DRUG001C3001/24weeks/progs
$ sasb
sas program "mk_ifmts" ended with return code 0:
0 ERROR(s)
0 WARNING(s)

Roland@DELL1 /cygdrive/c/pharma/xenuyama/tokyo/DRUG001/DRUG001C3001/24weeks/progs
$ showfmts
$COUNTRY
NY
RACECD
SEXCD
TRTCD
TRTNARR

Roland@DELL1 /cygdrive/c/pharma/xenuyama/tokyo/DRUG001/DRUG001C3001/24weeks/progs

The "showfmts" script has listed all the formats that are assigned by the %allocr script in alphabetical order. To see an individual format, use the showfmt script ("showfmts" but without the "s" at the end). Note that for character formats that start with a "$" the dollar sign must be "escaped" using a backslash. This is because the Unix or Cygwin shell will think it is a variable that it is required to resolve just like "$prog" so you have to stop it from resolving in this way. I will display the "racecd" format and the "$country" format.
 
Roland@DELL1 /cygdrive/c/pharma/xenuyama/tokyo/DRUG001/DRUG001C3001/24weeks/progs
$ showfmt racecd
1                       CAUCASIAN
2                       BLACK
3                       ASIAN
4                       HISPANIC
5                       OTHER

Roland@DELL1 /cygdrive/c/pharma/xenuyama/tokyo/DRUG001/DRUG001C3001/24weeks/progs
$ showfmt \$country
CH                      Switzerland
D                       Germany
F                       France
J                       Japan

Roland@DELL1 /cygdrive/c/pharma/xenuyama/tokyo/DRUG001/DRUG001C3001/24weeks/progs

Time to do a "find ." to see what stage we have reached. Remember that the ".chk" file was created by "sasb" with its findings from the sas log. It will be empty in this case.
 
Roland@DELL1 /cygdrive/c/pharma/xenuyama/tokyo/DRUG001/DRUG001C3001/24weeks/progs
$ cd /cygdrive/c/pharma

Roland@DELL1 /cygdrive/c/pharma
$ find .
.
./xenuyama
./xenuyama/formats
./xenuyama/macros
./xenuyama/tokyo
./xenuyama/tokyo/DRUG001
./xenuyama/tokyo/DRUG001/DRUG001C3001
./xenuyama/tokyo/DRUG001/DRUG001C3001/24weeks
./xenuyama/tokyo/DRUG001/DRUG001C3001/24weeks/data
./xenuyama/tokyo/DRUG001/DRUG001C3001/24weeks/data/analysis
./xenuyama/tokyo/DRUG001/DRUG001C3001/24weeks/data/derived
./xenuyama/tokyo/DRUG001/DRUG001C3001/24weeks/data/raw
./xenuyama/tokyo/DRUG001/DRUG001C3001/24weeks/formats
./xenuyama/tokyo/DRUG001/DRUG001C3001/24weeks/formats/formats.sas7bcat
./xenuyama/tokyo/DRUG001/DRUG001C3001/24weeks/macros
./xenuyama/tokyo/DRUG001/DRUG001C3001/24weeks/macros/allocr.sas
./xenuyama/tokyo/DRUG001/DRUG001C3001/24weeks/macros/allocw.sas
./xenuyama/tokyo/DRUG001/DRUG001C3001/24weeks/progs
./xenuyama/tokyo/DRUG001/DRUG001C3001/24weeks/progs/mk_ifmts.chk
./xenuyama/tokyo/DRUG001/DRUG001C3001/24weeks/progs/mk_ifmts.log
./xenuyama/tokyo/DRUG001/DRUG001C3001/24weeks/progs/mk_ifmts.sas
./xenuyama/tokyo/DRUG001/DRUG001C3001/24weeks/progs/silly_sas_program.sas
./xenuyama/tokyo/DRUG001/DRUG001C3001/formats
./xenuyama/tokyo/DRUG001/DRUG001C3001/macros
./xenuyama/tokyo/DRUG001/formats
./xenuyama/tokyo/DRUG001/macros
./xenuyama/tokyo/formats
./xenuyama/tokyo/macros

Roland@DELL1 /cygdrive/c/pharma

Creating the derived datasets

The programs that create the derived datasets will most definitely be part of the final Spectre run. In order to be recognised by Spectre as derived dataset programs they have to follow a naming convention which is that they must start with "d" (for "derived") or "s" (for "stats") followed by a two digit number and an underscore such as "d01_", "d02_", "s01_". Programs will be run by Spectre in alphabetical order so you have to choose the numbers you use in the program name to give you the correct order run. This is explained in detail on this page.

I am going to build a "demog" dataset and an "adv" dataset and place them in the "derived" folder. The "adv" datasets relies on the "demog" dataset so I will name the "demog" program as d01_demog and the adv program as d02_adv so they run in the correct order. I have no real data so this is generated test data. I borrowed some code from the "Creating Test Datasets" page that you can link to here.

First I will generate the headers.
 
Roland@DELL1 /cygdrive/c/pharma
$ cd $xyprogs

Roland@DELL1 /cygdrive/c/pharma/xenuyama/tokyo/DRUG001/DRUG001C3001/24weeks/progs
$ prog=d01_demog

Roland@DELL1 /cygdrive/c/pharma/xenuyama/tokyo/DRUG001/DRUG001C3001/24weeks/progs
$ hdr $prog
Enter program purpose: Build the demog dataset
created d01_demog.sas

Roland@DELL1 /cygdrive/c/pharma/xenuyama/tokyo/DRUG001/DRUG001C3001/24weeks/progs
$ hdr d02_adv
Enter program purpose: Build the adv dataset
created d02_adv.sas

Roland@DELL1 /cygdrive/c/pharma/xenuyama/tokyo/DRUG001/DRUG001C3001/24weeks/progs

Now I add the sas code using Wordpad and here are the two code members..
 
/*
/ Program      : d01_demog.sas
/ Author       : Roland (Roland)
/ Date         : 03-Mar-2007
/ SAS version  : 9.1.3
/ Client       : xenuyama
/ Office       : tokyo
/ Drug         : DRUG001
/ Protocol     : DRUG001C3001
/ Increment    : 24weeks
/ Purpose      : Build the demog dataset
/ Notes        : 
/===============================================================================
/ Modification History:
/ -user-id --date-- --mod-id--- ---------------------purpose--------------------

/=============================================================================*/

%allocw

data der.demog; 
  informat dob date7. 
  trtcd sexcd racecd weight height 
  patno invid sitecd fascd comma13.; 
  input patno invid sitecd fascd dob 
  trtcd sexcd racecd weight height; 
  age=%age(dob,"01jan2006"d); 
  format dob date9. sexcd sexcd. racecd racecd. 
  trtcd trtcd. weight height 5.1 age 3. 
  fascd ny.; 
  label patno="PATIENT NUMBER" 
        invid="INVESTIGATOR ID" 
        sitecd="SITE CODE" 
        fascd="FULL ANALYSIS SET (N/Y)" 
        dob="DATE OF BIRTH" 
        trtcd="TREATMENT REGIMEN" 
        sexcd="GENDER CODE" 
        racecd="RACE CODE" 
        weight="WEIGHT (KG)" 
        height="HEIGHT (CM)" 
        age="AGE (YEARS)" 
        ; 
cards; 
100 1000 10 1 10oct85 1 1 1 78.1 200 
101 1000 10 1 20nov89 2 2 2 65.5 175 
102 1000 10 1 10oct75 1 1 1 79.6 212 
103 1000 10 0 20nov79 2 2 3 75.3 186 
200 2000 20 1 10oct65 1 1 1 78.1 200 
201 2000 20 1 20nov69 2 2 3 65.5 175 
202 2000 20 1 10oct85 1 1 1 79.6 212 
203 2000 20 1 20nov89 2 2 5 75.3 186 
300 3000 30 1 10oct75 1 1 2 78.1 200 
301 3000 30 1 20nov79 2 2 2 65.5 175 
302 3000 30 0 10oct65 1 1 1 79.6 212 
303 3000 30 1 20nov69 2 2 3 75.3 186 
400 4000 40 1 10oct85 1 1 1 78.1 200 
401 4000 40 1 20nov89 2 2 2 65.5 175
402 4000 40 0 10oct75 1 1 1 79.6 212 
403 4000 40 1 20may79 2 2 3 75.3 186 
404 4000 40 1 18jun70 1 1 3 76.6 190 
500 5000 50 1 10oct85 2 1 1 78.1 200 
501 5000 50 1 20nov89 1 2 2 65.5 175 
502 5000 50 0 10oct75 2 1 1 79.6 212 
503 5000 50 1 20may79 1 2 3 75.3 186 
901 9000 90 0 13may78 3 2 2 74.5 183 

run;
 


 
/*
/ Program      : d02_adv.sas
/ Author       : Roland (Roland)
/ Date         : 03-Mar-2007
/ SAS version  : 9.1.3
/ Client       : xenuyama
/ Office       : tokyo
/ Drug         : DRUG001
/ Protocol     : DRUG001C3001
/ Increment    : 24weeks
/ Purpose      : Build the adv dataset
/ Notes        : 
/===============================================================================
/ Modification History:
/ -user-id --date-- --mod-id--- ---------------------purpose--------------------

/=============================================================================*/

%allocw

data adv; 
  length amsoc ampt $ 60; 
  amsoc="Gastrointestinal disorders"; 
  ampt="Abdominal pain NOS";output; 
  ampt="Constipation";output; 
  ampt="Diarrhoea NOS";output; 
  ampt="Nausea";output; 
  ampt="Vomiting NOS";output; 
  amsoc="General disorders and administration site conditions"; 
  ampt="Chest pain";output; 
  ampt="Pain NOS";output; 
  amsoc="Musculoskeletal and connective tissue disorders"; 
  ampt="Back pain";output; 
  ampt="Pain in extremity";output; 
  amsoc="Nervous system disorders"; 
  ampt="Headache";output; 
  ampt="Tremor";output; 
  amsoc="Psychiatric disorders"; 
  ampt="Anxiety";output; 
  ampt="Insomnia";output; 
  amsoc="Respiratory, thoracic and mediastinal disorders"; 
  ampt="Cough";output; 
  ampt="Dyspnoea";output; 
  amsoc="Vascular disorders"; 
  ampt="Hypertension NOS";output; 
  ampt="Hypotension NOS";output; 
run; 
data der.adv; 
  do i=1 to nobsdem; 
    set der.demog(keep=patno invid fascd) point=i nobs=nobsdem; 
    do j=5 to ceil(ranuni(111)*30); 
      ptr=ceil(ranuni(222)*nobsadv); 
      set adv point=ptr nobs=nobsadv; 
      output; 
    end; 
  end; 
  stop; 
  drop j; 
run; 
 

Now I'll run the code.
 
Roland@DELL1 /cygdrive/c/pharma/xenuyama/tokyo/DRUG001/DRUG001C3001/24weeks/progs
$ echo $prog
d01_demog

Roland@DELL1 /cygdrive/c/pharma/xenuyama/tokyo/DRUG001/DRUG001C3001/24weeks/progs
$ sasb
sas program "d01_demog" ended with return code 0:
0 ERROR(s)
0 WARNING(s)

Roland@DELL1 /cygdrive/c/pharma/xenuyama/tokyo/DRUG001/DRUG001C3001/24weeks/progs
$ sasb d02_adv
sas program "d02_adv" ended with return code 0:
0 ERROR(s)
0 WARNING(s)

Roland@DELL1 /cygdrive/c/pharma/xenuyama/tokyo/DRUG001/DRUG001C3001/24weeks/progs
$

The programs ran without any problems. Time for another "find ." from the pharma directory to see what we have now.
 
Roland@DELL1 /cygdrive/c/pharma/xenuyama/tokyo/DRUG001/DRUG001C3001/24weeks/progs
$ cd /cygdrive/c/pharma

Roland@DELL1 /cygdrive/c/pharma
$ find .
.
./mk_ifmts.sas
./xenuyama
./xenuyama/formats
./xenuyama/macros
./xenuyama/tokyo
./xenuyama/tokyo/DRUG001
./xenuyama/tokyo/DRUG001/DRUG001C3001
./xenuyama/tokyo/DRUG001/DRUG001C3001/24weeks
./xenuyama/tokyo/DRUG001/DRUG001C3001/24weeks/data
./xenuyama/tokyo/DRUG001/DRUG001C3001/24weeks/data/analysis
./xenuyama/tokyo/DRUG001/DRUG001C3001/24weeks/data/derived
./xenuyama/tokyo/DRUG001/DRUG001C3001/24weeks/data/derived/adv.sas7bdat
./xenuyama/tokyo/DRUG001/DRUG001C3001/24weeks/data/derived/demog.sas7bdat
./xenuyama/tokyo/DRUG001/DRUG001C3001/24weeks/data/raw
./xenuyama/tokyo/DRUG001/DRUG001C3001/24weeks/formats
./xenuyama/tokyo/DRUG001/DRUG001C3001/24weeks/formats/formats.sas7bcat
./xenuyama/tokyo/DRUG001/DRUG001C3001/24weeks/macros
./xenuyama/tokyo/DRUG001/DRUG001C3001/24weeks/progs
./xenuyama/tokyo/DRUG001/DRUG001C3001/24weeks/progs/allocr.sas
./xenuyama/tokyo/DRUG001/DRUG001C3001/24weeks/progs/allocw.sas
./xenuyama/tokyo/DRUG001/DRUG001C3001/24weeks/progs/d01_demog.chk
./xenuyama/tokyo/DRUG001/DRUG001C3001/24weeks/progs/d01_demog.log
./xenuyama/tokyo/DRUG001/DRUG001C3001/24weeks/progs/d01_demog.sas
./xenuyama/tokyo/DRUG001/DRUG001C3001/24weeks/progs/d02_adv.chk
./xenuyama/tokyo/DRUG001/DRUG001C3001/24weeks/progs/d02_adv.log
./xenuyama/tokyo/DRUG001/DRUG001C3001/24weeks/progs/d02_adv.sas
./xenuyama/tokyo/DRUG001/DRUG001C3001/24weeks/progs/mk_ifmts.chk
./xenuyama/tokyo/DRUG001/DRUG001C3001/24weeks/progs/mk_ifmts.log
./xenuyama/tokyo/DRUG001/DRUG001C3001/24weeks/progs/mk_ifmts.sas
./xenuyama/tokyo/DRUG001/DRUG001C3001/24weeks/progs/silly_sas_program.sas
./xenuyama/tokyo/DRUG001/DRUG001C3001/formats
./xenuyama/tokyo/DRUG001/DRUG001C3001/macros
./xenuyama/tokyo/DRUG001/formats
./xenuyama/tokyo/DRUG001/macros
./xenuyama/tokyo/formats
./xenuyama/tokyo/macros

Roland@DELL1 /cygdrive/c/pharma

"makerun" and "runderived"

In real life, there will be several programs that build derived datasets and it will be necessary to run the entire suite of programs from time to time using the official Spectre method. There is a script named makerun that will generate three other scripts named "runderived", "runreports" and "runsuite". It is "runderived" that will build the derived datasets. Don't worry about the error messages coming out of "makerun". It is complaining that none of the reporting components are there. I will leave that for later. It will still give us the "runderived" we need.
 
Roland@DELL1 /cygdrive/c/pharma
$ cd $xyprogs

Roland@DELL1 /cygdrive/c/pharma/xenuyama/tokyo/DRUG001/DRUG001C3001/24weeks/progs
$ makerun
Error: File "protocol.txt", the protocol information file, is missing
grep: *.titles: No such file or directory
cat: [tlg]*.titles: No such file or directory

Roland@DELL1 /cygdrive/c/pharma/xenuyama/tokyo/DRUG001/DRUG001C3001/24weeks/progs
$ ls r*
runderived  runreports  runsuite

Roland@DELL1 /cygdrive/c/pharma/xenuyama/tokyo/DRUG001/DRUG001C3001/24weeks/progs

Here is the "runderived" script it generated.
 
#!/bin/bash
# Script     : runderived
# Author     : This script was automatically generated by the "makerun" script.
# Date       :  3-Mar-2007 at 07:03:06
# Client     : xenuyama
# Office     : tokyo
# Drug       : DRUG001
# Protocol   : DRUG001C3001
# Inc        : 24weeks
# Purpose    : To run the programs that build the derived datasets
# SubScripts : crtitlesds
# Notes      : If you edit this script to limit the number of datasets built
#              then note that there is a delete of all derived datasets in the
#              der. and stat. libraries near the start and all programs .log, .lst
#              and .chk members are deleted using the "rem" script. You should
#              comment out the "rem" lines that do not apply by putting a hash in
#              front of these commands as is the case with all the lines in this
#              header. It is recommended that for interim runs, you comment out the
#              lines that delete all the stats and der datasets.
#
#              Note that this script was generated by the "makerun" script.
#              Next time "makerun" is run, it will overwrite this member.
#
#              Note that to run this script you must use the command exactly
#              as shown in the usage notes below with the study programs
#              directory the current directory
#
# Usage:       ./runderived 1>runderived.log 2>runderived.err
#

# Define error exit routine
errorexit () {

  # email the user telling them the job ended due to errors
  msg="An error forced the derived datasets build script to end"
  iam=$(whoami)
  sendto=$(emailaddr $iam)

  # Use "ssmtp" for Cygwin and "mailx" for Unix
  if [ -n "$CYGWIN" ] ; then
/usr/sbin/ssmtp -t << --END--
To: $sendto
Subject: $msg

$msg
--END--

  else
    echo "$msg" | mailx -s "$msg" $sendto
  fi

  # say when the script ended
  echo "This script ended due to errors at $(date)"
  echo "This script ended due to errors at $(date)" 1>&2
  exit 2
}
 

# identify user
iam=$(whoami)
 

# say who is running this script and what date and time
echo "This script was started by $iam ($(getname $iam)) on $(date)"
echo "This script was started by $iam ($(getname $iam)) on $(date)" 1>&2
 
 

# Delete the "der" and "stat" derived datasets so long
# as they have group write permission.
rem /cygdrive/c/pharma/dat/tokyo/DRUG001/DRUG001C3001/der/progs/*.sas7bdat
rem /cygdrive/c/pharma/dat/tokyo/DRUG001/DRUG001C3001/stat/progs/*.sas7bdat
 

# Re-create the titles and protocol datasets
crtitlesds
 

# For all programs, delete the .log, .lst and .chk if they exist
# and there is group write permission.
rm -f d01_demog.log d01_demog.lst d01_demog.chk
rm -f d02_adv.log d02_adv.lst d02_adv.chk
 

# Run all programs using sasb and exit if a
# non-zero return code is detected.
sasb d01_demog
if [ $? -gt 1 ] ; then errorexit ; fi
sasb d02_adv
if [ $? -gt 1 ] ; then errorexit ; fi
 

# cat all the .chk files onto an empty runderived.chk
rm -f runderived.chk
cat d01_demog.chk >> runderived.chk
cat d02_adv.chk >> runderived.chk
 

# email the user telling them the job has ended
msg="the derived datasets build script has finished"
iam=$(whoami)
sendto=$(emailaddr $iam)

# Use "ssmtp" for Cygwin and "mailx" for Unix
if [ -n "$CYGWIN" ] ; then
/usr/sbin/ssmtp -t << --END--
To: $sendto
Subject: $msg

$msg
--END--
else
  echo "$msg" | mailx -s "$msg" $sendto
fi
 

# say when the script ended
echo "This script finished at $(date)"
echo "This script finished at $(date)" 1>&2
 

Now I am going to run "runderived" You will see the same error messages as before due to the reporting components being missing. It will write to both standard output and standard error so you will see two start and finish messages.
 
Roland@DELL1 /cygdrive/c/pharma/xenuyama/tokyo/DRUG001/DRUG001C3001/24weeks/progs
$ ./runderived
This script was started by Roland (Roland) on Sat Mar  3 07:07:46 WEST 2007
This script was started by Roland (Roland) on Sat Mar  3 07:07:46 WEST 2007
Error: File "protocol.txt", the protocol information file, is missing
grep: *.titles: No such file or directory
cat: [tlg]*.titles: No such file or directory
sas program "d01_demog" ended with return code 0:
0 ERROR(s)
0 WARNING(s)
sas program "d02_adv" ended with return code 0:
0 ERROR(s)
0 WARNING(s)
This script finished at Sat Mar  3 07:07:56 WEST 2007
This script finished at Sat Mar  3 07:07:56 WEST 2007

Roland@DELL1 /cygdrive/c/pharma/xenuyama/tokyo/DRUG001/DRUG001C3001/24weeks/progs

You will see that it found and ran "d01_demog" and "d02_adv" and did it in the correct order. Normally the output from "runderived" is sent to a "log" file and an "err" file but I wanted you to see all the messages as they were coming out. I'll run it again the way it is supposed to be run and "cat" the "log" and "err" file. You will see that all the useful stuff is written to the "err" file.
 
Roland@DELL1 /cygdrive/c/pharma/xenuyama/tokyo/DRUG001/DRUG001C3001/24weeks/progs
$ ./runderived 1>runderived.log 2>runderived.err

Roland@DELL1 /cygdrive/c/pharma/xenuyama/tokyo/DRUG001/DRUG001C3001/24weeks/progs
$ cat runderived.log
This script was started by Roland (Roland) on Sat Mar  3 07:08:54 WEST 2007
This script finished at Sat Mar  3 07:09:03 WEST 2007

Roland@DELL1 /cygdrive/c/pharma/xenuyama/tokyo/DRUG001/DRUG001C3001/24weeks/progs
$ cat runderived.err
This script was started by Roland (Roland) on Sat Mar  3 07:08:54 WEST 2007
Error: File "protocol.txt", the protocol information file, is missing
grep: *.titles: No such file or directory
cat: [tlg]*.titles: No such file or directory
sas program "d01_demog" ended with return code 0:
0 ERROR(s)
0 WARNING(s)
sas program "d02_adv" ended with return code 0:
0 ERROR(s)
0 WARNING(s)
This script finished at Sat Mar  3 07:09:03 WEST 2007

Roland@DELL1 /cygdrive/c/pharma/xenuyama/tokyo/DRUG001/DRUG001C3001/24weeks/progs

protocol.txt

Normally, before any programming starts in a programs directory, the Spectre administrator creates a file named "protocol.txt" that contains essential information about the protocol. The error message coming out of "makerun" and "runderived" was about this file being missing. The file could not be found so this was assumed to be an error. The reporting programs rely on it. I am introducing it here, at this later stage, as I want to explain to you how it links in with the reporting programs. The reporting programs need to know the paper size and the margins to be left around the edges to work out the linesize and pagesize for the sas programs. These are set up in this "protocol.txt" file. Also the allowed populations and the labels they equate to are set there. Another thing needed is the client style to be used for setting up the tables and listings header lines. Each client will have their own style. Spectre allows for any number of client styles. The client style I will be using is "xy" for the client "Xenuyama". There is a %titles macro that you will be calling in your reporting programs to set up the titles but it only starts this process. The rest must be done by the client titles macro which, because I set the style to "xy", will be the macro %xytitles.

To create the "protocol.txt" file a script needs to be run. You know what -- I have forgotten the name of it! But that is not a problem. All Spectre scripts and macros can be viewed in the terminal window. The command I need to find this script is "showme scripts" where I will be shown the complete list of scripts and their purposes. I type in the command as you see below.
 
Roland@DELL1 /cygdrive/c/pharma/xenuyama/tokyo/DRUG001/DRUG001C3001/24weeks/progs
$ showme scripts

And then my terminal window looks like the following and I can scroll up and down and find the script I want.
 
Index of members in this directory with standard headers
========================================================
(this list was generated by the crindex script)

a4lsps             - Calculate and display linesize and pagesize values for different
                     layouts based on A4 paper and margins.

                     Usage: a4lsps -l 1.0 -r 1.0 -t 1.0 -b 1.0

a4ps               - For paged adhoc reports that are not part of the reporting
                     system, create an A4 postscript file (and optionally print it).

                     Usage: a4ps file.lst > file.ps
                     a4ps file1.lst file2.lis subdir/file3.lst > file.ps
                     a4ps -p john file.lst
                     a4ps -p mika file1.lst file2.lst
                     a4ps -t 0.75 -p john file.lst
                     a4ps -b 0.5 -s 2 -e 3 -p john file.lst

a4ps2pdf           - To convert an A4 postscript file to a pdf

                     Usage: a4ps2pdf file.ps file.pdf
                     a4ps2pdf file.ps
                     a4ps2pdf -u file.ps   # creates uncompressed pdf

alltitles          - Production script to collect all .titles files together and put
                     in ALL.TITLES

                     Usage: alltitles

antigrep           - To list all files that DO NOT contain a specified string

                     Usage: antigrep 'FG_21_08' *.sas
 

badchars           - Show bad characters (not clean 7 bit) in the input stream

                     Usage: badlines file.ext | badchars
 

baddrug            - To list which SAS programs do not have a correct drug name
                     in the standard header.

                     Usage: baddrug
 

badinc             - To list which SAS programs do not have a correct increment
                     in the standard header.

/cygdrive/c/spectre/scripts/@index.txt 

I'll scroll up and down until I find this script. Here it is in the middle of the page.
 

                     Usage: contentsl adv
                     contentsl adv acct
                     contentsl    # all datasets are listed

contentsl_win      - To list the contents (in long form) of one or more SAS datasets
                     (or a whole library) in the current directory (uses SAS).

                     Usage: contentsl_win adv
                     contentsl_win adv acct
                     contentsl_win    # all datasets are listed

crindex            - To create an index of macros or scripts with standard headers
                     (uses SAS).

                     Usage: crindex * > @index.txt
                     crindex *.sas > @index.txt

crindex_win        - To create an index of macros or scripts with standard headers
                     (uses SAS).

                     Usage: crindex_win * > @index.txt
                     crindex_win *.sas > @index.txt

crprottmpl         - Production script to create file "protocol.template" in the study
                     programs directory.

                     Usage: crprottmpl

crtitlesds         - Production script to create der.titles dataset from individual
                     .titles files and der.protocol dataset from protocol.txt file
                     (uses SAS).

                     Usage: crtitlesds

crtitlesds_win     - Production script to create der.titles dataset from individual
                     .titles files and der.protocol dataset from protocol.txt file
                     (uses SAS).

                     Usage: crtitlesds_win

crtitlestmpl       - Production script to create file "titles.template" in the study
                     programs directory.

                     Usage: crtitlestmpl

dashes             - To list files that have spanning dashed lines in them

                     Usage: dashes *.lis
:

The script I need is named crprottmpl. It creates "protocol.template" which has to be copied across as "protocol.txt" and edited.

This display, where I can scroll up and down in my terminal window, has been created by an editor named "less". To get out of "less" and return to the terminal, press the "q" key.

Now I am back in the terminal window. I'll run the "crprottmpl" script and move "procotol.template" to "protocol.txt".
 
Roland@DELL1 /cygdrive/c/pharma/xenuyama/tokyo/DRUG001/DRUG001C3001/24weeks/progs
$ crprottmpl

Roland@DELL1 /cygdrive/c/pharma/xenuyama/tokyo/DRUG001/DRUG001C3001/24weeks/progs
$ ls pro*
protocol.template

Roland@DELL1 /cygdrive/c/pharma/xenuyama/tokyo/DRUG001/DRUG001C3001/24weeks/progs
$ mv protocol.template protocol.txt 

Roland@DELL1 /cygdrive/c/pharma/xenuyama/tokyo/DRUG001/DRUG001C3001/24weeks/progs
$ ls pro*
protocol.txt

Roland@DELL1 /cygdrive/c/pharma/xenuyama/tokyo/DRUG001/DRUG001C3001/24weeks/progs

This is the "protocol.txt" file I have to edit. I've reduced the text size so it hopefully won't wrap in your browser.
 
#===========================================================================================================================================
# Template for       Make a copy of this in the programs directory and call it "protocol.txt".
# protocol.txt       This file contains the list of protocol details that will be written to protocol dataset.
#
#
# This member was generated by the script "crprottmpl" for:
#
# CLIENT: xenuyama
# OFFICE: tokyo
# DRUG: DRUG001
# STUDY: DRUG001C3001
# INC: 24weeks
#
# DATE: 03-Mar-2007
#
#===================== THE LINES BELOW THAT START WITH A # ARE A GUIDE TO TELL YOU HOW TO FILL IN THE INFORMATION ==========================
#
# drugname: FKXYZ (XXXXX)                   (this information will appear in the headers)
#
# protocol: Protocol No. XY-XXX-YY-ZZ       (this information will appear in the headers)
#
# report: Report No. XYZZ-XXX-YY, Draft version,     (this information will appear in the headers)
#
# titlestyle: xy    Set this to the prefix of the client titles macro
#
# dflayout: p10     Default layout to use when no layout is specified in the titles member. This must be one of the allowed
#                   layouts as listed in "titles.template".
#
# dfllayout: l10    Default landscape layout when only "l" is specified as the layout in the titles member.
#
# dfplayout: p10    Default portrait layout when only "p" is specified as the layout in the titles member.
#
# dfltlayout: lt10  Default landscape tight (i.e. lines are closer together) layout when only "lt" is specified as the layout in the titles member.
#
# dfptlayout: pt10  Default portrait tight (i.e. lines are closer together) layout when only "pt" is specified as the layout in the titles member.
#
# paper: A4         Must be either "A4" or "Letter"
#
# margin: 1.0       All-round page margin in inches
#
# lmargin:          Left margin in inches if different from all-round margin value assigned to margin: (left in sense of portrait orientation).
#                   Leave this blank if there is the same all-round margin.
#
# rmargin:          Right margin in inches if different from all-round margin value assigned to margin: (right in sense of portrait orientation).
#                   Leave this blank if there is the same all-round margin.
#
# tmargin:          Top margin in inches if different from all-round margin value assigned to margin: (top in sense of portrait orientation).
#                   Leave this blank if there is the same all-round margin.
#
# bmargin:          Bottom margin in inches if different from all-round margin value assigned to margin: (bottom in sense of portrait orientation).
#                   Leave this blank if there is the same all-round margin.
#
# clean: clean in (0,1)  Selection criteria for selecting clean/unclean patients from the acct dataset.
#
# pop1: FAS                             First set of analysis set abbreviation and its label. What the programmer puts in their .titles file 
# poplabel1: Full Analysis Set          for the analysis set will be checked against the list you put in this member.
#
# pop2:                                 Second set of analysis set abbreviation and its label.
# poplabel2:                            There are a maximum of 9 sets allowed.
#
#============================================================================================================================================

drugname: XYZ (XXXXX)
protocol: Protocol No. XY-XXX-YY-ZZ
report: Report No. XYZZ-XXX-YY, Draft version, 
titlestyle: xy
dflayout: p10
dfllayout: l10
dfplayout: p10
dfltlayout: lt10
dfptlayout: pt10
paper: A4
margin: 1.0
lmargin: 
rmargin: 
tmargin: 
bmargin: 
clean: 
pop1: FAS
poplabel1: Full Analysis Set
pop2: PPS
poplabel2: Per-Protocol Set
pop3: ITT
poplabel3: Intent-to-Treat
pop4: SAF
poplabel4: Safety population
pop5: 
poplabel5: 
pop6: 
poplabel6: 
pop7: 
poplabel7: 
pop8: 
poplabel8: 
pop9: 
poplabel9: 
 

This is the information part of the file after making the changes. I will allow most of them to default.
 
drugname: DRUG001
protocol: Protocol No. XY-XXX-YY-ZZ
report: Report No. XYZZ-XXX-YY, Draft version, 
titlestyle: xy
dflayout: p10
dfllayout: l10
dfplayout: p10
dfltlayout: lt10
dfptlayout: pt10
paper: A4
margin: 1.0
lmargin: 
rmargin: 
tmargin: 
bmargin: 
clean: 
pop1: FAS
poplabel1: Full Analysis Set
pop2: PPS
poplabel2: Per-Protocol Set
pop3: ITT
poplabel3: Intent to Treat
pop4: 
poplabel4: 
pop5: 
poplabel5: 
pop6: 
poplabel6:
pop7: 
poplabel7: 
pop8: 
poplabel8: 
pop9: 
poplabel9: 

Once this file has been set up it has to be activated. This is done with the same script that activates report program titles members, as will be explained later. This script is named crtitlesds (create titles dataset). I will run it now. Again, it will complain that there are no "titles" members.
 
Roland@DELL1 /cygdrive/c/pharma/xenuyama/tokyo/DRUG001/DRUG001C3001/24weeks/progs
$ crtitlesds
grep: *.titles: No such file or directory
cat: [tlg]*.titles: No such file or directory

Roland@DELL1 /cygdrive/c/pharma/xenuyama/tokyo/DRUG001/DRUG001C3001/24weeks/progs

The way this protocol file has been activated is to create a sas dataset named "protocol" in the derived dataset folder. To see the contents of this dataset then use the showprot script. This will create an output that looks like the "protocol.txt" file but in reality it has read the "der.protocol" dataset and is just displaying it in the same style as the "protocol.txt" file.
 
Roland@DELL1 /cygdrive/c/pharma/xenuyama/tokyo/DRUG001/DRUG001C3001/24weeks/progs
$ showprot

Drugname: DRUG001
Protocol: Protocol No. XY-XXX-YY-ZZ
Report: Report No. XYZZ-XXX-YY, Draft version,
Titlestyle: xy
Paper: A4
Lmargin: 1.0
Rmargin: 1.0
Tmargin: 1.0
Bmargin: 1.0
Dflayout: P10
Dfllayout: L10
Dfplayout: P10
Dfltlayout: LT10
Dfptlayout: PT10
clean: 
pop1: FAS
poplabel1: Full Analysis Set
pop2: PPS
poplabel2: Per-Protocol Set
pop3: ITT
poplabel3: Intent to Treat
pop4: 
poplabel4: 
pop5: 
poplabel5: 
pop6: 
poplabel6: 
pop7: 
poplabel7: 
pop8: 
poplabel8: 
pop9:
poplabel9: 
 

Roland@DELL1 /cygdrive/c/pharma/xenuyama/tokyo/DRUG001/DRUG001C3001/24weeks/progs

It is time for another "find ." from the pharma directory. Look out for the "protocol" dataset. There will be a "titles" dataset as well but with nothing in it.
 
Roland@DELL1 /cygdrive/c/pharma/xenuyama/tokyo/DRUG001/DRUG001C3001/24weeks/progs
$ cd /cygdrive/c/pharma

Roland@DELL1 /cygdrive/c/pharma
$ find .
.
./mk_ifmts.sas
./xenuyama
./xenuyama/formats
./xenuyama/macros
./xenuyama/tokyo
./xenuyama/tokyo/DRUG001
./xenuyama/tokyo/DRUG001/DRUG001C3001
./xenuyama/tokyo/DRUG001/DRUG001C3001/24weeks
./xenuyama/tokyo/DRUG001/DRUG001C3001/24weeks/data
./xenuyama/tokyo/DRUG001/DRUG001C3001/24weeks/data/analysis
./xenuyama/tokyo/DRUG001/DRUG001C3001/24weeks/data/derived
./xenuyama/tokyo/DRUG001/DRUG001C3001/24weeks/data/derived/adv.sas7bdat
./xenuyama/tokyo/DRUG001/DRUG001C3001/24weeks/data/derived/demog.sas7bdat
./xenuyama/tokyo/DRUG001/DRUG001C3001/24weeks/data/derived/protocol.sas7bdat
./xenuyama/tokyo/DRUG001/DRUG001C3001/24weeks/data/derived/titles.sas7bdat
./xenuyama/tokyo/DRUG001/DRUG001C3001/24weeks/data/raw
./xenuyama/tokyo/DRUG001/DRUG001C3001/24weeks/formats
./xenuyama/tokyo/DRUG001/DRUG001C3001/24weeks/formats/formats.sas7bcat
./xenuyama/tokyo/DRUG001/DRUG001C3001/24weeks/macros
./xenuyama/tokyo/DRUG001/DRUG001C3001/24weeks/progs
./xenuyama/tokyo/DRUG001/DRUG001C3001/24weeks/progs/ALL.TITLES
./xenuyama/tokyo/DRUG001/DRUG001C3001/24weeks/progs/allocr.sas
./xenuyama/tokyo/DRUG001/DRUG001C3001/24weeks/progs/allocw.sas
./xenuyama/tokyo/DRUG001/DRUG001C3001/24weeks/progs/d01_demog.chk
./xenuyama/tokyo/DRUG001/DRUG001C3001/24weeks/progs/d01_demog.log
./xenuyama/tokyo/DRUG001/DRUG001C3001/24weeks/progs/d01_demog.sas
./xenuyama/tokyo/DRUG001/DRUG001C3001/24weeks/progs/d02_adv.chk
./xenuyama/tokyo/DRUG001/DRUG001C3001/24weeks/progs/d02_adv.log
./xenuyama/tokyo/DRUG001/DRUG001C3001/24weeks/progs/d02_adv.sas
./xenuyama/tokyo/DRUG001/DRUG001C3001/24weeks/progs/mk_ifmts.chk
./xenuyama/tokyo/DRUG001/DRUG001C3001/24weeks/progs/mk_ifmts.log
./xenuyama/tokyo/DRUG001/DRUG001C3001/24weeks/progs/mk_ifmts.sas
./xenuyama/tokyo/DRUG001/DRUG001C3001/24weeks/progs/protocol.txt
./xenuyama/tokyo/DRUG001/DRUG001C3001/24weeks/progs/runderived
./xenuyama/tokyo/DRUG001/DRUG001C3001/24weeks/progs/runderived.chk
./xenuyama/tokyo/DRUG001/DRUG001C3001/24weeks/progs/runderived.err
./xenuyama/tokyo/DRUG001/DRUG001C3001/24weeks/progs/runderived.log
./xenuyama/tokyo/DRUG001/DRUG001C3001/24weeks/progs/runreports
./xenuyama/tokyo/DRUG001/DRUG001C3001/24weeks/progs/runsuite
./xenuyama/tokyo/DRUG001/DRUG001C3001/24weeks/progs/silly_sas_program.sas
./xenuyama/tokyo/DRUG001/DRUG001C3001/24weeks/progs/work
./xenuyama/tokyo/DRUG001/DRUG001C3001/formats
./xenuyama/tokyo/DRUG001/DRUG001C3001/macros
./xenuyama/tokyo/DRUG001/formats
./xenuyama/tokyo/DRUG001/macros
./xenuyama/tokyo/formats
./xenuyama/tokyo/macros

Roland@DELL1 /cygdrive/c/pharma

"titles" members

Every report program in Spectre must have a "titles" member and in that "titles" member there must be at least one title line defined which must contain a table number/listing number/figure number These numbers must be unique so you can not have a Table 1.1 and a Listing 1.1, for example. I am going to create two table programs and a "titles" member to go with each. There is a "demog" datasets and an "adv" dataset. I want the "demog" table to be TABLE 1 and the "adv" table to be TABLE 2. I'll call the programs t_demog.sas and t_adv.sas.
 
Roland@DELL1 /cygdrive/c/pharma/xenuyama/tokyo/DRUG001/DRUG001C3001/24weeks/progs
$ prog=t_demog

Roland@DELL1 /cygdrive/c/pharma/xenuyama/tokyo/DRUG001/DRUG001C3001/24weeks/progs
$ titles
The file t_demog.titles has just been created

Roland@DELL1 /cygdrive/c/pharma/xenuyama/tokyo/DRUG001/DRUG001C3001/24weeks/progs

This is what the titles file looks like. There are a lot of instructions at the start to help you fill it out. You do not have to keep this header information. I have made the text smaller so it hopefully does not wrap in your browser.
 
#===========================================================================================================================================
# Template for titles.      Make a copy of this to go with your sas program and give it the file extension .titles such as t_meds.titles
#                           You must only have ONE set of titles in this file.
#
# This member was generated by the script "crtitlestmpl" for:
#
# CLIENT: xenuyama
# OFFICE: tokyo
# DRUG: DRUG001
# STUDY: DRUG001C3001
# INC: 24weeks
#
# DATE: 03-Mar-2007
#
#===================== THE LINES BELOW THAT START WITH A # ARE A GUIDE TO TELL YOU HOW TO FILL IN THE INFORMATION ==========================
#
# program: progname (put your program name here without the .sas extension. Case should match your program member name)
#
# layout: Leave blank to use study default or set it to l/p (landscape/portrait) [t] (tight lines) f (font size)
#         Here is a list of valid possible values: l8 l8.5 l9 l10 lt8 lt8.5 lt9 lt10 p8 pc8 p9 pt9 p10 pt10 p11 pt11
#         The preference is for p10 (portrait 10 point). If your report will not fit on the page then try l10 (landscape 10 point)
#         but if it still will not fit then try l9 and if it still will not fit then try l8. You should not go lower than an 8 point
#         font without asking for permission to do so.
#
# population: FAS, PPS, SEL etc. abbreviations. This must match one of the analysis set abbreviations in "protocol.txt".
#
# sascode: If you set this to anything, the sas program will be generated and any corresponding program you have will be overwritten.
#
# titles below: Put your titles BELOW this line. All titles will be CENTRED unless you start with a space in which case LEFT-ALIGNED.
# Table 1.2.3
# ANOTHER TITLE LINE
#  A LEFT-ALIGNED TITLE - THE FIRST SPACE WILL BE DROPPED WHEN IT IS LEFT-ALIGNED BUT EXTRA SPACES WILL BE SHOWN
# footnotes below: Put your footnotes BELOW this line. All footnotes will be LEFT-ALIGNED. Leading spaces are allowed.
# First footnote
# Second footnote
#   Third footnote indented two spaces
#
# endxxx: This line ends the titles entry. Do not specify anything after it.
#===========================================================================================================================================
program: t_demog 
layout: 
population: 
sascode: 
#################### Columns ruler for titles and footnotes -- do not exceed the maximum column for your layout ############################
#--------1---------2---------3---------4---------5---------6---------7---------8---------9---------0---------1---------2---------3---------4
titles below:
footnotes below:
endxxx:
#--------1---------2---------3---------4---------5---------6---------7---------8---------9---------0---------1---------2---------3---------4

I am going to choose a portrait 10 point font layout for the FAS (Full Analysis Set) population and give it a title of "TABLE 1". I'll strip out the comment lines so you can see it more clearly in larger text. Note that I have given it a footnote of "&_longline_". This is a spanning line of underscores that gets set up by Spectre.
 
program: t_demog 
layout: P10
population: FAS
sascode: 
titles below:
TABLE 1
DEMOGRAPHY
footnotes below:
&_longline_
endxxx:

The titles member has to be activated using the crtitlesds script. After it is activated, I can check it is there using the showtitles script. Note the warning about the program not being there yet.
 
Roland@DELL1 /cygdrive/c/pharma/xenuyama/tokyo/DRUG001/DRUG001C3001/24weeks/progs
$ crtitlesds
Warning: (crtitlesds) Titles entries exist for the following program(s) but no program yet exists
t_demog.sas

Roland@DELL1 /cygdrive/c/pharma/xenuyama/tokyo/DRUG001/DRUG001C3001/24weeks/progs
$ showtitles

Program: t_demog
Label: 
Population: FAS
Layout: P10
Sascode: 
Titles below:
TABLE 1
DEMOGRAPHY
Footnotes below:
&_longline_
 

Roland@DELL1 /cygdrive/c/pharma/xenuyama/tokyo/DRUG001/DRUG001C3001/24weeks/progs

I'll create the titles member for t_adv.sas at this point as I want to finish with the titles in this section and get on with the report code. I'll give t_adv a landscape 10 point font layout and table number 2. First I'll create the template.
 
Roland@DELL1 /cygdrive/c/pharma/xenuyama/tokyo/DRUG001/DRUG001C3001/24weeks/progs
$ prog=t_adv

Roland@DELL1 /cygdrive/c/pharma/xenuyama/tokyo/DRUG001/DRUG001C3001/24weeks/progs
$ titles
The file t_adv.titles has just been created

Roland@DELL1 /cygdrive/c/pharma/xenuyama/tokyo/DRUG001/DRUG001C3001/24weeks/progs

Next I'll edit it to give this, removing all the header instructions.
 
program: t_adv 
layout: L10
population: FAS
sascode: 
titles below:
TABLE 2
ADVERSE EVENTS
footnotes below:
&_longline_
endxxx:

Now I'll activate it.
 
Roland@DELL1 /cygdrive/c/pharma/xenuyama/tokyo/DRUG001/DRUG001C3001/24weeks/progs
$ crtitlesds
Warning: (crtitlesds) Titles entries exist for the following program(s) but no program yet exists
t_adv.sas
t_demog.sas

Roland@DELL1 /cygdrive/c/pharma/xenuyama/tokyo/DRUG001/DRUG001C3001/24weeks/progs

Reporting code members

I'll create the header for t_demog first.
 
Roland@DELL1 /cygdrive/c/pharma/xenuyama/tokyo/DRUG001/DRUG001C3001/24weeks/progs
$ prog=t_demog

Roland@DELL1 /cygdrive/c/pharma/xenuyama/tokyo/DRUG001/DRUG001C3001/24weeks/progs
$ hdr $prog
Enter program purpose: Table of demography
created t_demog.sas

Roland@DELL1 /cygdrive/c/pharma/xenuyama/tokyo/DRUG001/DRUG001C3001/24weeks/progs

Now I'll add the code. I am making the call to %unistats the simplest one possible for this demonstration. See the page about %unistats to learn more about improving the layout here.
 
/*
/ Program      : t_demog.sas
/ Author       : Roland (Roland)
/ Date         : 03-Mar-2007
/ SAS version  : 9.1.3
/ Client       : xenuyama
/ Office       : tokyo
/ Drug         : DRUG001
/ Protocol     : DRUG001C3001
/ Increment    : 24weeks
/ Purpose      : Table of demography
/ Notes        : 
/===============================================================================
/ Modification History:
/ -user-id --date-- --mod-id--- ---------------------purpose--------------------

/=============================================================================*/

%allocr

%titles

proc sort data=der.demog(where=(&_pop_.cd=1)) 
  out=demog(drop=&_pop_.cd); 
  by patno invid; 
run; 

%popfmt(demog,trtcd,uniqueid=patno invid) 

%openrep

%unistats(dsin=demog,
descstats=N Min Mean Max STD., 
varlist=sexcd racecd age weight height)

%closerep
 

Now I'll run the code...
 
Roland@DELL1 /cygdrive/c/pharma/xenuyama/tokyo/DRUG001/DRUG001C3001/24weeks/progs
$ sasb
sas program "t_demog" ended with return code 0:
0 ERROR(s)
0 WARNING(s)

Roland@DELL1 /cygdrive/c/pharma/xenuyama/tokyo/DRUG001/DRUG001C3001/24weeks/progs

Spectre sends the reporting program output to ".lis" files when you are between the %openrep and %closerep macros and not the ".lst" files that you are used to. This is so it can add page numbers to the listings. This leaves you free to use ".lst" output for diagnostics. Here is the contents of t_demog.lis
 
DRUG001                                                         Page 1 of 1
Protocol No. XY-XXX-YY-ZZ
Report No. XYZZ-XXX-YY, Draft version, March 3, 2007

                                  TABLE 1

                                DEMOGRAPHY
                             FULL ANALYSIS SET

___________________________________________________________________________

                                  Number of Patients (%) / Descriptive Stat

                                  Ambicor (1g/day)    Betamaxin (500mg/day)
                                       (N=9)                  (N=8)
___________________________________________________________________________

GENDER CODE
    MALE                              7 ( 77.8)              1 ( 12.5)
    FEMALE                            2 ( 22.2)              7 ( 87.5)

RACE CODE
    CAUCASIAN                         5 ( 55.6)              1 ( 12.5)
    BLACK                             2 ( 22.2)              3 ( 37.5)
    ASIAN                             2 ( 22.2)              3 ( 37.5)
    OTHER                             0 (  0.0)              1 ( 12.5)

AGE (YEARS)
    N                                 9                      8
    Min                              16.0                   16.0
    Mean                             26.3                   24.0
    Max                              40.0                   36.0
    STD.                              8.03                   8.49

WEIGHT (KG)
    N                                 9                      8
    Min                              65.5                   65.5
    Mean                             76.6                   70.8
    Max                              79.6                   78.1
    STD.                              4.36                   5.69

HEIGHT (CM)
    N                                 9                      8
    Min                             175.0                  175.0
    Mean                            197.2                  182.3
    Max                             212.0                  200.0
    STD.                             11.94                   9.00
 
 
 
 

___________________________________________________________________________

Next I'll create the header for t_adv.
 
Roland@DELL1 /cygdrive/c/pharma/xenuyama/tokyo/DRUG001/DRUG001C3001/24weeks/progs
$ prog=t_adv

Roland@DELL1 /cygdrive/c/pharma/xenuyama/tokyo/DRUG001/DRUG001C3001/24weeks/progs
$ hdr $prog
Enter program purpose: Table of adverse events
created t_adv.sas

Roland@DELL1 /cygdrive/c/pharma/xenuyama/tokyo/DRUG001/DRUG001C3001/24weeks/progs

Now I add the code. I am making the call to %npcttab the simplest one possible for this demonstration. See the page about %npcttab to learn more about improving the layout here.
 
/*
/ Program      : t_adv.sas
/ Author       : Roland (Roland)
/ Date         : 03-Mar-2007
/ SAS version  : 9.1.3
/ Client       : xenuyama
/ Office       : tokyo
/ Drug         : DRUG001
/ Protocol     : DRUG001C3001
/ Increment    : 24weeks
/ Purpose      : Table of adverse events
/ Notes        : 
/===============================================================================
/ Modification History:
/ -user-id --date-- --mod-id--- ---------------------purpose--------------------

/=============================================================================*/

%allocr

%titles

proc sort data=der.demog(where=(&_pop_.cd=1)) out=demog(drop=&_pop_.cd); 
  by patno invid; 
run; 

%popfmt(demog,trtcd,uniqueid=patno invid) 

proc sort data=der.adv out=adv; 
  by patno invid; 
run; 

data adv; 
  merge demog(in=_dem keep=patno invid trtcd) adv(in=_adv); 
  by patno invid; 
  if _dem and _adv; 
run; 

%openrep

%npcttab(dsin=adv,midlvl=amsoc,lowlvl=ampt)

%closerep
 

Now I'll run the code.
 
Roland@DELL1 /cygdrive/c/pharma/xenuyama/tokyo/DRUG001/DRUG001C3001/24weeks/progs
$ sasb
sas program "t_adv" ended with return code 0:
0 ERROR(s)
0 WARNING(s)

Roland@DELL1 /cygdrive/c/pharma/xenuyama/tokyo/DRUG001/DRUG001C3001/24weeks/progs

Here is the contents of t_adv.lis
 
DRUG001                                                                                                  Page 1 of 2
Protocol No. XY-XXX-YY-ZZ
Report No. XYZZ-XXX-YY, Draft version, March 3, 2007

                                                      TABLE 2

                                                   ADVERSE EVENTS
                                                 FULL ANALYSIS SET

____________________________________________________________________________________________________________________

                                                            Ambicor (1g/day)    Betamaxin (500mg/day)       Total
                                                                 (N=9)                  (N=8)              (N=17)
____________________________________________________________________________________________________________________

Gastrointestinal disorders
   ANY AE                                                       5 ( 55.6)              7 ( 87.5)          12 ( 70.6)
   Diarrhoea NOS                                                5 ( 55.6)              4 ( 50.0)           9 ( 52.9)
   Constipation                                                 3 ( 33.3)              4 ( 50.0)           7 ( 41.2)
   Abdominal pain NOS                                           3 ( 33.3)              3 ( 37.5)           6 ( 35.3)
   Nausea                                                       2 ( 22.2)              4 ( 50.0)           6 ( 35.3)
   Vomiting NOS                                                 2 ( 22.2)              4 ( 50.0)           6 ( 35.3)

Respiratory, thoracic and mediastinal disorders
   ANY AE                                                       5 ( 55.6)              7 ( 87.5)          12 ( 70.6)
   Dyspnoea                                                     4 ( 44.4)              6 ( 75.0)          10 ( 58.8)
   Cough                                                        3 ( 33.3)              5 ( 62.5)           8 ( 47.1)

Psychiatric disorders
   ANY AE                                                       5 ( 55.6)              6 ( 75.0)          11 ( 64.7)
   Insomnia                                                     4 ( 44.4)              5 ( 62.5)           9 ( 52.9)
   Anxiety                                                      4 ( 44.4)              3 ( 37.5)           7 ( 41.2)

Musculoskeletal and connective tissue disorders
   ANY AE                                                       5 ( 55.6)              5 ( 62.5)          10 ( 58.8)
   Pain in extremity                                            4 ( 44.4)              3 ( 37.5)           7 ( 41.2)
   Back pain                                                    4 ( 44.4)              2 ( 25.0)           6 ( 35.3)

Vascular disorders

____________________________________________________________________________________________________________________
DRUG001                                                                                                  Page 2 of 2
Protocol No. XY-XXX-YY-ZZ
Report No. XYZZ-XXX-YY, Draft version, March 3, 2007

                                                      TABLE 2

                                                   ADVERSE EVENTS
                                                 FULL ANALYSIS SET

____________________________________________________________________________________________________________________

                                                            Ambicor (1g/day)    Betamaxin (500mg/day)       Total
                                                                 (N=9)                  (N=8)              (N=17)
____________________________________________________________________________________________________________________

   ANY AE                                                       4 ( 44.4)              6 ( 75.0)          10 ( 58.8)
   Hypotension NOS                                              4 ( 44.4)              5 ( 62.5)           9 ( 52.9)
   Hypertension NOS                                             1 ( 11.1)              3 ( 37.5)           4 ( 23.5)

General disorders and administration site conditions
   ANY AE                                                       5 ( 55.6)              4 ( 50.0)           9 ( 52.9)
   Pain NOS                                                     5 ( 55.6)              4 ( 50.0)           9 ( 52.9)
   Chest pain                                                   3 ( 33.3)              2 ( 25.0)           5 ( 29.4)

Nervous system disorders
   ANY AE                                                       4 ( 44.4)              5 ( 62.5)           9 ( 52.9)
   Headache                                                     3 ( 33.3)              5 ( 62.5)           8 ( 47.1)
   Tremor                                                       3 ( 33.3)              4 ( 50.0)           7 ( 41.2)
 
 
 
 
 
 
 
 
 
 
 

____________________________________________________________________________________________________________________

Time for another "find ." from the pharma directory.
 
Roland@DELL1 /cygdrive/c/pharma/xenuyama/tokyo/DRUG001/DRUG001C3001/24weeks/progs
$ cd /cygdrive/c/pharma

Roland@DELL1 /cygdrive/c/pharma
$ find .
.
./xenuyama
./xenuyama/formats
./xenuyama/macros
./xenuyama/tokyo
./xenuyama/tokyo/DRUG001
./xenuyama/tokyo/DRUG001/DRUG001C3001
./xenuyama/tokyo/DRUG001/DRUG001C3001/24weeks
./xenuyama/tokyo/DRUG001/DRUG001C3001/24weeks/data
./xenuyama/tokyo/DRUG001/DRUG001C3001/24weeks/data/analysis
./xenuyama/tokyo/DRUG001/DRUG001C3001/24weeks/data/derived
./xenuyama/tokyo/DRUG001/DRUG001C3001/24weeks/data/derived/adv.sas7bdat
./xenuyama/tokyo/DRUG001/DRUG001C3001/24weeks/data/derived/demog.sas7bdat
./xenuyama/tokyo/DRUG001/DRUG001C3001/24weeks/data/derived/protocol.sas7bdat
./xenuyama/tokyo/DRUG001/DRUG001C3001/24weeks/data/derived/titles.sas7bdat
./xenuyama/tokyo/DRUG001/DRUG001C3001/24weeks/data/raw
./xenuyama/tokyo/DRUG001/DRUG001C3001/24weeks/formats
./xenuyama/tokyo/DRUG001/DRUG001C3001/24weeks/formats/formats.sas7bcat
./xenuyama/tokyo/DRUG001/DRUG001C3001/24weeks/macros
./xenuyama/tokyo/DRUG001/DRUG001C3001/24weeks/macros/allocr.sas
./xenuyama/tokyo/DRUG001/DRUG001C3001/24weeks/macros/allocw.sas
./xenuyama/tokyo/DRUG001/DRUG001C3001/24weeks/progs
./xenuyama/tokyo/DRUG001/DRUG001C3001/24weeks/progs/ALL.TITLES
./xenuyama/tokyo/DRUG001/DRUG001C3001/24weeks/progs/d01_demog.chk
./xenuyama/tokyo/DRUG001/DRUG001C3001/24weeks/progs/d01_demog.log
./xenuyama/tokyo/DRUG001/DRUG001C3001/24weeks/progs/d01_demog.sas
./xenuyama/tokyo/DRUG001/DRUG001C3001/24weeks/progs/d02_adv.chk
./xenuyama/tokyo/DRUG001/DRUG001C3001/24weeks/progs/d02_adv.log
./xenuyama/tokyo/DRUG001/DRUG001C3001/24weeks/progs/d02_adv.sas
./xenuyama/tokyo/DRUG001/DRUG001C3001/24weeks/progs/mk_ifmts.chk
./xenuyama/tokyo/DRUG001/DRUG001C3001/24weeks/progs/mk_ifmts.log
./xenuyama/tokyo/DRUG001/DRUG001C3001/24weeks/progs/mk_ifmts.sas
./xenuyama/tokyo/DRUG001/DRUG001C3001/24weeks/progs/protocol.txt
./xenuyama/tokyo/DRUG001/DRUG001C3001/24weeks/progs/runderived
./xenuyama/tokyo/DRUG001/DRUG001C3001/24weeks/progs/runderived.chk
./xenuyama/tokyo/DRUG001/DRUG001C3001/24weeks/progs/runderived.err
./xenuyama/tokyo/DRUG001/DRUG001C3001/24weeks/progs/runderived.log
./xenuyama/tokyo/DRUG001/DRUG001C3001/24weeks/progs/runreports
./xenuyama/tokyo/DRUG001/DRUG001C3001/24weeks/progs/runsuite
./xenuyama/tokyo/DRUG001/DRUG001C3001/24weeks/progs/silly_sas_program.sas
./xenuyama/tokyo/DRUG001/DRUG001C3001/24weeks/progs/titles.template
./xenuyama/tokyo/DRUG001/DRUG001C3001/24weeks/progs/t_adv.chk
./xenuyama/tokyo/DRUG001/DRUG001C3001/24weeks/progs/t_adv.lis
./xenuyama/tokyo/DRUG001/DRUG001C3001/24weeks/progs/t_adv.log
./xenuyama/tokyo/DRUG001/DRUG001C3001/24weeks/progs/t_adv.sas
./xenuyama/tokyo/DRUG001/DRUG001C3001/24weeks/progs/t_adv.titles
./xenuyama/tokyo/DRUG001/DRUG001C3001/24weeks/progs/t_demog.chk
./xenuyama/tokyo/DRUG001/DRUG001C3001/24weeks/progs/t_demog.lis
./xenuyama/tokyo/DRUG001/DRUG001C3001/24weeks/progs/t_demog.log
./xenuyama/tokyo/DRUG001/DRUG001C3001/24weeks/progs/t_demog.sas
./xenuyama/tokyo/DRUG001/DRUG001C3001/24weeks/progs/t_demog.titles
./xenuyama/tokyo/DRUG001/DRUG001C3001/formats
./xenuyama/tokyo/DRUG001/DRUG001C3001/macros
./xenuyama/tokyo/DRUG001/formats
./xenuyama/tokyo/DRUG001/macros
./xenuyama/tokyo/formats
./xenuyama/tokyo/macros

"makerun" and "runreports"

In real life, there will be many reporting programs and it will be necessary to run the entire suite of programs from time to time using the official Spectre method. You have already been introduced to the script named makerun that will generate the three scripts named "runderived", "runreports" and "runsuite". It is "runreports" that will create the report output. This time it will run with no error messages as everything that should be there is now in place.
 
Roland@DELL1 /cygdrive/c/pharma
$ cd $xyprogs

Roland@DELL1 /cygdrive/c/pharma/xenuyama/tokyo/DRUG001/DRUG001C3001/24weeks/progs
$ makerun

Roland@DELL1 /cygdrive/c/pharma/xenuyama/tokyo/DRUG001/DRUG001C3001/24weeks/progs

This is the contents of runreports that was generated.
 
#!/bin/bash
# Script     : runreports
# Author     : This script was automatically generated by the "makerun" script.
# Date       :  3-Mar-2007 at 07:57:06
# Client     : xenuyama
# Office     : tokyo
# Drug       : DRUG001
# Protocol   : DRUG001C3001
# Inc        : 24weeks
# Purpose    : To run the programs that create reports
# SubScripts : crtitlesds donepages
# Notes      : If you edit this script to limit the number of reports produced
#              then note that there is a delete of all programs .log, .lst, .chk
#              and .lis members using "rm". You should comment out the "rm"
#              lines that do not apply by putting a hash in front of these
#              commands as is the case with all the lines in this header.
#
#              Note that this script was generated by the "makerun" script.
#              Next time "makerun" is run, it will overwrite this member.
#
#              Note that to run this script you must use the command exactly
#              as shown in the usage notes below with the study programs
#              directory the current directory.
#
# Usage:       ./runreports 1>runreports.log 2>runreports.err
#
 

# identify user
iam=$(whoami)

# say who is running this script and what date and time
echo "This script was started by $iam ($(getname $iam)) on $(date)"
echo "This script was started by $iam ($(getname $iam)) on $(date)" 1>&2
 

# Create the titles and protocol datasets
crtitlesds
 

# Set up an environment variable for routing the output
OUTDIR=$PWD
 

# convert to a Windows path style for Cygwin
OUTDIRWIN=$(echo "$OUTDIR" | sed -e 's%^/cygdrive/%%' -e 's%\(^.\)%\1:%' -e 's%/%\\%g')

export OUTDIR OUTDIRWIN
 

# Delete the "donelist" files
rm -f $OUTDIR/donelist.txt $OUTDIR/donelist.tmp
 

# For all programs, delete the .log, .lst, .chk and .lis* if they exist
# and there is group write permission.
rm -f t_adv.log t_adv.lst t_adv.chk t_adv.lis 
rm -f t_demog.log t_demog.lst t_demog.chk t_demog.lis 
 

# Run all programs using sasb
sasb t_adv
sasb t_demog
 

# cat all the .chk files onto an empty runreports.chk
rm -f runreports.chk
cat t_adv.chk >> runreports.chk
cat t_demog.chk >> runreports.chk
 

# add number of pages and sort "donelist" into order
donepages $OUTDIR/donelist.tmp | sort > $OUTDIR/donelist.txt
 

# email the user telling them the job has ended
msg="the report production script has finished"
iam=$(whoami)
sendto=$(emailaddr $iam)

# Use "ssmtp" for Cygwin and "mailx" for Unix
if [ -n "$CYGWIN" ] ; then
/usr/sbin/ssmtp -t << --END--
To: $sendto
Subject: $msg

$msg
--END--
else
  echo "$msg" | mailx -s "$msg" $sendto
fi
 

# say when the script ended
echo "This script finished at $(date)"
echo "This script finished at $(date)" 1>&2

If you look at the "runreports" script you will see it deletes two files named "donelist.txt" and "donelist.tmp". These files do not appear in the "find ." above. This is because they are only created when "runreports" runs and not when individual users run their reporting code. What it is doing is writing a record of what reporting programs ran. At the end it will add the number of pages in each output and sorts it into order as the final "donelist.txt". This file can then be used to gather outputs in the correct order and can form the basis for creating PDF files. We are not going to go into creating PDFs on this page, though. Next I will run "runreports".
 
Roland@DELL1 /cygdrive/c/pharma/xenuyama/tokyo/DRUG001/DRUG001C3001/24weeks/progs
$ ./runreports
This script was started by Roland (Roland) on Sat Mar  3 08:00:04 WEST 2007
This script was started by Roland (Roland) on Sat Mar  3 08:00:04 WEST 2007
sas program "t_adv" ended with return code 0:
0 ERROR(s)
0 WARNING(s)
sas program "t_demog" ended with return code 0:
0 ERROR(s)
0 WARNING(s)
This script finished at Sat Mar  3 08:00:21 WEST 2007
This script finished at Sat Mar  3 08:00:21 WEST 2007

Roland@DELL1 /cygdrive/c/pharma/xenuyama/tokyo/DRUG001/DRUG001C3001/24weeks/progs

Here is a "find ." done from the pharma directory again. Note the "donelist" files that have appeared.
 
Roland@DELL1 /cygdrive/c/pharma/xenuyama/tokyo/DRUG001/DRUG001C3001/24weeks/progs
$ cd /cygdrive/c/pharma

Roland@DELL1 /cygdrive/c/pharma
$ find .
.
./xenuyama
./xenuyama/formats
./xenuyama/macros
./xenuyama/tokyo
./xenuyama/tokyo/DRUG001
./xenuyama/tokyo/DRUG001/DRUG001C3001
./xenuyama/tokyo/DRUG001/DRUG001C3001/24weeks
./xenuyama/tokyo/DRUG001/DRUG001C3001/24weeks/data
./xenuyama/tokyo/DRUG001/DRUG001C3001/24weeks/data/analysis
./xenuyama/tokyo/DRUG001/DRUG001C3001/24weeks/data/derived
./xenuyama/tokyo/DRUG001/DRUG001C3001/24weeks/data/derived/adv.sas7bdat
./xenuyama/tokyo/DRUG001/DRUG001C3001/24weeks/data/derived/demog.sas7bdat
./xenuyama/tokyo/DRUG001/DRUG001C3001/24weeks/data/derived/protocol.sas7bdat
./xenuyama/tokyo/DRUG001/DRUG001C3001/24weeks/data/derived/titles.sas7bdat
./xenuyama/tokyo/DRUG001/DRUG001C3001/24weeks/data/raw
./xenuyama/tokyo/DRUG001/DRUG001C3001/24weeks/formats
./xenuyama/tokyo/DRUG001/DRUG001C3001/24weeks/formats/formats.sas7bcat
./xenuyama/tokyo/DRUG001/DRUG001C3001/24weeks/macros
./xenuyama/tokyo/DRUG001/DRUG001C3001/24weeks/macros/allocr.sas
./xenuyama/tokyo/DRUG001/DRUG001C3001/24weeks/macros/allocw.sas
./xenuyama/tokyo/DRUG001/DRUG001C3001/24weeks/progs
./xenuyama/tokyo/DRUG001/DRUG001C3001/24weeks/progs/ALL.TITLES
./xenuyama/tokyo/DRUG001/DRUG001C3001/24weeks/progs/d01_demog.chk
./xenuyama/tokyo/DRUG001/DRUG001C3001/24weeks/progs/d01_demog.log
./xenuyama/tokyo/DRUG001/DRUG001C3001/24weeks/progs/d01_demog.sas
./xenuyama/tokyo/DRUG001/DRUG001C3001/24weeks/progs/d02_adv.chk
./xenuyama/tokyo/DRUG001/DRUG001C3001/24weeks/progs/d02_adv.log
./xenuyama/tokyo/DRUG001/DRUG001C3001/24weeks/progs/d02_adv.sas
./xenuyama/tokyo/DRUG001/DRUG001C3001/24weeks/progs/donelist.tmp
./xenuyama/tokyo/DRUG001/DRUG001C3001/24weeks/progs/donelist.txt
./xenuyama/tokyo/DRUG001/DRUG001C3001/24weeks/progs/mk_ifmts.chk
./xenuyama/tokyo/DRUG001/DRUG001C3001/24weeks/progs/mk_ifmts.log
./xenuyama/tokyo/DRUG001/DRUG001C3001/24weeks/progs/mk_ifmts.sas
./xenuyama/tokyo/DRUG001/DRUG001C3001/24weeks/progs/protocol.txt
./xenuyama/tokyo/DRUG001/DRUG001C3001/24weeks/progs/runderived
./xenuyama/tokyo/DRUG001/DRUG001C3001/24weeks/progs/runderived.chk
./xenuyama/tokyo/DRUG001/DRUG001C3001/24weeks/progs/runderived.err
./xenuyama/tokyo/DRUG001/DRUG001C3001/24weeks/progs/runderived.log
./xenuyama/tokyo/DRUG001/DRUG001C3001/24weeks/progs/runreports
./xenuyama/tokyo/DRUG001/DRUG001C3001/24weeks/progs/runreports.chk
./xenuyama/tokyo/DRUG001/DRUG001C3001/24weeks/progs/runsuite
./xenuyama/tokyo/DRUG001/DRUG001C3001/24weeks/progs/silly_sas_program.sas
./xenuyama/tokyo/DRUG001/DRUG001C3001/24weeks/progs/titles.template
./xenuyama/tokyo/DRUG001/DRUG001C3001/24weeks/progs/t_adv.chk
./xenuyama/tokyo/DRUG001/DRUG001C3001/24weeks/progs/t_adv.lis
./xenuyama/tokyo/DRUG001/DRUG001C3001/24weeks/progs/t_adv.log
./xenuyama/tokyo/DRUG001/DRUG001C3001/24weeks/progs/t_adv.sas
./xenuyama/tokyo/DRUG001/DRUG001C3001/24weeks/progs/t_adv.titles
./xenuyama/tokyo/DRUG001/DRUG001C3001/24weeks/progs/t_demog.chk
./xenuyama/tokyo/DRUG001/DRUG001C3001/24weeks/progs/t_demog.lis
./xenuyama/tokyo/DRUG001/DRUG001C3001/24weeks/progs/t_demog.log
./xenuyama/tokyo/DRUG001/DRUG001C3001/24weeks/progs/t_demog.sas
./xenuyama/tokyo/DRUG001/DRUG001C3001/24weeks/progs/t_demog.titles
./xenuyama/tokyo/DRUG001/DRUG001C3001/24weeks/progs/work
./xenuyama/tokyo/DRUG001/DRUG001C3001/formats
./xenuyama/tokyo/DRUG001/DRUG001C3001/macros
./xenuyama/tokyo/DRUG001/formats
./xenuyama/tokyo/DRUG001/macros
./xenuyama/tokyo/formats
./xenuyama/tokyo/macros

Roland@DELL1 /cygdrive/c/pharma

These are the contents of the donelist files. Note that donelist.txt is a sorted version of donelist.tmp and with total pages added.
 
Roland@DELL1 /cygdrive/c/pharma
$ cd -
/cygdrive/c/pharma/xenuyama/tokyo/DRUG001/DRUG001C3001/24weeks/progs

Roland@DELL1 /cygdrive/c/pharma/xenuyama/tokyo/DRUG001/DRUG001C3001/24weeks/progs
$ cat donelist.tmp
002-000-000-000-000-000 t_adv.lis 
001-000-000-000-000-000 t_demog.lis 

Roland@DELL1 /cygdrive/c/pharma/xenuyama/tokyo/DRUG001/DRUG001C3001/24weeks/progs
$ cat donelist.txt
001-000-000-000-000-000 t_demog.lis                               1
002-000-000-000-000-000 t_adv.lis                                 2

Roland@DELL1 /cygdrive/c/pharma/xenuyama/tokyo/DRUG001/DRUG001C3001/24weeks/progs

As I promised, I have guided you through from empty directories to producing final reports, step by step. That is now done. What you see is what ran on my PC using Cygwin.

Spectre as a "push button" reporting system

In this final section, I will explain, in very simple terms, how Spectre can become a "push button" reporting system. For this to be achieved, a full set of reporting macros needs to be written such that there is no reporting code in the "progs" directory. These reporting macros still have to be called from somewhere and that somewhere is the "titles" files in the "sascode" line. What I will do first is move t_demog.sas and t_adv.sas into the increment macros directory as macros of the same name and put macro definitions around them. The needed change should be obvious so I won't repeat the code here.

Now comes the change to the titles members to call these macros from the "sascode" line. t_demog.titles now looks like this.
 
program: t_demog 
layout: P10
population: FAS
sascode: %t_demog
titles below:
TABLE 1
DEMOGRAPHY
footnotes below:
&_longline_
endxxx:

t_adv.titles now looks like this.
 
program: t_adv 
layout: L10
population: FAS
sascode: %t_adv
titles below:
TABLE 2
ADVERSE EVENTS
footnotes below:
&_longline_
endxxx:

I want you to consider that these two very simple titles definitions could have come out of a spreadsheet somewhere and been exported to the programs directory. Once this method is used, then in a sense, report coding is no more. True, somebody has to write the reporting macros, but when the CDISC standards have all been clarified and report layouts clarified then there could be a repository of reporting macros for you to use. If this happens then you won't need programmers to write the reporting macros any more. When that happens, Spectre will have become a push-button reporting system.

Now I have changed the titles, I will rerun the "crtitlesds" script. There will still be a t_adv.sas and a t_demog.sas after "crtitlesds" has run but look at them now! They have been overwritten and now contain the sas code that was defined to the titles member in the "sascode" line.
 
Roland@DELL1 /cygdrive/c/pharma/xenuyama/tokyo/DRUG001/DRUG001C3001/24weeks/progs
$ crtitlesds

Roland@DELL1 /cygdrive/c/pharma/xenuyama/tokyo/DRUG001/DRUG001C3001/24weeks/progs
$ ls t*.sas
t_adv.sas  t_demog.sas

Roland@DELL1 /cygdrive/c/pharma/xenuyama/tokyo/DRUG001/DRUG001C3001/24weeks/progs
$ cat t_adv.sas
/*
/ Program      : t_adv.sas
/ Author       : Automatically generated by the "crtitlesds" script
/ Date         :  3-Mar-2007 at 08:06:26
/ Client       : xenuyama
/ Office       : tokyo
/ Drug         : DRUG001
/ Protocol     : DRUG001C3001
/ Increment    : 24weeks
/ Notes        : Do not edit this member as it will get overwritten next time
/                "crtitlesds" is run. If you wish to change the code you must
/                change it in the .titles member.
/==============================================================================*/

%t_adv

Roland@DELL1 /cygdrive/c/pharma/xenuyama/tokyo/DRUG001/DRUG001C3001/24weeks/progs
$ cat t_demog.sas
/*
/ Program      : t_demog.sas
/ Author       : Automatically generated by the "crtitlesds" script
/ Date         :  3-Mar-2007 at 08:06:26
/ Client       : xenuyama
/ Office       : tokyo
/ Drug         : DRUG001
/ Protocol     : DRUG001C3001
/ Increment    : 24weeks
/ Notes        : Do not edit this member as it will get overwritten next time
/                "crtitlesds" is run. If you wish to change the code you must
/                change it in the .titles member.
/==============================================================================*/

%t_demog

Roland@DELL1 /cygdrive/c/pharma/xenuyama/tokyo/DRUG001/DRUG001C3001/24weeks/progs

What I will do now is delete all the t_* files that are not titles members so that only the titles members remain.
 
Roland@DELL1 /cygdrive/c/pharma/xenuyama/tokyo/DRUG001/DRUG001C3001/24weeks/progs
$ ls t_*
t_adv.chk  t_adv.lis  t_adv.log  t_adv.sas  t_adv.titles  t_demog.chk  t_demog.lis  t_demog.log  t_demog.sas  t_demog.titles

Roland@DELL1 /cygdrive/c/pharma/xenuyama/tokyo/DRUG001/DRUG001C3001/24weeks/progs
$ \rm t_*.chk t_*.lis t_*.log t_*.sas

Roland@DELL1 /cygdrive/c/pharma/xenuyama/tokyo/DRUG001/DRUG001C3001/24weeks/progs
$ ls t_*
t_adv.titles  t_demog.titles

Roland@DELL1 /cygdrive/c/pharma/xenuyama/tokyo/DRUG001/DRUG001C3001/24weeks/progs

Can you see that all that is left are the two "titles" members? Imagine they were exported there from a statistician's spreadsheet. Now I will run "makerun". No problems there, as you can see.
 
Roland@DELL1 /cygdrive/c/pharma/xenuyama/tokyo/DRUG001/DRUG001C3001/24weeks/progs
$ makerun

Roland@DELL1 /cygdrive/c/pharma/xenuyama/tokyo/DRUG001/DRUG001C3001/24weeks/progs

Now I will run "runreports". Everything worked as it did before. The ".lis" outputs are there and the same as before!
 
Roland@DELL1 /cygdrive/c/pharma/xenuyama/tokyo/DRUG001/DRUG001C3001/24weeks/progs
$ ./runreports
This script was started by Roland (Roland) on Sat Mar  3 08:10:36 WEST 2007
This script was started by Roland (Roland) on Sat Mar  3 08:10:37 WEST 2007
sas program "t_adv" ended with return code 0:
0 ERROR(s)
0 WARNING(s)
sas program "t_demog" ended with return code 0:
0 ERROR(s)
0 WARNING(s)
This script finished at Sat Mar  3 08:10:52 WEST 2007
This script finished at Sat Mar  3 08:10:52 WEST 2007

Roland@DELL1 /cygdrive/c/pharma/xenuyama/tokyo/DRUG001/DRUG001C3001/24weeks/progs
$ ls t_*.*
t_adv.chk  t_adv.log  t_adv.titles  t_demog.lis  t_demog.sas
t_adv.lis  t_adv.sas  t_demog.chk   t_demog.log  t_demog.titles

Roland@DELL1 /cygdrive/c/pharma/xenuyama/tokyo/DRUG001/DRUG001C3001/24weeks/progs

So there you see Spectre working as a "push button" reporting system. It may take a while for this concept to "sink in" but I hope you will eventually realize that Spectre can, indeed, become a "push button" reporting system.

Conclusion

You have seen, step by step, Spectre report a very simple study from empty directories through to final report run. Lastly, you have seen how Spectre can become a "push button" reporting system.


 

Use the "Back" button of your browser to return to the previous page

contact the author













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.