38 #include "apd_cmdline.h"
51 lininterp(
float y0,
float y1,
float x0,
float x1,
float interp )
53 float m = (y1-y0)/(x1-x0);
80 if( strchr( sp,
':' ) ){
81 char *colptr = strchr( sp,
':' );
83 sscanf( colptr+1,
"%d%n", &inc, &consumed );
84 if( !consumed || consumed!=strlen(colptr+1) ) {
85 fprintf( stderr,
"Illegal range specified: %s\n", sp );
91 if( !strcmp(
"*", sp ) ) {
94 for(
int i=0; i<
max; i+=inc )
95 nodes.insert(nodes.end(),i);
97 for(
int i=0; i<
max; i+=inc )
103 if( strchr( sp,
'-' ) ){
106 int nr = sscanf( sp,
"%d-%s", &s, fs );
108 fprintf( stderr,
"Illegal range specified: %s\n", sp );
113 if( !strcmp(fs,
"*") )
117 sscanf( fs,
"%d%n", &f, &consumed );
118 if( consumed != strlen(fs) ) {
119 fprintf( stderr,
"Illegal range specified: %s\n", sp );
125 fprintf( stderr,
"Illegal range specified: %s\n", sp );
129 fprintf( stderr,
"Illegal range, maximum node number exceeded: %s\n", sp );
132 for(
int i=s; i<=f; i+=inc )
138 sscanf( sp,
"%d", &num );
140 if( !sscanf( sp,
"%d", &num ) || num<0 || num>=
max ) {
141 fprintf( stderr,
"Illegal node number specified in list: %d\n", num );
153 char *lc = strdup( list );
154 char *sp = strtok( lc,
"," );
157 while( sp != NULL ) {
161 sp = strtok( NULL,
"," );
165 if( !ch_nodes.size() ) {
166 fprintf( stderr,
"No nodes specified: %s\n", list );
171 nodes.resize( ch_nodes.size() );
173 auto end=ch_nodes.end();
174 for(
auto sit=ch_nodes.cbegin(); sit!=end; sit++ )
183 gengetopt_args_info args;
186 if (cmdline_parser (argc, argv, &args) != 0)
193 if( strcmp(args.inputs[0],
"-") )
194 fin = fopen( args.inputs[0],
"r" );
198 cerr <<
"File is not a proper IGB file: "<< args.inputs[0] << endl;
203 float DVDT_THRESH = args.dvdt_arg*h->
inc_t();
204 float repolarize = args.repol_arg;
205 float v_thresh = args.rep_level_arg;
206 float plusthresh = 10.;
209 if( args.threshold_mode_counter )
214 int MINAPD = args.minapd_arg;
215 if( args.peak_value_arg == peak_value_arg_plateau )
216 if( MINAPD<args.plateau_duration_arg + args.plateau_start_arg ) {
217 MINAPD += args.plateau_duration_arg + args.plateau_start_arg;
218 cerr <<
"warning: changing apdmin to "<<MINAPD<<
" from "<<MINAPD<<endl;
221 float *oldervm = (
float *)calloc(h->
slice_sz(),
sizeof(float));
222 float *oldvm = (
float *)calloc(h->
slice_sz(),
sizeof(float));
223 float *vm = (
float *)calloc(h->
slice_sz(),
sizeof(float));
224 float *apd = (
float *)calloc(h->
slice_sz(),
sizeof(float));
225 float *vmthresh = (
float *)calloc(h->
slice_sz(),
sizeof(float));
226 float *vmrest = (
float *)calloc(h->
slice_sz(),
sizeof(float));
227 bool *peaked = (
bool *)calloc(h->
slice_sz(),
sizeof(bool));
228 vector<float> repol_tm( h->
slice_sz(),-1.);
231 int *last_apstart = NULL;
232 if( args.mode_arg==mode_arg_act) last_apstart = (
int *)calloc(h->
slice_sz(),
sizeof(int));
234 for(
int i=0; i<h->
slice_sz(); i++ ) {
238 vmthresh[i] = threshtype==
MinDeriv?0:v_thresh;
239 if( args.mode_arg==mode_arg_act) last_apstart[i] =
NO_PRIOR;
243 if( args.first_given )
244 first = args.first_arg;
245 else if( args.first_time_given )
246 first = (args.first_time_arg-h->
org_t())/h->
inc_t();
247 for(
int t=0; t<first; t++ )
252 int unfound = nodes.size();
254 for(
int t=first; t<h->
t() && unfound; t++ ){
259 memcpy( oldvm, vm, h->
slice_sz()*
sizeof(
float) );
261 #pragma omp parallel for
262 for(
int j=0; j<nodes.size(); j++ ) {
269 if( t && fabs(vm[i]-oldervm[i])<0.001 )
270 vmrest[i] = oldvm[i];
272 if( (vm[i]-oldvm[i])>DVDT_THRESH && vm[i]>args.vup_arg ) {
274 if( oldvm[i]<=args.vup_arg )
275 apdstart[i] =
lininterp( oldvm[i], vm[i], t-1, t, args.vup_arg );
277 apdstart[i] =
lininterp( oldvm[i]-oldervm[i], vm[i]-oldvm[i],
278 t-1, t, DVDT_THRESH )*h->
inc_t();
281 if( args.mode_arg == mode_arg_detect ) {
282 cout << i <<
" @ " << apdstart[i]+h->
org_t() << endl;
289 if( !peaked[i] && apdstart[i]!=
UNSTARTED ) {
290 switch( threshtype ) {
296 if( vm[i]<oldvm[i] ) {
298 vmthresh[i] = vmrest[i]+plusthresh;
302 if( args.peak_value_arg == peak_value_arg_upstroke ) {
303 if( vm[i]<oldvm[i] ) {
305 vmthresh[i] = vmrest[i] + (1.-repolarize/100.)*(oldvm[i] -vmrest[i] );
308 if( t*h->
inc_t()-apdstart[i] < args.plateau_start_arg ) {
310 }
else if( t*h->
inc_t()-apdstart[i] < args.plateau_start_arg+args.plateau_duration_arg ) {
311 if( vm[i] > vmthresh[i] )
314 vmthresh[i] = vmrest[i] + (1.-repolarize/100.)*(vmthresh[i] -vmrest[i] );
323 if( peaked[i] && vm[i]-vmrest[i]<args.mindv_arg ) {
326 if( args.mode_arg==mode_arg_debug )
327 cout <<
"node: " << i <<
" failed to reach min dv/dt at frame " << t<< endl;
331 if( peaked[i] && apd[i]==
UNCOMPUTED && args.mode_arg==mode_arg_act_first ) {
333 }
else if( peaked[i] && apd[i]==
UNCOMPUTED && args.mode_arg==mode_arg_act) {
335 if( last_apstart[i]==
NO_PRIOR || (t-last_apstart[i])*h->
inc_t()>MINAPD ) {
336 cout << i <<
" : " << apdstart[i]+h->
org_t() << endl;
341 }
else if( peaked[i] && apd[i]==
UNCOMPUTED ) {
344 if( threshtype==
MinDeriv && oldervm[i]-oldvm[i] > oldvm[i]-vm[i] &&
345 oldervm[i]-oldvm[i]>vmthresh[i] ) {
346 vmthresh[i] = oldervm[i] -oldvm[i] ;
347 apd[i] = (t - 1)*h->
inc_t() - apdstart[i];
349 }
else if(vm[i]<=vmthresh[i] && oldvm[i]>vmthresh[i] ) {
350 apd[i] =
lininterp( oldvm[i], vm[i], t-1, t, vmthresh[i] )*h->
inc_t()-apdstart[i];
354 if( apd[i] < MINAPD ) {
358 if( args.mode_arg==mode_arg_debug )
359 cerr <<
"node: " << i <<
" APD too short at frame " << t<< endl;
360 }
else if( args.mode_arg == mode_arg_first ) {
362 }
else if( args.mode_arg == mode_arg_all ) {
363 cout << i <<
" : " << apd[i];
364 if( args.start_times_flag )
365 cout <<
"\t\tstarted : " << apdstart[i] + h->
org_t();
367 }
else if( args.mode_arg == mode_arg_repol_all ) {
368 cout << i <<
" : " << apd[i] + apdstart[i] + h->
org_t();
369 if( args.start_times_flag )
370 cout <<
"\t\tstarted : " << apdstart[i] + h->
org_t();
372 }
else if( args.mode_arg == mode_arg_repol_first ){
373 if( repol_tm[i] < 0. ) {
374 repol_tm[i] =apd[i] + apdstart[i] + h->
org_t();
376 }
else if( args.mode_arg == mode_arg_debug ) {
377 cout <<
"node:" << i <<
"\tAPD: " << apd[i] <<
"\tstarted: " << apdstart[i] + h->
org_t();
378 cout <<
"\trest: " << vmrest[i];
379 cout <<
"\tvmthresh: " << vmthresh[i];
385 if( (args.mode_arg==mode_arg_all || args.mode_arg==mode_arg_debug ||
386 args.mode_arg==mode_arg_repol_all ) &&
387 apd[i]!=
UNCOMPUTED && t*h->
inc_t()-apdstart[i]+apd[i]>args.blank_arg ) {
393 float *tmp = oldervm;
401 if( args.mode_arg == mode_arg_first ) {
403 if( strcmp(args.output_file_arg,
"-") )
404 out = fopen( args.output_file_arg,
"w" );
406 for(
int i=0; i<h->
slice_sz(); i++ ){
407 if( args.start_times_flag )
408 fprintf( out,
"%f\t%f\n", apd[i], apdstart[i]+h->
org_t() );
410 fprintf( out,
"%f\n", apd[i] );
413 }
else if( args.mode_arg == mode_arg_repol_first ) {
415 if( strcmp(args.output_file_arg,
"-") )
416 out = fopen( args.output_file_arg,
"w" );
418 for(
int i=0; i<repol_tm.size(); i++ )
419 if( args.start_times_flag )
420 fprintf( out,
"%f\t%f\n", repol_tm[i], apdstart[i]+h->
org_t() );
422 fprintf( out,
"%f\n", repol_tm[i] );
424 }
else if( args.mode_arg == mode_arg_act_first ) {
426 if( strcmp(args.output_file_arg,
"-") )
427 out = fopen( args.output_file_arg,
"w" );
429 for(
int i=0; i<apdstart.size(); i++ )
430 fprintf( out,
"%f\n", apdstart[i]+h->
org_t() );
void extract_nodes(const char *list, vector< int > &nodes, int max)
int main(int argc, char *argv[])
float lininterp(float y0, float y1, float x0, float x1, float interp)
bool process_specifier(char *sp, set< int > &nodes, int max)
constexpr T max(T a, T b)