openCARP
Doxygen code documentation for the open cardiac electrophysiology simulator openCARP
trace.cc
Go to the documentation of this file.
1 // SPDX-FileCopyrightText: Copyright (c) NumeriCor GmbH
2 // SPDX-License-Identifier: LicenseRef-APL-1.1
3 
4 #include <stdio.h>
5 #include <stdlib.h>
6 #include <string.h>
7 #include <math.h>
8 #include <stdbool.h>
9 #include "trace.h"
10 #include "basics.h"
11 
12 namespace limpet {
13 
15 
16 // internally used prototypes
17 bool IsEquDistSampling(trace *tr);
18 
19 
27 void
28 set_trace_amp(trace *tr, float val, float whenceforth )
29 {
30  for( int i=0; i<tr->N; i++ )
31  if( tr->dt*i >= whenceforth )
32  tr->s[i] = val;
33 }
34 
35 
47 int
48 mk_RRC_trace(trace *tr, float st, float delay, float clamp, float dur)
49 {
50  tr->N = 8;
51  tr->t = (double*)malloc(tr->N*sizeof(double));
52  tr->s = (float *)malloc(tr->N*sizeof(float ));
53  tr->t[0] = 0 ; tr->s[0] = 0 ;
54  tr->t[1] = 0.1 ; tr->s[1] = st ;
55  tr->t[2] = 1 ; tr->s[2] = st ;
56  tr->t[3] = 1.1 ; tr->s[3] = 0 ;
57  tr->t[4] = delay ; tr->s[4] = 0 ;
58  tr->t[5] = delay+0.1 ; tr->s[5] = clamp ;
59  tr->t[6] = delay+dur ; tr->s[6] = clamp ;
60  tr->t[7] = delay+dur+0.1 ; tr->s[7] = 0 ;
61  tr->eqdist = IsEquDistSampling(tr);
62  return 0;
63 }
64 
65 
74 int
75 read_trace(trace *tr, const char *name )
76 {
77  int err = 0;
78 
79  FILE *f;
80  if ( (f = fopen(name,"r")) != NULL ) {
81  int n;
82  char buf[128], *bufptr;
83  bufptr = fgets(buf,128,f);
84  sscanf( buf, "%d", &tr->N );
85  tr->t = (double*)malloc(tr->N*sizeof(double));
86  tr->s = (float *)malloc(tr->N*sizeof(float ));
87  for (int i=0;i<tr->N;i++)
88  n = fscanf( f, "%lf %f\n", tr->t+i, tr->s+i );
89  fclose(f);
90  tr->eqdist = IsEquDistSampling(tr);
91  } else {
92  log_msg(0, 3, 0, "Could not open stimulus pulse file %s for reading\n", name);
93  err++;
94  }
95 
96  return err;
97 }
98 
107 void
109 {
110  if(tr->t != NULL) free(tr->t);
111  if(tr->s != NULL) free(tr->s);
112 }
113 
114 
123 {
124  double dt_o = tr->t[1]-tr->t[0];
125  // differences in sampling should be less than 0.1%
126  double r_err = 0.001*dt_o;
127 
128  for (int i=1;i<tr->N-1;i++) {
129  double dt_n = tr->t[i+1]-tr->t[i];
130  if (dt_n-dt_o > r_err)
131  return false;
132  }
133  tr->dt = dt_o;
134  return true;
135 }
136 
137 
138 
147 void resample_trace(trace *tr, double dt )
148 {
149 
150  // interpolate to match dt
151  int N = (int)( (tr->t[tr->N-1]-tr->t[0])/dt )+1;
152  float *s = (float*)malloc(N*sizeof(float));
153  if (!tr->t) {
154  tr->t = (double*)malloc(tr->N*sizeof(double));
155  for (int i=0; i<tr->N;i++) tr->t[i] = i*tr->dt;
156  }
157 
158  interp1(tr->t,tr->s,tr->N,NULL,s,N,dt,_LINEAR_IP);
159 
160  free(tr->t);
161  free(tr->s);
162  tr->dt = dt;
163  tr->N = N;
164  tr->dur = dt*(N-1);
165  tr->s = s;
166  tr->t = NULL;
167 }
168 
179 double trace_duration(trace *tr, const char* f)
180 {
181  bool tr_read = false;
182 
183  // trace has not been read previously
184  if (!tr->s) {
185  if (f!=NULL) {
186  read_trace(tr, f);
187  tr_read = true;
188  } else
189  return -1.;
190  }
191 
192  double duration = 0;
193  if (tr->t)
194  duration = tr->t[tr->N-1]-tr->t[0];
195  else
196  duration = tr->N*tr->dt;
197 
198  if (tr_read) {
199  if (tr->s) free(tr->s);
200  if (tr->t) free(tr->t);
201  }
202  return duration;
203 }
204 
205 
220 void
221 interp1(const double *x, const float *y, int N, double *xi, float *yi, int NI, double dxi, IpMeth_t meth)
222 {
223  // initialize interpolation array
224  memset(yi,0,sizeof(float)*NI);
225 
226  // iterate over target array
227  for (int i=0; i<NI; i++) {
228 
229  // x-axis sample point
230  double xv = xi!=NULL?xi[i]:x[0]+i*dxi;
231 
232  // are we within input x-range?
233  if (xv < x[0] || xv > x[N-1])
234  continue;
235 
236  //binary search
237  int i1 = 0;
238  int i2 = N-1;
239  while(i2 > (i1+1)) {
240  int mid = (i2+i1)/2;
241  if (x[mid] <= xv) {
242  i1 = mid;
243  } else {
244  i2 = mid;
245  }
246  }
247 
248  switch (meth) {
249  case _LINEAR_IP:
250  yi[i] = y[i1] + (y[i2]-y[i1])/(x[i2]-x[i1])*(xv-x[i1]);
251  break;
252  case _NEAREST_IP:
253  if ((xi[i]-x[i1])>= (x[i2]-xi[i]))
254  yi[i] = y[i1];
255  else
256  yi[i] = y[i2];
257  break;
258  }
259  }
260 }
261 
262 } // namespace limpet
Basic utility structs and functions, mostly IO related.
#define log_msg(F, L, O,...)
Definition: filament.h:8
V clamp(const V val, const W start, const W end)
Clamp a value into an interval [start, end].
Definition: kdpart.hpp:117
int mk_RRC_trace(trace *tr, float st, float delay, float clamp, float dur)
make a trace for a repolarization reserve current calculation
Definition: trace.cc:48
double trace_duration(trace *tr, const char *f)
Definition: trace.cc:179
void resample_trace(trace *tr, double dt)
Definition: trace.cc:147
void free_trace(trace *tr)
Definition: trace.cc:108
void set_trace_amp(trace *tr, float val, float whenceforth)
change the amplitude of part of a trace
Definition: trace.cc:28
void interp1(const double *x, const float *y, int N, double *xi, float *yi, int NI, double dxi, IpMeth_t meth)
Definition: trace.cc:221
int read_trace(trace *tr, const char *name)
Definition: trace.cc:75
bool IsEquDistSampling(trace *tr)
Definition: trace.cc:122
enum limpet::ip_method IpMeth_t
@ _NEAREST_IP
Definition: trace.h:21
@ _LINEAR_IP
Definition: trace.h:21
manage input, output, resampling of traces
Definition: trace.h:10
double dt
sampling interval if equidistant samples
Definition: trace.h:15
double dur
duration
Definition: trace.h:14
bool eqdist
sampling intervals are equidistant
Definition: trace.h:16
float * s
samples
Definition: trace.h:13
int N
number of samples
Definition: trace.h:11
double * t
time vector
Definition: trace.h:12