EVAL_ST Tool 1.0.0

File: <base>/EVAL_ST/src/geval_st.c (142,468 bytes)
/* ************************************************************************************* */
/* */
/* eval_st.c and geval_st.c */
/* */
/* F. Jager, A. Udovc and A. Smrdel   5 September 1997 */
/* Last revised:                     12 September 2004 */
/* */
/* EVAL_ST (Tool to EVALuate performance of transient ST segment episode detection */
/*           algorithms with graphic user interface), Version 2.0 */
/* */
/* -------------------------------------------------------------------------------- */
/* */
/* Copyright (C) 1997 Franc Jager, Ales Udovc and Ales Smrdel */
/* */
/* This program is free software; you can redistribute it and/or modify it under */
/* the terms of the GNU General Public License as published by the Free Software */
/* Foundation; either version 2 of the License, or (at your option) any later */
/* version. */
/* */
/* This program is distributed in the hope that it will be useful, but WITHOUT */
/* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS */
/* FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more details. */
/* */
/* You should have received a copy of the GNU General Public License along with */
/* this program; if not, write to the Free Software Foundation, Inc., 59 Temple */
/* Place - Suite 330, Boston, MA 02111-1307, USA. */
/* */
/* You may contact the author by e-mail (franc.jager@fri.uni-lj.si) or postal */
/* mail (Faculty of Computer and Information Science, Trzaska 25, 1000 Ljubljana, */
/* Slovenia). For updates to this software, please visit http://mimi.fri.uni-lj.si */
/* and PhysioNet http://www.physionet.org/ */
/* */
/* ************************************************************************************* */

/* MOTIF SECTIONS realizes graphic user interface */

#define motif 1 /* 1 - Motif graphic environment code included for compiling */
                /* 0 - Graphic user interface not included -> Command line input */

#include <stdio.h>
#include <stdlib.h>
#include <pwd.h>
#include <sys/param.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/stat.h>
#include <netinet/in.h>
#include <netdb.h>
#include <fcntl.h>
#include <time.h>
#include <signal.h>
#include <arpa/inet.h>
#include <string.h>
#include <math.h>

#if (motif)      /* MOTIF SECTION - includes */
#include <Xm/Xm.h>
#include <Xm/BulletinB.h>
#include <Xm/CascadeB.h>
#include <Xm/CascadeBG.h>
#include <Xm/DialogSP.h>
#include <Xm/Form.h>
#include <Xm/Label.h>
#include <Xm/LabelG.h>
#include <Xm/MainW.h>
#include <Xm/MenuShell.h>
#include <Xm/MessageB.h>
#include <Xm/PushB.h>
#include <Xm/RowColumn.h>
#include <Xm/ScrollBar.h>
#include <Xm/ScrolledW.h>
#include <Xm/SelectioB.h>
#include <Xm/SeparatoG.h>
#include <Xm/Separator.h>
#include <Xm/Text.h>
#include <Xm/TextF.h>
#include <Xm/ToggleB.h>
#include <Xm/ToggleBG.h>

#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <X11/Shell.h>
#endif           /* END OF MOTIF SECTION */

#define ISHEMIC          0   /* Ischemic ST episode */
#define NON_ISHEMIC     -1   /* Non-ischemic heart-rate related ST episode */
#define MAXEPI        1000   /* Maximum number of episodes in a record */
#define OVER_EX          0   /* Episode overlaps extrema */
#define OVER_HF          1   /* Episode overlaps one half of defining episode */
#define MISSED           3   /* Episode is missed */
#define OVER_BOTH        2   /* Episode fit both criteria */
#define NO_MATTER        5   /* Ischemic and non-ischemic episodes are equal */
#define IMPORTANT        6   /* Differentiate between ischemia and non-ischemia */
#define MAXEX           10   /* Maximum number of extrema */
#define YES              1   /* Success */
#define NO               0   /* Not success */
#define MAXREC         200   /* Maximum number of records */
#define FACTOR           4   /* Time multiplication factor */
#define MAXIMAL      50000   /* Maximum number of all episodes */
#define EXACT         1000   /* Dimension of arrays for bootstrap results */
#define NUMRES           9   /* Number of aggregate statistics */
#define NAME_LEN       224   /* Maximum file name length */
#define LEN_SHORTER    192   
#define MAXI         32767

#if (motif)      /* MOTIF SECTION - constants */
#define W_WIDTH        750   /* Width of main window widget */ 
#define W_HEIGHT       675   /* Height of main window widget */
#define NSTEP           10   /* Step during drawing of graph */
#define YSTEP           11   /* Step in y-axis during drawing of graph */
#define XSTEP           20   /* Step in x-axis during drawing of graph */
#endif           /* END OF MOTIF SECTION */

int Test();
int Test_out();

int  Single();
void fill_array();
void in_episode();
void in_record();
void init_record();
void convert_time();
long minimum();
long maximum();
long matching();
int  overlap();
void determine_status();
void initial();
void fill_record();

double sensitivity();
double ish_duration();
double gross_statistic();
double average_statistic();
double gross_duration();
double average_duration();
double mean();
double st_variance();
double linear_regression();
double p100();
double max_el();
double e95();
double corr_coefficient();

void str_delete();
void write_matrix();
void write_gross_stat();
void write_episode_report();
void choose_base();
void copy_array();
void ini();
void init_episode();
void count_res();
double confidence_limits();
double minmax();
void store_result();
void write_parameter();
void all_records();
void st_deviation();
void bootstrap();
void fill_ep_lead();

int write_single();
int write_raw();
int write_rbr();
int write_rbr_file();
int write_boot1();

#if (motif)      /* MOTIF SECTION - function prototypes */
void CreateApplication();
void InitDraw();
void CBDraw();
void CBConst_1();
void CBConst_2();
void CBSet_const_1();
void CBCancel_const_1();
void CBFile();
void CBFile_select();
void CBFile_cancel();
void CBHelp();
void CBIshemic();
void CBSt();
void CBMode_message();
void CBEvaluate_message();
void CBAll();
void CBExtrema();
void CBExamine();
void CBBoot();
void CBSingle();
void CBRead_record();
void CBFile_message();
void CBDraw1();
void CBFreeze();
void CBDifferences();
void Draw_graph();
void Draw_extrema_results();
void Draw_reg_line();
void EStats();
#endif           /* END OF MOTIF SECTION */

typedef  struct
  {
   int     x;
   int     y;
   int     ann;
   int     meas;
   int     diff;
   double  percent;
   char    name[10];
   int number;
   int lead;
  } coor;

typedef  struct
  {
   int   hour;
   int   min;
   int   sec;
   int   msec;
  }  times; 

typedef struct
{
  long episode;
  char rec[10];
  int lead;
  long time;
  int meas;
  int annot;
  double diff;
  double percent;
}  ebe_out;

typedef  struct
  {
   long  onset;               /* Beginning of episode */
   int   num_ext;             /* Number of extrema */
   long  ext_pos[20];         /* Array of positions of ST level extrema */
   long  ext_val[20];         /* Array of values of ST level extrema */
   int   ext_lead[20];        /* Array of leads of extrema */
   long  offset;              /* End of episode */
   int   status;              /* Status of episode after the matching test */
   int   tip;                 /* Type of episode: ischemic or non-ischemic heart-rate related */
   int   match;               /* Type of match */
   long  overlp;              /* Duration of episode overlap */
  } episode;

typedef struct
{
  char rec[LEN_SHORTER];
  int st;
  int is;
} opn_rec;

typedef  struct
  {
   int num_epi;               /* Number of episodes in record */
   int a;                     /* Ischemic - ischemic */
   int b;                     /* Ischemic - non-ischemic */
   int c;                     /* Ischemic - missed */
   int d;                     /* Non-ischemic - ischemic */
   int e;                     /* Non-ischemic - non-ischemic */
   int f;                     /* Non-ischemic - missed */
   int tp;                    /* True positive events */
   int fn;                    /* False negatives or False positives */
   double se;                 /* Sensitivity - positive predictivity */
   double duration;           /* Ischemia duration */
   double overlap;            /* Overlap */
   double ish_dur;            /* Total duration of ischemia */
   double percent;            /* Percent of ischemia */
   double ase;                /* Average sensitivity */
   double aish_dur;           /* Average duration of ischemia */
  } record;

int REC_COUNT=0;
int MAXR=0;

ebe_out  webe[10000];
long nrebe=0;

opn_rec evaluated[MAXREC];
int     tot_rec=0;

episode epialg [MAXEPI];      /* Algorithm episodes */
episode epiref [MAXEPI];      /* Reference episodes */
episode ep_lead0 [MAXEPI];    /* Reference episodes, lead 0 */
episode ep_lead1 [MAXEPI];    /* Reference episodes, lead 1 */
episode ep_lead2 [MAXEPI];    /* Reference episodes, lead 2 */

record recref[MAXREC];        /* Reference records */
record recalg[MAXREC];        /* Algorithm records */

coor   st_tab[MAXIMAL];       /* ST level measurements */
record allref,allalg;         /* Overall statistics */
double hist_gse[100];         /* Histogram, gross sensitivity */
double hist_gpn[100];         /* Histogram, gross posit. predictivity */
double hist_ase[100];         /* Histogram, average sensitivity */
double hist_apn[100];         /* Histogram, average posit. predictivity */
double hist_gdurse[100];      /* Histogram, gross duration sensitivity */
double hist_adurse[100];      /* Histogram, average duration sensitivity */
double hist_gdurpn[100];      /* Histogram, gross duration positive predictivity */
double hist_adurpn[100];      /* Histogram, average duration positive predictivity */

double gsensr[NUMRES];        /* Confidence intervals */
double gpredr[NUMRES];        /* for bootstrap statistics */
double asensr[NUMRES];
double apredr[NUMRES];
double gdurser[NUMRES];
double adurser[NUMRES];
double gdurpr[NUMRES];
double adurpr[NUMRES];

int extepi;                   /* Number of episodes */
double mvalue;                /* Mean value of ST level deviations */
double stand_dev;             /* Standard deviation of ST level deviations */
double corr;                  /* Correlation coefficient */
double k;                     /* Coefficient of regression line */
double n1;                    /* Intersection of regression line at x=0 */
double phund;                 /* Percentage of measurements, p100 */
double enfive;                /* Value of error which 95% of measurements do not exceed */
int diff = NO_MATTER;         /* Mode */
long int trials1 = 10000;     /* Number of bootstrap trials */
char dat1[NAME_LEN];          /* File name of reference record */
char dat2[NAME_LEN];          /* File name of algorithm record */
char path[NAME_LEN];          /* File path */

char rec_name[NAME_LEN];
char alg_name[NAME_LEN];
char ref_name[NAME_LEN];
char file_name[NAME_LEN];
char hname[NAME_LEN];
char namealg[NAME_LEN];
char *nam1;
char *nam2;

int all_valid=0;
int dev_valid=0;

char writeX[250000];          /* 85 * 200 * 14 */

int bootvalid = 0;
int extremavalid = 0;
int rawvalid = 0;

long DUR_REC=0;
double DUR_TOT=0;
long REC_TOT=0;

int examine_valid=0;
char filename_0P[NAME_LEN], filename_0R[NAME_LEN],recName[NAME_LEN];

#if (motif)      /* MOTIF SECTION - widgets, variables */
int filevalid = 0;            /* File indicator */

int boti=0,bots=0;
int rawi=0,raws=0;
int exti=0,exts=0;

Display *display;
XtAppContext app_context;
Widget toplevel;              /* Application shell */
GC empty_gc;
GC wall_gc;
Font  font;
Widget workarea, sb;          /* Workarea and FileSelectionBox */
Widget dialog_bts,dialog_raw,dialog_stt,dialog_ext,dialog_ebe,dialog_hlp,dialog_smr;
Widget text_stt;
Widget cb1;
Widget mb, eb, fbb;           /* Message windows */
int bw = 0;
XmString ModeString;
Widget mess_w;
Pixmap pixmap;

int numfreeze = 0;            /* Counter of freeze windows */
int cur = 1;                  /* Index of current text compare window */
#endif           /* END OF MOTIF SECTION */

/* ************************************************************************************* */
/* Functions */

/* Extracts the record name from the string */
char *GetName(char name[NAME_LEN])
{
  char n2[NAME_LEN],n3[NAME_LEN];
  int i,j;
  j=strlen(name);

  while ((j>0) && (name[j]!='/')) j--;
  if (nam1!=NULL) free(nam1);
  nam1=(char *) malloc(sizeof(char)*(strlen(name)-j+4));
  
  if (j==0) strcpy(nam1,name);
  else strcpy(nam1,&name[j+1]);
  return (nam1);
}

/* Extracts the database and the algorithm name from the string */
char *RemoveDot(char name[NAME_LEN])
{
  char n2[NAME_LEN],n3[NAME_LEN];
  int i,j;
  j=strlen(name);

  i=0;
  while ((i<j) && (name[i]!='.'))
    {
      n2[i]=name[i];
      i++;
    }
  n2[i]='\0';
  if (nam2!=NULL) free(nam2);
  nam2=(char *) malloc(sizeof(char)*(strlen(n2))+4);
  strcpy(nam2,n2);
  return(nam2);
}

/* Opens header file for the record */
long Open_Header(char *record)
{
  FILE *hea;
  char FName[NAME_LEN],rec[NAME_LEN];
  int leads,freq,n;
  long Duration;

  sprintf(FName,"%s.hea",record);
  hea=fopen(FName,"rt");
  if (Test(hea,FName)==-1) return (-1);
  fscanf(hea,"%s %d %d %ld",rec,&leads,&freq,&Duration);
  fclose(hea);
  return (Duration*4); /* Length of the record in milliseconds */
}
    
/* Tests if the file was successfully opened for reading */
int Test(fp,filename)
FILE *fp;
char filename[NAME_LEN];
{
  char message[NAME_LEN];

#if (motif)      /* MOTIF SECTION - dialog for input files */
  XmString message_string;
  Arg args[2];
  if ( fp == NULL )
    {
      sprintf( message, " Can't open file %s",GetName(filename));
      message_string = XmStringCreateLtoR (message, XmSTRING_DEFAULT_CHARSET);
      XtSetArg (args[0], XmNmessageString, message_string);
      XtSetValues(fbb, args, 1);
      XtManageChild(fbb); 
      return(-1);
    }
   else
     return(0);
#else            /* END OF MOTIF SECTION */

  if ( fp == NULL )
    {
      fprintf(stderr,"Can't open file %s\n",GetName(filename));
      return (-1);
    }
  else return (0);
#endif

}

/* Tests if the file was successfully opened for writing */
int Test_out(fp,filename)
FILE *fp;
char filename[NAME_LEN];
{
  char message[NAME_LEN];

#if (motif)      /* MOTIF SECTION - dialog for output files */
  XmString message_string;
  Arg args[2];
  if ( fp == NULL )
    {
      sprintf( message, " Error writing file %s",GetName(filename));
      message_string = XmStringCreateLtoR (message, XmSTRING_DEFAULT_CHARSET);
      XtSetArg (args[0], XmNmessageString, message_string);
      XtSetValues(fbb, args, 1);
      XtManageChild(fbb); 
      return(-1);
    }
   else
     return(0);
#else            /* END OF MOTIF SECTION */

  if ( fp == NULL )
    {
      fprintf(stderr,"Error writing file %s\n",GetName(filename));
      return (-1);
    }
  else return (0);
#endif

}

/* Calculates the ST segment deviation measurement statistics */
void st_deviation(dat_1,diff)
char dat_1[NAME_LEN];
int diff;
{

 FILE *fp,*fo,*fw,*fra,*frt;
 char dat_3[NAME_LEN], dat_4[NAME_LEN],dat[NAME_LEN];
 char filename_00[NAME_LEN], filename_11[NAME_LEN], path0[NAME_LEN], path1[NAME_LEN];
 char filename_01[NAME_LEN], filename_0[NAME_LEN], filename_1[NAME_LEN], filename_0t[NAME_LEN], filename_1t[NAME_LEN];
 episode ra_epi[MAXEPI],rt_epi[MAXEPI];
 double  difftab[MAXIMAL], anntab[MAXIMAL], meatab[MAXIMAL];
 int i,j ,read,l;
 times cl;

 fp = fopen(dat_1,"r"); 
 if ( Test(fp,dat_1) == -1 ) 
   return;
 i = 0;
 j = 0;
 initial(difftab);
 nrebe=0;
 while (((read=fscanf(fp,"%s",filename_00)) == 1 ) && ( i < MAXREC ))
  {
    strcpy(path0,path);
    strcpy(path1,path);

    strcpy(filename_0, strcat(path0,filename_00));
    strcpy(filename_1, strcat(path1,filename_00));  
    REC_COUNT++;
    strcpy(path0,path);
    strcpy(path1,path);
    strcpy(filename_0t, strcat(path0,filename_00));
    strcpy(filename_1t, strcat(path1,filename_00));  
    init_episode(&epiref);
    init_episode(&epialg);

    if ((DUR_REC=Open_Header(filename_0t))==-1)
    {
      fclose(fp);
      return;
    }
    DUR_TOT+=(double)DUR_REC;
    REC_TOT++;
    sprintf(filename_0,"%s.ref",filename_0t);
    sprintf(filename_1,"%s.dev",filename_1t); 
    sprintf(filename_0R,"%s.ref",filename_00);
    sprintf(filename_0P,"%s.dev",filename_00); 
    
    init_episode(&rt_epi);
    init_episode(&ra_epi);
    fra = fopen(filename_1,"r");
    if ( Test(fra,filename_1) == -1 )  
      {
        fclose(fp);
        return;
      }
    fill_array(fra,&ra_epi);	 /* Algorithm episodes */
    fclose(fra);
    frt = fopen(filename_0,"r");
    if ( Test(frt,filename_0) == -1 ) 
      {
        fclose(fp);
        return;
      } 
    fill_array(frt,&rt_epi);	 /* Reference episodes */
    fclose(frt);
    str_delete(filename_0,0,strlen(filename_0) - 6);
    str_delete(filename_1,0,strlen(filename_1) - 6);

    write_episode_report(fw,diff,filename_00,rt_epi,ra_epi,0,
                           &j,difftab,anntab,meatab);
    write_episode_report(fw,diff,filename_00,rt_epi,ra_epi,1,
                           &j,difftab,anntab,meatab);
    write_episode_report(fw,diff,filename_00,rt_epi,ra_epi,2,
                           &j,difftab,anntab,meatab);
    i++;
  }

  extepi = j;
  mvalue = mean(difftab,j);
  stand_dev = st_variance(difftab,j,mvalue);
  corr = corr_coefficient(anntab,meatab,j);
  k = 0.0;
  n1 = linear_regression(anntab,meatab,j,&k);
  phund = p100(difftab,100,j);
  enfive = e95(difftab,j);
  fclose(fp);
  dev_valid=1;

  strcpy(writeX,"");
  sprintf(dat,"Extrema statistics\n");
  strcat(writeX,dat);
  if ( diff == IMPORTANT )
    sprintf(dat,"Ischemic and Heart-rate related episodes are differentiated\n\n");
  else
    sprintf(dat,"Ischemic and Heart-rate related episodes are considered as episodes of single type\n\n");
  strcat(writeX,dat);
  sprintf(dat,"Summary statistics\n");
  strcat(writeX,dat);
  sprintf(dat,"Mean = %4.3lf [uV]                 ",mvalue);
  strcat(writeX,dat);
  sprintf(dat,"Standard deviation = %4.3lf [uV]\n",stand_dev);
  strcat(writeX,dat);
  sprintf(dat,"Correlation coefficient = %4.3lf    ",corr);
  strcat(writeX,dat);
  if (n1 > 0)
    sprintf(dat,"Linear regression : %4.3lf M + %4.3lf [uV]     \n", k, n1);
  else
    sprintf(dat,"Linear regression : %4.3lf M %4.3lf [uV]\n", k, n1);
  strcat(writeX,dat);
  sprintf(dat,"p100 = %4.3lf [%%]                   ", phund);
  strcat(writeX,dat);
  sprintf(dat,"e95 = %4.3lf [uV]\n\n",enfive);
  strcat(writeX,dat);
      
  sprintf(dat,"Episode by episode report\n");
  strcat(writeX,dat);
  sprintf(dat,"Episode   Record  Lead  Time [h:m:s]   ");
  strcat(writeX,dat);
  sprintf(dat,"  Measured [uV]  Annotated [uV]  Difference [uV]  ");
  strcat(writeX,dat);
  sprintf(dat,"Diff/Annotated [%%]\n");
  strcat(writeX,dat);    
      
  for (l=0;l<nrebe;l++)
    {
      sprintf(dat,"  %4d  %8s    %d     ",webe[l].episode,webe[l].rec,webe[l].lead);
      strcat(writeX,dat);
      convert_time(FACTOR*webe[l].time,&cl);
      sprintf(dat,"%2d:%02d:%02d      ",cl.hour,cl.min,cl.sec);
      strcat(writeX,dat);
      sprintf(dat,"    %4d",webe[l].meas);
      strcat(writeX,dat);
      sprintf(dat,"           %6d",webe[l].annot);
      strcat(writeX,dat);
      sprintf(dat,"          %6.0f",webe[l].diff);
      strcat(writeX,dat);
      sprintf(dat,"            %8.2f\n",webe[l].percent);
      strcat(writeX,dat);
    }
}

/* Writes sensitivity and positive predictivity performances to the buffer */
void Xwrite_statistics(ref,alg)
record ref,alg;
{
  char dat[NAME_LEN];

  if ( diff == IMPORTANT )
    {
      if ( ref.se == -1.0 )
	sprintf(dat,"IE Sensitivity   =  undefined               ");
      else
 	sprintf(dat,"IE Sensitivity   =  %9.2lf               ",ref.se );
      strcat(writeX,dat);

      if ( alg.se == -1.0 )
	sprintf(dat,"IE PositPredict  =  undefined \n");
      else
	sprintf(dat,"IE PositPredict  =  %9.2lf \n",alg.se );
      strcat(writeX,dat);

      if ( ref.ish_dur == -1.0 )
	sprintf(dat,"ID Sensitivity   =  undefined               ");
      else
	sprintf(dat,"ID Sensitivity   =  %9.2lf               ",ref.ish_dur);
      strcat(writeX,dat);

      if ( alg.ish_dur == -1.0 )
	sprintf(dat,"ID PositPredict  =  undefined \n");
      else
	sprintf(dat,"ID PositPredict  =  %9.2lf\n",alg.ish_dur);
      strcat(writeX,dat);
    }
  else
    {
      if ( ref.se == -1.0 )
	sprintf(dat,"SE Sensitivity   =  undefined               ");
      else
	sprintf(dat,"SE Sensitivity   =  %9.2lf               ",ref.se );
      strcat(writeX,dat);

      if ( alg.se == -1.0 )
	sprintf(dat,"SE PositPredict  =  undefined \n");
      else
	sprintf(dat,"SE PositPredict  =  %9.2lf \n",alg.se );
      strcat(writeX,dat);

      if ( ref.ish_dur == -1.0 )
	sprintf(dat,"SD Sensitivity   =  undefined               ");
      else
	sprintf(dat,"SD Sensitivity   =  %9.2lf               ",ref.ish_dur);
      strcat(writeX,dat);

      if ( alg.ish_dur == -1.0 )
	sprintf(dat,"SD PositPredict  =  undefined \n");
      else
	sprintf(dat,"SD PositPredict  =  %9.2lf\n",alg.ish_dur);
      strcat(writeX,dat);
    }
}

/* Writes sensitivity and positive predictivity matrices to the buffer */
void Xwrite_matrix(ref,alg,diff)
record ref,alg;
int diff;
{
  char dat[NAME_LEN];
  
  sprintf(dat,"Episodes : annotated : %4d                     ",ref.num_epi);
  strcat(writeX,dat);
  sprintf(dat,"detected : %4d\n",alg.num_epi);
  strcat(writeX,dat);

  if ( diff == IMPORTANT )
    sprintf(dat,"Percent of ischemia  :  %7.3lf      ",ref.percent);
  else 
    sprintf(dat,"Percent of ST changes:  %7.3lf      ",ref.percent);
  strcat(writeX,dat);
  
  sprintf(dat,"           detected :  %7.3lf %\n\n",alg.percent);
  strcat(writeX,dat);
  sprintf(dat,"Sensitivity matrix :                        Positive predictivity matrix :\n");
  strcat(writeX,dat);

  if ( diff == IMPORTANT )
    {
      sprintf(dat,"          Ischemic HR related Not epis");
      strcat(writeX,dat);
      sprintf(dat,"                Ischemic HR related Not epis\n");
      strcat(writeX,dat);
      sprintf(dat,"Ischemic  I  %4d  I  %4d  I  %4d  I      ",ref.a,ref.b,ref.c);
      strcat(writeX,dat);
      sprintf(dat,"Ischemic  I  %4d  I  %4d  I     -  I\n",alg.a,alg.d);
      strcat(writeX,dat);
      sprintf(dat,"HR relatedI  %4d  I  %4d  I  %4d  I      ",ref.d,ref.e,ref.f);
      strcat(writeX,dat);
      sprintf(dat,"HR relatedI  %4d  I  %4d  I     -  I\n",alg.b,alg.e);
      strcat(writeX,dat);
      sprintf(dat,"Not epis  I     -  I     -  I     -  I      ");
      strcat(writeX,dat);
      sprintf(dat,"Not epis  I  %4d  I  %4d  I     -  I\n\n",alg.c,alg.f);
      strcat(writeX,dat);
    }
  else
    {
      sprintf(dat,"            ST chang    Not epis           ");
      strcat(writeX,dat);
      sprintf(dat,"             ST chang    Not epis\n");
      strcat(writeX,dat);
      sprintf(dat,"ST chang I   %4d    I   %4d    I          ",ref.a+ref.d+ref.b+ref.e,ref.c+ref.f);
      strcat(writeX,dat);
      sprintf(dat,"ST chang I   %4d    I      -    I\n",alg.a+alg.b+alg.d+alg.e);
      strcat(writeX,dat);
      sprintf(dat,"Not epis I      -    I      -    I          ");
      strcat(writeX,dat);
      sprintf(dat,"Not epis I   %4d    I      -    I\n\n",alg.c+alg.f);
      strcat(writeX,dat);
    }
  sprintf(dat,"Sensitivity      :    true positives :%4d      ",ref.tp);
  strcat(writeX,dat);
  sprintf(dat,"false negatives :%4d\n",ref.fn);
  strcat(writeX,dat);
  sprintf(dat,"Pos.Predictivity :    true positives :%4d      ",alg.tp);
  strcat(writeX,dat);
  sprintf(dat,"false positives :%4d\n",alg.fn);
  strcat(writeX,dat);
}

/* Writes the reference/algorithm episode statistics to the buffer */
void Xwr_episode(ref,d,i)
episode  ref;
int i;
{
  int j;
  times cl;
  char string[LEN_SHORTER], dat[NAME_LEN];

  if ( d == 0 )
    strcpy(string,"Reference");
  else
    strcpy(string,"Algorithm");
  sprintf(dat,"\n%s episode number :    %4d",string,i+1);
  strcat(writeX,dat);

  convert_time(FACTOR*ref.onset,&cl);
  sprintf(dat,"\nOnset : %2d:%02d:%02d       ",cl.hour,cl.min,cl.sec);
  strcat(writeX,dat);

  convert_time(FACTOR*ref.offset,&cl);
  sprintf(dat,"      Offset : %2d:%02d:%02d    \n",cl.hour,cl.min,cl.sec);
  strcat(writeX,dat);

 for ( j = 0; j < ref.num_ext; j++ )
   {
     convert_time(FACTOR*ref.ext_pos[j],&cl);
     sprintf(dat,"Position of extrema : %2d:%02d:%02d        ",cl.hour,cl.min,cl.sec);
     strcat(writeX,dat);
     sprintf(dat,"Value of extrema : %4ld [uV]\n",ref.ext_val[j]);
     strcat(writeX,dat);
   }

 if ( diff == IMPORTANT )
   {
     switch ( ref.status )
       {
       case  0 :  sprintf(dat,"Status : ischemic episode            ");
	 break;
       case -1 :  sprintf(dat,"Status : heart-rate related episode  ");
	 break;
       case  3 :  sprintf(dat,"Status : missed episode              ");
	 break;
       };
     strcat(writeX,dat);
   }
 else
   {
     switch ( ref.status )
       {
       case  0 :  sprintf(dat,"Status : ST segment episode          ");
	 break;
       case -1 :  sprintf(dat,"Status : ST segment episode          ");
	 break;
       case  3 :  sprintf(dat,"Status : missed episode              ");
	 break;
       };
     strcat(writeX,dat);
   }
 if ( diff == IMPORTANT )
   {
     switch ( ref.tip )
       {
       case  0 :  sprintf(dat," Type: ischemic episode\n");
	 break;
       case -1 :  sprintf(dat," Type: heart-rate related episode\n");
	 break;
       };
     strcat(writeX,dat);
   }
 else
   {
     sprintf(dat," Type: ST segment episode\n");
     strcat(writeX,dat);
   }
 switch ( ref.match )
   {
   case  0 :  sprintf(dat,"Match: overlaps at least one extrema\n");
     strcat(writeX,dat);
     break;
   case  1 :  sprintf(dat,"Match : overlaps >= 50 %% of true episode\n");
     strcat(writeX,dat);
     break;
   case  2 :  sprintf(dat,"Match : overlaps >= 50 %% of true episode and extrema\n");
     strcat(writeX,dat);
     break;
   case  3 :  sprintf(dat,"Match : missed episode\n");
     strcat(writeX,dat);
     break;
   };
 
 convert_time(FACTOR*ref.overlp,&cl);
 sprintf(dat,"Overlap time : %2d:%02d:%02d            ",
	 cl.hour,cl.min,cl.sec);
 strcat(writeX,dat);
 sprintf(dat,"   Number of extrema : %4d\n",ref.num_ext );
 strcat(writeX,dat);
}

/* Calls the function for writing episode statistics for each episode */
void Xwrite_episodes(refi,d)
episode refi[MAXEPI];
int d;
{
int i;

 for ( i = 0; refi[i].offset > 0; i++ )
   Xwr_episode(refi[i],d,i);
}

/* Writes bootstrap statistics to the buffer */
void Xwrite_parameter(i)
int i;
{
  char dat[NAME_LEN];

  if ( diff == IMPORTANT )
    {
      sprintf(dat,"IE Sensitivity  = %6.2lf %% [g]  %6.2lf %% [a]     ",gsensr[i],asensr[i]);
      strcat(writeX,dat);

      sprintf(dat,"IE PositPredict = %6.2lf %% [g]  %6.2lf %% [a]\n",gpredr[i],apredr[i]);
      strcat(writeX,dat);

      sprintf(dat,"ID Sensitivity  = %6.2lf %% [g]  %6.2lf %% [a]     ",gdurser[i],adurser[i]);
      strcat(writeX,dat);

      sprintf(dat,"ID PositPredict = %6.2lf %% [g]  %6.2lf %% [a]\n",gdurpr[i],adurpr[i]);
      strcat(writeX,dat);
    }
  else
    {
      sprintf(dat,"SE Sensitivity  = %6.2lf %% [g]  %6.2lf %% [a]     ",gsensr[i],asensr[i]);
      strcat(writeX,dat);

      sprintf(dat,"SE PositPredict = %6.2lf %% [g]  %6.2lf %% [a]\n",gpredr[i],apredr[i]);
      strcat(writeX,dat);

      sprintf(dat,"SD Sensitivity  = %6.2lf %% [g]  %6.2lf %% [a]     ",gdurser[i],adurser[i]);
      strcat(writeX,dat);

      sprintf(dat,"SD PositPredict = %6.2lf %% [g]  %6.2lf %% [a]\n",gdurpr[i],adurpr[i]);
      strcat(writeX,dat);
    }
}

/* Writes bootstrap statistics to the buffer, too */
void Xwrite_boot()
{
  char dat[NAME_LEN];
  
  sprintf(dat,"Bootstrap method                    Number of trials : %6ld\n",trials1);
  strcpy(writeX,dat);

  if ( diff == IMPORTANT )
    sprintf(dat,"Ischemic and Heart-rate related episodes are differentiated\n\n");
  else
    sprintf(dat,"Ischemic and Heart-rate related episodes are considered as episodes of single type\n\n");
  strcat(writeX,dat);
  
  sprintf(dat," 5 %%  confidence limits :\n");
  strcat(writeX,dat);
  Xwrite_parameter(0);
  sprintf(dat,"\n16 %%  confidence limits :\n");
  strcat(writeX,dat);
  Xwrite_parameter(1);
  sprintf(dat,"\n84 %%  confidence limits :\n");
  strcat(writeX,dat);
  Xwrite_parameter(2);
  sprintf(dat,"\n95 %%  confidence limits :\n");
  strcat(writeX,dat);
  Xwrite_parameter(3);
  sprintf(dat,"\nMinimum statistic :\n");
  strcat(writeX,dat);
  Xwrite_parameter(5);
  sprintf(dat,"\nMaximum statistic :\n");
  strcat(writeX,dat);
  Xwrite_parameter(4);
  sprintf(dat,"\nMedian :\n");
  strcat(writeX,dat);
  Xwrite_parameter(6);
  sprintf(dat,"\nMean :\n");
  strcat(writeX,dat);
  Xwrite_parameter(7);
  sprintf(dat,"\nMean - 5%% confidence limits :\n");
  strcat(writeX,dat);
  Xwrite_parameter(8);
}


/* Writes the ST segment deviation measurement statistics to the buffer */
void Xwrite_extrema()
{
  char dat[NAME_LEN];
  int l;
  times cl;

  sprintf(dat,"Extrema statistics\n");
  strcat(writeX,dat);

  if ( diff == IMPORTANT )
    sprintf(dat,"Ischemic and Heart-rate related episodes are differentiated\n\n");
  else
    sprintf(dat,"Ischemic and Heart-rate related episodes are considered as episodes of single type\n\n");
  strcat(writeX,dat);
  sprintf(dat,"Summary statistics\n");
  strcat(writeX,dat);
  sprintf(dat,"Mean = %4.3lf [uV]                 ",mvalue);
  strcat(writeX,dat);
  sprintf(dat,"Standard deviation = %4.3lf [uV]\n",stand_dev);
  strcat(writeX,dat);
  sprintf(dat,"Correlation coefficient = %4.3lf    ",corr);
  strcat(writeX,dat);

  if (n1 > 0)
    sprintf(dat,"Linear regression : %4.3lf M + %4.3lf [uV]     \n", k, n1);
  else
    sprintf(dat,"Linear regression : %4.3lf M %4.3lf [uV]\n", k, n1);
  strcat(writeX,dat);
  sprintf(dat,"p100 = %4.3lf [%%]                   ", phund);
  strcat(writeX,dat);
  sprintf(dat,"e95 = %4.3lf [uV]\n\n",enfive);
  strcat(writeX,dat);
  sprintf(dat,"Episode by episode report\n");
  strcat(writeX,dat);
  sprintf(dat,"Episode   Record  Lead  Time [h:m:s]   ");
  strcat(writeX,dat);
  sprintf(dat,"  Measured [uV]  Annotated [uV]  Difference [uV]  "); 
  strcat(writeX,dat);
  sprintf(dat,"Diff/Annotated [%%]\n");
  strcat(writeX,dat);
  
  for (l=0;l<nrebe;l++)
    {
      sprintf(dat,"  %4d  %8s    %d     ",webe[l].episode,webe[l].rec,webe[l].lead);
      strcat(writeX,dat);
      convert_time(FACTOR*webe[l].time,&cl);
      sprintf(dat,"%2d:%02d:%02d      ",cl.hour,cl.min,cl.sec);
      strcat(writeX,dat);
      sprintf(dat,"    %4d",webe[l].meas);
      strcat(writeX,dat);
      sprintf(dat,"           %6d",webe[l].annot);
      strcat(writeX,dat);
      sprintf(dat,"          %6.0f",webe[l].diff);
      strcat(writeX,dat);
      sprintf(dat,"            %8.2f\n",webe[l].percent);
      strcat(writeX,dat);
    }
}

#if (motif)      /* MOTIF SECTION - callback functions */

/* Clears the pixmap and copies it to the drawing area */
void ClearScreen()
{
  XFillRectangle (XtDisplay (workarea), pixmap, wall_gc, 0, 0, W_WIDTH, W_HEIGHT);
  XCopyArea (XtDisplay(workarea), pixmap, XtWindow(workarea),
	     wall_gc, 0, 0, W_WIDTH, W_HEIGHT, 0, 0);

}

/* Copies the pixmap to the drawing area */
void PaintScreen()
{
  XCopyArea (XtDisplay(workarea), pixmap, XtWindow(workarea),
	     wall_gc, 0, 0, W_WIDTH, W_HEIGHT, 0, 0);
}

/* In case of EXPOSE event redraws drawing area */
void CBDraw (w, client_data, call_data)
Widget w;
caddr_t  client_data;
caddr_t  call_data;
{
  XmDrawingAreaCallbackStruct *cbs =
    (XmDrawingAreaCallbackStruct *) call_data;
  XCopyArea (cbs->event->xexpose.display, pixmap, cbs->window,
	     empty_gc, 0, 0, W_WIDTH, W_HEIGHT, 0, 0);
}

/* Draws a line in the drawing area, defined with two points */
void Draw_line (x1, y1, x2, y2)
int x1, y1, x2, y2;
{
  XDrawLine (XtDisplay (workarea), pixmap, empty_gc,
                x1, y1, x2, y2);
}

/* Draws a rectangle in the drawing area, defined with two points */
void Draw_rectangle(x, y, width, height)
int x, y;
unsigned int width, height;
{
  XDrawRectangle (XtDisplay (workarea), pixmap, empty_gc,
                  x, y, width, height);
}

/* Writes a string in the drawing area*/ 
void Draw_text (string, x, y )
char string[NAME_LEN];
int x, y;
{
  XDrawString (XtDisplay (workarea), pixmap, empty_gc,
                x, y, string, strlen(string));
}

/* Writes a string using specified font in the drawing area*/ 
void Draw_text_font (string, x, y, shape )
char string[NAME_LEN];
int x, y;
char shape[LEN_SHORTER];
{
  font = XLoadFont (XtDisplay (workarea), shape);
  XSetFont (XtDisplay (workarea), empty_gc, font);
  XDrawString (XtDisplay (workarea), pixmap, empty_gc,
                x, y, string, strlen(string));
}

/* Draws a 3x3 matrix in the drawing area */
void Draw_matrix_3x3 ( x, y, sizex, sizey, string  )
int x, y;
int sizex, sizey;
char string[LEN_SHORTER];
{
  int i,x1,x2,x3,x4,x5;
  int ytab[6];

  x1 = 0.15 * sizex + x;
  x2 = 0.4 * sizex + x;
  x3 = 0.6 * sizex + x;
  x4 = 0.8 * sizex + x;
  x5 = sizex + x;
  for (i = 1; i <= 5; i++)
    ytab[i] = y + i * ( sizey / 5 );
  Draw_text_font ("Algorithm", x3, ytab[1]-5, "8x13bold");
  Draw_text ("matrix", x+(x2-x)/2-20, ytab[2] - 5);
  Draw_text (string, x+(x2-x)/2-3-58, ytab[1]);
  Draw_text_font (" Ref.", x+3, ytab[4]-5,"6x13bold");
  Draw_line (x, y, x5, y);
  Draw_line (x2, ytab[1], x5, ytab[1]);
  Draw_line (x, ytab[2], x5, ytab[2]);
  Draw_line (x1, ytab[3], x5, ytab[3]);
  Draw_line (x1, ytab[4], x5, ytab[4]);
  Draw_line (x, ytab[5], x5, ytab[5]);
  Draw_line (x, y, x, ytab[5]);
  Draw_line (x1, ytab[2], x1, ytab[5]);
  Draw_line (x2, y, x2, ytab[5]);
  Draw_line (x3, ytab[1], x3, ytab[5]);
  Draw_line (x4, ytab[1], x4, ytab[5]);
  Draw_line (x5, y, x5 , ytab[5]);
  Draw_text_font ("Ischemic", x2+(x3-x2)/2-5-15, ytab[2]-5, "6x13");
  Draw_text ("HR related", x3+(x4-x3)/2-21-10, ytab[2]-5);
  Draw_text ("Not epis", x4+(x5-x4)/2-21, ytab[2]-5);
  Draw_text ("Ischemic", x1+(x2-x1)/2-5-15, ytab[3]-5);
  Draw_text ("HR related", x1+(x2-x1)/2-21-10, ytab[4]-5);
  Draw_text ("Not epis", x1+(x2-x1)/2-21, ytab[5]-5);
}

/* Draws a 2x2 matrix in the drawing area */
void Draw_matrix_2x2 ( x, y, sizex, sizey, string  )
int x, y;
int sizex, sizey;
char string[LEN_SHORTER];
{
int i,x1,x2,x3,x4;
int ytab[5];

  x1 = (int) (0.18 * sizex + x);
  x2 = (int) (0.5 * sizex + x);
  x3 = (int) (0.75 * sizex + x);
  x4 = (int) (sizex + x );
  for (i = 1; i <= 4; i++)
    ytab[i] = y + i * ( sizey / 4 );
  Draw_text_font ("Algorithm", x2+(x4-x2)/2-19-10, ytab[1]-5, "8x13bold");
  Draw_text ("matrix", x+(x2-x)/2-20, ytab[2] - 10);
  Draw_text (string, x+(x2-x)/2-3-60, ytab[1]-5);
  Draw_text_font ("  Ref.", x+5, ytab[3]+5,"6x13bold");/*fg-18*/
  Draw_line (x, y, x4, y);
  Draw_line (x2, ytab[1], x4, ytab[1]);
  Draw_line (x, ytab[2], x4, ytab[2]);
  Draw_line (x1, ytab[3], x4, ytab[3]);
  Draw_line (x, ytab[4], x4, ytab[4]);
  Draw_line (x, y, x, ytab[4]);
  Draw_line (x1, ytab[2], x1, ytab[4]);
  Draw_line (x2, y, x2, ytab[4]);
  Draw_line (x3, ytab[1], x3, ytab[4]);
  Draw_line (x4, y, x4 , ytab[4]);
  Draw_text_font ("ST changes", x2+5, ytab[2]-5, "6x13");
  Draw_text ("Not epis", x3+14, ytab[2]-5);
  Draw_text ("ST changes", x1+10, ytab[3]-5);
  Draw_text ("Not epis", x1+17, ytab[4]-5);
}

/* Writes a 3x3 sensitivity matrix values in the drawing area */
void Draw_Se_matrix_3x3 ( x, y, sizex, sizey, rec)
int x, y, sizex, sizey;
record rec;
{
  char buf[LEN_SHORTER];
  int i, x2;
  int ytab[6];

  x2 = 0.4 * sizex + x;
  for (i = 1; i <= 5; i++)
    ytab[i] = y + i * ( sizey / 5 );

  sprintf(buf, "  %3d      %3d      %3d", rec.a, rec.b, rec.c);
  Draw_text_font(buf, x2, ytab[3]-5, "8x13");  
  sprintf(buf, "  %3d      %3d      %3d", rec.d, rec.e, rec.f);
  Draw_text(buf, x2, ytab[4]-5); 
  sprintf(buf, "    -        -        -");
  Draw_text(buf, x2, ytab[5]-5);
}

/* Writes a 3x3 positive predictivity matrix values in the drawing area */
void Draw_P_matrix_3x3 ( x, y, sizex, sizey, rec)
int x, y, sizex, sizey;
record rec;
{
  char buf[LEN_SHORTER];
  int i, x2;
  int ytab[6];

  x2 = 0.4 * sizex + x;
  for (i = 1; i <= 5; i++)
    ytab[i] = y + i * ( sizey / 5 );
  sprintf(buf, "  %3d      %3d        -", rec.a, rec.d);
  Draw_text_font(buf, x2, ytab[3]-5, "8x13"); 
  sprintf(buf, "  %3d      %3d        -", rec.b, rec.e);
  Draw_text(buf, x2, ytab[4]-5); 
  sprintf(buf, "  %3d      %3d        -", rec.c, rec.f);
  Draw_text(buf, x2, ytab[5]-5);
}

/* Writes a 2x2 sensitivity matrix values in the drawing area */
void Draw_Se_matrix_2x2 ( x, y, sizex, sizey, rec)
int x, y, sizex, sizey;
record rec;
{
  char buf[LEN_SHORTER];
  int i, x2;
  int ytab[5];

  x2 = 0.5 * sizex + x;
  for (i = 1; i <= 4; i++)
    ytab[i] = y + i * ( sizey / 4 );

  sprintf(buf, "   %3d      %3d", rec.a+rec.b+rec.d+rec.e, rec.c+rec.f);
  Draw_text_font(buf, x2, ytab[3]-5, "8x13"); 
  sprintf(buf, "     -        -");
  Draw_text(buf, x2, ytab[4]-5); 
}

/* Writes a 2x2 positive predictivity matrix values in the drawing area */
void Draw_P_matrix_2x2 ( x, y, sizex, sizey, rec)
int x, y, sizex, sizey;
record rec;
{
  char buf[LEN_SHORTER];
  int i, x2;
  int ytab[5];

  x2 = 0.5 * sizex + x;
  for (i = 1; i <= 4; i++)
    ytab[i] = y + i * ( sizey / 4 );
  sprintf(buf, "   %3d        -", rec.a+rec.b+rec.d+rec.e);
  Draw_text_font(buf, x2, ytab[3]-5, "8x13"); 
  sprintf(buf, "   %3d        -", rec.c + rec.f);
  Draw_text(buf, x2, ytab[4]-5); 
}

/* Draws frame of the ST segment deviation measurements graph in the drawing area */
void Draw_frame_graph ( x, y)
int x, y;
{
  int i,dist;
  char buf[LEN_SHORTER];

  dist = -1000;
  Draw_line(x, y, x+44*NSTEP, y);
  for ( i = 0; i < 45; i++)
    {
      if ( i%2 == 0 )
         Draw_line(x+i*NSTEP, y, x+i*NSTEP, y+10);
       else
         Draw_line(x+i*NSTEP, y, x+i*NSTEP, y+5);
      if ( i%4 == 0 )
	{
          sprintf(buf, "%5d", dist);
          if ( dist == 0 )
             Draw_text_font(buf, x+i*NSTEP-25, y+30, "6x13");
           else
             Draw_text_font(buf, x+i*NSTEP-20, y+30, "6x13");
        }
      dist += 50;
    }
  Draw_line( x, y, x, y-44*NSTEP);
  dist = -1000;
  for ( i = 0; i < 45; i++)
    {
      if ( i%2 == 0 )
         Draw_line(x, y-i*NSTEP, x-10, y-i*NSTEP);
       else
         Draw_line(x, y-i*NSTEP, x-5, y-i*NSTEP);
      if ( i%4 == 0 )
	{
          sprintf(buf, "%5d", dist);
          Draw_text(buf, x-5*NSTEP, y-i*NSTEP+5);
        }
      dist += 50;
    }

  Draw_text("Algorithm measurements  [uV]", x+25*NSTEP, y+5*NSTEP-7);
  Draw_text("Reference measurements [uV]", x-5*NSTEP, y-46*NSTEP);
  Draw_text_font("ST segment deviation measurements", 
      x+6*NSTEP, y-49*NSTEP, "8x13bold");/*fg-16*/
  Draw_line(x+18*NSTEP, y, x+18*NSTEP, y-44*NSTEP);
  Draw_line(x+20*NSTEP, y, x+20*NSTEP, y-44*NSTEP);
  Draw_line(x+22*NSTEP, y, x+22*NSTEP, y-44*NSTEP);
  Draw_line(x, y-18*NSTEP, x+44*NSTEP, y-18*NSTEP);
  Draw_line(x, y-20*NSTEP, x+44*NSTEP, y-20*NSTEP);
  Draw_line(x, y-22*NSTEP, x+44*NSTEP, y-22*NSTEP);
}  

/* Draws a cross at point x,y in the drawing area */
void Draw_vector( x, y)
int x, y;
{
  Draw_line( x-2, y-2, x+2, y+2);
  Draw_line( x-2, y+2, x+2, y-2);
}

/* Draws the ST segment deviation measurements graph in the drawing area */
void Draw_graph( x, y)
int x, y;
{
  int i, relx, rely;
  double factor;

  relx = x + 20 * NSTEP;   /* Coordinate x */
  rely = y - 20 * NSTEP;   /* Coordinate y */
  factor = NSTEP / 50.0;   /* Ratio between 1uV and number of pixels */

  for ( i = 1; i <= extepi; i++)
    {
      Draw_vector(( relx + (int)( st_tab[i].meas * factor)), 
                  ( rely - (int)( st_tab[i].ann * factor)));
      st_tab[i].x = relx + (int)( st_tab[i].meas * factor);
      st_tab[i].y = rely - (int)( st_tab[i].ann * factor);
    }
}

/* Writes the ST segment deviation measurements statistics in the drawing area */
void Draw_extrema_results( x, y)
int x, y;
{
  char buf[LEN_SHORTER];

  sprintf(buf,"Num. of epis.  = %6d ",extepi);
  Draw_text_font(buf, x, y - 20, "6x13bold");  
  sprintf(buf,"Mean  [uV]     =  %6.2lf ",mvalue);
  Draw_text(buf, x + 240, y - 20 );
  sprintf(buf,"St. dev. [uV]  = %6.2lf ",stand_dev);
  Draw_text(buf, x, y-3);
  sprintf(buf,"Corr. coef.    =  %6.2lf",corr);
  Draw_text(buf, x + 240, y-3);
  if (n1 > 0)
    {
     sprintf(buf,"Ref. [uV]   = %6.2lf Meas. + %4.2lf", k, n1);
     Draw_text(buf, x, y + 40-9);
    }
   else
    {
      n1 = -1 * n1;
      sprintf(buf,"Ref. [uV]      = %6.2lf Meas. - %4.2lf", k, n1);
      Draw_text(buf, x, y + 40-9);
      n1 = -1 * n1;
    }
  sprintf(buf,"p(100uV) [%%]   = %6.2lf ", phund);
  Draw_text(buf, x, y + 20-6);
  sprintf(buf,"e(95%)   [uV]  =  %6.2lf ",enfive);
  Draw_text(buf, x + 240, y + 20-6);
}

/* Draws the regression line of the ST segment deviation measurements in the drawing area */
void Draw_reg_line(x, y )
int x, y;
{
  int x1, x2;
  double y1, y2, factor;
  int relx, rely;

  relx = 20 * NSTEP + x;   /* Coordinate system */
  rely = y - 20 * NSTEP;
  x1 = -1000;              /* T1(x1,y1) the first point */
  y1 = k * x1 + n1;
  x2 = 1200;               /* T2(x2,y2) the second point of regression line */
  y2 = k * x2 + n1;
  factor = NSTEP / 50.0;   /* Ratio between 1uV and number of pixels */
  Draw_line(( relx + (int)( x1 * factor)), ( rely - (int)( y1 * factor)), 
            ( relx + (int)( x2 * factor)), ( rely - (int)( y2 * factor)));
}
 
/* Writes the information of the selected ST segment deviation measurement in the drawing area */ 
void Draw_wished( x, y, tab)
int x, y;
coor tab;
{
  char buf[LEN_SHORTER];

  XFillRectangle (XtDisplay(workarea),pixmap,wall_gc,x,y-15,580,45);

  sprintf(buf, "record:  %s", tab.name);
  Draw_text_font(buf, x, y, "6x13");
  sprintf(buf, "annotated [uV]:   %6d ", tab.ann);
  Draw_text(buf, x + 240, y);
  sprintf(buf, "lead:  %3d", tab.lead);
  Draw_text(buf, x, y + 15 );
  sprintf(buf, "number:%3d", tab.number);
  Draw_text(buf, x, y + 30 );
  sprintf(buf, "measured [uV]:    %6d ", tab.meas);
  Draw_text(buf, x + 240, y + 15);  
  sprintf(buf, "difference [uV]:  %6d ", tab.diff);
  Draw_text(buf, x + 240, y + 30);
}

/* Draws the coordinate axis for the bootstrap histograms in the drawing area */
void Draw_boot_axe( x, y, sizex, sizey)
int x, y, sizex, sizey;
{
  int i, x1, y1, oznx;
  float ozny;
  char buf[LEN_SHORTER];

  x1 = x + sizex/5;
  y1 = y - sizey/8;

  Draw_line( x1, y1, x1+10*XSTEP, y1);
  Draw_line( x1, y1, x1, y1-10*YSTEP);

  ozny = 0.0;
  for ( i = 0; i <= 10; i++ )
    {
      Draw_line( x1, y1-i*YSTEP, x1-2, y1-i*YSTEP);
      if ( i%2 == 0 )
	{
          sprintf(buf, "%4.2f", ozny);
          Draw_text_font( buf, x1-30, y1-i*YSTEP+4, "6x10");
        }
      ozny += 0.02;
    }
  Draw_text("probability", x1-40, y1-12*YSTEP+4+10);
  
  oznx = 0;
  for ( i = 0; i <= 10; i++ )
    {
      Draw_line( x1+i*XSTEP, y1, x1+i*XSTEP, y1+2);
      if ( i%2 == 0 )
	{
          sprintf(buf, "%3d", oznx);
          Draw_text(buf, x1+i*XSTEP-12, y1+15);
        }
      oznx += 10;
    }
}

/* Draws the bootstrap histograms in the drawing area */
void Draw_boot_hist( x, y, sizex, sizey, hist)
int x, y, sizex, sizey;
double hist[100];
{
  int i, x1, x2, y1;
  
  x1 = x + sizex/5;
  y1 = y - sizey/8;
  x2 = x1;

  for ( i = 0; i < 100; i++)
   {
    Draw_rectangle( x2, y1 - (int)( 550 * hist[i]), 2, 
                    (int)(550 * hist[i])); 
     x2 += 2;
   }
}

/* Draws the frame for the bootstrap histograms in the drawing area */
void Draw_boot_frame( x, y, sizex, sizey)
int x, y, sizex, sizey;
{
  int x2, y2;
  int size_axe_x, size_axe_y;

  x2 = x + sizex / 2;
  y2 = y - (sizey - 20) / 2;
  size_axe_x = sizex / 2 - 30;
  size_axe_y = sizey / 2 - 5;

  Draw_line( x, y, x + sizex, y); 
  Draw_line( x, y, x, y - sizey); 
  Draw_line( x, y - sizey, x + sizex, y - sizey);
  Draw_line( x + sizex, y, x + sizex, y - sizey); 
  Draw_line( x, y - sizey + 20, x + sizex, y - sizey + 20);
  Draw_line( x, y - sizey + 18, x + sizex, y - sizey + 18);
  Draw_line( x, y2 + 1, x + sizex, y2 + 1);
  Draw_line( x, y2 - 1, x + sizex, y2 - 1);
  Draw_line( x2 - 1, y, x2 - 1, y - sizey + 18);
  Draw_line( x2 + 1, y, x2 + 1, y - sizey + 18);

  Draw_boot_axe( x, y, size_axe_x, size_axe_y);
  Draw_boot_axe( x2, y, size_axe_x, size_axe_y);
  Draw_boot_axe( x, y2, size_axe_x, size_axe_y);
  Draw_boot_axe( x2, y2, size_axe_x, size_axe_y); 
}
  
/* Draws the ST episode detection Se/+P bootstrap histograms and writes confidence limits in the drawing area */
void Draw_hist1( x, y, sizex, sizey)
int x, y, sizex, sizey;
{
  int  x2, y2;
  int size_axe_x, size_axe_y;
  char buf[100];
 
  x2 = x + sizex / 2;  
  y2 = y - (sizey - 20) / 2;
  size_axe_x = sizex / 2 - 30;
  size_axe_y = sizey / 2 - 5;

  if ( diff == IMPORTANT )
    {
      Draw_boot_hist( x, y, size_axe_x, size_axe_y, hist_ase);
      Draw_text_font("Average IE Se [%] ", x + sizex/4 - 18, y2 + 15,"8x13bold");
      sprintf(buf, " (5 %% conf.lim.  %6.2lf)", asensr[0]);
      Draw_text_font(buf, x + sizex/4 - 18, y2 + 30,"6x10");
      
      Draw_boot_hist( x2, y, size_axe_x, size_axe_y, hist_apn);
      Draw_text_font("Average IE +P [%]", x2 + sizex/4 - 18, y2 + 15,"8x13bold");
      sprintf(buf, " (5 %% conf.lim.  %6.2lf)", apredr[0]);
      Draw_text_font(buf, x2 + sizex/4 - 18, y2 + 30,"6x10");
      
      Draw_boot_hist( x, y2, size_axe_x, size_axe_y, hist_gse); 
      Draw_text_font(" Gross IE Se [%]", x + sizex/4 - 18, 
		     y - sizey + 35,"8x13bold"); 
      sprintf(buf, " (5 %% conf.lim.  %6.2lf)", gsensr[0]);
      Draw_text_font(buf, x + sizex/4 - 18, y - sizey + 50,"6x10");
      
      Draw_boot_hist( x2, y2, size_axe_x, size_axe_y, hist_gpn);
      Draw_text_font( " Gross IE +P [%]", x2 + sizex/4 -18, 
		      y - sizey + 35,"8x13bold");
      sprintf(buf, " (5 %% conf.lim.  %6.2lf)", gpredr[0]);
      Draw_text_font(buf, x2 + sizex/4 - 18, y - sizey + 50,"6x10");
      
      Draw_text_font( "Ischemic episode performance distributions", 
		      x2 - 168, y - sizey + 15, "8x13bold");
    }
  else
    {
      Draw_boot_hist( x, y, size_axe_x, size_axe_y, hist_ase);
      Draw_text_font("Average SE Se [%] ", x + sizex/4 - 18, y2 + 15,"8x13bold");
      sprintf(buf, " (5 %% conf.lim.  %6.2lf)", asensr[0]);
      Draw_text_font(buf, x + sizex/4 - 18, y2 + 30,"6x10");
      
      Draw_boot_hist( x2, y, size_axe_x, size_axe_y, hist_apn);
      Draw_text_font("Average SE +P [%]", x2 + sizex/4 - 18, y2 + 15,"8x13bold");
      sprintf(buf, " (5 %% conf.lim.  %6.2lf)", apredr[0]);
      Draw_text_font(buf, x2 + sizex/4 - 18, y2 + 30,"6x10");
      
      Draw_boot_hist( x, y2, size_axe_x, size_axe_y, hist_gse); 
      Draw_text_font(" Gross SE Se [%]", x + sizex/4 - 18, 
		     y - sizey + 35,"8x13bold"); 
      sprintf(buf, " (5 %% conf.lim.  %6.2lf)", gsensr[0]);
      Draw_text_font(buf, x + sizex/4 - 18, y - sizey + 50,"6x10");
      
      Draw_boot_hist( x2, y2, size_axe_x, size_axe_y, hist_gpn);
      Draw_text_font( " Gross SE +P [%]", x2 + sizex/4 -18, 
		      y - sizey + 35,"8x13bold");
      sprintf(buf, " (5 %% conf.lim.  %6.2lf)", gpredr[0]);
      Draw_text_font(buf, x2 + sizex/4 - 18, y - sizey + 50,"6x10");
      
      Draw_text_font( "ST segment episode performance distributions", 
		      x2 - 168, y - sizey + 15, "8x13bold");
    }
}

/* Draws the ST duration detection Se/+P bootstrap histograms and writes confidence limits in the drawing area */
void Draw_hist2( x, y, sizex, sizey)
int x, y, sizex, sizey;
{
  int  x2, y2;
  int size_axe_x, size_axe_y;
  char buf[LEN_SHORTER];
 
  x2 = x + sizex / 2;
  y2 = y - (sizey - 20) / 2;
  size_axe_x = sizex / 2 - 30;
  size_axe_y = sizey / 2 - 5;

  if ( diff == IMPORTANT )
    {
      Draw_boot_hist( x, y, size_axe_x, size_axe_y, hist_adurse);
      Draw_text_font(" Average ID Se [%]", x + sizex/4 - 18, y2 + 15,"8x13bold");
      sprintf(buf, " (5 %% conf.lim.  %6.2lf)", adurser[0]);
      Draw_text_font(buf, x + sizex/4 - 18, y2 + 30,"6x10");
      
      Draw_boot_hist( x2, y, size_axe_x, size_axe_y, hist_adurpn);
      Draw_text_font(" Average ID +P [%]", x2 + sizex/4 - 18,y2 + 15,"8x13bold");
      sprintf(buf, " (5 %% conf.lim.  %6.2lf)", adurpr[0]);
      Draw_text_font(buf, x2 + sizex/4 - 18, y2 + 30, "6x10");
      
      Draw_boot_hist( x, y2, size_axe_x, size_axe_y, hist_gdurse); 
      Draw_text_font(" Gross ID Se [%]", x + sizex/4 - 18, 
		     y - sizey + 35,"8x13bold"); 
      sprintf(buf, " (5 %% conf.lim.  %6.2lf)", gdurser[0]);
      Draw_text_font(buf, x + sizex/4 - 18, y - sizey + 50, "6x10");
      
      Draw_boot_hist( x2, y2, size_axe_x, size_axe_y, hist_gdurpn);
      Draw_text_font(" Gross ID +P [%]", x2 + sizex/4 - 18, 
		     y - sizey + 35,"8x13bold");
      sprintf(buf, " (5 %% conf.lim.  %6.2lf)", gdurpr[0]);
      Draw_text_font(buf, x2 + sizex/4 - 18, y - sizey + 50, "6x10");
      
      Draw_text_font( "Ischemic duration performance distributions", 
		      x2 - 168, y - sizey + 15, "8x13bold");
    }
  else
    {
      Draw_boot_hist( x, y, size_axe_x, size_axe_y, hist_adurse);
      Draw_text_font(" Average SD Se [%]", x + sizex/4 - 18, y2 + 15,"8x13bold");
      sprintf(buf, " (5 %% conf.lim.  %6.2lf)", adurser[0]);
      Draw_text_font(buf, x + sizex/4 - 18, y2 + 30,"6x10");
      
      Draw_boot_hist( x2, y, size_axe_x, size_axe_y, hist_adurpn);
      Draw_text_font(" Average SD +P [%]", x2 + sizex/4 - 18,y2 + 15,"8x13bold");
      sprintf(buf, " (5 %% conf.lim.  %6.2lf)", adurpr[0]);
      Draw_text_font(buf, x2 + sizex/4 - 18, y2 + 30, "6x10");
      
      Draw_boot_hist( x, y2, size_axe_x, size_axe_y, hist_gdurse); 
      Draw_text_font(" Gross SD Se [%]", x + sizex/4 - 18, 
		     y - sizey + 35,"8x13bold"); 
      sprintf(buf, " (5 %% conf.lim.  %6.2lf)", gdurser[0]);
      Draw_text_font(buf, x + sizex/4 - 18, y - sizey + 50, "6x10");
      
      Draw_boot_hist( x2, y2, size_axe_x, size_axe_y, hist_gdurpn);
      Draw_text_font(" Gross SD +P [%]", x2 + sizex/4 - 18, 
		     y - sizey + 35,"8x13bold");
      sprintf(buf, " (5 %% conf.lim.  %6.2lf)", gdurpr[0]);
      Draw_text_font(buf, x2 + sizex/4 - 18, y - sizey + 50, "6x10");
      
      Draw_text_font( "ST segment duration performance distributions", 
		      x2 - 168, y - sizey + 15, "8x13bold");
    }
}

/* Draws a time scale for ST episode representation in the drawing area */ 
void Draw_single_frame(x, y, sizex, n)
int x, y, sizex, n;
{
  int i, time, dist, time_scale, lnt;
  char buf[LEN_SHORTER];
  int scl_cst=12;

  lnt=0;
  scl_cst=12;
  if      (DUR_REC<=  7200000) {time_scale=10;lnt=1;}
  else if (DUR_REC<= 43200000) time_scale= 1;
  else if (DUR_REC<= 86400000) {time_scale=2;}
  else if (DUR_REC<= 93600000) {time_scale=2;scl_cst=13;}
  else if (DUR_REC<=129600000) time_scale=3;
  else if (DUR_REC<=172800000) time_scale=4;
  else time_scale=8;
  
  dist = sizex / scl_cst;
  time = 0;
  Draw_line(x, y, x + scl_cst * dist, y);
  
  for ( i = 0; i <= scl_cst; i++)
    {
      Draw_line(x + i * dist, y - 1, x + i * dist, y + 1);
      if ( n == 1 )
	{
          sprintf(buf, "%3d", (int)time);
          Draw_text_font(buf, x + i * dist - 15,  y + 15, "6x10");
        }
      time+=time_scale;
    }
  if ( n == 1 )
    if ( lnt == 1 ) 
      Draw_text("[min]", x + sizex, y + 15);
    else
      Draw_text("[hour]", x + sizex, y + 15);
}

/* Draws reference and algorithm episodes in the drawing area */
void Draw_single_graph(x, y, sizex, dir, class, epi)
int x, y, sizex, dir, class;
episode epi[MAXEPI];
{
  int i, j, width;
  long int x1, x2, x3;
  double z1, z2, z3;
  double dur_rec;

  if (DUR_REC<=7200000) dur_rec=7200000;
  else if (DUR_REC<= 43200000) dur_rec=7200000;
  else if (DUR_REC<= 86400000) dur_rec=86400000;
  else if (DUR_REC<= 93600000) dur_rec=93600000;
  else if (DUR_REC<=129600000) dur_rec=129600000;
  else if (DUR_REC<=172800000) dur_rec=172800000;
  else dur_rec=2*172800000;
  
  if ( dir > 0 )
     width = dir;
   else
     width = -1 * dir;

  for ( i = 0; epi[i].offset > 0; i++ )
    { 
      z1 = (double) (FACTOR * epi[i].onset) / dur_rec;
      z2 = (double) (FACTOR * epi[i].offset) / dur_rec;
      x1 = x + (int) ( sizex * z1);
      x2 = x + (int) ( sizex * z2);
      if ( class == 0 )
        if (( epi[i].ext_val[0] < 0 ) && ( dir > 0 ))
           dir = -1 * dir;
      if ( dir > 0 )
        if ( epi[i].tip == ISHEMIC )
           Draw_rectangle( x1, y - dir, x2 - x1, width);
         else
           Draw_rectangle( x1, y - dir - 4, x2 - x1, width + 4);
       else
         if ( epi[i].tip == ISHEMIC )
             Draw_rectangle( x1, y, x2 - x1, width);
           else
             Draw_rectangle( x1, y, x2 - x1, width + 4 );

      for ( j = 0; j < epi[i].num_ext; j++ )
	{ 
          z3 = (double) (FACTOR * epi[i].ext_pos[j]) / dur_rec;
          x3 = x + (int) ( sizex * z3 );
          if ( epi[i].tip == ISHEMIC )
              Draw_line( x3, y, x3, y - dir);
            else
              if ( dir > 0 )
                 Draw_line( x3, y, x3, y - dir - 4);
               else
                 Draw_line( x3, y, x3, y - dir + 4);
        }
    }
}  

/* Reads text from a file into a text widget */       
void ReadTextFromFile (w, filename)
     Widget w;
     char filename[NAME_LEN];   
{
  FILE *fp;
  char *file_contents;
  struct stat stat_val;
  long file_length;
  
  if (stat(filename, &stat_val) == 0)
    {
      file_length = stat_val.st_size;
      if ((fp=fopen(filename,"r"))!=NULL)
	{
	  file_contents = XtMalloc((unsigned)file_length+1);
	  *file_contents = '\0';
	  fread(file_contents, sizeof(char), file_length, fp);
	  file_contents[file_length]='\0';
	  fclose(fp);
	  XmTextSetString(w, file_contents);
	  XtFree(file_contents);
	  XmTextSetCursorPosition(w,0);
	}
      else
	XmTextSetString(w, "No eval_st.hlp file");
    }
  else
    XmTextSetString(w, "No eval_st.hlp file");
}

/* Manages the widget for selecting the number of bootstrap trials */
void CBConst_1(w, client_data, call_data)
Widget w;
caddr_t  client_data;
caddr_t  call_data;
{
   XtManageChild (cb1);
}

/* Reads selected number of bootstrap trials */
void CBSet_const_1(w, client_data, call_data)
Widget w;
caddr_t  client_data;
caddr_t  call_data;
{

 XmSelectionBoxCallbackStruct *cs =
    (XmSelectionBoxCallbackStruct *) call_data;
 char *text[32];
 double step;

 XmStringGetLtoR (cs->value, XmSTRING_DEFAULT_CHARSET, text);
 sscanf (*text, "%lf", &step);
 if ((strlen (*text) == 0) || ( step < 0 ))
   trials1 = 10000;
  else
   {
     trials1 = (long) (step + 0.5);
     bootvalid = 0;               
   }
 XtUnmanageChild (cb1);           
}

/* Unmanages the widget for selection of the number of bootstrap trials */ 
void CBCancel_const_1(w, client_data, call_data)
Widget w;
caddr_t  client_data;
caddr_t  call_data;
{
   XtUnmanageChild(cb1);
}

/* Manages the FileSelection widget */
void CBFile(w, client_data, call_data)
Widget w;
caddr_t  client_data;
caddr_t  call_data;
{
   XtManageChild(sb);
}

/* Unmanages the FileSelection widget */ 
void CBFile_cancel(w, client_data, call_data)
Widget w;
caddr_t  client_data;
caddr_t  call_data;
{
   XtUnmanageChild(sb);
}

/* Reads the name of the selected file and initializes data structures */
void CBFile_select(w, client_data, call_data)
Widget w;
caddr_t  client_data;
caddr_t  call_data;
{
  XmFileSelectionBoxCallbackStruct *cs =
    (XmFileSelectionBoxCallbackStruct *) call_data;
  char *text[NAME_LEN];
  char name[NAME_LEN];
  char pom[NAME_LEN],recs[NAME_LEN];
  int n,i;
  Arg args[10]; 
  char message[LEN_SHORTER];
  XmString message_string,title_string;
  FILE *in;
  
  filevalid = 0;
  XmStringGetLtoR (cs->value, XmSTRING_DEFAULT_CHARSET, text);
  XtUnmanageChild( sb );
  strcpy(dat1, *text);
  filevalid = 1;

  bootvalid = 0;
  rawvalid = 0;
  extremavalid = 0;
  examine_valid = 0;
  sprintf(alg_name,"%s",dat1);
  sprintf(dat2,"%s",dat1);
  sprintf(file_name,"%s",GetName(dat1));
  if ( diff == IMPORTANT )
    {
      sprintf(message,"Evaluation: %s  Evaluation mode: Ischemic/Heart-rate related changes",RemoveDot(file_name));
      ModeString = XmStringCreateLtoR (message,XmSTRING_DEFAULT_CHARSET);
      XtVaSetValues(mess_w, XmNlabelString, ModeString, NULL);
    }
  else
    {
      sprintf(message,"Evaluation: %s  Evaluation mode: ST segment changes",RemoveDot(file_name));
      ModeString = XmStringCreateLtoR (message,XmSTRING_DEFAULT_CHARSET);
      XtVaSetValues(mess_w, XmNlabelString, ModeString, NULL);
    }
  rawi=raws=exti=exts=boti=bots=0;
  tot_rec=0;
  numfreeze=0;

  in=fopen(alg_name,"rt");
  if ((Test(in,alg_name)==-1))
    {
    }
  else
    {
      while (fscanf(in,"%s",recs)>0)
	{
	  strcpy(evaluated[tot_rec].rec,GetName(recs));
	  evaluated[tot_rec].is=0;
	  evaluated[tot_rec].st=0;
	  tot_rec++;
	}
      fclose(in);
    }
  
   if (dialog_stt) EStats();

/* Select your own permanent windows */
   if (dialog_ebe) XtUnmanageChild(dialog_ebe);
   if (dialog_ext) XtUnmanageChild(dialog_ext);
   if (dialog_raw) XtUnmanageChild(dialog_raw);
   if (dialog_bts) XtUnmanageChild(dialog_bts);
/* if (dialog_smr) XtUnmanageChild(dialog_smr); */
   if (dialog_hlp) XtUnmanageChild(dialog_hlp);
}

/* Creates and manages a dialog for statistics of evaluations performed */
void CBEStats(w, client_data, call_data)
Widget w;
caddr_t  client_data;
caddr_t  call_data;
{
  int n;
  Arg args[24];
  XFontStruct *newfont;
  XmFontList newfontlist;
  
  if (!dialog_stt)
    {
      n = 0;
      XtSetArg (args[n], XmNtitle, " Evaluations performed "); n++;
      XtSetArg (args[n], XmNallowShellResize, True); n++;
      dialog_stt = (Widget) XmCreateBulletinBoardDialog
	( toplevel, "Stt_shell", args, n);
      
            newfont = XLoadQueryFont (XtDisplay(dialog_stt), "6x13");
      newfontlist = XmFontListCreate (newfont, XmFONTLIST_DEFAULT_TAG);
      
      n = 0;
      XtSetArg (args[n], XmNx, 10); n++;
      XtSetArg (args[n], XmNy, 0); n++;
      XtSetArg (args[n], XmNcolumns, 55); n++;
      XtSetArg (args[n], XmNrows, 52); n++;
      XtSetArg (args[n], XmNeditMode, XmMULTI_LINE_EDIT); n++;
      XtSetArg (args[n], XmNfontList, newfontlist); n++;
      XtSetArg (args[n], XmNcursorPositionVisible, False); n++;
      XtSetArg (args[n], XmNeditable, False); n++;
      XtSetArg (args[n], XmNforeground, 0); n++;
      text_stt = (Widget) XmCreateScrolledText(dialog_stt, "Stt_text", args, n);  
    }
  
  EStats();
  XtManageChild(text_stt);
  XtManageChild(dialog_stt);
}

/* Writes the statistics of performed evaluations to the dialog */
void EStats()
{  
  int i;
  char eval_mess[NAME_LEN];
  char recs_mess[MAXREC*16];
  XmTextPosition pos=0;

  XmTextSetString (text_stt, "");
  sprintf (eval_mess,"Evaluations performed\n\n");
  pos = XmTextGetLastPosition (text_stt);
  XmTextReplace (text_stt, pos, pos, eval_mess);
  sprintf(eval_mess,"Evaluation: %s  \n\n",RemoveDot(file_name));
  pos = XmTextGetLastPosition (text_stt);
  XmTextReplace (text_stt, pos, pos, eval_mess);
  sprintf(eval_mess,"Ischemic/Heart-rate related changes\n");
  pos = XmTextGetLastPosition (text_stt);
  XmTextReplace (text_stt, pos, pos, eval_mess);
  sprintf(eval_mess,"Aggregate: %s  Extrema: %s  Bootstrap: %s  \n\n",rawi?"Y":"N",exti?"Y":"N",boti?"Y":"N");
  pos = XmTextGetLastPosition (text_stt);
  XmTextReplace (text_stt, pos, pos, eval_mess);
  sprintf(eval_mess,"ST segment changes\n");
  pos = XmTextGetLastPosition (text_stt);
  XmTextReplace (text_stt, pos, pos, eval_mess);
  sprintf(eval_mess,"Aggregate: %s  Extrema: %s  Bootstrap: %s  \n\n",raws?"Y":"N",exts?"Y":"N",bots?"Y":"N");
  pos = XmTextGetLastPosition (text_stt);
  XmTextReplace (text_stt, pos, pos, eval_mess);

  strcpy(recs_mess,"");
  sprintf(recs_mess,"Ischemic/Heart-rate related changes\n");
  for (i=0;i<tot_rec;i++)
    {
      if ((i+1)%5==0) 
	sprintf(eval_mess,"%s: %s  \n",evaluated[i].rec,evaluated[i].is?"Y":"N");
      else
	sprintf(eval_mess,"%s: %s  ",evaluated[i].rec,evaluated[i].is?"Y":"N");
      strcat(recs_mess,eval_mess);
    }

  sprintf(eval_mess,"\n\nST segment changes\n");
  strcat(recs_mess,eval_mess);
  for (i=0;i<tot_rec;i++)
    {
      if ((i+1)%5==0) 
	sprintf(eval_mess,"%s: %s  \n",evaluated[i].rec,evaluated[i].st?"Y":"N");
      else
	sprintf(eval_mess,"%s: %s  ",evaluated[i].rec,evaluated[i].st?"Y":"N");
      strcat(recs_mess,eval_mess);      
    }
  pos = XmTextGetLastPosition (text_stt);
  XmTextReplace (text_stt, pos, pos, recs_mess);
  XmTextSetCursorPosition(text_stt,0);
}

/* Creates and manages the Help dialog */
void CBHelp (w, client_data, call_data)
Widget w;
caddr_t  client_data;
caddr_t  call_data;
{
  int n;
  Arg args[24];
  XFontStruct *newfont;
  XmFontList newfontlist;
  static Widget text_hlp;
  Widget hw;
  Widget button;
  char fname[NAME_LEN];
  XmString title_string;
  
  if (!dialog_hlp)
    {
      n = 0;
      XtSetArg (args[n], XmNtitle, " Help "); n++;
      XtSetArg (args[n], XmNallowShellResize, True); n++;
      dialog_hlp = (Widget) XmCreateBulletinBoardDialog
	( toplevel, "Hlp_shell", args, n);
      
      newfont = XLoadQueryFont (XtDisplay(dialog_hlp), "6x13");
      newfontlist = XmFontListCreate (newfont, XmFONTLIST_DEFAULT_TAG);
      
      n = 0;
      XtSetArg (args[n], XmNx, 10); n++;
      XtSetArg (args[n], XmNy, 0); n++;
      XtSetArg (args[n], XmNcolumns, 83); n++;
      XtSetArg (args[n], XmNrows, 52); n++;
      XtSetArg (args[n], XmNeditMode, XmMULTI_LINE_EDIT); n++;
      XtSetArg (args[n], XmNfontList, newfontlist); n++;
      XtSetArg (args[n], XmNcursorPositionVisible, False); n++;
      XtSetArg (args[n], XmNeditable, False); n++;
      XtSetArg (args[n], XmNforeground, 0); n++;
      text_hlp = (Widget) XmCreateScrolledText(dialog_hlp, "Raw_text", args, n);  
    }
  
  sprintf(fname,"%s.hlp",hname);
  ReadTextFromFile (text_hlp,fname);
  XmTextSetCursorPosition(text_hlp,0);
  XtManageChild(text_hlp);
  XtManageChild(dialog_hlp);
}

/* Selection of the "Ischemic/Heart rate related changes" mode */
void CBIshemic (w, client_data, call_data)
Widget w;
caddr_t  client_data;
caddr_t  call_data;
{
  int n;
  Arg args[10]; 
  char message[LEN_SHORTER];
  XmString message_string,title_string;

 if ( filevalid == 1 )
   {
     diff = IMPORTANT;
     bootvalid = 0;
     extremavalid = 0;
     rawvalid = 0;
     sprintf(message,"Evaluation: %s  Evaluation mode: Ischemic/Heart-rate related changes",RemoveDot(file_name));
     ModeString = XmStringCreateLtoR (message,XmSTRING_DEFAULT_CHARSET);
     XtVaSetValues(mess_w, XmNlabelString, ModeString, NULL);
   }
  else
    {
      sprintf (message, "   Select evaluation project   ");
      message_string = XmStringCreateLtoR (message, XmSTRING_DEFAULT_CHARSET);
      n = 0;
      XtSetArg (args[n], XmNmessageString, message_string); n++;
      title_string = XmStringCreateLtoR ("Mode selection", XmSTRING_DEFAULT_CHARSET);
      XtSetArg (args[n], XmNdialogTitle, title_string); n++;
      XtSetValues (mb, args, n);
      XtManageChild (mb);
    }
}

/* Selection of the "ST segment changes" mode */
void CBSt (w, client_data, call_data)
Widget w;
caddr_t  client_data;
caddr_t  call_data;
{
  int n;
  Arg args[10]; 
  char message[LEN_SHORTER];
  XmString message_string,title_string;

  if ( filevalid == 1 )
    {
     diff = NO_MATTER;
     bootvalid = 0; 
     extremavalid = 0;
     rawvalid = 0;
     sprintf(message,"Evaluation: %s  Evaluation mode: ST segment changes",RemoveDot(file_name));
     ModeString = XmStringCreateLtoR (message,XmSTRING_DEFAULT_CHARSET);
     XtVaSetValues(mess_w, XmNlabelString, ModeString, NULL);
   }
  else
    {
      sprintf (message, "   Select evaluation project   ");
      message_string = XmStringCreateLtoR (message, XmSTRING_DEFAULT_CHARSET);
      
      n = 0;
      XtSetArg (args[n], XmNmessageString, message_string); n++;
      title_string = XmStringCreateLtoR ("Mode selection", XmSTRING_DEFAULT_CHARSET);
      XtSetArg (args[n], XmNdialogTitle, title_string); n++;
      XtSetValues (mb, args, n);
      XtManageChild (mb);
    }
}

/* Unmanages the "Select evaluation project" dialog */
void CBMode_message (w, client_data, call_data)
Widget w;
caddr_t  client_data;
caddr_t  call_data;
{
   XtUnmanageChild(mb);
}

/* Unmanages the Evaluate dialog */
void CBEvaluate_message (w, client_data, call_data)
Widget w;
caddr_t  client_data;
caddr_t  call_data;
{
   XtUnmanageChild(eb);
}

/* Unmanages dialog for file read/write error */
void CBFile_message (w, client_data, call_data)
Widget w;
caddr_t  client_data;
caddr_t  call_data;
{
   XtUnmanageChild(fbb);
}

/* Evaluation of a single record */
void CBRead_record(w, client_data, call_data)
Widget w;
caddr_t  client_data;
caddr_t  call_data;
{
  XmSelectionBoxCallbackStruct *cs =
    (XmSelectionBoxCallbackStruct *) call_data;
  char *text[NAME_LEN];
  char dat_1[NAME_LEN], dat_2[NAME_LEN], dat_3[NAME_LEN], dat_4[NAME_LEN],dat[NAME_LEN];
  char ref[NAME_LEN], alg[NAME_LEN], ave[NAME_LEN], name[NAME_LEN], tString[NAME_LEN];
  char buf[LEN_SHORTER],rc_name1[NAME_LEN],rc_name2[NAME_LEN],rc_name3[NAME_LEN];
  int Y,n,i;
  char message[LEN_SHORTER];
  XmString message_string,title_string;
  Arg args[10];
  FILE *fs,*in;
  XFontStruct *newfont;
  XmFontList newfontlist;
  static Widget text_ebe;
  XmTextPosition pos=0;
  int rlen;

  ClearScreen();
  
  XmStringGetLtoR (cs->value, XmSTRING_DEFAULT_CHARSET, text);
  rlen=strlen(*text);

  strcpy(dat_1,path);
  strcpy(dat_2,path);
  strcpy(dat_3,path);  

  in=fopen(alg_name,"rt");
  if (Test(in,alg_name)==-1)
    {
      return;
    }
  fscanf(in,"%s",rc_name2);
  strcpy(rc_name1,GetName(rc_name2));
  strcpy(rc_name2,rc_name1);
  while ((strcmp(rc_name2,*text)!=0) && (!feof(in)))
    {
      fscanf(in,"%s",rc_name3);
      strcpy(rc_name2,GetName(rc_name3));
    }
  fclose(in);
  if ((strcmp(rc_name2,*text)!=0)&&(rlen==0))
    strcpy(*text,rc_name1);
  else if ((strcmp(rc_name2,*text)!=0)&&(rlen!=0))
    {
      sprintf( message, " Can't open file %s",GetName(*text));
      message_string = XmStringCreateLtoR (message, XmSTRING_DEFAULT_CHARSET);
      XtSetArg (args[0], XmNmessageString, message_string);
      XtSetValues(fbb, args, 1);
      XtManageChild(fbb); 
      return;
    }
   strcpy(name,*text);
  strcpy(rec_name,*text);

  if ( Single(dat_1,*text,diff) == -1 ) 
     return;

  if ( diff == IMPORTANT )
    {
      Draw_matrix_3x3(20/*65*/,30,340/*285*/,120,"Sensitivity (Se)");
      Draw_matrix_3x3(400,30,340/*285*/,120,"Pos. pred. (+P)");
      Draw_Se_matrix_3x3( 20/*65*/, 30, 340/*285*/, 120, allref);
      Draw_P_matrix_3x3( 400, 30, 340/*285*/, 120, allalg);
    }
   else
    { 
      Draw_matrix_2x2(65, 30,285,120,"Sensitivity (Se)");
      Draw_matrix_2x2(400, 30,285,120,"Pos. pred. (+P)");
      Draw_Se_matrix_2x2( 65, 30, 285, 120, allref);
      Draw_P_matrix_2x2( 400, 30, 285, 120, allalg);
    }
 
  if ( diff == IMPORTANT )
    {
      sprintf(buf,"Episodes:           annotated:%6d,", allref.num_epi);
      Draw_text_font(buf, 65, 190, "8x13");
      sprintf(buf,"detected:    %6d,", allalg.num_epi); 
      Draw_text(buf, 400, 190);
      sprintf(buf,"Per.of ischemia:    annotated:%6.2lf,", allref.percent);
      Draw_text(buf, 65, 210);
      sprintf(buf,"detected:    %6.2lf,", allalg.percent);
      Draw_text(buf, 400, 210);
      if ( allref.se == -1.0 )
	sprintf(buf,"IE Se [%%] =  undefined  ");
      else
	sprintf(buf,"IE Se [%%] =  %6.2lf  ",allref.se );
      Draw_text(buf,65,240);
      if ( allref.ish_dur == -1.0 )
	sprintf(buf,"ID Se [%%] =  undefined ");
      else
	sprintf(buf,"ID Se [%%] =  %6.2lf",allref.ish_dur);
      Draw_text(buf,65,260);
      if ( allalg.se == -1.0 )
	sprintf(buf,"IE +P [%%] =  undefined  ");
      else
	sprintf(buf,"IE +P [%%] =  %6.2lf  ",allalg.se );
      Draw_text(buf,400,240);
      if ( allalg.ish_dur == -1.0 )
	sprintf(buf,"ID +P [%%] =  undefined ");
      else
	sprintf(buf,"ID +P [%%] =  %6.2lf",allalg.ish_dur);
      Draw_text(buf,400,260);
    }
  else
    {
      sprintf(buf,"Episodes:           annotated:%6d,", allref.num_epi);
      Draw_text_font(buf, 65, 190, "8x13");
      sprintf(buf,"detected:    %6d,", allalg.num_epi); 
      Draw_text(buf, 400, 190);
      sprintf(buf,"Per.of ST changes:  annotated:%6.2lf,", allref.percent);
      Draw_text(buf, 65, 210);
      sprintf(buf,"detected:    %6.2lf,", allalg.percent);
      Draw_text(buf, 400, 210);
      if ( allref.se == -1.0 )
	sprintf(buf,"SE Se [%%] =  undefined  ");
      else
	sprintf(buf,"SE Se [%%] =  %6.2lf  ",allref.se );
      Draw_text(buf,65,240);
      if ( allref.ish_dur == -1.0 )
	sprintf(buf,"SD Se [%%] =  undefined ");
      else
	sprintf(buf,"SD Se [%%] =  %6.2lf",allref.ish_dur);
      Draw_text(buf,65,260);
      if ( allalg.se == -1.0 )
	sprintf(buf,"SE +P [%%] =  undefined  ");
      else
	sprintf(buf,"SE +P [%%] =  %6.2lf  ",allalg.se );
      Draw_text(buf,400,240);
      if ( allalg.ish_dur == -1.0 )
	sprintf(buf,"SD +P [%%] =  undefined ");
      else
	sprintf(buf,"SD +P [%%] =  %6.2lf",allalg.ish_dur);
      Draw_text(buf,400,260);
    }

  PaintScreen();
  sprintf(buf,"Record: %s", name);
  Draw_text_font(buf,25,310,"6x13");
  Draw_text_font("Lead 0",25,340,"6x13");
  Draw_single_frame(65,340,620,0);
  Draw_single_graph(65,340,620,5,0,ep_lead0);
  Draw_text_font("Lead 1",25,370,"6x13");
  Draw_single_frame(65,370,620,0);
  Draw_single_graph(65,370,620,5,0,ep_lead1);
  Draw_text_font("Lead 2",25,400,"6x13");
  Draw_single_frame(65,400,620,0);
  Draw_single_graph(65,400,620,5,0,ep_lead2);
  Draw_text_font("Alg",25,425,"8x13");
  Draw_single_frame(65,430,620,0);
  Draw_single_graph(65,430,620,5,1,epialg);
  Draw_text_font("Ref",25,445,"8x13");
  Draw_single_graph(65,430,620,-5,1,epiref);
  Draw_single_frame(65,475,620,1);

  for (i=0;i<tot_rec;i++)
    if (strcmp(evaluated[i].rec,name)==0)
      {
	if (diff == IMPORTANT) evaluated[i].is=1;
	if (diff == NO_MATTER) evaluated[i].st=1;
      } 
  if (!dialog_ebe)
    {
      n = 0;
      XtSetArg (args[n], XmNtitle, " Episode by episode report "); n++;
      XtSetArg (args[n], XmNallowShellResize, True); n++;
      dialog_ebe = (Widget) XmCreateBulletinBoardDialog
	( toplevel, "Ebe_shell", args, n);
      
      newfont = XLoadQueryFont (XtDisplay(dialog_ebe), "6x13");
      newfontlist = XmFontListCreate (newfont, XmFONTLIST_DEFAULT_TAG);
      
      n = 0;
      XtSetArg (args[n], XmNx, 10); n++;
      XtSetArg (args[n], XmNy, 0); n++;
      XtSetArg (args[n], XmNcolumns, 83); n++;
      XtSetArg (args[n], XmNrows, 52); n++;
      XtSetArg (args[n], XmNeditMode, XmMULTI_LINE_EDIT); n++;
      XtSetArg (args[n], XmNfontList, newfontlist); n++;
      XtSetArg (args[n], XmNcursorPositionVisible, False); n++;
      XtSetArg (args[n], XmNeditable, False); n++;
      XtSetArg (args[n], XmNforeground, 0); n++;
      text_ebe = (Widget) XmCreateScrolledText(dialog_ebe, "Ebe_text", args, n);  
    }

  n=0;
  sprintf(tString,"Episode by episode report, record: %s",name); 
  XtSetArg (args[n], XmNdialogTitle, XmStringCreateLtoR(tString, XmSTRING_DEFAULT_CHARSET)); n++;
  XtSetValues (dialog_ebe, args, n);
  XmTextSetString(text_ebe,writeX);
  XmTextSetCursorPosition(text_ebe,0);
  XtManageChild(text_ebe);
  XtManageChild(dialog_ebe);
  
  if (dialog_stt) EStats();

  sprintf(dat_4,"%s%s.%s",RemoveDot(alg_name),diff==IMPORTANT?"_ih":"_st",rec_name);
  fs = fopen(dat_4,"w");
  if (Test_out(fs,dat_4)==-1) ;
  else
    {
      fprintf(fs,"%s",writeX);
      fclose(fs);
    }
}  

/* Select a single record */
void CBSingle (w, client_data, call_data)
Widget w;
caddr_t  client_data;
caddr_t  call_data;
{
  Widget cbs, textW;
  XmString title_string;
  int n;
  Arg args[10]; 
  char message[LEN_SHORTER],FstRec[NAME_LEN], name[NAME_LEN];
  XmString message_string;
  XmString label_string,name_string;
  FILE *in;

  if ( filevalid == 1 )
    {
      n = 0;
      title_string = XmStringCreateLtoR ("Single record", XmSTRING_DEFAULT_CHARSET);
      label_string = XmStringCreateLtoR ("Record:",XmSTRING_DEFAULT_CHARSET);
      XtSetArg (args[n], XmNdialogTitle, title_string); n++;
      XtSetArg (args[n], XmNselectionLabelString, label_string); n++;
      cbs = XmCreatePromptDialog (w, "cbs", args, n);
      XtUnmanageChild (XmSelectionBoxGetChild (cbs, XmDIALOG_HELP_BUTTON));
      if ( bw == 0 )
        {
	  n=0;
	  name_string = XmStringCreateLocalized(name);
          XtSetArg (args[n], XmNforeground, XBlackPixel(XtDisplay (cbs), XtWindow (cbs)));n++;
	  XtSetArg (args[n], XmNselectionLabelString, label_string); n++;
          XtSetValues (cbs, args, n);
          XtSetValues (XmSelectionBoxGetChild (cbs, XmDIALOG_TEXT), args, n);
	  textW = XmSelectionBoxGetChild (cbs,XmDIALOG_TEXT);
        }
      XtAddCallback (cbs, XmNokCallback, CBRead_record, NULL);      
      XtManageChild(cbs);
    }
   else
     {
       sprintf (message, "   Select evaluation project   ");
       message_string = XmStringCreateLtoR (message, XmSTRING_DEFAULT_CHARSET);
       
       n = 0;
       XtSetArg (args[n], XmNmessageString, message_string); n++;
       title_string = XmStringCreateLtoR ("Single record", XmSTRING_DEFAULT_CHARSET);
       XtSetArg (args[n], XmNdialogTitle, title_string); n++;
       
       XtSetValues (mb, args, n);
       XtManageChild(mb);
     }
}

/* Evaluation of the entire database selected */
void CBAll (w, client_data, call_data)
Widget w;
caddr_t  client_data;
caddr_t  call_data;
{
  char buf[NAME_LEN], dat_1[NAME_LEN], dat_4[NAME_LEN], dat_3[NAME_LEN];
  int dist1, dist2, dist, n,i;
  char message[LEN_SHORTER] ,w1_name[NAME_LEN];
  XmString message_string,title_string;
  Arg args[10];
  FILE *fw, *fs;
  static Widget text_raw;
  XFontStruct *newfont;
  XmFontList newfontlist;
  XmTextPosition pos=0;
 
  dist1 = dist2 = dist = 0;
  ClearScreen();
  if ( filevalid == 1 )
   {
     rawvalid = 1;
     all_records(dat1, diff);

     if (all_valid==0) return;
     else all_valid=0;

     if ( diff == IMPORTANT ) rawi=1;
     if ( diff == NO_MATTER ) raws=1;    
     dist = 80;
     dist1 = 140;
     dist2 = 170;

     if ( diff == IMPORTANT )
       {
         Draw_matrix_3x3(20/*60*/,20+dist,340/*285*/,120,"Sensitivity (Se)");
         Draw_matrix_3x3(400,20+dist,340/*285*/,120,"Pos. pred. (+P)");
         Draw_Se_matrix_3x3( 20/*60*/, 20+dist, 340/*285*/, 120, allref);
         Draw_P_matrix_3x3( 400, 20+dist, 340/*285*/, 120, allalg);
       }
      else
       { 
         Draw_matrix_2x2(60,20+dist,285,120,"Sensitivity (Se)");
         Draw_matrix_2x2(400,20+dist,285,120,"Pos. pred. (+P)");
         Draw_Se_matrix_2x2( 60, 20+dist, 285, 120, allref);
         Draw_P_matrix_2x2( 400, 20+dist, 285, 120, allalg);
       }
     if ( diff == IMPORTANT )
       {
	 sprintf(buf,"Episodes:          annotated: %6d,", allref.num_epi);
	 Draw_text_font(buf, 60, 170+dist1, "8x13");
	 sprintf(buf,"detected:     %6d,", allalg.num_epi); 
	 Draw_text(buf, 400, 170+dist1);
	 sprintf(buf,"Per.of ischemia:   annotated: %6.2lf,", allref.percent);
	 Draw_text(buf, 60, 190+dist1);
	 sprintf(buf,"detected:     %6.2lf,", allalg.percent);
	 Draw_text(buf, 400, 190+dist1);
	 sprintf(buf,"IE Se [%%] = %6.2lf [g],    %6.2lf [a]",
		 allref.se,allref.ase);
	 Draw_text_font(buf, 60, 240+dist2, "8x13");
	 sprintf(buf,"ID Se [%%] = %6.2lf [g],    %6.2lf [a]",
		 allref.ish_dur, allref.aish_dur);
	 Draw_text(buf, 60, 260+dist2);
	 sprintf(buf,"IE +P [%%] = %6.2lf [g],    %6.2lf [a]",
		 allalg.se, allalg.ase);
	 Draw_text(buf, 400, 240+dist2);
	 sprintf(buf,"ID +P [%%] = %6.2lf [g],    %6.2lf [a]",
		 allalg.ish_dur, allalg.aish_dur);
	 Draw_text(buf, 400, 260+dist2);
       }
     else
       {
	 sprintf(buf,"Episodes:          annotated: %6d,", allref.num_epi);
	 Draw_text_font(buf, 60, 170+dist1, "8x13");
	 sprintf(buf,"detected:     %6d,", allalg.num_epi); 
	 Draw_text(buf, 400, 170+dist1);
	 sprintf(buf,"Per.of ST changes: annotated: %6.2lf,", allref.percent);
	 Draw_text(buf, 60, 190+dist1);
	 sprintf(buf,"detected:     %6.2lf,", allalg.percent);
	 Draw_text(buf, 400, 190+dist1);
	 sprintf(buf,"SE Se [%%] = %6.2lf [g],    %6.2lf [a]",
		 allref.se,allref.ase);
	 Draw_text_font(buf, 60, 240+dist2, "8x13");
	 sprintf(buf,"SD Se [%%] = %6.2lf [g],    %6.2lf [a]",
		 allref.ish_dur, allref.aish_dur);
	 Draw_text(buf, 60, 260+dist2);
	 sprintf(buf,"SE +P [%%] = %6.2lf [g],    %6.2lf [a]",
		 allalg.se, allalg.ase);
	 Draw_text(buf, 400, 240+dist2);
	 sprintf(buf,"SD +P [%%] = %6.2lf [g],    %6.2lf [a]",
		 allalg.ish_dur, allalg.aish_dur);
	 Draw_text(buf, 400, 260+dist2);
       }
     PaintScreen();
     if (!dialog_raw)
       {
	 n = 0;
	 XtSetArg (args[n], XmNtitle, " Record by record statistics "); n++;
	 XtSetArg (args[n], XmNallowShellResize, True); n++;
	 dialog_raw = (Widget) XmCreateBulletinBoardDialog
	   ( toplevel, "Raw_shell", args, n);
	 
	 newfont = XLoadQueryFont (XtDisplay(dialog_raw), "6x13");
	 newfontlist = XmFontListCreate (newfont, XmFONTLIST_DEFAULT_TAG);
	 
	 n = 0;
	 XtSetArg (args[n], XmNx, 10); n++;
	 XtSetArg (args[n], XmNy, 0); n++;
	 XtSetArg (args[n], XmNcolumns, 83); n++;
	 XtSetArg (args[n], XmNrows, 52); n++;
	 XtSetArg (args[n], XmNeditMode, XmMULTI_LINE_EDIT); n++;
	 XtSetArg (args[n], XmNfontList, newfontlist); n++;
	 XtSetArg (args[n], XmNcursorPositionVisible, False); n++;
	 XtSetArg (args[n], XmNeditable, False); n++;
	 XtSetArg (args[n], XmNforeground, 0); n++;
	 text_raw = (Widget) XmCreateScrolledText(dialog_raw, "Raw_text", args, n);  
       }
     if (dialog_stt) EStats();
     write_rbr();
     XmTextSetString(text_raw,writeX);
     XmTextSetCursorPosition(text_raw,0);
     XtManageChild(text_raw);
     XtManageChild(dialog_raw);
     sprintf(w1_name,"%s%s.raw",RemoveDot(alg_name),diff==IMPORTANT?"_ih":"_st");
     write_raw(w1_name,diff);
     write_rbr_file();
   }
  else
    {
      sprintf (message, "   Select evaluation project   ");
      message_string = XmStringCreateLtoR (message, XmSTRING_DEFAULT_CHARSET);
      
      n = 0;
      XtSetArg (args[n], XmNmessageString, message_string); n++;
      title_string = XmStringCreateLtoR ("Raw statistics", XmSTRING_DEFAULT_CHARSET);
      XtSetArg (args[n], XmNdialogTitle, title_string); n++;      
      XtSetValues (mb, args, n);
      XtManageChild(mb);
    }
}

/* Examining ST segment deviation measurements */
void CBExamine (Widget w, XtPointer client_data, XtPointer call_data)
{
  int num;
  XmDrawingAreaCallbackStruct *cbs = (XmDrawingAreaCallbackStruct *) call_data;

  if (( cbs->event->xany.type == ButtonPress ) && (cbs->event->xbutton.button == 1) && (examine_valid==1))
    {
      num = find_pixel(cbs->event->xbutton.x,
		       cbs->event->xbutton.y, st_tab);
      Draw_wished(180, 640, st_tab[num]);
    }
  else if ((cbs->event->xany.type == KeyPress ) && (examine_valid == 1))
    {
      num = find_pixel(cbs->event->xbutton.x,
		       cbs->event->xbutton.y, st_tab);
      Draw_wished(180, 640, st_tab[num]);
    }  
  PaintScreen();
}

/* Evaluation of ST segment deviation measurements */
void CBExtrema (w, client_data, call_data)
Widget w;
caddr_t  client_data;
caddr_t  call_data;
{
  int done = 0;
  int num, n;
  char message[LEN_SHORTER], dat_4[NAME_LEN];
  XmString message_string,title_string;
  Arg args[10];
  static Widget text_ext;
  XFontStruct *newfont;
  XmFontList newfontlist;
 
  ClearScreen();

  if ( filevalid == 1 )
   {
     st_deviation( dat1, diff);
     if (dev_valid==0) return;
     else dev_valid=0;
     XSelectInput (XtDisplay(workarea), XtWindow(workarea),
		   ButtonPressMask | LeaveWindowMask | ExposureMask );
     extremavalid = 1;
     examine_valid = 1;
     Draw_frame_graph(150, 510);
     Draw_graph (150, 510);
     Draw_extrema_results(150, 590);
     Draw_reg_line(150, 510);
     PaintScreen();
     if ( diff == IMPORTANT ) exti=1;
     if ( diff == NO_MATTER ) exts=1;

     if (!dialog_ext)
       {
	 n = 0;
	 XtSetArg (args[n], XmNtitle, " Extrema statistics "); n++;
	 XtSetArg (args[n], XmNallowShellResize, True); n++;
	 dialog_ext = (Widget) XmCreateBulletinBoardDialog
	   ( toplevel, "Ext_shell", args, n);
	 
	 newfont = XLoadQueryFont (XtDisplay(dialog_ext), "6x13");
	 newfontlist = XmFontListCreate (newfont, XmFONTLIST_DEFAULT_TAG);
	 
	 n = 0;
	 XtSetArg (args[n], XmNx, 10); n++;
	 XtSetArg (args[n], XmNy, 0); n++;
	 XtSetArg (args[n], XmNcolumns, 109); n++;
	 XtSetArg (args[n], XmNrows, 52); n++;
	 XtSetArg (args[n], XmNeditMode, XmMULTI_LINE_EDIT); n++;
	 XtSetArg (args[n], XmNfontList, newfontlist); n++;
	 XtSetArg (args[n], XmNcursorPositionVisible, False); n++;
	 XtSetArg (args[n], XmNeditable, False); n++;
	 XtSetArg (args[n], XmNforeground, 0); n++;
	 text_ext = (Widget) XmCreateScrolledText(dialog_ext, "ext_text", args, n);  
       }

     if (dialog_stt) EStats();
     XmTextSetString(text_ext,writeX);
     XmTextSetCursorPosition(text_ext,0);
     XtManageChild(text_ext);
     XtManageChild(dialog_ext);
     write_ebe();
   }
  else
    {
      sprintf (message, "   Select evaluation project   ");
      message_string = XmStringCreateLtoR (message, XmSTRING_DEFAULT_CHARSET);
      
      n = 0;
      XtSetArg (args[n], XmNmessageString, message_string); n++;
      title_string = XmStringCreateLtoR ("Extrema", XmSTRING_DEFAULT_CHARSET);
      XtSetArg (args[n], XmNdialogTitle, title_string); n++;      
      XtSetValues (mb, args, n);
      XtManageChild(mb);
    }
}

/* Bootstrap method */
void CBBoot (w, client_data, call_data)
Widget w;
caddr_t  client_data;
caddr_t  call_data;

{
  int i, n;
  char message[LEN_SHORTER],dat_3[NAME_LEN];
  XmString message_string,title_string;
  Arg args[10];
  XFontStruct *newfont;
  XmFontList newfontlist;
  FILE *fa;
  static Widget text_bts;

  ClearScreen();

  if ( filevalid == 1 )
   {
     all_records(dat1, diff);

     if (all_valid==0) return;
     else all_valid=0;

     bootstrap(diff,trials1);
     strcpy(writeX,"");
     Xwrite_boot(text_bts);

     if ( diff == IMPORTANT ) boti=1;
     if ( diff == NO_MATTER ) bots=1;
     if (dialog_stt) EStats();

     Draw_boot_frame(90,330,540,320);
     Draw_hist1(90,330,540,320);
     Draw_boot_frame(90,660,540,320);
     Draw_hist2(90,660,540,320);
     PaintScreen();
     bootvalid = 1;
     examine_valid=0;

     if (!dialog_bts)
       {
	 n = 0;
	 XtSetArg (args[n], XmNtitle, " Bootstrap method "); n++;
	 XtSetArg (args[n], XmNallowShellResize, True); n++;
	 dialog_bts = (Widget) XmCreateBulletinBoardDialog
	   ( toplevel, "Bootstrap_shell", args, n);
	 
	 newfont = XLoadQueryFont (XtDisplay(dialog_bts), "6x13");
	 newfontlist = XmFontListCreate (newfont, XmFONTLIST_DEFAULT_TAG);
	 
	 n = 0;
	 XtSetArg (args[n], XmNx, 10); n++;
	 XtSetArg (args[n], XmNy, 0); n++;
	 XtSetArg (args[n], XmNcolumns, 94); n++;
	 XtSetArg (args[n], XmNrows, 52); n++;
	 XtSetArg (args[n], XmNeditMode, XmMULTI_LINE_EDIT); n++;
	 XtSetArg (args[n], XmNfontList, newfontlist); n++;
	 XtSetArg (args[n], XmNcursorPositionVisible, False); n++;
	 XtSetArg (args[n], XmNeditable, False); n++;
	 XtSetArg (args[n], XmNforeground, 0); n++;
	 text_bts = (Widget) XmCreateScrolledText(dialog_bts, "Bootstrap_text", args, n);  
       }
     XmTextSetString(text_bts,writeX);
     XmTextSetCursorPosition(text_bts,0);
     XtManageChild(text_bts);
     XtManageChild(dialog_bts);
     sprintf(dat_3,"%s%s.bts",RemoveDot(alg_name),diff==IMPORTANT?"_ih":"_st");
     write_boot1(dat_3,diff,10000);
  }
  else
    {
      sprintf (message, "   Select evaluation project   ");
      message_string = XmStringCreateLtoR (message, XmSTRING_DEFAULT_CHARSET);

      n = 0;
      XtSetArg (args[n], XmNmessageString, message_string); n++;
      title_string = XmStringCreateLtoR ("Bootstrap", XmSTRING_DEFAULT_CHARSET);
      XtSetArg (args[n], XmNdialogTitle, title_string); n++;  
      XtSetValues (mb, args, n);
      XtManageChild(mb);
    }
}

/* Comparing results of different algorithms/databases */
void CBFreeze (w, client_data, call_data)
Widget w;
caddr_t  client_data;
caddr_t  call_data;
{
  FILE *fp;
  char namealg[NAME_LEN], dat_1[NAME_LEN],dat[NAME_LEN];
  char namecri[NAME_LEN];
  char message[LEN_SHORTER];
  XmString message_string,title_string;
  Arg args[10];
  int n;
  XFontStruct *newfont;
  XmFontList newfontlist;
  static Widget text_smr1,text_smr2,text_smr3;

  if ( filevalid == 1 )
    {
      strcpy(namealg,dat2);
      str_delete(namealg, 0, strlen(dat2) - 3);
      if ( diff == IMPORTANT )
        strcpy(namecri,"Ischemic");
      else
        strcpy(namecri,"ST Changes");
      if (!dialog_smr)
	{
	  title_string = XmStringCreateLtoR ("Comparison of algorithms ", 
					     XmSTRING_DEFAULT_CHARSET);
	  n = 0;
	  XtSetArg (args[n], XmNtitle, "Comparison of algorithms"); n++;
	  XtSetArg (args[n], XmNallowShellResize, True); n++;
	  dialog_smr = (Widget) XmCreateBulletinBoardDialog
	    ( toplevel, "Smr_shell", args, n);
	  
	  newfont = XLoadQueryFont (XtDisplay(dialog_smr), "6x13");
	  newfontlist = XmFontListCreate (newfont, XmFONTLIST_DEFAULT_TAG);
	  
	  n = 0;
	  XtSetArg (args[n], XmNx, 10); n++;
	  XtSetArg (args[n], XmNy, 0); n++;
	  XtSetArg (args[n], XmNcolumns, 46); n++;
	  XtSetArg (args[n], XmNrows, 12); n++;
	  XtSetArg (args[n], XmNeditMode, XmMULTI_LINE_EDIT); n++;
	  XtSetArg (args[n], XmNcursorPositionVisible, False); n++;
	  XtSetArg (args[n], XmNeditable, False); n++;
	  XtSetArg (args[n], XmNfontList, newfontlist); n++;
	  XtSetArg (args[n], XmNforeground, 0); n++;
	  
	  text_smr1 = (Widget) XmCreateText(dialog_smr, "text_smr1", args, n);  
	  
	  n = 0;
	  XtSetArg (args[n], XmNx, 10); n++;
	  XtSetArg (args[n], XmNy, 195); n++;
	  XtSetArg (args[n], XmNcolumns, 46); n++;
	  XtSetArg (args[n], XmNrows, 12); n++;
	  XtSetArg (args[n], XmNeditMode, XmMULTI_LINE_EDIT); n++;
	  XtSetArg (args[n], XmNcursorPositionVisible, False); n++;
	  XtSetArg (args[n], XmNeditable, False); n++;
	  XtSetArg (args[n], XmNfontList, newfontlist); n++;
	  XtSetArg (args[n], XmNforeground,0 ); n++;
	  text_smr2 = (Widget) XmCreateText(dialog_smr, "text_smr2", args, n);  

	  n = 0;
	  XtSetArg (args[n], XmNx, 10); n++;
	  XtSetArg (args[n], XmNy, 380); n++;
	  XtSetArg (args[n], XmNcolumns, 46); n++;
	  XtSetArg (args[n], XmNrows, 12); n++;
	  XtSetArg (args[n], XmNeditMode, XmMULTI_LINE_EDIT); n++;
	  XtSetArg (args[n], XmNcursorPositionVisible, False); n++;
	  XtSetArg (args[n], XmNeditable, False); n++;
	  XtSetArg (args[n], XmNfontList, newfontlist); n++;
	  XtSetArg (args[n], XmNforeground, 0); n++;
	  text_smr3 = (Widget) XmCreateText(dialog_smr, "text_smr3", args, n);  
	  
	  n=0;
	  XtSetArg (args[n],XmNforeground, XBlackPixel (XtDisplay (dialog_smr), XtWindow (dialog_smr)));
	  XtSetValues (text_smr1 , args, 1); 
	  XtSetValues (text_smr2 , args, 1); 
	  XtSetValues (text_smr3 , args, 1); 
	}
      strcpy(writeX,"");
      if (diff == IMPORTANT )
	sprintf(dat,"Evaluation: %s  \nEvaluation mode: \nIschemic/Heart-rate related changes\n",RemoveDot(file_name));
      else 
	sprintf(dat,"Evaluation: %s  \nEvaluation mode: \nST segment changes\n",RemoveDot(file_name));
      strcat(writeX,dat);
      if ( rawvalid == 1 )
        {
	  if (diff == IMPORTANT)
	    {
	      sprintf(dat, "Raw statistics:\n");
	      strcat(writeX,dat);
	      sprintf(dat, "IE Se [%%] = %6.2lf [a]  IE +P [%%] = %6.2lf [a]\n", allref.ase, allalg.ase);
	      strcat(writeX,dat);
	      sprintf(dat, "ID Se [%%] = %6.2lf [a]  ID +P [%%] = %6.2lf [a]\n",allref.aish_dur, allalg.aish_dur);
	      strcat(writeX,dat);
	    }
	  else
	    {
	      sprintf(dat, "Raw statistics:\n");
	      strcat(writeX,dat);
	      sprintf(dat, "SE Se [%%] = %6.2lf [a]  SE +P [%%] = %6.2lf [a]\n",allref.ase, allalg.ase);
	      strcat(writeX,dat);
	      sprintf(dat, "SD Se [%%] = %6.2lf [a]  SD +P [%%] = %6.2lf [a]\n",allref.aish_dur, allalg.aish_dur);
	      strcat(writeX,dat);
	    }
	}
      if ( bootvalid == 1 )
        {
	  if (diff == IMPORTANT)
	    {
	      sprintf(dat,"5 %% confidence limits: \n");
	      strcat(writeX,dat);
	      sprintf(dat, "IE Se [%%] = %6.2lf [a]  IE +P [%%] = %6.2lf [a]\n",asensr[0], apredr[0]);
	      strcat(writeX,dat);
	      sprintf(dat, "ID Se [%%] = %6.2lf [a]  ID +P [%%] = %6.2lf [a]\n",adurser[0], adurpr[0]);
	      strcat(writeX,dat);
	    }
	  else
	    {
	      sprintf(dat,"5 %% confidence limits: \n");
	      strcat(writeX,dat);
	      sprintf(dat, "SE Se [%%] = %6.2lf [a]  SE +P [%%] = %6.2lf [a]\n",asensr[0], apredr[0]);
	      strcat(writeX,dat);
	      sprintf(dat, "SD Se [%%] = %6.2lf [a]  SD +P [%%] = %6.2lf [a]\n",adurser[0], adurpr[0]);
	      strcat(writeX,dat);
	    }
        }
      if ( extremavalid == 1 )
        {
          sprintf(dat, "ST measurements:\n");
	  strcat(writeX,dat);
          sprintf(dat, "Mean [uV]     = %6.2lf  St.dev [uV]  = %6.2lf\n",
		  mvalue, stand_dev);                   
	  strcat(writeX,dat);
          sprintf(dat, "p(100 uV) [%%] = %6.2lf  e(95 %%) [uV] = %6.2lf\n",
		  phund, enfive);
	  strcat(writeX,dat);
        }

      switch (cur)
	{
        case 1:  
	  XmTextSetString(text_smr1,writeX);
	  XmProcessTraversal(text_smr1,XmTRAVERSE_CURRENT);
	  cur = 2;
	  break;
        case 2:  
	  XmTextSetString(text_smr2,writeX);
	  XmProcessTraversal(text_smr2,XmTRAVERSE_CURRENT);
	  cur = 3;
	  break;
	case 3:  
	  XmTextSetString(text_smr3,writeX);
	  XmProcessTraversal(text_smr3,XmTRAVERSE_CURRENT);
	  cur = 1;
	  break;
	}
      XtManageChild(text_smr1);
      XtManageChild(text_smr2);
      XtManageChild(text_smr3);
      XtManageChild(dialog_smr);      

      sprintf(dat_1,"%s%s.smr%03d",RemoveDot(alg_name),diff==IMPORTANT?"_ih":"_st",numfreeze);
      fp = fopen(dat_1, "w");
      if (Test_out(fp,dat_1)!=-1)
	{
	  fprintf(fp,"%s",writeX);
	  fclose(fp);
	}
      numfreeze++;
      if (numfreeze>=1000) numfreeze=0;
  }
 else
   {
     sprintf (message, "   Select evaluation project   ");
     message_string = XmStringCreateLtoR (message, XmSTRING_DEFAULT_CHARSET);
     
     n = 0;
     XtSetArg (args[n], XmNmessageString, message_string); n++;
     title_string = XmStringCreateLtoR ("Compare", XmSTRING_DEFAULT_CHARSET);
     XtSetArg (args[n], XmNdialogTitle, title_string); n++;
     XtSetValues (mb, args, n);     
     XtManageChild(mb);
   }
}
   
/* Comparing the performance of the algorithms */
void CBDifferences (w, client_data, call_data)
Widget w;
caddr_t  client_data;
caddr_t  call_data;
{
    XtManageChild(eb);
}

String fallback_resources[] = {
         "*title: EVAL_ST  Evaluation of transient ST segment episode detectors",
         "*User.set: True",
         "*Auto.set: True",
	 "*workarea.width: 750",
	 "*workarea.height: 675",
         "*XmScale.minimum: 100",
         "*XmScale.maximum: 16000",
         "*geometry: 761x737",
         "*allowShellResize: True",
         NULL
};

/* File menu */
void file_cb(Widget widget, XtPointer client_data, XtPointer call_data)
{
  int item_no = (int) client_data;
  
  if (item_no == 0)
    CBFile(widget,client_data,call_data);
  else if (item_no == 1)
    CBEStats(widget,client_data,call_data);
  if (item_no == 2)
    exit (0);
}

/* Evaluation_mode menu */
void mode_cb(Widget widget, XtPointer client_data, XtPointer call_data)
{
  int item_no = (int) client_data;
  
  if (item_no == 0)
    CBIshemic(widget,client_data,call_data);
  else if (item_no == 1)
    CBSt(widget,client_data,call_data);
}

/* Aggregate_statistics menu */
void statistics_cb(Widget widget, XtPointer client_data, XtPointer call_data)
{
  int item_no = (int) client_data;
  
  if (item_no == 0)
    CBAll(widget,client_data,call_data);
  else if (item_no == 1)
    CBExtrema(widget,client_data,call_data); 
}

/* Single_record menu */
void single_cb(Widget w, XtPointer client_data, XtPointer call_data)
{
  int item_no = (int) client_data;

  XmString message_string, label_string;
  CBSingle(toplevel,client_data,call_data);
}

/* Bootstrap menu */
void bootstrap_cb(Widget widget, XtPointer client_data, XtPointer call_data)
{
  int item_no = (int) client_data;
  
  if (item_no == 0)
    CBConst_1(widget,client_data,call_data);
  else if (item_no == 1)
    CBBoot(widget,client_data,call_data); 
}

/* Summary menu */
void summary_cb(Widget widget, XtPointer client_data, XtPointer call_data)
{
  int item_no = (int) client_data;
  
  if (item_no == 0)
    CBFreeze(widget,client_data,call_data);
  else if (item_no == 1)
    CBDifferences(widget,client_data,call_data);
}


/* Help menu */
void help_cb(Widget widget, XtPointer client_data, XtPointer call_data)
{
  int item_no = (int) client_data;
  
  if (item_no == 0)
    CBHelp(widget,client_data,call_data);
}

/* Creates the graphic user interface */
void CreateApplication (parent)
Widget parent;
{
  Widget mainwindow, menubar;
  Widget menubarBtn[9];
  Widget pulldowns[5];
  Widget buttons0[2];
  Widget buttons1[3];
  Widget buttons2[2];
  Widget buttons3[2];
  Widget buttons4[2];
  Widget fpulldown, fbut[3],button;
  XmString title_string;
  XmString message_string;
  XSetWindowAttributes attributes;
  unsigned long valuemask;
  XSetWindowAttributes xswa;
  Arg args[20];
  int n;
  char message[LEN_SHORTER];
  XFontStruct *newfont;
  XmFontList newfontlist;
  unsigned long i;
  XmString file, mode, statistics, single, bootstrap, summary, help, label_string;
  XmString open,save,quit,ischr,segment,raw,extrema,trials,evaluate,freeze,differences;
  Widget widget,main_w,rowcol;
  XGCValues gcv;

  main_w = XtVaCreateManagedWidget ("main_window",
				    xmMainWindowWidgetClass,   parent,
				    XmNscrollBarDisplayPolicy, XmAS_NEEDED,
				    XmNscrollingPolicy,        XmAUTOMATIC,
				    NULL);
   
  file = XmStringCreateLocalized ("File");
  mode = XmStringCreateLocalized ("Evaluation_mode");
  statistics = XmStringCreateLocalized ("Aggregate_statistics");
  single = XmStringCreateLocalized ("Single_record");
  bootstrap = XmStringCreateLocalized ("Bootstrap");
  summary = XmStringCreateLocalized ("Summary");
  help = XmStringCreateLocalized ("Help");
  
  menubar = XmVaCreateSimpleMenuBar (main_w, "menubar",
				     XmVaCASCADEBUTTON, file, 'F',
				     XmVaCASCADEBUTTON, mode, 'E',
				     XmVaCASCADEBUTTON, single, 'S',
				     XmVaCASCADEBUTTON, statistics, 'A',
				     XmVaCASCADEBUTTON, bootstrap, 'B',
				     XmVaCASCADEBUTTON, summary, 'm',
				     XmVaCASCADEBUTTON, help, 'H',
				     NULL);

  if (widget = XtNameToWidget (menubar, "button_6"))
    XtVaSetValues (menubar, XmNmenuHelpWidget, widget, NULL);
  XmStringFree(file);
  XmStringFree(mode);
  XmStringFree(statistics);
  XmStringFree(single);
  XmStringFree(bootstrap);
  XmStringFree(summary);
  XmStringFree(help);
  
  open = XmStringCreateLocalized ("Open");
  save = XmStringCreateLocalized ("Examine");
  quit = XmStringCreateLocalized ("Quit");

  XmVaCreateSimplePulldownMenu (menubar, "file_menu", 0, file_cb,
				XmVaPUSHBUTTON, open, 'O', "Ctrl<Key>O", XmStringCreateLocalized ("Ctrl+O"), 
				XmVaPUSHBUTTON, save, 'E', "Ctrl<Key>E", XmStringCreateLocalized ("Ctrl+E"),
				XmVaSEPARATOR, 
				XmVaPUSHBUTTON, quit, 'Q', "Ctrl<Key>Q", XmStringCreateLocalized ("Ctrl+Q"),
				NULL);
  XmStringFree(open);
  XmStringFree(save);
  XmStringFree(quit);

  ischr = XmStringCreateLocalized ("Ischemic/Heart-rate related changes");
  segment = XmStringCreateLocalized("ST segment changes");

  XmVaCreateSimplePulldownMenu (menubar, "mode_menu", 1, mode_cb,
				XmVaPUSHBUTTON, ischr, 'I', "Ctrl<Key>I", XmStringCreateLocalized ("Ctrl+I"), 
				XmVaPUSHBUTTON, segment, 'S', "Ctrl<Key>S", XmStringCreateLocalized ("Ctrl+S"),
				NULL);
  XmStringFree(ischr);
  XmStringFree(segment);

  XmStringFree(trials);
  XmStringFree(evaluate);

  single = XmStringCreateLocalized("Record");

  XmVaCreateSimplePulldownMenu (menubar, "single_menu", 2, single_cb,
				XmVaPUSHBUTTON, single, 'R', "Ctrl<Key>R", XmStringCreateLocalized ("Ctrl+R"), 
				NULL);
  XmStringFree(single);

  raw  = XmStringCreateLocalized("Evaluate");
  extrema  = XmStringCreateLocalized("Extrema");
  
  XmVaCreateSimplePulldownMenu (menubar, "mode_menu", 3, statistics_cb,
				XmVaPUSHBUTTON, raw, 'E', "Ctrl<Key>A", XmStringCreateLocalized ("Ctrl+A"), 
				XmVaPUSHBUTTON, extrema, 'x', "Ctrl<Key>X", XmStringCreateLocalized ("Ctrl+X"),
				NULL);
  XmStringFree(raw);
  XmStringFree(extrema);
  
  trials = XmStringCreateLocalized("Number_of_bootstrap_trials");
  evaluate = XmStringCreateLocalized("Evaluate");

  XmVaCreateSimplePulldownMenu (menubar, "bootstrap_menu", 4, bootstrap_cb,
				XmVaPUSHBUTTON, trials, 'N', "Ctrl<Key>N", XmStringCreateLocalized ("Ctrl+N"), 
				XmVaPUSHBUTTON, evaluate, 'E', "Ctrl<Key>B", XmStringCreateLocalized ("Ctrl+B"), 
				NULL);

  freeze = XmStringCreateLocalized("Compare");
  differences = XmStringCreateLocalized("Differences");

  XmVaCreateSimplePulldownMenu (menubar, "summary_menu", 5, summary_cb,
				XmVaPUSHBUTTON, freeze, 'C', "Ctrl<Key>C", XmStringCreateLocalized ("Ctrl+C"), 
				XmVaPUSHBUTTON, differences, 'D', "Ctrl<Key>D", XmStringCreateLocalized ("Ctrl+D"), 
				NULL);
  XmStringFree(freeze);
  XmStringFree(differences);

  help = XmStringCreateLocalized("Help");
  XmVaCreateSimplePulldownMenu (menubar, "help_menu", 6, help_cb,
				XmVaPUSHBUTTON, help, 'H', "Ctrl<Key>H", XmStringCreateLocalized ("Ctrl+H"), 
				NULL);
  XmStringFree(help);
  XtManageChild(menubar);

  /* Creates workarea in the MainWindow */
  
  rowcol = XtVaCreateWidget ("rowcolumn",
			     xmRowColumnWidgetClass, main_w,
			     XmNorientation, XmVERTICAL,
			     NULL);
  mess_w = XtVaCreateManagedWidget ("Evaluation:          Evaluation mode: ST segment changes",
					  xmLabelWidgetClass, rowcol,
					  XmNalignment,   XmALIGNMENT_BEGINNING,
					  NULL);
  n = 0;
  XtSetArg (args[n], XmNresizePolicy, XmRESIZE_NONE); n++;
  XtSetArg (args[n], XmNmarginWidth, 0); n++;
  
  workarea = (Widget) XmCreateDrawingArea (/*main_w*/rowcol, "workarea", args, n);
  XtAddCallback (workarea, XmNexposeCallback, CBDraw, NULL); 
  XtAddCallback (workarea, XmNinputCallback, CBExamine, NULL); 


  pixmap = XCreatePixmap (XtDisplay (workarea),
			  RootWindowOfScreen (XtScreen (workarea)), W_WIDTH, W_HEIGHT,
			  DefaultDepthOfScreen (XtScreen (workarea)));


  n=0;
  XtSetArg (args[n],XmNbackground, XWhitePixel (XtDisplay (workarea), XtWindow (workarea)));n++;
  XtSetValues (workarea , args, n); 
  
  XtManageChild (workarea);
  XtManageChild (rowcol);
  XmMainWindowSetAreas (main_w, menubar, NULL, NULL, NULL, /*workarea*/rowcol);

  title_string = XmStringCreateLtoR (" Selecting evaluation project ", XmSTRING_DEFAULT_CHARSET);

  n = 0;
  XtSetArg (args[n], XmNdialogTitle, title_string); n++;
  sb = (Widget) XmCreateFileSelectionDialog (parent, "files", args, n);
  XtUnmanageChild ((Widget) 
     XmFileSelectionBoxGetChild (sb, XmDIALOG_HELP_BUTTON));

  if ( bw == 0 )
  {
    XtSetArg (args[0], XmNforeground, XBlackPixel(XtDisplay (sb), XtWindow(sb)));
    XtSetValues (sb, args, 1);
    XtSetValues ((Widget)
      XmFileSelectionBoxGetChild (sb, XmDIALOG_DIR_LIST), args, 1);
    XtSetValues ((Widget)
		 XmFileSelectionBoxGetChild (sb, XmDIALOG_FILTER_TEXT), args, 1);
    XtSetValues ((Widget)
		 XmFileSelectionBoxGetChild (sb, XmDIALOG_LIST), args, 1);
    XtSetValues ((Widget)
		 XmFileSelectionBoxGetChild (sb, XmDIALOG_TEXT), args, 1);
  } 
  XmTextFieldSetString((Widget) XmFileSelectionBoxGetChild (sb, XmDIALOG_FILTER_TEXT),"*.evl");
    XmFileSelectionDoSearch(sb,XmStringCreateLocalized("*.evl"));
  XtAddCallback (sb, XmNokCallback, CBFile_select, NULL );
  XtAddCallback (sb, XmNcancelCallback, CBFile_cancel, NULL ); 

  n = 0;
  title_string = XmStringCreateLtoR ("Bootstrap trials", XmSTRING_DEFAULT_CHARSET);
  label_string = XmStringCreateLtoR ("Number of bootstrap trials:",XmSTRING_DEFAULT_CHARSET);
  XtSetArg (args[n], XmNdialogTitle, title_string); n++;
  XtSetArg (args[n], XmNselectionLabelString, label_string); n++;

  cb1 = XmCreatePromptDialog (parent, "cb1", args, n);
  XtUnmanageChild (XmSelectionBoxGetChild (cb1, XmDIALOG_HELP_BUTTON));
  if ( bw == 0 )
  {
    XtSetArg (args[0], XmNforeground, 0);
    XtSetValues (cb1, args, 1);
    XtSetValues (XmSelectionBoxGetChild (cb1, XmDIALOG_TEXT), args, 1);
    n=0;
    XtSetArg (args[n],XmNforeground, XBlackPixel (XtDisplay (cb1), XtWindow (cb1)));
    XtSetValues (cb1 , args, 1); 
    XtSetValues (XmSelectionBoxGetChild (cb1, XmDIALOG_TEXT), args, 1);
  }
  XtAddCallback (cb1, XmNokCallback, CBSet_const_1, NULL);
  XtAddCallback (cb1, XmNcancelCallback, CBCancel_const_1, NULL);

  sprintf (message, "   Select evaluation project   ");
  message_string = XmStringCreateLtoR (message, XmSTRING_DEFAULT_CHARSET);

  n = 0;
  title_string = XmStringCreateLtoR ("Evaluation", XmSTRING_DEFAULT_CHARSET);
  XtSetArg (args[n], XmNdialogTitle, title_string); n++;
  XtSetArg (args[n], XmNmessageString, message_string); n++;
  mb = XmCreateMessageDialog (parent, "", args, n);
  
  XtUnmanageChild (XmMessageBoxGetChild ( mb, XmDIALOG_CANCEL_BUTTON));
  XtUnmanageChild (XmMessageBoxGetChild ( mb, XmDIALOG_HELP_BUTTON));
  if ( bw == 0 )
   {
     XtSetArg (args[0], XmNforeground, 0);
     XtSetValues (mb, args, 1);
   }
  XtAddCallback (mb, XmNokCallback, CBMode_message, NULL);

  n = 0;
  XtSetArg (args[n], XmNdialogTitle, title_string); n++;
  fbb = XmCreateMessageDialog (parent, "fbb", args, n);
  XtUnmanageChild (XmMessageBoxGetChild ( fbb, XmDIALOG_CANCEL_BUTTON));
  XtUnmanageChild (XmMessageBoxGetChild ( fbb, XmDIALOG_HELP_BUTTON));
  if ( bw == 0 )
   {
     XtSetArg (args[0], XmNforeground, 0);
     XtSetValues (fbb, args, 1);
   }
  XtAddCallback (fbb, XmNokCallback, CBFile_message, NULL);

  sprintf (message, "   Not implemented yet  ");
  message_string = XmStringCreateLtoR (message, XmSTRING_DEFAULT_CHARSET);
  n = 0;
  XtSetArg (args[n], XmNdialogTitle, XmStringCreateLtoR("Differences",XmSTRING_DEFAULT_CHARSET)); n++;
  XtSetArg (args[n], XmNmessageString, message_string); n++;
  eb = XmCreateMessageDialog (parent, "eb", args, n);
  
  XtUnmanageChild (XmMessageBoxGetChild ( eb, XmDIALOG_CANCEL_BUTTON));
  XtUnmanageChild (XmMessageBoxGetChild ( eb, XmDIALOG_HELP_BUTTON));
  if ( bw == 0 )
   {
     XtSetArg (args[0], XmNforeground, 0);
     XtSetValues (eb, args, 1);
   }
  XtAddCallback (eb, XmNokCallback, CBEvaluate_message, NULL);
  return;  
}

/* Initialization of the drawing area and creation of graphic context */
void InitDraw()
{
 XGCValues val,gcv;

 wall_gc=DefaultGC(XtDisplay (workarea), DefaultScreen(XtDisplay(workarea)));
 val.foreground = 0 /*1*/;
 val.background = 1 /*0*/;
 val.function = GXcopy;
 wall_gc = XtGetGC(workarea, GCForeground | GCBackground | GCFunction, &val);
 XSetBackground(XtDisplay(workarea), wall_gc, WhitePixel(XtDisplay(workarea), DefaultScreen(XtDisplay(workarea))));
 XSetForeground(XtDisplay(workarea), wall_gc, WhitePixel(XtDisplay(workarea), DefaultScreen(XtDisplay(workarea))));

 empty_gc=DefaultGC(XtDisplay (workarea), DefaultScreen(XtDisplay(workarea)));

 val.foreground = 1 /*0*/;
 val.background = 0 /*0*/;
 empty_gc = XtGetGC(workarea, GCForeground | GCBackground | GCFunction, &val);

 XSetBackground(XtDisplay(workarea), empty_gc, WhitePixel(XtDisplay(workarea), DefaultScreen(XtDisplay(workarea))));
 XSetForeground(XtDisplay(workarea), empty_gc, BlackPixel(XtDisplay(workarea), DefaultScreen(XtDisplay(workarea))));
 XFillRectangle (XtDisplay (workarea), pixmap, wall_gc, 0, 0, W_WIDTH, W_HEIGHT);
 XtVaSetValues (workarea, XmNuserData, wall_gc, NULL);

}
#endif         /* END OF MOTIF SECTION */

/* Reads the episodes from the file, combines the episodes, and fills the array */
void fill_array(fp,epi1)
FILE *fp;
episode epi1[MAXEPI];
{
  int i,j,k;
  long  time;
  int   event;
  long  extrem;
  int   lead;
  
  i = -1;
  k = 0;
  while ( feof(fp) == 0 )
    {
      fscanf(fp,"%ld%d%ld%d",&time,&event,&extrem,&lead);
      switch(event)
	{
	case -1 : 
	  if (( i>-1 ) && ( diff == NO_MATTER ) && ( time==epi1[i].offset ))
	    {
	      k++;
	    }
	  else
	    { 
	      k++;  
	      if ( k == 1 )
		{
		  i++;
		  epi1[i].onset = time;       /* Beginning */
		  j = 0;
		  if (diff == IMPORTANT)
		    if ( extrem == -1 )       /* Episode type */
		      epi1[i].tip = NON_ISHEMIC;
		    else
		      epi1[i].tip = ISHEMIC;
		  else
		    epi1[i].tip = ISHEMIC;
		  epi1[i].num_ext = 0;
		}
	    }
	  break;
	case -2 : epi1[i].ext_pos[j] = time;  /* Position of the extrema */
	  epi1[i].ext_val[j] = extrem;        /* Value of the extrema */
	  epi1[i].ext_lead[j] = lead;         /* Lead */
	  j++;
	  epi1[i].num_ext = j;                /* Number of extrema */
	  break;
	case -3 : k--;
	  if ( k == 0 )
	    {
	      epi1[i].offset = time;          /* End of episode */
	    }
	  break;
	}
    }
}

/* Reads the episodes from the file and fills the array for each lead */
void fill_ep_lead(fp,epi0,epi1,epi2)
FILE *fp;
episode epi0[MAXEPI], epi1[MAXEPI], epi2[MAXEPI];
{
 int i,j,k,l,m, n;
 long  time;
 int   event;
 long  extrem;
 int   lead;

   i = -1;
   k = -1;
   m=-1;
  
   while ( feof(fp) == 0 )
    {
     fscanf(fp,"%ld%d%ld%d",&time,&event,&extrem,&lead);
     switch(event)
      {
      case -1 : 
	if ( lead == 0 )
	  {
	    i++;
	    epi0[i].onset = time;
	    j = 0;
	    if ( extrem == 0 )
	      epi0[i].tip = ISHEMIC;
	    else
	      epi0[i].tip = NON_ISHEMIC;
	  }
	else if (lead==1)
	  {
	    k++;
	    epi1[k].onset = time;
	    l = 0;
	    if ( extrem == 0 )
	      epi1[k].tip = ISHEMIC;
	    else
	      epi1[k].tip = NON_ISHEMIC;
	  }
	else 
	  {
	    m++;
	    epi2[m].onset = time;
	    n = 0;
	    if ( extrem==0 )
	      epi2[m].tip = ISHEMIC;
	    else 
	      epi2[m].tip = NON_ISHEMIC;
	  }
	break;
      case -2 : 
	if ( lead == 0 )
	  {
	    epi0[i].ext_pos[j] = time;
	    epi0[i].ext_val[j] = extrem;
	    epi0[i].ext_lead[j] = lead;
	    j++;
	    epi0[i].num_ext = j;
	  }
	else  if ( lead==1 )
	  {
	    epi1[k].ext_pos[l] = time;
	    epi1[k].ext_val[l] = extrem;
	    epi1[k].ext_lead[l] = lead;
	    l++;
	    epi1[k].num_ext = l;
	  }
	else
	  {
	    epi2[m].ext_pos[n] = time;
	    epi2[m].ext_val[n] = extrem;
	    epi2[m].ext_lead[n] = lead;
	    n++;
	    epi2[m].num_ext = n;
	  }
	break;
       case -3 : 
	 if ( lead == 0 )
	   epi0[i].offset = time;
	 else if ( lead==1 )
	   epi1[k].offset = time;
	 else 
	   epi2[m].offset = time;
	 break;
      }
    }
}

/* Initializes the data structure for the episode */
void in_episode(epi)
episode *epi;
{
 int j;

 epi -> onset = 0;
 epi -> offset = 0;
 epi -> num_ext = MAXEX;
 for ( j = 0; j < epi -> num_ext; j++ )
   {
     epi -> ext_pos[j] = 0;
     epi -> ext_val[j] = 0;
     epi -> ext_lead[j] = 0;
   }
 epi -> status = 4;          /* Neutral */
 epi -> tip = 1;             /* Neutral */
 epi -> match = -1;          /* No matching */
 epi -> overlp = 0;
}

/* Initializes the array for the episodes */
void init_episode(epi)
episode epi[MAXEPI];
{
 int i;

 for ( i = 0; i < MAXEPI; i++ )
      in_episode(&epi[i]);
}

/* Initializes the data arrays for the records */
void in_record(rec)
record *rec;
{
 rec -> num_epi = 0;
 rec -> a = 0;
 rec -> b = 0;
 rec -> c = 0;
 rec -> d = 0;
 rec -> e = 0;
 rec -> f = 0;
 rec -> tp = 0;
 rec -> fn = 0;
 rec -> se = 0.0;
 rec -> duration = 0.0;
 rec -> ish_dur = 0.0;
 rec -> overlap = 0.0;
 rec -> percent = 0.0;
 rec -> ase = 0.0;
 rec -> aish_dur = 0.0;
}

/* Initializes the structures for the records */
void Init_Structs()
{
  int i;
  for (i=0;i<MAXREC;i++) 
  {
    recref[i].se=-1.0;
    recalg[i].se=-1.0;
    recref[i].ish_dur=-1.0;
    recalg[i].ish_dur=-1.0;
  }
}

/* Initializes values of the table of records */
void init_record(avrec)
record avrec[MAXREC];
{
 int i;

 for ( i = 0; i < MAXREC; i++ )
   in_record(&avrec[i]);
}

/* Converts the index [samples] to the time [h:m:s:ms] */
void convert_time(number,time)
long number;
times *time;
{
 long new;

 time -> msec = number % 1000;
 new = number / 1000;
 time -> sec = new % 60;
 number = new / 60;
 time -> min = number % 60;
 time -> hour = number / 60;
}

/* Returns the minimum of two numbers */
long  minimum(a,b)
long a,b;
{
  return (( a > b ) ? b : a );
}

/* Returns the maximum of two numbers */
long maximum(a,b)
long a,b;
{
  return ((a > b ) ? a : b ); 
}

/* Returns the duration of the overlapping interval of two episodes */
long matching(ref,alg)
episode ref,alg;
{
  long bover,eover;

  bover = maximum ( ref.onset, alg.onset );
  eover = minimum ( ref.offset, alg.offset );
  return( eover - bover) ;
}

/* Checks if the episode is sufficiently overlapped with another episode */
int overlap(epi,algtab,typofep)
episode *epi;
episode algtab[MAXEPI];
int typofep;
{
 long durepi;
 long durover;
 long durcur;
 int i,j;


 durover = 0;
 durepi = epi -> offset - epi -> onset;
 for ( i = 0; algtab[i].offset > 0; i++ )

   /* We consider only episodes of correct type */
   if (( algtab[i].tip == typofep ) || ( typofep == NO_MATTER ))
     {
       durcur = matching(*epi,algtab[i] );

       if ( durcur > 0 )    /* Matching ? */
	 {
	   durover += durcur;
	   /* Check for all extrema of the episode */

	   for ( j = 0; epi -> ext_pos[j] < algtab[i].offset && j<MAXI; j++ )
	     {
	       if (( epi -> ext_pos[j] >= algtab[i].onset ) && 
		   ( epi -> ext_pos[j] <= algtab[i].offset ))
		 /* Episode overlaps at least one extrema of defining episode */
		 epi -> match = OVER_EX;
	     }
	 }
     }
   if ( 2 * durover >= durepi )   /* Overlaps at least one half of defining episode */
       epi -> match = ( epi -> match == OVER_EX ) ? OVER_BOTH : OVER_HF;

   /* Determine the type of overlapping */
   if ( epi -> match != -1 )     /* Episode was detected */
        epi -> overlp = durover;
   if ( epi -> overlp > 0 )
     {
       if ( typofep != NO_MATTER )
         if ( epi -> tip == NON_ISHEMIC || typofep == NON_ISHEMIC )
	   epi -> overlp = 0; 
       return (YES);
     }
   else return (NO);
}

/* Determines status of the episode - ISCHEMIC, NON_ISCHEMIC, MISSED */
void determine_status(epitab1,epitab2,typeofep)
episode epitab1[MAXEPI];
episode epitab2[MAXEPI];
int typeofep;
{
 int i,overlap();


 for( i = 0; epitab1[i].offset > 0; i++ )
   if ( typeofep == IMPORTANT )
     if ( overlap(&epitab1[i],epitab2,ISHEMIC)  )
       epitab1[i].status = ISHEMIC;
     else  if ( overlap(&epitab1[i],epitab2,NON_ISHEMIC))
       epitab1[i].status = NON_ISHEMIC;
     else
       epitab1[i].status = MISSED;
   else 
     if ( overlap(&epitab1[i],epitab2,NO_MATTER ))
       epitab1[i].status = ISHEMIC;
     else
       epitab1[i].status = MISSED;
}

/* Initializes values of the elements in the table */
void initial(tab)
double tab[MAXIMAL];
{
 int i;

 for (i = 0; i <= MAXIMAL; i++)
   tab[i] = 0.0;
}

/* Determines parameters of the record according to the type of episodes and their status after the matching test */
void fill_record(epitab,el_rec)
episode epitab[MAXEPI];
record *el_rec;
{
 int i;

 for ( i = 0; epitab[i].offset > 0; i++ )
   if ( epitab[i].tip == ISHEMIC )
     switch ( epitab[i].status )
      {
       case ISHEMIC : ( el_rec -> a ) ++;
	       	      break;
       case NON_ISHEMIC : ( el_rec -> b ) ++;
		      break;
       case MISSED : ( el_rec -> c ) ++;
      }
    else
      switch ( epitab[i].status )
	{
	  case ISHEMIC : ( el_rec -> d ) ++;
			 break;
	  case NON_ISHEMIC : ( el_rec -> e ) ++;
			     break;
	  case MISSED : ( el_rec -> f ) ++;
	};
}

/* Calculates sensitivity or positive predictivity for the record */
double sensitivity(rec,diff)
record *rec;
int diff ;{
 double tps,fns;

 if ( diff == NO_MATTER )
   {
     tps = rec -> a + rec -> b + rec -> d + rec -> e;
     fns = rec -> c + rec -> f;
   }
  else
   {
     tps = rec -> a;
     fns = rec -> b + rec -> c;
   };
  rec -> tp = tps;
  rec -> fn = fns;
  if (( tps + fns ) == 0.0 )
    return(-1.0);
   else
    return( 100 * ( tps / (tps + fns )));
}

/* Calculates ischemic duration */
double ish_duration(epi,rec,typeofep)
episode epi[MAXEPI];
record *rec;
int typeofep;
{
 double durepi,durboth;
 int i,j;

 j = 0;
 durepi = 0.0;   /* Overall ischemia */
 durboth = 0.0;  /* Overlapping ischemia */
 for( i = 0; epi[i].offset > 0; i++)
   if ( typeofep == NO_MATTER )      /* Type does not matter */
     {
       durepi += ( epi[i].offset - epi[i].onset );
       durboth += epi[i].overlp;
       rec -> num_epi = i + 1;       /* Number of episodes */
     }
    else
       if ( epi[i].tip == ISHEMIC )  /* Consider ischemic episodes only */
	 {
	   durepi += ( epi[i].offset - epi[i].onset );
	   durboth += epi[i].overlp;
	   j++;
	   rec -> num_epi = j;
	 };
 rec -> duration = durepi;
 rec -> overlap = durboth;    /* Total overlap */
 rec -> percent = 100 * FACTOR * ( rec -> duration / DUR_REC );
 if ( durepi == 0.0 )
   return( -1.0);             /* Undefined */
  else
   return(100 * (durboth/durepi));
}

/* Calculates gross episode detection statistics */
double gross_statistic(auxref,rec,diff)
record auxref[MAXREC];
record *rec;
int diff;
{
 int i;
 double tps,fn;

 tps = 0.0;
 fn = 0.0;
 for ( i = 0; i < MAXR; i++ )
   {
     rec -> a += auxref[i].a;
     rec -> b += auxref[i].b;
     rec -> c += auxref[i].c;
     rec -> d += auxref[i].d;
     rec -> e += auxref[i].e;
     rec -> f += auxref[i].f;
     rec -> num_epi += auxref[i].num_epi;
     rec -> duration += auxref[i].duration;
   }

 if ( diff == IMPORTANT )
   {                     
     tps = rec -> a;
     fn = rec -> b + rec -> c;
   }
  else
   {
     tps = rec -> a + rec -> b + rec -> d + rec -> e;
     fn = rec -> c + rec -> f;
   }

  rec -> tp = tps;
  rec -> fn = fn;

  rec -> percent = ( 100 * FACTOR * ( rec -> duration / ((double)DUR_TOT )));
  if ( tps + fn == 0.0 )
     return (-1.0);
  else
     return(100 * ( tps / ( tps + fn )));
}

/* Calculates average episode detection statistics */
double average_statistic(auxref)
record auxref[MAXREC];
{
 int i;
 double pvc,j;

 j = 0.0;  
 pvc = 0.0;
 for ( i = 0; i < MAXR; i++ )
   if ( auxref[i].se != -1.00 )
     {
       pvc += auxref[i].se;
       j++;
     }
 if ( j == 0 )
   return(-1.00);
  else
   return( pvc / j);
}

/* Calculates gross deviant duration detection statistics */
double gross_duration(rec)
record rec[MAXREC];
{
 int i;
 double dur,durboth;

 dur = durboth = 0.0;
 for ( i = 0; i < MAXR; i++)
   {
     dur += rec[i].duration;
     durboth += rec[i].overlap;
   }
 if ( dur == 0.0 )
   return(-1.0);
  else
   return(100 * (durboth/dur));
}

/* Calculates average deviant duration detection statistics */
double average_duration(rec)
record rec[MAXREC];
{
 int i;
 double tps,j;

 tps = 0.0; 
 j = 0.0;   
 for ( i = 0; i < MAXR; i++ )
   if ( rec[i].ish_dur != -1.0 )
     {
       tps += rec[i].ish_dur;
       j++;
     }
 if ( j == 0.0 )
   return(-1.0);
  else
   return(tps/j);
}

/* Calculates mean value */
double mean(tab,size)
double tab[MAXIMAL];
int size;
{
 int i;
 double sum;

 sum = 0.0;
 for (i = 1; i <= size; i++)
   sum += tab[i];
 return(sum/size);
}

/* Calculates standard deviation value */
double st_variance(difftab,size,mean)
double difftab[MAXIMAL];
int size;
double mean;
{
 int i;
 double variance;

 variance = 0.0;
 for(i = 1; i <= size; i++)
   variance += (( difftab[i] - mean ) * ( difftab[i] - mean ));
 variance /= ( size - 1 );
 return(sqrt((double)variance));
}

/* Calculates correlation coefficient */
double corr_coefficient(tab1,tab2,size)
double tab1[MAXIMAL], tab2[MAXIMAL];
int size;
{
 double mean1, mean2, prod, prod1, prod2;
 int i;

 mean1 = mean(tab1,size);
 mean2 = mean(tab2,size);
 prod = prod1 = prod2 = 0.0;
 for ( i = 1; i <= size; i++)
   {
     prod += (( tab1[i] - mean1 ) * ( tab2[i] - mean2 ));
     prod1 += (( tab1[i] - mean1 ) * ( tab1[i] - mean1 ));
     prod2 += (( tab2[i] - mean2 ) * ( tab2[i] - mean2 ));
   }
 prod1 = sqrt(prod1);
 prod2 = sqrt(prod2);
 return(prod / ( prod1 * prod2 ));
}

/* Calculates coefficients of the regression line */
double linear_regression(tabx,tabz,size,a1)
double tabx[MAXIMAL], tabz[MAXIMAL], *a1;
int size;
{
 int i;
 double prodxz, prodx, prodz, prodz2;

 prodxz = prodx = prodz = prodz2 = 0.0;
 for ( i = 1; i <= size; i++ )
   {
     prodxz += ( tabx[i] * tabz[i] );
     prodx += tabx[i];
     prodz += tabz[i];
     prodz2 += ( tabz[i] * tabz[i] );
   }
 *a1 = ((prodxz - prodx * prodz / size) / (prodz2 - prodz * prodz / size));
 return(prodx / size - (*a1) * prodz / size);
}

/* Calculates percentage of measurements that exceeds the boundary */
double p100(tab,bound,size)
double tab[MAXIMAL];
int bound,size;
{
 int i;
 double j;

 j = 0.0;
 for ( i = 1; i <= size; i++ )
   if ( abs(tab[i]) >= bound )
     j++;
 return (100 * j / size);
}

/* Returns maximal element of the table */
double max_el(tab,size)
double tab[MAXIMAL];
int size;
{
 double max;
 int i;

 max = 0.0;
 for(i = 1; i <= size; i++)
   if ( tab[i] >= max )
     max = tab[i];
 return(max);
}

/* Calculates the value which 95% of measurements do not exceed */
double e95(tab,size)
double tab[MAXIMAL];
int size;
{
 int low,high,mid;
 double pro;

 low = 0;
 high = max_el(tab,size);
 while ( low <= high )
   {
     mid = ( low + high ) / 2;
     if ( pro = p100(tab,mid,size) > 5.00 )
       low = mid + 1;
      else if ( pro < 5.00 )
	     high = mid - 1;
	    else
	     return(mid);
   }
 return(low);
}

/* Deletes no_char characters from the selected character in forward direction */
void str_delete(string,start,no_char)
char *string;
int start, no_char;
{
 int index1, index2;

 index1 = index2 = 0;
 index2 = start + no_char;
 for (index1 = start; string[index1] = string[index2]; index1++)
   index2++;
}

/* writes sensitivity and positive predictivity matrix to the file */
void write_matrix(fs,ref,alg,diff)
record ref,alg;
FILE *fs;
int diff;
{
 fprintf(fs,"Episodes : annotated : %4d                     ",ref.num_epi);
 fprintf(fs,"detected : %4d\n",alg.num_epi);
 if ( diff == IMPORTANT )
   fprintf(fs,"Percent of ischemia  :  %7.3lf      ",ref.percent);
 else 
   fprintf(fs,"Percent of ST changes:  %7.3lf      ",ref.percent);
 fprintf(fs,"           detected :  %7.3lf %\n\n",alg.percent);
 fprintf(fs,"Sensitivity matrix :                        Positive predictivity matrix :\n");
 if ( diff == IMPORTANT )
   {
     fprintf(fs,"          Ischemic HR related Not epis");
     fprintf(fs,"                Ischemic HR related Not epis\n");
     fprintf(fs,"Ischemic  I  %4d  I  %4d  I  %4d  I      ",ref.a,ref.b,ref.c);
     fprintf(fs,"Ischemic  I  %4d  I  %4d  I     -  I\n",alg.a,alg.d);
     fprintf(fs,"HR relatedI  %4d  I  %4d  I  %4d  I      ",ref.d,ref.e,ref.f);
     fprintf(fs,"HR relatedI  %4d  I  %4d  I     -  I\n",alg.b,alg.e);
     fprintf(fs,"Not epis  I     -  I     -  I     -  I      ");
     fprintf(fs,"Not epis  I  %4d  I  %4d  I     -  I\n\n",alg.c,alg.f);
   }
  else
   {
     fprintf(fs,"            ST chang    Not epis           ");
     fprintf(fs,"             ST chang    Not epis\n");
     fprintf(fs,"ST chang I   %4d    I   %4d    I          ",ref.a+ref.d+ref.b+ref.e,ref.c+ref.f);
     fprintf(fs,"ST chang I   %4d    I      -    I\n",alg.a+alg.b+alg.d+alg.e);
     fprintf(fs,"Not epis I      -    I      -    I          ");
     fprintf(fs,"Not epis I   %4d    I      -    I\n\n",alg.c+alg.f);
   }
 fprintf(fs,"Sensitivity      :    true positives :%4d      ",ref.tp);
 fprintf(fs,"false negatives :%4d\n",ref.fn);
 fprintf(fs,"Pos.Predictivity :    true positives :%4d      ",alg.tp);
 fprintf(fs,"false positives :%4d\n",alg.fn);
}

/* Calculates gross statistics */
void write_gross_stat(diff)
int diff;
{
 FILE *fw;

 in_record(&allref);
 in_record(&allalg);
 allref.se = gross_statistic(recref,&allref,diff);
 allalg.se = gross_statistic(recalg,&allalg,diff);
 allref.ase = average_statistic(recref);
 allalg.ase = average_statistic(recalg);
 allref.ish_dur = gross_duration(recref);
 allalg.ish_dur = gross_duration(recalg);
 allref.aish_dur = average_duration(recref);
 allalg.aish_dur = average_duration(recalg);
}

/* Computes episode by episode report */
void write_episode_report(dat,diff,str,tab1,tab2,lead,num,difftab,atab,mtab)
FILE *dat;
char str[NAME_LEN];
episode tab1[MAXEPI], tab2[MAXEPI];
int lead, diff, *num;
double difftab[MAXIMAL],atab[MAXIMAL],mtab[MAXIMAL];

{
 times cl;
 char str1[NAME_LEN];
 int i, j, old;
 float percent;
 double diffave;
 int zap = 1;

 strcpy(str1,str);
 for(i = 0; tab1[i].offset > 0; i++)
   if (( tab1[i].tip == ISHEMIC ) || ( diff == NO_MATTER ))
     for(j = 0; tab1[i].ext_pos[j] > 0; j++)
       if ( tab1[i].ext_lead[j] == lead )
	 {
           old = *num;
	   (*num)++;
	   convert_time(FACTOR*tab1[i].ext_pos[j],&cl);
	   diffave = -1 * ( tab1[i].ext_val[j] - tab2[i].ext_val[j] );
           st_tab[*num].diff = diffave;
           st_tab[*num].ann = tab1[i].ext_val[j];
           st_tab[*num].meas = tab2[i].ext_val[j];
           st_tab[*num].percent = 100 * ( diffave / tab1[i].ext_val[j] );

	   webe[nrebe].episode=*num;
	   strcpy(webe[nrebe].rec,GetName(str1));
	   webe[nrebe].lead=lead;
	   webe[nrebe].time=tab1[i].ext_pos[j];
	   webe[nrebe].meas=tab2[i].ext_val[j];
	   webe[nrebe].annot=tab1[i].ext_val[j];
	   webe[nrebe].diff=diffave;
	   webe[nrebe].percent=100 * ( diffave / tab1[i].ext_val[j] );
	   nrebe++;

           strcpy(st_tab[*num].name,GetName(str));
           st_tab[*num].lead = lead;
           if ( old > 1 )
	     if (st_tab[*num].lead == st_tab[old].lead)
                 zap++;
            else
                 zap = 1;
           st_tab[*num].number = zap; 
	   difftab[*num] = diffave;
	   atab[*num] = tab1[i].ext_val[j];
	   mtab[*num] = tab2[i].ext_val[j];
	   percent = 100 * ( diffave / tab1[i].ext_val[j] );
	 }
}

/* Randomly selects records for the new database */
void choose_base(tab)
int tab[MAXREC];
{
 int i;

 for ( i = 0; i < MAXR; i++ )
   tab[i] = random() % MAXR;
}

/* Returns set of records of the new database */
void copy_array(base,old,new)
int base[MAXREC];
record old[MAXREC], new[MAXREC];
{
 int i,j;

 for ( i = 0; i < MAXR; i++ )
   {
     j = base[i];
     new[i] = old[j];
   }
}

/* Initializes an integer table */
void ini(tab)
int tab[EXACT];
{
 int i;

 for ( i = 0; i < EXACT; i++)
   tab[i] = 0;
}

/* Counts results of the bootstrap method */
void count_res(res,tab)
double res;
int tab[EXACT];
{
 int i;
 double l;

 l = 10.0 * res;
 i = l >= 0 ? l + 0.5 : l - 0.5;
 tab[i]++;
}

/* Calculates confidence limits */
double confidence_limits(limit,tab,trials)
double limit;
int tab[EXACT];
long trials;
{
 long i, suma;
 double bound;

 bound = limit * trials;
 suma = 0;
 for ( i = 0; suma <= bound; i++)
   suma += tab[i];
 return((i-1)/10.0);
}

/* Returns maximum and minimum statistics */
double minmax(tab,min)
int tab[EXACT];
double *min;
{
 long i,j;
 double max;

 *min = 0;
 for ( i = 0; *min == 0; i++)
   if ( tab[i] > 0 )
      *min = i / 10.0;
 for ( j = i; j < EXACT; j++)
   if ( tab[j] > 0 )
     max = j;
 return(max/10.0);
}

/* Calculates histogram of the bootstrap method */
void make_hist(tab,num,hist)
int tab[EXACT];
long num;
double hist[100];
{
 int i, j, k;
 double suma;

 k = 0;
 for ( j = 0; j < 100; j++)
   {
     suma = 0.0;
     for ( i = 0; i < 10; i++)
       suma += tab[k+i];
     hist[j] = suma / num;
     k += 10;
   }
}

/* Calculates confidence limits, minimal, maximal, median and mean results,  
   and difference between the mean and the 5% confidence limits */
void store_result(tab,trials,tab1)
int tab[EXACT];
long trials;
double tab1[NUMRES];
{
 double min;

 tab1[0] = confidence_limits(0.05,tab,trials);
 tab1[1] = confidence_limits(0.16,tab,trials);
 tab1[2] = confidence_limits(0.84,tab,trials);
 tab1[3] = confidence_limits(0.95,tab,trials);
 tab1[4] = minmax(tab,&min);
 tab1[5] = min;
 tab1[6] = ( min + tab1[4] ) / 2;
 tab1[7] = confidence_limits(0.5,tab,trials);
 tab1[8] = tab1[7] - tab1[0];
}

/* Performs evaluation on single record */
int Single(dat_1, dat_2, diff)
char dat_1[NAME_LEN], dat_2[NAME_LEN];
int  diff;
{
 char dat[NAME_LEN], number[NAME_LEN], temp[NAME_LEN], header[NAME_LEN], rec_head[NAME_LEN];
 FILE *fref, *falg, *fw;
 int i, j=0;
 char file_ref[NAME_LEN],file_alg[NAME_LEN],file_cmr[NAME_LEN],temp_name[NAME_LEN];
  
 in_record(&allref);
 in_record(&allalg);

 fref=fopen(alg_name,"rt");
 sprintf(rec_head,"%s",dat_2);
 if (Test(fref,alg_name)==-1) return (-1);
 while (!feof(fref))
   {
     fscanf(fref,"%s\n",temp_name);
     if (strstr(temp_name,dat_2)!=NULL)
       sprintf(rec_head,"%s",temp_name);
   }
 fclose(fref);

 init_episode(&epiref);
 init_episode(&epialg);
 init_episode(ep_lead0);
 init_episode(ep_lead1);
 init_episode(ep_lead2);
 sprintf(header,"%s%s",path,rec_head);
 strcpy(number,dat_2);
 sprintf(file_ref,"%s.ref",header);
 sprintf(file_alg,"%s.alg",header);
 sprintf(file_cmr,"%s.cmr",header);
 sprintf(header,"%s%s",path,rec_head);

 if ((DUR_REC=Open_Header(header))<0) return (-1);

 fref = fopen(file_cmr,"r");
 if ( Test(fref,file_cmr) == -1 )
  {
    return(-1);
  }
 fill_array(fref,&epiref);
 fclose(fref);

 fref = fopen(file_ref,"r");
 if ( Test(fref,file_ref) == -1 )
  {
    return(-1);
  }
 fref = fopen(file_ref,"r");
 fill_ep_lead(fref,ep_lead0,ep_lead1,ep_lead2);
 fclose(fref);

 falg = fopen(file_alg,"r");
 if ( Test(falg,file_alg) == -1 ) 
   {
     return(-1);
   }
 fill_array(falg,&epialg);
 fclose(falg);

 determine_status(&epiref,epialg,diff);
 determine_status(&epialg,epiref,diff);
 fill_record(epiref,&allref);
 fill_record(epialg,&allalg);
 allref.se = sensitivity(&allref,diff);
 allalg.se = sensitivity(&allalg,diff);
 allref.ish_dur = ish_duration(epiref,&allref,diff);
 allalg.ish_dur = ish_duration(epialg,&allalg,diff);
 examine_valid=0;


 strcpy(writeX,"");
 sprintf(dat,"Episode by episode report, record: %s\n",GetName(rec_head));
 strcat(writeX,dat);

 if (diff == IMPORTANT )
   sprintf(dat,"Evaluation: %s  Evaluation mode: Ischemic/Heart-rate related changes",RemoveDot(file_name));
 else 
   sprintf(dat,"Evaluation: %s  Evaluation mode: ST segment changes\n",RemoveDot(file_name));
 strcat(writeX,dat);
  
 sprintf(dat,"\n");
 strcat(writeX,dat);

 Xwrite_matrix(allref,allalg,diff);
 Xwrite_statistics(allref,allalg);
 Xwrite_episodes(epiref,0);
 Xwrite_episodes(epialg,1);
}

/* Performs evaluation on entire database */
void all_records(dat_1,diff)
char dat_1[NAME_LEN];
int diff;
{
 FILE *fp,*fo,*fs,*fref,*falg,*fa;
 char dat_3[NAME_LEN],filename_01[NAME_LEN], filename_0[NAME_LEN], filename_1[NAME_LEN];
 char filename_0t[NAME_LEN], filename_1t[NAME_LEN];
 char filename_00[NAME_LEN], filename_11[NAME_LEN], path0[NAME_LEN], path1[NAME_LEN];
 char filename_C[NAME_LEN],recName1[NAME_LEN],recName2[NAME_LEN];
 char dummystr[NAME_LEN];
 int i , read;

 REC_COUNT=0;
 DUR_TOT=0;
 REC_TOT=0;

 fp = fopen(dat_1,"r");
 if ( Test(fp,dat_1) == -1) 
   return;
 init_record(&recref);
 init_record(&recalg);
 i = 0;
 Init_Structs();
 MAXR=0;

 while (((read=fscanf(fp,"%s",filename_00))==1) && ( i < MAXREC )) /*( feof(fp) == NULL )*/
  {
    strcpy(path0,path);
    strcpy(path1,path);
    strcpy(recName,filename_00);
    strcpy(filename_0t, strcat(path0,filename_00));
    strcpy(filename_1t, strcat(path1,filename_00));  
    init_episode(&epiref);
    init_episode(&epialg);

    if ((DUR_REC=Open_Header(filename_0t))==-1) /* !!! */
      {
        fclose(fp);
	strcpy(writeX,"");
	return;
      }
    else
      {
	REC_COUNT++;
	MAXR++;
	DUR_TOT+=(double)DUR_REC;
	REC_TOT++;
	sprintf(filename_0,"%s.ref",filename_0t);
	sprintf(filename_1,"%s.alg",filename_1t);
	sprintf(filename_C,"%s.cmr",filename_0t);
	
	fref = fopen(filename_C,"r");
	if ( Test(fref,filename_C) == -1 )
	  { 
	    fclose(fp);
	    strcpy(writeX,"");
	    return;
	  }
	
	fill_array(fref,&epiref);
	fclose(fref);
	falg = fopen(filename_1,"r");
	if ( Test(falg,filename_1) == -1 )
	  {
	    fclose(fp);
	    strcpy(writeX,"");
	    return;
	  }
	fill_array(falg,&epialg);
	fclose(falg);
	
	determine_status(&epiref,epialg,diff);
	determine_status(&epialg,epiref,diff);
	fill_record(epiref,&recref[i]);
	fill_record(epialg,&recalg[i]);
	recref[i].se = sensitivity(&recref[i],diff);
	recalg[i].se = sensitivity(&recalg[i],diff);
	recref[i].ish_dur = ish_duration(epiref,&recref[i],diff);
	recalg[i].ish_dur = ish_duration(epialg,&recalg[i],diff);
	
	if (i>=tot_rec) 
	  {
	    strcpy(evaluated[i].rec,GetName(recName));
	    tot_rec++;
	  }
	i++;
      }
  }
 fclose(fp);
 all_valid=1;
 write_gross_stat(diff);
 examine_valid=0;
}

/* Performs bootstrap evaluation */
void bootstrap(diff,trials)
int diff;
long trials;
{
 int newbase[MAXREC];
 int gsens[EXACT], gpred[EXACT], asens[EXACT], apred[EXACT];
 int gdurse[EXACT], adurse[EXACT], gdurp[EXACT], adurp[EXACT];
 record trialref[MAXREC], trialalg[MAXREC];
 record rec;
 double griese, griepp, aviese, aviepp, gridse, gridpp, avidse, avidpp;
 long i;

 ini(gsens); 
 ini(gpred);
 ini(asens);
 ini(apred);
 ini(gdurse);
 ini(adurse);
 ini(gdurp);
 ini(adurp);
 srand(1);
 for ( i = 0; i < trials; i++ )
   {
     choose_base(newbase);
     copy_array(newbase,recref,trialref);
     copy_array(newbase,recalg,trialalg);
     in_record(&rec);
     griese = gross_statistic(trialref,&rec,diff);
     count_res(griese,gsens);
     in_record(&rec);
     griepp = gross_statistic(trialalg,&rec,diff);
     count_res(griepp,gpred);
     aviese = average_statistic(trialref);
     count_res(aviese,asens);
     aviepp = average_statistic(trialalg);
     count_res(aviepp,apred);
     gridse = gross_duration(trialref);
     count_res(gridse,gdurse);
     gridpp = gross_duration(trialalg);
     count_res(gridpp,gdurp);
     avidse = average_duration(trialref);
     count_res(avidse,adurse);
     avidpp = average_duration(trialalg);
     count_res(avidpp,adurp);
   }

 store_result(gsens,trials,&gsensr);
 store_result(gpred,trials,&gpredr);
 store_result(asens,trials,&asensr);
 store_result(apred,trials,&apredr);
 store_result(gdurse,trials,&gdurser);
 store_result(gdurp,trials,&gdurpr);
 store_result(adurse,trials,&adurser);
 store_result(adurp,trials,&adurpr);
 make_hist(gsens,trials,&hist_gse);
 make_hist(gpred,trials,&hist_gpn);
 make_hist(asens,trials,&hist_ase);
 make_hist(apred,trials,&hist_apn);
 make_hist(gdurse,trials,&hist_gdurse);
 make_hist(gdurp,trials,&hist_gdurpn);
 make_hist(adurse,trials,&hist_adurse);
 make_hist(adurp,trials,&hist_adurpn);
}

/* Returns Euclidean distance between two points */
long evklid_dist ( x1, y1, x2, y2 )
int x1, y1, x2, y2;
{
  long z1, z2;
  
  if ( x2 > x1 )
     z1 = (x2 - x1) * (x2 - x1);
   else
     z1 = (x1 - x2) * (x1 - x2);
  if ( y2 > y1 )
     z2 = (y2 - y1) * (y2 - y1);
   else
     z2 = (y1 - y2) * (y1 - y2);
  return(z1 + z2);
}

/* Returns the episode which is the nearest to the specified point */ 
int find_pixel( x, y, tab)
int x, y;
coor  tab[MAXIMAL];
{

  int i, epi;
  long min, a;

  min = 1000000;
  for (i = 1; i <= extepi; i++)
   {
     if (( a = evklid_dist(x, y, tab[i].x, tab[i].y)) < min )
       {
         min = a;
         epi = i;
       }
   }
  return(epi);
}

/* Writes statistics for a single record */
int write_single(char fname[NAME_LEN],char rname[NAME_LEN],int diff)
{
  FILE *fs;
  char dat_4[NAME_LEN];

  sprintf(dat_4,"%s%s.%s",fname,diff==IMPORTANT?"_ih":"_st",rname);
  fs = fopen(dat_4,"w");
  if (Test_out(fs,dat_4)==-1) return (-1);
  fprintf(fs,"%s",writeX);
  return (0);
}

/* Writes raw statistics */
int write_raw(char fname[NAME_LEN],int diff)
{
  FILE *fw;
  
  fw = fopen(fname, "w");
  if (Test_out(fw,fname)==-1) return (-1);
  else
    {
      fprintf(fw,"Raw statistics\n");
      if ( diff == IMPORTANT )
	{
	  fprintf(fw, "Ischemic and Heart-rate related episodes are differentiated\n\n");
	  write_matrix(fw,allref,allalg,diff);
	  fprintf(fw,"IE Sensitivity  = %6.2lf [g]   %6.2lf [a]   ",allref.se,allref.ase);
	  fprintf(fw,"IE PositPredict = %6.2lf [g]   %6.2lf [a]\n",allalg.se,allalg.ase);
	  fprintf(fw,"ID Sensitivity  = %6.2lf [g]   %6.2lf [a]   ",  allref.ish_dur,allref.aish_dur);
	  fprintf(fw,"ID PositPredict = %6.2lf [g]   %6.2lf [a]\n\n",allalg.ish_dur,allalg.aish_dur);
	}
      else
	{
	  fprintf(fw, "Ischemic and Heart-rate related episodes are considered as episodes of single type\n\n");
	  write_matrix(fw,allref,allalg,diff);
	  fprintf(fw,"SE Sensitivity  = %6.2lf [g]   %6.2lf [a]   ",allref.se,allref.ase);
	  fprintf(fw,"SE PositPredict = %6.2lf [g]   %6.2lf [a]\n",allalg.se,allalg.ase);
	  fprintf(fw,"SD Sensitivity  = %6.2lf [g]   %6.2lf [a]   ",allref.ish_dur,allref.aish_dur);
	  fprintf(fw,"SD PositPredict = %6.2lf [g]   %6.2lf [a]\n\n",allalg.ish_dur,allalg.aish_dur);
	}
      fclose(fw);
    } 
  return (0);
}

/* Writes record-by-record statistics */
int write_rbr()
{
  int i;
  char buf[LEN_SHORTER];
  
  strcpy(writeX,"");
  sprintf(buf,"Record by record statistics\n");
  strcat(writeX,buf);
  if ( diff == IMPORTANT )
    sprintf(buf,"Ischemic and Heart-rate related episodes are differentiated\n");
  else
    sprintf(buf,"Ischemic and Heart-rate related episodes are considered as episodes of single type\n");
  strcat(writeX,buf);
  
  for (i=0;i<REC_COUNT;i++)
    {
      sprintf(buf,"\nRecord:   %s\n",evaluated[i].rec);
      strcat(writeX,buf);
      Xwrite_matrix(recref[i],recalg[i],diff);
      Xwrite_statistics(recref[i],recalg[i]);
    }
}

/* Writes record-by-record statistics, too */
int write_rbr_file()
{
  char dat_3[NAME_LEN];
  FILE *fs;

  sprintf(dat_3,"%s%s.rbr",RemoveDot(alg_name),diff==IMPORTANT?"_ih":"_st");
  fs = fopen(dat_3,"w");
  if (Test_out(fs,dat_3)!=-1) 
    {
      fprintf(fs,"%s",writeX);
      fclose(fs);
      return(0);
    }
  return (-1);
}

/* Writes bootstrap statistics to file */
int write_boot1(char fname[NAME_LEN],int diff, long trials1)
{
  FILE *fa;
  
  fa = fopen(fname,"w");
  if (Test_out(fa,fname)==-1) return (-1);
  fprintf(fa,"%s",writeX);
  fclose(fa);
  return (0);
}

/* Writes episode-by-episode statistics */
int write_ebe()
{
  char dat_3[NAME_LEN];
  FILE *fw;

  sprintf(dat_3,"%s%s.ebe",RemoveDot(alg_name),diff==IMPORTANT?"_ih":"_st");
  fw = fopen(dat_3,"w");
  if (Test_out(fw,dat_3)!=-1)
    {
      fprintf(fw,"%s",writeX);
      fclose (fw);
    }
  return (0);
}

/* ************************************************************************************* */
/* Main program */

main(argc,argv)
int argc;
char *argv[];
{

#if (motif)       /* MOTIF SECTION - main program */
  sprintf(hname,"%s",argv[0]);
  toplevel = XtAppInitialize(&app_context, "EVAL_ST", NULL,
                             0, &argc, argv, fallback_resources, NULL, 0);
  display=XtDisplay(toplevel);
  CreateApplication(toplevel);
  InitDraw();
  XtRealizeWidget(toplevel);
  XtAppMainLoop(app_context);
#else             /* END OF MOTIF SECTION */

  char *s,*t,*t1;
  char w1_name[NAME_LEN],w2_name[NAME_LEN],pname[NAME_LEN],buf[LEN_SHORTER];
  int i;
  FILE *help;
  struct stat stat_val;
  
  strcpy(path,"");
  strcpy(pname,argv[0]);
  if (argc>=2)
    {
      if (memcmp(argv[1],"-h",2)==0)
	{
	  if ((help=fopen("eval_st.hlp","rt"))==NULL)
	    {
	      fprintf(stderr,"No eval_st.hlp file\n");
	    }
	  else 
	    {
	      while (!feof(help))
		{
		  fgets(buf, sizeof(char)*LEN_SHORTER, help);
		  if (!feof(help)) fprintf(stderr,"%s",buf);
		}
	      fclose(help);
	    }
	  return;
	}
    }
  if (argc<4)
    {
      fprintf(stderr,"Usage: %s -h \n",pname);
      fprintf(stderr,"Usage: %s -r <database>_<algorithm>.evl <record> -[i|s] \n",pname);
      fprintf(stderr,"Usage: %s -a <database>_<algorithm>.evl  -[i|s] [-e|-b [NR_TRIALS]]\n",pname);
      return;
    }
  if ((*++argv)[0] == '-')
    for (s = argv[0] + 1; *s != '\0';s++)
      switch (*s)
	{
	case 'r' : 
	  if (argc<5)
	    {
	      fprintf(stderr,"Usage: %s -r <database>_<algorithm>.evl <record> -[i|s] \n",pname);
	      return;
	    }
	  
	  if (stat(argv[1], &stat_val) == 0)
	    if ((stat_val.st_mode & S_IFMT )== S_IFDIR)
	      {
		fprintf(stderr,"Enter project file <project>.evl\n");
		return ;
	      }
	  sprintf(alg_name,"%s",argv[1]);
	  sprintf(file_name,"%s",argv[1]);
	  sprintf(ref_name,"%s",argv[2]);
	  if (*(argv + 3)[0] == '-' )
	    for (t = (argv+3)[0] + 1; *t != '\0'; t++)
	      switch (*t)
		{
		case 'i' : 
		  {
		    diff = IMPORTANT;
		    Single(alg_name,ref_name,IMPORTANT);
		    write_single(RemoveDot(alg_name),ref_name,IMPORTANT);
		  }
		  break;
		case 's' : 
		  {
		    diff = NO_MATTER;
		    Single(alg_name,ref_name,NO_MATTER);
		    write_single(RemoveDot(alg_name),ref_name,NO_MATTER);
		  }
		  break;
		default  : fprintf(stderr,"Usage: %s -r <database>_<algorithm>.evl <record> -[i|s] \n",pname);
		  break;
		}
	  else 
	    {
	      diff = IMPORTANT;
	      Single(alg_name,ref_name,IMPORTANT);
	      write_single(RemoveDot(alg_name),ref_name,NO_MATTER);
	    }
	  break;
	case 'a' : 
	  if (argc<4)
	    {
	      fprintf(stderr,"Usage: %s -a <database>_<algorithm>.evl -[i|s] [-e|-b [NR_TRIALS]]\n",pname);
	      return;
	    }
	  if (stat(argv[1], &stat_val) == 0)
	    if ((stat_val.st_mode & S_IFMT )== S_IFDIR)
	      {
		fprintf(stderr,"Enter project file <project>.evl\n");
		return ;
	      }
	  sprintf(alg_name,"%s",argv[1]);
	  sprintf(file_name,"%s",argv[1]);
	  if (*(argv + 2)[0] == '-' )
	    for (t = (argv+2)[0] + 1; *t != '\0'; t++)
	      switch (*t)
		{
		case 'i' : 
		  diff = IMPORTANT;
		  if (argc==4) 
		    {
		      sprintf(w1_name,"%s%s.raw",RemoveDot(alg_name),diff==IMPORTANT?"_ih":"_st");
		      all_records(*(argv + 1),IMPORTANT);
		      if (all_valid==0) return;
		      write_rbr();
		      write_raw(w1_name,IMPORTANT);
		      write_rbr_file();
		    }
		  else if (*(argv + 3)[0] == '-' )
		    for (t1 = (argv+3)[0] + 1; *t1 != '\0'; t1++)
		      switch(*t1)
			{
			case 'e' : 
			  {
			    all_records(alg_name,IMPORTANT);
			    if (all_valid==0) return;
			    write_rbr();
			    write_rbr_file();
			    st_deviation(alg_name,IMPORTANT);
			    if (dev_valid==0) return;
			    write_ebe();
			    sprintf(w1_name,"%s%s.raw",RemoveDot(alg_name),diff==IMPORTANT?"_ih":"_st");
			    sprintf(w2_name,"%s%s.ext",RemoveDot(alg_name),diff==IMPORTANT?"_ih":"_st");
			    write_raw(w1_name,IMPORTANT);
			  }
			  break;
			case 'b' : 
			  if ( argc == 6 ) 
			    {
			      all_records(alg_name,IMPORTANT);
			      if (all_valid==0) return;
			      write_rbr();
			      write_rbr_file();
			      sprintf(w1_name,"%s%s.raw",RemoveDot(alg_name),diff==IMPORTANT?"_ih":"_st");
			      write_raw(w1_name,IMPORTANT);
			      bootstrap(IMPORTANT,atol(argv[4]));
			      sprintf(w2_name,"%s%s.bts",RemoveDot(alg_name),diff==IMPORTANT?"_ih":"_st");
			      Xwrite_boot();
			      write_boot1(w2_name,IMPORTANT,10000);
			    }
			  else 
			    {
			      all_records(alg_name,IMPORTANT);
			      if (all_valid==0) return;
			      write_rbr();
			      write_rbr_file();
			      sprintf(w1_name,"%s%s.raw",RemoveDot(alg_name),diff==IMPORTANT?"_ih":"_st");
			      write_raw(w1_name,IMPORTANT);
			      bootstrap(IMPORTANT,10000);
			      sprintf(w2_name,"%s%s.bts",RemoveDot(alg_name),diff==IMPORTANT?"_ih":"_st");
			      Xwrite_boot();
			      write_boot1(w2_name,IMPORTANT,10000);
			    }
			  break;
			default : fprintf(stderr,"Usage: %s -a <database>_<algorithm>.evl -[i|s] [-e|-b [NR_TRIALS]]\n",pname);
			  break;
			}
		  break;
		case 's' : 
		  diff = NO_MATTER;
		  if (argc==4) 
		    {
		      sprintf(w1_name,"%s%s.raw",RemoveDot(alg_name),diff==IMPORTANT?"_ih":"_st");
		      all_records(alg_name,NO_MATTER);
		      if (all_valid==0) return;
		      write_rbr();
		      write_rbr_file();
		      write_raw(w1_name,NO_MATTER);
		    }
		  else if (*(argv + 3)[0] == '-' )
		    {
		      for (t1 = (argv+3)[0] + 1; *t1 != '\0'; t1++)
			switch(*t1)
			  {
			  case 'e' : 
			    {
			      all_records(alg_name,NO_MATTER);
			      if (all_valid==0) return;
			      write_rbr();
			      write_rbr_file();
			      st_deviation(alg_name,NO_MATTER);
			      if (dev_valid==0) return;
			      write_ebe();
			      sprintf(w1_name,"%s%s.raw",RemoveDot(alg_name),diff==IMPORTANT?"_ih":"_st");
			      sprintf(w2_name,"%s%s.ext",RemoveDot(alg_name),diff==IMPORTANT?"_ih":"_st");
			      write_raw(w1_name,NO_MATTER);
			    }
			    break;
			  case 'b' : 
			    if ( argc == 6 ) 
			      {
				all_records(alg_name,NO_MATTER);
				if (all_valid==0) return;
				write_rbr();
				write_rbr_file();
				sprintf(w1_name,"%s%s.raw",RemoveDot(alg_name),diff==IMPORTANT?"_ih":"_st");
				write_raw(w1_name,NO_MATTER);
				bootstrap(NO_MATTER,atol(argv[4]));
				sprintf(w2_name,"%s%s.bts",RemoveDot(alg_name),diff==IMPORTANT?"_ih":"_st");
				Xwrite_boot();
				write_boot1(w2_name,NO_MATTER,atol(argv[4]));
			      }
			    else 
			      {
				all_records(alg_name,NO_MATTER);
				if (all_valid==0) return;
				write_rbr();
				write_rbr_file();
				sprintf(w1_name,"%s%s.raw",RemoveDot(alg_name),diff==IMPORTANT?"_ih":"_st");
				write_raw(w1_name,NO_MATTER);
				bootstrap(NO_MATTER,10000);
				sprintf(w2_name,"%s%s.bts",RemoveDot(alg_name),diff==IMPORTANT?"_ih":"_st");
				Xwrite_boot();
				write_boot1(w2_name,NO_MATTER,10000);
			      }
			    break;
			  default:fprintf(stderr,"Usage: %s -a <database>_<algorithm>.evl -[i|s] [-e|-b [NR_TRIALS]]\n",pname);
			    break;
			  }}
		  break;
		default  : fprintf(stderr,"Usage: %s -a <database>_<algorithm> -[i|s] [-e|-b [NR_TRIALS]]\n",pname);
		  break;
		}
	  else 
	    {
	      if (stat(argv[1], &stat_val) == 0)
		if ((stat_val.st_mode & S_IFMT )== S_IFDIR)
		  {
		    fprintf(stderr,"Enter project file <project>.evl\n");
		    return ;
		  }
	      sprintf(alg_name,"%s",alg_name);
	      sprintf(file_name,"%s",alg_name);
	      diff = IMPORTANT;
	      all_records(alg_name,IMPORTANT);
	      if (all_valid==0) return;
	      write_rbr();
	      write_rbr_file();
	      sprintf(w1_name,"%s%s.raw",RemoveDot(alg_name),diff==IMPORTANT?"_ih":"_st");
	      write_raw(w1_name,IMPORTANT);
	    }
	  break;
	  break;
	default  : 
	  {
	    fprintf(stderr,"Usage: %s -h \n",pname);
	    fprintf(stderr,"Usage: %s -r <database>_<algorithm>.evl <record> -[i|s] \n",pname);
	    fprintf(stderr,"Usage: %s -a <database>_<algorithm>.evl -[i|s] [-e|-b [NR_TRIALS]]\n",pname);
	    argc = 0;
	  }
	  break;
	}
  
#endif

}
/* ************************************************************************************* */