Information-Based Similarity 1.0.0

File: <base>/src/ibs-0.9.c (5,553 bytes)
/* file: ibs.c              Albert Yang, MD                25 August 2004

-------------------------------------------------------------------------------
ibs: calculates information-based similarity index (IBS) between two
data sets

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 (ccyang@physionet.org/).  For updates to
this software, please visit PhysioNet (http://www.physionet.org/).
-----------------------------------------------------------------------------

Compile this program by

    gcc -o ibs -O ibs.c -lm

Input usage

ibs m file1 file2

m: m-tuple binary sequence
file1 and file2: input time series

The program performs two main calculations:
1. Determine the word rank order frequency (WROF) list of a given time
series.  
2. Calculate the information-based similarity between two WROF lists.

Output file:
the information-based similarity index using m-tuple binary sequences.

*/


#include <stdio.h>
#include <stdlib.h>
#include <math.h>

#define MAXDAT 150000

int m, nw;

static int rr1[MAXDAT];
static int rr2[MAXDAT];


void swap (int array[2][nw], int i, int j) {
	int k, temp;
	for(k=0 ; k<2 ; k++) { 
           temp = array[k][i];
	   array[k][i] = array[k][j];
	   array[k][j] = temp;
	}   
}


int partition(int array[2][nw], int left, int right, int ic) {
	int pivot = array[ic][left];
	int i = left-1; 
	int j = right+1;

	while (1) {
		do {j--;
		} while (array[ic][j] > pivot);
		
		do {i++;
		} while (array[ic][i] < pivot);
		
		if (i < j) 
			swap(array, i, j); // swap ith and jth elements of array
		else
			return j;
	}
}

void quicksort(int array[2][nw], int left, int right, int ic) {
	int pivot_index;
	if (left < right) {
		pivot_index = partition(array, left, right, ic);
		quicksort(array, left, pivot_index, ic);
		quicksort(array, pivot_index+1, right, ic);
	}
}

float distance(int rr1[], int rr2[], int nlin1, int nlin2)
{
  float d;
  int i, j, mtuple, ns1 = nlin1 - m + 1, ns2 = nlin2 - m + 1;
  float f1, f2, dr, p, pi, pj;
  
  int w1[2][nw];
  int w2[2][nw];
  int temp[nw];
  
  for (i=0 ; i<nw; i++){
     w1[0][i]=i;
     w1[1][i]=0;
     w2[0][i]=i;
     w2[1][i]=0;
  }   
  
  for (i=0 ; i<ns1; i++){
     mtuple = 0;
     for (j=1 ; j<=m ; j++){mtuple = mtuple + (1 << (m-j))*rr1[i+j-1];}
     w1[1][mtuple] = w1[1][mtuple] + 1;
  }

  for (i=0 ; i<ns2; i++){
     mtuple = 0;
     for (j=1 ; j<=m ; j++){mtuple = mtuple + (1 << (m-j))*rr2[i+j-1];}
     w2[1][mtuple] = w2[1][mtuple] + 1;
  }
  
  for (i=0 ; i<nw; i++){ temp[i] = w1[1][i]; }
  quicksort( w1, 0, nw - 1, 1 );
  for (i=0 ; i<nw; i++){ w1[1][i] = nw - i - 1; }
  quicksort( w1, 0, nw - 1, 0 );
  for (i=0 ; i<nw; i++){ w1[0][i] = temp[i]; }
  
  
  for (i=0 ; i<nw; i++){ temp[i] = w2[1][i]; }
  quicksort( w2, 0, nw - 1, 1 );
  for (i=0 ; i<nw; i++){ w2[1][i] = nw - i - 1; }
  quicksort( w2, 0, nw - 1, 0 );
  for (i=0 ; i<nw; i++){ w2[0][i] = temp[i]; }

 
  /*Calculate Total Occurrence*/
  f1=0;
  f2=0;
  for (i=0 ; i<nw ; i++)
  {
    f1 = f1 + w1[0][i];
    f2 = f2 + w2[0][i];
  }
  
  /*Calculate Distance(W1,W2)*/
  dr = 0;
  p = 0;
  for (i=0 ; i<nw ; i++)
  {
    pi = w1[0][i]/f1;
    pj = w2[0][i]/f2;
    if (pi > 0) pi = -pi * log( pi ); else pi = 0;
    if (pj > 0) pj = -pj * log( pj ); else pj = 0;
    dr = dr + abs( w1[1][i] - w2[1][i] ) * (pi + pj);
    p = p + ( pi + pj );

  }

  if (p > 0) d = dr / p / (nw-1); else d = -1;  
   
  return (d);
}


int main(int argc, char **argv)
{

     int i, nlin1, nlin2;
     float rrn,rrn1;
     
     m=atol(argv[1]);
     nw=1 << m;

     /*
     for (i = 1; i < argc; ) {
          printf("%s", argv[i]);
          if (++i < argc)
               putchar(' ');
     putchar('\n');
     }
     */
      
     FILE *RF1;   /* File variable for RR interval time series 1 */
     FILE *RF2;   /* File variable for RR interval time series 2 */
     
     RF1 = fopen(argv[2], "r");
     RF2 = fopen(argv[3], "r");

     /* Read RR interval time series 1 */
     i = 0;
     fscanf(RF1, "%f", &rrn);
     while(!feof(RF1)) 
     { 
       nlin1 = i;  
       fscanf(RF1, "%f", &rrn1);
       if (rrn1 > rrn) rr1[i] = 1; else rr1[i] = 0; 
       rrn = rrn1; 
       i++;
     }

     /* Read RR interval time series 2*/ 
     i = 0;      
     fscanf(RF2, "%f", &rrn);
     while(!feof(RF2)) 
     { 
       nlin2 = i;  
       fscanf(RF2, "%f", &rrn1);
       if (rrn1 > rrn) rr2[i] = 1;  else rr2[i] = 0; 
       rrn = rrn1; 
       i++;
     }
     
     
    int fclose( FILE *stream );
    
    /*
    for(i=0 ; i<nlin2 ; i++) { 
      printf("%d\n", rr2[i]);
    } 
    */
     
    
    printf("%f\n",distance(rr1, rr2, nlin1, nlin2));  

    exit(0);

}