openCARP
Doxygen code documentation for the open cardiac electrophysiology simulator openCARP
IGBfilament.cc
Go to the documentation of this file.
1 /*
2  * Calculate phase signularities based on Martin Bishop's isovalue approach.
3  */
4 
5 #include <string>
6 #include "IGBheader.h"
7 #include "filament.h"
8 #include <iostream>
9 #include "fil_cmdline.h"
10 
11 #define BUFSIZE 1024
12 
13 int initTBuffer (tbuffer *tbf, double dt);
14 int shiftTBuffer(tbuffer *tbf);
15 void freeTBuffer (tbuffer *tbf);
16 void read_mesh(std::string,ElemList *, NodeList*);
17 
18 //
19 #undef __FUNCT__
20 #define __FUNCT__ "main"
21 int main( int argc, char *argv[] )
22 {
23  ElemList el;
24  ElemList *elst = &el;
25  NodeList nl;
26  NodeList *nlst = &nl;
27  char *dn = NULL;
28 
29  struct gengetopt_args_info args;
30 
31  if (cmdline_parser(argc, argv, &args) != 0)
32  return 1;
33 
34  // Positional arguments are all argv after all options
35  // Using cmdline_parser’s internal method:
36  int first_pos = argc - args.inputs_num; // inputs_num counts leftover arguments
37  if (args.inputs_num != 2) {
38  fprintf(stderr, "Error: Missing required positional arguments.\n");
39  cmdline_parser_print_help();
40  return 1;
41  }
42  char *basemesh = argv[first_pos]; // first positional argument
43  char *igb_data_file = argv[first_pos+1]; // second positional argument
44 
45  float dt = args.dt_arg;
46  float vth = args.threshold_arg;
47  std::string aux_mesh = args.aux_mesh_arg;
48 
49 
50  read_mesh(const_cast<char*>(basemesh), elst, nlst);
51 
52  // initialize time slice buffer
53  tbuffer tbf;
54  tbf.dname = igb_data_file;
55  tbf.dsize = sizeof(float);
56  tbf.rwdth = 2; // two samples where we resample signal
57  tbf.t = 0.;
58 
59  int nSliceRead = initTBuffer(&tbf,dt);
60  if( nSliceRead<0 ) exit(1);
61 
62  // initialize filaments
63  FILE *filHdls[3];
64  init_filament_IO(aux_mesh.c_str(),tbf.numSamps,filHdls);
65 
66  // write bogus empty frames to keep the #slices the same as the IGB file
67  for(int i=0;i<nSliceRead/2;i++) {
68  filament f;
69  write_filaments(&f,filHdls,tbf.t);
70  tbf.t += tbf.dt_in;
71  }
72 
73  // loop over file
74  for(int i=0;i<tbf.numSamps-nSliceRead;i++) {
75 
76  log_msg(NULL,0,0, "\nAnalyzing instant %.3f ms --- ", tbf.t);
77  filament f;
78  if(tbf.filled) {
79 
80  // make sure data are at +/- dt/2
81  interpolateTBuffer(&tbf);
82 
83  // dm1 and d1 hold data now at the interval dt
85  compute_filament((float*)tbf.dr[0], (float*)tbf.dr[1], vth,elst, nlst, &f, meth);
86  }
87  write_filaments(&f,filHdls,tbf.t);
88 
89  int err = shiftTBuffer(&tbf);
90  }
91 
92  // write bogus empty frames to keep the #slices the same as the IGB file
93  for(int i=0;i<nSliceRead-nSliceRead/2;i++) {
94  filament f;
95  write_filaments(&f,filHdls,tbf.t);
96  tbf.t += tbf.dt_in;
97  }
98 
99  log_msg(NULL,0,0, "\n");
100 
101  // close files
102  close_filament_IO(filHdls);
103  fclose( tbf.data );
104 
105  // deconstruct
106  freeTBuffer(&tbf);
107 
108  cmdline_parser_free(&args);
109 }
110 
111 
118 int
119 initTBuffer(tbuffer *tbf,double dt)
120 {
121  // open data file first
122  int IOerr = 0;
123  tbf->data = fopen(tbf->dname,"rb");
124  if(tbf->data!=NULL)
125  tbf->igb = new IGBheader( tbf->data, true );
126 
127  tbf->numSamps = tbf->igb->t();
128  tbf->nodes = tbf->igb->x();
129  tbf->dt_in = tbf->igb->inc_t();
130  tbf->h_wdth = ceil(dt/tbf->dt_in/2);;
131  tbf->wdth = tbf->h_wdth*2+1;
132 
133  float h_range_T = tbf->h_wdth*tbf->dt_in;
134  float h_dt = dt/2;
135  tbf->rdist = (h_range_T-h_dt)/tbf->dt_in; // rel distance to central sample
136 
137  // allocate tbuffer
138  tbf->d = (float **)malloc(sizeof(float*)*tbf->wdth);
139  for(int i=0;i<tbf->wdth;i++)
140  tbf->d[i] = (float *)malloc(tbf->dsize*tbf->nodes);
141 
142  if(tbf->d[tbf->wdth-1]==NULL)
143  log_msg(NULL,5,LOCAL, "Warning: Memory allocation error" );
144 
145  // allocate interpolated tbuffer
146  tbf->dr = (float **)malloc(sizeof(void*)*tbf->rwdth);
147  for(int i=0;i<tbf->rwdth;i++)
148  tbf->dr[i] = (float *)malloc(tbf->dsize*tbf->nodes);
149 
150  // globalize memory allocation success or failure
151  tbf->buffered = 0;
152  tbf->filled = false;
153 
154  // fill
155  int err = 0;
156  for(int i=tbf->h_wdth;i<tbf->wdth;i++)
157  //if(rootReadSeq(tbf->data,tbf->dsize,tbf->nodes,(void *)(tbf->d[i]),
158  //tbf->bswp)!=tbf->nodes) {
159  if( tbf->igb->read_data( tbf->d[i], 1, NULL ) != tbf->nodes ) {
160  log_msg(NULL, 5, 0, "Premature eof. Trying to read time slice %.2f", tbf->t );
161  err++;
162  } else {
163  tbf->buffered++;
164  }
165 
166  return err?-1:tbf->wdth-tbf->h_wdth;
167 }
168 
169 
170 int
172 {
173  int err = 0;
174 
175  float *tmp = tbf->d[0];
176  for(int j=0;j<tbf->wdth-1;j++) tbf->d[j] = tbf->d[j+1];
177  tbf->d[tbf->wdth-1] = tmp;
178 
179  //if(rootReadSeq(tbf->data,tbf->dsize,tbf->nodes,(void *)tbf->d[tbf->wdth-1],
180  // tbf->bswp)!=tbf->nodes) {
181  if( tbf->igb->read_data( tbf->d[tbf->wdth-1], 1, NULL ) != tbf->nodes ) {
182  err--;
183  tbf->filled = false;
184  tbf->buffered--;
185  log_msg(NULL,3,0, "Premature eof. Trying to read time slice %.2f,", tbf->t );
186  }
187  else {
188  tbf->buffered++;
189  if(tbf->buffered==tbf->wdth) tbf->filled = true;
190  }
191  tbf->t += tbf->dt_in;
192 
193  return err?0:1;
194 }
195 
196 void
198 {
199  for(int i=0;i<tbf->rwdth;i++) free(tbf->dr[i]);
200  for(int i=0;i<tbf->wdth; i++) free(tbf->d[i] );
201 
202  free(tbf->d );
203  free(tbf->dr);
204 }
205 
206 
211 void
212 read_mesh( std::string mesh, ElemList *elst, NodeList *nlst )
213 {
214  FILE *ndin = fopen( (mesh+".pts").c_str(), "r" );
215  FILE *elin = fopen( (mesh+".elem").c_str(), "r" );
216  if( !ndin || !elin ) {
217  std::cerr << "cannot read mesh: " << mesh <<"\n";
218  exit(1);
219  }
220 
221  size_t buffsz=2048;
222  constexpr size_t buffsz_etype = 2048;
223  char *buff = (char *)malloc(buffsz*sizeof(char));;
224 
225  // read points file
226  getline( &buff, &buffsz, ndin );
227  sscanf( buff, "%d", &nlst->NNodes );
228  nlst->Node = (Point*)malloc(nlst->NNodes*sizeof(Point));
229  for( int i=0; i<nlst->NNodes; i++ ) {
230  getline( &buff, &buffsz, ndin );
231 #ifdef REAL_IS_DOUBLE
232  sscanf( buff, "%lf %lf %lf", &nlst->Node[i].x,&nlst->Node[i].y,&nlst->Node[i].z);
233 #else
234  sscanf( buff, "%f %f %f", &nlst->Node[i].x,&nlst->Node[i].y,&nlst->Node[i].z);
235 #endif
236  }
237  fclose( ndin );
238  // read elem file
239  getline( &buff, &buffsz, elin );
240  sscanf( buff, "%d", &elst->NElems );
241  elst->Ele = (Elem*)malloc(elst->NElems*sizeof(Elem));
242  size_t elign = 0;
243  int j=0;
244  for( int i=0; i<elst->NElems; i++ ) {
245  Elem *e = elst->Ele+j;
246  getline( &buff, &buffsz, elin );
247  char etype[buffsz_etype];
248  int p[8];
249  sscanf( buff, "%s %d %d %d %d %d %d %d %d", etype, p, p+1,p+2, p+3, p+4, p+5, p+6, p+7 );
250  if( !strcmp(etype,"Tr") ){
251  e->type = Tri;
252  e->Nnode= 3;
253  } else if( !strcmp(etype,"Tt") ){
254  e->type = Tetra;
255  e->Nnode= 4;
256  } else {
257  elign++;
258  continue;
259  }
260  e->N = (int*)malloc(e->Nnode*sizeof(int));
261  memmove( e->N, p, e->Nnode*sizeof(p[0]) );
262  j++;
263  }
264  if( elign ) {
265  std::cerr << "Info: " << elign << " elements ignored\n";
266  elst->NElems = j;
267  }
268  fclose( elin );
269 }
int main(int argc, char *argv[])
Definition: IGBfilament.cc:21
int initTBuffer(tbuffer *tbf, double dt)
Definition: IGBfilament.cc:119
int shiftTBuffer(tbuffer *tbf)
Definition: IGBfilament.cc:171
void read_mesh(std::string, ElemList *, NodeList *)
Definition: IGBfilament.cc:212
void freeTBuffer(tbuffer *tbf)
Definition: IGBfilament.cc:197
#define LOCAL
Definition: basics.h:325
size_t x(void)
Definition: IGBheader.h:268
size_t t(void)
Definition: IGBheader.h:277
int read_data(T *dp, size_t numt=1, char *buf=NULL)
Definition: IGBheader.h:432
void inc_t(float a)
Definition: IGBheader.h:329
int init_filament_IO(const char *meshname, int numT, FILE *fh[])
Definition: filament.cc:270
void interpolateTBuffer(tbuffer *tbf)
Definition: filament.cc:124
void write_filaments(filament *f, FILE *filHdls[], float t)
Definition: filament.cc:348
void close_filament_IO(FILE *fh[])
Definition: filament.cc:414
bool compute_filament(float *d0, float *d1, float vth, ElemList *elst, NodeList *nlst, filament *f, SingularityDetector_t meth)
Definition: filament.cc:171
SingularityDetector_t
Definition: filament.h:14
@ face_based
Definition: filament.h:14
#define log_msg(F, L, O,...)
Definition: filament.h:8
@ Tri
Definition: filament.h:16
@ Tetra
Definition: filament.h:16
vec3< POINT_REAL > Point
Definition: vect.h:93
Integer NElems
number of elements (owned+ghost in case of LOCAL_ELEM)
Definition: filament.h:60
Elem * Ele
Definition: filament.h:61
Definition: filament.h:53
Elem_t type
Definition: filament.h:54
int Nnode
Definition: filament.h:55
int * N
Definition: filament.h:56
Point * Node
list of nodes*
Definition: filament.h:49
Integer NNodes
number of global nodes*
Definition: filament.h:50
time slice buffer for post processing
Definition: filament.h:66
float ** dr
resampled data buffer
Definition: filament.h:76
int wdth
width of buffer, always 2*h_wdth+1
Definition: filament.h:74
int h_wdth
half width of sample buffer
Definition: filament.h:73
float t
time
Definition: filament.h:79
IGBheader * igb
IGB file reader.
Definition: filament.h:82
FILE * data
file hdl
Definition: filament.h:68
float dt_in
temporal sampling of input data
Definition: filament.h:80
int rwdth
width of resampling buffer
Definition: filament.h:77
int dsize
size of data tokens in bytes
Definition: filament.h:70
bool filled
is buffer fully loaded?
Definition: filament.h:81
const char * dname
name of data input file
Definition: filament.h:67
int numSamps
number of time slices in file
Definition: filament.h:71
float ** d
data buffer
Definition: filament.h:69
float rdist
rel dist of sample to center
Definition: filament.h:78
int nodes
number of nodes in time slice
Definition: filament.h:72
int buffered
number of samples in buffer
Definition: filament.h:75