My Project
ecat63ml.c
Go to the documentation of this file.
1/******************************************************************************
2
3 Copyright (c) 2003-2007 Turku PET Centre
4
5 Library: ecat63ml.c
6 Description: Reading and writing ECAT 6.3 matrix list.
7 Assumptions:
8 1. Assumes that matrix list data is in VAX little endian format
9 2. Data is automatically converted to big endian when read, if necessary
10 according to the current platform.
11
12 This library is free software; you can redistribute it and/or
13 modify it under the terms of the GNU Lesser General Public
14 License as published by the Free Software Foundation; either
15 version 2.1 of the License, or (at your option) any later version.
16
17 This library is distributed in the hope that it will be useful,
18 but WITHOUT ANY WARRANTY; without even the implied warranty of
19 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
20 See the GNU Lesser General Public License for more details:
21 http://www.gnu.org/copyleft/lesser.html
22
23 You should have received a copy of the GNU Lesser General Public License
24 along with this library/program; if not, write to the Free Software
25 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
26
27 Turku PET Centre, Turku, Finland, http://www.turkupetcentre.fi/
28
29 Modification history:
30 2003-07-21 Vesa Oikonen
31 Created from ecat63.c.
32 2003-08-05 VO
33 Included functions ecat63SortMatlistByPlane(), ecat63SortMatlistByFrame()
34 and ecat63CheckMatlist().
35 2004-06-20 VO
36 ecat63PrintMatlist(): blkNr is printed correctly (+1).
37 2004-06-27 VO
38 Included ecat63DeleteLateFrames().
39 2004-09-20 VO
40 Doxygen style comments.
41 2007-02-27 VO
42 Added functions ecat63GetMatrixBlockSize() and ecat63GetPlaneAndFrameNr().
43 2007-03-13 VO
44 Corrected comments.
45 Added functions ecat63GetNums() and ecat63GatherMatlist().
46 2007-17-07 Harri Merisaari
47 Fixed for ANSI
48
49******************************************************************************/
50#include <stdio.h>
51#include <stdlib.h>
52#include <math.h>
53#include <ctype.h>
54#include <string.h>
55#include <unistd.h>
56#include <time.h>
57/*****************************************************************************/
58#include <swap.h>
59#include "include/img.h"
60#include "include/ecat63.h"
61/*****************************************************************************/
62
63/*****************************************************************************/
70 mlist->matrixSpace=mlist->matrixNr=0; mlist->matdir=NULL;
71}
72/*****************************************************************************/
73
74/*****************************************************************************/
81 if(mlist->matrixSpace>0) free((char*)(mlist->matdir));
82 mlist->matrixSpace=mlist->matrixNr=0;
83}
84/*****************************************************************************/
85
86/*****************************************************************************/
97int ecat63ReadMatlist(FILE *fp, MATRIXLIST *ml) {
98 int i, err=0, little;
99 int blk=MatFirstDirBlk, next_blk=0, nr_free, prev_blk, nr_used;
100 size_t sn;
101 unsigned int dirbuf[MatBLKSIZE/4];
102
103
104 if(ECAT63_TEST) printf("ecat63ReadMatlist(fp, mlist)\n");
105 if(fp==NULL) return(1);
106 little=little_endian();
107 /* Make sure that matrix list is empty */
109 /* Seek the first list block */
110 fseek(fp, (blk-1)*MatBLKSIZE, SEEK_SET); if(ftell(fp)!=(blk-1)*MatBLKSIZE) return(2);
111 do {
112 /* Read the data block */
113 if(ECAT63_TEST) printf(" reading dirblock %d\n", blk);
114 sn=fread(dirbuf, sizeof(int), MatBLKSIZE/4, fp); if(sn<MatBLKSIZE/4) return(3);
115 /* Allocate (more) memory for one block */
116 if(ml->matrixSpace==0) {
118 ml->matdir=(MatDir*)malloc(ml->matrixSpace*sizeof(MatDir));
119 } else if(ml->matrixSpace<(ml->matrixNr+MatBLKSIZE/4)) {
120 ml->matrixSpace+=MatBLKSIZE/4;
121 ml->matdir=(MatDir*)realloc(ml->matdir, sizeof(MatDir)*ml->matrixSpace);
122 }
123 if(ml->matdir==NULL) return(4);
124 /* Byte order conversion for ints in big endian platforms */
125 if(!little) swawbip(dirbuf, MatBLKSIZE);
126 /* Read "header" integers */
127 nr_free = dirbuf[0];
128 next_blk = dirbuf[1];
129 prev_blk = dirbuf[2];
130 nr_used = dirbuf[3];
131 /*printf("nr_free=%d next_blk=%d prev_blk=%d nr_used=%d\n", nr_free, next_blk, prev_blk, nr_used);*/
132 for(i=4; i<MatBLKSIZE/4; i+=4) if(dirbuf[i]>0) {
133 ml->matdir[ml->matrixNr].matnum=dirbuf[i];
134 ml->matdir[ml->matrixNr].strtblk=dirbuf[i+1];
135 ml->matdir[ml->matrixNr].endblk=dirbuf[i+2];
136 ml->matdir[ml->matrixNr].matstat=dirbuf[i+3];
137 /*
138 printf("matnum=%d strtblk=%d endblk=%d matstat=%d matrixNr=%d\n",
139 ml->matdir[ml->matrixNr].matnum, ml->matdir[ml->matrixNr].strtblk,
140 ml->matdir[ml->matrixNr].endblk, ml->matdir[ml->matrixNr].matstat,
141 ml->matrixNr);
142 */
143 ml->matrixNr++;
144 }
145 blk=next_blk;
146 /* Seek the next list block */
147 fseek(fp, (blk-1)*MatBLKSIZE, SEEK_SET); if(ftell(fp)!=(blk-1)*MatBLKSIZE) err=1;
148 } while(err==0 && feof(fp)==0 && blk!=MatFirstDirBlk);
149 if(err) {ecat63EmptyMatlist(ml); return(5);}
150 return(0);
151}
152/*****************************************************************************/
153
154/*****************************************************************************/
161 int i;
162 Matval matval;
163
164 printf(" matrix pl fr gate bed startblk blknr\n");
165 for(i=0; i<ml->matrixNr; i++) {
166 mat_numdoc(ml->matdir[i].matnum, &matval);
167 printf("%4d %8d %3d %3d %3d %3d %8d %3d\n", i+1, ml->matdir[i].matnum,
168 matval.plane, matval.frame, matval.gate, matval.bed,
169 ml->matdir[i].strtblk, 1+ml->matdir[i].endblk-ml->matdir[i].strtblk);
170 }
171 return;
172}
173/*****************************************************************************/
174
175/*****************************************************************************/
186int ecat63Matenter(FILE *fp, int matnum, int blkNr) {
187 unsigned int i=0, dirblk, little, busy=1, nxtblk=0, oldsize;
188 unsigned int dirbuf[MatBLKSIZE/4];
189
190 if(ECAT63_TEST) printf("ecat63Matenter(fp, %d, %d)\n", matnum, blkNr);
191 if(fp==NULL || matnum<1 || blkNr<1) return(0);
192 little=little_endian(); memset(dirbuf, 0, MatBLKSIZE);
193 /* Read first matrix list block */
194 dirblk=MatFirstDirBlk;
195 fseek(fp, (dirblk-1)*MatBLKSIZE, SEEK_SET);
196 if(ftell(fp)!=(dirblk-1)*MatBLKSIZE) return(0);
197 if(fread(dirbuf, sizeof(int), MatBLKSIZE/4, fp) != MatBLKSIZE/4) return(0);
198 /* Byte order conversion for ints in big endian platforms */
199 if(!little) swawbip(dirbuf, MatBLKSIZE);
200
201 while(busy) {
202 nxtblk=dirblk+1;
203 for(i=4; i<MatBLKSIZE/4; i+=4) {
204 if(dirbuf[i]==0) { /* Check for end of matrix list */
205 busy=0; break;
206 } else if(dirbuf[i]==matnum) { /* Check if this matrix already exists */
207 oldsize=dirbuf[i+2]-dirbuf[i+1]+1;
208 if(oldsize<blkNr) { /* If old matrix is smaller */
209 dirbuf[i] = 0xFFFFFFFF;
210 if(!little) swawbip(dirbuf, MatBLKSIZE);
211 fseek(fp, (dirblk-1)*MatBLKSIZE, SEEK_SET);
212 if(ftell(fp)!=(dirblk-1)*MatBLKSIZE) return(0);
213 if(fwrite(dirbuf, sizeof(int), MatBLKSIZE/4, fp) != MatBLKSIZE/4) return(0);
214 if(!little) swawbip(dirbuf, MatBLKSIZE);
215 nxtblk=dirbuf[i+2]+1;
216 } else { /* old matrix size is ok */
217 nxtblk=dirbuf[i+1]; dirbuf[0]++; dirbuf[3]--; busy=0;
218 break;
219 }
220 } else /* not this one */
221 nxtblk=dirbuf[i+2]+1;
222 }
223 if(!busy) break;
224 if(dirbuf[1]!=MatFirstDirBlk) {
225 dirblk=dirbuf[1];
226 fseek(fp, (dirblk-1)*MatBLKSIZE, SEEK_SET);
227 if(ftell(fp)!=(dirblk-1)*MatBLKSIZE) return(0);
228 if(fread(dirbuf, sizeof(int), MatBLKSIZE/4, fp) != MatBLKSIZE/4) return(0);
229 if(!little) swawbip(dirbuf, MatBLKSIZE);
230 } else {
231 dirbuf[1]=nxtblk;
232 if(!little) swawbip(dirbuf, MatBLKSIZE);
233 fseek(fp, (dirblk-1)*MatBLKSIZE, SEEK_SET);
234 if(ftell(fp)!=(dirblk-1)*MatBLKSIZE) return(0);
235 if(fwrite(dirbuf, sizeof(int), MatBLKSIZE/4, fp) != MatBLKSIZE/4) return(0);
236 dirbuf[0]=31; dirbuf[1]=MatFirstDirBlk; dirbuf[2]=dirblk;
237 dirbuf[3]=0; dirblk=nxtblk;
238 for(i=4; i<MatBLKSIZE/4; i++) dirbuf[i]=0;
239 }
240 }
241 dirbuf[i]=matnum;
242 dirbuf[i+1]=nxtblk;
243 dirbuf[i+2]=nxtblk+blkNr;
244 dirbuf[i+3]=1;
245 dirbuf[0]--;
246 dirbuf[3]++;
247 if(!little) swawbip(dirbuf, MatBLKSIZE);
248 fseek(fp, (dirblk-1)*MatBLKSIZE, SEEK_SET); if(ftell(fp)!=(dirblk-1)*MatBLKSIZE) return(0);
249 if(fwrite(dirbuf, sizeof(int), MatBLKSIZE/4, fp) != MatBLKSIZE/4) return(0);
250 if(ECAT63_TEST) printf("returning %d from ecat63Matenter()\n", nxtblk);
251 return(nxtblk);
252}
253/*****************************************************************************/
254
255/*****************************************************************************/
266int mat_numcod(int frame, int plane, int gate, int data, int bed) {
267 return((frame&0xFFF)|((bed&0xF)<<12)|((plane&0xFF)<<16)|
268 ((gate&0x3F)<<24)|((data&0x3)<<30));
269}
276void mat_numdoc(int matnum, Matval *matval) {
277 matval->frame = matnum&0xFFF;
278 matval->plane = (matnum>>16)&0xFF;
279 matval->gate = (matnum>>24)&0x3F;
280 matval->data = (matnum>>30)&0x3;
281 matval->bed = (matnum>>12)&0xF;
282}
283/*****************************************************************************/
284
285/*****************************************************************************/
292 int i, j;
293 Matval mv1, mv2;
294 MatDir tmpMatdir;
295
296 for(i=0; i<ml->matrixNr-1; i++) {
297 mat_numdoc(ml->matdir[i].matnum, &mv1);
298 for(j=i+1; j<ml->matrixNr; j++) {
299 mat_numdoc(ml->matdir[j].matnum, &mv2);
300 if(mv2.plane<mv1.plane||(mv2.plane==mv1.plane&&mv2.frame<mv1.frame)) {
301 tmpMatdir=ml->matdir[i];
302 ml->matdir[i]=ml->matdir[j]; ml->matdir[j]=tmpMatdir;
303 mat_numdoc(ml->matdir[i].matnum, &mv1);
304 }
305 }
306 }
307}
308/*****************************************************************************/
309
310/*****************************************************************************/
317 int i, j;
318 Matval mv1, mv2;
319 MatDir tmpMatdir;
320
321 for(i=0; i<ml->matrixNr-1; i++) {
322 mat_numdoc(ml->matdir[i].matnum, &mv1);
323 for(j=i+1; j<ml->matrixNr; j++) {
324 mat_numdoc(ml->matdir[j].matnum, &mv2);
325 if(mv2.frame<mv1.frame||(mv2.frame==mv1.frame&&mv2.plane<mv1.plane)) {
326 tmpMatdir=ml->matdir[i];
327 ml->matdir[i]=ml->matdir[j]; ml->matdir[j]=tmpMatdir;
328 mat_numdoc(ml->matdir[i].matnum, &mv1);
329 }
330 }
331 }
332}
333/*****************************************************************************/
334
335/*****************************************************************************/
343 int i;
344
345 if(ml==NULL) return(1);
346 for(i=0; i<ml->matrixNr; i++) if(ml->matdir[i].matstat!=1) return(1);
347 return(0);
348}
349/*****************************************************************************/
350
351/*****************************************************************************/
360int ecat63DeleteLateFrames(MATRIXLIST *ml, int frame_nr) {
361 int i, del_nr=0;
362 Matval matval;
363
364 for(i=0; i<ml->matrixNr; i++) {
365 mat_numdoc(ml->matdir[i].matnum, &matval);
366 if(matval.frame>frame_nr) {del_nr++; ml->matdir[i].matstat=-1;}
367 }
368 return(del_nr);
369}
370/*****************************************************************************/
371
372/*****************************************************************************/
382int ecat63GetMatrixBlockSize(MATRIXLIST *mlist, int *blk_nr) {
383 int m, prev_blk, blk;
384
385 /* Check input */
386 if(mlist==NULL) return STATUS_FAULT;
387 if(blk_nr!=NULL) *blk_nr=0;
388
389 /* Calculate the size of first data matrix */
390 m=0; prev_blk=blk=mlist->matdir[m].endblk - mlist->matdir[m].strtblk;
391 for(m=1; m<mlist->matrixNr; m++) {
392 blk=mlist->matdir[m].endblk - mlist->matdir[m].strtblk;
393 if(blk!=prev_blk) return STATUS_VARMATSIZE;
394 else prev_blk=blk;
395 }
396 if(blk_nr!=NULL) *blk_nr=blk;
397 return STATUS_OK;
398}
399/*****************************************************************************/
400
401/*****************************************************************************/
414int ecat63GetPlaneAndFrameNr(MATRIXLIST *mlist, ECAT63_mainheader *h, int *plane_nr, int *frame_nr) {
415 Matval matval;
416 int m, plane, frame, prev_plane, prev_frame, fnr, pnr;
417
418 /* Check input */
419 if(mlist==NULL) return STATUS_FAULT;
420 if(plane_nr!=NULL) *plane_nr=0;
421 if(frame_nr!=NULL) *frame_nr=0;
422
423 /* Sort matrices by plane so that following computation works */
425
426 prev_plane=plane=-1; prev_frame=frame=-1;
427 fnr=pnr=0;
428 for(m=0; m<mlist->matrixNr; m++) if(mlist->matdir[m].matstat==1) {
429 mat_numdoc(mlist->matdir[m].matnum, &matval);
430 plane=matval.plane;
431 if(h->num_frames>=h->num_gates)
432 frame=matval.frame;
433 else
434 frame=matval.gate;
435 if(plane!=prev_plane) {
436 fnr=1; pnr++;
437 } else {
438 fnr++;
439 if(prev_frame>0 && frame!=prev_frame+1) return STATUS_MISSINGMATRIX;
440 }
441 prev_plane=plane; prev_frame=frame;
442 } /* next matrix */
443 if(fnr*pnr != mlist->matrixNr) return STATUS_MISSINGMATRIX;
444 if(plane_nr!=NULL) *plane_nr=pnr;
445 if(frame_nr!=NULL) *frame_nr=fnr;
446 return STATUS_OK;
447}
448/*****************************************************************************/
449
450/*****************************************************************************/
462int ecat63GetNums(MATRIXLIST *ml, short int *num_planes, short int *num_frames, short int *num_gates, short int *num_bed_pos) {
463 int i, nmax;
464 Matval* matval;
465
466 if(ml==NULL) return(1);
467 if(ml->matrixNr<1) return(2);
468
469 /* Allocate memory for matrix values */
470 matval = (Matval*)calloc(ml->matrixNr,sizeof(Matval));
471 if(matval == NULL) return(3);
472
473 /* And get the matrix values */
474 for(i=0; i<ml->matrixNr; i++) mat_numdoc(ml->matdir[i].matnum, matval+i);
475
476 /* Planes */
477 if(num_planes!=NULL) {
478 nmax=matval[0].plane;
479 for(i=1; i<ml->matrixNr; i++) if(matval[i].plane>nmax) nmax=matval[i].plane;
480 *num_planes=nmax;
481 }
482 /* Frames */
483 if(num_frames!=NULL) {
484 nmax=matval[0].frame;
485 for(i=1; i<ml->matrixNr; i++) if(matval[i].frame>nmax) nmax=matval[i].frame;
486 *num_frames=nmax;
487 }
488 /* Gates */
489 if(num_gates!=NULL) {
490 nmax=matval[0].gate;
491 for(i=1; i<ml->matrixNr; i++) if(matval[i].gate>nmax) nmax=matval[i].gate;
492 *num_gates=nmax;
493 }
494 /* Beds */
495 if(num_bed_pos!=NULL) {
496 nmax=matval[0].bed;
497 for(i=1; i<ml->matrixNr; i++) if(matval[i].bed>nmax) nmax=matval[i].bed;
498 *num_bed_pos=nmax;
499 }
500 free(matval);
501 return(0);
502}
503/*****************************************************************************/
504
505/*****************************************************************************/
519int ecat63GatherMatlist(MATRIXLIST *ml, short int do_planes, short int do_frames, short int do_gates, short int do_beds) {
520 int i, ncurr, n;
521 Matval* matval;
522
523 if(ml==NULL) return(1);
524 if(ml->matrixNr<1) return(0);
525
526 /* Allocate memory for matrix values */
527 matval = (Matval*)calloc(ml->matrixNr,sizeof(Matval));
528 if(matval == NULL) return(3);
529
530 /* And get the matrix values */
531 for(i=0; i<ml->matrixNr; i++) mat_numdoc(ml->matdir[i].matnum, matval+i);
532
533 /* Planes */
534 if(do_planes!=0) {
535 ncurr=1;
536 while(ncurr <= ml->matrixNr) {
537 /* Find any matrix with this number? */
538 for(i=0, n=0; i<ml->matrixNr; i++) if(matval[i].plane==ncurr) {n=1; break;}
539 /* If yes, then go on to the next matrix number */
540 if(n==1) {ncurr++; continue;}
541 /* If not, then subtract 1 from all matrix numbers that are larger */
542 for(i=0, n=0; i<ml->matrixNr; i++)
543 if(matval[i].plane>ncurr) {
544 matval[i].plane--; n++;
545 }
546 /* If no larger values were found any more, then quit */
547 if(n<1) break;
548 }
549 }
550
551 /* Frames */
552 if(do_frames!=0) {
553 ncurr=1;
554 while(ncurr <= ml->matrixNr) {
555 /* Find any matrix with this number? */
556 for(i=0, n=0; i<ml->matrixNr; i++) if(matval[i].frame==ncurr) {n=1; break;}
557 /* If yes, then go on to the next matrix number */
558 if(n==1) {ncurr++; continue;}
559 /* If not, then subtract 1 from all matrix numbers that are larger */
560 for(i=0, n=0; i<ml->matrixNr; i++)
561 if(matval[i].frame>ncurr) {matval[i].frame--; n++;}
562 /* If no larger values were found any more, then quit */
563 if(n<1) break;
564 }
565 }
566
567 /* Gates */
568 if(do_gates!=0) {
569 ncurr=1;
570 while(ncurr <= ml->matrixNr) {
571 /* Find any matrix with this number? */
572 for(i=0, n=0; i<ml->matrixNr; i++) if(matval[i].gate==ncurr) {n=1; break;}
573 /* If yes, then go on to the next matrix number */
574 if(n==1) {ncurr++; continue;}
575 /* If not, then subtract 1 from all matrix numbers that are larger */
576 for(i=0, n=0; i<ml->matrixNr; i++)
577 if(matval[i].gate>ncurr) {matval[i].gate--; n++;}
578 /* If no larger values were found any more, then quit */
579 if(n<1) break;
580 }
581 }
582
583 /* Beds */
584 if(do_beds!=0) {
585 ncurr=1;
586 while(ncurr <= ml->matrixNr) {
587 /* Find any matrix with this number? */
588 for(i=0, n=0; i<ml->matrixNr; i++) if(matval[i].bed==ncurr) {n=1; break;}
589 /* If yes, then go on to the next matrix number */
590 if(n==1) {ncurr++; continue;}
591 /* If not, then subtract 1 from all matrix numbers that are larger */
592 for(i=0, n=0; i<ml->matrixNr; i++)
593 if(matval[i].bed>ncurr) {matval[i].bed--; n++;}
594 /* If no larger values were found any more, then quit */
595 if(n<1) break;
596 }
597 }
598
599 /* Write matrix values (possibly changed) into matrix list */
600 for(i=0; i<ml->matrixNr; i++) ml->matdir[i].matnum=mat_numcod(
601 matval[i].frame, matval[i].plane,
602 matval[i].gate, matval[i].data,
603 matval[i].bed);
604 free(matval);
605 return(0);
606}
607/*****************************************************************************/
608
609/*****************************************************************************/
610
#define MatFirstDirBlk
Definition: ecat63.h:28
int ECAT63_TEST
Definition: ecat63.h:52
#define MatBLKSIZE
Definition: ecat63.h:27
int ecat63Matenter(FILE *fp, int matnum, int blkNr)
Definition: ecat63ml.c:186
int ecat63GetPlaneAndFrameNr(MATRIXLIST *mlist, ECAT63_mainheader *h, int *plane_nr, int *frame_nr)
Definition: ecat63ml.c:414
void ecat63InitMatlist(MATRIXLIST *mlist)
Definition: ecat63ml.c:69
void ecat63EmptyMatlist(MATRIXLIST *mlist)
Definition: ecat63ml.c:80
int ecat63GatherMatlist(MATRIXLIST *ml, short int do_planes, short int do_frames, short int do_gates, short int do_beds)
Definition: ecat63ml.c:519
int ecat63ReadMatlist(FILE *fp, MATRIXLIST *ml)
Definition: ecat63ml.c:97
int mat_numcod(int frame, int plane, int gate, int data, int bed)
Definition: ecat63ml.c:266
int ecat63GetNums(MATRIXLIST *ml, short int *num_planes, short int *num_frames, short int *num_gates, short int *num_bed_pos)
Definition: ecat63ml.c:462
int ecat63GetMatrixBlockSize(MATRIXLIST *mlist, int *blk_nr)
Definition: ecat63ml.c:382
int ecat63DeleteLateFrames(MATRIXLIST *ml, int frame_nr)
Definition: ecat63ml.c:360
void ecat63SortMatlistByPlane(MATRIXLIST *ml)
Definition: ecat63ml.c:291
void ecat63PrintMatlist(MATRIXLIST *ml)
Definition: ecat63ml.c:160
int ecat63CheckMatlist(MATRIXLIST *ml)
Definition: ecat63ml.c:342
void mat_numdoc(int matnum, Matval *matval)
Definition: ecat63ml.c:276
void ecat63SortMatlistByFrame(MATRIXLIST *ml)
Definition: ecat63ml.c:316
@ STATUS_OK
Definition: img.h:118
@ STATUS_MISSINGMATRIX
Definition: img.h:119
@ STATUS_VARMATSIZE
Definition: img.h:120
@ STATUS_FAULT
Definition: img.h:118
MatDir * matdir
Definition: ecat63.h:65
int matrixNr
Definition: ecat63.h:63
int matrixSpace
Definition: ecat63.h:64
Definition: ecat63.h:55
int matstat
Definition: ecat63.h:59
int endblk
Definition: ecat63.h:58
int matnum
Definition: ecat63.h:56
int strtblk
Definition: ecat63.h:57
Definition: ecat63.h:68
int bed
Definition: ecat63.h:69
int frame
Definition: ecat63.h:69
int gate
Definition: ecat63.h:69
int plane
Definition: ecat63.h:69
int data
Definition: ecat63.h:69
short int num_frames
Definition: ecat63.h:97
short int num_gates
Definition: ecat63.h:97