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

Sort or otherwise change the order of data in TAC struct. More...

#include "tpcclibConfig.h"
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <time.h>
#include <string.h>
#include "tpctac.h"

Go to the source code of this file.

Functions

int tacVerifyTimeOrder (TAC *d, TPCSTATUS *status)
 
int tacSortByTime (TAC *d, TPCSTATUS *status)
 
int tacSortByConc (TAC *d, const int i, TPCSTATUS *status)
 
int tacSortByName (TAC *d, TPCSTATUS *status)
 
int tacSortByAUC (TAC *d, TPCSTATUS *status)
 
int tacMoveTACC (TAC *d, int from, int to)
 
int tacSwapTACCs (TAC *d, int i1, int i2)
 
int tacDeleteTACC (TAC *d, int i)
 
int tacMultipleSamples (TAC *d1, const int fixMode, TAC *d2, const int verbose)
 Check TAC data for multiple samples with the same sample time. Optionally replace the multiple samples with their mean.
 

Detailed Description

Sort or otherwise change the order of data in TAC struct.

Definition in file tacorder.c.

Function Documentation

◆ tacDeleteTACC()

int tacDeleteTACC ( TAC * d,
int i )

Delete specified TACC inside TAC structure, moving the positions of other TACCs accordingly.

Returns
enum tpcerror (TPCERROR_OK when successful).
Author
Vesa Oikonen
See also
tacSwapTACCs, tacMoveTACC
Parameters
dPointer to TAC data. Main header is not changed, but tacNr is decreased.
iTACC index [0..tacNr-1].

Definition at line 310 of file tacorder.c.

315 {
316 /* Check that region exists */
317 if(d==NULL || i<0 || i>=d->tacNr) return(TPCERROR_FAIL);
318 /* If the last TACC is to be deleted, then just decrease the tacNr */
319 if(i==d->tacNr-1) {d->tacNr--; return(TPCERROR_OK);}
320 /* Otherwise move it to the last position, and then decrease tacNr */
321 if(tacMoveTACC(d, i, d->tacNr-1)!=TPCERROR_OK) return(TPCERROR_FAIL);
322 d->tacNr--;
323 return(TPCERROR_OK);
324}
int tacNr
Definition tpctac.h:91
int tacMoveTACC(TAC *d, int from, int to)
Definition tacorder.c:250
@ TPCERROR_FAIL
General error.
@ TPCERROR_OK
No error.

Referenced by tacReadReference(), and tacWMove().

◆ tacMoveTACC()

int tacMoveTACC ( TAC * d,
int from,
int to )

Move TACC from one position to another inside TAC structure, moving the positions of other TACCs accordingly.

Returns
enum tpcerror (TPCERROR_OK when successful).
Author
Vesa Oikonen
See also
tacSwapTACCs, tacDeleteTACC, tacCopyTacc
Parameters
dPointer to TAC data. Main header and tacNr are not changed.
fromTACC index [0.._tacNr-1]
toTACC index [0.._tacNr-1]

Definition at line 250 of file tacorder.c.

257 {
258 int i;
259 TACC tacc;
260 size_t taccSize;
261
262 if(d==NULL || from<0 || to<0) return(TPCERROR_FAIL);
263 if(from>=d->_tacNr || to>=d->_tacNr) return(TPCERROR_FAIL);
264 if(from==to) return(TPCERROR_OK); // nothing to do
265 taccSize=sizeof(TACC);
266 memcpy(&tacc, d->c+from, taccSize);
267 if(from>to) for(i=from; i>to; i--)
268 memcpy(d->c+i, d->c+(i-1), taccSize);
269 else for(i=from; i<to; i++)
270 memcpy(d->c+i, d->c+(i+1), taccSize);
271 memcpy(d->c+i, &tacc, taccSize);
272 return(TPCERROR_OK);
273}
Definition tpctac.h:66
TACC * c
Definition tpctac.h:117
int _tacNr
Definition tpctac.h:119

Referenced by tacDeleteTACC().

◆ tacMultipleSamples()

int tacMultipleSamples ( TAC * d1,
const int fixMode,
TAC * d2,
const int verbose )

Check TAC data for multiple samples with the same sample time. Optionally replace the multiple samples with their mean.

Data does no need to be sorted before calling this. Output is not necessarily sorted either.

See also
tacCorrectFrameOverlap, tacCompareTimes, tacSortByTime, tacIsX, tacDeleteSample
Returns
If fixMode is zero, then returns 1 if multiple samples are found, and 0 if not. If fixMode is 1, then returns 0 if successful, and otherwise >0.
Parameters
d1Pointer to the input TAC structure; optionally modified.
fixModeJust inspect for multiple samples (0), or replace those with mean (1).
d2Pointer to the output TAC structure; enter NULL if just inspecting. To replace the contents of input TAC, enter the same pointer here.
verboseVerbose level; if zero, then nothing is printed to stderr or stdout.

Definition at line 336 of file tacorder.c.

346 {
347 if(verbose>0) {printf("\n%s(%d)\n", __func__, fixMode); fflush(stdout);}
348
349 /* Check data */
350 if(fixMode!=0 && (d1==NULL || d2==NULL || d1->sampleNr<1)) return(2);
351 if(d1==NULL || d1->sampleNr<2 || !tacIsX(d1)) return(0);
352
353 /* Set limit for similarity of sample times; the same sample times can have been saved in
354 files with variable precision. */
355 const double simlim=1.0E-03; if(verbose>1) printf(" limit := %g\n", simlim);
356
357 /* Check if there are any multiple samples */
358 int isMultiple=0;
359 for(int i=0; i<d1->sampleNr-1 && !isMultiple; i++) {
360 double t1; if(d1->isframe) t1=0.5*(d1->x1[i]+d1->x2[i]); else t1=d1->x[i];
361 for(int j=i+1; j<d1->sampleNr; j++) {
362 double t2; if(d1->isframe) t2=0.5*(d1->x1[j]+d1->x2[j]); else t2=d1->x[j];
363 double dt=fabs(t2-t1);
364 if(verbose>4) printf(" |%g - %g| = %g\n", t1, t2, dt);
365 if(dt<simlim) {isMultiple=1; break;}
366 }
367 }
368 if(verbose>1) {printf(" isMultiple := %d\n", isMultiple); fflush(stdout);}
369 if(fixMode==0) return(isMultiple); // done, if fixing not asked for
370
371 /* If there were no multiples, copy the input to output and quit */
372 if(!isMultiple) {
373 TAC itac; tacInit(&itac);
374 if(tacDuplicate(d1, &itac)!=TPCERROR_OK) return(3);
375 if(tacDuplicate(&itac, d2)!=TPCERROR_OK) {tacFree(&itac); return(3);}
376 tacFree(&itac); return(0);
377 }
378
379 /* Ok there are multiples that need to be fixed. */
380 /* We'll start by making a copy of the input data, and removing any existing data in
381 the output; copy is needed, because output structure can be the same as input */
382 TAC itac; tacInit(&itac); if(tacDuplicate(d1, &itac)!=TPCERROR_OK) return(4);
383 tacFree(d2);
384 /* Delete missing samples from the input */
385 tacDeleteMissingSamples(&itac); if(verbose>2) printf(" itac.sampleNr := %d\n", itac.sampleNr);
386 /* Allocate memory for the output data */
387 if(tacAllocate(d2, itac.sampleNr, itac.tacNr)!=TPCERROR_OK) {tacFree(&itac); return(5);}
388 if(tacCopyHdr(&itac, d2)!=TPCERROR_OK) {tacFree(&itac); return(6);}
389 for(int r=0; r<itac.tacNr; r++)
390 if(tacCopyTacchdr(&itac.c[r], &d2->c[r])!=TPCERROR_OK) {tacFree(&itac); return(7);}
392 d2->tacNr=itac.tacNr;
393
394 /* Go through the input data */
395 while(itac.sampleNr>0) {
396 /* Find the smallest sample time */
397 int i=tacMinX(&itac); if(i<0) break;
398 if(verbose>3) printf(" smallest x[%d]=%g\n", i, itac.x[i]);
399 /* Copy values to the first free output sample */
400 for(int r=0; r<itac.tacNr; r++) d2->c[r].y[d2->sampleNr]=0.0;
401 int rn[itac.tacNr]; for(int r=0; r<itac.tacNr; r++) rn[r]=0;
402 for(int r=0; r<itac.tacNr; r++)
403 if(isfinite(itac.c[r].y[i])) {
404 d2->c[r].y[d2->sampleNr]=itac.c[r].y[i];
405 rn[r]++;
406 }
407 d2->x[d2->sampleNr]=itac.x[i]; d2->x1[d2->sampleNr]=itac.x1[i]; d2->x2[d2->sampleNr]=itac.x2[i];
408 double t1; if(itac.isframe) t1=0.5*(itac.x1[i]+itac.x2[i]); else t1=itac.x[i];
409 /* Delete the sample from input */
410 tacDeleteSample(&itac, i);
411 /* Search the input for matching sample times */
412 while(itac.sampleNr>0) {
413 /* Find the smallest sample time left */
414 int i=tacMinX(&itac); if(i<0) break;
415 if(verbose>3) printf(" smallest x[%d]=%g\n", i, itac.x[i]);
416 double t2; if(itac.isframe) t2=0.5*(itac.x1[i]+itac.x2[i]); else t2=itac.x[i];
417 double dt=fabs(t2-t1); if(verbose>4) printf(" |%g - %g| = %g\n", t1, t2, dt);
418 if(!(dt<simlim)) break; // if this is not close enough, then none will be
419 /* Add values to the first free output sample */
420 for(int r=0; r<itac.tacNr; r++)
421 if(isfinite(itac.c[r].y[i])) {
422 d2->c[r].y[d2->sampleNr]+=itac.c[r].y[i];
423 rn[r]++;
424 }
425 /* Delete also this sample from input */
426 tacDeleteSample(&itac, i);
427 }
428 /* Divide values by the summed number of samples */
429 for(int r=0; r<itac.tacNr; r++) d2->c[r].y[d2->sampleNr]/=(double)rn[r];
430 /* Move to next output sample */
431 d2->sampleNr++;
432 }
433 tacFree(&itac);
434
435 /* Check that we got something left */
436 if(d2->sampleNr<1) return(10);
437
438 return(0);
439}
double * y
Definition tpctac.h:75
Definition tpctac.h:87
double * x
Definition tpctac.h:97
int sampleNr
Definition tpctac.h:89
int isframe
Definition tpctac.h:95
weights weighting
Definition tpctac.h:115
double * x2
Definition tpctac.h:101
double * x1
Definition tpctac.h:99
void tacFree(TAC *tac)
Definition tac.c:106
int tacDuplicate(TAC *tac1, TAC *tac2)
Make a duplicate of TAC structure.
Definition tac.c:356
int tacAllocate(TAC *tac, int sampleNr, int tacNr)
Definition tac.c:130
void tacInit(TAC *tac)
Definition tac.c:24
int tacCopyTacchdr(TACC *d1, TACC *d2)
Definition tac.c:282
int tacCopyHdr(TAC *tac1, TAC *tac2)
Copy TAC header data from tac1 to tac2.
Definition tac.c:310
int tacDeleteMissingSamples(TAC *d)
Delete those samples (time frames) from TAC structure, which contain only missing y values,...
Definition tacx.c:450
int tacMinX(TAC *d)
Get the minimum x value in TAC structure.
Definition tacx.c:201
int tacDeleteSample(TAC *d, int i)
Delete a certain sample (time frame) from TAC structure.
Definition tacx.c:426
int tacIsX(TAC *d)
Verify if TAC structure contains reasonable x values (times).
Definition tacx.c:226
@ WEIGHTING_OFF
Not weighted or weights not available (weights for all included samples are 1.0).

◆ tacSortByAUC()

int tacSortByAUC ( TAC * d,
TPCSTATUS * status )

Sort TACs in decreasing order by their area-under-curve (AUC).

Returns
enum tpcerror (TPCERROR_OK when successful).
Author
Vesa Oikonen
See also
tacSortByName, tacSortByTime
Parameters
dPointer to TAC structure.
statusPointer to status data; enter NULL if not needed.

Definition at line 205 of file tacorder.c.

210 {
211 int verbose=0; if(status!=NULL) verbose=status->verbose;
212 if(verbose>0) printf("%s()\n", __func__);
213 /* Check that required data exists */
214 if(d==NULL) {
215 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_NO_DATA);
216 return TPCERROR_NO_DATA;
217 }
218 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_OK);
219 if(d->tacNr<2) return TPCERROR_OK;
220 /* Calculate AUCs for each TAC */
221 double auc[d->tacNr], fdur, v;
222 int i, j;
223 for(i=0; i<d->tacNr; i++) {
224 auc[i]=0.0;
225 for(j=0; j<d->sampleNr; j++) {
226 fdur=d->x2[0]-d->x1[0]; v=d->c[i].y[j];
227 if(isnan(fdur) || isnan(v)) continue;
228 auc[i]+=fdur*v;
229 }
230 }
231 /* Sort */
232 double a;
233 for(i=0; i<d->tacNr-1; i++)
234 for(j=i+1; j<d->tacNr; j++)
235 if(auc[j]>auc[i]) {
236 tacSwapTACCs(d, j, i);
237 a=auc[i]; auc[i]=auc[j]; auc[j]=a;
238 }
239 return TPCERROR_OK;
240}
void statusSet(TPCSTATUS *s, const char *func, const char *srcfile, int srcline, tpcerror error)
Definition statusmsg.c:142
int verbose
Verbose level, used by statusPrint() etc.
int tacSwapTACCs(TAC *d, int i1, int i2)
Definition tacorder.c:282
@ TPCERROR_NO_DATA
File contains no data.

◆ tacSortByConc()

int tacSortByConc ( TAC * d,
const int i,
TPCSTATUS * status )

Sort samples (frames) in TAC structure by decreasing sample value.

See also
tacSortByTime, tacSortByAUC
Returns
enum tpcerror (TPCERROR_OK when successful).
Author
Vesa Oikonen
Parameters
dPointer to TAC structure.
iIndex of y column which the sorting is based on.
statusPointer to status data; enter NULL if not needed.

Definition at line 122 of file tacorder.c.

129 {
130 int verbose=0; if(status!=NULL) verbose=status->verbose;
131 if(verbose>0) printf("%s()\n", __func__);
132 /* Check that required data exists */
133 if(d==NULL || d->tacNr<1) {
134 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_NO_DATA);
135 return TPCERROR_NO_DATA;
136 }
137 if(i<0 || i>=d->_tacNr) {
138 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_FAIL);
139 return TPCERROR_FAIL;
140 }
141 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_OK);
142 if(d->sampleNr<1) return TPCERROR_OK;
143
144 TACC *c;
145 int ri, fi, fj;
146 double s, a1, a2;
147 for(fi=0; fi<d->sampleNr-1; fi++) for(fj=fi+1; fj<d->sampleNr; fj++) {
148 a1=d->c[i].y[fi]; a2=d->c[i].y[fj];
149 if(a2<=a1) continue;
150 s=d->x[fi]; d->x[fi]=d->x[fj]; d->x[fj]=s;
151 s=d->x1[fi]; d->x1[fi]=d->x1[fj]; d->x1[fj]=s;
152 s=d->x2[fi]; d->x2[fi]=d->x2[fj]; d->x2[fj]=s;
153 s=d->w[fi]; d->w[fi]=d->w[fj]; d->w[fj]=s;
154 for(ri=0; ri<d->_tacNr; ri++) {
155 c=d->c+ri;
156 s=c->y[fi]; c->y[fi]=c->y[fj]; c->y[fj]=s;
157 }
158 }
159 return TPCERROR_OK;
160}
double * w
Definition tpctac.h:111

◆ tacSortByName()

int tacSortByName ( TAC * d,
TPCSTATUS * status )

Sort TACs in alphabetical order by their TAC name.

Returns
enum tpcerror (TPCERROR_OK when successful).
Author
Vesa Oikonen
See also
tacSortByAUC, tacSortByTime, tacSwapTACCs
Parameters
dPointer to TAC structure.
statusPointer to status data; enter NULL if not needed.

Definition at line 178 of file tacorder.c.

183 {
184 int verbose=0; if(status!=NULL) verbose=status->verbose;
185 if(verbose>0) printf("%s()\n", __func__);
186 /* Check that required data exists */
187 if(d==NULL) {
188 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_NO_DATA);
189 return TPCERROR_NO_DATA;
190 }
191 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_OK);
192 if(d->tacNr<2) return TPCERROR_OK;
193 qsort(d->c, d->tacNr, sizeof(TACC), tacQSortName);
194 return TPCERROR_OK;
195}

◆ tacSortByTime()

int tacSortByTime ( TAC * d,
TPCSTATUS * status )

Sort samples (frames) in TAC structure by increasing sample time.

Returns
enum tpcerror (TPCERROR_OK when successful).
Author
Vesa Oikonen
See also
tacVerifyTimeOrder, tacMultipleSamples, tacSortByConc, tacSortByAUC, tacCorrectFrameOverlap, tacDeleteSample, tacIsX, tacMinX
Parameters
dPointer to TAC structure.
statusPointer to status data; enter NULL if not needed.

Definition at line 74 of file tacorder.c.

79 {
80 int verbose=0; if(status!=NULL) verbose=status->verbose;
81 if(verbose>0) printf("%s()\n", __func__);
82 /* Check that required data exists */
83 if(d==NULL || d->tacNr<1) {
84 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_NO_DATA);
85 return TPCERROR_NO_DATA;
86 }
87 /* All sample times must be available */
88 if(tacXNaNs(d)>0) {
89 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_MISSING_DATA);
91 }
92 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_OK);
93 if(d->sampleNr<1) return TPCERROR_OK;
94
95 TACC *c;
96 int ri, fi, fj;
97 double s, a1, a2;
98 for(fi=0; fi<d->sampleNr-1; fi++) for(fj=fi+1; fj<d->sampleNr; fj++) {
99 if(d->isframe==0) {a1=d->x[fi]; a2=d->x[fj];}
100 else {a1=0.5*(d->x1[fi]+d->x2[fi]); a2=0.5*(d->x1[fj]+d->x2[fj]);}
101 if(a2>=a1) continue;
102 s=d->x[fi]; d->x[fi]=d->x[fj]; d->x[fj]=s;
103 s=d->x1[fi]; d->x1[fi]=d->x1[fj]; d->x1[fj]=s;
104 s=d->x2[fi]; d->x2[fi]=d->x2[fj]; d->x2[fj]=s;
105 s=d->w[fi]; d->w[fi]=d->w[fj]; d->w[fj]=s;
106 for(ri=0; ri<d->tacNr; ri++) {
107 c=d->c+ri;
108 s=c->y[fi]; c->y[fi]=c->y[fj]; c->y[fj]=s;
109 }
110 }
111 return TPCERROR_OK;
112}
int tacXNaNs(TAC *tac)
Definition tacnan.c:23
@ TPCERROR_MISSING_DATA
File contains missing values.

Referenced by tacInput2sim(), tacReadModelingData(), tacReadModelingInput(), and tacSetXContiguous().

◆ tacSwapTACCs()

int tacSwapTACCs ( TAC * d,
int i1,
int i2 )

Change places between two TACCs inside TAC structure.

Returns
enum tpcerror (TPCERROR_OK when successful).
Author
Vesa Oikonen
See also
tacDeleteTACC, tacMoveTACC
Parameters
dPointer to TAC data. Main header and tacNr are not changed.
i1TACC index 1 [0.._tacNr-1]
i2TACC index 2 [0.._tacNr-1]

Definition at line 282 of file tacorder.c.

289 {
290 TACC tacc;
291 size_t taccSize;
292
293 if(d==NULL || i1<0 || i2<0) return(TPCERROR_FAIL);
294 if(i1>=d->_tacNr || i2>=d->_tacNr) return(TPCERROR_FAIL);
295 if(i1==i2) return(TPCERROR_OK); // nothing to do
296 taccSize=sizeof(TACC);
297 memcpy(&tacc, d->c+i1, taccSize);
298 memcpy(d->c+i1, d->c+i2, taccSize);
299 memcpy(d->c+i2, &tacc, taccSize);
300 return(TPCERROR_OK);
301}

Referenced by tacSortByAUC().

◆ tacVerifyTimeOrder()

int tacVerifyTimeOrder ( TAC * d,
TPCSTATUS * status )

Verify that x values (sample or frame times) in TAC structure are ordered by increasing x. Overlapping samples are ok here.

Returns
enum tpcerror (TPCERROR_OK when in increasing order).
0 if in increasing order, >0 otherwise or in case of error.
Author
Vesa Oikonen
See also
tacSortByTime, tacCorrectFrameOverlap, tacMultipleSamples, tacIsX, tacMinX.
Parameters
dPointer to TAC structure; not modified.
statusPointer to status data; enter NULL if not needed

Definition at line 25 of file tacorder.c.

30 {
31 int verbose=0; if(status!=NULL) verbose=status->verbose;
32 if(verbose>0) printf("%s()\n", __func__);
33 /* Check that required data exists */
34 if(d==NULL || d->sampleNr<1) {
35 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_NO_DATA);
36 return TPCERROR_NO_DATA;
37 }
38 /* All sample times must be available */
39 if(tacXNaNs(d)>0) {
40 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_MISSING_DATA);
42 }
43 /* Less than two samples are always in order */
44 if(d->sampleNr<2) {
45 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_OK);
46 return TPCERROR_OK;
47 }
48
49 int fi;
50 double p, s;
51
52 fi=0; if(d->isframe==0) p=d->x[fi]; else p=0.5*(d->x1[fi]+d->x2[fi]);
53 for(fi=1; fi<d->sampleNr; fi++) {
54 if(d->isframe==0) s=d->x[fi]; else s=0.5*(d->x1[fi]+d->x2[fi]);
55 if(s<p) {
56 if(verbose>2) printf("x[%d]=%g\nx[%d]=%g\n", fi-1, p, fi, s);
57 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_OVERLAPPING_DATA);
59 }
60 p=s;
61 }
62 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_OK);
63 return TPCERROR_OK;
64}
@ TPCERROR_OVERLAPPING_DATA
Overlapping data.

Referenced by tacCorrectFrameOverlap(), and tacIsXContiguous().