TPCCLIB
Loading...
Searching...
No Matches
tpcpar.h File Reference

Header file for libtpcpar. More...

#include "tpcclibConfig.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include "tpcextensions.h"
#include "tpccsv.h"
#include "tpcift.h"
#include "tpcmodels.h"

Go to the source code of this file.

Data Structures

struct  PARR
struct  PARN
struct  PAR

Enumerations

enum  parformat {
  PAR_FORMAT_UNKNOWN , PAR_FORMAT_RES , PAR_FORMAT_FIT , PAR_FORMAT_IFT ,
  PAR_FORMAT_CSV_INT , PAR_FORMAT_CSV_UK , PAR_FORMAT_TSV_INT , PAR_FORMAT_TSV_UK ,
  PAR_FORMAT_XML , PAR_FORMAT_HTML , PAR_FORMAT_LAST
}

Functions

void parInit (PAR *par)
void parrInit (PARR *parr)
void parnInit (PARN *parn)
void parFree (PAR *par)
void parrFree (PARR *parr)
int parAllocate (PAR *par, int parNr, int tacNr)
int parAllocateMore (PAR *par, int parNr, int tacNr)
int parrAllocate (PARR *parr, int parNr)
char * parIsStudyNr (PAR *par)
int parSetStudyNr (PAR *par, const char *s)
void parEnsureNames (PAR *d)
int parIsWSS (PAR *par)
int parIsFitRange (PAR *par)
int parIsModel (PAR *par)
int parSDWithPar (PAR *par, int pi)
int parCLWithPar (PAR *par, int pi)
int parIsFitNr (PAR *par)
int parIsDataNr (PAR *par)
int parDeletePar (PAR *par, int pi)
int parDeleteTAC (PAR *par, int ti)
char * parIsOptcrit (PAR *par)
char * parFormattxt (parformat c)
int parFormatIdentify (const char *s)
int parFormatFromExtension (const char *s)
char * parDefaultExtension (parformat c)
int parWrite (PAR *par, FILE *fp, parformat format, int extra, TPCSTATUS *status)
int parRead (PAR *par, const char *fname, TPCSTATUS *status)
void parListLimits (PAR *par, FILE *fp)
int parWriteLimits (PAR *par, const char *fname, const int verbose)
int parReadLimits (PAR *par, const char *fname, const int verbose)
int parWriteCSV (PAR *par, FILE *fp, parformat format, int extra, TPCSTATUS *status)
int parReadCSV (PAR *par, CSV *csv, IFT *hdr, TPCSTATUS *status)
int parToIFT (PAR *par, IFT *ift, TPCSTATUS *status)
int parWriteIFT (PAR *par, FILE *fp, TPCSTATUS *status)
int parFromIFT (PAR *par, IFT *ift, TPCSTATUS *status)
int parWriteRES (PAR *par, FILE *fp, TPCSTATUS *status)
int parReadRES (PAR *par, CSV *csv, IFT *ift, TPCSTATUS *status)
int parPrintType (PAR *par, int parIndex)
int parWriteFIT (PAR *par, FILE *fp, TPCSTATUS *status)
int parReadFIT (PAR *par, CSV *csv, IFT *ift, TPCSTATUS *status)
int parWriteXML (PAR *par, FILE *fp, TPCSTATUS *status)
int parSelectByAnother (PAR *d1, PAR *d2, int *pn, int *pr, TPCSTATUS *status)
int parCombineTACs (PAR *d1, PAR *d2, TPCSTATUS *status)
int parCompareParameterNames (PAR *d1, PAR *d2, const int i, const int casens, TPCSTATUS *status)
int parCompareParameterUnits (PAR *d1, PAR *d2, const int i, TPCSTATUS *status)
int parCompareTacNames (PAR *d1, PAR *d2, const int i, const int casens, TPCSTATUS *status)
int parCompareParameters (PAR *d1, PAR *d2, const int pi, const int ti, int checkpar, int checksd, int checkcl, const double test_abs, const double test_rel, TPCSTATUS *status)
int parCompareWSS (PAR *d1, PAR *d2, const int ti, const double test_abs, const double test_rel, TPCSTATUS *status)
int parSortByName (PAR *d, TPCSTATUS *status)
int parSelectTACs (PAR *d, const char *region_name, int reset, TPCSTATUS *status)
int parSelectedTACs (PAR *d)
int parSelectParameters (PAR *d, const char *par_name, int reset, TPCSTATUS *status)
int parSelectedParameters (PAR *d)
int parFindParameter (PAR *d, const char *par_name)
double parGetParameter (PAR *d, const char *par_name, const int ti)
int parGetParameterUnit (PAR *d, const char *par_name)
void parValueRange (PAR *d, const int i, double *pmin, double *pmax)
int parExampleTTACs (PAR *d, int type, TPCSTATUS *status)
int parExamplePerfectBolus (PAR *d, TPCSTATUS *status)
int parExampleRadiowaterBolus (PAR *d, TPCSTATUS *status)

Detailed Description

Header file for libtpcpar.

Header file for model parameter library.

Author
Vesa Oikonen

Definition in file tpcpar.h.

Enumeration Type Documentation

◆ parformat

enum parformat

PAR file format codes;

See also
par_format
Enumerator
PAR_FORMAT_UNKNOWN 

Unknown format.

PAR_FORMAT_RES 

Model result format of Turku PET Centre.

PAR_FORMAT_FIT 

Function fit format of Turku PET Centre.

PAR_FORMAT_IFT 

Interfile-type data (supported for writing).

PAR_FORMAT_CSV_INT 

International CSV.

PAR_FORMAT_CSV_UK 

UK CSV.

PAR_FORMAT_TSV_INT 

International TSV (comma as decimal separator).

PAR_FORMAT_TSV_UK 

UK TSV (point as decimal separator).

PAR_FORMAT_XML 

XML format (currently not supported).

PAR_FORMAT_HTML 

HTML table format (currently not supported).

PAR_FORMAT_LAST 

End of list.

Definition at line 27 of file tpcpar.h.

27 {
39} parformat;
parformat
Definition tpcpar.h:27
@ PAR_FORMAT_XML
XML format (currently not supported).
Definition tpcpar.h:36
@ PAR_FORMAT_HTML
HTML table format (currently not supported).
Definition tpcpar.h:37
@ PAR_FORMAT_CSV_UK
UK CSV.
Definition tpcpar.h:33
@ PAR_FORMAT_CSV_INT
International CSV.
Definition tpcpar.h:32
@ PAR_FORMAT_IFT
Interfile-type data (supported for writing).
Definition tpcpar.h:31
@ PAR_FORMAT_TSV_INT
International TSV (comma as decimal separator).
Definition tpcpar.h:34
@ PAR_FORMAT_RES
Model result format of Turku PET Centre.
Definition tpcpar.h:29
@ PAR_FORMAT_FIT
Function fit format of Turku PET Centre.
Definition tpcpar.h:30
@ PAR_FORMAT_UNKNOWN
Unknown format.
Definition tpcpar.h:28
@ PAR_FORMAT_LAST
End of list.
Definition tpcpar.h:38
@ PAR_FORMAT_TSV_UK
UK TSV (point as decimal separator).
Definition tpcpar.h:35

Function Documentation

◆ parAllocate()

int parAllocate ( PAR * par,
int parNr,
int tacNr )
extern

Allocate memory for PAR data.

Any previous contents are deleted.

Returns
Returns TPCERROR status.
See also
parInit, parFree, parAllocateMore, parAllocateWithTAC
Parameters
parPointer to initiated PAR struct data; any old contents are deleted. tacNr and parNr inside the struct are set to or kept at zero.
parNrNr of parameters to allocate
tacNrNr of parameter sets (TACs) to allocate

Definition at line 108 of file par.c.

116 {
117 if(par==NULL) return TPCERROR_FAIL;
118 /* Delete any previous contents */
119 parFree(par);
120 /* If no memory is requested, then just return */
121 if(parNr<1 && tacNr<1) return TPCERROR_OK;
122 if(parNr<1 || tacNr<1) return TPCERROR_FAIL;
123
124 /* Allocate memory for PARR data */
125 int ret;
126 par->r=(PARR*)malloc(tacNr*sizeof(PARR));
127 if(par->r==NULL) return TPCERROR_OUT_OF_MEMORY;
128 for(int i=0; i<tacNr; i++) {
129 parrInit(&par->r[i]);
130 ret=parrAllocate(par->r+i, parNr); if(ret!=TPCERROR_OK) return ret;
131 }
132 par->_tacNr=tacNr;
133
134 /* Allocate memory for parameter names and units */
135 par->n=(PARN*)malloc(parNr*sizeof(PARN));
136 if(par->n==NULL) return TPCERROR_OUT_OF_MEMORY;
137 for(int i=0; i<parNr; i++) parnInit(&par->n[i]);
138 par->_parNr=parNr;
139
140 return TPCERROR_OK;
141}
void parFree(PAR *par)
Definition par.c:75
int parrAllocate(PARR *parr, int parNr)
Definition par.c:150
void parrInit(PARR *parr)
Definition par.c:41
void parnInit(PARN *parn)
Definition par.c:59
int _parNr
Definition tpcpar.h:110
PARR * r
Definition tpcpar.h:114
int _tacNr
Definition tpcpar.h:106
PARN * n
Definition tpcpar.h:112
Definition tpcpar.h:80
Definition tpcpar.h:46
@ TPCERROR_FAIL
General error.
@ TPCERROR_OUT_OF_MEMORY
Cannot allocate memory.
@ TPCERROR_OK
No error.

Referenced by parAllocateWithTAC(), parExamplePerfectBolus(), parExampleRadiowaterBolus(), parExampleTTACs(), parFromIFT(), parReadCSV(), parReadFIT(), and parReadRES().

◆ parAllocateMore()

int parAllocateMore ( PAR * par,
int parNr,
int tacNr )
extern

Allocate more memory for PAR data. Previous contents are preserved.

Returns
Returns TPCERROR status.
See also
parAllocate, parInit, parRead, parFree
Parameters
parPointer to initiated and previously allocated PAR struct data; any old contents are preserved, including tacNr and parNr.
parNrNr of additional parameters to allocate; if struct contains unused space for requested parameters already, then nothing is done.
tacNrNr of additional parameter sets (TACs) to allocate; if struct contains unused space for requested parameters already, then nothing is done.

Definition at line 183 of file par.c.

193 {
194 if(par==NULL) return TPCERROR_FAIL;
195 if(par->_parNr<1 || par->_tacNr<1) return TPCERROR_FAIL;
196 if(parNr<0 || tacNr<0) return TPCERROR_FAIL;
197 /* Check if there is enough space already */
198 int newTacNr, addTacNr, newParNr, addParNr;
199 newTacNr=par->tacNr+tacNr; addTacNr=newTacNr-par->_tacNr;
200 newParNr=par->parNr+parNr; addParNr=newParNr-par->_parNr;
201 if(addTacNr<=0 && addParNr<=0) return TPCERROR_OK;
202
203 /* Reallocate memory for parameter names and units, if necessary */
204 if(addParNr>0) {
205 PARN *parnPtr;
206 parnPtr=realloc(par->n, sizeof(PARN)*newParNr);
207 if(parnPtr==NULL) return TPCERROR_OUT_OF_MEMORY;
208 par->n=parnPtr;
209 parnPtr+=par->_parNr; for(int i=0; i<addParNr; i++) parnInit(parnPtr++);
210 }
211
212 /* Reallocate memory for parameters of previous TACs, if necessary */
213 if(addParNr>0) {
214 int i, j;
215 for(i=0; i<par->tacNr; i++) {
216 par->r[i].p=realloc(par->r[i].p, sizeof(double)*newParNr);
217 par->r[i].sd=realloc(par->r[i].sd, sizeof(double)*newParNr);
218 par->r[i].cl1=realloc(par->r[i].cl1, sizeof(double)*newParNr);
219 par->r[i].cl2=realloc(par->r[i].cl2, sizeof(double)*newParNr);
220 if(par->r[i].p==NULL || par->r[i].sd==NULL || par->r[i].cl1==NULL || par->r[i].cl2==NULL)
222 for(j=par->parNr; j<newParNr; j++)
223 par->r[i].p[j]=par->r[i].sd[j]=par->r[i].cl1[j]=par->r[i].cl2[j]=nan("");
224 }
225 }
226
227 /* Allocate memory for more TACs, if necessary */
228 if(addTacNr>0) {
229 PARR *parrPtr;
230 parrPtr=realloc(par->r, sizeof(PARR)*newTacNr);
231 if(parrPtr==NULL) return TPCERROR_OUT_OF_MEMORY;
232 par->r=parrPtr;
233 parrPtr+=par->_tacNr;
234 for(int i=0; i<addTacNr; i++, parrPtr++) {
235 parrInit(parrPtr);
236 if(parrAllocate(parrPtr, newParNr)!=TPCERROR_OK)
238 }
239 }
240
241 par->_parNr=newParNr;
242 par->_tacNr=newTacNr;
243 return TPCERROR_OK;
244}
int parNr
Definition tpcpar.h:108
int tacNr
Definition tpcpar.h:104
double * cl2
Definition tpcpar.h:70
double * p
Definition tpcpar.h:64
double * sd
Definition tpcpar.h:66
double * cl1
Definition tpcpar.h:68

Referenced by parCombineTACs().

◆ parCLWithPar()

int parCLWithPar ( PAR * par,
int pi )
extern

Check if specified parameter has confidence limits in at least one of the regions.

See also
parSDWithPar, parIsWSS
Returns
Returns 1 if CLs exist, and 0 if not (or in case of an error).
Parameters
parPointer to parameter data.
piIndex of parameter [0..parNr-1] to check.

Definition at line 325 of file par.c.

330 {
331 if(par==NULL || par->tacNr<1 || pi<0 || pi>=par->parNr) return(0);
332 for(int i=0; i<par->tacNr; i++)
333 if(!isnan(par->r[i].cl1[pi]) && !isnan(par->r[i].cl2[pi])) return(1);
334 return(0);
335}

Referenced by parWriteCSV(), and parWriteXML().

◆ parCombineTACs()

int parCombineTACs ( PAR * d1,
PAR * d2,
TPCSTATUS * status )

Copy parameters from source PAR structure to target structure for TACs that are available in both structures.

Returns
enum tpcerror (TPCERROR_OK when successful).
See also
parSelectByAnother, parSelectTACs, parEnsureNames
Parameters
d1Pointer to target PAR structure.
d2Pointer to source PAR structure; not modified.
statusPointer to status data; enter NULL if not needed.

Definition at line 99 of file parcomb.c.

106 {
107 int verbose=0; if(status!=NULL) verbose=status->verbose;
108 if(verbose>0) printf("%s()\n", __func__);
109
110 /* Check what there is to copy */
111 int tacNr;
112 int ret=parSelectByAnother(d1, d2, NULL, &tacNr, status);
113 if(ret!=TPCERROR_OK) return(ret);
114 if(tacNr<1) {
115 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_NO_DATA);
116 return TPCERROR_NO_DATA;
117 }
118 int parNr=d2->parNr;
119 if(verbose>1) printf("%d TACs and %d parameters to copy.\n", tacNr, parNr);
120
121 /* Allocate memory for the new parameters */
122 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_OK);
123 ret=parAllocateMore(d1, parNr, 0);
124 if(ret!=TPCERROR_OK) return(ret);
125
126 /* Copy new parameter names */
127 for(int i=0; i<d2->parNr; i++) {
128 strcpy(d1->n[i+d1->parNr].name, d2->n[i].name);
129 d1->n[i+d1->parNr].unit=d2->n[i].unit;
130 d1->n[i+d1->parNr].lim1=d2->n[i].lim1;
131 d1->n[i+d1->parNr].lim2=d2->n[i].lim2;
132 d1->n[i+d1->parNr].tol=d2->n[i].tol;
133 }
134
135 /* Copy contents for common TACs */
136 for(int i=0; i<d1->tacNr; i++) {
137 /* find matching TAC name */
138 if(strnlen(d1->r[i].name, 1)<1) continue;
139 int j;
140 for(j=0; j<d2->tacNr; j++) {
141 if(strnlen(d2->r[j].name, 1)<1) continue;
142 if(strcasecmp(d1->r[i].name, d2->r[j].name)==0) break;
143 /* Allow mixed '-' and '_' */
144 char *buf1, *buf2;
145 buf1=strdup(d1->r[i].name); strReplaceChar(buf1, '-', '_');
146 buf2=strdup(d2->r[j].name); strReplaceChar(buf2, '-', '_');
147 int ret=strcasecmp(buf1, buf2);
148 free(buf1); free(buf2);
149 if(ret==0) break;
150 }
151 if(j==d2->tacNr) continue; // matching name not found, leave values as NaN
152
153 /* Copy new parameter values */
154 for(int k=0; k<d2->parNr; k++) {
155 d1->r[i].p[k+d1->parNr]=d2->r[j].p[k];
156 d1->r[i].sd[k+d1->parNr]=d2->r[j].sd[k];
157 d1->r[i].cl1[k+d1->parNr]=d2->r[j].cl1[k];
158 d1->r[i].cl2[k+d1->parNr]=d2->r[j].cl2[k];
159 }
160 }
161
162 d1->parNr+=d2->parNr;
163
164 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_OK);
165 return TPCERROR_OK;
166}
int parAllocateMore(PAR *par, int parNr, int tacNr)
Definition par.c:183
int parSelectByAnother(PAR *d1, PAR *d2, int *pn, int *pr, TPCSTATUS *status)
Definition parcomb.c:22
void statusSet(TPCSTATUS *s, const char *func, const char *srcfile, int srcline, tpcerror error)
Definition statusmsg.c:142
void strReplaceChar(char *s, char c1, char c2)
Definition stringext.c:134
char * strdup(const char *s)
Definition stringext.c:185
size_t strnlen(const char *s, size_t n)
Definition stringext.c:566
int unit
Definition tpcpar.h:86
double lim2
Definition tpcpar.h:90
double tol
Definition tpcpar.h:92
char name[MAX_PARNAME_LEN+1]
Definition tpcpar.h:82
double lim1
Definition tpcpar.h:88
char name[MAX_TACNAME_LEN+1]
Definition tpcpar.h:50
int verbose
Verbose level, used by statusPrint() etc.
@ TPCERROR_NO_DATA
File contains no data.

◆ parCompareParameterNames()

int parCompareParameterNames ( PAR * d1,
PAR * d2,
const int i,
const int casens,
TPCSTATUS * status )
extern

Check whether parameter names are the same in two PAR data.

Comparison is very strict, thus the names may need to be preprocessed if this is used for other purpose than SW testing.

Returns
0 in case of match, 1 if no match or error.
Author
Vesa Oikonen
Parameters
d1Pointer to PAR struct.
d2Pointer to PAR struct.
iParameter index [0..parNr-1] to compare; enter <0 to verify all.
casensCase-sensitivity: 0=case does not have to match; <>0=case must match.
statusPointer to status data; enter NULL if not needed.

Definition at line 28 of file parcomp.c.

39 {
40 int verbose=0; if(status!=NULL) verbose=status->verbose;
41 if(verbose>1) printf("%s()\n", __func__);
42
43 /* Check that required data exists */
44 if(d1==NULL || d2==NULL || d1->parNr<1 || d2->parNr<1) {
45 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_NO_DATA);
46 return 1;
47 }
48 /* If index is specified, then verify that that parameter is available */
49 if(i>=0 && (i>=d1->parNr || i>=d2->parNr)) {
50 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_FAIL);
51 return 1;
52 }
53
54 /* If index is not specified, then parNr must match */
55 if(i<0 && (d1->parNr!=d2->parNr)) {
56 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_OK);
57 if(verbose>0) printf("different parameter nr.\n");
58 return(1);
59 }
60
61 /* Compare */
62 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_OK);
63 int vr;
64 for(int pi=0; pi<d1->parNr; pi++) if(i<0 || i==pi) {
65 if(casens==0) vr=strcasecmp(d1->n[pi].name, d2->n[pi].name);
66 else vr=strcmp(d1->n[pi].name, d2->n[pi].name);
67 if(vr==0) continue;
68 /* No problem, if difference is '_' versus '-' */
69 if(strchr(d1->n[pi].name, '-') || strchr(d1->n[pi].name, '_')) {
70 char *buf1, *buf2;
71 buf1=strdup(d1->n[pi].name); strReplaceChar(buf1, '-', '_');
72 buf2=strdup(d2->n[pi].name); strReplaceChar(buf2, '-', '_');
73 if(verbose>100) printf("'%s' vs '%s'\n", buf1, buf2);
74 if(casens==0) vr=strcasecmp(buf1, buf2); else vr=strcmp(buf1, buf2);
75 free(buf1); free(buf2);
76 }
77 if(vr==0) continue;
78 /* No problem, if difference is '_' versus ' ' */
79 if(strchr(d1->n[pi].name, '_') || strchr(d2->n[pi].name, '_')) {
80 char *buf1, *buf2;
81 buf1=strdup(d1->n[pi].name); strReplaceChar(buf1, '_', ' ');
82 buf2=strdup(d2->n[pi].name); strReplaceChar(buf2, '_', ' ');
83 if(verbose>100) printf("'%s' vs '%s'\n", buf1, buf2);
84 if(casens==0) vr=strcasecmp(buf1, buf2); else vr=strcmp(buf1, buf2);
85 free(buf1); free(buf2);
86 }
87 if(vr==0) continue;
88 if(verbose>0) {
89 printf("par1.n[%d].name := '%s'\n", pi, d1->n[pi].name);
90 printf("par2.n[%d].name := '%s'\n", pi, d2->n[pi].name);
91 }
92 return(1);
93 }
94 return(0);
95}

◆ parCompareParameters()

int parCompareParameters ( PAR * d1,
PAR * d2,
const int pi,
const int ti,
int checkpar,
int checksd,
int checkcl,
const double test_abs,
const double test_rel,
TPCSTATUS * status )
extern

Check whether parameter values are the same in two PAR data.

Note that units are ignored here. If either absolute or relative difference is below the limit, the test is reported as passed.

See also
parCompareParameterUnits.
Returns
0 in case of match, and >0 if no match or error.
Author
Vesa Oikonen
Parameters
d1Pointer to PAR structure.
d2Pointer to PAR structure.
piPAR index [0..parNr-1] to compare; enter <0 to verify all parameters.
tiTAC index [0..tacNr-1] to compare; enter <0 to verify all TACs.
checkparCheck parameter values (1) or do not check (0).
checksdCheck parameter SD values (1) or do not check (0).
checkclCheck parameter CL values (1) or do not check (0).
test_absLimit for accepted absolute difference; obligatory.
test_relOptional limit for accepted relative difference |2*(x1-x2)/(x1+x2)| ; set to negative value to not test this; in case of zero mean, this test is assumed to fail, but test for absolute difference may still pass.
statusPointer to status data; enter NULL if not needed.

Definition at line 237 of file parcomp.c.

260 {
261 int verbose=0; if(status!=NULL) verbose=status->verbose;
262 if(verbose>1) printf("%s()\n", __func__);
263
264 /* Check that required data exists */
265 if(d1==NULL || d2==NULL || d1->tacNr<1 || d2->tacNr<1 || d1->parNr<1 || d2->parNr<1) {
266 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_NO_DATA);
267 return 1;
268 }
269 /* Check that at least something is tested */
270 if(!checkpar && !checksd && !checkcl) {
271 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_FAIL);
272 return 1;
273 }
274 /* If index is specified, then verify that TAC or PAR is available */
275 if(pi>=0 && (pi>=d1->parNr || pi>=d2->parNr)) {
276 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_FAIL);
277 return 2;
278 }
279 if(ti>=0 && (ti>=d1->tacNr || ti>=d2->tacNr)) {
280 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_FAIL);
281 return 2;
282 }
283
284 /* If index is not specified, then parNr or tacNr must match */
285 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_OK);
286 if(pi<0 && (d1->parNr!=d2->parNr)) {
287 if(verbose>0) printf("different parameter nr.\n");
288 return(3);
289 }
290 if(ti<0 && (d1->tacNr!=d2->tacNr)) {
291 if(verbose>0) printf("different TAC nr.\n");
292 return(3);
293 }
294
295 /* Compare */
296 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_OK);
297 int pj, tj;
298 if(checkpar) {
299 for(tj=0; tj<d1->tacNr; tj++) if(ti<0 || tj==ti) {
300 for(pj=0; pj<d1->parNr; pj++) if(pi<0 || pj==pi) {
301 if(doubleMatch(d1->r[tj].p[pj], d2->r[tj].p[pj], test_abs)==1) continue;
302 if(test_rel>0.0 && doubleMatchRel(d1->r[tj].p[pj], d2->r[tj].p[pj], test_rel)==1) continue;
303 if(verbose>0) {
304 double s=fabs(d1->r[tj].p[pj]-d2->r[tj].p[pj]);
305 printf("par1.r[%d].p[%d] := %g\n", tj, pj, d1->r[tj].p[pj]);
306 printf("par2.r[%d].p[%d] := %g\n", tj, pj, d2->r[tj].p[pj]);
307 printf("|diff| := %g\n", s);
308 printf("diff_limit := %g\n", test_abs);
309 if(test_rel>0.0) printf("rel_diff_limit := %g\n", test_rel);
310 }
311 return(10);
312 }
313 }
314 }
315 if(checksd) {
316 for(tj=0; tj<d1->tacNr; tj++) if(ti<0 || tj==ti) {
317 for(pj=0; pj<d1->parNr; pj++) if(pi<0 || pj==pi) {
318 if(doubleMatch(d1->r[tj].sd[pj], d2->r[tj].sd[pj], test_abs)==1) continue;
319 if(test_rel>0.0 && doubleMatchRel(d1->r[tj].sd[pj], d2->r[tj].sd[pj], test_rel)==1) continue;
320 if(verbose>0) {
321 double s=fabs(d1->r[tj].sd[pj]-d2->r[tj].sd[pj]);
322 printf("par1.r[%d].sd[%d] := %g\n", tj, pj, d1->r[tj].sd[pj]);
323 printf("par2.r[%d].sd[%d] := %g\n", tj, pj, d2->r[tj].sd[pj]);
324 printf("|diff| := %g\n", s);
325 printf("diff_limit := %g\n", test_abs);
326 if(test_rel>0.0) printf("rel_diff_limit := %g\n", test_rel);
327 }
328 return(10);
329 }
330 }
331 }
332 if(checkcl) {
333 for(tj=0; tj<d1->tacNr; tj++) if(ti<0 || tj==ti) {
334 for(pj=0; pj<d1->parNr; pj++) if(pi<0 || pj==pi) {
335 if(doubleMatch(d1->r[tj].cl1[pj], d2->r[tj].cl1[pj], test_abs)==1) continue;
336 if(test_rel>0.0 && doubleMatchRel(d1->r[tj].cl1[pj], d2->r[tj].cl1[pj], test_rel)==1) continue;
337 if(verbose>0) {
338 double s=fabs(d1->r[tj].cl1[pj]-d2->r[tj].cl1[pj]);
339 printf("par1.r[%d].cl1[%d] := %g\n", tj, pj, d1->r[tj].cl1[pj]);
340 printf("par2.r[%d].cl1[%d] := %g\n", tj, pj, d2->r[tj].cl1[pj]);
341 printf("|diff| := %g\n", s);
342 printf("diff_limit := %g\n", test_abs);
343 if(test_rel>0.0) printf("rel_diff_limit := %g\n", test_rel);
344 }
345 return(10);
346 }
347 }
348 for(tj=0; tj<d1->tacNr; tj++) if(ti<0 || tj==ti) {
349 for(pj=0; pj<d1->parNr; pj++) if(pi<0 || pj==pi) {
350 if(doubleMatch(d1->r[tj].cl2[pj], d2->r[tj].cl2[pj], test_abs)==1) continue;
351 if(test_rel>0.0 && doubleMatchRel(d1->r[tj].cl2[pj], d2->r[tj].cl2[pj], test_rel)==1) continue;
352 if(verbose>0) {
353 double s=fabs(d1->r[tj].cl2[pj]-d2->r[tj].cl2[pj]);
354 printf("par1.r[%d].cl2[%d] := %g\n", tj, pj, d1->r[tj].cl2[pj]);
355 printf("par2.r[%d].cl2[%d] := %g\n", tj, pj, d2->r[tj].cl2[pj]);
356 printf("|diff| := %g\n", s);
357 printf("diff_limit := %g\n", test_abs);
358 if(test_rel>0.0) printf("rel_diff_limit := %g\n", test_rel);
359 }
360 return(10);
361 }
362 }
363 }
364
365 return(0);
366}
int doubleMatch(const double v1, const double v2, const double lim)
Definition doubleutil.c:27
int doubleMatchRel(const double v1, const double v2, const double lim)
Definition doubleutil.c:77

◆ parCompareParameterUnits()

int parCompareParameterUnits ( PAR * d1,
PAR * d2,
const int i,
TPCSTATUS * status )
extern

Check whether parameter units are the same in two PAR data.

Returns
0 in case of match, 1 if no match or error.
Author
Vesa Oikonen
Parameters
d1Pointer to PAR structure.
d2Pointer to PAR structure.
iParameter index [0..parNr-1] to compare; enter <0 to verify all.
statusPointer to status data; enter NULL if not needed.

Definition at line 103 of file parcomp.c.

112 {
113 int verbose=0; if(status!=NULL) verbose=status->verbose;
114 if(verbose>1) printf("%s()\n", __func__);
115
116 /* Check that required data exists */
117 if(d1==NULL || d2==NULL || d1->parNr<1 || d2->parNr<1) {
118 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_NO_DATA);
119 return 1;
120 }
121 /* If index is specified, then verify that parameter is available */
122 if(i>=0 && (i>=d1->parNr || i>=d2->parNr)) {
123 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_FAIL);
124 return 1;
125 }
126
127 /* If index is not specified, then parNr must match */
128 if(i<0 && (d1->parNr!=d2->parNr)) {
129 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_OK);
130 if(verbose>0) printf("different parameter nr.\n");
131 return(1);
132 }
133
134 /* Compare */
135 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_OK);
136 for(int pi=0; pi<d1->parNr; pi++) if(i<0 || i==pi) {
137 if(d1->n[pi].unit!=d2->n[pi].unit) {
138 if(verbose>0) {
139 printf("par1.n[%d].unit := '%s'\n", pi, unitName(d1->n[pi].unit));
140 printf("par2.n[%d].unit := '%s'\n", pi, unitName(d2->n[pi].unit));
141 }
142 return(1);
143 }
144 }
145 return(0);
146}
char * unitName(int unit_code)
Definition units.c:143

◆ parCompareTacNames()

int parCompareTacNames ( PAR * d1,
PAR * d2,
const int i,
const int casens,
TPCSTATUS * status )
extern

Check whether TAC names are the same in two PAR data.

Comparison is very strict, thus the names may need to be preprocessed if this is used for other purpose than SW testing.

Returns
0 in case of match, 1 if no match or error.
Author
Vesa Oikonen
Parameters
d1Pointer to PAR structure.
d2Pointer to PAR structure.
iParameter index [0..tacNr-1] to compare; enter <0 to verify all.
casensCase-sensitivity: 0=case does not have to match; <>0=case must match.
statusPointer to status data; enter NULL if not needed.

Definition at line 157 of file parcomp.c.

168 {
169 int verbose=0; if(status!=NULL) verbose=status->verbose;
170 if(verbose>1) printf("%s()\n", __func__);
171
172 /* Check that required data exists */
173 if(d1==NULL || d2==NULL || d1->tacNr<1 || d2->tacNr<1) {
174 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_NO_DATA);
175 return 1;
176 }
177 /* If index is specified, then verify that TAC is available */
178 if(i>=0 && (i>=d1->tacNr || i>=d2->tacNr)) {
179 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_FAIL);
180 return 1;
181 }
182
183 /* If index is not specified, then tacNr must match */
184 if(i<0 && (d1->tacNr!=d2->tacNr)) {
185 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_OK);
186 if(verbose>0) printf("different TAC nr.\n");
187 return(1);
188 }
189
190 /* Compare */
191 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_OK);
192 int vr;
193 for(int ri=0; ri<d1->tacNr; ri++) if(i<0 || i==ri) {
194 if(casens==0) vr=strcasecmp(d1->r[ri].name, d2->r[ri].name);
195 else vr=strcmp(d1->r[ri].name, d2->r[ri].name);
196 if(vr==0) continue;
197 /* No problem, if difference is '_' versus '-' */
198 if(strchr(d1->r[ri].name, '-') || strchr(d1->r[ri].name, '_')) {
199 char *buf1, *buf2;
200 buf1=strdup(d1->r[ri].name); strReplaceChar(buf1, '-', '_');
201 buf2=strdup(d2->r[ri].name); strReplaceChar(buf2, '-', '_');
202 if(verbose>100) printf("'%s' vs '%s'\n", buf1, buf2);
203 if(casens==0) vr=strcasecmp(buf1, buf2); else vr=strcmp(buf1, buf2);
204 free(buf1); free(buf2);
205 }
206 if(vr==0) continue;
207 /* No problem, if difference is '_' versus ' ' */
208 if(strchr(d1->r[ri].name, '_') || strchr(d2->r[ri].name, '_')) {
209 char *buf1, *buf2;
210 buf1=strdup(d1->r[ri].name); strReplaceChar(buf1, '_', ' ');
211 buf2=strdup(d2->r[ri].name); strReplaceChar(buf2, '_', ' ');
212 if(verbose>100) printf("'%s' vs '%s'\n", buf1, buf2);
213 if(casens==0) vr=strcasecmp(buf1, buf2); else vr=strcmp(buf1, buf2);
214 free(buf1); free(buf2);
215 }
216 if(vr==0) continue;
217 if(verbose>0) {
218 printf("par1.r[%d].name := '%s'\n", ri, d1->r[ri].name);
219 printf("par2.r[%d].name := '%s'\n", ri, d2->r[ri].name);
220 }
221 return(1);
222 }
223 return(0);
224}

◆ parCompareWSS()

int parCompareWSS ( PAR * d1,
PAR * d2,
const int ti,
const double test_abs,
const double test_rel,
TPCSTATUS * status )
extern

Check whether fit WSS values are the same in two PAR data.

Note that units are ignored here. If either absolute or relative difference is below the limit, the test is reported as passed.

See also
parCompareParameters.
Returns
0 in case of match, and >0 if no match or error.
Author
Vesa Oikonen
Parameters
d1Pointer to PAR structure.
d2Pointer to PAR structure.
tiTAC index [0..tacNr-1] to compare; enter <0 to verify all TACs.
test_absLimit for accepted absolute difference; obligatory.
test_relOptional limit for accepted relative difference |2*(x1-x2)/(x1+x2)| ; set to negative value to not test this; in case of zero mean, this test is assumed to fail, but test for absolute difference may still pass.
statusPointer to status data; enter NULL if not needed.

Definition at line 378 of file parcomp.c.

393 {
394 int verbose=0; if(status!=NULL) verbose=status->verbose;
395 if(verbose>1) printf("%s()\n", __func__);
396
397 /* Check that required data exists */
398 if(d1==NULL || d2==NULL || d1->tacNr<1 || d2->tacNr<1) {
399 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_NO_DATA);
400 return 1;
401 }
402 /* If index is specified, then verify that TAC is available */
403 if(ti>=0 && (ti>=d1->tacNr || ti>=d2->tacNr)) {
404 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_FAIL);
405 return 2;
406 }
407
408 /* If index is not specified, then tacNr must match */
409 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_OK);
410 if(ti<0 && (d1->tacNr!=d2->tacNr)) {
411 if(verbose>0) printf("different TAC nr.\n");
412 return(3);
413 }
414
415 /* Compare */
416 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_OK);
417 int tj;
418 for(tj=0; tj<d1->tacNr; tj++) if(ti<0 || tj==ti) {
419 if(doubleMatch(d1->r[tj].wss, d2->r[tj].wss, test_abs)==1)
420 continue;
421 if(test_rel>0.0 && doubleMatchRel(d1->r[tj].wss, d2->r[tj].wss, test_rel)==1)
422 continue;
423 if(verbose>0) {
424 double s=fabs(d1->r[tj].wss-d2->r[tj].wss);
425 printf("par1.r[%d].wss := %g\n", tj, d1->r[tj].wss);
426 printf("par2.r[%d].wss := %g\n", tj, d2->r[tj].wss);
427 printf("|diff| := %g\n", s);
428 printf("diff_limit := %g\n", test_abs);
429 if(test_rel>0.0) printf("rel_diff_limit := %g\n", test_rel);
430 }
431 return(10);
432 }
433 return(0);
434}
double wss
Definition tpcpar.h:72

◆ parDefaultExtension()

char * parDefaultExtension ( parformat c)
extern

Return pointer to default PAR file name extension, including the dot, based on the PAR format code.

Returns
pointer to the file name extension string.
See also
parformat, parFormatFromExtension, parFormattxt, parWrite
Author
Vesa Oikonen
Parameters
cPAR format code

Definition at line 133 of file pario.c.

136 {
137 if(c<PAR_FORMAT_UNKNOWN || c>=PAR_FORMAT_LAST) return NULL;
138 return (char*)par_fn_ext[c];
139}

◆ parDeletePar()

int parDeletePar ( PAR * par,
int pi )
extern

Deletes the specified parameter (column) from data.

Returns
Returns TPCERROR status.
See also
parDeleteTAC
Parameters
parPointer to parameter data.
piIndex of parameter [0..parNr-1] to remove.

Definition at line 478 of file par.c.

483 {
484 if(par==NULL || par->tacNr<1 || pi<0 || pi>=par->parNr) return(TPCERROR_FAIL);
485 if(pi==par->parNr-1) {par->parNr--; return(TPCERROR_OK);}
486
487 int i, j;
488
489 /* Parameter name and unit */
490 PARN parn;
491 memcpy(&parn, &par->n[pi], sizeof(PARN));
492 for(i=pi+1; i<par->parNr; i++)
493 memcpy(&par->n[i-1], &par->n[i], sizeof(PARN));
494 memcpy(&par->n[par->parNr-1], &parn, sizeof(PARN));
495
496 /* Parameter values */
497 double p, sd, cl1, cl2;
498 for(j=0; j<par->tacNr; j++) {
499 p=par->r[j].p[pi]; sd=par->r[j].sd[pi];
500 cl1=par->r[j].cl1[pi]; cl2=par->r[j].cl2[pi];
501 for(i=pi+1; i<par->parNr; i++) {
502 par->r[j].p[i-1]=par->r[j].p[i]; par->r[j].sd[i-1]=par->r[j].sd[i];
503 par->r[j].cl1[i-1]=par->r[j].cl1[i]; par->r[j].cl2[i-1]=par->r[j].cl2[i];
504 }
505 par->r[j].p[par->parNr-1]=p; par->r[j].sd[par->parNr-1]=sd;
506 par->r[j].cl1[par->parNr-1]=cl1; par->r[j].cl2[par->parNr-1]=cl2;
507 }
508
509 par->parNr--;
510 return(TPCERROR_OK);
511}

Referenced by parReadCSV(), and parReadRES().

◆ parDeleteTAC()

int parDeleteTAC ( PAR * par,
int ti )
extern

Deletes the specified TAC (row) from data.

Returns
Returns TPCERROR status.
See also
parDeletePar, parSortByName
Parameters
parPointer to parameter data.
tiIndex of TAC [0..tacNr-1] to remove.

Definition at line 519 of file par.c.

524 {
525 if(par==NULL || par->tacNr<1 || ti<0 || ti>=par->tacNr) return(TPCERROR_FAIL);
526 /* Free the memory allocated for the TAC */
527 parrFree(par->r+ti);
528 /* If the last TAC is to be deleted, then just reduce the tacNr */
529 if(ti==par->tacNr-1) {par->tacNr--; return(TPCERROR_OK);}
530 /* Otherwise move the following TACs in its place */
531 for(int i=ti+1; i<par->tacNr; i++) par->r[i-1]=par->r[i];
532 par->tacNr--; parrInit(par->r+par->tacNr);
533 return(TPCERROR_OK);
534}
void parrFree(PARR *parr)
Definition par.c:87

◆ parEnsureNames()

void parEnsureNames ( PAR * d)
extern

Ensure that PAR struct contains a name for each TAC and parameters. If not available, then index+1 is written as name.

See also
parSetStudyNr, parSortByName
Parameters
dPointer to parameter data.

Definition at line 449 of file par.c.

452 {
453 if(d==NULL || d->tacNr<1 || d->parNr<1) return;
454 /* Ensure TAC names */
455 int u, n;
456 u=d->tacNr; n=1; while((u/=10)>=1) n++;
458 for(int i=0; i<d->tacNr; i++) {
459 if(strlen(d->r[i].name)<1 || strcmp(d->r[i].name, ".")==0)
460 sprintf(d->r[i].name, "%0*d", n, 1+i);
461 }
462 /* Ensure parameter names */
463 u=d->parNr; n=1; while((u/=10)>=1) n++;
465 for(int i=0; i<d->parNr; i++) {
466 if(strlen(d->n[i].name)<1 || strcmp(d->n[i].name, ".")==0)
467 sprintf(d->n[i].name, "P%0*d", n, 1+i);
468 }
469 return;
470}
#define MAX_TACNAME_LEN
Max length of TAC ID name (not including trailing zero).
#define MAX_PARNAME_LEN
Max string length for PAR name.

◆ parExamplePerfectBolus()

int parExamplePerfectBolus ( PAR * d,
TPCSTATUS * status )
extern

Create PAR data containing function parameters for perfect bolus TAC, starting from zero and approaching zero after the peak.

Note
For use in algorithm and software tests.

Creates Gamma variate function (gammav) function with zero delay and with p[1]=1. Maximum is at 1.2 s and max value is 100 kBq/mL. Integral from 0 to infinity is 326.19382 (p[0]*p[2]^2).

Returns
enum tpcerror (TPCERROR_OK when successful).
Author
Vesa Oikonen
See also
parInit, parExampleTTACs, simBTAC
Parameters
dPointer to initiated PAR struct, which will be allocated and filled here; any previous content will be deleted.
statusPointer to status data; enter NULL if not needed

Definition at line 120 of file parexample.c.

126 {
127 int verbose=0; if(status!=NULL) verbose=status->verbose;
128 if(verbose>0) printf("%s(par)\n", __func__);
129
130 /* Check that required data exists */
131 if(d==NULL) {
132 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_NO_DATA);
133 return TPCERROR_NO_DATA;
134 }
135 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_OK);
136
137 int ret, pi, parNr;
138
139 /* Allocate memory */
140 parNr=modelParNr(modelCodeIndex("gammav"));
141 ret=parAllocate(d, parNr, 1); if(ret!=TPCERROR_OK) return(ret);
142 d->tacNr=1; d->parNr=4;
144 /* Set header fields */
145 iftPut(&d->h, "studynr", "ptac1401", 1, NULL);
146 iftPut(&d->h, "analysis_time", "2016-07-05 15:40:03", 1, NULL);
147 iftPut(&d->h, "program", "libtpcpar (c) 2016", 1, NULL);
148 iftPut(&d->h, "datafile","ptac1401.tac",1,NULL);
149 iftPut(&d->h, "weighting", "no", 1, NULL);
150 iftPut(&d->h, "unit", unitName(UNIT_KBQ_PER_ML), 1, NULL);
151 iftPut(&d->h, "timeunit", unitName(UNIT_SEC), 1, NULL);
152 /* Set parameter names */
153 pi=0; strcpy(d->n[pi].name, "A"); d->n[pi].unit=UNIT_KBQ_PER_ML;
154 pi++; strcpy(d->n[pi].name, "B"); d->n[pi].unit=UNIT_UNITLESS;
155 pi++; strcpy(d->n[pi].name, "C"); d->n[pi].unit=UNIT_PER_SEC;
156 pi++; strcpy(d->n[pi].name, "tDelay"); d->n[pi].unit=UNIT_SEC;
157 /* Set region names */
158 sprintf(d->r[0].name, "bolus");
159 /* Set regional fit options */
160 d->r[0].model=modelCodeIndex("gammav");
161 d->r[0].fitNr=parNr;
162 d->r[0].dataNr=100;
163 d->r[0].start=0.0;
164 d->r[0].end=60.0;
165 d->r[0].wss=0.0E+000;
166 /* Set parameter values and region names */
167 pi=0; d->r[0].p[pi]=226.523;
168 pi++; d->r[0].p[pi]=1.0;
169 pi++; d->r[0].p[pi]=1.2;
170 pi++; d->r[0].p[pi]=0.0;
171
172 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_OK);
173 return TPCERROR_OK;
174}
int iftPut(IFT *ift, const char *key, const char *value, char comment, TPCSTATUS *status)
Definition ift.c:63
unsigned int modelParNr(const unsigned int code)
Definition modell.c:256
unsigned int modelCodeIndex(const char *s)
Definition modell.c:237
int parAllocate(PAR *par, int parNr, int tacNr)
Definition par.c:108
int format
Definition tpcpar.h:102
IFT h
Optional (but often useful) header information.
Definition tpcpar.h:147
int fitNr
Definition tpcpar.h:58
int dataNr
Definition tpcpar.h:62
unsigned int model
Definition tpcpar.h:48
double start
Definition tpcpar.h:52
double end
Definition tpcpar.h:54
@ UNIT_PER_SEC
1/s
@ UNIT_KBQ_PER_ML
kBq/mL
@ UNIT_UNITLESS
Unitless.
@ UNIT_SEC
seconds

◆ parExampleRadiowaterBolus()

int parExampleRadiowaterBolus ( PAR * d,
TPCSTATUS * status )
extern

Create PAR data containing function parameters for bolus injection radiowater BTAC.

Note
For use in algorithm and software tests.
Returns
enum tpcerror (TPCERROR_OK when successful).
Author
Vesa Oikonen
See also
parInit, parExampleTTACs, simBTAC, parExamplePerfectBolus
Parameters
dPointer to initiated PAR structure, which will be allocated and filled here; any previous content will be deleted.
statusPointer to status data; enter NULL if not needed

Definition at line 184 of file parexample.c.

190 {
191 int verbose=0; if(status!=NULL) verbose=status->verbose;
192 if(verbose>0) printf("%s(par)\n", __func__);
193
194 /* Check that required data exists */
195 if(d==NULL) {
196 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_NO_DATA);
197 return TPCERROR_NO_DATA;
198 }
199 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_OK);
200
201 int ret, pi, parNr;
202
203 /* Allocate memory */
204 parNr=modelParNr(modelCodeIndex("fengm2"));
205 ret=parAllocate(d, parNr, 1); if(ret!=TPCERROR_OK) return(ret);
206 d->tacNr=1; d->parNr=7;
208 /* Set header fields */
209 iftPut(&d->h, "studynr", "btac1313", 1, NULL);
210 iftPut(&d->h, "analysis_time", "2025-11-14 11:46:02", 1, NULL);
211 iftPut(&d->h, "program", "libtpcpar (c) 2025", 1, NULL);
212 iftPut(&d->h, "datafile","meanaorta.tac",1,NULL);
213 iftPut(&d->h, "weighting", "no", 1, NULL);
214 iftPut(&d->h, "unit", unitName(UNIT_KBQ_PER_ML), 1, NULL);
215 iftPut(&d->h, "timeunit", unitName(UNIT_SEC), 1, NULL);
216 /* Set parameter names */
217 pi=0; strcpy(d->n[pi].name, "A1"); d->n[pi].unit=UNIT_UNITLESS;
218 pi++; strcpy(d->n[pi].name, "L1"); d->n[pi].unit=UNIT_UNITLESS;
219 pi++; strcpy(d->n[pi].name, "A2"); d->n[pi].unit=UNIT_UNITLESS;
220 pi=0; strcpy(d->n[pi].name, "L2"); d->n[pi].unit=UNIT_UNITLESS;
221 pi++; strcpy(d->n[pi].name, "A3"); d->n[pi].unit=UNIT_UNITLESS;
222 pi++; strcpy(d->n[pi].name, "L3"); d->n[pi].unit=UNIT_UNITLESS;
223 pi++; strcpy(d->n[pi].name, "tDelay"); d->n[pi].unit=UNIT_SEC;
224 /* Set region names */
225 sprintf(d->r[0].name, "bolus");
226 /* Set regional fit options */
227 d->r[0].model=modelCodeIndex("fengm2");
228 d->r[0].fitNr=parNr;
229 d->r[0].dataNr=100;
230 d->r[0].start=0.0;
231 d->r[0].end=420.0;
232 d->r[0].wss=0.0E+000;
233 /* Set parameter values and region names */
234 pi=0; d->r[0].p[pi]=66.;
235 pi++; d->r[0].p[pi]=-0.14;
236 pi++; d->r[0].p[pi]=50.;
237 pi++; d->r[0].p[pi]=-0.024;
238 pi++; d->r[0].p[pi]=40;
239 pi++; d->r[0].p[pi]=-0.001;
240 pi++; d->r[0].p[pi]=10.; // delay time
241
242 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_OK);
243 return TPCERROR_OK;
244}

◆ parExampleTTACs()

int parExampleTTACs ( PAR * d,
int type,
TPCSTATUS * status )
extern

Create PAR data containing function parameters for typical-looking PET TTACs for use in algorithm and software tests.

Creates three fengm2 functions with zero delay.

Returns
enum tpcerror (TPCERROR_OK when successful).
Author
Vesa Oikonen
See also
parInit, parExamplePerfectBolus
Parameters
dPointer to initiated PAR struct, which will be allocated and filled here; any previous content will be deleted.
typeTTAC type; currently unused
statusPointer to status data; enter NULL if not needed

Definition at line 24 of file parexample.c.

32 {
33 int verbose=0; if(status!=NULL) verbose=status->verbose;
34 if(verbose>0) printf("%s(par, %d)\n", __func__, type);
35
36 /* Check that required data exists */
37 if(d==NULL) {
38 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_NO_DATA);
39 return TPCERROR_NO_DATA;
40 }
41 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_OK);
42
43 int ret, pi, ri, parNr;
44
45 /* Allocate memory */
46 parNr=modelParNr(modelCodeIndex("fengm2"));
47 ret=parAllocate(d, parNr, 3); if(ret!=TPCERROR_OK) return(ret);
48 d->tacNr=3; d->parNr=5;
50 /* Set header fields */
51 iftPut(&d->h, "studynr", "ttac1313", 1, NULL);
52 iftPut(&d->h, "analysis_time", "2016-07-01 15:05:43", 1, NULL);
53 iftPut(&d->h, "program", "libtpcpar (c) 2016", 1, NULL);
54 iftPut(&d->h, "datafile","ttac1313.tac",1,NULL);
55 iftPut(&d->h, "weighting", "no", 1, NULL);
56 iftPut(&d->h, "unit", unitName(UNIT_KBQ_PER_ML), 1, NULL);
57 iftPut(&d->h, "timeunit", unitName(UNIT_MIN), 1, NULL);
58 /* Set parameter names */
59 pi=0; strcpy(d->n[pi].name, "A1"); d->n[pi].unit=UNIT_KBQ_PER_ML;
60 pi++; strcpy(d->n[pi].name, "L1"); d->n[pi].unit=UNIT_PER_MIN;
61 pi++; strcpy(d->n[pi].name, "A2"); d->n[pi].unit=UNIT_KBQ_PER_ML;
62 pi++; strcpy(d->n[pi].name, "L2"); d->n[pi].unit=UNIT_PER_MIN;
63 pi++; strcpy(d->n[pi].name, "A3"); d->n[pi].unit=UNIT_KBQ_PER_ML;
64 pi++; strcpy(d->n[pi].name, "L4"); d->n[pi].unit=UNIT_PER_MIN;
65 pi++; strcpy(d->n[pi].name, "tDelay"); d->n[pi].unit=UNIT_MIN;
66 /* Set regional fit options */
67 for(ri=0; ri<d->tacNr; ri++) {
68 d->r[ri].model=modelCodeIndex("fengm2");
69 d->r[ri].fitNr=parNr;
70 d->r[ri].dataNr=100;
71 d->r[ri].start=0.0;
72 d->r[ri].end=60.0;
73 d->r[ri].wss=0.0E+000;
74 }
75 /* Set parameter values and region names */
76 ri=0;
77 strcpy(d->r[ri].name, "fast");
78 pi=0; d->r[ri].p[pi]=200.;
79 pi++; d->r[ri].p[pi]=-0.8;
80 pi++; d->r[ri].p[pi]=50.;
81 pi++; d->r[ri].p[pi]=-0.2;
82 pi++; d->r[ri].p[pi]=20.;
83 pi++; d->r[ri].p[pi]=-0.005;
84 pi++; d->r[ri].p[pi]=0.0;
85 ri++;
86 strcpy(d->r[ri].name, "moder");
87 pi=0; d->r[ri].p[pi]=50.;
88 pi++; d->r[ri].p[pi]=-0.2;
89 pi++; d->r[ri].p[pi]=50.;
90 pi++; d->r[ri].p[pi]=-0.02;
91 pi++; d->r[ri].p[pi]=3.;
92 pi++; d->r[ri].p[pi]=-0.001;
93 pi++; d->r[ri].p[pi]=0.0;
94 ri++;
95 strcpy(d->r[ri].name, "slow");
96 pi=0; d->r[ri].p[pi]=5.;
97 pi++; d->r[ri].p[pi]=-0.05;
98 pi++; d->r[ri].p[pi]=70.;
99 pi++; d->r[ri].p[pi]=-0.001;
100 pi++; d->r[ri].p[pi]=30.;
101 pi++; d->r[ri].p[pi]=-0.0005;
102 pi++; d->r[ri].p[pi]=0.0;
103
104 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_OK);
105 return TPCERROR_OK;
106}
@ UNIT_MIN
minutes
@ UNIT_PER_MIN
1/min

◆ parFindParameter()

int parFindParameter ( PAR * d,
const char * par_name )
extern

Searches PAR structure for the given parameter name (case insensitive).

Returns
the index [0..parNr-1] of the parameter, or <0 if not found.
Author
Vesa Oikonen
See also
parGetParameter, parSelectParameters
Parameters
dPointer to PAR structure.
par_nameName of the parameter. Comparison is case-insensitive, but otherwise strict match is required.

Definition at line 219 of file parselect.c.

225 {
226 /* Check that required data exists */
227 if(d==NULL || d->parNr<1 || par_name==NULL) return(-1);
228 /* Find the name */
229 for(int i=0; i<d->parNr; i++) {
230 if(strcasecmp(par_name, d->n[i].name)==0) return(i);
231 }
232 return(-1);
233}

◆ parFormatFromExtension()

int parFormatFromExtension ( const char * s)
extern

Identify the PAR file format from the extension of file name.

Returns
enum parformat, or 0 (enum PAR_FORMAT_UNKNOWN) if not identified.
Author
Vesa Oikonen
See also
parFormattxt, parformat, parFormatIdentify, parWrite
Parameters
sPointer to file name with or without path; mere extension is not accepted here. For example /path/filename.res or filename.fit.bak are accepted.

Definition at line 102 of file pario.c.

106 {
107 if(s==NULL || strlen(s)<1) return PAR_FORMAT_UNKNOWN;
108 /* Get pointer to the extensions */
109 char *cptr=filenameGetExtensions(s);
110 if(cptr==NULL) return PAR_FORMAT_UNKNOWN;
111 /* Try to find some known extensions */
112 if(strcasestr(cptr, ".res")) return PAR_FORMAT_RES;
113 if(strcasestr(cptr, ".fit")) return PAR_FORMAT_FIT;
114 if(strcasestr(cptr, ".ift")) return PAR_FORMAT_IFT;
115 if(strcasestr(cptr, ".csv")) return PAR_FORMAT_CSV_UK;
116 if(strcasestr(cptr, ".tsv")) return PAR_FORMAT_TSV_UK;
117 if(strcasestr(cptr, ".txt")) return PAR_FORMAT_TSV_UK;
118 if(strcasestr(cptr, ".par")) return PAR_FORMAT_TSV_UK;
119 if(strcasestr(cptr, ".lim")) return PAR_FORMAT_TSV_UK;
120 if(strcasestr(cptr, ".dat")) return PAR_FORMAT_TSV_UK;
121 if(strcasestr(cptr, ".xml")) return PAR_FORMAT_XML;
122 if(strcasestr(cptr, ".htm")) return PAR_FORMAT_HTML;
123 return PAR_FORMAT_UNKNOWN;
124}
char * filenameGetExtensions(const char *s)
Get all extensions of a file name.
Definition filename.c:203
char * strcasestr(const char *haystack, const char *needle)
Definition stringext.c:155

◆ parFormatIdentify()

int parFormatIdentify ( const char * s)
extern

Identify the string representations of the PAR file format.

Returns
enum parformat, or 0 (enum PAR_FORMAT_UNKNOWN) if not identified.
Author
Vesa Oikonen
See also
parFormattxt, parformat, parFormatFromExtension, parRead
Parameters
sPAR format as a string.

Definition at line 74 of file pario.c.

77 {
78 if(s==NULL || strlen(s)<1) return PAR_FORMAT_UNKNOWN;
79 /* Try if string can be found directly in the table */
80 for(int i=0; i<PAR_FORMAT_LAST; i++) {
81 if(strcasecmp(par_format[i], s)==0) return i;
82 }
83 /* Format string is not following TPC standard, lets try something else */
84 if( strcasecmp(s, "dat")==0) return PAR_FORMAT_TSV_UK;
85 else if(strcasecmp(s, "txt")==0) return PAR_FORMAT_TSV_UK;
86 else if(strcasecmp(s, "par")==0) return PAR_FORMAT_CSV_UK;
87 else if(strcasecmp(s, "lim")==0) return PAR_FORMAT_TSV_UK;
88 else if(strcasecmp(s, "htm")==0) return PAR_FORMAT_HTML;
89 else if(strcasecmp(s, "csv")==0) return PAR_FORMAT_CSV_UK;
90 else if(strcasecmp(s, "tsv")==0) return PAR_FORMAT_TSV_UK;
91
92 return PAR_FORMAT_UNKNOWN;
93}

◆ parFormattxt()

char * parFormattxt ( parformat c)
extern

Return pointer to PAR file format description with the format code.

Returns
pointer to the PAR file format string.
See also
parformat, parFormatIdentify, parFormatFromExtension
Author
Vesa Oikonen
Parameters
cPAR format code.

Definition at line 59 of file pario.c.

62 {
63 if(c<PAR_FORMAT_UNKNOWN || c>=PAR_FORMAT_LAST) return NULL;
64 return (char*)par_format[c];
65}

Referenced by parRead(), parWrite(), and parWriteCSV().

◆ parFree()

void parFree ( PAR * par)
extern

Free memory allocated for PAR. All data is cleared.

See also
parInit, parAllocate, parRead
Parameters
parPointer to PAR struct

Definition at line 75 of file par.c.

78 {
79 if(par==NULL) return;
80 for(int i=0; i<par->_tacNr; i++) parrFree(par->r+i);
81 free(par->r);
82 free(par->n);
83 iftFree(&par->h);
84 parInit(par);
85}
void iftFree(IFT *ift)
Definition ift.c:37
void parInit(PAR *par)
Definition par.c:25

Referenced by parAllocate(), parFromIFT(), parRead(), parReadCSV(), parReadFIT(), and parReadRES().

◆ parFromIFT()

int parFromIFT ( PAR * par,
IFT * ift,
TPCSTATUS * status )
extern

Copy parameters data in IFT into PAR struct. IFT contents must be in specific format and order.

Returns
enum tpcerror (TPCERROR_OK when successful).
Author
Vesa Oikonen
Parameters
parPointer to initiated target PAR struct; any previous contents are deleted
iftPointer to source IFT struct, contents of which are to be copied
statusPointer to status data; enter NULL if not needed

Definition at line 207 of file parift.c.

215 {
216 int verbose=0; if(status!=NULL) verbose=status->verbose;
217 if(par==NULL) {
218 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_FAIL);
219 return TPCERROR_FAIL;
220 }
221 if(verbose>0) printf("%s()\n", __func__);
222 if(ift==NULL || ift->keyNr<1) {
223 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_NO_DATA);
224 return TPCERROR_NO_DATA;
225 }
226
227 /* Verify that IFT contains results */
228 if(strcasecmp(ift->item[0].key, "content") ||
229 strcasecmp(ift->item[0].value, "parameters")
230 ) {
231 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_UNSUPPORTED);
233 }
234
235 int ret, parNr, tacNr;
236 /* Read the nr of parameters */
237 if(iftGetInt(ift, iftFindKey(ift, "par_nr", 0), &parNr)!=0 || parNr<1) {
238 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_UNSUPPORTED);
240 }
241 if(verbose>5) printf("parNr := %d\n", parNr);
242 /* Read the nr of parameter sets (tacs) */
243 tacNr=iftFindNrOfKeys(ift, "parameter-set");
244 if(tacNr<1) {
245 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_UNSUPPORTED);
247 }
248 if(verbose>5) printf("tacNr := %d\n", tacNr);
249
250 /* Allocate memory for PAR */
251 parFree(par);
252 ret=parAllocate(par, parNr, tacNr);
253 if(ret!=TPCERROR_OK) {
254 statusSet(status, __func__, __FILE__, __LINE__, ret);
255 return ret;
256 }
257 par->parNr=parNr; par->tacNr=tacNr;
258
259 /* Read header contents */
260 for(int i=1, ret=0; i<ift->keyNr && ret==TPCERROR_OK; i++) {
261 /* not if value is missing */
262 if(ift->item[i].value==NULL || strlen(ift->item[i].value)<1) continue;
263 /* not if key is missing */
264 if(ift->item[i].key==NULL || strlen(ift->item[i].key)<1) continue;
265 /* end of header? */
266 if(strcasecmp(ift->item[i].key, "parameter-set")==0) break;
267 /* not needed */
268 if(strcasecmp(ift->item[i].key, "par_nr")==0) continue;
269 if(strcasecmp(ift->item[i].key, "format")==0) continue;
270 if(strcasecmp(ift->item[i].key, "tac_nr")==0) continue;
271 /* ok to copy */
272 ret=iftPut(&par->h, ift->item[i].key, ift->item[i].value, 1, NULL);
273 }
274 if(ret!=TPCERROR_OK) {
275 statusSet(status, __func__, __FILE__, __LINE__, ret);
276 return ret;
277 }
278
279 /* Read parameter values */
280 int i, pi=0, ri=0; ret=0;
281 char tmp[128];
282 i=iftFindKey(ift, "parameter-set", 0);
283 for(i++; i<ift->keyNr && ret==TPCERROR_OK; i++) {
284 if(verbose>60)
285 printf("i=%d key='%s' value='%s'\n",
286 i, ift->item[i].key, ift->item[i].value);
287 /* new parameter-set? */
288 if(strcasecmp(ift->item[i].key, "parameter-set")==0) {
289 ri++; pi=0; if(ri<par->tacNr) continue; else break;}
290 /* parameter set info? */
291 if(strcasecmp(ift->item[i].key, "tac_name")==0) {
292 strncpy(par->r[ri].name, ift->item[i].value, MAX_TACNAME_LEN);
293 par->r[ri].name[MAX_TACNAME_LEN]='\0';
294 continue;
295 }
296 if(strcasecmp(ift->item[i].key, "wss")==0) {
297 if(iftGetDouble(ift, i, &par->r[ri].wss)) {ret++; break;}
298 continue;
299 }
300 if(strcasecmp(ift->item[i].key, "model")==0) {
301 if(iftGetUInt(ift, i, &par->r[ri].model)) {ret++; break;}
302 continue;
303 }
304 if(strcasecmp(ift->item[i].key, "data_nr")==0) {
305 if(iftGetInt(ift, i, &par->r[ri].dataNr)) {ret++; break;}
306 continue;
307 }
308 if(strcasecmp(ift->item[i].key, "fit_nr")==0) {
309 if(iftGetInt(ift, i, &par->r[ri].fitNr)) {ret++; break;}
310 continue;
311 }
312 if(strcasecmp(ift->item[i].key, "fit_start")==0) {
313 if(iftGetDouble(ift, i, &par->r[ri].start)) {ret++; break;}
314 continue;
315 }
316 if(strcasecmp(ift->item[i].key, "fit_end")==0) {
317 if(iftGetDouble(ift, i, &par->r[ri].end)) {ret++; break;}
318 continue;
319 }
320 /* SD or CL ? */
321 if(strcasecmp(ift->item[i].key, "SD")==0) {
322 if(iftGetDouble(ift, i, &par->r[ri].sd[pi])) {ret++; break;}
323 continue;
324 }
325 if(strcasecmp(ift->item[i].key, "95%CL1")==0) {
326 if(iftGetDouble(ift, i, &par->r[ri].cl1[pi])) {ret++; break;}
327 continue;
328 }
329 if(strcasecmp(ift->item[i].key, "95%CL2")==0) {
330 if(iftGetDouble(ift, i, &par->r[ri].cl2[pi])) {ret++; break;}
331 continue;
332 }
333 /* Ok this should be parameter */
334 if(pi>=par->parNr) {ret++; break;}
335 strncpy(par->n[pi].name, ift->item[i].key, MAX_PARNAME_LEN);
336 par->n[pi].name[MAX_PARNAME_LEN]='\0';
337 if(iftGetDouble(ift, i, &par->r[ri].p[pi])) {ret++; break;}
338 /* next token, if one exists, should be the unit */
339 if(strTokenNr(ift->item[i].value, " \t")==2) {
340 if(strTokenNCpy(ift->item[i].value, " \t", 2, tmp, 64)>0)
341 par->n[pi].unit=unitIdentify(tmp);
342 }
343 pi++;
344 }
345 if(ret!=TPCERROR_OK) {
346 statusSet(status, __func__, __FILE__, __LINE__, ret);
347 return ret;
348 }
349
350 /* Set format in struct */
352
353 /* Quit */
354 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_OK);
355 return(TPCERROR_OK);
356}
int iftFindNrOfKeys(IFT *ift, const char *key)
Definition iftfind.c:142
int iftFindKey(IFT *ift, const char *key, int start_index)
Definition iftfind.c:30
int iftGetUInt(IFT *ift, int index, unsigned int *v)
Definition iftget.c:101
int iftGetDouble(IFT *ift, int index, double *v)
Definition iftget.c:52
int iftGetInt(IFT *ift, int index, int *v)
Definition iftget.c:76
int strTokenNr(const char *s1, const char *s2)
Definition stringext.c:25
int strTokenNCpy(const char *s1, const char *s2, int i, char *s3, int count)
Definition stringext.c:53
char * value
Definition tpcift.h:37
char * key
Definition tpcift.h:32
IFT_ITEM * item
Definition tpcift.h:57
int keyNr
Definition tpcift.h:47
@ TPCERROR_UNSUPPORTED
Unsupported file type.
int unitIdentify(const char *s)
Definition units.c:162

Referenced by parRead().

◆ parGetParameter()

double parGetParameter ( PAR * d,
const char * par_name,
const int ti )
extern

Searches PAR structure for the given parameter name (case insensitive).

Returns
the value of the parameter for specified TAC, or NaN if not found.
Author
Vesa Oikonen
See also
parGetParameterUnit, parFindParameter, parSelectParameters
Parameters
dPointer to PAR structure.
par_nameName of the parameter. Comparison is case-insensitive, but otherwise strict match is required.
tiTAC index [0..tacNr-1].

Definition at line 242 of file parselect.c.

250 {
251 double v=nan("");
252 /* Check that required data exists */
253 if(d==NULL || d->parNr<1 || ti<0 || ti>=d->tacNr || par_name==NULL) return(v);
254 /* Find the name */
255 for(int pi=0; pi<d->parNr; pi++)
256 if(strcasecmp(par_name, d->n[pi].name)==0) v=d->r[ti].p[pi];
257 return(v);
258}

◆ parGetParameterUnit()

int parGetParameterUnit ( PAR * d,
const char * par_name )
extern

Searches PAR structure for the given parameter name (case insensitive).

Returns
the enum of the unit of the parameter, or UNIT_UNKNOWN if not found.
Author
Vesa Oikonen
See also
parFindParameter, parGetParameter
Parameters
dPointer to PAR structure.
par_nameName of the parameter. Comparison is case-insensitive, but otherwise strict match is required.

Definition at line 267 of file parselect.c.

272 {
273 int u=UNIT_UNKNOWN;
274 /* Check that required data exists */
275 if(d==NULL || d->parNr<1 || par_name==NULL) return(u);
276 /* Find the name */
277 for(int pi=0; pi<d->parNr; pi++) if(strcasecmp(par_name, d->n[pi].name)==0) u=d->n[pi].unit;
278 return(u);
279}
@ UNIT_UNKNOWN
Unknown unit.

◆ parInit()

void parInit ( PAR * par)
extern

Initiate the PAR struct before any use.

Author
Vesa Oikonen
See also
parrInit, parnInit, parFree, parAllocate, parRead
Parameters
parPointer to PAR

Definition at line 25 of file par.c.

28 {
29 if(par==NULL) return;
31 par->tacNr=par->_tacNr=0;
32 par->parNr=par->_parNr=0;
33 par->n=NULL;
34 par->r=NULL;
35 iftInit(&par->h);
36}
void iftInit(IFT *ift)
Definition ift.c:21

Referenced by parFree().

◆ parIsDataNr()

int parIsDataNr ( PAR * par)
extern

Check if any of parameter sets has dataNr specified.

See also
parIsFitNr, parIsWSS
Returns
Returns 0 if not, 1 if the same in each set, and 2 if variable.
Parameters
parPointer to parameter data

Definition at line 362 of file par.c.

365 {
366 if(par==NULL || par->tacNr<1) return(0);
367 int ri, ret=0;
368 for(ri=0; ri<par->tacNr; ri++) {
369 if(ret==0 && par->r[ri].dataNr>0) ret=1;
370 if(ri>0 && par->r[ri].dataNr!=par->r[ri-1].dataNr) {ret=2; break;}
371 }
372 return(ret);
373}

Referenced by parToIFT(), parWriteCSV(), and parWriteXML().

◆ parIsFitNr()

int parIsFitNr ( PAR * par)
extern

Check if any of parameter sets has fitNr specified.

See also
parIsDataNr, parIsWSS
Returns
Returns 0 if not, 1 if the same in each set, and 2 if variable.
Parameters
parPointer to parameter data.

Definition at line 343 of file par.c.

346 {
347 if(par==NULL || par->tacNr<1) return(0);
348 int ri, ret=0;
349 for(ri=0; ri<par->tacNr; ri++) {
350 if(ret==0 && par->r[ri].fitNr>0) ret=1;
351 if(ri>0 && par->r[ri].fitNr!=par->r[ri-1].fitNr) {ret=2; break;}
352 }
353 return(ret);
354}

Referenced by parToIFT(), parWriteCSV(), and parWriteXML().

◆ parIsFitRange()

int parIsFitRange ( PAR * par)
extern

Check if any of parameter sets has fit range specified.

See also
parIsFitNr, parIsDataNr, parIsWSS
Returns
Returns 0 if not, 1 if the same in each set, and 2 if variable.
Parameters
parPointer to parameter data.

Definition at line 267 of file par.c.

270 {
271 if(par==NULL || par->tacNr<1) return(0);
272 int ri, ret=0;
273 for(ri=0; ri<par->tacNr; ri++) {
274 if(!isnan(par->r[ri].start) || !isnan(par->r[ri].end)) ret=1;
275 if(ri==0 || ret==0) continue;
276 if(!doubleMatch(par->r[ri].start, par->r[0].start, 0.01)) {ret=2; break;}
277 if(!doubleMatch(par->r[ri].end, par->r[0].end, 0.01)) {ret=2; break;}
278 }
279 return(ret);
280}

Referenced by parToIFT(), parWriteCSV(), and parWriteXML().

◆ parIsModel()

int parIsModel ( PAR * par)
extern

Check if any of parameter sets has model id specified.

See also
parIsFitNr, parIsWSS, parRead, parIsOptcrit
Returns
Returns 0 if not, 1 if the same in each set, and 2 if variable.
Parameters
parPointer to parameter data.

Definition at line 288 of file par.c.

291 {
292 if(par==NULL || par->tacNr<1) return(0);
293 int ri, ret=0;
294 for(ri=0; ri<par->tacNr; ri++) {
295 if(ret==0 && par->r[ri].model>0) ret=1;
296 if(ri>0 && par->r[ri].model!=par->r[ri-1].model) {ret=2; break;}
297 }
298 return(ret);
299}

Referenced by parToIFT(), parWriteCSV(), and parWriteXML().

◆ parIsOptcrit()

char * parIsOptcrit ( PAR * par)
extern

Check if PAR data contains optimality criterion.

See also
parIsModel, parIsWSS, studynrFromFilename
Returns
Returns pointer to optimization criterion name, or NULL if not found.
Parameters
parPointer to parameter data.

Definition at line 381 of file par.c.

384 {
385 if(par==NULL || par->h.keyNr<1) return((char*)NULL);
386 int li=iftFindKey(&par->h, "optimality_criterion", 0);
387 if(li<0) li=iftFindKey(&par->h, "optcrit", 0);
388 if(li<0) return((char*)NULL);
389 if(par->h.item[li].value==NULL || strlen(par->h.item[li].value)<1) return((char*)NULL);
390 return(par->h.item[li].value);
391}

◆ parIsStudyNr()

char * parIsStudyNr ( PAR * par)
extern

Check if PAR data contains study number.

See also
parSetStudyNr, parIsModel, parIsWSS, studynrFromFilename, parEnsureNames
Returns
Returns pointer to study number, or NULL if not found.
Parameters
parPointer to parameter data.

Definition at line 399 of file par.c.

402 {
403 if(par==NULL || par->h.keyNr<1) return((char*)NULL);
404 int li=iftFindKey(&par->h, "studynr", 0);
405 if(li<0) li=iftFindKey(&par->h, "study_number", 0);
406 if(li<0) return((char*)NULL);
407 if(par->h.item[li].value==NULL || strlen(par->h.item[li].value)<1) return((char*)NULL);
408 return(par->h.item[li].value);
409}

◆ parIsWSS()

int parIsWSS ( PAR * par)
extern

Check if any of parameter sets has WSS.

See also
parIsFitNr, parIsDataNr, parCLWithPar, parSDWithPar, parIsOptcrit
Returns
Returns 1 if WSS exists, and 0 if not (or in case of an error).
Parameters
parPointer to parameter data.

Definition at line 252 of file par.c.

255 {
256 if(par==NULL || par->tacNr<1) return(0);
257 for(int ri=0; ri<par->tacNr; ri++) if(!isnan(par->r[ri].wss)) return(1);
258 return(0);
259}

Referenced by parWriteCSV(), parWriteRES(), and parWriteXML().

◆ parListLimits()

void parListLimits ( PAR * par,
FILE * fp )
extern

List parameter limits in PAR structure.

See also
parWriteLimits, parWrite, parFree
Parameters
parPointer to PAR structure, from which the limits are printed.
fpFile pointer for the output; usually stdout.

Definition at line 406 of file pario.c.

411 {
412 //printf("%s()\n", __func__);
413 if(par==NULL || par->parNr<1) {fprintf(fp, "No parameter limits.\n"); return;}
414
415 fprintf(fp, "Parameter limits:\n");
416 for(int i=0; i<par->parNr; i++) {
417 if(strlen(par->n[i].name)>0) fprintf(fp, "%s", par->n[i].name);
418 else fprintf(fp, "p%d", 1+i);
419 fprintf(fp, "\t%g\t%g\n", par->n[i].lim1, par->n[i].lim2);
420 }
421 fprintf(fp, "\n");
422 return;
423}

◆ parnInit()

void parnInit ( PARN * parn)
extern

Initiate the PARN struct before any use.

Author
Vesa Oikonen
See also
parInit, parrInit
Parameters
parnPointer to PARN

Definition at line 59 of file par.c.

62 {
63 if(parn==NULL) return;
64 parn->name[0]='\0';
65 parn->unit=UNIT_UNKNOWN;
66 parn->lim1=parn->lim2=parn->tol=nan("");
67 parn->sw=0;
68}
char sw
Definition tpcpar.h:94

Referenced by parAllocate(), and parAllocateMore().

◆ parPrintType()

int parPrintType ( PAR * par,
int parIndex )
extern

Determine whether the parameter should be printed as integer (0), float (1), or exponential (2).

Returns
Returns the code, or <0 in case of an error.
Parameters
parPointer to the PAR structure.
parIndexIndex of the parameter to test.

Definition at line 584 of file parres.c.

589 {
590 int vi, partype=0;
591 double x, m=0.0, pint;
592
593 if(par==NULL || par->tacNr<1 || parIndex<0 || parIndex>=par->tacNr)
594 return(-1);
595 for(vi=0; vi<par->tacNr; vi++) {
596 x=par->r[vi].p[parIndex];
597 if(modf(x, &pint)!=0.0) partype=1;
598 x=fabs(x); if(x>m) m=x;
599 }
600 if(partype==1 && (m>=10.0 || m<0.1)) partype=2;
601 return(partype);
602}

Referenced by parWriteRES().

◆ parrAllocate()

int parrAllocate ( PARR * parr,
int parNr )
extern

Allocate memory for PARR data. Any previous contents are deleted.

See also
parrInit, parrFree, parAllocate
Returns
Returns TPCERROR status.
Parameters
parrPointer to initiated PARR struct data; any old contents are deleted.
parNrNr of parameters to allocate.

Definition at line 150 of file par.c.

155 {
156 if(parr==NULL) return TPCERROR_FAIL;
157 /* Delete any previous contents */
158 parrFree(parr);
159 /* If no memory is requested, then just return */
160 if(parNr<1) return TPCERROR_OK;
161
162 /* Allocate memory for PARR data */
163 parr->p=malloc(parNr*sizeof(double));
164 parr->sd=malloc(parNr*sizeof(double));
165 parr->cl1=malloc(parNr*sizeof(double));
166 parr->cl2=malloc(parNr*sizeof(double));
167 if(parr->p==NULL || parr->sd==NULL || parr->cl1==NULL || parr->cl2==NULL)
169 /* Initiate values to NaNs */
170 for(int i=0; i<parNr; i++)
171 parr->p[i]=parr->sd[i]=parr->cl1[i]=parr->cl2[i]=nan("");
172
173 return TPCERROR_OK;
174}

Referenced by parAllocate(), and parAllocateMore().

◆ parRead()

int parRead ( PAR * par,
const char * fname,
TPCSTATUS * status )
extern

Read parameter file contents into PAR data structure. This function reads RES and FIT format, and some CSV formats.

Author
Vesa Oikonen
Returns
code tpcerror, TPCERROR_OK (0) when successful.
See also
parWrite, parInit, parFree
Parameters
parPointer to initiated PAR struct where parameter data will be written; any old content is deleted. Call parInit() before first use.
fnamePointer to the file name; this string is not modified.
statusPointer to status data; enter NULL if not needed.

Definition at line 232 of file pario.c.

240 {
241 int verbose=0; if(status!=NULL) verbose=status->verbose;
242 if(fname==NULL || strlen(fname)<1 || par==NULL) {
243 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_FAIL);
244 return TPCERROR_FAIL;
245 }
246 if(verbose>1) {printf("%s(%s)\n", __func__, fname); fflush(stdout);}
247 int format=PAR_FORMAT_UNKNOWN;
248
249 /* Delete any previous data */
250 parFree(par);
251
252 /* Try to read the file as CSV file */
253 if(verbose>1) {printf("opening file\n"); fflush(stdout);}
254 FILE *fp;
255 fp=fopen(fname, "r");
256 if(fp==NULL) {
257 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_CANNOT_OPEN);
259 }
260 int ret;
261 CSV csv; csvInit(&csv);
262 ret=csvRead(&csv, fp, status);
263 fclose(fp);
264 if(ret!=TPCERROR_OK) {
265 statusSet(status, __func__, __FILE__, __LINE__, ret);
266 csvFree(&csv); return ret;
267 }
268 if(verbose>20) {
269 printf("\n --- CSV contents ---\n");
270 csvWrite(&csv, 0, stdout, status);
271 }
272
273 /* Try to identify file format from a magic number in the start */
274 if(verbose>1) {printf("checking for magic number\n"); fflush(stdout);}
275 if(strncasecmp(csv.c[0].content, "FIT1", 4)==0) {
276 format=PAR_FORMAT_FIT;
277 } else if(strncasecmp(csv.c[0].content, "<?xml version", 5)==0) {
278 format=PAR_FORMAT_XML;
279 } else if(strcasecmp(csv.c[0].content, "Parameters")==0) {
280 /* now determine the field and decimal separators */
281 if(csv.separator==';') format=PAR_FORMAT_CSV_INT;
282 else if(csv.separator==',') format=PAR_FORMAT_CSV_UK;
283 else if(csv.separator=='\t' || csv.separator==' ') {
284 // either UK or INT, we'll decide it later
285 format=PAR_FORMAT_TSV_UK;
286 }
287 }
288 if(verbose>3) {printf("format := %s\n", parFormattxt(format)); fflush(stdout);}
289
290 /* If identified already, then read data and return */
291 if(format!=PAR_FORMAT_UNKNOWN) {
292 if(verbose>1) {printf("format := %s\n", parFormattxt(format)); fflush(stdout);}
293 IFT hdr; iftInit(&hdr);
294 /* These formats may contain additional header information in comment
295 lines; read headers from those into TAC struct for further processing */
296 if(format==PAR_FORMAT_CSV_UK || format==PAR_FORMAT_CSV_INT ||
297 format==PAR_FORMAT_TSV_UK || format==PAR_FORMAT_TSV_INT
298 ) {
299 fp=fopen(fname, "r");
300 if(fp!=NULL) {
301 if(iftRead(&hdr, fp, 1, 2, status)!=TPCERROR_OK) iftFree(&hdr);
302 fclose(fp);
303 }
304 /* Header may not exist, therefore do not worry about errors here */
305 }
306 /* FIT (and RES) formats are easier to read partially from IFT struct */
307 if(format==PAR_FORMAT_FIT) {
308 fp=fopen(fname, "r");
309 if(fp==NULL) ret=TPCERROR_CANNOT_OPEN; // these formats must have header
310 else {
311 ret=iftRead(&hdr, fp, 0, 1, status);
312 fclose(fp);
313 }
314 if(ret!=TPCERROR_OK) {
315 csvFree(&csv); iftFree(&hdr);
316 statusSet(status, __func__, __FILE__, __LINE__, ret);
317 return ret;
318 }
319 }
320 switch(format) {
321 case PAR_FORMAT_FIT:
322 ret=parReadFIT(par, &csv, &hdr, status);
323 break;
325 /* __attribute__((fallthrough)); */
327 /* __attribute__((fallthrough)); */
329 /* __attribute__((fallthrough)); */
331 /* __attribute__((fallthrough)); */
332 default:
333 ret=parReadCSV(par, &csv, &hdr, status);
334 break;
335 }
336 csvFree(&csv); iftFree(&hdr);
337 if(ret!=TPCERROR_OK) {
338 statusSet(status, __func__, __FILE__, __LINE__, ret);
339 parFree(par); return ret;
340 }
341 /* Set study number, if not yet set, based on file name */
342 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_OK);
343 return TPCERROR_OK;
344 }
345
346 /* The rest of the formats are a bit more difficult to identify */
347
348 /* Try to read as IFT */
349 if(verbose>3) {printf("trying IFT format\n"); fflush(stdout);}
350 fp=fopen(fname, "r");
351 if(fp!=NULL) {
352 IFT hdr; iftInit(&hdr);
353 iftRead(&hdr, fp, 1, 1, status); fclose(fp);
354 if(hdr.keyNr>0) {
355 if(!strcasecmp(hdr.item[0].key, "content") && !strcasecmp(hdr.item[0].value, "parameters"))
356 format=PAR_FORMAT_IFT;
357 }
358 if(format==PAR_FORMAT_IFT) {
359 if(verbose>1) printf("format := %s\n", parFormattxt(format));
360 ret=parFromIFT(par, &hdr, status);
361 csvFree(&csv); iftFree(&hdr);
362 if(ret!=TPCERROR_OK) {parFree(par); return ret;}
363 /* Set study number, if not yet set, based on file name */
364 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_OK);
365 return TPCERROR_OK;
366 }
367 if(verbose>3) printf("not IFT\n");
368 iftFree(&hdr);
369 }
370
371 /* Try to read as RES file */
372 if(verbose>3) {printf("trying RES format\n"); fflush(stdout);}
373 /* Header is obligatory, read that to IFT */
374 fp=fopen(fname, "r");
375 if(fp!=NULL) {
376 IFT hdr; iftInit(&hdr);
377 ret=iftRead(&hdr, fp, 0, 1, status); fclose(fp);
378 if(ret!=TPCERROR_OK) {
379 csvFree(&csv); iftFree(&hdr);
380 statusSet(status, __func__, __FILE__, __LINE__, ret);
381 return ret;
382 }
383 ret=parReadRES(par, &csv, &hdr, status);
384 iftFree(&hdr);
385 if(ret==TPCERROR_OK) {
386 csvFree(&csv);
387 /* Set study number, if not yet set, based on file name */
388 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_OK);
389 return TPCERROR_OK;
390 }
391 }
392
393 /* Currently any other format cannot be read */
394 if(verbose>3) {printf("currently not supported format\n"); fflush(stdout);}
395 csvFree(&csv);
396 parFree(par);
397 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_UNSUPPORTED);
399}
void csvInit(CSV *csv)
Definition csv.c:22
void csvFree(CSV *csv)
Definition csv.c:38
int csvRead(CSV *csv, FILE *fp, TPCSTATUS *status)
Definition csvio.c:124
int csvWrite(CSV *csv, int regular, FILE *fp, TPCSTATUS *status)
Definition csvio.c:52
int iftRead(IFT *ift, FILE *fp, int is_key_required, int is_comment_accepted, TPCSTATUS *status)
Definition iftio.c:130
int parReadCSV(PAR *par, CSV *csv, IFT *hdr, TPCSTATUS *status)
Definition parcsv.c:221
int parReadFIT(PAR *par, CSV *csv, IFT *ift, TPCSTATUS *status)
Definition parfit.c:131
int parFromIFT(PAR *par, IFT *ift, TPCSTATUS *status)
Definition parift.c:207
char * parFormattxt(parformat c)
Definition pario.c:59
int parReadRES(PAR *par, CSV *csv, IFT *ift, TPCSTATUS *status)
Definition parres.c:268
char * content
Definition tpccsv.h:30
Definition tpccsv.h:36
char separator
Definition tpccsv.h:49
CSV_item * c
Definition tpccsv.h:38
Definition tpcift.h:43
@ TPCERROR_CANNOT_OPEN
Cannot open file.

◆ parReadCSV()

int parReadCSV ( PAR * par,
CSV * csv,
IFT * hdr,
TPCSTATUS * status )
extern

Read parameter data into PAR structure.

Returns
enum tpcerror (TPCERROR_OK when successful).
Author
Vesa Oikonen
See also
parWriteCSV, parRead, parFormatIdentify
Parameters
parPointer to target PAR structure.
csvPointer to CSV from which data is read.
hdrPointer to possible header data, which, if available, is processed and copied to PAR too; enter NULL if not available.
statusPointer to status data; enter NULL if not needed.

Definition at line 221 of file parcsv.c.

231 {
232 int verbose=0; if(status!=NULL) verbose=status->verbose;
233 if(par==NULL) {
234 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_FAIL);
235 return TPCERROR_FAIL;
236 }
237
238 parFree(par);
239 if(csv==NULL || csv->row_nr<1 || csv->col_nr<1) {
240 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_NO_DATA);
241 return TPCERROR_NO_DATA;
242 }
243 if(verbose>0) printf("%s()\n", __func__);
244
245 /* Check that this is valid CSV or TSV parameter file */
246 if(strcasecmp(csv->c[0].content, "Parameters")) {
247 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_UNSUPPORTED);
249 }
250
251 /* Remove initial and trailing space characters from CSV.
252 Those may exist in manually made files. */
253 csvCleanSpaces(csv);
254
255 /* Calculate the number of parameters from the title line */
256 int colNr=1, parNr=0;
257 for(int i=1; i<csv->nr; i++) {
258 if(csv->c[i].row==0) { // title line
259 colNr++;
260 /* do not count special columns */
261 if(strncasecmp(csv->c[i].content, "SD", 2)==0) continue;
262 if(strncasecmp(csv->c[i].content, "95%CL", 5)==0) continue;
263 if(strcasecmp(csv->c[i].content, "WSS")==0) continue;
264 if(strcasecmp(csv->c[i].content, "Model")==0) continue;
265 if(strcasecmp(csv->c[i].content, "Start[min]")==0) continue;
266 if(strcasecmp(csv->c[i].content, "End[min]")==0) continue;
267 if(strcasecmp(csv->c[i].content, "dataNr")==0) continue;
268 if(strcasecmp(csv->c[i].content, "fitNr")==0) continue;
269 parNr++;
270 } else break; // this is not more in title line
271 }
272 if(parNr<1 || csv->row_nr<2) {
273 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_INVALID_FORMAT);
275 }
276 if(verbose>2) printf(" parNr := %d\n colNr := %d\n", parNr, colNr);
277
278 /* Allocate memory for parameters */
279 int ret;
280 ret=parAllocate(par, parNr, csv->row_nr-1);
281 if(ret!=TPCERROR_OK) {statusSet(status, __func__, __FILE__, __LINE__, ret); return ret;}
282 par->parNr=parNr; par->tacNr=csv->row_nr-1;
283
284
285 /* Read CSV contents into PAR struct */
286 int decimal_comma=-1;
287 ret=0; if(csv->separator==',') decimal_comma=0;
288 /* Read TAC names from column 1 */
289 for(int ri=1; ri<csv->row_nr; ri++) {
290 int i=ri*colNr; if(i>=csv->nr || csv->c[i].col!=0) {ret++; break;}
291 strlcpy(par->r[ri-1].name, csv->c[i].content, MAX_TACNAME_LEN);
292 }
293
294 /* Read one column at a time */
295 parNr=0;
296 for(int ci=1; ci<colNr && ret==0; ci++) {
297 //printf("parNr=%d / %d\n", parNr, par->parNr);
298 if(parNr>par->parNr) {ret++; break;}
299 int ri=0; int i=ri*colNr+ci;
300 if(i>=csv->nr || csv->c[i].col!=ci) {ret++; break;}
301 if(strcasecmp(csv->c[i].content, "Model")==0) {
302 for(ri=1; ri<csv->row_nr; ri++) {
303 int i=ri*colNr+ci;
304 if(i>=csv->nr || csv->c[i].col!=ci) {ret++; break;}
305 par->r[ri-1].model=modelCodeIndex(csv->c[i].content);
306 }
307 continue;
308 }
309 if(strncasecmp(csv->c[i].content, "SD", 2)==0) {
310 if(parNr==0) {ret++; break;}
311 for(ri=1; ri<csv->row_nr; ri++) {
312 i=ri*colNr+ci;
313 if(i>=csv->nr || csv->c[i].col!=ci) {ret++; break;}
314 par->r[ri-1].sd[parNr-1]=atofVerified(csv->c[i].content);
315 }
316 continue;
317 }
318 if(strncasecmp(csv->c[i].content, "95%CL1", 6)==0) {
319 if(parNr==0) {ret++; break;}
320 for(ri=1; ri<csv->row_nr; ri++) {
321 i=ri*colNr+ci;
322 if(i>=csv->nr || csv->c[i].col!=ci) {ret++; break;}
323 par->r[ri-1].cl1[parNr-1]=atofVerified(csv->c[i].content);
324 }
325 continue;
326 }
327 if(strncasecmp(csv->c[i].content, "95%CL2", 6)==0) {
328 if(parNr==0) {ret++; break;}
329 for(ri=1; ri<csv->row_nr; ri++) {
330 i=ri*colNr+ci;
331 if(i>=csv->nr || csv->c[i].col!=ci) {ret++; break;}
332 par->r[ri-1].cl2[parNr-1]=atofVerified(csv->c[i].content);
333 }
334 continue;
335 }
336 if(strcasecmp(csv->c[i].content, "WSS")==0 || strcasecmp(csv->c[i].content, "SS")==0) {
337 for(ri=1; ri<csv->row_nr; ri++) {
338 i=ri*colNr+ci;
339 if(i>=csv->nr || csv->c[i].col!=ci) {ret++; break;}
340 par->r[ri-1].wss=atofVerified(csv->c[i].content);
341 }
342 continue;
343 }
344 if(strncasecmp(csv->c[i].content, "Start", 5)==0) {
345 for(ri=1; ri<csv->row_nr; ri++) {
346 i=ri*colNr+ci;
347 if(i>=csv->nr || csv->c[i].col!=ci) {ret++; break;}
348 par->r[ri-1].start=atofVerified(csv->c[i].content);
349 }
350 continue;
351 }
352 if(strncasecmp(csv->c[i].content, "End", 3)==0) {
353 for(ri=1; ri<csv->row_nr; ri++) {
354 i=ri*colNr+ci;
355 if(i>=csv->nr || csv->c[i].col!=ci) {ret++; break;}
356 par->r[ri-1].end=atofVerified(csv->c[i].content);
357 }
358 continue;
359 }
360 if(strcasecmp(csv->c[i].content, "dataNr")==0) {
361 for(ri=1; ri<csv->row_nr; ri++) {
362 i=ri*colNr+ci;
363 if(i>=csv->nr || csv->c[i].col!=ci) {ret++; break;}
364 par->r[ri-1].dataNr=atoi(csv->c[i].content);
365 }
366 continue;
367 }
368 if(strcasecmp(csv->c[i].content, "fitNr")==0) {
369 for(ri=1; ri<csv->row_nr; ri++) {
370 i=ri*colNr+ci;
371 if(i>=csv->nr || csv->c[i].col!=ci) {ret++; break;}
372 par->r[ri-1].fitNr=atoi(csv->c[i].content);
373 }
374 continue;
375 }
376 /* then this column is a parameter */
377 char tmp[128];
378 /* parameter name may contain unit */
379 if(strTokenNCpy(csv->c[i].content, "[] \t", 1, par->n[parNr].name, MAX_PARNAME_LEN)==0)
380 {ret++; break;}
381 if(strTokenNCpy(csv->c[i].content, "[] \t", 2, tmp, 128)>0)
382 par->n[parNr].unit=unitIdentify(tmp);
383 //strncpy(par->n[parNr].name, csv->c[i].content, MAX_PARNAME_LEN);
384 //par->n[parNr].name[MAX_PARNAME_LEN]='\0';
385 /* Read parameter values */
386 for(ri=1; ri<csv->row_nr; ri++) {
387 i=ri*colNr+ci;
388 if(i>=csv->nr || csv->c[i].col!=ci) {ret++; break;}
389 par->r[ri-1].p[parNr]=atofVerified(csv->c[i].content);
390 if(decimal_comma<1) {
391 /* Try to determine whether file format is UK or INT */
392 if(strchr(csv->c[i].content, '.')!=NULL) decimal_comma=0;
393 else if(strchr(csv->c[i].content, ',')!=NULL) decimal_comma=1;
394 }
395 }
396 parNr++;
397 }
398 if(ret>0) {
399 parFree(par);
400 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_INVALID_FORMAT);
402 }
403
404
405 /* If one 'parameter' is named WSS or SS, then move its contents to
406 correct place inside the struct */
407 {
408 int ci=-1;
409 for(int i=0; i<par->parNr; i++) {
410 if(!strcasecmp(par->n[i].name, "WSS") || !strcasecmp(par->n[i].name, "SS")) ci=i;
411 }
412 if(ci>=0 && ci<par->parNr && par->parNr>1) {
413 if(verbose>4) {
414 printf("column %d contains WSS, moving to correct place\n", 1+ci); fflush(stdout);}
415 for(int i=0; i<par->tacNr; i++) par->r[i].wss=par->r[i].p[ci];
416 /* delete the parameter column */
417 parDeletePar(par, ci);
418 }
419 }
420
421
422 /* Set format in struct */
423 if(csv->separator==';') {
424 if(decimal_comma==1) par->format=PAR_FORMAT_CSV_INT;
425 else par->format=PAR_FORMAT_CSV_UK;
426 } else if(csv->separator==',') {
428 } else if(csv->separator=='\t' || csv->separator==' ') {
429 if(decimal_comma==1) par->format=PAR_FORMAT_TSV_INT;
430 else par->format=PAR_FORMAT_TSV_UK;
431 } else {
432 if(decimal_comma==1) par->format=PAR_FORMAT_TSV_INT;
433 else par->format=PAR_FORMAT_TSV_UK;
434 }
435
436
437
438 /* Copy header */
439 if(hdr!=NULL && hdr->keyNr>0) {
440 if(verbose>4) {
441 printf("copying header contents (%d items) to PAR struct\n", hdr->keyNr); fflush(stdout);}
442 if(iftDuplicate(hdr, &par->h)!=TPCERROR_OK) {
443 if(verbose>0) {printf(" error in iftDuplicate()\n"); fflush(stdout);}
444 parFree(par);
445 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_INVALID_HEADER);
447 }
448 /* Move standard fields from header to struct */
449 double v, f;
450 int i, n, u;
451 char key[32];
452
453 strcpy(key, "fit_start");
454 if(!iftGetDoubleWithUnit(&par->h, iftFindKey(&par->h, key, 0), &v, &u)) {
455 f=unitConversionFactor(u, UNIT_MIN); if(!isnan(f)) v*=f;
456 for(i=0; i<par->tacNr; i++) if(isnan(par->r[i].start)) par->r[i].start=v;
457 }
458 strcpy(key, "fit_end");
459 if(!iftGetDoubleWithUnit(&par->h, iftFindKey(&par->h, key, 0), &v, &u)) {
460 f=unitConversionFactor(u, UNIT_MIN); if(!isnan(f)) v*=f;
461 for(i=0; i<par->tacNr; i++) if(isnan(par->r[i].end)) par->r[i].end=v;
462 }
463 strcpy(key, "dataNr");
464 if(!iftGetInt(&par->h, iftFindKey(&par->h, key, 0), &n)) {
465 for(i=0; i<par->tacNr; i++) if(par->r[i].dataNr<=0) par->r[i].dataNr=n;
466 }
467 strcpy(key, "model");
468 i=iftFindKey(&par->h, key, 0);
469 if(i>=0) {
470 unsigned int n=modelCodeIndex(par->h.item[i].value);
471 iftDelete(&par->h, i);
472 for(i=0; i<par->tacNr; i++) par->r[i].model=n;
473 }
474 }
475
476 /* Quit */
477 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_OK);
478 return(TPCERROR_OK);
479}
int csvCleanSpaces(CSV *csv)
Definition csvio.c:422
double atofVerified(const char *s)
Definition decpoint.c:75
int iftDelete(IFT *ift, int index)
Definition ift.c:206
int iftDuplicate(IFT *ift1, IFT *ift2)
Definition ift.c:236
int iftGetDoubleWithUnit(IFT *ift, int index, double *v, int *unit)
Definition iftget.c:129
int parDeletePar(PAR *par, int pi)
Definition par.c:478
size_t strlcpy(char *dst, const char *src, size_t dstsize)
Definition stringext.c:632
int col
Definition tpccsv.h:28
int row
Definition tpccsv.h:26
int row_nr
Definition tpccsv.h:44
int col_nr
Definition tpccsv.h:46
int nr
Definition tpccsv.h:42
@ TPCERROR_INVALID_FORMAT
Invalid file format.
@ TPCERROR_INVALID_HEADER
Invalid header contents.
double unitConversionFactor(const int u1, const int u2)
Definition units.c:487

Referenced by parRead().

◆ parReadFIT()

int parReadFIT ( PAR * par,
CSV * csv,
IFT * ift,
TPCSTATUS * status )
extern

Read (old) fit data into PAR struct.

Returns
enum tpcerror (TPCERROR_OK when successful).
Author
Vesa Oikonen
See also
parRead, parWriteFIT
Parameters
parPointer to target PAR struct.
csvPointer to source CSV from which data is read.
iftPointer to source IFT struct which contains whole result file data, in case the data could not be read into CSV.
statusPointer to status data; enter NULL if not needed

Definition at line 131 of file parfit.c.

141 {
142 int verbose=0; if(status!=NULL) verbose=status->verbose;
143 if(par==NULL) {
144 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_FAIL);
145 return TPCERROR_FAIL;
146 }
147 parFree(par);
148
149 if(csv==NULL || ift==NULL || csv->row_nr<1 || csv->col_nr<1) {
150 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_NO_DATA);
151 return TPCERROR_NO_DATA;
152 }
153 if(verbose>0) printf("%s()\n", __func__);
154
155 if(verbose>10) {
156 printf("\n CSV contents shown with separator ; \n\n");
157 char sep=csv->separator;
158 csv->separator=';'; csvWrite(csv, 0, stdout, NULL); csv->separator=sep;
159 printf("\n IFT contents \n\n");
160 iftWrite(ift, stdout, NULL);
161 printf("\n");
162 }
163
164 int i, n, ret, titlerow, tunit=UNIT_UNKNOWN;
165 char *cptr, tmp[256];
166
167 /* TAC nr */
168 i=iftFindKey(ift, "Nr of VOIs", 0);
169 if(i<0) i=iftFindKey(ift, "voiNr", 0);
170 if(i<0) i=iftFindKey(ift, "tacNr", 0);
171 if(i<0) {
172 parFree(par);
173 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_UNSUPPORTED);
175 }
176 int tacNr=atoi(ift->item[i].value);
177
178 /* Find (and ignore) the parameter title line */
179 i=0; if(verbose>2) printf("estimating parNr\n");
180 while(i<csv->nr) {
181 i=csvSearchField(csv, "Region", i); if(i<0) break;
182 if(i>=0 && csv->c[i].col==0) break;
183 i++;
184 }
185 if(i<0 || i==csv->nr) {
186 parFree(par);
187 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_INVALID_FORMAT);
189 }
190 titlerow=csv->c[i].row; if(verbose>3) printf("titlerow := %d\n", titlerow);
191#if(1)
192 /* Parameter nr from the row with most columns */
193 int parNr=0;
194 for(int r=0; r<tacNr; r++) {
195 int n=csvRowLength(csv, r+titlerow+1); if(verbose>5) printf("n=%d at row %d\n", n, r+titlerow+1);
196 if(n>parNr) parNr=n;
197 }
198 if(verbose>4) printf(" initial_parNr := %d\n", parNr);
199#else
200 /* Parameter nr from the next row */
201 int parNr=csvRowLength(csv, titlerow+1);
202#endif
203 if(csv->separator!=' ') parNr-=7; else parNr-=9;
204 if(verbose>2) {
205 printf(" parNr := %d\n", parNr);
206 printf(" tacNr := %d\n", tacNr);
207 }
208 if(parNr<1 || tacNr<1) {
209 parFree(par);
210 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_INVALID_FORMAT);
212 }
213 /* Allocate space for parameters */
214 ret=parAllocate(par, parNr, tacNr); if(ret!=TPCERROR_OK) {
215 parFree(par);
216 statusSet(status, __func__, __FILE__, __LINE__, ret);
217 return ret;
218 }
219 par->parNr=parNr; par->tacNr=tacNr;
220
221 /* Check magic string and get program name from the first non-comment IFT field */
222 i=0;
223 while(ift->item[i].comment && i<ift->keyNr && ift->item[i].key!=NULL) i++;
224 if(verbose>3) {
225 printf("ift->item[%d].value := '%s'\n", i, ift->item[i].value);
226 }
227 if(i==ift->keyNr || strncasecmp(ift->item[i].value, "FIT1", 4)) {
228 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_UNSUPPORTED);
230 }
231 cptr=ift->item[i].value+4;
232 if(strncpyCleanSpaces(tmp, cptr, 256)<1) {
233 parFree(par);
234 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_UNSUPPORTED);
236 }
237 iftPut(&par->h, "program", tmp, 0, NULL);
238
239 /* Get analysis time from IFT struct */
240 i=iftFindKey(ift, "Date", 0);
241 if(i>=0) iftPut(&par->h, "analysis_time", ift->item[i].value, 0, NULL);
242
243 /* Filename of the original data */
244 i=iftFindKey(ift, "Data file", 0);
245 if(i>=0) iftPut(&par->h, "datafile", ift->item[i].value, 0, NULL);
246
247 /* Study number */
248 i=iftFindKey(ift, "Study number", 0);
249 if(i<0) i=iftFindKey(ift, "studynr", 0);
250 if(i>=0) iftPut(&par->h, "studynr", ift->item[i].value, 0, NULL);
251
252 /* Units of the original data */
253 i=iftFindKey(ift, "Data unit", 0);
254 if(i>=0) iftPut(&par->h, "unit", ift->item[i].value, 0, NULL);
255 i=iftFindKey(ift, "Time unit", 0);
256 if(i>=0) {
257 iftPut(&par->h, "timeunit", ift->item[i].value, 0, NULL);
258 tunit=unitIdentify(ift->item[i].value);
259 }
260
261 /* Set parameter names */
262 for(i=0; i<parNr; i++) sprintf(par->n[i].name, "p%d", 1+i);
263
264 /* Read TAC parameters */
265 ret=0; if(verbose>2) {printf("reading individual parameter values...\n"); fflush(stdout);}
266 for(int j=0; j<tacNr; j++) {
267 n=csvRowLength(csv, 1+j+titlerow); if(csv->separator!=' ') n-=7; else n-=9;
268 if(n>parNr) {ret++; break;}
269 i=0; n=1+j+titlerow;
270 /* copy tac name */
271 strlcpy(par->r[j].name, csvCell(csv, n, i), MAX_TACNAME_LEN);
272 if(csv->separator==' ') {
273 i++;
274 strlcat(par->r[j].name, " ", MAX_TACNAME_LEN);
275 strlcat(par->r[j].name, cptr=csvCell(csv, n, i), MAX_TACNAME_LEN);
276 i++;
277 strlcat(par->r[j].name, " ", MAX_TACNAME_LEN);
278 strlcat(par->r[j].name, cptr=csvCell(csv, n, i), MAX_TACNAME_LEN);
279 }
280 /* fit start and end times */
281 i++; par->r[j].start=atofVerified(csvCell(csv, n, i));
282 i++; par->r[j].end=atofVerified(csvCell(csv, n, i));
283 if(tunit==UNIT_SEC) {par->r[j].start/=60.; par->r[j].end/=60.;}
284 /* nr of fitted samples */
285 i++; par->r[j].dataNr=atoi(csvCell(csv, n, i));
286 /* (W)SS */
287 i++; par->r[j].wss=atofVerified(csvCell(csv, n, i));
288 /* nr of parameters for this TAC; this is not the same as the nr of fitted (free)
289 parameters that would be stored in PAR struct */
290 i++; int tacParNr=atoi(csvCell(csv, n, i));
291 par->r[j].fitNr=0;
292 /* function id */
293 i++; par->r[j].model=modelOld2New(atoi(csvCell(csv, n, i)));
294 /* function parameter values */
295#if(1)
296 int k; // read the ones that actually are saved... and then fill the rest with NaNs
297 for(k=0; k<tacParNr; k++) {
298 i++; par->r[j].p[k]=atofVerified(csvCell(csv, n, i));
299 }
300 for(; k<parNr; k++) par->r[j].p[k]=nan("");
301#else
302 for(int k=0; k<parNr; k++) {
303 i++; par->r[j].p[k]=atofVerified(csvCell(csv, n, i));}
304#endif
305 }
306 if(ret>0) {
307 parFree(par);
308 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_INVALID_FORMAT);
310 }
311
312 /* Fix region names (mainly, remove dots) */
313 {
314 int i, tac;
315 char fnsp[3][MAX_TACNAME_LEN+1];
316 for(tac=0; tac<par->tacNr; tac++) {
317 for(i=0; i<3; i++) {
318 if(roinameSubpart(par->r[tac].name, "_ ", i, fnsp[i], MAX_TACNAME_LEN)==NULL ||
319 strcmp(fnsp[i], ".")==0)
320 strcpy(fnsp[i], "");
321 }
322 strcpy(par->r[tac].name, fnsp[0]);
323 if(strlen(fnsp[1]) || strlen(fnsp[2])) strcat(par->r[tac].name, "_");
324 if(strlen(fnsp[1])) strcat(par->r[tac].name, fnsp[1]);
325 if(strlen(fnsp[2])) {strcat(par->r[tac].name, "_"); strcat(par->r[tac].name, fnsp[2]);}
326 }
327 }
328
329 /* Set format in struct */
331
332 /* Quit */
333 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_OK);
334 return(TPCERROR_OK);
335}
char * csvCell(CSV *csv, int row, int col)
Definition csv.c:358
int csvRowLength(CSV *csv, int row)
Definition csv.c:244
int csvSearchField(CSV *csv, const char *s, int start_index)
Definition csvfind.c:50
int iftWrite(IFT *ift, FILE *fp, TPCSTATUS *status)
Definition iftio.c:98
unsigned int modelOld2New(const unsigned int i)
Definition modell.c:205
char * roinameSubpart(const char *roiname, const char *dlm, const unsigned int si, char *subpart, const unsigned int slen)
Definition roiname.c:20
int strncpyCleanSpaces(char *s1, const char *s2, int maxlen)
Definition stringext.c:265
size_t strlcat(char *dst, const char *src, size_t dstsize)
Definition stringext.c:592
char comment
Definition tpcift.h:27

Referenced by parRead().

◆ parReadLimits()

int parReadLimits ( PAR * par,
const char * fname,
const int verbose )
extern

Read the specified file and try to find constraints and tolerance for parameters listed in PAR structure.

Returns
enum tpcerror (TPCERROR_OK when successful).
Author
Vesa Oikonen
See also
parWriteLimits, parWrite, parFree
Parameters
parPointer to PAR structure, into which the limits are saved. This must also list the parameter names that are searched for from the file.
fnameInput file name.
verboseVerbose level; if zero, then nothing is printed to stderr or stdout.

Definition at line 489 of file pario.c.

497 {
498 if(verbose>0) {printf("%s(%s)\n", __func__, fname); fflush(stdout);}
499 if(par==NULL || par->parNr<1) return TPCERROR_NO_DATA;
500 if(strlen(fname)<1) return(TPCERROR_INVALID_FILENAME);
501
502 /* Open file */
503 if(verbose>1) printf(" opening %s\n", fname);
504 FILE *fp=fopen(fname, "r");
505 if(fp==NULL) return TPCERROR_CANNOT_READ;
506
507 /* Read file into IFT struct */
508 if(verbose>1) printf(" reading into IFT\n");
509 IFT ift; iftInit(&ift);
510 if(iftRead(&ift, fp, 1, 0, NULL)!=TPCERROR_OK) {fclose(fp); return TPCERROR_CANNOT_READ;}
511 fclose(fp);
512 if(verbose>1) printf(" keyNr=%d\n", ift.keyNr);
513
514 /* Search for parameter limits in the IFT */
515 char pname[MAX_PARNAME_LEN+10];
516 int n=0;
517 double f;
518 for(int i=0; i<par->parNr; i++) {
519 if(strlen(par->n[i].name)>0) strcpy(pname, par->n[i].name);
520 else sprintf(pname, "p%d", 1+i);
521 strcat(pname, "_lower");
522 if(iftGetDoubleValue(&ift, pname, 0, &f)>=0 && !isnan(f)) {par->n[i].lim1=f; n++;}
523 if(verbose>2) printf(" %s -> %g\n", pname, f);
524 pname[strlen(pname)-6]=(char)0; strcat(pname, "_upper");
525 if(iftGetDoubleValue(&ift, pname, 0, &f)>=0 && !isnan(f)) {par->n[i].lim2=f; n++;}
526 if(verbose>2) printf(" %s -> %g\n", pname, f);
527 pname[strlen(pname)-6]=(char)0; strcat(pname, "_tol");
528 if(iftGetDoubleValue(&ift, pname, 0, &f)>=0 && !isnan(f)) {par->n[i].tol=f; n++;}
529 if(verbose>2) printf(" %s -> %g\n", pname, f);
530 }
531 iftFree(&ift);
532 if(verbose>1) printf(" n=%d\n", n);
533 if(n==0) return TPCERROR_NO_DATA;
534
535 return TPCERROR_OK;
536}
int iftGetDoubleValue(IFT *ift, const char *key, int index, double *v)
Definition iftfind.c:191
@ TPCERROR_INVALID_FILENAME
Invalid file name.
@ TPCERROR_CANNOT_READ
Cannot read file.

◆ parReadRES()

int parReadRES ( PAR * par,
CSV * csv,
IFT * ift,
TPCSTATUS * status )
extern

Read result (RES) data into PAR struct.

Returns
enum tpcerror (TPCERROR_OK when successful).
Author
Vesa Oikonen
Parameters
parPointer to target PAR struct.
csvPointer to CSV from which data is read.
iftPointer to IFT struct which contains whole result file data, in case the data could not be read into CSV (which happens when spaces were used as field separator).
statusPointer to status data; enter NULL if not needed.

Definition at line 268 of file parres.c.

278 {
279 int verbose=0; if(status!=NULL) verbose=status->verbose;
280 if(verbose>0) {printf("%s()\n", __func__); fflush(stdout);}
281 if(par==NULL) {
282 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_FAIL);
283 return TPCERROR_FAIL;
284 }
285 parFree(par);
286
287 if(csv==NULL || ift==NULL || csv->row_nr<1 || csv->col_nr<1) {
288 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_NO_DATA);
289 return TPCERROR_NO_DATA;
290 }
291
292 if(verbose>10) {
293 printf("\n CSV contents shown with separator ; \n\n");
294 char sep=csv->separator;
295 csv->separator=';'; csvWrite(csv, 0, stdout, NULL); csv->separator=sep;
296 printf("\n IFT contents \n\n");
297 iftWrite(ift, stdout, NULL);
298 }
299
300 int i, ret, titlerow;
301 int ri, ci, parNr=0, tacNr=0;
302 char *cptr;
303
304 /* Find the result title line; get initial parameter and tac nr */
305 i=0; if(verbose>2) printf("estimating parNr and tacNr\n");
306 while(i<csv->nr) {
307 i=csvFindField(csv, "Region", i); if(i<0) break;
308 if(i>=0 && csv->c[i].col==0) break;
309 i++;
310 }
311 if(i<0 || i==csv->nr) {
312 parFree(par);
313 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_INVALID_FORMAT);
315 }
316 titlerow=csv->c[i].row;
317 /* Get parameter nr */
318 parNr=csvRowLength(csv, titlerow)-1;
319 // sometimes empty cells in the end
320 ci=parNr; while(ci>0 && strlen(csv->c[ci].content)<1) {ci--; parNr--;}
321 // sometimes an empty cell before parameter names
322 if(strlen(csv->c[i+1].content)<1) parNr--;
323 /* Get region nr */
324 ri=1+titlerow; ci=0;
325 cptr=csvCell(csv, ri, ci);
326 while(cptr!=NULL) {
327 if(csv->separator!=' ') {
328 if(strncasecmp(cptr, "SD . .", 3) && strncasecmp(cptr, "CL 95% ", 7)) tacNr++;
329 } else {
330 if(strcasecmp(cptr, "SD") && strcasecmp(cptr, "CL")) tacNr++;
331 }
332 ri++; cptr=csvCell(csv, ri, ci);
333 }
334 if(verbose>2) {
335 printf(" parNr := %d\n", parNr);
336 printf(" tacNr := %d\n", tacNr);
337 }
338 if(parNr<1 || tacNr<1) {
339 parFree(par);
340 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_INVALID_FORMAT);
342 }
343 /* Allocate space for parameters */
344 ret=parAllocate(par, parNr, tacNr); if(ret!=TPCERROR_OK) {
345 parFree(par);
346 statusSet(status, __func__, __FILE__, __LINE__, ret);
347 return ret;
348 }
349 par->parNr=parNr; par->tacNr=tacNr;
350
351 /* Get program name from the first non-comment IFT field */
352 if(verbose>2) printf("searching obligatory program name\n");
353 i=0;
354 while(ift->item[i].comment && i<ift->keyNr && ift->item[i].key!=NULL) i++;
355 if(verbose>3) {
356 printf("ift->item[%d].value := '%s'\n", i, ift->item[i].value);
357 }
358 if(i==ift->keyNr || !strcasestr(ift->item[i].value, "(c)")) {
359 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_UNSUPPORTED);
361 }
362 iftPut(&par->h, "program", ift->item[i].value, 0, NULL);
363
364 /* Get analysis time from IFT struct */
365 i=iftFindKey(ift, "Date", 0);
366 if(i>=0) iftPut(&par->h, "analysis_time", ift->item[i].value, 0, NULL);
367
368 /* Study number */
369 i=iftFindKey(ift, "Study", 0);
370 if(i>=0) iftPut(&par->h, "studynr", ift->item[i].value, 0, NULL);
371
372 /* Optional filenames etc */
373 i=iftFindKey(ift, "Data file", 0);
374 if(i>=0) iftPut(&par->h, "datafile", ift->item[i].value, 0, NULL);
375 i=iftFindKey(ift, "Plasma file", 0);
376 if(i>=0) iftPut(&par->h, "plasmafile", ift->item[i].value, 0, NULL);
377 i=iftFindKey(ift, "2nd plasma file", 0);
378 if(i>=0) iftPut(&par->h, "plasmafile2", ift->item[i].value, 0, NULL);
379 i=iftFindKey(ift, "Blood file", 0);
380 if(i>=0) iftPut(&par->h, "bloodfile", ift->item[i].value, 0, NULL);
381 i=iftFindKey(ift, "Reference file", 0);
382 if(i>=0) iftPut(&par->h, "reffile", ift->item[i].value, 0, NULL);
383 i=iftFindKey(ift, "Reference region", 0);
384 if(i>=0) iftPut(&par->h, "refname", ift->item[i].value, 0, NULL);
385
386 /* Fit method (optional) */
387 i=iftFindKey(ift, "Fit method", 0);
388 if(i>=0) iftPut(&par->h, "fitmethod", ift->item[i].value, 0, NULL);
389
390 /* Constants (optional) */
391 i=iftFindKey(ift, "Tissue density", 0);
392 if(i>=0) iftPut(&par->h, "density", ift->item[i].value, 0, NULL);
393 i=iftFindKey(ift, "Lumped constant", 0);
394 if(i>=0) iftPut(&par->h, "LC", ift->item[i].value, 0, NULL);
395 i=iftFindKey(ift, "Concentration", 0);
396 if(i>=0) iftPut(&par->h, "concentration", ift->item[i].value, 0, NULL);
397 i=iftFindKey(ift, "Beta", 0);
398 if(i>=0) iftPut(&par->h, "beta", ift->item[i].value, 0, NULL);
399 i=iftFindKey(ift, "Vb", 0);
400 if(i>=0) iftPut(&par->h, "Vb", ift->item[i].value, 0, NULL);
401 i=iftFindKey(ift, "fA", 0);
402 if(i>=0) iftPut(&par->h, "fA", ift->item[i].value, 0, NULL);
403 i=iftFindKey(ift, "Extraction", 0);
404 if(i>=0) iftPut(&par->h, "E", ift->item[i].value, 0, NULL);
405
406 /* Weighting (obligatory) */
407 if(verbose>2) printf("searching obligatory information on weighting\n");
408 if(iftSearchValue(ift, "not weighted", 0)>=0) {
409 iftPut(&par->h, "weighting", "no", 0, NULL);
410 } else if(iftSearchValue(ift, "was weighted", 0)>=0) {
411 iftPut(&par->h, "weighting", "yes", 0, NULL);
412 } else {
413 i=iftFindKey(ift, "Weighting", 0);
414 if(i>=0) {
415 iftPut(&par->h, "weighting", ift->item[i].value, 0, NULL);
416 } else {
417 parFree(par);
418 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_INVALID_FORMAT);
420 }
421 }
422
423 /* Read parameter names (possibly reorganized later) */
424 ri=titlerow; ci=1; cptr=csvCell(csv, ri, ci);
425 if(strlen(cptr)<1) {ci++; cptr=csvCell(csv, ri, ci);}
426 for(i=0; i<parNr; i++) {
427 strlcpy(par->n[i].name, cptr, MAX_PARNAME_LEN);
428 ci++; cptr=csvCell(csv, ri, ci);
429 }
430
431 /* Read parameter values for each region */
432 int tac=0;
433 double *dptr;
434 ri=1+titlerow; ret=TPCERROR_OK;
435 do {
436 ci=0; cptr=csvCell(csv, ri, ci);
437 if(cptr==NULL) {if(tac<tacNr) ret=TPCERROR_INVALID_FORMAT; break;}
438 //printf(" cell='%s'\n", cptr);
439 //printf(" ri=%d ci=%d tac=%d\n", ri, ci, tac);
440 /* check if this is SD line */
441 dptr=NULL;
442 if(csv->separator==' ') {
443 if(!strcasecmp(cptr, "SD")) {
444 if(tac<1) {ret=TPCERROR_INVALID_FORMAT; break;}
445 ci=3; dptr=par->r[tac-1].sd;
446 } else if(!strcasecmp(cptr, "CL")) {
447 if(tac<1) {ret=TPCERROR_INVALID_FORMAT; break;}
448 if(!strcasecmp(csvCell(csv, ri, 2), "Lower")) {
449 ci=3; dptr=par->r[tac-1].cl1;
450 } else if(!strcasecmp(csvCell(csv, ri, 2), "Upper")) {
451 ci=3; dptr=par->r[tac-1].cl2;
452 }
453 }
454 } else {
455 if(!strncasecmp(cptr, "SD . .", 3)) {
456 if(tac<1) {ret=TPCERROR_INVALID_FORMAT; break;}
457 ci=1; dptr=par->r[tac-1].sd;
458 } else if(!strncasecmp(cptr, "CL 95% Lower", 8)) {
459 if(tac<1) {ret=TPCERROR_INVALID_FORMAT; break;}
460 ci=1; dptr=par->r[tac-1].cl1;
461 } else if(!strncasecmp(cptr, "CL 95% Upper", 8)) {
462 if(tac<1) {ret=TPCERROR_INVALID_FORMAT; break;}
463 ci=1; dptr=par->r[tac-1].cl2;
464 }
465 }
466 if(dptr!=NULL) {
467 //printf(" sd or cl\n");
468 for(i=0; i<parNr; i++) {
469 cptr=csvCell(csv, ri, ci);
470 if(cptr==NULL) {ret=TPCERROR_INVALID_FORMAT; break;}
471 dptr[i]=atofVerified(cptr);
472 ci++;
473 }
474 ri++; continue;
475 }
476 if(tac>=tacNr) break;
477 //printf(" param\n");
478 /* copy tac name */
479 strlcpy(par->r[tac].name, cptr, MAX_TACNAME_LEN);
480 if(csv->separator==' ') {
481 ci++; cptr=csvCell(csv, ri, ci);
482 strlcat(par->r[tac].name, " ", MAX_TACNAME_LEN);
483 strlcat(par->r[tac].name, cptr, MAX_TACNAME_LEN);
484 ci++; cptr=csvCell(csv, ri, ci);
485 strlcat(par->r[tac].name, " ", MAX_TACNAME_LEN);
486 strlcat(par->r[tac].name, cptr, MAX_TACNAME_LEN);
487 }
488 /* copy parameter values */
489 ci++; //cptr=csvCell(csv, ri, ci); //if(strlen(cptr)<1) ci++;
490 for(i=0; i<parNr; i++) {
491 cptr=csvCell(csv, ri, ci);
492 if(cptr==NULL) {ret=TPCERROR_INVALID_FORMAT; break;}
493 par->r[tac].p[i]=atofVerified(cptr);
494 ci++;
495 }
496 if(ret!=TPCERROR_OK) break;
497 ri++; tac++;
498 } while(1);
499 if(ret!=TPCERROR_OK) {
500 parFree(par);
501 statusSet(status, __func__, __FILE__, __LINE__, ret);
502 return ret;
503 }
504
505 /* Read parameter units, if available */
506 i=iftFindKey(ift, "Units", 0);
507 if(i>0) {
508 int n=strTokenNr(ift->item[i].value, " \t");
509 if(n>parNr) n=parNr;
510 char tmp[256];
511 for(int j=0; j<n; j++) {
512 strTokenNCpy(ift->item[i].value, " \t", 1+j, tmp, 256);
513 par->n[j].unit=unitIdentify(tmp);
514 }
515 }
516
517 /* Fix region names (mainly, remove dots) */
518 {
519 int i, tac;
520 char fnsp[3][MAX_TACNAME_LEN+1];
521 for(tac=0; tac<par->tacNr; tac++) {
522 for(i=0; i<3; i++) {
523 if(roinameSubpart(par->r[tac].name, "_ ", i, fnsp[i], MAX_TACNAME_LEN)==NULL ||
524 strcmp(fnsp[i], ".")==0)
525 strcpy(fnsp[i], "");
526 }
527 strcpy(par->r[tac].name, fnsp[0]);
528 if(strlen(fnsp[1]) || strlen(fnsp[2])) strcat(par->r[tac].name, "_");
529 if(strlen(fnsp[1])) strcat(par->r[tac].name, fnsp[1]);
530 if(strlen(fnsp[2])) {
531 strcat(par->r[tac].name, "_"); strcat(par->r[tac].name, fnsp[2]);}
532 }
533 }
534
535 /* Data range (optional) */
536 i=iftFindKey(ift, "Data range", 0);
537 if(i>=0) {
538 double t1, t2;
539 char tmp[256];
540 int n;
541 n=sscanf(ift->item[i].value, "%lf - %lf %s", &t1, &t2, tmp);
542 if(n==3 && unitIdentify(tmp)==UNIT_SEC) {
543 t1/=60.; t2/=60.;
544 }
545 if(n>=2) for(i=0; i<par->tacNr; i++) {par->r[i].start=t1; par->r[i].end=t2;}
546 }
547
548
549 /* Data nr (optional) */
550 i=iftFindKey(ift, "Data nr", 0);
551 if(i>=0) {
552 int n; n=atoi(ift->item[i].value);
553 for(i=0; i<par->tacNr; i++) par->r[i].dataNr=n;
554 }
555
556 /* If one 'parameter' is named WSS or SS, then move its contents to
557 correct place inside the struct */
558 ci=-1;
559 for(i=0; i<par->parNr; i++) {
560 if(!strcasecmp(par->n[i].name, "WSS") || !strcasecmp(par->n[i].name, "SS"))
561 ci=i;
562 }
563 if(ci>=0 && ci<par->parNr && par->parNr>1) {
564 if(verbose>4) printf("column %d contains WSS, moving to correct place\n", 1+ci);
565 for(i=0; i<par->tacNr; i++) par->r[i].wss=par->r[i].p[ci];
566 /* delete the parameter column */
567 parDeletePar(par, ci);
568 }
569
570 /* Set format in struct */
572
573 /* Quit */
574 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_OK);
575 return(TPCERROR_OK);
576}
int csvFindField(CSV *csv, const char *s, int start_index)
Definition csvfind.c:27
int iftSearchValue(IFT *ift, const char *s, int start_index)
Definition iftfind.c:114

Referenced by parRead().

◆ parrFree()

void parrFree ( PARR * parr)
extern

Free memory allocated for PARR. All data is cleared.

Parameters
parrPointer to PARR struct

Definition at line 87 of file par.c.

90 {
91 if(parr==NULL) return;
92 free(parr->p);
93 free(parr->sd);
94 free(parr->cl1);
95 free(parr->cl2);
96 parrInit(parr);
97}

Referenced by parDeleteTAC(), parFree(), and parrAllocate().

◆ parrInit()

void parrInit ( PARR * parr)
extern

Initiate the PARR struct before any use.

Author
Vesa Oikonen
See also
parInit, parnInit
Parameters
parrPointer to PARR

Definition at line 41 of file par.c.

44 {
45 if(parr==NULL) return;
46 parr->model=0;
47 parr->name[0]='\0';
48 parr->start=parr->end=nan("");
49 parr->fitNr=0;
50 parr->dataNr=0;
51 parr->p=parr->sd=parr->cl1=parr->cl2=NULL;
52 parr->wss=nan("");
53 parr->sw=0;
54}
char sw
Definition tpcpar.h:74

Referenced by parAllocate(), parAllocateMore(), parDeleteTAC(), and parrFree().

◆ parSDWithPar()

int parSDWithPar ( PAR * par,
int pi )
extern

Check if specified parameter has SD in at least one of the regions.

See also
parCLWithPar, parIsWSS
Returns
Returns 1 if SD exists, and 0 if not (or in case of an error).
Parameters
parPointer to parameter data.
piIndex of parameter [0..parNr-1] to check.

Definition at line 307 of file par.c.

312 {
313 //printf("%s(%d)\n", __func__, pi); fflush(stdout);
314 if(par==NULL || par->tacNr<1 || pi<0 || pi>=par->parNr) return(0);
315 for(int i=0; i<par->tacNr; i++) if(!isnan(par->r[i].sd[pi])) return(1);
316 return(0);
317}

Referenced by parWriteCSV(), and parWriteXML().

◆ parSelectByAnother()

int parSelectByAnother ( PAR * d1,
PAR * d2,
int * pn,
int * pr,
TPCSTATUS * status )

Select parameters and regions in a PAR structure that are available in another PAR structure.

Returns
enum tpcerror (TPCERROR_OK when successful).
See also
parSelectTACs, parEnsureNames, parCompareParameterNames, parCompareTacNames, parSelectedParameters, parSelectedTACs
Parameters
d1Pointer to target PAR structure, in which the PARN and PARR switches are set.
d2Pointer to PAR structure to which the first is compared to; not modified.
pnPointer to store the number of available parameters; enter NULL, if not needed.
prPointer to store the number of available regions; enter NULL, if not needed.
statusPointer to status data; enter NULL if not needed.

Definition at line 22 of file parcomb.c.

33 {
34 int verbose=0; if(status!=NULL) verbose=status->verbose;
35 if(verbose>0) printf("%s()\n", __func__);
36 if(pn!=NULL) *pn=0;
37 if(pr!=NULL) *pr=0;
38 /* Check that required data exists */
39 if(d1==NULL || d1->parNr<1 || d1->tacNr<1) {
40 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_NO_DATA);
41 return TPCERROR_NO_DATA;
42 }
43 /* Unselect all */
44 for(int i=0; i<d1->parNr; i++) d1->n[i].sw=0;
45 for(int i=0; i<d1->tacNr; i++) d1->r[i].sw=0;
46 /* If no data to compare to, then that is it */
47 if(d2==NULL || d2->parNr<1 || d2->tacNr<1) {
48 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_OK);
49 return TPCERROR_OK;
50 }
51
52 /* Search for parameter names */
53 for(int i=0; i<d1->parNr; i++) {
54 if(strnlen(d1->n[i].name, 1)<1) continue;
55 for(int j=0; j<d2->parNr; j++) {
56 if(strnlen(d2->n[j].name, 1)<1) continue;
57 if(strcasecmp(d1->n[i].name, d2->n[j].name)==0) {d1->n[i].sw=1; continue;}
58 /* Allow mixed '-' and '_' */
59 char *buf1, *buf2;
60 buf1=strdup(d1->n[i].name); strReplaceChar(buf1, '-', '_');
61 buf2=strdup(d2->n[j].name); strReplaceChar(buf2, '-', '_');
62 int ret=strcasecmp(buf1, buf2);
63 free(buf1); free(buf2);
64 if(ret==0) {d1->n[i].sw=1; continue;}
65 }
66 }
67
68 /* Search for TAC names */
69 for(int i=0; i<d1->tacNr; i++) {
70 if(strnlen(d1->r[i].name, 1)<1) continue;
71 for(int j=0; j<d2->tacNr; j++) {
72 if(strnlen(d2->r[j].name, 1)<1) continue;
73 if(strcasecmp(d1->r[i].name, d2->r[j].name)==0) {d1->r[i].sw=1; continue;}
74 /* Allow mixed '-' and '_' */
75 char *buf1, *buf2;
76 buf1=strdup(d1->r[i].name); strReplaceChar(buf1, '-', '_');
77 buf2=strdup(d2->r[j].name); strReplaceChar(buf2, '-', '_');
78 int ret=strcasecmp(buf1, buf2);
79 free(buf1); free(buf2);
80 if(ret==0) {d1->r[i].sw=1; continue;}
81 }
82 }
83
84 /* Count the selected numbers, if needed */
85 if(pn!=NULL) *pn=parSelectedParameters(d1);
86 if(pr!=NULL) *pr=parSelectedTACs(d1);
87
88 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_OK);
89 return TPCERROR_OK;
90}
int parSelectedTACs(PAR *d)
Definition parselect.c:100
int parSelectedParameters(PAR *d)
Definition parselect.c:199

Referenced by parCombineTACs().

◆ parSelectedParameters()

int parSelectedParameters ( PAR * d)
extern

Get the number of selected parameters (sw!=0) in PAR structure.

Returns
the number of selected parameters.
Author
Vesa Oikonen
See also
parSelectParameters, parFindParameter, parSelectByAnother
Parameters
dPointer to PAR data

Definition at line 199 of file parselect.c.

202 {
203 int pi, n;
204
205 /* Check the input */
206 if(d==NULL || d->parNr<1) return(0);
207 /* Check each VOI */
208 for(pi=n=0; pi<d->parNr; pi++) if(d->n[pi].sw!=0) n++;
209 return(n);
210}

Referenced by parSelectByAnother().

◆ parSelectedTACs()

int parSelectedTACs ( PAR * d)
extern

Get the number of selected TACs (sw!=0) in PAR structure.

Returns
the number of selected TACs.
Author
Vesa Oikonen
See also
parSelectTACs, parSortByName, parSelectByAnother
Parameters
dPointer to PAR data.

Definition at line 100 of file parselect.c.

103 {
104 int ri, n;
105
106 /* Check the input */
107 if(d==NULL || d->tacNr<1) return(0);
108 /* Check each VOI */
109 for(ri=n=0; ri<d->tacNr; ri++) if(d->r[ri].sw!=0) n++;
110 return(n);
111}

Referenced by parSelectByAnother().

◆ parSelectParameters()

int parSelectParameters ( PAR * d,
const char * par_name,
int reset,
TPCSTATUS * status )
extern

Select the parameter(s) in PAR struct that have matching name or number.

Returns
the number of newly selected parameters, or <=0 in case of an error.
Author
Vesa Oikonen
See also
parSelectedParameters, parFindParameter, parSelectTACs, parSelectByAnother, parEnsureNames
Parameters
dPointer to PAR structure.
par_nameName of parameter, or parameter numbers (as string, for example '1-3' or '1,2,3'); string can be given with quotation marks. Enter NULL to select all parameters, or empty string to select parameters with empty name (which really should not exist).
reset1=Non-matching parameters are deselected, 0=Old selections are preserved.
statusPointer to status data; enter NULL if not needed.

Definition at line 120 of file parselect.c.

132 {
133 int verbose=0; if(status!=NULL) verbose=status->verbose;
134 if(verbose>0) printf("%s()\n", __func__);
135 /* Check that required data exists */
136 if(d==NULL || d->parNr<1) {
137 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_NO_DATA);
138 return(0);
139 }
140
141 int pi, len, match_nr=0;
142
143 /* Check if NULL was given as parameter name; if, then select all */
144 if(par_name==NULL) {
145 for(pi=0; pi<d->parNr; pi++) d->n[pi].sw=1;
146 return(d->parNr);
147 }
148
149 /* Reset all selections if required */
150 if(reset!=0) for(pi=0; pi<d->parNr; pi++) d->n[pi].sw=0;
151
152 /* Remove any quotation marks from the name */
153 len=strlen(par_name);
154 char local_name[len+1];
155 if(len>1) len=strncpyClean(local_name, par_name, len+1);
156 else strcpy(local_name, par_name);
157
158 /* If parameter name is empty, then select all tacs with missing names */
159 if(len<1 || strcmp(local_name, ".")==0) {
160 for(pi=0; pi<d->parNr; pi++) {
161 if(strlen(d->n[pi].name)==0) {d->n[pi].sw=1; match_nr++; continue;}
162 /* maybe here should also be checked for names consisting of only space characters */
163 }
164 return(match_nr);
165 }
166
167 /* Check each parameter name */
168 for(pi=0; pi<d->parNr; pi++) {
169 /* does the name match? */
170 if(strcasecmp(d->n[pi].name, local_name)==0) {
171 d->n[pi].sw=1; match_nr++; continue;
172 }
173 }
174 /* If at least one match was found, then we are ready */
175 if(match_nr>0) return(match_nr);
176
177 /* Since there was no match with names, we'll try with numbers */
178 INTLIST li; intlistInit(&li);
179 if(intlistExpandFromString(local_name, ", ", &li, 1)<1) {intlistFree(&li); return(0);}
180 intlistSort(&li);
181 for(int i=0; i<li.nr; i++) {
182 if(li.i[i]<1) continue;
183 if(li.i[i]>d->parNr) break;
184 d->n[li.i[i]-1].sw=1; match_nr++;
185 }
186 intlistFree(&li);
187
188 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_OK);
189 return(match_nr);
190}
void intlistInit(INTLIST *l)
Definition intutil.c:80
int intlistExpandFromString(const char *s1, const char *s2, INTLIST *l, const int ifnew)
Definition intutil.c:190
void intlistFree(INTLIST *l)
Definition intutil.c:92
void intlistSort(INTLIST *l)
Definition intutil.c:137
int strncpyClean(char *s1, const char *s2, int maxlen)
Definition stringext.c:321

◆ parSelectTACs()

int parSelectTACs ( PAR * d,
const char * region_name,
int reset,
TPCSTATUS * status )
extern

Select the TAC(s) in PAR structure that have matching ID name or number.

Returns
the number of newly selected VOIs, or <=0 in case of an error.
Author
Vesa Oikonen
See also
parSelectedTACs, parSelectParameters, parSortByName, parSelectByAnother, parEnsureNames
Parameters
dPointer to PAR structure.
region_nameName of TAC, or TAC numbers (as string, for example '1-3' or '1,2,3'); string can be given with quotation marks. Enter NULL to select all TACs, or empty string to select TACs with empty name fields (which really should not exist).
reset1=Non-matching VOIs are deselected, 0=Old selections are preserved.
statusPointer to status data; enter NULL if not needed.

Definition at line 24 of file parselect.c.

36 {
37 int verbose=0; if(status!=NULL) verbose=status->verbose;
38 if(verbose>0) printf("%s()\n", __func__);
39 /* Check that required data exists */
40 if(d==NULL || d->tacNr<1) {
41 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_NO_DATA);
42 return(0);
43 }
44
45 int ri, len, match_nr=0;
46
47 /* Check if NULL was given as tac name; if, then select all */
48 if(region_name==NULL) {
49 for(ri=0; ri<d->tacNr; ri++) d->r[ri].sw=1;
50 return(d->tacNr);
51 }
52
53 /* Reset all selections if required */
54 if(reset!=0) for(ri=0; ri<d->tacNr; ri++) d->r[ri].sw=0;
55
56 /* Remove any quotation marks from the name */
57 len=strlen(region_name);
58 char local_name[len+1];
59 if(len>1) len=strncpyClean(local_name, region_name, len+1);
60 else strcpy(local_name, region_name);
61
62 /* If tac name is empty, then select all tacs with missing names */
63 if(len<1 || strcmp(local_name, ".")==0) {
64 for(ri=0; ri<d->tacNr; ri++) {
65 if(strlen(d->r[ri].name)==0) {d->r[ri].sw=1; match_nr++; continue;}
66 /* maybe here should also be checked for names consisting of only space characters */
67 }
68 return(match_nr);
69 }
70
71 /* Check each TAC name */
72 for(ri=0; ri<d->tacNr; ri++) {
73 /* does the name match? */
74 if(roinameMatch(d->r[ri].name, local_name, status)!=0) {d->r[ri].sw=1; match_nr++; continue;}
75 }
76 /* If at least one match was found, then we are ready */
77 if(match_nr>0) return(match_nr);
78
79 /* Since there was no match with names, we'll try with numbers */
80 INTLIST li; intlistInit(&li);
81 if(intlistExpandFromString(local_name, ", ", &li, 1)<1) {intlistFree(&li); return(0);}
82 intlistSort(&li);
83 for(int i=0; i<li.nr; i++) {
84 if(li.i[i]<1) continue;
85 if(li.i[i]>d->tacNr) break;
86 d->r[li.i[i]-1].sw=1; match_nr++;
87 }
88 intlistFree(&li);
89 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_OK);
90 return(match_nr);
91}
int roinameMatch(const char *roiname, const char *test_str, TPCSTATUS *status)
Definition roiname.c:183

◆ parSetStudyNr()

int parSetStudyNr ( PAR * par,
const char * s )
extern

Set study number in PAR data, overwriting any previous study number.

See also
parIsStudyNr, tacSetHeaderStudynr, tacGetHeaderStudynr, studynrFromFilename
Returns
enum tpcerror (TPCERROR_OK when successful).
Parameters
parPointer to parameter data.
sPointer to string containing the study number; enter NULL or "" if you only want to delete studynr in header.

Definition at line 417 of file par.c.

423 {
424 if(par==NULL) return TPCERROR_FAIL;
425
426 /* Find and delete previous studynr(s) */
427 int i=0, start=0;
428 while(1) {
429 i=iftFindKey(&par->h, "studynr", start);
430 if(i<0) i=iftFindKey(&par->h, "study_number", start);
431 if(i<0) i=iftFindKey(&par->h, "study number", start);
432 if(i<0) break;
433 iftDelete(&par->h, i); if(i>start) start=i;
434 }
435
436 /* If new studynr is empty, then just return */
437 if(s==NULL || *s=='\0') return(TPCERROR_OK);
438
439 /* Otherwise create new key and value */
440 return(iftPut(&par->h, "studynr", s, (char)1, NULL));
441}

◆ parSortByName()

int parSortByName ( PAR * d,
TPCSTATUS * status )
extern

Sort TACs in alphabetical order by their TAC name.

Returns
enum tpcerror (TPCERROR_OK when successful).
See also
parSelectTACs, tacSortByName, parEnsureNames
Parameters
dPointer to PAR struct.
statusPointer to status data; enter NULL if not needed.

Definition at line 30 of file parorder.c.

35 {
36 int verbose=0; if(status!=NULL) verbose=status->verbose;
37 if(verbose>0) printf("%s()\n", __func__);
38 /* Check that required data exists */
39 if(d==NULL) {
40 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_NO_DATA);
41 return TPCERROR_NO_DATA;
42 }
43 if(d->tacNr>d->_tacNr) {
44 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_FAIL);
45 return TPCERROR_FAIL;
46 }
47 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_OK);
48 if(d->tacNr<2) return TPCERROR_OK;
49 qsort(d->r, d->tacNr, sizeof(PARR), parQSortName);
50 return TPCERROR_OK;
51}

◆ parToIFT()

int parToIFT ( PAR * par,
IFT * ift,
TPCSTATUS * status )
extern

Copy PAR data into IFT struct.

Returns
enum tpcerror (TPCERROR_OK when successful).
Author
Vesa Oikonen
Parameters
parPointer to source PAR struct, contents of which are to be copied
iftPointer to initiated target IFT struct; any previous contents are deleted
statusPointer to status data; enter NULL if not needed

Definition at line 24 of file parift.c.

32 {
33 int verbose=0; if(status!=NULL) verbose=status->verbose;
34 if(ift==NULL) {
35 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_FAIL);
36 return TPCERROR_FAIL;
37 }
38 if(verbose>0) printf("%s():\n", __func__);
39 if(par==NULL || par->tacNr<1 || par->parNr<1) {
40 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_NO_DATA);
41 return TPCERROR_NO_DATA;
42 }
43
44 /* Set decimal and item separators */
45 int tointl=0;
47 tointl=1;
48
49 int ret;
50 char tmp[128];
51
52 /* Set content id */
53 ret=iftPut(ift, "content", "parameters", 1, NULL);
54 if(ret!=TPCERROR_OK) {
55 statusSet(status, __func__, __FILE__, __LINE__, ret);
56 return ret;
57 }
58
59 /* Copy PAR headers */
60 sprintf(tmp, "%d", par->parNr);
61 ret=iftPut(ift, "par_nr", tmp, 1, NULL);
62 for(int i=0; i<par->h.keyNr && ret==TPCERROR_OK; i++) {
63 /* not if value is missing */
64 if(par->h.item[i].value==NULL || strlen(par->h.item[i].value)<1) continue;
65 /* not if key is missing */
66 if(par->h.item[i].key==NULL || strlen(par->h.item[i].key)<1) continue;
67 /* not if this will be written later */
68 if(strcasecmp(par->h.item[i].key, "model")==0) continue;
69 if(strcasecmp(par->h.item[i].key, "dataNr")==0) continue;
70 if(strcasecmp(par->h.item[i].key, "fitNr")==0) continue;
71 if(strcasecmp(par->h.item[i].key, "fit_start")==0) continue;
72 if(strcasecmp(par->h.item[i].key, "fit_end")==0) continue;
73 /* ok to copy */
74 ret=iftPut(ift, par->h.item[i].key, par->h.item[i].value, 1, NULL);
75 }
76 if(ret!=TPCERROR_OK) {
77 statusSet(status, __func__, __FILE__, __LINE__, ret);
78 return ret;
79 }
80
81 if(parIsModel(par)==1) {
82 sprintf(tmp, "%d", par->r[0].model);
83 iftPut(ift, "model", tmp, 0, NULL);
84 }
85 if(parIsDataNr(par)==1) {
86 sprintf(tmp, "%d", par->r[0].dataNr);
87 iftPut(ift, "data_nr", tmp, 0, NULL);
88 }
89 if(parIsFitNr(par)==1) {
90 sprintf(tmp, "%d", par->r[0].fitNr);
91 iftPut(ift, "fit_nr", tmp, 0, NULL);
92 }
93 if(parIsFitRange(par)==1) {
94 sprintf(tmp, "%g min", par->r[0].start);
95 if(tointl) strReplaceChar(tmp, '.', ',');
96 iftPut(ift, "fit_start", tmp, 0, NULL);
97 sprintf(tmp, "%g min", par->r[0].end);
98 if(tointl) strReplaceChar(tmp, '.', ',');
99 iftPut(ift, "fit_end", tmp, 0, NULL);
100 }
101
102 /* Copy parameter table contents into IFT */
103 int ri, pi;
104 for(ri=0; ri<par->tacNr; ri++) {
105 sprintf(tmp, "%d", 1+ri);
106 iftPut(ift, "parameter-set", tmp, 0, NULL);
107 iftPut(ift, "tac_name", par->r[ri].name, 0, NULL);
108 if(parIsModel(par)==2) {
109 sprintf(tmp, "%d", par->r[ri].model);
110 iftPut(ift, "model", tmp, 0, NULL);
111 }
112 if(parIsDataNr(par)==2) {
113 sprintf(tmp, "%d", par->r[ri].dataNr);
114 iftPut(ift, "dataNr", tmp, 0, NULL);
115 }
116 if(parIsFitNr(par)==2) {
117 sprintf(tmp, "%d", par->r[ri].fitNr);
118 iftPut(ift, "fitNr", tmp, 0, NULL);
119 }
120 if(parIsFitRange(par)==2) {
121 sprintf(tmp, "%g min", par->r[ri].start);
122 if(tointl) strReplaceChar(tmp, '.', ',');
123 iftPut(ift, "fit_start", tmp, 0, NULL);
124 sprintf(tmp, "%g min", par->r[ri].end);
125 if(tointl) strReplaceChar(tmp, '.', ',');
126 iftPut(ift, "fit_end", tmp, 0, NULL);
127 }
128 if(!isnan(par->r[ri].wss)) {
129 sprintf(tmp, "%g", par->r[ri].wss);
130 if(tointl) strReplaceChar(tmp, '.', ',');
131 iftPut(ift, "wss", tmp, 0, NULL);
132 }
133 for(pi=0; pi<par->parNr; pi++) if(!isnan(par->r[ri].p[pi])) {
134 if(par->n[pi].unit==UNIT_UNKNOWN) sprintf(tmp, "%g", par->r[ri].p[pi]);
135 else sprintf(tmp, "%g %s", par->r[ri].p[pi], unitName(par->n[pi].unit));
136 if(tointl) strReplaceChar(tmp, '.', ',');
137 iftPut(ift, par->n[pi].name, tmp, 0, NULL);
138 if(!isnan(par->r[ri].sd[pi])) {
139 sprintf(tmp, "%g", par->r[ri].sd[pi]);
140 if(tointl) strReplaceChar(tmp, '.', ',');
141 iftPut(ift, "SD", tmp, 0, NULL);
142 }
143 if(!isnan(par->r[ri].cl1[pi])) {
144 sprintf(tmp, "%g", par->r[ri].cl1[pi]);
145 if(tointl) strReplaceChar(tmp, '.', ',');
146 iftPut(ift, "95%CL1", tmp, 0, NULL);
147 }
148 if(!isnan(par->r[ri].cl2[pi])) {
149 sprintf(tmp, "%g", par->r[ri].cl2[pi]);
150 if(tointl) strReplaceChar(tmp, '.', ',');
151 iftPut(ift, "95%CL2", tmp, 0, NULL);
152 }
153 } // next parameter
154 } // next tac
155
156 /* Quit */
157 statusSet(status, __func__, __FILE__, __LINE__, ret);
158 return(ret);
159}
int parIsFitRange(PAR *par)
Definition par.c:267
int parIsFitNr(PAR *par)
Definition par.c:343
int parIsDataNr(PAR *par)
Definition par.c:362
int parIsModel(PAR *par)
Definition par.c:288

Referenced by parWriteIFT().

◆ parValueRange()

void parValueRange ( PAR * d,
const int i,
double * pmin,
double * pmax )
extern

Finds the min and max parameter value in PAR structure.

Author
Vesa Oikonen
See also
parFindParameter, parGetParameter, parSelectParameters
Parameters
dPointer to PAR structure.
iParameter index [0..parNr-1].
pminPointer to min parameter value; NULL if not needed.
pmaxPointer to max parameter value; NULL if not needed.

Definition at line 287 of file parselect.c.

296 {
297 if(pmin!=NULL) *pmin=nan("");
298 if(pmax!=NULL) *pmax=nan("");
299 if(d==NULL || i<0 || i>=d->parNr || d->tacNr<1) return;
300
301 double mi, ma; mi=ma=d->r[0].p[i];
302 for(int j=1; j<d->tacNr; j++) {
303 if(d->r[j].p[i]<mi) mi=d->r[j].p[i];
304 else if(d->r[j].p[i]>ma) ma=d->r[j].p[i];
305 }
306 if(pmin!=NULL) *pmin=mi;
307 if(pmax!=NULL) *pmax=ma;
308 return;
309}

◆ parWrite()

int parWrite ( PAR * par,
FILE * fp,
parformat format,
int extra,
TPCSTATUS * status )
extern

Write PAR data into specified file in specified format.

Returns
enum tpcerror (TPCERROR_OK when successful).
Author
Vesa Oikonen
See also
parRead, parFree, parAllocate, parFormatFromExtension
Parameters
parPointer to PAR struct, contents of which are to be written.
fpOutput file pointer.
formatFile format code; enter PAR_FORMAT_UNKNOWN (0) to write data in the format specified inside the PAR struct.
extraWrite (1) or do not write (0) also extra header fields found in PAR; only effective with CSV formats.
statusPointer to status data; enter NULL if not needed.

Definition at line 148 of file pario.c.

161 {
162 int verbose=0; if(status!=NULL) verbose=status->verbose;
163 if(fp==NULL) {
164 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_CANNOT_WRITE);
166 }
167 if(par==NULL || par->tacNr<1 || par->parNr<1) {
168 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_NO_DATA);
169 return TPCERROR_NO_DATA;
170 }
171 if(par->tacNr>par->_tacNr || par->parNr>par->_parNr) { // programmers fail
172 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_FAIL);
173 return TPCERROR_FAIL;
174 }
175
176 /* Determine and verify the write format */
177 if(format<=PAR_FORMAT_UNKNOWN || format>=PAR_FORMAT_LAST)
178 format=par->format;
179 if(format<=PAR_FORMAT_UNKNOWN || format>=PAR_FORMAT_LAST) {
180 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_INVALID_FORMAT);
182 }
183 if(verbose>0) {
184 printf("%s():\n", __func__);
185 printf("writing %d parameters from %d TACs in %s format\n",
186 par->parNr, par->tacNr, parFormattxt(format));
187 fflush(stdout);
188 }
189
190 /* Write file */
191 int ret;
192 switch(format) {
194 /* __attribute__((fallthrough)); */
196 /* __attribute__((fallthrough)); */
198 /* __attribute__((fallthrough)); */
200 ret=parWriteCSV(par, fp, format, extra, status);
201 break;
202 case PAR_FORMAT_RES:
203 ret=parWriteRES(par, fp, status);
204 break;
205 case PAR_FORMAT_FIT:
206 ret=parWriteFIT(par, fp, status);
207 break;
208 case PAR_FORMAT_IFT:
209 ret=parWriteIFT(par, fp, status);
210 break;
211 case PAR_FORMAT_XML:
212 ret=parWriteXML(par, fp, status);
213 break;
214 default:
216 }
217 fflush(fp); fflush(stderr);
218
219 /* Quit */
220 statusSet(status, __func__, __FILE__, __LINE__, ret);
221 return(ret);
222}
int parWriteCSV(PAR *par, FILE *fp, parformat format, int extra, TPCSTATUS *status)
Definition parcsv.c:26
int parWriteFIT(PAR *par, FILE *fp, TPCSTATUS *status)
Definition parfit.c:27
int parWriteIFT(PAR *par, FILE *fp, TPCSTATUS *status)
Definition parift.c:167
int parWriteRES(PAR *par, FILE *fp, TPCSTATUS *status)
Definition parres.c:26
int parWriteXML(PAR *par, FILE *fp, TPCSTATUS *status)
Definition parxmlio.c:26
@ TPCERROR_CANNOT_WRITE
Cannot write file.

◆ parWriteCSV()

int parWriteCSV ( PAR * par,
FILE * fp,
parformat format,
int extra,
TPCSTATUS * status )
extern

Write PAR data into specified file pointer in specified CSV or TSV format.

Returns
enum tpcerror (TPCERROR_OK when successful).
Author
Vesa Oikonen
See also
parReadCSV, parWrite
Parameters
parPointer to source PAR structure, contents of which are to be written.
fpOutput file pointer.
formatFile format code; enter PAR_FORMAT_UNKNOWN (0) to write data in the format specified inside PAR structure.
extraWrite (1) or do not write (0) also extra header fields found in PAR.
statusPointer to status data; enter NULL if not needed.

Definition at line 26 of file parcsv.c.

38 {
39 int verbose=0; if(status!=NULL) verbose=status->verbose;
40 if(fp==NULL) {
41 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_CANNOT_WRITE);
43 }
44 if(verbose>0) {printf("%s():\n", __func__); fflush(stdout);}
45 if(par==NULL || par->tacNr<1 || par->parNr<1) {
46 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_NO_DATA);
47 return TPCERROR_NO_DATA;
48 }
49
50 /* Determine and verify the write format */
51 if(format<=PAR_FORMAT_UNKNOWN || format>=PAR_FORMAT_LAST) format=par->format;
52 /* Set decimal and item separators */
53 int tointl=0;
54 char separator;
55 if(format==PAR_FORMAT_CSV_INT) {
56 tointl=1; separator=';';
57 } else if(format==PAR_FORMAT_CSV_UK) {
58 tointl=0; separator=',';
59 } else if(format==PAR_FORMAT_TSV_INT) {
60 tointl=1; separator='\t';
61 } else if(format==PAR_FORMAT_TSV_UK) {
62 tointl=0; separator='\t';
63 } else {
64 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_INVALID_FORMAT);
66 }
67 if(verbose>0) {
68 printf("writing %d parameters from %d TACs in %s format\n",
69 par->parNr, par->tacNr, parFormattxt(format));
70 }
71
72 int ret;
73
74 /* Write header if requested */
75 if(extra) {
76 if(verbose>1) printf(" add common info into header\n");
77 char tmp[128];
78 if(parIsModel(par)==1) { // same model in each TAC
79 iftDeleteKey(&par->h, "model");
80 sprintf(tmp, "%s", modelCode(par->r[0].model));
81 iftPut(&par->h, "model", tmp, 1, NULL);
82 }
83 if(parIsDataNr(par)==1) {
84 iftDeleteKey(&par->h, "dataNr");
85 sprintf(tmp, "%d", par->r[0].dataNr);
86 iftPut(&par->h, "dataNr", tmp, 1, NULL);
87 }
88 if(parIsFitNr(par)==1) {
89 iftDeleteKey(&par->h, "fitNr");
90 sprintf(tmp, "%d", par->r[0].fitNr);
91 iftPut(&par->h, "fitNr", tmp, 1, NULL);
92 }
93 if(parIsFitRange(par)==1) {
94 char unittext[60];
95 int tunit=UNIT_UNKNOWN;
96 int i=iftFindKey(&par->h, "timeunit", 0);
97 if(i<0) i=iftFindKey(&par->h, "time_unit", 0);
98 if(i>=0) tunit=unitIdentify(par->h.item[i].value);
99 if(unitIsTime(tunit)) sprintf(unittext, " %s", unitName(tunit)); else strcpy(unittext, "");
100 iftDeleteKey(&par->h, "fit_start");
101 sprintf(tmp, "%g%s", par->r[0].start, unittext);
102 iftPut(&par->h, "fit_start", tmp, 1, NULL);
103 iftDeleteKey(&par->h, "fit_end");
104 sprintf(tmp, "%g%s", par->r[0].end, unittext);
105 iftPut(&par->h, "fit_end", tmp, 1, NULL);
106 }
107 if(verbose>1) {printf(" writing parameter header\n"); fflush(stdout);}
108 for(int i=0; i<par->h.keyNr; i++) par->h.item[i].comment=1;
109 ret=iftWrite(&par->h, fp, status); if(ret!=TPCERROR_OK) return ret;
110 //fprintf(fp, "\n");
111 fflush(fp);
112 }
113
114 /* Allocate initial space for CSV structure; more will be added later when necessary */
115 CSV csv; csvInit(&csv);
116 ret=csvAllocate(&csv, (par->parNr+1)*(par->tacNr+1));
117 if(ret!=TPCERROR_OK) {
118 if(verbose>1) {fprintf(stderr, "Error: cannot allocate memory for CSV.\n"); fflush(stderr);}
119 statusSet(status, __func__, __FILE__, __LINE__, ret);
120 return ret;
121 }
122 csv.separator=separator;
123
124 /* Write parameter table into CSV */
125 if(verbose>1) {printf(" writing parameter table\n"); fflush(stdout);}
126 int pi, ri;
127 /* Parameter names */
128 if(verbose>2) {printf(" writing parameter names\n"); fflush(stdout);}
129 char pstr[MAX_PARNAME_LEN+MAX_UNITS_LEN+3];
130 ret=csvPutString(&csv, "Parameters", 0);
131 /* Column for model id, if different models fitted to TACs */
132 if(parIsModel(par)==2 && ret==TPCERROR_OK)
133 ret=csvPutString(&csv, "Model", 0);
134 for(pi=0; pi<par->parNr && ret==TPCERROR_OK; pi++) {
135 if(par->n[pi].unit==UNIT_UNKNOWN) {
136 ret=csvPutString(&csv, par->n[pi].name, 0);
137 } else {
138 sprintf(pstr, "%s[%s]", par->n[pi].name, unitName(par->n[pi].unit));
139 ret=csvPutString(&csv, pstr, 0);
140 }
141 if(ret==TPCERROR_OK && parSDWithPar(par, pi)) {
142 ret=csvPutString(&csv, "SD", 0);
143 }
144 if(ret==TPCERROR_OK && parCLWithPar(par, pi)) {
145 ret=csvPutString(&csv, "95%CL1", 0);
146 if(ret==TPCERROR_OK) ret=csvPutString(&csv, "95%CL2", 0);
147 }
148 }
149 if(ret==TPCERROR_OK && parIsWSS(par))
150 ret=csvPutString(&csv, "WSS", 0);
151 if(ret==TPCERROR_OK && parIsFitRange(par)==2) {
152 ret=csvPutString(&csv, "Start[min]", 0);
153 if(ret==TPCERROR_OK) ret=csvPutString(&csv, "End[min]", 0);
154 }
155 if(ret==TPCERROR_OK && parIsDataNr(par)==2)
156 ret=csvPutString(&csv, "DataNr", 0);
157 if(ret==TPCERROR_OK && parIsFitNr(par)==2)
158 ret=csvPutString(&csv, "FitNr", 0);
159 if(ret!=TPCERROR_OK) {
160 statusSet(status, __func__, __FILE__, __LINE__, ret);
161 csvFree(&csv); return ret;
162 }
163 /* Data table */
164 if(verbose>2) {printf(" writing parameter values\n"); fflush(stdout);}
165 for(ri=0; ri<par->tacNr && ret==TPCERROR_OK; ri++) {
166 if(verbose>3) {printf(" for region %d\n", 1+ri); fflush(stdout);}
167 /* Region names and parameter values */
168 if(strlen(par->r[ri].name)>0) {
169 ret=csvPutString(&csv, par->r[ri].name, 1);
170 } else {
171 char buf[16]; sprintf(buf, "tac%d", 1+ri);
172 ret=csvPutString(&csv, buf, 1);
173 }
174 if(parIsModel(par)==2 && ret==TPCERROR_OK)
175 ret=csvPutString(&csv, modelCode(par->r[ri].model), 0);
176 for(pi=0; pi<par->parNr && ret==TPCERROR_OK; pi++) {
177 ret=csvPutDouble(&csv, par->r[ri].p[pi], 0, tointl);
178 if(ret==TPCERROR_OK && parSDWithPar(par, pi))
179 ret=csvPutDouble(&csv, par->r[ri].sd[pi], 0, tointl);
180 if(ret==TPCERROR_OK && parCLWithPar(par, pi)) {
181 ret=csvPutDouble(&csv, par->r[ri].cl1[pi], 0, tointl);
182 if(ret==TPCERROR_OK)
183 ret=csvPutDouble(&csv, par->r[ri].cl2[pi], 0, tointl);
184 }
185 }
186 /* WSS etc */
187 if(ret==TPCERROR_OK && parIsWSS(par))
188 ret=csvPutDouble(&csv, par->r[ri].wss, 0, tointl);
189 if(ret==TPCERROR_OK && parIsFitRange(par)==2) {
190 ret=csvPutDouble(&csv, par->r[ri].start, 0, tointl);
191 if(ret==TPCERROR_OK) ret=csvPutDouble(&csv, par->r[ri].end, 0, tointl);
192 }
193 if(ret==TPCERROR_OK && parIsDataNr(par)==2)
194 ret=csvPutInt(&csv, par->r[ri].dataNr, 0);
195 if(ret==TPCERROR_OK && parIsFitNr(par)==2)
196 ret=csvPutInt(&csv, par->r[ri].fitNr, 0);
197 }
198 if(ret!=TPCERROR_OK) {
199 statusSet(status, __func__, __FILE__, __LINE__, ret);
200 csvFree(&csv); return ret;
201 }
202
203 /* Write CSV into file pointer */
204 if(verbose>2) {printf(" actually writing CSV in file\n"); fflush(stdout);}
205 ret=csvWrite(&csv, 0, fp, status);
206 csvFree(&csv); fflush(fp);
207 if(ret!=TPCERROR_OK) {csvFree(&csv); return ret;}
208
209 /* Quit */
210 statusSet(status, __func__, __FILE__, __LINE__, ret);
211 return(ret);
212}
int csvPutInt(CSV *csv, int v, int newline)
Definition csv.c:222
int csvAllocate(CSV *csv, int nr)
Definition csv.c:58
int csvPutString(CSV *csv, const char *s, int newline)
Definition csv.c:144
int csvPutDouble(CSV *csv, double v, int newline, int tointl)
Definition csv.c:193
void iftDeleteKey(IFT *ift, const char *key)
Definition iftfind.c:169
char * modelCode(const unsigned int i)
Definition modell.c:176
int parSDWithPar(PAR *par, int pi)
Definition par.c:307
int parCLWithPar(PAR *par, int pi)
Definition par.c:325
int parIsWSS(PAR *par)
Definition par.c:252
#define MAX_UNITS_LEN
Define max units string length.
int unitIsTime(int u)
Definition units.c:359

Referenced by parWrite().

◆ parWriteFIT()

int parWriteFIT ( PAR * par,
FILE * fp,
TPCSTATUS * status )
extern

Write FIT data into specified file pointer in (old) fit file format.

See also
parWrite
Returns
enum tpcerror (TPCERROR_OK when successful).
Author
Vesa Oikonen
Parameters
parPointer to PAR struct, contents of which are to be written.
fpOutput file pointer.
statusPointer to status data; enter NULL if not needed.

Definition at line 27 of file parfit.c.

34 {
35 int verbose=0; if(status!=NULL) verbose=status->verbose;
36 if(fp==NULL) {
37 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_CANNOT_WRITE);
39 }
40 if(verbose>0) printf("%s():\n", __func__);
41 if(par==NULL || par->tacNr<1 || par->parNr<1) {
42 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_NO_DATA);
43 return TPCERROR_NO_DATA;
44 }
45
46 int i, j, n;
47 char tmp[256];
48
49 /* Write magic string and fit program name */
50 i=iftFindKey(&par->h, "program", 0);
51 if(i<0 || !strnlen(par->h.item[i].value, 10)) strcpy(tmp, "libtpcpar");
52 else strlcpy(tmp, par->h.item[i].value, 256);
53 n=fprintf(fp, "%-11.11s %s\n", "FIT1", tmp);
54 if(n<5) {
55 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_CANNOT_WRITE);
57 }
58
59 /* Write fit date and time */
60 i=iftFindKey(&par->h, "analysis_time", 0);
61 if(i>=0) strlcpy(tmp, par->h.item[i].value, 256); else strcpy(tmp, "");
62 fprintf(fp, "Date:\t%s\n", tmp);
63
64 /* Write the name of the original datafile */
65 i=iftFindKey(&par->h, "datafile", 0);
66 if(i>=0) fprintf(fp, "Data file:\t%s\n", par->h.item[i].value);
67 else fprintf(fp, "Data file:\t\n");
68
69 /* Write the study number */
70 i=iftFindKey(&par->h, "studynr", 0);
71 if(i<0) i=iftFindKey(&par->h, "study_number", 0);
72 if(i>=0) fprintf(fp, "Study number:\t%s\n", par->h.item[i].value);
73
74 /* Write the concentration (y) unit of the original data */
75 i=iftFindKey(&par->h, "unit", 0);
76 if(i<0) i=iftFindKey(&par->h, "calibration_unit", 0);
77 if(i>=0) fprintf(fp, "Data unit:\t%s\n", par->h.item[i].value);
78 else fprintf(fp, "Data unit:\t\n");
79
80 /* Write the time (x) unit of the original data */
81 i=iftFindKey(&par->h, "timeunit", 0);
82 if(i<0) i=iftFindKey(&par->h, "time_unit", 0);
83 if(i>=0) fprintf(fp, "Time unit:\t%s\n", par->h.item[i].value);
84 else fprintf(fp, "Time unit:\t\n");
85
86 /* Write the tacNr to be saved */
87 fprintf(fp, "Nr of VOIs:\t%d\n", par->tacNr);
88
89 /* Write the Fit title */
90 fprintf(fp, "%s %s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\n",
91 "Region", "Plane", "Start", "End", "dataNr", "WSS", "parNr", "Type", "Parameters");
92
93 /* Write the individual fits */
94 for(i=0; i<par->tacNr; i++) {
95 /* Tac id */
96 if(strlen(par->r[i].name)>0) {
97 if(!roinameSubpart(par->r[i].name, "_- ", 0, tmp, 7)) strcpy(tmp, ".");
98 fprintf(fp, "%s ", tmp);
99 if(!roinameSubpart(par->r[i].name, "_- ", 1, tmp, 7)) strcpy(tmp, ".");
100 fprintf(fp, "%s ", tmp);
101 if(!roinameSubpart(par->r[i].name, "_- ", 2, tmp, 7)) strcpy(tmp, ".");
102 fprintf(fp, "%s", tmp);
103 } else {
104 fprintf(fp, "tac%d . .", 1+i);
105 }
106 /* Time range, sample nr, (W)SS, parameter nr, function id */
107 fprintf(fp, "\t%.3f\t%.3f\t%d\t%.2E\t%d\t%04d",
108 par->r[i].start, par->r[i].end, par->r[i].dataNr,
109 par->r[i].wss, par->parNr, modelOldId(par->r[i].model) );
110 /* Function parameters */
111 for(j=0; j<par->parNr; j++) fprintf(fp, "\t%.6E", par->r[i].p[j]);
112 n=fprintf(fp, "\n");
113 } // next fit
114 if(n==0) {
115 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_CANNOT_WRITE);
117 }
118
119 /* Quit */
120 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_OK);
121 return(TPCERROR_OK);
122}
unsigned int modelOldId(const unsigned int i)
Definition modell.c:191

Referenced by parWrite().

◆ parWriteIFT()

int parWriteIFT ( PAR * par,
FILE * fp,
TPCSTATUS * status )
extern

Write PAR data into specified file pointer in IFT format.

Returns
enum tpcerror (TPCERROR_OK when successful).
Author
Vesa Oikonen
Parameters
parPointer to source PAR struct, contents of which are to be written
fpOutput file pointer
statusPointer to status data; enter NULL if not needed

Definition at line 167 of file parift.c.

174 {
175 int verbose=0; if(status!=NULL) verbose=status->verbose;
176 if(fp==NULL) {
177 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_CANNOT_WRITE);
179 }
180 if(verbose>0) printf("%s()\n", __func__);
181 if(par==NULL || par->tacNr<1 || par->parNr<1) {
182 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_NO_DATA);
183 return TPCERROR_NO_DATA;
184 }
185
186 int ret;
187 IFT ift;
188 iftInit(&ift);
189 ret=parToIFT(par, &ift, status);
190 if(ret!=TPCERROR_OK) {iftFree(&ift); return ret;}
191 ret=iftWrite(&ift, fp, status);
192 iftFree(&ift);
193 if(ret!=TPCERROR_OK) return ret;
194
195 /* Quit */
196 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_OK);
197 return(TPCERROR_OK);
198}
int parToIFT(PAR *par, IFT *ift, TPCSTATUS *status)
Definition parift.c:24

Referenced by parWrite().

◆ parWriteLimits()

int parWriteLimits ( PAR * par,
const char * fname,
const int verbose )
extern

Write parameter constraints from PAR structure into specified file.

Returns
enum tpcerror (TPCERROR_OK when successful).
Author
Vesa Oikonen
See also
parReadLimits, parWrite, parFree, parListLimits
Parameters
parPointer to PAR structure, from which the limits are to be written.
fnameOutput file name. Enter 'stdout' to print to stdout.
verboseVerbose level; if zero, then nothing is printed to stderr or stdout

Definition at line 432 of file pario.c.

439 {
440 if(verbose>0) {printf("%s(%s)\n", __func__, fname); fflush(stdout);}
441 if(par==NULL || par->parNr<1) return TPCERROR_NO_DATA;
442 if(strlen(fname)<1) return(TPCERROR_INVALID_FILENAME);
443
444 /* Copy limits into IFT struct */
445 IFT ift; iftInit(&ift);
446 char pname[MAX_PARNAME_LEN+10];
447 for(int i=0; i<par->parNr; i++) {
448 if(!isnan(par->n[i].lim1)) {
449 if(strlen(par->n[i].name)>0) strcpy(pname, par->n[i].name); else sprintf(pname, "p%d", 1+i);
450 strcat(pname, "_lower"); iftPutDouble(&ift, pname, par->n[i].lim1, 0, NULL);
451 }
452 if(!isnan(par->n[i].lim2)) {
453 if(strlen(par->n[i].name)>0) strcpy(pname, par->n[i].name); else sprintf(pname, "p%d", 1+i);
454 strcat(pname, "_upper"); iftPutDouble(&ift, pname, par->n[i].lim2, 0, NULL);
455 }
456 if(!isnan(par->n[i].tol)) {
457 if(strlen(par->n[i].name)>0) strcpy(pname, par->n[i].name); else sprintf(pname, "p%d", 1+i);
458 strcat(pname, "_tol"); iftPutDouble(&ift, pname, par->n[i].tol, 0, NULL);
459 }
460 }
461 if(verbose>1) printf(" keyNr=%d\n", ift.keyNr);
462 if(ift.keyNr<1) {iftFree(&ift); return TPCERROR_NO_DATA;}
463
464 /* Write IFT */
465 if(strcasecmp(fname, "stdout")==0) { // into stdout
466 iftWrite(&ift, stdout, NULL);
467 } else { // into specified file
468 if(verbose>1) printf(" opening %s\n", fname);
469 FILE *fp=fopen(fname, "w");
470 if(fp==NULL) {iftFree(&ift); return TPCERROR_CANNOT_WRITE;}
471 if(verbose>1) printf(" writing in %s\n", fname);
472 if(iftWrite(&ift, fp, NULL)!=TPCERROR_OK) {
473 iftFree(&ift); fclose(fp); return TPCERROR_CANNOT_WRITE;
474 }
475 fclose(fp);
476 }
477 iftFree(&ift);
478
479 return TPCERROR_OK;
480}
int iftPutDouble(IFT *ift, const char *key, const double value, char comment, TPCSTATUS *status)
Definition ift.c:128

◆ parWriteRES()

int parWriteRES ( PAR * par,
FILE * fp,
TPCSTATUS * status )
extern

Write PAR data into specified file pointer in result (RES) file format.

See also
parWrite
Returns
enum tpcerror (TPCERROR_OK when successful).
Author
Vesa Oikonen
Parameters
parPointer to source PAR struct, contents of which are to be written.
fpOutput file pointer.
statusPointer to status data; enter NULL if not needed.

Definition at line 26 of file parres.c.

33 {
34 int verbose=0; if(status!=NULL) verbose=status->verbose;
35 if(fp==NULL) {
36 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_CANNOT_WRITE);
38 }
39 if(verbose>0) {printf("%s():\n", __func__); fflush(stdout);}
40 if(par==NULL || par->tacNr<1 || par->parNr<1) {
41 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_NO_DATA);
42 return TPCERROR_NO_DATA;
43 }
44
45 int i, j, n;
46 char tmp[256];
47
48 /* RES format has quite strict rules on the header, therefore
49 it is written here directly and not through IFT struct etc. */
50
51 /* Analysis program name (obligatory, with (c)) */
52 i=iftFindKey(&par->h, "program", 0);
53 if(i<0 || !strcasestr(par->h.item[i].value, "(c)")) {
54 //statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_INVALID_VALUE);
55 //return TPCERROR_INVALID_VALUE;
56 n=fprintf(fp, "results (c) none\n\n");
57 } else {
58 n=fprintf(fp, "%s\n\n", par->h.item[i].value);
59 }
60 if(n<6) {
61 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_CANNOT_WRITE);
63 }
64
65 /* Write calculation date and time (obligatory) */
66 i=iftFindKey(&par->h, "analysis_time", 0);
67 if(i<0) {
68 //statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_INVALID_VALUE);
69 //return TPCERROR_INVALID_VALUE;
70 time_t t=time(NULL);
71 fprintf(fp, "Date:\t%s\n", ctime_r_int(&t, tmp));
72 } else {
73 fprintf(fp, "Date:\t%s\n", par->h.item[i].value);
74 }
75
76 /* Write the studynr (optional) */
77 i=iftFindKey(&par->h, "studynr", 0);
78 if(i<0) i=iftFindKey(&par->h, "study_number", 0);
79 if(i>=0) fprintf(fp, "Study:\t%s\n", par->h.item[i].value);
80
81 /* Write the names of the original datafiles (optional) */
82 i=iftFindKey(&par->h, "datafile", 0);
83 if(i>=0) fprintf(fp, "Data file:\t%s\n", par->h.item[i].value);
84 i=iftFindKey(&par->h, "plasmafile", 0);
85 if(i>=0) fprintf(fp, "Plasma file:\t%s\n", par->h.item[i].value);
86 i=iftFindKey(&par->h, "plasmafile2", 0);
87 if(i>=0) fprintf(fp, "2nd Plasma file:\t%s\n", par->h.item[i].value);
88 i=iftFindKey(&par->h, "bloodfile", 0);
89 if(i>=0) fprintf(fp, "Blood file:\t%s\n", par->h.item[i].value);
90 i=iftFindKey(&par->h, "reffile", 0);
91 if(i>=0) fprintf(fp, "Reference file:\t%s\n", par->h.item[i].value);
92 i=iftFindKey(&par->h, "refname", 0);
93 if(i>=0) fprintf(fp, "Reference region:\t%s\n", par->h.item[i].value);
94
95 /* Write data range, nr, and fit method (optional) */
96 if(!isnan(par->r[0].start) && !isnan(par->r[0].end))
97 fprintf(fp, "Data range:\t%g - %g min\n", par->r[0].start, par->r[0].end);
98 if(par->r[0].dataNr>0)
99 fprintf(fp, "Data nr:\t%d\n", par->r[0].dataNr);
100 i=iftFindKey(&par->h, "fitmethod", 0);
101 if(i>=0) fprintf(fp, "Fit method:\t%s\n", par->h.item[i].value);
102
103 /* Write constants (optional) */
104 i=iftFindKey(&par->h, "density", 0);
105 if(i>=0) fprintf(fp, "Tissue density:\t%s\n", par->h.item[i].value);
106 i=iftFindKey(&par->h, "LC", 0);
107 if(i>=0) fprintf(fp, "Lumped constant:\t%s\n", par->h.item[i].value);
108 i=iftFindKey(&par->h, "concentration", 0);
109 if(i>=0) fprintf(fp, "Concentration:\t%s\n", par->h.item[i].value);
110 i=iftFindKey(&par->h, "beta", 0);
111 if(i>=0) fprintf(fp, "Beta:\t%s\n", par->h.item[i].value);
112 i=iftFindKey(&par->h, "Vb", 0);
113 if(i>=0) fprintf(fp, "Vb:\t%s\n", par->h.item[i].value);
114 i=iftFindKey(&par->h, "fA", 0);
115 if(i>=0) fprintf(fp, "fA:\t%s\n", par->h.item[i].value);
116 i=iftFindKey(&par->h, "E", 0);
117 if(i<0) i=iftFindKey(&par->h, "extraction", 0);
118 if(i>=0) fprintf(fp, "Extraction:\t%s\n", par->h.item[i].value);
119
120 /* Weighting (obligatory) */
121 i=iftFindKey(&par->h, "weighting", 0);
122 if(i>=0) fprintf(fp, "Weighting:\t%s\n", par->h.item[i].value);
123 else fprintf(fp, "Weighting:\t%s\n", "unknown");
124
125 /* Should column be printed as integers (0), floats (1) or exponentials (2)? */
126 int partype[par->parNr]; /* 0=int, 1=double, 2=exp */
127 for(i=0; i<par->parNr; i++) partype[i]=parPrintType(par, i);
128
129 /* Title line (obligatory) */
130 fprintf(fp, "\n%s", "Region");
131 for(i=0; i<par->parNr; i++) {
132 if(strlen(par->n[i].name)<1) strcpy(tmp, ".");
133 else strcpy(tmp, par->n[i].name);
134 fprintf(fp, "\t%s", tmp);
135 }
136 if(parIsWSS(par)) fprintf(fp, "\tWSS");
137 fprintf(fp, "\n");
138
139 /* Write units, if they exist, as comment line */
140 for(i=j=0; i<par->parNr; i++) if(par->n[i].unit!=UNIT_UNKNOWN) j++;
141 if(j>0) {
142 fprintf(fp, "%s", "# Units:");
143 for(i=0; i<par->parNr; i++) {
144 fprintf(fp, "\t%s", unitName(par->n[i].unit));
145 }
146 if(parIsWSS(par)) fprintf(fp, "\t.");
147 fprintf(fp, "\n");
148 }
149
150
151 /* Write regional results */
152 for(i=0; i<par->tacNr; i++) {
153 if(strlen(par->r[i].name)>0) {
154 if(!roinameSubpart(par->r[i].name, "_- ", 0, tmp, 7)) strcpy(tmp, ".");
155 fprintf(fp, "%s ", tmp);
156 if(!roinameSubpart(par->r[i].name, "_- ", 1, tmp, 7)) strcpy(tmp, ".");
157 fprintf(fp, "%s ", tmp);
158 if(!roinameSubpart(par->r[i].name, "_- ", 2, tmp, 7)) strcpy(tmp, ".");
159 fprintf(fp, "%s", tmp);
160 } else {
161 fprintf(fp, "tac%d . .", 1+i);
162 }
163 for(j=0; j<par->parNr; j++) {
164 if(isnan(par->r[i].p[j])) {fprintf(fp, "\t."); continue;}
165 switch(partype[j]) {
166 case 0: fprintf(fp, "\t%.0f", par->r[i].p[j]); break;
167 case 1:
168 if(par->r[i].p[j]>=0) n=4; else n=3;
169 fprintf(fp, "\t%.*f", n, par->r[i].p[j]);
170 break;
171 default:
172 if(par->r[i].p[j]>=0) n=4; else n=3;
173 fprintf(fp, "\t%.*e", n, par->r[i].p[j]);
174 break;
175 }
176 }
177 if(parIsWSS(par)) {
178 if(isnan(par->r[i].wss)) fprintf(fp, "\t.");
179 else fprintf(fp, "\t%g", par->r[i].wss);
180 }
181 fprintf(fp, "\n");
182 /* Write SD's, if they exist */
183 for(j=n=0; j<par->parNr; j++) if(!isnan(par->r[i].sd[j])) n++;
184 if(n>0) {
185 fprintf(fp, "SD . .");
186 for(j=0; j<par->parNr; j++) {
187 if(!isnan(par->r[i].sd[j])) {
188 switch(partype[j]) {
189 case 0: fprintf(fp, "\t%.0f", par->r[i].sd[j]); break;
190 case 1:
191 if(par->r[i].sd[j]>=0) n=4; else n=3;
192 fprintf(fp, "\t%.*f", n, par->r[i].sd[j]);
193 break;
194 default:
195 if(par->r[i].sd[j]>=0) n=4; else n=3;
196 fprintf(fp, "\t%.*e", n, par->r[i].sd[j]);
197 break;
198 }
199 } else {
200 fprintf(fp, "\t.");
201 }
202 }
203 if(parIsWSS(par)) fprintf(fp, "\t.");
204 fprintf(fp, "\n");
205 }
206 /* Write lower confidence limits, if they exist */
207 for(j=n=0; j<par->parNr; j++) if(!isnan(par->r[i].cl1[j])) n++;
208 if(n>0) {
209 fprintf(fp, "CL 95%% Lower");
210 for(j=0; j<par->parNr; j++) {
211 if(!isnan(par->r[i].cl1[j])) {
212 switch(partype[j]) {
213 case 0: fprintf(fp, "\t%.0f", par->r[i].cl1[j]); break;
214 case 1:
215 if(par->r[i].cl1[j]>=0) n=4; else n=3;
216 fprintf(fp, "\t%.*f", n, par->r[i].cl1[j]);
217 break;
218 default:
219 if(par->r[i].cl1[j]>=0) n=4; else n=3;
220 fprintf(fp, "\t%.*e", n, par->r[i].cl1[j]);
221 break;
222 }
223 } else {
224 fprintf(fp, "\t.");
225 }
226 }
227 if(parIsWSS(par)) fprintf(fp, "\t.");
228 fprintf(fp, "\n");
229 }
230 /* Write upper confidence limits, if they exist */
231 for(j=n=0; j<par->parNr; j++) if(!isnan(par->r[i].cl2[j])) n++;
232 if(n>0) {
233 fprintf(fp, "CL 95%% Upper");
234 for(j=0; j<par->parNr; j++) {
235 if(!isnan(par->r[i].cl2[j])) {
236 switch(partype[j]) {
237 case 0: fprintf(fp, "\t%.0f", par->r[i].cl2[j]); break;
238 case 1:
239 if(par->r[i].cl2[j]>=0) n=4; else n=3;
240 fprintf(fp, "\t%.*f", n, par->r[i].cl2[j]);
241 break;
242 default:
243 if(par->r[i].cl2[j]>=0) n=4; else n=3;
244 fprintf(fp, "\t%.*e", n, par->r[i].cl2[j]);
245 break;
246 }
247 } else {
248 fprintf(fp, "\t.");
249 }
250 }
251 if(parIsWSS(par)) fprintf(fp, "\t.");
252 fprintf(fp, "\n");
253 }
254 } /* next region */
255
256
257 /* Quit */
258 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_OK);
259 return(TPCERROR_OK);
260}
char * ctime_r_int(const time_t *t, char *buf)
Convert calendar time t into a null-terminated string of the form YYYY-MM-DD hh:mm:ss,...
Definition datetime.c:119
int parPrintType(PAR *par, int parIndex)
Definition parres.c:584

Referenced by parWrite().

◆ parWriteXML()

int parWriteXML ( PAR * par,
FILE * fp,
TPCSTATUS * status )
extern

Write PAR data into specified file pointer in Excel compatible XML format.

See also
parWrite, parRead, parWriteCSV
Returns
enum tpcerror (TPCERROR_OK when successful).
Author
Vesa Oikonen
Parameters
parPointer to source PAR struct, contents of which are to be written
fpFile pointer
statusPointer to status data; enter NULL if not needed

Definition at line 26 of file parxmlio.c.

33 {
34 int verbose=0; if(status!=NULL) verbose=status->verbose;
35 if(verbose>0) printf("%s()\n", __func__);
36 if(fp==NULL) {
37 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_CANNOT_WRITE);
39 }
40 if(par==NULL || par->tacNr<1 || par->parNr<1) {
41 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_NO_DATA);
42 return TPCERROR_NO_DATA;
43 }
44
45 /* Calculate column number */
46 int colNr=par->parNr+1; // including tac name
47 if(parIsModel(par)>0) colNr++;
48 for(int pi=0; pi<par->parNr; pi++) {
49 if(parSDWithPar(par, pi)) colNr++;
50 if(parCLWithPar(par, pi)) colNr+=2;
51 }
52 if(parIsWSS(par)) colNr++;
53 if(parIsFitRange(par)>0) colNr+=2;
54 if(parIsDataNr(par)>0) colNr++;
55 if(parIsFitNr(par)>0) colNr++;
56 if(verbose>1) printf(" colNr := %d\n", colNr);
57
58 /* Write XML header */
59 if(verbose>2) printf("writing XML header\n");
60 int n=fprintf(fp, "<?xml version=\"1.0\"?>\n");
61 if(n<1) {
62 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_CANNOT_WRITE);
64 }
65 fprintf(fp, "<ss:Workbook xmlns:ss=\"urn:schemas-microsoft-com:office:spreadsheet\">\n");
66 fprintf(fp, " <ss:Styles>\n");
67 fprintf(fp, " <ss:Style ss:ID=\"1\">\n");
68 fprintf(fp, " <ss:Font ss:Bold=\"1\"/>\n");
69 fprintf(fp, " </ss:Style>\n");
70 fprintf(fp, " </ss:Styles>\n");
71 fprintf(fp, " <ss:Worksheet ss:Name=\"Sheet1\">\n");
72 fprintf(fp, " <ss:Table>\n");
73
74 /* Set column widths */
75 for(int i=0; i<colNr; i++) fprintf(fp, " <ss:Column ss:Width=\"80\"/>\n");
76
77 /* Write the title line */
78 if(verbose>2) printf("writing title line\n");
79 fprintf(fp, " <ss:Row ss:StyleID=\"1\">\n");
80 fprintf(fp, " <ss:Cell>\n");
81 fprintf(fp, " <ss:Data ss:Type=\"String\">Parameters</ss:Data>\n");
82 fprintf(fp, " </ss:Cell>\n");
83 /* model id */
84 if(parIsModel(par)>0) {
85 fprintf(fp, " <ss:Cell>\n");
86 fprintf(fp, " <ss:Data ss:Type=\"String\">Model</ss:Data>\n");
87 fprintf(fp, " </ss:Cell>\n");
88 }
89 /* parameter names with units, and SD and/or CLs, if available */
90 for(int pi=0; pi<par->parNr; pi++) {
91 if(par->n[pi].unit==UNIT_UNKNOWN) {
92 fprintf(fp, " <ss:Cell>\n");
93 fprintf(fp, " <ss:Data ss:Type=\"String\">%s</ss:Data>\n", par->n[pi].name);
94 fprintf(fp, " </ss:Cell>\n");
95 } else {
96 fprintf(fp, " <ss:Cell>\n");
97 fprintf(fp, " <ss:Data ss:Type=\"String\">%s[%s]</ss:Data>\n",
98 par->n[pi].name, unitName(par->n[pi].unit));
99 fprintf(fp, " </ss:Cell>\n");
100 }
101 if(parSDWithPar(par, pi)) {
102 fprintf(fp, " <ss:Cell>\n");
103 fprintf(fp, " <ss:Data ss:Type=\"String\">SD</ss:Data>\n");
104 fprintf(fp, " </ss:Cell>\n");
105 }
106 if(parCLWithPar(par, pi)) {
107 fprintf(fp, " <ss:Cell>\n");
108 fprintf(fp, " <ss:Data ss:Type=\"String\">95%%CL1</ss:Data>\n");
109 fprintf(fp, " </ss:Cell>\n");
110 fprintf(fp, " <ss:Cell>\n");
111 fprintf(fp, " <ss:Data ss:Type=\"String\">95%%CL2</ss:Data>\n");
112 fprintf(fp, " </ss:Cell>\n");
113 }
114 }
115 if(parIsWSS(par)) {
116 fprintf(fp, " <ss:Cell>\n");
117 fprintf(fp, " <ss:Data ss:Type=\"String\">WSS</ss:Data>\n");
118 fprintf(fp, " </ss:Cell>\n");
119 }
120 if(parIsFitRange(par)>0) {
121 fprintf(fp, " <ss:Cell>\n");
122 fprintf(fp, " <ss:Data ss:Type=\"String\">Start[min]</ss:Data>\n");
123 fprintf(fp, " </ss:Cell>\n");
124 fprintf(fp, " <ss:Cell>\n");
125 fprintf(fp, " <ss:Data ss:Type=\"String\">End[min]</ss:Data>\n");
126 fprintf(fp, " </ss:Cell>\n");
127 }
128 if(parIsDataNr(par)>0) {
129 fprintf(fp, " <ss:Cell>\n");
130 fprintf(fp, " <ss:Data ss:Type=\"String\">DataNr</ss:Data>\n");
131 fprintf(fp, " </ss:Cell>\n");
132 }
133 if(parIsFitNr(par)>0) {
134 fprintf(fp, " <ss:Cell>\n");
135 fprintf(fp, " <ss:Data ss:Type=\"String\">FitNr</ss:Data>\n");
136 fprintf(fp, " </ss:Cell>\n");
137 }
138 /* End the title line */
139 n=fprintf(fp, " </ss:Row>\n");
140 if(n<1) {
141 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_CANNOT_WRITE);
143 }
144
145 /* Write parameters */
146 if(verbose>2) printf("writing data table\n");
147 for(int ri=0; ri<par->tacNr; ri++) {
148 if(verbose>3) printf(" for region %d\n", 1+ri);
149 /* Start the line */
150 fprintf(fp, " <ss:Row>\n");
151 /* Region names and parameter values */
152 fprintf(fp, " <ss:Cell>\n");
153 char *senc=strEncodeForXML(par->r[ri].name);
154 if(senc==NULL) fprintf(fp, " <ss:Data ss:Type=\"String\">%s</ss:Data>\n", par->r[ri].name);
155 else {fprintf(fp, " <ss:Data ss:Type=\"String\">%s</ss:Data>\n", senc); free(senc);}
156 fprintf(fp, " </ss:Cell>\n");
157 if(parIsModel(par)>0) {
158 fprintf(fp, " <ss:Cell>\n");
159 fprintf(fp, " <ss:Data ss:Type=\"String\">%s</ss:Data>\n", modelCode(par->r[ri].model));
160 fprintf(fp, " </ss:Cell>\n");
161 }
162 for(int pi=0; pi<par->parNr; pi++) {
163 fprintf(fp, " <ss:Cell>\n");
164 if(isnan(par->r[ri].p[pi])) fprintf(fp, " <ss:Data ss:Type=\"Number\"></ss:Data>\n");
165 else fprintf(fp, " <ss:Data ss:Type=\"Number\">%g</ss:Data>\n", par->r[ri].p[pi]);
166 fprintf(fp, " </ss:Cell>\n");
167 if(parSDWithPar(par, pi)) {
168 fprintf(fp, " <ss:Cell>\n");
169 if(isnan(par->r[ri].sd[pi])) fprintf(fp, " <ss:Data ss:Type=\"Number\"></ss:Data>\n");
170 else fprintf(fp, " <ss:Data ss:Type=\"Number\">%g</ss:Data>\n", par->r[ri].sd[pi]);
171 fprintf(fp, " </ss:Cell>\n");
172 }
173 if(parCLWithPar(par, pi)) {
174 fprintf(fp, " <ss:Cell>\n");
175 if(isnan(par->r[ri].cl1[pi])) fprintf(fp, " <ss:Data ss:Type=\"Number\"></ss:Data>\n");
176 else fprintf(fp, " <ss:Data ss:Type=\"Number\">%g</ss:Data>\n", par->r[ri].cl1[pi]);
177 fprintf(fp, " </ss:Cell>\n");
178 fprintf(fp, " <ss:Cell>\n");
179 if(isnan(par->r[ri].cl2[pi])) fprintf(fp, " <ss:Data ss:Type=\"Number\"></ss:Data>\n");
180 else fprintf(fp, " <ss:Data ss:Type=\"Number\">%g</ss:Data>\n", par->r[ri].cl2[pi]);
181 fprintf(fp, " </ss:Cell>\n");
182 }
183 }
184 /* WSS etc */
185 if(parIsWSS(par)) {
186 fprintf(fp, " <ss:Cell>\n");
187 if(isnan(par->r[ri].wss)) fprintf(fp, " <ss:Data ss:Type=\"Number\"></ss:Data>\n");
188 else fprintf(fp, " <ss:Data ss:Type=\"Number\">%g</ss:Data>\n", par->r[ri].wss);
189 fprintf(fp, " </ss:Cell>\n");
190 }
191 if(parIsFitRange(par)>0) {
192 fprintf(fp, " <ss:Cell>\n");
193 if(isnan(par->r[ri].start)) fprintf(fp, " <ss:Data ss:Type=\"Number\"></ss:Data>\n");
194 else fprintf(fp, " <ss:Data ss:Type=\"Number\">%g</ss:Data>\n", par->r[ri].start);
195 fprintf(fp, " </ss:Cell>\n");
196 fprintf(fp, " <ss:Cell>\n");
197 if(isnan(par->r[ri].end)) fprintf(fp, " <ss:Data ss:Type=\"Number\"></ss:Data>\n");
198 else fprintf(fp, " <ss:Data ss:Type=\"Number\">%g</ss:Data>\n", par->r[ri].end);
199 fprintf(fp, " </ss:Cell>\n");
200 }
201 if(parIsDataNr(par)>0) {
202 fprintf(fp, " <ss:Cell>\n");
203 fprintf(fp, " <ss:Data ss:Type=\"Number\">%d</ss:Data>\n", par->r[ri].dataNr);
204 fprintf(fp, " </ss:Cell>\n");
205 }
206 if(parIsFitNr(par)>0) {
207 fprintf(fp, " <ss:Cell>\n");
208 fprintf(fp, " <ss:Data ss:Type=\"Number\">%d</ss:Data>\n", par->r[ri].fitNr);
209 fprintf(fp, " </ss:Cell>\n");
210 }
211 /* End the line */
212 n=fprintf(fp, " </ss:Row>\n");
213 if(n<1) {
214 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_CANNOT_WRITE);
216 }
217 }
218
219 /* Write XML end part */
220 fprintf(fp, " </ss:Table>\n");
221 fprintf(fp, " </ss:Worksheet>\n");
222 n=fprintf(fp, "</ss:Workbook>\n");
223 if(n<1) {
224 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_CANNOT_WRITE);
226 }
227
228 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_OK);
229 return(TPCERROR_OK);
230}
char * strEncodeForXML(const char *s)
Definition stringext.c:731

Referenced by parWrite().