1 /******************************************************************************
2
3 Copyright (c) 2003-2007 Turku PET Centre
4
5 Library: ecat7ml.c
6 Description: Reading and writing ECAT 7.x matrix list.
7
8 This library is free software; you can redistribute it and/or
9 modify it under the terms of the GNU Lesser General Public
10 License as published by the Free Software Foundation; either
11 version 2.1 of the License, or (at your option) any later version.
12
13 This library is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
16 See the GNU Lesser General Public License for more details:
17 http://www.gnu.org/copyleft/lesser.html
18
19 You should have received a copy of the GNU Lesser General Public License
20 along with this library/program; if not, write to the Free Software
21 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22
23 Turku PET Centre, Turku, Finland, http://www.turkupetcentre.fi/
24
25 Modification history:
26 2003-07-21 Vesa Oikonen
27 First created.
28 2004-06-20 VO
29 ecat7PrintMatlist(): blkNr is printed correctly (+1).
30 2004-06-27 VO
31 Included ecat7DeleteLateFrames().
32 2007-02-27 VO
33 Added functions ecat7GetMatrixBlockSize() and ecat7GetPlaneAndFrameNr().
34 2007-03-13 VO
35 Added functions ecat7GetNums() and ecat7GatherMatlist().
36 2007-17-07 Harri Merisaari
37 fixed for ANSI
38
39 ******************************************************************************/
40 #include <stdio.h>
41 #include <stdlib.h>
42 #include <math.h>
43 #include <ctype.h>
44 #include <string.h>
45 #include <unistd.h>
46 #include <time.h>
47 /*****************************************************************************/
48 #include "swap.h"
49 #include "ecat7.h"
50 /*****************************************************************************/
51
52 /*****************************************************************************/
53 /*!
54 * Prepare matrix list for additional matrix data and return block number
55 * for matrix header. Directory records are written in big endian byte order.
56 * Set block_nr to the number of data blocks + (nr of header blocks - 1)
57 *
58 * @param fp file pointer
59 * @param matrix_id matrix identifier coding
60 * @param block_nr matrix number [1..number of matrixes]
61 * @return returns the block number for matrix header, -1 if invalid input,
62 * -2 if first directory block is not found, -3 if failed to read first block,
63 * -9 if other directory block is not found, -10 if failed to read other block,
64 * -11 if place for new directory block is not found, -12 if failed clear new
65 * block, -15 if place for new directory block is not found, -16 if failed to
66 * write into new block
67 */
ecat7EnterMatrix(FILE * fp,int matrix_id,int block_nr)68 int ecat7EnterMatrix(FILE *fp, int matrix_id, int block_nr) {
69 unsigned int i=0, dirblk, little, busy=1, nxtblk=0, oldsize;
70 /*unsigned*/ int dirbuf[MatBLKSIZE/4];
71
72 if(ECAT7_TEST) printf("ecat7EnterMatrix(fp, %d, %d)\n", matrix_id, block_nr);
73 /* Check the input */
74 if(fp==NULL || matrix_id<1 || block_nr<1) return(-1);
75 /* Is this a little endian machine? */
76 little=little_endian();
77 /* Read first directory record block */
78 dirblk=MatFirstDirBlk;
79 fseek(fp, (dirblk-1)*MatBLKSIZE, SEEK_SET);
80 if(ftell(fp)!=(dirblk-1)*MatBLKSIZE) return(-2);
81 if(fread(dirbuf, sizeof(int), MatBLKSIZE/4, fp) != MatBLKSIZE/4) return(-3);
82 /* Byte order conversion for ints in little endian platforms */
83 if(little) swawbip(dirbuf, MatBLKSIZE);
84 /* Read through the existing directory records */
85 while(busy) {
86 /* Go through the directory entries in this record */
87 for(i=4, nxtblk=dirblk+1; i<MatBLKSIZE/4; i+=4) {
88 oldsize=dirbuf[i+2]-dirbuf[i+1]+1;
89 if(dirbuf[i]==0) { /* Check for end of matrix list */
90 busy=0; break;
91 } else if(dirbuf[i]==matrix_id) { /* Maybe this matrix already exists? */
92 /* yes it does; is old data smaller? */
93 if(oldsize<block_nr) {
94 /* it was smaller, so do not use it, but mark it deleted */
95 dirbuf[i] = 0xFFFFFFFF; dirbuf[i+3]=-1;
96 if(little) swawbip(dirbuf, MatBLKSIZE);
97 fseek(fp, (dirblk-1)*MatBLKSIZE, SEEK_SET);
98 if(ftell(fp)!=(dirblk-1)*MatBLKSIZE) return(-6);
99 if(fwrite(dirbuf, sizeof(int), MatBLKSIZE/4, fp) != MatBLKSIZE/4) return(-7);
100 if(little) swawbip(dirbuf, MatBLKSIZE);
101 nxtblk=dirbuf[i+2]+1;
102 } else { /* old matrix size is ok */
103 nxtblk=dirbuf[i+1]; dirbuf[0]++; dirbuf[3]--; busy=0;
104 break;
105 }
106 } else { /* this is not the same matrix */
107 /* But is deleted and of same or smaller size? */
108 if(dirbuf[i+3]==-1 && block_nr<=oldsize) {
109 /* yes it was, so lets recycle it */
110 dirbuf[i]=matrix_id;
111 nxtblk=dirbuf[i+1]; dirbuf[0]++; dirbuf[3]--; busy=0;
112 break;
113 }
114 /* nothing to be done with this entry */
115 nxtblk=dirbuf[i+2]+1;
116 }
117 } /* next entry in this record */
118 if(!busy) break; /* stop reading existing records */
119 /* Read the next directory record */
120 if(dirbuf[1]!=MatFirstDirBlk) {
121 /* There are more records left to read */
122 dirblk=dirbuf[1];
123 fseek(fp, (dirblk-1)*MatBLKSIZE, SEEK_SET);
124 if(ftell(fp)!=(dirblk-1)*MatBLKSIZE) return(-9);
125 if(fread(dirbuf, sizeof(int), MatBLKSIZE/4, fp) != MatBLKSIZE/4) return(-10);
126 if(little) swawbip(dirbuf, MatBLKSIZE);
127 } else {
128 /* No more records to read, so lets write a new empty one */
129 dirbuf[1]=nxtblk; /* write a pointer to the new one */
130 if(little) swawbip(dirbuf, MatBLKSIZE);
131 fseek(fp, (dirblk-1)*MatBLKSIZE, SEEK_SET);
132 if(ftell(fp)!=(dirblk-1)*MatBLKSIZE) return(-11);
133 if(fwrite(dirbuf, sizeof(int), MatBLKSIZE/4, fp) != MatBLKSIZE/4) return(-12);
134 /* and then initiate the contents of the next one, but do not write it */
135 dirbuf[0]=31; dirbuf[1]=MatFirstDirBlk; dirbuf[2]=dirblk;
136 dirbuf[3]=0; dirblk=nxtblk;
137 for(i=4; i<MatBLKSIZE/4; i++) dirbuf[i]=0;
138 }
139 } /* next directory record */
140 dirbuf[i]=matrix_id;
141 dirbuf[i+1]=nxtblk;
142 dirbuf[i+2]=nxtblk+block_nr;
143 dirbuf[i+3]=1; /* mark the entry as read/write */
144 dirbuf[0]--;
145 dirbuf[3]++;
146 if(little) swawbip(dirbuf, MatBLKSIZE);
147 fseek(fp, (dirblk-1)*MatBLKSIZE, SEEK_SET);
148 if(ftell(fp)!=(dirblk-1)*MatBLKSIZE) return(-15);
149 if(fwrite(dirbuf, sizeof(int), MatBLKSIZE/4, fp) != MatBLKSIZE/4) return(-16);
150 if(ECAT7_TEST) printf("returning %d from ecat7EnterMatrix()\n", nxtblk);
151 return(nxtblk);
152 }
153