./004075500235250000145000000000001066060521200110355ustar00neildil00004310034654./makefile010064400235250000145000000003460770477643200125570ustar00neildil00004310034654mu = roxburgh mi = neededroutines MSSStest.exe: $(mi).o $(mu).o g++ -g -o MSSStest.exe $(mi).o $(mu).o -lm -lc $(mi).o: $(mi).cpp $(mi).h g++ -c $(mi).cpp -g -o $(mi).o $(mu).o: $(mu).cpp g++ -c $(mu).cpp -g -o $(mu).o ./neededroutines.cpp010064400235250000145000000157561065564224600146050ustar00neildil00004310034654#include "neededroutines.h" float gammln(float xx) { // This routine, from Numerical Recipes in C, calculates log of the gamma // function of x (remember that gamma(x) = (x-1)!, if x is an integer. double x, z, tmp, ser; double cof[6] = {76.18009173, -86.50532033, 24.01409822, -1.231739516, 0.120858003e-2, -0.536382e-5}; int i; if (xx < 1) {z = 1 - xx; return log(PI2) + log(z) - gammln(1+z) - log(sin(PI2 * z)); } x = xx - 1.0; tmp = x+5.5; tmp -= (x+0.5) * log(tmp); ser = 1.0; for (i=0; i<=5; i++) {x += 1.0; ser += cof[i] / x; } return -tmp + log(2.50662827465*ser); } double randunif() { JC = (JC * 69069) & 037777777777; // congruential part JT ^= JT >> 15; // tausworthe part JT ^= (JT << 17) & 037777777777; return(((JT ^ JC) >> 1) * Norm); } void sdrni(unsigned long* i) { unsigned long k=*i; // if(k==0) k=time(0); // I have had to comment out the line above and replace it with the line // below because Visual C++ does not seem to recognise the time() command. k = 1; JT = k/65536; JC = k-65536*JT; JT = 65536*JT+1; JC = 32768*JC+1; } #define SORT2SWAPf(a,b) tempf=(a); (a)=(b); (b)=tempf; #define SORT2SWAPi(a,b) tempi=(a); (a)=(b); (b)=tempi; const int SORT2NSTACK=50; const int SORT2M=7; void sort2(unsigned long n, float arr[], int brr[]) { // Sorts array arr[1:n] into ascending order, while making the corresponding // rearrangement of the array brr[1:n] // (from p334 of Numerical Recipes in C) unsigned long i, ir=n, j, k, l=1; int *istack, jstack = 0; float a, tempf; int b, tempi; istack = new int [SORT2NSTACK+1]; for (;;) {if (ir-l < SORT2M) {for (j=l+1; j<=ir; j++) {a = arr[j]; b = brr[j]; for (i=j-1; i>=1; i--) {if (arr[i] <= a) break; arr[i+1] = arr[i]; brr[i+1] = brr[i]; } arr[i+1] = a; brr[i+1] = b; } if (!jstack) {delete [] istack; return; } ir = istack[jstack]; l = istack[jstack-1]; jstack -= 2; } else {k=(l+ir) >> 1; // This means (l+ir)/2 (>> is right shift operator) SORT2SWAPf(arr[k], arr[l+1]); SORT2SWAPi(brr[k], brr[l+1]); if (arr[l+1] > arr[ir]) {SORT2SWAPf(arr[l+1], arr[ir]); SORT2SWAPi(brr[l+1], brr[ir]); } if (arr[l] > arr[ir]) {SORT2SWAPf(arr[l], arr[ir]); SORT2SWAPi(brr[l], brr[ir]); } if (arr[l+1] > arr[l]) {SORT2SWAPf(arr[l+1], arr[l]); SORT2SWAPi(brr[l+1], brr[l]); } i=l+1; j = ir; a = arr[l]; b = brr[l]; for (;;) {do {i++;} while (arr[i]a); if (j SORT2NSTACK) {cout << "ERROR in sort2: SORT2NSTACK too small"; exit(0); } if (ir-i+1 >= j-l) {istack[jstack] = ir; istack[jstack-1] = i; ir = j-1; } else {istack[jstack] = j-1; istack[jstack-1] = l; l = i; } } } } void rank(unsigned long len, float arr[], int ranks[]) { // Ranks array arr[1:n] (based on sort2(), // taken from p334 of Numerical Recipes in C) int i; float *arrcopy; int *index; arrcopy = new float [len+1]; index = new int [len+1]; for (i=1; i<=len; i++) {arrcopy[i] = (float) arr[i]; index[i] = i; } sort2(len, arrcopy, index); for (i=1; i<=len; i++) ranks[index[i]] = i; } float rankties(unsigned long len, float arr[], float ranks[]) { // This is very similar to rank(). The difference is that this assigns // non-integer ranks when there are tied data. // It also returns a correction factor, CKW, for tied data. This is used by // the Kruskal-Wallis test (see Biostatistics, Fisher and van Belle, p478). int i, begin, end, TL; float mid, CKW; int *intranks; intranks = new int [len+1]; rank(len, arr, intranks); for (i=1; i<=len; i++) ranks[i] = (float) intranks[i]; begin = 1; CKW = 0; while(beginbegin) {mid = (begin + end) * 1.0 / 2; for (i=begin; i<=end; i++) ranks[i] = mid; TL = end - begin + 1; CKW += pow(TL*1.0, 3) - TL; } begin = end+1; } CKW /= pow(len*1.0, 3) - len; return CKW; } float pchisq(int df, float x) { // This returns the probability that X>x where X~chisq(df) return gammq(df*0.5, x/2); } float gammp(float a, float x) { // Returns the incomplete gamma function P(a,x) // Function taken from Numerical Recipes in C, p218-9 float gamser, gammcf, gln; if (x<0.0 || a<=0.0) {cout << "Invalid arguments in routine gammp\n"; exit(0); } if (x < (a+1.0) ) {// Use the series representation gser(&gamser, a, x, &gln); return gamser; } else {// Use the continued fraction representation gcf(&gammcf, a, x, &gln); return 1.0 - gammcf; // and take its complement } } float gammq(float a, float x) { // Returns the incomplete gamma function Q(a,x) = 1 - P(a,x) // Function taken from Numerical Recipes in C, p218-9 float gamser, gammcf, gln; if (x<0.0 || a<=0.0) {cout << "Invalid arguments in routine gammp\n"; exit(0); } if (x < (a+1.0) ) {// Use the series representation gser(&gamser, a, x, &gln); return 1.0 - gamser; // and take its complement } else {// Use the continued fraction representation gcf(&gammcf, a, x, &gln); return gammcf; } } void gser(float *gamser, float a, float x, float *gln) { // Returns the incomplete gamma function P(a,x) evaluated by its series // representation as gamser. Also returns ln Gamma(a) as gln. // Function taken from Numerical Recipes in C, p218-9 int n; float sum, del, ap; *gln = gammln(a); if (x<=0.0) {if (x<0.0) {cout << "x less than 0 in routine gser\n"; exit(0); } *gamser = 0.0; return; } else {ap = a; del = sum = 1.0/a; for (n=1; n<=ITMAX; n++) {++ap; del *= x/ap; sum += del; if (fabs(del) < fabs(sum)*EPS) {*gamser = sum*exp(-x+a*log(x)-(*gln)); return; } } cout << "a too large, or ITMAX (set to 100) too small in routine gser"; exit(1); return; } } void gcf(float *gammcf, float a, float x, float *gln) { // Returns the incomplete gamma function Q(a,x) evaluated by its continued // fraction representation as gammcf. Also returns ln Gamma(a) as gln. // Function taken from Numerical Recipes in C, p218-9 int i; float an, b, c, d, del, h; *gln = gammln(a); b = x+1.0-a; c = 1.09/FPMIN; d=1.0/b; h=d; for (i=1; i<=ITMAX; i++) {an = -i*(i-a); b += 2.0; d = an*d+b; if (fabs(d) < FPMIN) d = FPMIN; c = b+an/c; if (fabs(c) < FPMIN) c = FPMIN; d = 1.0/d; del = d*c; h *= del; if (fabs(del-1.0) < EPS) break; } if (i>ITMAX) {cout << "a too large, ITMAX too small in gcf"; exit(0); } *gammcf = exp(-x+a*log(x)-(*gln))*h; }./neededroutines.h010064400235250000145000000027541014043455200142300ustar00neildil00004310034654#include #include #include #include using namespace std; const double PI2 = 3.141593; // Three consts needed for gammp() and gammq() const int ITMAX = 100; const double EPS = 3.0e-7; const double FPMIN = 1.0e-30; float gammln(float xx); // For generating uniform random numbers (obtained from David Robelin) /* Combined congruential and Tauseworthe generators from SuperDuper * package. Should work on machines with unsigned long of at least 32 * bits. JC and JT must be initialized to values with 0 < JC < 2^32 and * 0 < JT < 2^32. JC must be odd. * References: Marsaglia, Ananthanarayanan & Paul, 1973, * Learmonth & Lewis, 1973, and Dudewicz, 1976) tu dois avoir les lignes suivantes dans ton programme : unsigned long iseed=125645; // or some other integer sdrni(&iseed); Il suffit que tu aies ecrit ces lignes avant d'appeler la fonction drand48(). */ static unsigned long JC, JT; static double Norm=4.656612873E-10; double randunif(); void sdrni(unsigned long* i); // End of bit for generating uniform random numbers void sort2(unsigned long n, float arr[], int brr[]); void rank(unsigned long len, float arr[], int ranks[]); float rankties(unsigned long len, float arr[], float ranks[]); float pchisq(int df, float x); float gammp(float a, float x); float gammq(float a, float x); void gcf(float *gammcf, float a, float x, float *gln); void gser(float *gamser, float a, float x, float *gln); ./roxburgh.cpp010064400235250000145000000313331065564224600134150ustar00neildil00004310034654#include "neededroutines.h" const int MAXPERSON = 20000; const int MAXGROUPS = 100; const int NSIMUL = 1000; int readdata(int familyno[], int indivno[], int edssv[], int durationv[], int groupv[], int &ngroups); void calcglobal(float msssv[], int edssv[], int durationv[], int nperson); void calclocal(float msssv[], int edssv[], int durationv[], int nperson); void kruskal_test(float msssv[], int durationv[], int groupv[], int nperson, int permp); void kruskal_perm(float ranksv[], int groupv[], int nperson, float TKWv, int numgroupv[]); inline void permute(int n, int labels[]); void dump_msss(int familynov[], int indivnov[], int edssv[], int durationv[], int groupv[], float msssv[], int nperson); int main(int argc, char *argv[]) { // arguments to main() are int edss[MAXPERSON], duration[MAXPERSON]; // edss actually means edss score * 2 (in order to be an integer) int familyno[MAXPERSON], indivno[MAXPERSON]; float msss[MAXPERSON]; int group[MAXPERSON], ngroups; int edssfreq[20]; int seed, flag, key, nperson, tabletype, permp, i, j; seed = 10; unsigned long iseed=seed; sdrni(&iseed); cout << "Borland C++ 5.5.1 for Win32 Copyright (c) 1993, 2000 Borland\n"; cout << "MSSStest version 2.0 September 2004\n"; nperson = readdata(familyno, indivno, edss, duration, group, ngroups); ofstream fout("msss.out", ios::app); if (!fout) {cout << "Cannot open `msss.out' file to store results.\n"; cout << "Type 0 and return to end program\n"; cin >> key; exit(0); } flag = 0; while (!flag) {cout << "Do you wish to use global MSSS or local MSSS?\n(We strongly recommend global MSSS as the default.)\n"; cout << "Type 1 for global MSSS or 2 for local MSSS.\nThen press return.\n"; cin >> key; if (key==1 || key==2) {flag = 1; if (key==1) {cout << "You selected global MSSS.\n"; fout << "Using global MSSS.\n"; } if (key==2) {cout << "You selected local MSSS.\n"; fout << "Using local MSSS.\n"; } } } tabletype = key; fout.close(); if (ngroups>1) {flag = 0; while (!flag) {cout << "Do you also wish to calculate permutation p-value?\n"; cout << "Type 1 for permutation p-value or 0 for no permutation p-value.\nThen press return.\n"; cin >> key; if (key==1 || key==0) {flag = 1; if (key==1) cout << "You chose to calculate permutation p-value.\n"; if (key==0) cout << "You selected no permutation p-value.\n"; } } permp = key; } // end of if (ngroups>1) section if (tabletype==1) calcglobal(msss, edss, duration, nperson); else calclocal(msss, edss, duration, nperson); if (ngroups==1) permp = 0; kruskal_test(msss, duration, group, nperson, permp); dump_msss(familyno, indivno, edss, duration, group, msss, nperson); if (ngroups>1) cout << "Mean MSSS and test result (if any) saved in file `msss.out'.\n"; cout << "Type 0 and return to end program\n"; cin >> key; } int readdata(int familynov[], int indivnov[], int edssv[], int durationv[], int groupv[], int &ngroups) { int i, usegroup[MAXGROUPS], key, tempi, nper; float temp; int errorflag1, errorflag2; cout << "Reading data file `edss.txt'.\n"; for (i=0; i> key; exit(0); } while (!fin.eof()) {fin >> tempi; familynov[i] = tempi; if (fin.eof()) break; fin >> indivnov[i]; fin >> temp; edssv[i] = (int) floor(temp * 2 + 0.0001); fin >> temp; durationv[i] = (int) floor(temp + 0.0001); fin >> groupv[i]; if (groupv[i] < 0 || groupv[i] >= MAXGROUPS) {cout << "Error in data. Groups' designations should be >=0 and <" << MAXGROUPS << ".\n"; cout << "Type 0 and return to end program\n"; cin >> key; exit(0); } usegroup[groupv[i]] = 1; i++; } fin.close(); nper = i; ngroups = 0; for (i=0; i0) ngroups++; cout << "Found data on " << nper << " individuals in " << ngroups << " groups.\n"; cout << "Family number, individual number, EDSS, duration and group for first and last individuals are:\n"; cout << familynov[0] << " " << indivnov[0] << " " << edssv[0] * 1.0 / 2 << " " << durationv[0] << " " << groupv[0] << endl; cout << familynov[nper-1] << " " << indivnov[nper-1] << " " << edssv[nper-1] * 1.0 / 2 << " " << durationv[nper-1] << " " << groupv[nper-1] << endl; /* if (ngroups<2) {cout << "Error in data. There must be at least two groups.\n"; cout << "Type 0 and return to end program\n"; cin >> key; exit(0); } */ errorflag1 = 0; errorflag2 = 0; for (i=0; i20 || edssv[i]==1) errorflag1 = 1; if (edssv[i]==20) errorflag2 = 1; } if (errorflag1) {cout << "File contains illegal EDSS values. Legal values are 0, 1, 1.5, 2, ..., 9.5.\n"; cout << "Type 0 and return to end program\n"; cin >> key; exit(0); } if (errorflag2) cout << "WARNING: File contains EDSS values of 10. These will be treated as though 9.5.\n"; ofstream fout("msss.out", ios::trunc); if (!fout) {cout << "Cannot create new `msss.out' file to store output.\n"; cout << "Type 0 and return to end program\n"; cin >> key; exit(0); } fout << nper << " individuals.\n"; fout << ngroups << " groups.\n"; fout.close(); return nper; } void calcglobal(float msssv[], int edssv[], int durationv[], int nperson) { int i, j, key, durtemp, edsstemp; float mssstable[20][31]; cout << "Reading global MSSS file `global.dat'.\n"; ifstream fin("global.dat"); if (!fin) {cout << "Cannot find file `global.dat'." << endl; cout << "Type 0 and return to end program\n"; cin >> key; exit(0); } for (i=0; i<20; i++) for (j=0; j<31; j++) fin >> mssstable[i][j]; fin.close(); for (i=0; i30) durtemp = 30; else durtemp = durationv[i]; if (edssv[i]==20) edsstemp = 19; else edsstemp = edssv[i]; msssv[i] = mssstable[edsstemp][durtemp]; } } void calclocal(float msssv[], int edssv[], int durationv[], int nperson) { int i, j, mindur, maxdur, durtemp, edsstemp; int counts[20][31], cumcounts[20][31]; float mssstable[20][31]; for (i=0; i<20; i++) for (j=0; j<31; j++) counts[i][j] = 0; for (i=0; i=2 && durationv[i]<=3) {mindur = durationv[i] - 1; maxdur = durationv[i]+2; } if (durationv[i]>3) {mindur = durationv[i] - 2; maxdur = durationv[i] + 2; if (maxdur>30) maxdur = 30; } for (j=mindur; j<=maxdur; j++) counts[edssv[i]][j]++; } for (i=0; i<31; i++) {cumcounts[0][i] = counts[0][i]; cumcounts[1][i] = counts[0][i]; // That is for an EDSS of 0.5 (which does not exist) for (j=2; j<20; j++) cumcounts[j][i] = cumcounts[j-1][i] + counts[j][i]; } for (i=0; i<31; i++) {mssstable[0][i] = (cumcounts[0][i] + 1) / 2; mssstable[0][i] /= (cumcounts[19][i] + 1); for (j=1; j<20; j++) {mssstable[j][i] = (cumcounts[j-1][i] + 1 + cumcounts[j][i]) / 2; mssstable[j][i] /= (cumcounts[19][i] + 1); } } for (i=0; i30) durtemp = 30; else durtemp = durationv[i]; if (edssv[i]==20) edsstemp = 19; else edsstemp = edssv[i]; msssv[i] = mssstable[edsstemp][durtemp] * 10; } } void kruskal_test(float msssv[], int durationv[], int groupv[], int npersonv, int permp) { int i, numgroup[MAXGROUPS], ngroups, key, count, newgroupv[MAXPERSON+1]; float msssvec1[MAXPERSON+1], msssvec2[MAXPERSON+1], ranks[MAXPERSON+1], sumranks[MAXGROUPS], summsss[MAXGROUPS]; float TKW, CKW, Tstat, pval; count = 0; for (i=0; i0) {msssvec1[count] = msssv[i]; newgroupv[count] = groupv[i]; count++; } // Just take people with duration>0 ofstream fout("msss.out", ios::app); if (!fout) {cout << "Cannot open `msss.out' file to store results.\n"; cout << "Type 0 and return to end program\n"; cin >> key; exit(0); } if (count0 are used.\n" << npersonv - count << " individuals with duration=0 have been excluded.\n"; fout << "Only individuals with duration >0 are used.\n" << npersonv - count << " individuals with duration=0 have been excluded.\n"; npersonv = count; } for (i=0; i0) {ngroups++; TKW += pow(sumranks[i], 2) / numgroup[i]; } TKW *= 12.0 / (npersonv * (npersonv+1)); Tstat = TKW; TKW -= 3 * (npersonv+1); // Correction for ties TKW /= (1 - CKW); // If H_0 true, TKW is asymptotic chisq with (ngroups-1) df cout << "Mean MSSS score in each group is:\n"; fout << "Mean MSSS score in each group is:\n"; for (i=0; i0) {cout << "Group " << i << ": " << summsss[i] / numgroup[i] << endl; fout << "Group " << i << ": " << summsss[i] / numgroup[i] << endl; } if (ngroups>1) {cout << "Kruskal-Wallis test statistic is " << TKW << ".\nAsymptotically this is distributed chi-square on " << ngroups-1 << " degrees of freedom.\n"; fout << "Kruskal-Wallis test statistic is " << TKW << ".\nAsymptotically this is distributed chi-square on " << ngroups-1 << " degrees of freedom.\n"; pval = pchisq(ngroups-1, TKW); if (pval>0.000001) {cout << "This gives a p-value of " << pval << ".\n"; fout << "This gives a p-value of " << pval << ".\n"; } else {cout << "This gives a p-value of <10e-6.\n"; fout << "This gives a p-value of <10e-6.\n"; } } fout.close(); if (ngroups>1 & permp) kruskal_perm(ranks, newgroupv, npersonv, Tstat, numgroup); } void kruskal_perm(float ranksv[], int groupv[], int nperson, float Tstatv, int numgroupv[]) { int sim, i, greater, key; int groupperm[MAXPERSON+1]; float sumranksperm[MAXGROUPS], Tperm; greater = 0; for (i=0; i0) Tperm += pow(sumranksperm[i], 2) / numgroupv[i]; Tperm *= 12.0 / (nperson * (nperson+1)); if (Tperm>Tstatv) greater++; } cout << "Based on " << NSIMUL << " permutations, the permutation p-value is " << (greater + 1.0) / (NSIMUL+1) << ".\n"; ofstream fout("msss.out", ios::app); if (!fout) {cout << "Cannot open `msss.out' file to store results.\n"; cout << "Type 0 and return to end program\n"; cin >> key; exit(0); } fout << "Based on " << NSIMUL << " permutations, the permutation p-value is " << (greater + 1.0) / (NSIMUL+1) << ".\n"; fout.close(); } inline void permute(int n, int labels[]) { // This takes vector of labels labels[] and randomly permutes it int i, choose, temp; for (i=0; i> key; exit(0); } fout << "Family\tIndiv\tEDSS\tDur\tGroup\tMSSS\n"; for (i=0; i1000 patients) and the method of recruitment of patients is such that the distribution of EDSS conditional on duration is very different from that of the combined cohort of 9892 patients used to calculate the Global table. This could be, for example, if a study recruited only fast and/or slow progressors. P-values for the Kruskal-Wallis test can be obtained either by using an asymptotic (large sample) approximation or by an exact, permutation method. The asymptotic method should be fine for large samples. However, if the sample is small, ask MSSStest to also calculate a permutation p-value. In most cases, this should be very similar to that calculated by the asymptotic method. If they are very different, the sample is too small for the asymptotic approximation to be reliable and the permutation p-value should be used instead. Another application of the MSSS is to describe disease severity in a single dataset. If all patients entered into MSSStest are in a single dataset it will calculate the mean Global MSSS for this dataset but will not perform a Kruskal-Wallis test. The mean is calculated excluding patients with duration 0 years because EDSS assessments in the first year are not adequately predictive of later disease progression. Input files =========== MSSStest requires as input files: edss.txt This should be a tab or space delimited text file (ASCII) file. It should contain one row for each individual in the data set. Five columns are required. The first two columns are simply labels for the individuals in the data set. They are not used to perform the test. The first column is the family number and the second column is the number of the individual in the family. The third column is for the EDSS score. The fourth is for the disease duration at the time the EDSS was measured, rounded down to the next lowest whole year. The fifth is for the group to which the individual belongs. Groups are coded numerically and should be between 0 and 99. An example edss.txt file is provided. Note that no header row is allowed. global.dat This is the Global MSSS table: a matrix for converting EDSS scores into MSSS scores. It is not necessary to understand it, but if you are interested, row i corresponds to an EDSS score of i/2 (e.g. the fifth row is for EDSS=2.5) and column j corresponds to a duration of j-1 years. Output files =========== MSSStest produces the two output files. msss.out This contains a summary of the results of the Kruskal-Wallis test or in the case of a single test just the mean MSSS. indivmsss.out This is the same as edss.txt, except that an extra, sixth column is added which contains each individual's MSSS scores. Obtaining MSSStest ================== Versions of MSSStest are available for Windows and Linux - see the download page: http://www-gene.cimr.cam.ac.uk/MSgenetics/GAMES/MSSS/download.html If you wish to use the program on a platform other than Windows or Linux, we also provide source code on the download page. MSSStest is written in C++ and may be compiled using a suitable C++ compiler. The files roxburgh.cpp and neededroutines.cpp are C++ source files and neededroutines.h is a "header" file. In unix, compilation would normally be by: CC -o MSSStest.exe neededroutines.cpp roxburgh.cpp -lm -lc where CC is the command name of the compiler. This produces the executable file MSSStest.exe. Alternatively, a makefile is also included (this may require editing for your C++ compiler). Testing the program =================== We provide a test file, edss.dat. This contains 250 patients, belonging to three genotype groups. When these data are analysed using the Global MSSS, the p-value is 0.69. When they are analysed using Local MSSS (which we do not recommend for such a small dataset), it is 0.62. The data files edss.txt and global.dat need to be in the same folder as the file mssstest.exe. The way the program is launched in Windows is simply by double clicking on the mssstest.exe icon (once it has been unzipped). Licensing of MSSStest ===================== This software is downloaded at the user's risk. Anyone may copy it but no one may sell it. We make no representation or warranties with respect to the MSSStest software and specifically disclaim any implied warranties of merchantability and fitness for a particular purpose. We reserve the right to revise the MSSStest software and to make changes therein from time to time without obligation to notify any person or organisation of such revision or changes. While we make every effort to ensure the reliability of the MSSStest software we may not be held responsible for errors, omissions or other inaccuracies or any consequences thereof. THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SHAUN SEAMAN OR RICHARD ROXBURGH OR THEIR EMPLOYERS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. Version 2.0 September 2004 ========================== The new features of this version are A)The program will calculate mean EDSS where all patients are included in one group. This can then be used as a general descriptor of progression in that group. B)While the program still accepts data from patients with disease duration less than one year ie whose disease duration in is given as "0" and will calculate a nominal MSSS for these patients these patients are not included in the calculation of mean MSSS nor used in the Kruskal Wallis tests. Note entering all patients in a group with disease duration "0" will cause it to crash. Version 3.0: 1st August 2007 ============================ Versions of the program prior to this date had an error which made the file indivmsss.out unreliable when patients of duration 0 were entered. Individuals' MSSS scores as listed in this file were correct. However they were assigned to the wrong group if there were patients with duration 0 in the input file. This did not affect the Kruskal Wallis analysis or p values but did mean that calculated mean scores for each group were unreliable. MSSStest version 3.0 has this bug corrected. We are grateful to Yoav Ben-Shlomo (Dept. of Social Medicine, University of Bristol) for bringing this error to our attention. Shaun Seaman and Richard Roxburgh 2 August 2007 Max Planck Institute for Psychiatry Kraepelinstr. 2-10 Munich Germany ./edss.txt010064400235250000145000000061761065564071300125540ustar00neildil000043100346541 1 5 13 2 2 1 8.5 7 3 3 1 8 4 3 4 1 7.5 38 2 5 1 7 14 3 6 1 6.5 21 1 7 1 6.5 4 3 8 1 6 12 2 9 1 6 24 2 10 1 6 12 2 11 1 6 10 2 12 1 6 0 3 13 1 5.5 12 3 14 1 5 16 2 15 1 4.5 10 1 16 1 4 2 1 17 1 3.5 0 1 18 1 3 34 3 19 1 3 12 3 20 1 3 12 3 21 1 2.5 14 1 22 1 2.5 6 1 23 1 2 4 3 24 1 2 10 1 25 1 1.5 7 1 26 1 1 23 2 27 1 1 15 3 28 1 0 8 1 29 1 6 42 3 30 1 7.5 21 2 31 1 7.5 18 3 32 1 7.5 35 3 33 1 3 28 2 34 1 6 15 1 35 1 6 14 1 36 1 6.5 11 3 37 1 2 28 1 38 1 6 2 3 39 1 2.5 6 1 40 1 7 24 2 41 1 8.5 10 3 42 1 2 22 1 43 1 7 22 3 44 1 5.5 10 3 45 1 3.5 1 1 46 1 1.5 3 1 47 1 6 9 3 48 1 1.5 4 2 49 1 3 11 3 50 1 6.5 11 2 51 1 0 15 2 52 1 2.5 5 2 53 1 3.5 12 3 54 1 1.5 4 3 55 1 1 2 1 56 1 5 17 2 57 1 3.5 6 1 58 1 6 8 2 59 1 6.5 13 3 60 1 2.5 10 3 61 1 6 18 3 62 1 3 10 1 63 1 5 10 1 64 1 2.5 11 3 65 1 6.5 8 2 66 1 9 17 1 67 1 8.5 46 1 68 1 1 18 1 69 1 1 0 2 70 1 1 5 1 71 1 1 1 3 72 1 7 17 2 73 1 1 6 1 74 1 1.5 5 2 75 1 1 10 2 76 1 5.5 30 2 77 1 1 0 2 78 1 0 6 2 79 1 3.5 2 3 80 1 2.5 1 2 81 1 1.5 10 3 82 1 3.5 24 2 83 1 1.5 6 3 84 1 2 0 1 85 1 2 5 1 86 1 6.5 20 2 87 1 4.5 20 1 88 1 3 0 1 89 1 1.5 4 3 90 1 0 2 3 91 1 0 0 2 92 1 2 0 1 93 1 6.5 17 1 94 1 3.5 14 2 95 1 6 16 2 96 1 9.5 18 2 97 1 4 7 1 98 1 8 10 1 99 1 1.5 9 3 100 1 9.5 14 2 101 1 5.5 5 3 102 1 5.5 18 2 103 1 7 18 3 104 1 1.5 6 2 105 1 1.5 1 1 106 1 6 20 3 107 1 1 1 3 108 1 0 3 3 109 1 0 14 1 110 1 1.5 5 1 111 1 5.5 8 3 112 1 9 28 2 113 1 6 33 2 114 1 4 10 2 115 1 6 4 1 116 1 7 13 1 117 1 7.5 9 1 118 1 1.5 11 1 119 1 5 11 3 120 1 7 16 3 121 1 6.5 22 2 122 1 3 15 3 123 1 5.5 1 3 124 1 7 23 2 125 1 6.5 14 1 126 1 3.5 9 2 127 1 2 6 3 128 1 7 22 2 129 1 2.5 18 1 130 1 7 31 1 131 1 7 22 1 132 1 5.5 10 3 133 1 7.5 20 1 134 1 1 7 1 135 1 2 39 3 136 1 2 34 1 137 1 0 2 2 138 1 3 17 3 139 1 3 6 1 140 1 3.5 13 1 141 1 2 4 2 142 1 0 2 3 143 1 1.5 15 2 144 1 2.5 2 1 145 1 4 5 3 146 1 1 17 1 147 1 1.5 16 1 148 1 4 17 2 149 1 3 18 3 150 1 2.5 0 2 151 1 8 12 1 152 1 0 0 1 153 1 1 2 1 154 1 2 2 3 155 1 2 3 1 156 1 3.5 17 2 157 1 3 18 2 158 1 3.5 2 1 159 1 4.5 9 2 160 1 4.5 22 2 161 1 2 7 1 162 1 6.5 24 1 163 1 3 6 3 164 1 3 7 3 165 1 5 7 3 166 1 0 1 1 167 1 6 11 3 168 1 7.5 10 2 169 1 8 16 1 170 1 1.5 14 1 171 1 1 1 1 172 1 4.5 5 2 173 1 1 3 3 174 1 2 3 3 175 1 2 7 3 176 1 6 11 1 177 1 1.5 3 1 178 1 1 3 1 179 1 1 1 1 180 1 2 2 2 181 1 1.5 19 2 182 1 1 11 1 183 1 2 5 1 184 1 1 6 2 185 1 6.5 33 2 186 1 1.5 19 2 187 1 2 13 3 188 1 6 21 2 189 1 3 2 2 190 1 1 7 1 191 1 1 1 3 192 1 1 5 2 193 1 1.5 9 1 194 1 1.5 4 2 195 1 2 4 3 196 1 7 27 3 197 1 7.5 24 3 198 1 3 15 3 199 1 3.5 9 1 200 1 3 7 1 201 1 1.5 3 1 202 1 1 1 3 203 1 1 13 1 204 1 2.5 9 3 205 1 7 22 2 206 1 3.5 10 2 207 1 3.5 10 3 208 1 1 3 3 209 1 6 16 3 210 1 4 5 3 211 1 7 47 3 212 1 7 4 3 213 1 3 9 2 214 1 8 25 2 215 1 6 3 2 216 1 5 6 1 217 1 4 14 3 218 1 2 19 2 219 1 7 12 1 220 1 3 4 3 221 1 6 28 1 222 1 9 13 1 223 1 4 16 2 224 1 2 2 3 225 1 6 13 1 226 1 6 8 2 227 1 6 11 3 228 1 3 3 3 229 1 2 1 2 230 1 8 3 2 231 1 5 6 1 232 1 7 9 1 233 1 2 4 2 234 1 1 11 2 235 1 5 13 1 236 1 8 29 1 237 1 2.5 12 3 238 1 2 3 1 239 1 6 14 2 240 1 6 20 1 241 1 4 6 2 242 1 1.5 18 2 243 1 4 5 3 244 1 0 0 2 245 1 3 2 1 246 1 1.5 0 2 247 1 2 15 2 248 1 0 1 2 249 1 2 0 3 250 1 3 0 1./global.dat010064400235250000145000000067431014043435000127720ustar00neildil000043100346540.823 0.671 0.528 0.45 0.345 0.3 0.254 0.238 0.209 0.206 0.188 0.167 0.155 0.134 0.11 0.098 0.086 0.053 0.043 0.054 0.049 0.049 0.035 0.053 0.045 0.05 0.047 0.053 0.036 0.025 0.01 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2.851 2.436 2.011 1.768 1.446 1.282 1.13 1.039 0.937 0.881 0.776 0.704 0.641 0.564 0.487 0.453 0.384 0.318 0.26 0.277 0.261 0.301 0.234 0.274 0.242 0.233 0.198 0.224 0.166 0.177 0.134 4.741 4.295 3.693 3.339 2.871 2.597 2.327 2.103 1.922 1.757 1.532 1.395 1.279 1.134 1.029 0.994 0.854 0.763 0.657 0.631 0.587 0.657 0.544 0.581 0.522 0.474 0.452 0.481 0.404 0.468 0.445 6.326 5.866 5.236 4.825 4.275 3.897 3.539 3.17 2.926 2.649 2.341 2.128 1.978 1.795 1.7 1.642 1.425 1.277 1.116 1.004 0.942 1.024 0.902 0.908 0.862 0.765 0.782 0.78 0.736 0.797 0.816 7.47 7.08 6.464 6.002 5.418 4.942 4.546 4.126 3.808 3.448 3.099 2.817 2.635 2.44 2.332 2.259 1.993 1.77 1.566 1.39 1.292 1.386 1.276 1.255 1.248 1.148 1.168 1.154 1.164 1.19 1.187 8.034 7.929 7.271 6.821 6.248 5.79 5.382 4.966 4.568 4.163 3.789 3.456 3.246 3.048 2.91 2.824 2.56 2.304 2.085 1.889 1.706 1.774 1.663 1.642 1.626 1.556 1.582 1.56 1.52 1.506 1.454 8.582 8.642 7.983 7.541 6.986 6.574 6.138 5.749 5.357 4.929 4.544 4.202 3.935 3.694 3.548 3.441 3.175 2.953 2.695 2.502 2.293 2.338 2.196 2.19 2.148 2.047 2.081 2.03 1.876 1.785 1.691 9.085 9.092 8.575 8.138 7.652 7.259 6.807 6.463 6.1 5.64 5.267 4.93 4.621 4.375 4.255 4.135 3.869 3.654 3.374 3.197 2.993 2.968 2.816 2.784 2.708 2.529 2.627 2.564 2.387 2.266 2.226 9.405 9.346 8.946 8.555 8.119 7.753 7.325 6.981 6.605 6.133 5.762 5.409 5.115 4.901 4.806 4.672 4.414 4.168 3.897 3.733 3.521 3.428 3.285 3.211 3.094 2.837 2.994 2.906 2.755 2.684 2.745 9.512 9.499 9.179 8.831 8.424 8.078 7.66 7.324 6.951 6.501 6.125 5.803 5.526 5.311 5.223 5.087 4.813 4.555 4.278 4.133 3.94 3.828 3.694 3.685 3.517 3.211 3.399 3.291 3.04 3.013 3.131 9.604 9.626 9.378 9.073 8.707 8.381 7.981 7.655 7.321 6.901 6.567 6.287 6.014 5.785 5.687 5.502 5.187 4.939 4.628 4.5 4.31 4.211 4.093 4.186 4.009 3.744 3.945 3.857 3.456 3.405 3.501 9.756 9.737 9.586 9.349 9.079 8.827 8.496 8.243 7.967 7.652 7.385 7.168 6.909 6.722 6.542 6.325 6 5.742 5.437 5.354 5.163 5.093 5.035 5.16 5.03 4.875 5.019 4.925 4.537 4.354 4.347 9.839 9.839 9.786 9.625 9.47 9.317 9.08 8.914 8.708 8.526 8.303 8.144 7.92 7.821 7.574 7.402 7.138 6.892 6.626 6.589 6.435 6.353 6.352 6.469 6.362 6.256 6.394 6.325 5.986 5.684 5.608 9.898 9.898 9.876 9.773 9.683 9.595 9.453 9.328 9.211 9.093 8.921 8.785 8.625 8.546 8.335 8.169 7.966 7.765 7.543 7.507 7.451 7.333 7.348 7.457 7.383 7.238 7.439 7.382 7.067 6.759 6.662 9.909 9.941 9.931 9.857 9.802 9.763 9.681 9.592 9.549 9.471 9.335 9.239 9.13 9.029 8.858 8.703 8.541 8.381 8.227 8.215 8.225 8.083 8.103 8.198 8.147 8.003 8.211 8.141 7.898 7.658 7.537 9.954 9.966 9.967 9.921 9.878 9.862 9.814 9.758 9.739 9.701 9.607 9.523 9.431 9.337 9.2 9.107 9.041 8.993 8.94 8.978 8.984 8.866 8.835 8.865 8.812 8.727 8.889 8.91 8.753 8.62 8.472 9.984 9.984 9.988 9.972 9.95 9.946 9.925 9.895 9.887 9.865 9.83 9.778 9.712 9.654 9.574 9.508 9.485 9.523 9.511 9.573 9.581 9.491 9.42 9.433 9.387 9.351 9.482 9.562 9.454 9.38 9.273 9.983 9.983 9.994 9.983 9.975 9.975 9.966 9.954 9.956 9.945 9.935 9.918 9.883 9.855 9.819 9.78 9.754 9.788 9.775 9.814 9.803 9.77 9.725 9.753 9.735 9.75 9.802 9.85 9.798 9.747 9.674 9.998 9.998 9.995 9.994 9.992 9.992 9.992 9.99 9.99 9.987 9.986 9.978 9.965 9.959 9.952 9.944 9.94 9.955 9.957 9.964 9.951 9.962 9.947 9.953 9.955 9.975 9.962 9.979 9.976 9.962 9.911