5 /* version 3.6. (c) Copyright 1993-2004 by the University of Washington.
6 Written by Joseph Felsenstein, Akiko Fuseki, Sean Lamont, and Andrew Keeffe.
7 Permission is granted to copy and use this program provided no fee is
8 charged for it and provided that this copyright notice is not removed. */
10 #define zsmoothings 10 /* number of zero-branch correction iterations */
11 #define epsilonf 0.000001 /* a very small but not too small number */
12 #define delta 0.0001 /* a not quite so small number */
13 #define MAXNUMTREES 100000000 /* a number bigger than conceivable numtrees */
17 /* function prototypes */
18 void getoptions(void);
21 void inputoptions(void);
22 void fitch_getinput(void);
23 void secondtraverse(node *, double , long *, double *);
24 void firsttraverse(node *, long *, double *);
25 double evaluate(tree *);
26 void nudists(node *, node *);
27 void makedists(node *);
29 void makebigv(node *);
30 void correctv(node *);
31 void alter(node *, node *);
35 void filltraverse(node *, node *, boolean);
36 void fillin(node *, node *, boolean);
37 void insert_(node *, node *, boolean);
38 void copynode(node *, node *);
40 void copy_(tree *, tree *);
41 void setuptipf(long, tree *);
42 void buildnewtip(long , tree *, long);
43 void buildsimpletree(tree *, long);
44 void addtraverse(node *, node *, boolean, long *, boolean *);
45 void re_move(node **, node **);
46 void rearrange(node *, long *, long *, boolean *);
47 void describe(node *);
49 void nodeinit(node *);
51 void treevaluate(void);
53 void globrearrange(long* numtrees,boolean* succeeded);
54 /* function prototypes */
59 Char infilename[FNMLNGTH], outfilename[FNMLNGTH], intreename[FNMLNGTH], outtreename[FNMLNGTH];
60 long nonodes2, outgrno, nums, col, datasets, ith, njumble, jumb=0;
64 boolean minev, global, jumble, lengths, usertree, lower, upper, negallowed,
65 outgropt, replicates, trout, printdata, progress, treeprint,
68 double trweight; /* to make treeread happy */
69 boolean goteof, haslengths; /* ditto ... */
70 boolean first; /* ditto ... */
75 tree curtree, priortree, bestree, bestree2;
83 /* interactively set options */
84 long inseed0=0, loopcount;
109 printf("\nFitch-Margoliash method version %s\n\n",VERSION);
110 printf("Settings for this run:\n");
111 printf(" D Method (F-M, Minimum Evolution)? %s\n",
112 (minev ? "Minimum Evolution" : "Fitch-Margoliash"));
113 printf(" U Search for best tree? %s\n",
114 (usertree ? "No, use user trees in input file" : "Yes"));
116 printf(" N Use lengths from user trees? %s\n",
117 (lengths ? "Yes" : "No"));
119 printf(" P Power?%9.5f\n",power);
120 printf(" - Negative branch lengths allowed? %s\n",
121 negallowed ? "Yes" : "No");
122 printf(" O Outgroup root?");
124 printf(" Yes, at species number%3ld\n", outgrno);
126 printf(" No, use as outgroup species%3ld\n", outgrno);
127 printf(" L Lower-triangular data matrix?");
132 printf(" R Upper-triangular data matrix?");
137 printf(" S Subreplicates?");
143 printf(" G Global rearrangements?");
148 printf(" J Randomize input order of species?");
150 printf(" Yes (seed =%8ld,%3ld times)\n", inseed0, njumble);
152 printf(" No. Use input order\n");
154 printf(" M Analyze multiple data sets?");
156 printf(" Yes, %2ld sets\n", datasets);
159 printf(" 0 Terminal type (IBM PC, ANSI, none)?");
164 if (!(ibmpc || ansi))
166 printf(" 1 Print out the data at start of run");
171 printf(" 2 Print indications of progress of run");
176 printf(" 3 Print out tree");
181 printf(" 4 Write out trees onto tree file?");
187 "\n Y to accept these or type the letter for one to change\n");
189 phyFillScreenColor();
191 scanf("%c%*[^\n]", &ch);
196 if (strchr("DJOUNPG-LRSM01234",ch) != NULL) {
201 if (minev && (!negallowed))
206 negallowed = !negallowed;
216 initjumble(&inseed, &inseed0, seed, &njumble);
229 outgropt = !outgropt;
231 initoutgroup(&outgrno, spp);
243 replicates = !replicates;
247 usertree = !usertree;
253 initdatasets(&datasets);
256 initseed(&inseed, &inseed0, seed);
260 initterminal(&ibmpc, &ansi);
264 printdata = !printdata;
268 progress = !progress;
272 treeprint = !treeprint;
280 printf("Not a possible option!\n");
282 countup(&loopcount, 100);
284 if (lower && upper) {
285 printf("ERROR: Data matrix cannot be both uppeR and Lower triangular\n");
295 x = (vector *)Malloc(spp*sizeof(vector));
296 reps = (intvector *)Malloc(spp*sizeof(intvector));
298 x[i]=(vector)Malloc(nonodes2 * sizeof(double));
299 reps[i]=(intvector)Malloc(spp * sizeof(long));
301 nayme = (naym *)Malloc(spp*sizeof(naym));
302 enterorder = (long *)Malloc(spp*sizeof(long));
308 /* initializes variables */
310 inputnumbers2(&spp, &nonodes2, 1);
314 alloctree(&curtree.nodep, nonodes2);
315 allocd(nonodes2, curtree.nodep);
316 allocw(nonodes2, curtree.nodep);
318 alloctree(&bestree.nodep, nonodes2);
319 allocd(nonodes2, bestree.nodep);
320 allocw(nonodes2, bestree.nodep);
321 alloctree(&priortree.nodep, nonodes2);
322 allocd(nonodes2, priortree.nodep);
323 allocw(nonodes2, priortree.nodep);
325 alloctree(&bestree2.nodep, nonodes2);
326 allocd(nonodes2, bestree2.nodep);
327 allocw(nonodes2, bestree2.nodep);
336 /* print options information */
339 fprintf(outfile, "\nFitch-Margoliash method version %s\n\n",VERSION);
341 fprintf(outfile, "Minimum evolution method option\n\n");
342 fprintf(outfile, " __ __ 2\n");
343 fprintf(outfile, " \\ \\ (Obs - Exp)\n");
344 fprintf(outfile, "Sum of squares = /_ /_ ------------\n");
345 fprintf(outfile, " ");
346 if (power == (long)power)
347 fprintf(outfile, "%2ld\n", (long)power);
349 fprintf(outfile, "%4.1f\n", power);
350 fprintf(outfile, " i j Obs\n\n");
351 fprintf(outfile, "Negative branch lengths ");
353 fprintf(outfile, "not ");
354 fprintf(outfile, "allowed\n\n");
356 fprintf(outfile, "global optimization\n\n");
360 void fitch_getinput()
362 /* reads the input data */
364 } /* fitch_getinput */
367 void secondtraverse(node *q, double y, long *nx, double *sum)
369 /* from each of those places go back to all others */
370 /* nx comes from firsttraverse */
371 /* sum comes from evaluate via firsttraverse */
372 double z=0.0, TEMP=0.0;
376 TEMP = q->d[(*nx) - 1] - z;
377 *sum += q->w[(*nx) - 1] * (TEMP * TEMP);
379 secondtraverse(q->next->back, z, nx, sum);
380 secondtraverse(q->next->next->back, z, nx,sum);
382 } /* secondtraverse */
385 void firsttraverse(node *p, long *nx, double *sum)
387 /* go through tree calculating branch lengths */
388 if (minev && (p != curtree.start))
393 secondtraverse(p->back, 0.0, nx, sum);
396 firsttraverse(p->next->back, nx,sum);
397 firsttraverse(p->next->next->back, nx,sum);
399 } /* firsttraverse */
402 double evaluate(tree *t)
406 /* evaluate likelihood of a tree */
407 firsttraverse(t->start->back ,&nx, &sum);
408 firsttraverse(t->start, &nx, &sum);
409 if ((!minev) && replicates && (lower || upper))
411 t->likelihood = -sum;
416 void nudists(node *x, node *y)
418 /* compute distance between an interior node and tips */
419 long nq=0, nr=0, nx=0, ny=0;
420 double dil=0, djl=0, wil=0, wjl=0, vi=0, vj=0;
421 node *qprime, *rprime;
424 rprime = qprime->next->back;
425 qprime = qprime->back;
427 dil = qprime->d[ny - 1];
428 djl = rprime->d[ny - 1];
429 wil = qprime->w[ny - 1];
430 wjl = rprime->w[ny - 1];
433 x->w[ny - 1] = wil + wjl;
434 if (wil + wjl <= 0.0)
437 x->d[ny - 1] = ((dil - vi) * wil + (djl - vj) * wjl) / (wil + wjl);
445 y->w[nx - 1] = wil + wjl;
446 if (wil + wjl <= 0.0)
449 y->d[nx - 1] = ((dil - vi) * wil + (djl - vj) * wjl) / (wil + wjl);
453 void makedists(node *p)
455 /* compute distances among three neighbors of a node */
456 long i=0, nr=0, ns=0;
461 for (i = 1; i <= 3; i++) {
465 if (s->w[nr - 1] + r->w[ns - 1] <= 0.0)
468 p->dist = (s->w[nr - 1] * s->d[nr - 1] + r->w[ns - 1] * r->d[ns - 1]) /
469 (s->w[nr - 1] + r->w[ns - 1]);
477 void makebigv(node *p)
479 /* make new branch length */
485 for (i = 1; i <= 3; i++) {
487 p->v = (p->dist + r->dist - q->dist) / 2.0;
498 void correctv(node *p)
500 /* iterate branch lengths if some are to be zero */
502 long i=0, j=0, n=0, nq=0, nr=0, ntemp=0;
503 double wq=0.0, wr=0.0;
510 for (i = 1; i <= zsmoothings; i++) {
511 for (j = 1; j <= 3; j++) {
513 wr = r->back->w[n - 1] + p->back->w[nr - 1];
514 wq = q->back->w[n - 1] + p->back->w[nq - 1];
515 if (wr + wq <= 0.0 && !negallowed)
518 p->v = ((p->dist - q->v) * wq + (r->dist - r->v) * wr) / (wr + wq);
519 if (p->v < 0 && !negallowed)
536 void alter(node *x, node *y)
538 /* traverse updating these views */
541 alter(x, y->next->back);
542 alter(x, y->next->next->back);
549 /* renew information about subtrees */
551 node *q, *r, *pprime, *temp;
555 for (i = 1; i <= 3; i++) {
568 /* update branch lengths around a node */
573 if (p->iter || p->next->iter || p->next->next->iter) {
583 /* go through tree getting new branch lengths and views */
587 smooth(p->next->back);
588 smooth(p->next->next->back);
592 void filltraverse(node *pb, node *qb, boolean contin)
597 filltraverse(pb, qb->next->back,contin);
598 filltraverse(pb, qb->next->next->back,contin);
602 if (!qb->next->back->tip)
603 nudists(qb->next->back, pb);
604 if (!qb->next->next->back->tip)
605 nudists(qb->next->next->back, pb);
609 void fillin(node *pa, node *qa, boolean contin)
612 fillin(pa->next->back, qa, contin);
613 fillin(pa->next->next->back, qa, contin);
615 filltraverse(pa, qa, contin);
619 void insert_(node *p, node *q, boolean contin_)
621 /* put p and q together and iterate info. on resulting tree */
622 double x=0.0, oldlike;
623 hookup(p->next->next, q->back);
629 p->next->back->v = x;
630 p->next->next->back->v = x;
631 p->next->next->v = x;
632 fillin(p->back, p, contin_);
635 oldlike = curtree.likelihood;
639 } while (fabs(curtree.likelihood - oldlike) > delta);
643 void copynode(node *c, node *d)
645 /* make a copy of a node */
647 memcpy(d->d, c->d, nonodes2*sizeof(double));
648 memcpy(d->w, c->w, nonodes2*sizeof(double));
652 d->xcoord = c->xcoord;
653 d->ycoord = c->ycoord;
659 void copy_(tree *a, tree *b)
661 /* make copy of a tree a to tree b */
665 for (i = 0; i < spp; i++) {
666 copynode(a->nodep[i], b->nodep[i]);
667 if (a->nodep[i]->back) {
668 if (a->nodep[i]->back == a->nodep[a->nodep[i]->back->index - 1])
669 b->nodep[i]->back = b->nodep[a->nodep[i]->back->index - 1];
670 else if (a->nodep[i]->back
671 == a->nodep[a->nodep[i]->back->index - 1]->next)
672 b->nodep[i]->back = b->nodep[a->nodep[i]->back->index - 1]->next;
675 = b->nodep[a->nodep[i]->back->index - 1]->next->next;
677 else b->nodep[i]->back = NULL;
679 for (i = spp; i < nonodes2; i++) {
682 for (j = 1; j <= 3; j++) {
685 if (p->back == a->nodep[p->back->index - 1])
686 q->back = b->nodep[p->back->index - 1];
687 else if (p->back == a->nodep[p->back->index - 1]->next)
688 q->back = b->nodep[p->back->index - 1]->next;
690 q->back = b->nodep[p->back->index - 1]->next->next;
698 b->likelihood = a->likelihood;
703 void setuptipf(long m, tree *t)
705 /* initialize branch lengths and views in a tip */
707 intvector n=(long *)Malloc(spp * sizeof(long));
710 WITH = t->nodep[m - 1];
711 memcpy(WITH->d, x[m - 1], (nonodes2 * sizeof(double)));
712 memcpy(n, reps[m - 1], (spp * sizeof(long)));
713 for (i = 0; i < spp; i++) {
714 if (i + 1 != m && n[i] > 0) {
715 if (WITH->d[i] < epsilonf)
716 WITH->d[i] = epsilonf;
717 WITH->w[i] = n[i] / exp(power * log(WITH->d[i]));
723 for (i = spp; i < nonodes2; i++) {
728 if (WITH->iter) WITH->v = 0.0;
733 void buildnewtip(long m, tree *t, long nextsp)
735 /* initialize and hook up a new tip */
738 p = t->nodep[nextsp + spp - 3];
739 hookup(t->nodep[m - 1], p);
743 void buildsimpletree(tree *t, long nextsp)
745 /* make and initialize a three-species tree */
746 curtree.start=curtree.nodep[enterorder[0] - 1];
747 setuptipf(enterorder[0], t);
748 setuptipf(enterorder[1], t);
749 hookup(t->nodep[enterorder[0] - 1], t->nodep[enterorder[1] - 1]);
750 buildnewtip(enterorder[2], t, nextsp);
751 insert_(t->nodep[enterorder[2] - 1]->back, t->nodep[enterorder[0] - 1],
753 } /* buildsimpletree */
756 void addtraverse(node *p, node *q, boolean contin, long *numtrees,
759 /* traverse through a tree, finding best place to add p */
762 if (evaluate(&curtree) > (bestree.likelihood +
763 epsilonf * fabs(bestree.likelihood))){
764 copy_(&curtree, &bestree);
768 copy_(&priortree, &curtree);
769 if (!q->tip && contin) {
770 addtraverse(p, q->next->back, contin,numtrees,succeeded);
771 addtraverse(p, q->next->next->back, contin,numtrees,succeeded);
776 void re_move(node **p, node **q)
778 /* re_move p and record in q where it was */
779 *q = (*p)->next->back;
780 hookup(*q, (*p)->next->next->back);
781 (*p)->next->back = NULL;
782 (*p)->next->next->back = NULL;
788 void globrearrange(long* numtrees,boolean* succeeded)
790 /* does global rearrangements */
793 int i,j,k,num_sibs,num_sibs2;
794 node *where,*sib_ptr,*sib_ptr2;
795 double oldbestyet = curtree.likelihood;
798 alloctree(&globtree.nodep,nonodes2);
799 alloctree(&oldtree.nodep,nonodes2);
800 setuptree(&globtree,nonodes2);
801 setuptree(&oldtree,nonodes2);
802 allocd(nonodes2, globtree.nodep);
803 allocd(nonodes2, oldtree.nodep);
804 allocw(nonodes2, globtree.nodep);
805 allocw(nonodes2, oldtree.nodep);
806 copy_(&curtree,&globtree);
807 copy_(&curtree,&oldtree);
808 for ( i = spp ; i < nonodes2 ; i++ ) {
809 num_sibs = count_sibs(curtree.nodep[i]);
810 sib_ptr = curtree.nodep[i];
811 if ( (i - spp) % (( nonodes2 / 72 ) + 1 ) == 0 )
814 for ( j = 0 ; j <= num_sibs ; j++ ) {
815 re_move(&sib_ptr,&where);
816 copy_(&curtree,&priortree);
819 copy_(&oldtree,&curtree);
820 copy_(&oldtree,&bestree);
821 sib_ptr=sib_ptr->next;
824 else num_sibs2 = count_sibs(where);
826 for ( k = 0 ; k < num_sibs2 ; k++ ) {
828 addtraverse(sib_ptr,sib_ptr2->back,true,numtrees,succeeded);
829 if ( addwhere && where != addwhere && where->back != addwhere
830 && bestree.likelihood > globtree.likelihood) {
831 copy_(&bestree,&globtree);
834 sib_ptr2 = sib_ptr2->next;
836 copy_(&oldtree,&curtree);
837 copy_(&oldtree,&bestree);
838 sib_ptr = sib_ptr->next;
841 copy_(&globtree,&curtree);
842 copy_(&globtree,&bestree);
843 if (success && globtree.likelihood > oldbestyet) {
849 freed(nonodes2, globtree.nodep);
850 freed(nonodes2, oldtree.nodep);
851 freew(nonodes2, globtree.nodep);
852 freew(nonodes2, oldtree.nodep);
853 freetree(&globtree.nodep,nonodes2);
854 freetree(&oldtree.nodep,nonodes2);
858 void rearrange(node *p, long *numtrees, long *nextsp, boolean *succeeded)
861 if (!p->tip && !p->back->tip) {
864 copy_(&curtree, &priortree);
865 addtraverse(r, q->next->back, false, numtrees,succeeded);
866 addtraverse(r, q->next->next->back, false, numtrees,succeeded);
867 copy_(&bestree, &curtree);
868 if (global && ((*nextsp) == spp)) {
874 rearrange(p->next->back, numtrees,nextsp,succeeded);
875 rearrange(p->next->next->back, numtrees,nextsp,succeeded);
880 void describe(node *p)
882 /* print out information for one branch */
887 fprintf(outfile, "%4ld ", q->index - spp);
889 for (i = 0; i < nmlngth; i++)
890 putc(nayme[p->index - 1][i], outfile);
892 fprintf(outfile, "%4ld ", p->index - spp);
893 fprintf(outfile, "%15.5f\n", q->v);
895 describe(p->next->back);
896 describe(p->next->next->back);
901 void summarize(long numtrees)
903 /* print out branch lengths etc. */
906 fprintf(outfile, "\nremember:");
908 fprintf(outfile, " (although rooted by outgroup)");
909 fprintf(outfile, " this is an unrooted tree!\n\n");
911 fprintf(outfile, "Sum of squares = %11.5f\n\n", -curtree.likelihood);
913 fprintf(outfile, "Sum of branch lengths = %11.5f\n\n", -curtree.likelihood);
914 if ((power == 2.0) && !minev) {
916 for (i = 1; i <= nums; i++) {
917 for (j = 1; j <= nums; j++) {
919 totalnum += reps[i - 1][j - 1];
922 fprintf(outfile, "Average percent standard deviation = ");
923 fprintf(outfile, "%11.5f\n\n",
924 100 * sqrt(-curtree.likelihood / (totalnum - 2)));
926 fprintf(outfile, "Between And Length\n");
927 fprintf(outfile, "------- --- ------\n");
928 describe(curtree.start->next->back);
929 describe(curtree.start->next->next->back);
930 describe(curtree.start->back);
931 fprintf(outfile, "\n\n");
934 treeout(curtree.start, &col, 0.43429445222, true,
940 void nodeinit(node *p)
942 /* initialize a node */
945 for (i = 1; i <= 3; i++) {
946 for (j = 0; j < nonodes2; j++) {
952 if ((!lengths) || p->iter)
954 if ((!lengths) || p->back->iter)
959 void initrav(node *p)
961 /* traverse to initialize */
965 initrav(p->next->back);
966 initrav(p->next->next->back);
971 /* evaluate user-defined tree, iterating branch lengths */
975 for (i = 1; i <= spp; i++)
976 setuptipf(i, &curtree);
977 unroot(&curtree,nonodes2);
979 initrav(curtree.start);
980 if (curtree.start->back != NULL) {
981 initrav(curtree.start->back);
984 oldlike = curtree.likelihood;
985 smooth(curtree.start);
987 } while (fabs(curtree.likelihood - oldlike) > delta);
995 /* contruct the tree */
996 long nextsp,numtrees;
997 boolean succeeded=false;
1001 inputdata(replicates, printdata, lower, upper, x, reps);
1002 setuptree(&curtree, nonodes2);
1003 for (which = 1; which <= spp; which++)
1004 setuptipf(which, &curtree);
1007 openfile(&intree,INTREE,"input tree file","r",progname,intreename);
1008 numtrees = countsemic(&intree);
1009 if (numtrees > MAXNUMTREES) {
1010 printf("\nERROR: number of input trees is read incorrectly from %s\n",
1015 fprintf(outfile, "User-defined tree");
1018 fprintf(outfile, ":\n\n");
1022 while (which <= numtrees) {
1023 treeread2 (intree, &curtree.start, curtree.nodep,
1024 lengths, &trweight, &goteof, &haslengths, &spp,false,nonodes2);
1026 curtree.start = curtree.nodep[outgrno - 1]->back;
1028 printree(curtree.start, treeprint, false, false);
1029 summarize(numtrees);
1030 clear_connections(&curtree,nonodes2);
1036 inputdata(replicates, printdata, lower, upper, x, reps);
1037 setuptree(&curtree, nonodes2);
1038 setuptree(&priortree, nonodes2);
1039 setuptree(&bestree, nonodes2);
1040 if (njumble > 1) setuptree(&bestree2, nonodes2);
1042 for (i = 1; i <= spp; i++)
1043 enterorder[i - 1] = i;
1045 randumize(seed, enterorder);
1047 buildsimpletree(&curtree, nextsp);
1048 curtree.start = curtree.nodep[enterorder[0] - 1]->back;
1049 if (jumb == 1) numtrees = 1;
1052 printf("Adding species:\n");
1053 writename(0, 3, enterorder);
1055 phyFillScreenColor();
1058 while (nextsp <= spp) {
1060 buildnewtip(enterorder[nextsp - 1], &curtree, nextsp);
1061 copy_(&curtree, &priortree);
1062 bestree.likelihood = -99999.0;
1063 curtree.start = curtree.nodep[enterorder[0] - 1]->back;
1064 addtraverse(curtree.nodep[enterorder[nextsp - 1] - 1]->back,
1065 curtree.start, true, &numtrees,&succeeded);
1066 copy_(&bestree, &curtree);
1068 writename(nextsp - 1, 1, enterorder);
1070 phyFillScreenColor();
1073 if (global && nextsp == spp) {
1075 printf("Doing global rearrangements\n");
1077 for (j = spp; j < nonodes2; j++)
1078 if ( (j - spp) % (( nonodes2 / 72 ) + 1 ) == 0 )
1087 curtree.start = curtree.nodep[enterorder[0] - 1]->back;
1088 if (nextsp == spp && global)
1089 globrearrange (&numtrees,&succeeded);
1091 rearrange(curtree.start,&numtrees,&nextsp,&succeeded);
1093 if (global && ((nextsp) == spp) && progress)
1096 if (global && nextsp == spp) {
1097 putc('\n', outfile);
1102 if (jumb == 1 && nextsp == spp)
1103 copy_(&bestree, &bestree2);
1104 else if (nextsp == spp) {
1105 if (bestree2.likelihood < bestree.likelihood)
1106 copy_(&bestree, &bestree2);
1109 if (nextsp == spp && jumb == njumble) {
1110 if (njumble > 1) copy_(&bestree2, &curtree);
1111 curtree.start = curtree.nodep[outgrno - 1]->back;
1112 printree(curtree.start, treeprint, true, false);
1113 summarize(numtrees);
1118 if (jumb == njumble && progress) {
1119 printf("\nOutput written to file \"%s\"\n\n", outfilename);
1121 printf("Tree also written onto file \"%s\"\n", outtreename);
1128 int main(int argc, Char *argv[])
1132 argc = 1; /* macsetup("Fitch",""); */
1137 openfile(&infile,INFILE,"input file","r",argv[0],infilename);
1138 openfile(&outfile,OUTFILE,"output file","w",argv[0],outfilename);
1147 openfile(&outtree,OUTTREE,"output tree file","w",argv[0],outtreename);
1148 for (i=0;i<spp;++i){
1150 for (ith = 1; ith <= datasets; ith++) {
1152 fprintf(outfile, "Data set # %ld:\n\n",ith);
1154 printf("\nData set # %ld:\n\n",ith);
1157 for (jumb = 1; jumb <= njumble; jumb++)
1160 if (eoln(infile) && (ith < datasets))
1168 fixmacfile(outfilename);
1169 fixmacfile(outtreename);
1171 printf("Done.\n\n");
1173 phyRestoreConsoleAttributes();