TPCCLIB
Loading...
Searching...
No Matches
cpt.c File Reference

Reading and writing CPT files. More...

#include "libtpccurveio.h"

Go to the source code of this file.

Functions

void libcpt_printdate (FILE *fp)
 
int cptrnameSplit (char *rname, char *name1, char *name2, char *name3, int max_name_len)
 
int cptReadOne (char *cptfile, DFT *dft, int verbose)
 
int cptWrite (DFT *dft, char *filename, int cpt_format)
 

Variables

char cpterrmsg [128]
 

Detailed Description

Reading and writing CPT files.

Author
Vesa Oikonen

Definition in file cpt.c.

Function Documentation

◆ cptReadOne()

int cptReadOne ( char * cptfile,
DFT * dft,
int verbose )

Read TACs from CPT file into a DFT.

Returns
Returns 0 if successful, sets cpterrmsg in case of an error.
See also
cptWrite, dftInit, cptrnameSplit
Parameters
cptfileCPT filename
dftPointer to DFT where TACs are read; must be empty and initialized
verboseVerbose level; if zero, then only warnings are printed into stderr

Definition at line 59 of file cpt.c.

66 {
67 int fi, fj, ri, ii, li, rn, fn, n, ret, colNr=10, lineNr=0;
68 char *cptr, tmp[512];
69 IFT ift;
70 int title_line, roi_col, roi_nr=0, frame_nr=0;
71
72 if(verbose>0) printf("%s('%s', *dft)\n", __func__, cptfile);
73
74 /* Check input */
75 if(cptfile==NULL || strlen(cptfile)<1 || dft==NULL) {
76 strcpy(cpterrmsg, "program error"); return(1);
77 }
78 dftEmpty(dft);
79
80 /*
81 * Read CPT file as IFT
82 */
83 iftInit(&ift);
84 ret=iftRead(&ift, cptfile, 0, verbose-1);
85 if(ret) {
86 strcpy(cpterrmsg, ift.status);
87 iftEmpty(&ift); return(4);
88 }
89 if(verbose>0) iftWrite(&ift, "stdout", 0);
90
91 /*
92 * Find the line of data titles
93 */
94 title_line=iftFindNthValue(&ift, " ROI Avg ", 1, 0);
95 if(title_line<0) {
96 sprintf(cpterrmsg, "unsupported filetype");
97 iftEmpty(&ift); return(6);
98 }
99 /* From title line, check if data consists of 10 or 11 columns */
100 strcpy(tmp, ift.item[title_line].value);
101 cptr=strtok(tmp, " \t\n\r");
102 if(strcasecmp(cptr, "Frame")!=0) {
103 sprintf(cpterrmsg, "unsupported filetype");
104 iftEmpty(&ift); return(7);
105 }
106 cptr=strtok(NULL, " \t\n\r");
107 colNr=10; if(strcasecmp(cptr, "ROI")!=0) colNr++;
108 if(colNr==10) roi_col=1; else roi_col=2;
109 if(verbose>1) printf("title_line=%d colNr=%d\n", title_line, colNr);
110
111 /*
112 * Mark data lines with sw=1
113 */
114 for(ii=lineNr=0; ii<ift.keyNr; ii++) {
115 /* Data can not start before title line and the unit line below it */
116 if(ii<title_line+2) {ift.item[ii].sw=0; continue;}
117 /* Comment lines cannot contain data, or at least we don't read it */
118 if(ift.item[ii].type!=' ' && ift.item[ii].type!='\0') {
119 ift.item[ii].sw=0; continue;}
120 /* and there cannot be any key */
121 if(ift.item[ii].key!=NULL && strlen(ift.item[ii].key)>0) {
122 ift.item[ii].sw=0; continue;}
123 /* Check that column number matches */
124 n=0; strncpy(tmp, ift.item[ii].value, 511); tmp[511]=(char)0;
125 cptr=strtok(tmp, " \t\n\r");
126 while(cptr!=NULL) {n++; cptr=strtok(NULL, " \t\n\r");}
127 if(n!=colNr) {ift.item[ii].sw=0; continue;}
128 ift.item[ii].sw=1; lineNr++;
129 }
130 if(lineNr<1) {
131 sprintf(cpterrmsg, "unsupported filetype");
132 iftEmpty(&ift); return(8);
133 }
134 if(verbose>1) printf("lineNr=%d\n", lineNr);
135
136 /*
137 * Read the data into a new, local table
138 */
139 double tactable[colNr][lineNr];
140 for(ii=0, n=0; ii<ift.keyNr; ii++) if(ift.item[ii].sw==1) {
141 ret=sscanf(ift.item[ii].value, "%lf %lf %lf %lf %lf %lf %lf %lf %lf %lf %lf",
142 &tactable[0][n], &tactable[1][n], &tactable[2][n], &tactable[3][n],
143 &tactable[4][n], &tactable[5][n], &tactable[6][n], &tactable[7][n],
144 &tactable[8][n], &tactable[9][n], &tactable[10][n] );
145 n++; /*printf("ret=%d\n", ret);*/
146 }
147 if(verbose>2) { /* print the table */
148 printf("\n");
149 for(fi=0; fi<lineNr; fi++) {
150 for(ri=0; ri<colNr; ri++) printf(" %g", tactable[ri][fi]);
151 printf("\n");
152 }
153 printf("\n");
154 }
155
156 /*
157 * Compute the number of ROIs and Frames from the data lines
158 */
159 for(fi=1, roi_nr=frame_nr=1; fi<lineNr; fi++) {
160 /* have these been seen before? */
161 for(fj=0, fn=rn=0; fj<fi; fj++) {
162 if(tactable[roi_col][fj]==tactable[roi_col][fi]) rn++;
163 if(tactable[0][fj]==tactable[0][fi]) fn++;
164 }
165 if(rn==0) roi_nr++;
166 if(fn==0) frame_nr++;
167 }
168 if(verbose>1) printf("roi_nr=%d frame_nr=%d\n", roi_nr, frame_nr);
169 /* Also, test that the highest frame number equals number of frames */
170 for(fi=0, n=0; fi<lineNr; fi++) if(tactable[0][fi]>n) n=tactable[0][fi];
171 if(n!=frame_nr) {
172 sprintf(cpterrmsg, "frames are not consequential");
173 iftEmpty(&ift); return(9);
174 }
175 /* And also, test that roi_nr*frame_nr == nr of data lines */
176 if(roi_nr*frame_nr!=lineNr) {
177 sprintf(cpterrmsg, "missing or extra samples");
178 iftEmpty(&ift); return(10);
179 }
180
181 /*
182 * Copy data into DFT
183 */
184
185 /* Allocate memory for DFT */
186 ret=dftSetmem(dft, frame_nr, roi_nr);
187 if(ret) {
188 sprintf(cpterrmsg, "cannot allocate memory");
189 iftEmpty(&ift); dftEmpty(dft); return(11);
190 }
191 dft->frameNr=frame_nr; dft->voiNr=roi_nr; dft->_type=1;
192
193 /* Make a list of ROI ID numbers */
194 int roi_id[roi_nr];
195 n=0; roi_id[n++]=tactable[roi_col][0];
196 for(fi=1; fi<lineNr; fi++) {
197 for(fj=0; fj<fi; fj++)
198 if(tactable[roi_col][fj]==tactable[roi_col][fi]) continue;
199 roi_id[n++]=(int)(0.5+tactable[roi_col][fi]);
200 }
201 if(verbose>2) {
202 printf("List of ROI ID numbers:\n");
203 for(ri=0; ri<roi_nr; ri++) printf(" %d : %d\n", ri+1, roi_id[ri]);
204 }
205
206 /* Extract data for one ROI at a time */
207 for(int ri=0; ri<roi_nr; ri++) {
208 fi=0; /* all frames of this ROI */
209 for(li=0; li<lineNr; li++) if(roi_id[ri]==(int)(0.5+tactable[roi_col][li])) {
210 /* Activity average value */
211 dft->voi[ri].y[fi]=tactable[colNr-8][li];
212 /* Only once for each ROI */
213 if(fi==0) {
214 /* ROI volume */
215 dft->voi[ri].size=tactable[colNr-1][li];
216 /* ROI name (may be changed later) */
217 sprintf(dft->voi[ri].voiname, "ROI%03d", roi_id[ri]);
218 if(colNr>10) sprintf(dft->voi[ri].place, "Pl%04.0f", tactable[1][ri]);
219 snprintf(dft->voi[ri].name, MAX_REGIONNAME_LEN, "%s . %s",
220 dft->voi[ri].voiname, dft->voi[ri].place);
221 }
222 /* Get frame times from the first ROI */
223 if(ri==0) {
224 dft->x1[fi]=tactable[colNr-4][li];
225 dft->x2[fi]=dft->x1[fi]+tactable[colNr-3][li];
226 dft->x[fi]=0.5*(dft->x1[fi]+dft->x2[fi]);
227 }
228 fi++;
229 } /* next frame */
230 } /* next ROI */
231 /* Convert frame times into minutes */
232 dftSec2min(dft); dft->timetype=3;
233
234 /*
235 * Get studynumber from filename
236 */
237 studynr_from_fname(cptfile, dft->studynr);
238
239 /*
240 * Try to find the data unit
241 */
242 ii=iftFindNthValue(&ift, "In units of ", 1, 0);
243 if(ii>=0) {
244 strncpy(tmp, ift.item[ii].value+12, 511); tmp[511]=(char)0;
245 cptr=strtok(tmp, " \t\n\r,;");
246 strncpy(dft->unit, cptr, MAX_UNITS_LEN);
247 dft->unit[MAX_UNITS_LEN]=(char)0;
248 } else {
249 strcpy(tmp, "Units"); ii=iftGet(&ift, tmp, 0);
250 if(ii>=0) {
251 strncpy(dft->unit, ift.item[ii].value, MAX_UNITS_LEN);
252 dft->unit[MAX_UNITS_LEN]=(char)0;
253 }
254 }
255
256 /*
257 * Try to extract the region name (if only one ROI)
258 */
259 if(dft->voiNr==1) {
260 ii=iftFindNthKey(&ift, "Using ROI ", 1, 0);
261 if(ii>=0) {
262 cptr=strchr(ift.item[ii].key, '\"');
263 if(cptr!=NULL) {
264 strncpy(dft->voi[0].name, cptr+1, MAX_REGIONNAME_LEN);
265 dft->voi[0].name[MAX_REGIONNAME_LEN]=(char)0;
266 cptr=strchr(dft->voi[0].name, '\"');
267 if(cptr!=NULL) *cptr=(char)0;
268 }
269 }
270 cptrnameSplit(dft->voi[0].name,
271 dft->voi[0].voiname, dft->voi[0].hemisphere, dft->voi[0].place,
273 }
274
275 /*
276 * Try to find the plane number
277 */
278 ii=iftFindNthKey(&ift, "Plane ", 1, 0);
279 if(ii>=0) {
280 n=atoi(ift.item[ii].key+6);
281 if(verbose>2) printf("Plane %d\n", n);
282 if(n>0) for(ri=0; ri<dft->voiNr; ri++) snprintf(dft->voi[ri].place, 7, "Pl%04d", n);
283 } else {
284 ii=iftFindNthValue(&ift, "Plane ", 1, 0);
285 if(ii>=0) {
286 n=atoi(ift.item[ii].value+6);
287 if(verbose>2) printf("Plane %d\n", n);
288 if(n>0) for(ri=0; ri<dft->voiNr; ri++) snprintf(dft->voi[ri].place, 7, "Pl%04d", n);
289 }
290 }
291
292 /* Set weights in DFT to 1.0 */
293 dft->isweight=0;
294 for(fi=0; fi<dft->frameNr; fi++) dft->w[fi]=1.0;
295
296
297 iftEmpty(&ift);
298 return(0);
299}
int cptrnameSplit(char *rname, char *name1, char *name2, char *name3, int max_name_len)
Definition cpt.c:24
char cpterrmsg[128]
Definition cpt.c:6
int dftSetmem(DFT *data, int frameNr, int voiNr)
Definition dft.c:57
void dftEmpty(DFT *data)
Definition dft.c:20
void dftSec2min(DFT *dft)
Definition dftunit.c:160
void iftEmpty(IFT *ift)
Definition ift.c:60
void iftInit(IFT *ift)
Definition ift.c:45
int iftRead(IFT *ift, char *filename, int is_key_required, int verbose)
Definition iftfile.c:24
int iftWrite(IFT *ift, char *filename, int verbose)
Definition iftfile.c:282
int iftFindNthValue(IFT *ift, char *str, int n, int verbose)
Definition iftsrch.c:120
int iftFindNthKey(IFT *ift, char *str, int n, int verbose)
Definition iftsrch.c:84
int iftGet(IFT *ift, char *key, int verbose)
Definition iftsrch.c:15
#define MAX_REGIONNAME_LEN
Definition libtpcmisc.h:154
int studynr_from_fname(char *fname, char *studynr)
Definition studynr.c:119
#define MAX_UNITS_LEN
Definition libtpcmisc.h:95
#define MAX_REGIONSUBNAME_LEN
Definition libtpcmisc.h:158
int _type
int timetype
Voi * voi
char studynr[MAX_STUDYNR_LEN+1]
double * w
double * x1
int voiNr
double * x2
int frameNr
int isweight
double * x
char unit[MAX_UNITS_LEN+1]
int keyNr
Definition libtpcmisc.h:270
const char * status
Definition libtpcmisc.h:277
IFT_KEY_AND_VALUE * item
Definition libtpcmisc.h:279
double size
char voiname[MAX_REGIONSUBNAME_LEN+1]
double * y
char name[MAX_REGIONNAME_LEN+1]
char hemisphere[MAX_REGIONSUBNAME_LEN+1]
char place[MAX_REGIONSUBNAME_LEN+1]

◆ cptrnameSplit()

int cptrnameSplit ( char * rname,
char * name1,
char * name2,
char * name3,
int max_name_len )

Split region name into 1-3 subparts of given max length.

Returns
Returns the number of subparts.
See also
cptReadOne
Parameters
rnameRegion name to split (string is not edited)
name1Pointer to 1st subname (anatomical region)
name2Pointer to 2nd subname (usually hemisphere)
name3Pointer to 3rd subname (usually image plane)
max_name_lenMax lenght of subnames, excluding terminal null

Definition at line 24 of file cpt.c.

35 {
36 char temp[MAX_REGIONNAME_LEN+1], *cptr, *cptr2;
37 int nr=0;
38
39 if(rname==NULL || name1==NULL || name2==NULL || name3==NULL) return(0);
40 if(max_name_len<1) return(0);
41 name1[0]=name2[0]=name3[0]=(char)0;
42 strncpy(temp, rname, MAX_REGIONNAME_LEN); temp[MAX_REGIONNAME_LEN]=(char)0;
43 cptr=strtok(temp, " _\t\n\r"); if(cptr==NULL) return(nr);
44 cptr2=strstr(cptr, "dx"); if(cptr2==NULL) cptr2=strstr(cptr, "sin");
45 if(cptr2!=NULL) {strcpy(name2, cptr2); *cptr2=(char)0; nr++;}
46 else strcpy(name2, ".");
47 strncpy(name1, cptr, max_name_len); name1[max_name_len]=(char)0; nr++;
48 cptr=strtok(NULL, " _\t\n\r"); if(cptr==NULL) return(nr);
49 strncpy(name3, cptr, max_name_len); name3[max_name_len]=(char)0; nr++;
50 return(nr);
51}

Referenced by cptReadOne().

◆ cptWrite()

int cptWrite ( DFT * dft,
char * filename,
int cpt_format )

Write TAC data in CPT (Imagetool) format. If TACs are from different planes, then each plane will be saved in its own file.

Returns
Returns 0 if successful; in case of an error, sets string cpterrmsg.
See also
cptReadOne, dftInit
Parameters
dftTAC data to write
filenameCPT path and file name without extension, because this function may need to add plane number before .cpt
cpt_formatSpecific CPT format: 0=default, others not yet supported

Definition at line 308 of file cpt.c.

316 {
317 int ri, fi, ret, n, roi_id;
318 FILE *fp;
319 char cptfile[FILENAME_MAX], tmp[256];
320
321 /* Check input */
322 if(dft==NULL || dft->voiNr<1 || dft->frameNr<1 || strlen(filename)<1) {
323 strcpy(cpterrmsg, "program error"); return(1);
324 }
325 if(cpt_format!=0) strcpy(cpterrmsg, "cpt format not supported yet");
326 /* Sort data by plane */
327 ret=dftSortPlane(dft);
328 if(ret) {
329 strcpy(cpterrmsg, "error in data file"); return(2);
330 }
331 /* Convert times to seconds if necessary */
332 if(dft->timeunit==TUNIT_MIN) dftMin2sec(dft);
333
334
335 for(ri=0; ri<dft->voiNr; ri++) {
336 /* Construct CPT filename */
337 strcpy(cptfile, filename);
338 if(strlen(dft->voi[ri].place)>0 && strcmp(dft->voi[ri].place, ".")!=0) {
339 snprintf(cptfile, FILENAME_MAX, "%s_%s.cpt", filename, dft->voi[ri].place);
340 } else {
341 snprintf(cptfile, FILENAME_MAX, "%s.cpt", filename);
342 }
343 /* Open file */
344 fp=fopen(cptfile, "w");
345 if(fp==NULL) {
346 sprintf(cpterrmsg, "cannot open file for write"); return(5);
347 }
348 /* Write 1st title */
349 if(strlen(dft->unit)==0) strcpy(tmp, "unknown"); else strcpy(tmp, dft->unit);
350 //fprintf(fp, "# In units of %s per pixel per second\n", tmp);
351 fprintf(fp, "# In units of %s\n", tmp);
352 /* Write 2nd title */
353 if(strncasecmp(dft->voi[ri].place, "Pl", 2)==0)
354 sprintf(tmp, "%d", atoi(dft->voi[ri].place+2));
355 else if(strlen(dft->voi[ri].place)==0 || strcmp(dft->voi[ri].place, ".")==0)
356 strcpy(tmp, "1");
357 else
358 strcpy(tmp, dft->voi[ri].place);
359 fprintf(fp, "Plane %-6.6s Scan Start Date (d m y): 1 1 1980 Scan Start Time (h m s): 0 0 0\n\n", tmp);
360 /* Write 3rd title */
361 fprintf(fp, "Frame ROI ID ROI Avg #pixels ROI Total %%Stdev Offset Duration ROI Surf. ROI Vol.\n");
362 fprintf(fp, " (screen) (sec) (sec) mmxmm mmxmmxmm\n");
363 /* Write all frames */
364 for(fi=0, n=ri; fi<dft->frameNr; fi++) {
365 n=ri;
366 /* current region */
367 strcpy(tmp, dft->voi[ri].voiname);
368 if(strlen(dft->voi[ri].hemisphere)>0 && strcmp(dft->voi[ri].hemisphere, ".")!=0) {
369 strcat(tmp, " "); strcat(tmp, dft->voi[ri].hemisphere);}
370 strcpy(tmp, "");
371 if(strncasecmp(dft->voi[ri].voiname, "ROI", 3)==0 && atoi(dft->voi[ri].voiname+3)>0)
372 roi_id=atoi(dft->voi[ri].voiname+3); else roi_id=1;
373 fprintf(fp, "%-6d %-3d %-8.8s %11.4e %5d %10.4e %7.1f %9.1f %9.1f %10.4e %10.4e\n",
374 fi+1, roi_id, tmp, dft->voi[ri].y[fi], 0, 0.0, 0.0,
375 dft->x1[fi], dft->x2[fi]-dft->x1[fi], 0.0, dft->voi[ri].size );
376 /* the rest of regions on the same plane */
377 while(n<dft->voiNr-1 && strcasecmp(dft->voi[ri].place, dft->voi[n+1].place)==0) {
378 n++; strcpy(tmp, dft->voi[n].voiname);
379 if(strlen(dft->voi[n].hemisphere)>0 && strcmp(dft->voi[n].hemisphere, ".")!=0) {
380 strcat(tmp, " "); strcat(tmp, dft->voi[n].hemisphere);}
381 strcpy(tmp, "");
382 if(strncasecmp(dft->voi[n].voiname, "ROI", 3)==0 && atoi(dft->voi[n].voiname+3)>0)
383 roi_id=atoi(dft->voi[n].voiname+3); else roi_id=n-ri+1;
384 fprintf(fp, "%-6d %-3d %-8.8s %11.4e %5d %10.4e %7.1f %9.1f %9.1f %10.4e %10.4e\n",
385 fi+1, roi_id, tmp, dft->voi[n].y[fi], 0, 0.0, 0.0,
386 dft->x1[fi], dft->x2[fi]-dft->x1[fi], 0.0, dft->voi[n].size );
387 }
388 }
389 ri=n;
390#if(0)
391 /* DON'T DO THIS; at least "asetaatti" program does not work with this */
392 /* In the end, write the number of frames */
393 fprintf(fp, "\n# %d Frame(s) analyzed.\n", dft->frameNr);
394#endif
395 fclose(fp);
396 }
397
398 return(0);
399}
int dftSortPlane(DFT *data)
Definition dft.c:875
void dftMin2sec(DFT *dft)
Definition dftunit.c:145
int timeunit

◆ libcpt_printdate()

void libcpt_printdate ( FILE * fp)

Print the compilation date and time to specified FILE pointer

Definition at line 13 of file cpt.c.

14{
15 fprintf(fp, "libcpt compiled on %s %s\n", __DATE__, __TIME__);
16}

Variable Documentation

◆ cpterrmsg

char cpterrmsg[128]

Error message from CPT functions.

Definition at line 6 of file cpt.c.

Referenced by cptReadOne(), and cptWrite().