ecat7ml.c
Go to the documentation of this file.
00001 /******************************************************************************
00002 
00003   Copyright (c) 2003-2007 Turku PET Centre
00004 
00005   Library:     ecat7ml.c
00006   Description: Reading and writing ECAT 7.x matrix list.
00007 
00008   This library is free software; you can redistribute it and/or
00009   modify it under the terms of the GNU Lesser General Public
00010   License as published by the Free Software Foundation; either
00011   version 2.1 of the License, or (at your option) any later version.
00012 
00013   This library is distributed in the hope that it will be useful,
00014   but WITHOUT ANY WARRANTY; without even the implied warranty of
00015   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
00016   See the GNU Lesser General Public License for more details:
00017   http://www.gnu.org/copyleft/lesser.html
00018 
00019   You should have received a copy of the GNU Lesser General Public License
00020   along with this library/program; if not, write to the Free Software
00021   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 
00022 
00023   Turku PET Centre, Turku, Finland, http://www.turkupetcentre.fi/
00024 
00025   Modification history:
00026   2003-07-21 Vesa Oikonen
00027     First created.
00028   2004-06-20 VO
00029     ecat7PrintMatlist(): blkNr is printed correctly (+1).
00030   2004-06-27 VO
00031     Included ecat7DeleteLateFrames().
00032   2007-02-27 VO
00033     Added functions ecat7GetMatrixBlockSize() and ecat7GetPlaneAndFrameNr().
00034   2007-03-13 VO
00035     Added functions ecat7GetNums() and ecat7GatherMatlist().
00036   2007-17-07 Harri Merisaari
00037     fixed for ANSI
00038 
00039 ******************************************************************************/
00040 #include <stdio.h>
00041 #include <stdlib.h>
00042 #include <math.h>
00043 #include <ctype.h>
00044 #include <string.h>
00045 #include <unistd.h>
00046 #include <time.h>
00047 /*****************************************************************************/
00048 #include <swap.h>
00049 #include "include/img.h"
00050 #include "include/ecat7.h"
00051 /*****************************************************************************/
00052 
00053 /*****************************************************************************/
00059 void ecat7InitMatlist(ECAT7_MATRIXLIST *mlist) {
00060   mlist->matrixSpace=mlist->matrixNr=0; mlist->matdir=NULL;
00061 }
00062 /*****************************************************************************/
00063 
00064 /*****************************************************************************/
00070 void ecat7EmptyMatlist(ECAT7_MATRIXLIST *mlist) {
00071   if(mlist->matrixSpace>0) free((char*)(mlist->matdir));
00072   mlist->matrixSpace=mlist->matrixNr=0;
00073 }
00074 /*****************************************************************************/
00075 
00076 /*****************************************************************************/
00086 int ecat7ReadMatlist(FILE *fp, ECAT7_MATRIXLIST *ml) {
00087   int i, err=0, little;
00088   int blk=MatFirstDirBlk, next_blk=0, nr_free, prev_blk, nr_used;
00089   size_t sn;
00090   unsigned int dirbuf[MatBLKSIZE/4];
00091 
00092 
00093   if(ECAT7_TEST) printf("ecat7ReadMatlist(fp, mlist)\n");
00094   if(fp==NULL) return(1);
00095   little=little_endian();
00096   /* Make sure that matrix list is empty */
00097   ecat7EmptyMatlist(ml);
00098   /* Seek the first list block */
00099   fseek(fp, (blk-1)*MatBLKSIZE, SEEK_SET); if(ftell(fp)!=(blk-1)*MatBLKSIZE) return(2);
00100   do {
00101     /* Read the data block */
00102     if(ECAT7_TEST) printf("  reading dirblock %d\n", blk);
00103     sn=fread(dirbuf, sizeof(int), MatBLKSIZE/4, fp); if(sn<MatBLKSIZE/4) return(3);
00104     /* Allocate (more) memory for one block */
00105     if(ml->matrixSpace==0) {
00106       ml->matrixSpace=MatBLKSIZE/4;
00107       ml->matdir=(ECAT7_MatDir*)malloc(ml->matrixSpace*sizeof(ECAT7_MatDir));
00108     } else if(ml->matrixSpace<(ml->matrixNr+MatBLKSIZE/4)) {
00109       ml->matrixSpace+=MatBLKSIZE/4;
00110       ml->matdir=(ECAT7_MatDir*)realloc(ml->matdir, sizeof(ECAT7_MatDir)*ml->matrixSpace);
00111     }
00112     if(ml->matdir==NULL) return(4);
00113     /* Byte order conversion for ints in little endian platforms */
00114     if(little) swawbip(dirbuf, MatBLKSIZE);
00115     /* Read "header" integers */
00116     nr_free  = dirbuf[0];
00117     next_blk = dirbuf[1];
00118     prev_blk = dirbuf[2];
00119     nr_used  = dirbuf[3];
00120     if(ECAT7_TEST>1) printf("nr_free=%d next_blk=%d prev_blk=%d nr_used=%d\n", nr_free, next_blk, prev_blk, nr_used);
00121     for(i=4; i<MatBLKSIZE/4; i+=4) if(dirbuf[i]>0) {
00122       ml->matdir[ml->matrixNr].id=dirbuf[i];
00123       ml->matdir[ml->matrixNr].strtblk=dirbuf[i+1];
00124       ml->matdir[ml->matrixNr].endblk=dirbuf[i+2];
00125       ml->matdir[ml->matrixNr].status=dirbuf[i+3];
00126       if(ECAT7_TEST>3) {
00127         printf("matnum=%d strtblk=%d endblk=%d matstat=%d matrixNr=%d\n",
00128           ml->matdir[ml->matrixNr].id, ml->matdir[ml->matrixNr].strtblk,
00129           ml->matdir[ml->matrixNr].endblk, ml->matdir[ml->matrixNr].status,
00130           ml->matrixNr);
00131       }
00132       ml->matrixNr++;
00133     }
00134     blk=next_blk;
00135     /* Seek the next list block */
00136     fseek(fp, (blk-1)*MatBLKSIZE, SEEK_SET); if(ftell(fp)!=(blk-1)*MatBLKSIZE) err=1;
00137   } while(err==0 && feof(fp)==0 && blk!=MatFirstDirBlk);
00138   if(err) {ecat7EmptyMatlist(ml); return(5);}
00139   return(0);
00140 }
00141 /*****************************************************************************/
00142 
00143 /*****************************************************************************/
00149 void ecat7PrintMatlist(ECAT7_MATRIXLIST *ml) {
00150   int i;
00151   ECAT7_Matval matval;
00152 
00153   printf("     matrix   pl  fr gate bed startblk blknr  status\n");
00154   for(i=0; i<ml->matrixNr; i++) {
00155     ecat7_id_to_val(ml->matdir[i].id, &matval);
00156     printf("%4d %8d %3d %3d %3d %3d %8d %5d  ", i+1, ml->matdir[i].id,
00157       matval.plane, matval.frame, matval.gate, matval.bed,
00158       ml->matdir[i].strtblk, 1+ml->matdir[i].endblk-ml->matdir[i].strtblk);
00159     if(ml->matdir[i].status==1) printf("read/write\n");
00160     else if(ml->matdir[i].status==0) printf("not ready\n");
00161     else if(ml->matdir[i].status==-1) printf("deleted\n");
00162     else printf("%d\n", ml->matdir[i].status);
00163   }
00164   return;
00165 }
00166 /*****************************************************************************/
00167 
00168 /*****************************************************************************/
00184 int ecat7EnterMatrix(FILE *fp, int matrix_id, int block_nr) {
00185   unsigned int i=0, dirblk, little, busy=1, nxtblk=0, oldsize;
00186   /*unsigned*/ int dirbuf[MatBLKSIZE/4];
00187 
00188   if(ECAT7_TEST) printf("ecat7EnterMatrix(fp, %d, %d)\n", matrix_id, block_nr);
00189   /* Check the input */
00190   if(fp==NULL || matrix_id<1 || block_nr<1) return(-1);
00191   /* Is this a little endian machine? */
00192   little=little_endian();
00193   /* Read first directory record block */
00194   dirblk=MatFirstDirBlk;
00195   fseek(fp, (dirblk-1)*MatBLKSIZE, SEEK_SET);
00196   if(ftell(fp)!=(dirblk-1)*MatBLKSIZE) return(-2);
00197   if(fread(dirbuf, sizeof(int), MatBLKSIZE/4, fp) != MatBLKSIZE/4) return(-3);
00198   /* Byte order conversion for ints in little endian platforms */
00199   if(little) swawbip(dirbuf, MatBLKSIZE);
00200   /* Read through the existing directory records */
00201   while(busy) {
00202     /* Go through the directory entries in this record */
00203     for(i=4, nxtblk=dirblk+1; i<MatBLKSIZE/4; i+=4) {
00204       oldsize=dirbuf[i+2]-dirbuf[i+1]+1;
00205       if(dirbuf[i]==0) {  /* Check for end of matrix list */
00206         busy=0; break;
00207       } else if(dirbuf[i]==matrix_id) {  /* Maybe this matrix already exists? */
00208         /* yes it does; is old data smaller? */
00209         if(oldsize<block_nr) {
00210           /* it was smaller, so do not use it, but mark it deleted */
00211           dirbuf[i] = 0xFFFFFFFF; dirbuf[i+3]=-1;
00212           if(little) swawbip(dirbuf, MatBLKSIZE);
00213           fseek(fp, (dirblk-1)*MatBLKSIZE, SEEK_SET);
00214           if(ftell(fp)!=(dirblk-1)*MatBLKSIZE) return(-6);
00215           if(fwrite(dirbuf, sizeof(int), MatBLKSIZE/4, fp) != MatBLKSIZE/4) return(-7);
00216           if(little) swawbip(dirbuf, MatBLKSIZE);
00217           nxtblk=dirbuf[i+2]+1;
00218         } else { /* old matrix size is ok */
00219           nxtblk=dirbuf[i+1]; dirbuf[0]++; dirbuf[3]--; busy=0;
00220           break;
00221         }
00222       } else { /* this is not the same matrix */
00223         /* But is deleted and of same or smaller size? */
00224         if(dirbuf[i+3]==-1 && block_nr<=oldsize) {
00225           /* yes it was, so lets recycle it */
00226           dirbuf[i]=matrix_id;
00227           nxtblk=dirbuf[i+1]; dirbuf[0]++; dirbuf[3]--; busy=0;
00228           break;
00229         }
00230         /* nothing to be done with this entry */
00231         nxtblk=dirbuf[i+2]+1;
00232       }
00233     } /* next entry in this record */
00234     if(!busy) break; /* stop reading existing records */
00235     /* Read the next directory record */
00236     if(dirbuf[1]!=MatFirstDirBlk) {
00237       /* There are more records left to read */
00238       dirblk=dirbuf[1];
00239       fseek(fp, (dirblk-1)*MatBLKSIZE, SEEK_SET);
00240       if(ftell(fp)!=(dirblk-1)*MatBLKSIZE) return(-9);
00241       if(fread(dirbuf, sizeof(int), MatBLKSIZE/4, fp) != MatBLKSIZE/4) return(-10);
00242       if(little) swawbip(dirbuf, MatBLKSIZE);
00243     } else {
00244       /* No more records to read, so lets write a new empty one */
00245       dirbuf[1]=nxtblk; /* write a pointer to the new one */
00246       if(little) swawbip(dirbuf, MatBLKSIZE);
00247       fseek(fp, (dirblk-1)*MatBLKSIZE, SEEK_SET);
00248       if(ftell(fp)!=(dirblk-1)*MatBLKSIZE) return(-11);
00249       if(fwrite(dirbuf, sizeof(int), MatBLKSIZE/4, fp) != MatBLKSIZE/4) return(-12);
00250       /* and then initiate the contents of the next one, but do not write it */
00251       dirbuf[0]=31; dirbuf[1]=MatFirstDirBlk; dirbuf[2]=dirblk;
00252       dirbuf[3]=0; dirblk=nxtblk;
00253       for(i=4; i<MatBLKSIZE/4; i++) dirbuf[i]=0;
00254     }
00255   } /* next directory record */
00256   dirbuf[i]=matrix_id;
00257   dirbuf[i+1]=nxtblk;
00258   dirbuf[i+2]=nxtblk+block_nr;
00259   dirbuf[i+3]=1; /* mark the entry as read/write */
00260   dirbuf[0]--;
00261   dirbuf[3]++;
00262   if(little) swawbip(dirbuf, MatBLKSIZE);
00263   fseek(fp, (dirblk-1)*MatBLKSIZE, SEEK_SET);
00264   if(ftell(fp)!=(dirblk-1)*MatBLKSIZE) return(-15);
00265   if(fwrite(dirbuf, sizeof(int), MatBLKSIZE/4, fp) != MatBLKSIZE/4) return(-16);
00266   if(ECAT7_TEST) printf("returning %d from ecat7EnterMatrix()\n", nxtblk);
00267   return(nxtblk);
00268 }
00269 /*****************************************************************************/
00270 
00271 /*****************************************************************************/
00282 int ecat7_val_to_id(int frame, int plane, int gate, int data, int bed) {
00283   return(
00284     ((bed & 0xF) << 12) |    /* bed */
00285     (frame & 0x1FF) |        /* frame */
00286     ((gate & 0x3F) << 24) |  /* gate */
00287     ((plane & 0xFF) << 16) | /* plane low */
00288     ((plane & 0x300) << 1) | /* plane high */
00289     ((data & 0x3) << 30) |   /* data low */
00290     ((data & 0x4) << 9)      /* data high */
00291   );
00292 }
00299 void ecat7_id_to_val(int matrix_id, ECAT7_Matval *matval) {
00300   matval->frame = matrix_id & 0x1FF;
00301   matval->plane = ((matrix_id >> 16) & 0xFF) + ((matrix_id >> 1) & 0x300);
00302   matval->gate  = (matrix_id >> 24) & 0x3F;
00303   matval->data  = ((matrix_id >> 30) & 0x3) + ((matrix_id >> 9) & 0x4);
00304   matval->bed   = (matrix_id >> 12) & 0xF;
00305 }
00306 /*****************************************************************************/
00307 
00308 /*****************************************************************************/
00314 void ecat7SortMatlistByPlane(ECAT7_MATRIXLIST *ml) {
00315   int i, j;
00316   ECAT7_Matval mv1, mv2;
00317   ECAT7_MatDir tmpMatdir;
00318 
00319   for(i=0; i<ml->matrixNr-1; i++) {
00320     ecat7_id_to_val(ml->matdir[i].id, &mv1);
00321     for(j=i+1; j<ml->matrixNr; j++) {
00322       ecat7_id_to_val(ml->matdir[j].id, &mv2);
00323       if(mv2.plane<mv1.plane||(mv2.plane==mv1.plane&&mv2.frame<mv1.frame)) {
00324         tmpMatdir=ml->matdir[i];
00325         ml->matdir[i]=ml->matdir[j];
00326   ml->matdir[j]=tmpMatdir;
00327         ecat7_id_to_val(ml->matdir[i].id, &mv1);
00328       }
00329     }
00330   }
00331 }
00332 /*****************************************************************************/
00333 
00334 /*****************************************************************************/
00340 void ecat7SortMatlistByFrame(ECAT7_MATRIXLIST *ml) {
00341   int i, j;
00342   ECAT7_Matval mv1, mv2;
00343   ECAT7_MatDir tmpMatdir;
00344 
00345   for(i=0; i<ml->matrixNr-1; i++) {
00346     ecat7_id_to_val(ml->matdir[i].id, &mv1);
00347     for(j=i+1; j<ml->matrixNr; j++) {
00348       ecat7_id_to_val(ml->matdir[j].id, &mv2);
00349       if(mv2.frame<mv1.frame||(mv2.frame==mv1.frame&&mv2.plane<mv1.plane)) {
00350         tmpMatdir=ml->matdir[i];
00351         ml->matdir[i]=ml->matdir[j]; ml->matdir[j]=tmpMatdir;
00352         ecat7_id_to_val(ml->matdir[i].id, &mv1);
00353       }
00354     }
00355   }
00356 }
00357 /*****************************************************************************/
00358 
00359 /*****************************************************************************/
00366 int ecat7CheckMatlist(ECAT7_MATRIXLIST *ml) {
00367   int i;
00368 
00369   if(ml==NULL) return(1);
00370   for(i=0; i<ml->matrixNr; i++) if(ml->matdir[i].status!=1) return(1);
00371   return(0);
00372 }
00373 /*****************************************************************************/
00374 
00375 /*****************************************************************************/
00383 int ecat7DeleteLateFrames(ECAT7_MATRIXLIST *ml, int frame_nr) {
00384   int i, del_nr=0;
00385   ECAT7_Matval matval;
00386 
00387   for(i=0; i<ml->matrixNr; i++) {
00388     ecat7_id_to_val(ml->matdir[i].id, &matval);
00389     if(matval.frame>frame_nr) {del_nr++; ml->matdir[i].status=-1;}
00390   }
00391   return(del_nr);
00392 }
00393 /*****************************************************************************/
00394 
00395 /*****************************************************************************/
00409 int ecat7GetPlaneAndFrameNr(ECAT7_MATRIXLIST *mlist, ECAT7_mainheader *h, int *plane_nr, int *frame_nr) {
00410   ECAT7_Matval matval;
00411   int m, plane, frame, prev_plane, prev_frame, fnr, pnr;
00412 
00413   /* Check input */
00414   if(mlist==NULL) return STATUS_FAULT;
00415   if(plane_nr!=NULL) *plane_nr=0;
00416   if(frame_nr!=NULL) *frame_nr=0;
00417 
00418   /* Sort matrices by plane so that following computation works */
00419   ecat7SortMatlistByPlane(mlist);
00420 
00421   prev_plane=plane=-1; prev_frame=frame=-1;
00422   fnr=pnr=0;
00423   for(m=0; m<mlist->matrixNr; m++) {
00424     ecat7_id_to_val(mlist->matdir[m].id, &matval);
00425     plane=matval.plane;
00426     if(h->num_frames>=h->num_gates)
00427       frame=matval.frame;
00428     else
00429       frame=matval.gate;
00430     if(plane!=prev_plane) {
00431       fnr=1; pnr++;
00432     } else {
00433       fnr++;
00434       if(prev_frame>0 && frame!=prev_frame+1) return STATUS_MISSINGMATRIX;
00435     }
00436     prev_plane=plane; prev_frame=frame;
00437   } /* next matrix */
00438   if(fnr*pnr != mlist->matrixNr) return STATUS_MISSINGMATRIX;
00439   if(plane_nr!=NULL) *plane_nr=pnr;
00440   if(frame_nr!=NULL) *frame_nr=fnr;
00441   return STATUS_OK;
00442 }
00443 /*****************************************************************************/
00444 
00445 /*****************************************************************************/
00455 int ecat7GetMatrixBlockSize(ECAT7_MATRIXLIST *mlist, int *blk_nr) {
00456   int m, prev_blk, blk;
00457 
00458   /* Check input */
00459   if(mlist==NULL) return STATUS_FAULT;
00460   if(blk_nr!=NULL) *blk_nr=0;
00461 
00462   /* Calculate the size of first data matrix */
00463   m=0; prev_blk=blk=mlist->matdir[m].endblk - mlist->matdir[m].strtblk;
00464   for(m=1; m<mlist->matrixNr; m++) {
00465     blk=mlist->matdir[m].endblk - mlist->matdir[m].strtblk;
00466     if(blk!=prev_blk) return STATUS_VARMATSIZE;
00467     else prev_blk=blk;
00468   }
00469   if(blk_nr!=NULL) *blk_nr=blk;
00470   return STATUS_OK;
00471 }
00472 /*****************************************************************************/
00473 
00474 /*****************************************************************************/
00489 int ecat7GetNums(ECAT7_MATRIXLIST *ml, ECAT7_mainheader *mh, FILE *fp, short int *num_planes,
00490      short int *num_frames, short int *num_gates, short int *num_bed_pos) {
00491   int i, nmax, ret=0;
00492   ECAT7_imageheader ih;
00493   ECAT7_scanheader sh;
00494   ECAT7_Matval* matval;
00495 
00496   if(ml==NULL) return(1);
00497   if(ml->matrixNr<1) return(2);
00498 
00499   /* Allocate memory for matrix values */
00500   matval = (ECAT7_Matval*)calloc(ml->matrixNr,sizeof(ECAT7_Matval));
00501   if(matval == NULL) return(3);
00502 
00503   /* And get the matrix values */
00504   for(i=0; i<ml->matrixNr; i++) ecat7_id_to_val(ml->matdir[i].id, matval+i);
00505 
00506   /* Planes */
00507   if(num_planes!=NULL) {
00508     nmax=matval[0].plane;
00509     for(i=1; i<ml->matrixNr; i++) if(matval[i].plane>nmax) nmax=matval[i].plane;
00510     *num_planes=nmax;
00511   }
00512   /* Frames */
00513   if(num_frames!=NULL) {
00514     nmax=matval[0].frame;
00515     for(i=1; i<ml->matrixNr; i++) if(matval[i].frame>nmax) nmax=matval[i].frame;
00516     *num_frames=nmax;
00517   }
00518   /* Gates */
00519   if(num_gates!=NULL) {
00520     nmax=matval[0].gate;
00521     for(i=1; i<ml->matrixNr; i++) if(matval[i].gate>nmax) nmax=matval[i].gate;
00522     *num_gates=nmax;
00523   }
00524   /* Beds */
00525   if(num_bed_pos!=NULL) {
00526     nmax=matval[0].bed;
00527     for(i=1; i<ml->matrixNr; i++) if(matval[i].bed>nmax) nmax=matval[i].bed;
00528     *num_bed_pos=nmax;
00529   }
00530 
00531   /* Check the num_planes from the first subheader in 3D formats */
00532   if(num_planes!=NULL && *num_planes<=1) switch(mh->file_type) {
00533     case ECAT7_VOLUME8:
00534     case ECAT7_VOLUME16:
00535       ret=ecat7ReadImageheader(fp, ml->matdir[0].strtblk, &ih);
00536       if(ret!=0) {
00537         free(matval);
00538         return(5);
00539       }
00540       if(ih.num_dimensions>2 && ih.z_dimension>1) *num_planes=ih.z_dimension;
00541       break;
00542     case ECAT7_3DSCAN:
00543     case ECAT7_3DSCAN8:
00544     case ECAT7_3DSCANFIT:
00545       ret=ecat7ReadScanheader(fp, ml->matdir[0].strtblk, &sh);
00546       if(ret!=0) {
00547         free(matval);
00548         return(5);
00549       }
00550       for(i=0, *num_planes=0; i<64; i++) *num_planes+=sh.num_z_elements[i];
00551       break;
00552   }
00553   free(matval);
00554   return(0);
00555 }
00556 /*****************************************************************************/
00557 
00558 /*****************************************************************************/
00572 int ecat7GatherMatlist(ECAT7_MATRIXLIST *ml, short int do_planes, short int do_frames,
00573            short int do_gates, short int do_beds) {
00574   int i, ncurr, n;
00575   ECAT7_Matval* matval;
00576 
00577   if(ml==NULL) return(1);
00578   if(ml->matrixNr<1) return(0);
00579 
00580   /* Allocate memory for matrix values */
00581   matval = (ECAT7_Matval*)calloc(ml->matrixNr,sizeof(ECAT7_Matval));
00582   if(matval == NULL) return(3);
00583 
00584   /* And get the matrix values */
00585   for(i=0; i<ml->matrixNr; i++) ecat7_id_to_val(ml->matdir[i].id, matval+i);
00586 
00587   /* Planes */
00588   if(do_planes!=0) {
00589     ncurr=1;
00590     while(ncurr <= ml->matrixNr) {
00591       /* Find any matrix with this number? */
00592       for(i=0, n=0; i<ml->matrixNr; i++) if(matval[i].plane==ncurr) {n=1; break;}
00593       /* If yes, then go on to the next matrix number */
00594       if(n==1) {ncurr++; continue;}
00595       /* If not, then subtract 1 from all matrix numbers that are larger */
00596       for(i=0, n=0; i<ml->matrixNr; i++)
00597         if(matval[i].plane>ncurr) {
00598           /*printf("    plane %d -> plane %d\n", matval[i].plane, matval[i].plane-1);*/
00599           matval[i].plane--; n++;
00600         }
00601       /* If no larger values were found any more, then quit */
00602       if(n<1) break;
00603     }
00604   }
00605 
00606   /* Frames */
00607   if(do_frames!=0) {
00608     ncurr=1;
00609     while(ncurr <= ml->matrixNr) {
00610       /* Find any matrix with this number? */
00611       for(i=0, n=0; i<ml->matrixNr; i++) if(matval[i].frame==ncurr) {n=1; break;}
00612       /* If yes, then go on to the next matrix number */
00613       if(n==1) {ncurr++; continue;}
00614       /* If not, then subtract 1 from all matrix numbers that are larger */
00615       for(i=0, n=0; i<ml->matrixNr; i++)
00616         if(matval[i].frame>ncurr) {matval[i].frame--; n++;}
00617       /* If no larger values were found any more, then quit */
00618       if(n<1) break;
00619     }
00620   }
00621 
00622   /* Gates */
00623   if(do_gates!=0) {
00624     ncurr=1;
00625     while(ncurr <= ml->matrixNr) {
00626       /* Find any matrix with this number? */
00627       for(i=0, n=0; i<ml->matrixNr; i++) if(matval[i].gate==ncurr) {n=1; break;}
00628       /* If yes, then go on to the next matrix number */
00629       if(n==1) {ncurr++; continue;}
00630       /* If not, then subtract 1 from all matrix numbers that are larger */
00631       for(i=0, n=0; i<ml->matrixNr; i++)
00632         if(matval[i].gate>ncurr) {matval[i].gate--; n++;}
00633       /* If no larger values were found any more, then quit */
00634       if(n<1) break;
00635     }
00636   }
00637 
00638   /* Beds */
00639   if(do_beds!=0) {
00640     ncurr=1;
00641     while(ncurr <= ml->matrixNr) {
00642       /* Find any matrix with this number? */
00643       for(i=0, n=0; i<ml->matrixNr; i++) if(matval[i].bed==ncurr) {n=1; break;}
00644       /* If yes, then go on to the next matrix number */
00645       if(n==1) {ncurr++; continue;}
00646       /* If not, then subtract 1 from all matrix numbers that are larger */
00647       for(i=0, n=0; i<ml->matrixNr; i++)
00648         if(matval[i].bed>ncurr) {matval[i].bed--; n++;}
00649       /* If no larger values were found any more, then quit */
00650       if(n<1) break;
00651     }
00652   }
00653 
00654   /* Write matrix values (possibly changed) into matrix list */
00655   for(i=0; i<ml->matrixNr; i++) ml->matdir[i].id=ecat7_val_to_id(
00656             matval[i].frame, matval[i].plane,
00657       matval[i].gate, matval[i].data,
00658       matval[i].bed);
00659   free(matval);
00660   return(0);
00661 }
00662 /*****************************************************************************/
00663 
00664 /*****************************************************************************/
00665