openCARP
Doxygen code documentation for the open cardiac electrophysiology simulator openCARP
signals.h
Go to the documentation of this file.
1 // ----------------------------------------------------------------------------
2 // openCARP is an open cardiac electrophysiology simulator.
3 //
4 // Copyright (C) 2020 openCARP project
5 //
6 // This program is licensed under the openCARP Academic Public License (APL)
7 // v1.0: You can use and redistribute it and/or modify it in non-commercial
8 // academic environments under the terms of APL as published by the openCARP
9 // project v1.0, or (at your option) any later version. Commercial use requires
10 // a commercial license (info@opencarp.org).
11 //
12 // This program is distributed without any warranty; see the openCARP APL for
13 // more details.
14 //
15 // You should have received a copy of the openCARP APL along with this program
16 // and can find it online: http://www.opencarp.org/license
17 // ----------------------------------------------------------------------------
18 
27 #ifndef SIGNAL
28 #define SIGNAL
29 
30 #include <string>
31 #include <assert.h>
32 #include <math.h>
33 #include <iostream>
34 #include <fstream>
35 #include <algorithm>
36 #include <iomanip>
37 #include <sstream>
38 
39 #include "SF_vector.h"
40 namespace opencarp {
41 namespace sig {
42 
43 typedef double sReal;
44 
45 // trailing underscore added to avoid clash with bidomain.h
46 // Stimulation.c needs to be modified to make use of traces as used in here
48 
49 template<typename V>
50 V mod(const V& a, const V& b)
51 {
52  return (a % b + b) % b;
53 }
54 
58  public:
60  bool header_on;
61  std::string header;
62  std::string col_sep;
63  int fmt_id;
65 
66  time_trace_ffmt() : time_trace_ffmt( true, false, "", " ", 1)
67  {}
68 
69  time_trace_ffmt(bool num_samples_on_, bool header_on_, std::string header_, std::string col_sep_)
70  : time_trace_ffmt(num_samples_on_, header_on_, header_, col_sep_, 1 )
71  {}
72 
73  time_trace_ffmt(bool num_samples_on_, bool header_on_, std::string header_, std::string col_sep_, int fmt_id_)
74  : num_samples_on(num_samples_on_), header_on(header_on_), header(header_), col_sep(col_sep_), fmt_id(fmt_id_)
75  {
76  // default column width is 8
77  colw = {8, 8};
78  }
79 
80  int parse_header(std::ifstream& inpf);
81 };
82 
85 inline int time_trace_ffmt::parse_header(std::ifstream& inpf)
86 {
87  int err = 0;
88 
89  // assume no comment, data section starts at the beginning
90  std::streampos start_of_data = inpf.beg;
91 
92  // read in first line
93  std::string line{};
94  std::getline(inpf,line);
95 
96  // comment line?
97  std::size_t found_hash = line.find_first_of("#");
98  if(found_hash != std::string::npos)
99  {
100  // keep reading comment lines
101  start_of_data = inpf.tellg();
102  }
103  else
104  {
105  // no header, check for number of samples
106  sReal t, f;
107  size_t items = sscanf(line.c_str(),"%lf %lf", &t, &f);
108 
109  if(items != 2)
110  {
111  // line holds number of samples
112  int num_samples{0};
113  size_t item = sscanf(line.c_str(),"%d", &num_samples);
114  if(!item)
115  err = -1;
116  else {
117  num_samples_on = true;
118  // put back
119  //for(size_t i=0; i<line.size(); i++)
120  //inpf.unget();
121  }
122  }
123  else
124  {
125  // we found a time value pair
126  num_samples_on = false;
127  }
128 
129  // set stream pointer back to start of data section
130  inpf.seekg(start_of_data,inpf.beg);
131  }
132  return err;
133 }
134 
143  public:
144  std::string label;
145  std::string t_unit;
146  std::string f_unit;
149  sReal dt;
150  sReal rtOff;
151  bool fade;
152 
153  // constructors
154 
156  time_trace() : time_trace( 1000., 10.0e-3, 0.0)
157  {}
158 
160  time_trace(sReal _dt) : time_trace(1000., _dt, 0.)
161  {}
162 
164  time_trace(sReal _duration, sReal _dt) : time_trace(_duration, _dt, 0.)
165  {}
166 
167  time_trace(sReal _duration, sReal _dt, sReal _rtOff, std::string _label) :
168  time_trace(_duration, _dt, _rtOff, _label, "", "")
169  {}
170 
172  time_trace(sReal _duration, sReal _dt, sReal _rtOff) : time_trace(_duration, _dt, _rtOff, "", "", "")
173  {}
174 
176  time_trace(sReal _duration, sReal _dt, sReal _rtOff, std::string _label, std::string _t_unit, std::string _f_unit)
177  {
178  dt = _dt;
179  rtOff = _rtOff;
180  int N = ceil(_duration/dt) + 1;
181 
182  f.assign(N, 0.0);
183  t.resize(N);
184 
185  sReal ct = 0;
186  for(size_t i=0; i<t.size(); i++) {
187  t[i] = ct;
188  ct += dt;
189  }
190 
191  set_labels(_label, _t_unit, _f_unit);
192  }
193 
195  {
196  label = in.label;
197  t_unit = in.t_unit;
198  f_unit = in.f_unit;
199  f = in.f;
200  t = in.t;
201  dt = in.dt;
202  rtOff = in.rtOff;
203  fade = in.fade;
204 
205  return *this;
206  }
207 
210  {
211  *this = a;
212  }
213 
215  time_trace(const time_trace& a, sReal val) : time_trace(a)
216  {
217  // use standard copy constructor and initialize signal with constant value
218  std::fill(f.begin(), f.end(), val);
219  }
220 
222  std::string format_file_header(const time_trace_ffmt ffmt_spec);
223 
224 
226  void operator *= (const time_trace& a);
227  void operator *= (const sReal s);
228  void operator += (const sReal a);
229  void operator += (const time_trace& a);
230  void operator <<= (int delta);
231  void operator >>= (int delta);
232 
233  // member functions
234  void set_labels(std::string _label)
235  {
236  label = _label;
237  }
238 
239  void set_labels(std::string _label, std::string _t_unit, std::string _f_unit)
240  {
241  label = _label;
242  setUnits(_t_unit, _f_unit);
243  }
244 
245  void setUnits(std::string _t_unit, std::string _f_unit)
246  {
247  t_unit = _t_unit;
248  f_unit = _f_unit;
249  }
250 
251  void resize(int numSamples)
252  {
253  t.resize(numSamples);
254  f.resize(numSamples);
255  }
256 
257  sReal duration ()
258  {
259  //return f.back();
260  return t[t.size()-1];
261  }
262 
263  size_t len() const
264  {
265  return t.size();
266  }
267 
268  sReal rta()
269  {
270  for(std::size_t i=0; i<len(); i++)
271  t[i] += rtOff;
272 
273  rtOff = 0.;
274 
275  return t[0];
276  }
277 
278  sReal zta()
279  {
280  rtOff = t[0];
281  for(std::size_t i=0; i<len(); i++)
282  t[i] -= rtOff;
283 
284  return -rtOff;
285  }
286 
287  // signal processing
288 
297  {
298  for(std::size_t i=0; i<len()-1; i++)
299  f[i] = f[i+1] - f[i];
300 
301  // last sample has no difference
302  f[len()-1] = 0.;
303 
304  return f;
305  }
306 
315  {
316  auto dFdt = f;
317 
318  int N = len();
319  int end = N-1;
320 
321  // take forward/backward difference at left/right edge
322  dFdt[0] = (f[1] - f[0]) / (t[1] - t[0]);
323  dFdt[end] = (f[end] - f[end-1]) / (t[end] - t[end-1]);
324 
325  // take centered differences on interior points
326  for(int i=1; i<end-1; i++)
327  {
328  sReal fdF = (f[i ] - f[i-1]) / (t[i ] - t[i-1]);
329  sReal bdF = (f[i+1] - f[i ]) / (t[i+1] - t[i ]);
330 
331  dFdt[i] = (fdF + bdF) * 0.5;
332  }
333 
334  // overwrite f
335  f = dFdt;
336 
337  return f;
338  }
339 
340  // time trace I/O
341  int read_trace(const std::string fname);
342  int read_trace(const std::string fname, bool unitize);
343 
344  int write_trace();
345  int write_trace(const std::string fname);
346  int write_trace(const std::string fname, time_trace_ffmt ffmt_spec);
347 
348 
349  // shift operations
350  size_t timeShift(sReal t_shift)
351  {
352  int dI = t_shift/dt;
353 
354  return dI;
355  }
356 
357 
358  // scaling functions
359 
362  void unitize()
363  {
364  assert(len()>0);
365 
366  sReal _mn = f[0];
367  sReal _mx = f[0];
368 
369  for (std::size_t i=1;i<len();i++) {
370  if (f[i] > _mx)
371  _mx = f[i];
372  else
373  if (f[i] < _mn)
374  _mn = f[i];
375  }
376 
377  //pair<SF::vector<int>::iterator, SF::vector<int>::iterator> mnmx;
378  //eal __mx, __mn;
379  //auto mnmx = std::minmax_element(f.begin(),f.end());
380  //__mn = nmx.first;
381  //__mx = mnmx.second;
382 
383  sReal unsc = fabs(_mx)>=fabs(_mn) ? 1./fabs(_mx):1./fabs(_mn);
384 
385  for (std::size_t i=0;i<len();i++)
386  f[i] *= unsc;
387 
388  }
389 
390 
391  // interpolation functions
392 
400  {
401  sReal dt_o = t[1] - t[0];
402 
403  // differences in sampling should be less than 0.1%
404  sReal r_err = 0.001*dt_o;
405 
406  for (std::size_t i=1; i<len()-1; i++) {
407  sReal dt_n = t[i+1] - t[i];
408  if ( (dt_n - dt_o) > r_err)
409  return false;
410  }
411 
412  return true;
413  }
414 
417  sReal fval_t(sReal _t)
418  {
419  if(_t < t[0])
420  return fade ? 0. : f[0];
421 
422  if(_t > t.back())
423  return fade ? 0. : f.back();
424 
425  int i = 0;
426  while(t[i] <= _t) i++;
427 
428  sReal K = (f[i] - f[i-1]) / (t[i] - t[i-1]);
429  sReal fval = f[i-1] + K * (_t - t[i-1]);
430 
431  return fval;
432  }
433 
434  void resample(time_trace& trc)
435  {
436  for(std::size_t i=0; i<trc.len(); i++)
437  trc.f[i] = fval_t(trc.t[i]);
438  }
439 
440  void resample(time_trace& trc, IpMeth_t meth)
441  {
442  interp1(trc, meth);
443  }
444 
455  void
456  interp1(time_trace& trc, IpMeth_t meth)
457  {
458 
459  // iterate over target array
460  for (std::size_t i=0; i<trc.len(); i++) {
461 
462  // data point to interpolate on
463  sReal _t = trc.t[i];
464 
465  // are we within input x-range?
466  if ( (_t < t[0]) || (_t > t.back()) )
467  continue;
468 
469  //binary search
470  int i1 = 0;
471  int i2 = len()-1;
472  while(i2 > (i1+1)) {
473  int mid = (i2+i1)/2;
474  if (t[mid] <= _t) {
475  i1 = mid;
476  } else {
477  i2 = mid;
478  }
479  }
480 
481  switch (meth) {
482  case _LINEAR_IP:
483  trc.f[i] = f[i1] + (f[i2]-f[i1])/(t[i2]-t[i1])*(_t-t[i1]);
484  break;
485  case _NEAREST_IP:
486  if ((trc.t[i]-t[i1]) >= (t[i2]-trc.t[i]))
487  trc.f[i] = f[i1];
488  else
489  trc.f[i] = f[i2];
490  break;
491  }
492  }
493  }
494 
495 };
496 
497 
500 {
501  assert( len() == a.len() );
502 
503  for(size_t i=0; i<len(); i++)
504  f[i] *= a.f[i];
505 }
506 
507 
508 inline void time_trace::operator *= (const sReal s)
509 {
510  for(auto & v : f) v *= s;
511 }
512 
513 inline void time_trace::time_trace::operator += (const sReal a)
514 {
515  for(auto & v : f) v += a;
516 }
517 
518 
520 {
521  assert( len() == a.len() );
522 
523  for(size_t i=0; i<len(); i++)
524  f[i] += a.f[i];
525 }
526 
527 inline void time_trace::operator <<= (int delta)
528 {
529  bool ring = delta < 0; // ring shift?
530  int N = len();
531 
532  if(ring)
533  delta = -delta;
534 
535  // ring buffer shift
536  SF::vector<sReal>tmp = f;
537  for(int i=0; i<N; i++)
538  f[mod((i-delta),N)] = tmp[i];
539 
540  // not ring, override
541  if(!ring)
542  for(std::size_t i=len()-delta;i<len();i++)
543  f[i] = 0.;
544 }
545 
546 inline void time_trace::operator >>= (int delta)
547 {
548  bool ring = delta < 0;
549  int N = len();
550 
551  if(ring)
552  delta = -delta;
553 
554  // ring buffer shift
555  SF::vector<sReal>tmp = f;
556  for(int i=0; i<N; i++)
557  f[mod((i+delta),N)] = tmp[i];
558 
559  // not ring, override
560  if(!ring)
561  for(int i=0;i<delta;i++)
562  f[i] = 0.;
563 }
564 
567 inline std::string time_trace::format_file_header(const time_trace_ffmt ffmt_spec)
568 {
569  std::ostringstream sheader_;
570 
571  if(ffmt_spec.header_on)
572  {
573  // write trace header comment section, for now this is empty
574  sheader_ << "# " << ffmt_spec.header << std::endl;
575 
576  // in this case we also print the format identifier
577  sheader_ << "# version = " << ffmt_spec.fmt_id << std::endl;
578 
579  // write column table header
580  sheader_ << "#" << std::endl;
581  sheader_ << "# TABLE_HEAD" << std::endl;
582  sheader_ << "# A = time" << std::endl;
583  sheader_ << "# B = " << label << std::endl;
584  sheader_ << "# [" << std::setw(ffmt_spec.colw[0]) << "A" << "]";
585  sheader_ << "[" << std::setw(ffmt_spec.colw[1]) << "B" << "]" << std::endl;
586  sheader_ << "# [" << std::setw(ffmt_spec.colw[0]) << t_unit << "]";
587  sheader_ << "[" << std::setw(ffmt_spec.colw[1]) << f_unit << "]" << std::endl;
588  sheader_ << "#" << std::endl;
589  sheader_ << "# DATA" << std::endl;
590  }
591 
592  if(ffmt_spec.num_samples_on)
593  // first line holds # of samples
594  sheader_ << len() << std::endl;
595 
596  std::string sheader = sheader_.str();
597 
598  return sheader;
599 }
600 
601 
604 /*
605 sReal duration(const std::string fname)
606 {
607  time_trace tmp;
608 
609  int err = tmp.read_trace(fname);
610 
611  return !err ? tmp.t.back() : -1;
612 }
613 */
614 
623 inline int time_trace::read_trace(std::string fname)
624 {
625  int err = 0;
626 
627  std::ifstream inpf(fname);
628 
629  // If we couldn't open the output file stream for writing
630  if (!inpf)
631  {
632  // Print an error and exit
633  std::cerr << "Trace file " << fname << " could not be opened for reading!" << std::endl;
634  err = -1;
635  }
636  else {
637 
638  time_trace_ffmt tt_ffmt{};
639 
640  tt_ffmt.parse_header(inpf);
641 
642  // first line holds # of samples
643  int numSamples{0};
644  if(tt_ffmt.num_samples_on)
645  {
646  inpf >> numSamples;
647 
648  // adjust signal buffer size
649  resize(numSamples);
650  }
651 
652  // read time/sample pairs
653  int i = 0;
654  while( inpf >> t[i] >> f[i] )
655  i++;
656 
657  if(tt_ffmt.num_samples_on)
658  {
659  if(i<numSamples || i<2)
660  err = -2;
661  }
662 
663  inpf.close();
664  }
665 
666  if(err)
667  return err;
668 
669  // fill trace data
670  // get units from comments header, if available
671  // set label from filename
672  // resample file according to given dt
673 
674  return err;
675 }
676 
677 
683 inline int time_trace::read_trace(std::string fname, bool _unitize)
684 {
685  int err = read_trace(fname);
686 
687  if(!err && _unitize)
688  unitize();
689 
690  return err;
691 }
692 
702 {
703  return write_trace(label + ".trc");
704 }
705 
706 
716 inline int time_trace::write_trace(const std::string fname)
717 {
718  time_trace_ffmt ffmt_spec;
719  int err = write_trace(fname, ffmt_spec);
720 
721  return err;
722 }
723 
733 inline int time_trace::write_trace(const std::string fname, time_trace_ffmt ffmt_spec)
734 {
735  int err = 0;
736 
737  std::ofstream outf(fname);
738 
739  // If we couldn't open the output file stream for writing
740  if (!outf) {
741  // Print an error and exit
742  std::cerr << "Trace file " << fname << " could not be opened for writing!" << std::endl;
743  err = -1;
744  }
745  else {
746  if(ffmt_spec.header_on)
747  {
748  // write trace file header
749  outf << format_file_header(ffmt_spec); //ffmt_spec.header_string(len());
750  }
751 
752  // write number of samples in file
753  if(ffmt_spec.num_samples_on)
754  outf << len() << std::endl;
755 
756  // data section
757  // write time/sample pairs
758  outf << std::fixed;
759  for(std::size_t i=0; i<len(); i++)
760  {
761  outf << std::setw(ffmt_spec.colw[0]+3) << std::setprecision(3) << t[i] << ffmt_spec.col_sep;
762  outf << std::setw(ffmt_spec.colw[1]+1) << std::setprecision(6) << f[i] << std::endl;
763  }
764  outf.close();
765  }
766 
767  return err;
768 }
769 
770 // define time_trace arithmetics
771 inline time_trace operator * (const time_trace& a, const time_trace& b)
772 {
773  assert( a.len() == b.len() );
774 
775  time_trace _mult = a;
776 
777  for(std::size_t i=0; i<a.len(); i++)
778  _mult.f[i] = a.f[i] * b.f[i];
779 
780  return _mult;
781 }
782 
783 inline time_trace operator / (const time_trace& a, const time_trace& b)
784 {
785  assert( a.len() == b.len() );
786 
787  time_trace _div = a;
788 
789  for(std::size_t i=0; i<a.len(); i++)
790  _div.f[i] = a.f[i] / b.f[i];
791 
792  return _div;
793 }
794 
795 inline time_trace operator + (const time_trace& a, const time_trace& b)
796 {
797  assert( a.len() == b.len() );
798 
799  time_trace _add = a;
800  for(std::size_t i=0; i<a.len(); i++)
801  _add.f[i] = a.f[i] + b.f[i];
802 
803  return _add;
804 }
805 
806 inline time_trace operator - (const time_trace& a, const time_trace& b)
807 {
808  assert( a.len() == b.len() );
809 
810  time_trace _sub = a;
811  for(std::size_t i=0; i<a.len(); i++)
812  _sub.f[i] = a.f[i] - b.f[i];
813 
814  return _sub;
815 }
816 
817 // truncated exponential pulse definition
818 class Pulse
819 {
820  public:
821  sReal duration;
822  float strength;
823  double d1;
824  float tau_edge;
825  float tau_plat;
826  int decay;
827  float s2r;
828  float bias;
829  bool constant;
830 
831  // constructor
833  {
834  duration = 1.0;
835  strength = 1.0;
836  d1 = 1.0;
837  tau_edge = 0.1;
838  tau_plat = 1000.0;
839  decay = 5.0;
840  s2r = 0.0;
841  bias = 0.0;
842  constant = false;
843  }
844 
845  //waveForm defineWave(
846 };
847 
848 // action potential foot definition
849 class APfoot
850 {
851  public:
852  sReal tau_f;
853  sReal A;
854  sReal B;
855 
856  // constructor
858  {
859  tau_f = 0.25;
860  A = 1.00;
861  B = -80.0;
862  }
863 };
864 
865 // step function
866 class Step {
867  public:
868  sReal trig;
869  bool rise;
870 
871  // constructor
873  {
874  trig = 0;
875  rise = true;
876  }
877 };
878 
879 // sine waves
880 class sineWave {
881  public:
882  sReal frq;
883  float phase;
884 
886  {
887  frq = 1.;
888  phase = 0.;
889  }
890 
891  sineWave(sReal _frq, sReal _phase) : frq(_frq)
892  {
893  phase = _phase;
894  }
895 };
896 
897 // abstract trace sampling function
899  public:
900  virtual SF::vector<sReal> & sample (time_trace &trc) = 0;
901 };
902 
903 
912 {
913  public:
914  sReal val;
915 
916  constFunc(sReal _val) : val(_val)
917  {}
918 
920  {
921  for(std::size_t i=0; i<trc.len(); i++)
922  trc.f[i] = val;
923 
924  return trc.f;
925  }
926 };
927 
933 class stepFunc : public sampleTraceFunc
934 {
935 
936  public:
938 
939  stepFunc(Step _pars) : pars(_pars)
940  {}
941 
943  {
944  sReal off = pars.rise ? 1. : 0.;
945  sReal on = pars.rise ? 0. : 1.;
946  for(std::size_t i=0; i<trc.t.size(); i++)
947  trc.f[i] = trc.t[i] < pars.trig ? on : off;
948 
949  return trc.f;
950  }
951 };
952 
955 class sineFunc : public sampleTraceFunc
956 {
957  public:
959 
960  sineFunc(sineWave _pars) : pars(_pars)
961  {}
962 
964  {
965  sReal phase_shift = pars.phase/180*M_PI;
966  for(std::size_t i=0; i<trc.len(); i++)
967  trc.f[i] = sin(2*M_PI*pars.frq*trc.t[i] + phase_shift);
968 
969  return trc.f;
970  }
971 };
972 
976 {
977  public:
979 
980  APfootFunc(APfoot _pars) : pars(_pars)
981  {}
982 
984  {
985  for(std::size_t i=0; i<trc.len(); i++)
986  trc.f[i] = pars.A*exp(trc.t[i]/pars.tau_f) + pars.B;
987 
988  return trc.f;
989  }
990 };
991 
995 {
996  public:
998 
999  monophasicTruncExpFunc(Pulse _pars) : pars(_pars)
1000  {}
1001 
1003  {
1004  double t0 = 0.;
1005  double t1 = t0 + pars.d1 - 5*pars.tau_edge;
1006  //double t2 = t0 + pars.d1;
1007 
1008  // first phase exponential rise and plateau
1009  time_trace zero(trc);
1010  //zero = 0.;
1011  time_trace phase_0 = zero;
1012 
1013  for(std::size_t i=0; i<trc.t.size(); i++)
1014  {
1015  sReal f0 = pars.tau_edge ? -expm1(-(trc.t[i]-t0)/pars.tau_edge):1.;
1016  sReal fp = exp(-(trc.t[i]-t0)/pars.tau_plat);
1017 
1018  phase_0.f[i]= f0*fp*pars.strength;
1019  }
1020 
1021  // end of plateau, exponential decay
1022  time_trace eps_0 = zero;
1023  time_trace eps_1 = zero;
1024 
1025  // step function
1026  Step stepPars;
1027  stepPars.trig = t1;
1028  stepPars.rise = false;
1029 
1030  // eps+, falling eps function 1 | 0
1031  stepFunc eps(stepPars);
1032  eps.sample(eps_0);
1033 
1034  // eps-, rising eps function 0 | 1
1035  eps.pars.rise = true;
1036  eps.sample(eps_1);
1037 
1038  // final falling phase
1039  time_trace phase_1 = zero;
1040  int i1 = int(t1/trc.dt);
1041  sReal f0 = phase_0.f[i1];
1042  for(std::size_t i=i1; i<trc.len(); i++)
1043  phase_1.f[i] = f0*exp(-(trc.t[i]-t1)/pars.tau_edge);
1044 
1045  // assemble pulse components
1046  time_trace pulse = phase_0 * eps_0 + phase_1 * eps_1;
1047  // this does not work, lvalue is time_trace &
1048  //trc = phase_0 * eps_0 + phase_1 * eps_1;
1049  trc = pulse;
1050 
1051  // add bias
1052  trc += pars.bias;
1053 
1054  return trc.f;
1055  }
1056 };
1057 
1061 {
1062  public:
1064 
1065  biphasicTruncExpFunc(Pulse _pars) : pars(_pars)
1066  {}
1067 
1069  {
1070  // create first phase
1071  monophasicTruncExpFunc cdmFunc1(pars);
1072  cdmFunc1.sample(trc);
1073 
1074  // create second phase, determine tilt
1075  if(pars.s2r == 0.)
1076  {
1077  int ph1_i1 = int((pars.d1 - 5*pars.tau_edge)/trc.dt);
1078  pars.strength = -trc.f[ph1_i1];
1079  }
1080  else
1081  pars.strength = -pars.s2r*pars.strength;
1082 
1083  time_trace ph2(trc);
1084  //ph2 = 0.;
1085  monophasicTruncExpFunc cdmFunc2(pars);
1086  cdmFunc2.sample(ph2);
1087 
1088  // shift phase 2 relative to phase 1
1089  ph2 >>= (pars.d1 - 5*pars.tau_edge)/trc.dt;
1090 
1091  trc += ph2;
1092 
1093  return trc.f;
1094  }
1095 };
1096 
1097 } // namespace sig
1098 } // namespace opencarp
1099 
1100 #endif
1101 
sReal tau_f
time constant of AP foot
Definition: signals.h:852
double sReal
Definition: signals.h:43
sReal A
change in delta Vm over tau_f
Definition: signals.h:853
sReal duration
pulse duration, default is 1 ms
Definition: signals.h:821
void operator<<=(int delta)
Definition: signals.h:527
The vector class and related algorithms.
constFunc(sReal _val)
Definition: signals.h:916
std::string col_sep
column separator, either " " or ","
Definition: signals.h:62
virtual SF::vector< sReal > & sample(time_trace &trc)
Definition: signals.h:1068
float s2r
strength of subpulse relative to leading pulse (biphasic pulse)
Definition: signals.h:827
float bias
constant term to add to stimulus waveform
Definition: signals.h:828
bool header_on
turn on header output
Definition: signals.h:60
int fmt_id
format identifier
Definition: signals.h:63
time_trace(sReal _duration, sReal _dt, sReal _rtOff, std::string _label)
Definition: signals.h:167
sReal dt
temporal discretization of trace, if regularly sampled
Definition: signals.h:149
int read_trace(const std::string fname)
determine duration of a signal stored in file
Definition: signals.h:623
int read_trace(trace *tr, const char *name)
Definition: trace.cc:43
float tau_plat
time constant governing plateau of pulse
Definition: signals.h:825
int parse_header(std::ifstream &inpf)
parse trace header from file
Definition: signals.h:85
time_trace_ffmt(bool num_samples_on_, bool header_on_, std::string header_, std::string col_sep_)
Definition: signals.h:69
stepFunc(Step _pars)
Definition: signals.h:939
void operator*=(const time_trace &a)
overloaded operators
Definition: signals.h:499
virtual SF::vector< sReal > & sample(time_trace &trc)
Definition: signals.h:983
virtual SF::vector< sReal > & sample(time_trace &trc)
Definition: signals.h:963
std::string label
descriptive label of signal
Definition: signals.h:144
size_t len() const
< length of trace in samples
Definition: signals.h:263
SF::vector< sReal > t
time axis
Definition: signals.h:148
time_trace(const time_trace &a)
copy constructor with setting of constant signal value
Definition: signals.h:209
time_trace operator/(const time_trace &a, const time_trace &b)
Definition: signals.h:783
float phase
phase in degree
Definition: signals.h:883
void set_labels(std::string _label, std::string _t_unit, std::string _f_unit)
Definition: signals.h:239
std::string format_file_header(const time_trace_ffmt ffmt_spec)
IO format file header from format specifciation and given time trace.
Definition: signals.h:567
bool IsEquDistSampling()
check whether time trace is sampled with constant sampling interval
Definition: signals.h:399
V mod(const V &a, const V &b)
Definition: signals.h:50
time_trace(sReal _duration, sReal _dt, sReal _rtOff)
Definition: signals.h:172
bool fade
signal fades to zero after end or remains at final amplitude
Definition: signals.h:151
monophasic truncated exponentials (capacitive discharge)
Definition: signals.h:994
const T * end() const
Pointer to the vector&#39;s end.
Definition: SF_vector.h:128
void interp1(time_trace &trc, IpMeth_t meth)
interpolate a time trace
Definition: signals.h:456
time_trace operator*(const time_trace &a, const time_trace &b)
Definition: signals.h:771
time_trace(sReal _dt)
prescribe dt only, default duration is 1000. ms
Definition: signals.h:160
std::string f_unit
unit of signal
Definition: signals.h:146
sReal B
baseline offset
Definition: signals.h:854
time_trace & operator=(const time_trace &in)
Definition: signals.h:194
bool num_samples_on
turn on # of samples output
Definition: signals.h:59
T & back()
Definition: SF_vector.h:144
float tau_edge
time constant for leading/trailing edges
Definition: signals.h:824
time_trace(sReal _duration, sReal _dt)
prescribe duration and sampling, use default real time offset
Definition: signals.h:164
void operator>>=(int delta)
Definition: signals.h:546
size_t timeShift(sReal t_shift)
Definition: signals.h:350
double d1
duration of first sub-pulse in [ms] (zero with monophasic pulse)
Definition: signals.h:823
void setUnits(std::string _t_unit, std::string _f_unit)
Definition: signals.h:245
std::string t_unit
unit of time axis
Definition: signals.h:145
time_trace()
use defaults only, 1000 ms duration, 10 us sampling interval, no real time offset ...
Definition: signals.h:156
std::string header
header
Definition: signals.h:61
biphasic truncated exponentials (capacitive discharge)
Definition: signals.h:1060
virtual SF::vector< sReal > & sample(time_trace &trc)
Definition: signals.h:1002
void resample(time_trace &trc, IpMeth_t meth)
Definition: signals.h:440
Time tracing class.
Definition: signals.h:142
time_trace operator+(const time_trace &a, const time_trace &b)
Definition: signals.h:795
action potential foot pulse
Definition: signals.h:975
int decay
edge decay time (multiples of tau_edge)
Definition: signals.h:826
virtual SF::vector< sReal > & sample(time_trace &trc)
Definition: signals.h:919
sReal rtOff
real time offset of time axis
Definition: signals.h:150
void operator+=(const sReal a)
void set_labels(std::string _label)
Definition: signals.h:234
SF::vector< sReal > & gradient()
Definition: signals.h:314
int write_trace()
write traces to file
Definition: signals.h:701
time_trace(const time_trace &a, sReal val)
copy constructor with setting of constant signal value
Definition: signals.h:215
sReal fval_t(sReal _t)
retrieve value of a function at a given time t
Definition: signals.h:417
constant function
Definition: signals.h:911
void resample(time_trace &trc)
Definition: signals.h:434
sineWave(sReal _frq, sReal _phase)
Definition: signals.h:891
SF::vector< int > colw
width of columns
Definition: signals.h:64
sineFunc(sineWave _pars)
Definition: signals.h:960
size_t size() const
The current size of the vector.
Definition: SF_vector.h:104
bool constant
constant value for all time
Definition: signals.h:829
time_trace(sReal _duration, sReal _dt, sReal _rtOff, std::string _label, std::string _t_unit, std::string _f_unit)
full constructor, prescribe all members
Definition: signals.h:176
manage trace format
Definition: signals.h:57
SF::vector< sReal > & diff()
Definition: signals.h:296
#define M_PI
Definition: ION_IF.h:51
time_trace operator-(const time_trace &a, const time_trace &b)
Definition: signals.h:806
void unitize()
scale signal to unity strength
Definition: signals.h:362
const T * begin() const
Pointer to the vector&#39;s start.
Definition: SF_vector.h:116
float strength
pulse amplitude, default is unit strength
Definition: signals.h:822
void assign(InputIterator s, InputIterator e)
Assign a memory range.
Definition: SF_vector.h:161
APfootFunc(APfoot _pars)
Definition: signals.h:980
void resize(size_t n)
Resize a vector.
Definition: SF_vector.h:209
virtual SF::vector< sReal > & sample(time_trace &trc)
Definition: signals.h:942
void resize(int numSamples)
Definition: signals.h:251
step function
Definition: signals.h:933
SF::vector< sReal > f
store function values of trace
Definition: signals.h:147
sReal frq
freq in [kHz]
Definition: signals.h:882
void interp1(const double *x, const float *y, int N, double *xi, float *yi, int NI, double dxi, IpMeth_t meth)
Definition: trace.cc:189
time_trace_ffmt(bool num_samples_on_, bool header_on_, std::string header_, std::string col_sep_, int fmt_id_)
Definition: signals.h:73
enum opencarp::sig::ip_method IpMeth_t