/*{{{ subtract_init(transform_info_ptr tinfo)*/ METHODDEF void subtract_init(transform_info_ptr tinfo) { struct subtract_storage *local_arg=(struct subtract_storage *)tinfo->methods->local_storage; transform_argument *args=tinfo->methods->arguments; transform_info_ptr side_tinfo= &local_arg->side_tinfo; local_arg->ttest=args[ARGS_TTEST].is_set; if (args[ARGS_LEAVE_TPARAMETERS].is_set && !local_arg->ttest) { TRACEMS(tinfo->emethods, 0, "subtract_init: Option -u given without -t. Adding -t...\n"); local_arg->ttest=TRUE; } if (args[ARGS_TYPE].is_set) { local_arg->type=(enum subtract_types)args[ARGS_TYPE].arg.i; } else { local_arg->type=SUBTRACT_TYPE_SUBTRACT; } if (local_arg->type!=SUBTRACT_TYPE_SUBTRACT && local_arg->ttest) { ERREXIT(tinfo->emethods, "subtract_init: T-test is only useful in subtract mode.\n"); } side_tinfo->emethods=tinfo->emethods; side_tinfo->methods= &local_arg->side_method; select_readasc(side_tinfo); growing_buf_init(&local_arg->side_argbuf); growing_buf_allocate(&local_arg->side_argbuf, 0); if (args[ARGS_CLOSE].is_set) { growing_buf_appendstring(&local_arg->side_argbuf, "-c "); } if (args[ARGS_FROMEPOCH].is_set) { #define BUFFER_SIZE 80 char buffer[BUFFER_SIZE]; snprintf(buffer, BUFFER_SIZE, "-f %ld ", args[ARGS_FROMEPOCH].arg.i); growing_buf_appendstring(&local_arg->side_argbuf, buffer); } growing_buf_appendstring(&local_arg->side_argbuf, args[ARGS_SUBTRACTFILE].arg.s); if (!local_arg->side_argbuf.can_be_freed || !setup_method(side_tinfo, &local_arg->side_argbuf)) { ERREXIT(tinfo->emethods, "subtract_init: Error setting readasc arguments.\n"); } (*side_tinfo->methods->transform_init)(side_tinfo); side_tinfo->tsdata=NULL; /* We still have to fetch the data... */ tinfo->methods->init_done=TRUE; }
/*{{{ echo_init(transform_info_ptr tinfo) {*/ METHODDEF void echo_init(transform_info_ptr tinfo) { struct echo_storage *local_arg=(struct echo_storage *)tinfo->methods->local_storage; transform_argument *args=tinfo->methods->arguments; char const *inbuf=args[ARGS_STRING].arg.s; growing_buf_init(&local_arg->buf); growing_buf_allocate(&local_arg->buf, 0); while (*inbuf !='\0') { char c=*inbuf++; if (c=='\\') { char c1; switch (c1=*inbuf++) { case 'n': c='\n'; break; case 't': c='\t'; break; case '\0': inbuf--; break; default: c=c1; break; } if (c=='\0') break; } growing_buf_appendchar(&local_arg->buf, c); } growing_buf_appendchar(&local_arg->buf, '\0'); if (!args[ARGS_OFILE].is_set) { local_arg->outfile=NULL; } else if (strcmp(args[ARGS_OFILE].arg.s, "stdout")==0) { local_arg->outfile=stdout; } else if (strcmp(args[ARGS_OFILE].arg.s, "stderr")==0) { local_arg->outfile=stderr; } else if ((local_arg->outfile=fopen(args[ARGS_OFILE].arg.s, "a"))==NULL) { ERREXIT1(tinfo->emethods, "echo_init: Can't open file >%s<\n", MSGPARM(args[ARGS_OFILE].arg.s)); } tinfo->methods->init_done=TRUE; }
/*{{{ trim_init(transform_info_ptr tinfo) {*/ METHODDEF void trim_init(transform_info_ptr tinfo) { struct trim_storage *local_arg=(struct trim_storage *)tinfo->methods->local_storage; transform_argument *args=tinfo->methods->arguments; if (args[ARGS_USE_XVALUES].is_set && args[ARGS_USE_CHANNEL].is_set) { ERREXIT(tinfo->emethods, "trim: -n and -x flags are exclusive.\n"); } if (args[ARGS_COLLAPSE_Q].is_set && (args[ARGS_COLLAPSE_Q].arg.d<=0.0 || args[ARGS_COLLAPSE_Q].arg.d>=100.0)) { ERREXIT(tinfo->emethods, "trim: -q quantile must be between 0 and 100%%.\n"); } growing_buf_init(&local_arg->rangearg); growing_buf_takethis(&local_arg->rangearg, args[ARGS_RANGES].arg.s); local_arg->current_epoch=0; tinfo->methods->init_done=TRUE; }
/*{{{ trim(transform_info_ptr tinfo) {*/ METHODDEF DATATYPE * trim(transform_info_ptr tinfo) { struct trim_storage *local_arg=(struct trim_storage *)tinfo->methods->local_storage; transform_argument *args=tinfo->methods->arguments; int item, shift, nrofshifts=1; long nr_of_input_ranges,nr_of_ranges; long output_points; long rangeno, current_output_point=0; const Bool collapse=args[ARGS_COLLAPSE].is_set || args[ARGS_COLLAPSE_Q].is_set; const DATATYPE collapse_quantile=(args[ARGS_COLLAPSE].is_set&&args[ARGS_COLLAPSE].arg.i==COLLAPSE_BY_MEDIAN ? 0.5 : (args[ARGS_COLLAPSE_Q].is_set ? args[ARGS_COLLAPSE_Q].arg.d/100.0 : 0.0)); array myarray, newarray; DATATYPE *oldtsdata; DATATYPE *new_xdata=NULL; growing_buf ranges, tokenbuf; growing_buf triggers; growing_buf_init(&ranges); growing_buf_init(&tokenbuf); growing_buf_init(&triggers); if (tinfo->data_type==FREQ_DATA) { tinfo->nr_of_points=tinfo->nroffreq; nrofshifts=tinfo->nrofshifts; } /*{{{ Parse the ranges argument */ nr_of_input_ranges=growing_buf_count_tokens(&local_arg->rangearg); if (nr_of_input_ranges<=0 || nr_of_input_ranges%2!=0) { ERREXIT(tinfo->emethods, "trim: Need an even number of arguments >=2\n"); } nr_of_input_ranges/=2; output_points=0; growing_buf_allocate(&ranges, 0); growing_buf_allocate(&tokenbuf, 0); growing_buf_get_firsttoken(&local_arg->rangearg,&tokenbuf); while (tokenbuf.current_length>0) { struct range thisrange; if (args[ARGS_USE_CHANNEL].is_set) { int const channel=find_channel_number(tinfo,args[ARGS_USE_CHANNEL].arg.s); if (channel>=0) { DATATYPE const minval=get_value(tokenbuf.buffer_start, NULL); growing_buf_get_nexttoken(&local_arg->rangearg,&tokenbuf); DATATYPE const maxval=get_value(tokenbuf.buffer_start, NULL); array indata; tinfo_array(tinfo, &indata); indata.current_vector=channel; thisrange.offset= -1; /* Marks no start recorded yet */ do { DATATYPE const currval=indata.read_element(&indata); if (currval>=minval && currval<=maxval) { if (thisrange.offset== -1) { thisrange.offset=indata.current_element; thisrange.length= 1; } else { thisrange.length++; } } else { if (thisrange.offset!= -1) { growing_buf_append(&ranges, (char *)&thisrange, sizeof(struct range)); output_points+=(collapse ? 1 : thisrange.length); thisrange.offset= -1; } } array_advance(&indata); } while (indata.message==ARRAY_CONTINUE); if (thisrange.offset!= -1) { growing_buf_append(&ranges, (char *)&thisrange, sizeof(struct range)); output_points+=(collapse ? 1 : thisrange.length); } } else { ERREXIT1(tinfo->emethods, "set xdata_from_channel: Unknown channel name >%s<\n", MSGPARM(args[ARGS_USE_CHANNEL].arg.s)); } } else { if (args[ARGS_USE_XVALUES].is_set) { if (tinfo->xdata==NULL) create_xaxis(tinfo, NULL); thisrange.offset=decode_xpoint(tinfo, tokenbuf.buffer_start); growing_buf_get_nexttoken(&local_arg->rangearg,&tokenbuf); thisrange.length=decode_xpoint(tinfo, tokenbuf.buffer_start)-thisrange.offset+1; } else { thisrange.offset=gettimeslice(tinfo, tokenbuf.buffer_start); growing_buf_get_nexttoken(&local_arg->rangearg,&tokenbuf); thisrange.length=gettimeslice(tinfo, tokenbuf.buffer_start); if (thisrange.length==0) { thisrange.length=tinfo->nr_of_points-thisrange.offset; } } if (thisrange.length<=0) { ERREXIT1(tinfo->emethods, "trim: length is %d but must be >0.\n", MSGPARM(thisrange.length)); } growing_buf_append(&ranges, (char *)&thisrange, sizeof(struct range)); output_points+=(collapse ? 1 : thisrange.length); } growing_buf_get_nexttoken(&local_arg->rangearg,&tokenbuf); } /*}}} */ nr_of_ranges=ranges.current_length/sizeof(struct range); if (nr_of_ranges==0) { TRACEMS(tinfo->emethods, 0, "trim: No valid ranges selected, rejecting epoch.\n"); return NULL; } TRACEMS2(tinfo->emethods, 1, "trim: nr_of_ranges=%ld, output_points=%ld\n", MSGPARM(nr_of_ranges), MSGPARM(output_points)); newarray.nr_of_vectors=tinfo->nr_of_channels*nrofshifts; newarray.nr_of_elements=output_points; newarray.element_skip=tinfo->itemsize; if (array_allocate(&newarray)==NULL) { ERREXIT(tinfo->emethods, "trim: Error allocating memory.\n"); } oldtsdata=tinfo->tsdata; if (tinfo->xdata!=NULL) { /* Store xchannelname at the end of xdata, as in create_xaxis(); otherwise we'll have * a problem after free()'ing xdata... */ new_xdata=(DATATYPE *)malloc(output_points*sizeof(DATATYPE)+strlen(tinfo->xchannelname)+1); if (new_xdata==NULL) { ERREXIT(tinfo->emethods, "trim: Error allocating xdata memory.\n"); } } if (tinfo->triggers.buffer_start!=NULL) { struct trigger trig= *(struct trigger *)tinfo->triggers.buffer_start; growing_buf_allocate(&triggers, 0); /* Record the file position... */ if (collapse) { /* Make triggers in subsequent append() work as expected at least with * continuous reading */ trig.position=local_arg->current_epoch*nr_of_ranges; trig.code= -1; } growing_buf_append(&triggers, (char *)&trig, sizeof(struct trigger)); } for (rangeno=0; rangeno<nr_of_ranges; rangeno++) { struct range *rangep=((struct range *)(ranges.buffer_start))+rangeno; long const old_startpoint=(rangep->offset>0 ? rangep->offset : 0); long const new_startpoint=(rangep->offset<0 ? -rangep->offset : 0); /*{{{ Transfer the data*/ if (old_startpoint<tinfo->nr_of_points /* Skip this explicitly if no "real" point needs copying (length confined within negative offset) * since otherwise an endless loop can result as the stop conditions below look at the array * states and no array is touched... */ && new_startpoint<rangep->length) for (item=0; item<tinfo->itemsize; item++) { array_use_item(&newarray, item); for (shift=0; shift<nrofshifts; shift++) { tinfo_array(tinfo, &myarray); array_use_item(&myarray, item); do { DATATYPE sum=0.0; long reached_length=new_startpoint; myarray.current_element= old_startpoint; if (collapse) { newarray.current_element=current_output_point; newarray.message=ARRAY_CONTINUE; /* Otherwise the loop below may finish promptly... */ if (args[ARGS_COLLAPSE].is_set) switch (args[ARGS_COLLAPSE].arg.i) { case COLLAPSE_BY_HIGHEST: sum= -FLT_MAX; break; case COLLAPSE_BY_LOWEST: sum= FLT_MAX; break; default: break; } } else { newarray.current_element=current_output_point+new_startpoint; } if (collapse && collapse_quantile>0.0) { array helparray=myarray; helparray.ringstart=ARRAY_ELEMENT(&myarray); helparray.current_element=helparray.current_vector=0; helparray.nr_of_vectors=1; helparray.nr_of_elements=rangep->length; sum=array_quantile(&helparray,collapse_quantile); myarray.message=ARRAY_CONTINUE; } else do { if (reached_length>=rangep->length) break; if (args[ARGS_COLLAPSE].is_set) { DATATYPE const hold=array_scan(&myarray); switch (args[ARGS_COLLAPSE].arg.i) { case COLLAPSE_BY_SUMMATION: case COLLAPSE_BY_AVERAGING: sum+=hold; break; case COLLAPSE_BY_HIGHEST: if (hold>sum) sum=hold; break; case COLLAPSE_BY_LOWEST: if (hold<sum) sum=hold; break; default: break; } } else { array_write(&newarray, array_scan(&myarray)); } reached_length++; } while (newarray.message==ARRAY_CONTINUE && myarray.message==ARRAY_CONTINUE); if (collapse) { if (args[ARGS_COLLAPSE].is_set && args[ARGS_COLLAPSE].arg.i==COLLAPSE_BY_AVERAGING && item<tinfo->itemsize-tinfo->leaveright) sum/=reached_length; array_write(&newarray, sum); } if (newarray.message==ARRAY_CONTINUE) { array_nextvector(&newarray); } if (myarray.message==ARRAY_CONTINUE) { array_nextvector(&myarray); } } while (myarray.message==ARRAY_ENDOFVECTOR); tinfo->tsdata+=myarray.nr_of_vectors*myarray.nr_of_elements*myarray.element_skip; } tinfo->tsdata=oldtsdata; } /*}}} */ if (new_xdata!=NULL) { /*{{{ Transfer xdata*/ DATATYPE sum=0.0; long reached_length=new_startpoint; long point, newpoint; if (collapse) { newpoint=current_output_point; } else { newpoint=current_output_point+new_startpoint; } for (point=old_startpoint; point<tinfo->nr_of_points && reached_length<rangep->length; point++) { if (collapse) { sum+=tinfo->xdata[point]; } else { new_xdata[newpoint]=tinfo->xdata[point]; newpoint++; } reached_length++; } if (collapse) { /* Summation of x axis values does not appear to make sense, so we always average: */ new_xdata[newpoint]=sum/reached_length; } /*}}} */ /* Save xchannelname to the end of new_xdata */ strcpy((char *)(new_xdata+output_points),tinfo->xchannelname); } if (tinfo->triggers.buffer_start!=NULL) { /* Collect triggers... */ struct trigger *intrig=(struct trigger *)tinfo->triggers.buffer_start+1; while (intrig->code!=0) { if (intrig->position>=old_startpoint && intrig->position<old_startpoint+rangep->length) { struct trigger trig= *intrig; if (collapse) { trig.position=current_output_point; } else { trig.position=intrig->position-old_startpoint+current_output_point; } growing_buf_append(&triggers, (char *)&trig, sizeof(struct trigger)); } intrig++; } } current_output_point+=(collapse ? 1 : rangep->length); } if (new_xdata!=NULL) { free(tinfo->xdata); tinfo->xdata=new_xdata; tinfo->xchannelname=(char *)(new_xdata+output_points); } if (tinfo->triggers.buffer_start!=NULL) { struct trigger trig; /* Write end marker */ trig.position=0; trig.code=0; growing_buf_append(&triggers, (char *)&trig, sizeof(struct trigger)); growing_buf_free(&tinfo->triggers); tinfo->triggers=triggers; } tinfo->multiplexed=FALSE; tinfo->nr_of_points=output_points; if (tinfo->data_type==FREQ_DATA) { tinfo->nroffreq=tinfo->nr_of_points; } else { tinfo->beforetrig-=((struct range *)(ranges.buffer_start))->offset; tinfo->aftertrig=output_points-tinfo->beforetrig; } tinfo->length_of_output_region=tinfo->nr_of_points*tinfo->nr_of_channels*tinfo->itemsize*nrofshifts; local_arg->current_epoch++; growing_buf_free(&tokenbuf); growing_buf_free(&ranges); return newarray.start; }
/*{{{ write_synamps_init(transform_info_ptr tinfo) {*/ METHODDEF void write_synamps_init(transform_info_ptr tinfo) { struct write_synamps_storage *local_arg=(struct write_synamps_storage *)tinfo->methods->local_storage; transform_argument *args=tinfo->methods->arguments; double xmin, xmax, ymin, ymax; int NoOfChannels=tinfo->nr_of_channels; int channel; growing_buf_init(&local_arg->triggers); local_arg->output_format=(args[ARGS_OUTPUTFORMAT].is_set ? (enum output_formats)args[ARGS_OUTPUTFORMAT].arg.i : FORMAT_EEGFILE); local_arg->SCAN=fopen(args[ARGS_OFILE].arg.s, "r+b"); if (!args[ARGS_APPEND].is_set || local_arg->SCAN==NULL) { /* target does not exist*/ /*{{{ Create file*/ if (local_arg->SCAN!=NULL) fclose(local_arg->SCAN); /*{{{ Calculate the span in x-y channel positions*/ xmin=ymin= FLT_MAX; xmax=ymax= -FLT_MAX; for (channel=0; channel<tinfo->nr_of_channels; channel++) { const double this_x=tinfo->probepos[3*channel], this_y=tinfo->probepos[3*channel+1]; if (this_x>xmax) xmax=this_x; if (this_x<xmin) xmin=this_x; if (this_y>ymax) ymax=this_y; if (this_y<ymin) ymin=this_y; } if (xmax==xmin) { xmax+=0.5; xmin-=0.5; } if (ymax==ymin) { ymax+=0.5; ymin-=0.5; } /*}}} */ if ((local_arg->SCAN=fopen(args[ARGS_OFILE].arg.s, "wb"))==NULL) { ERREXIT1(tinfo->emethods, "write_synamps_init: Can't open %s\n", MSGPARM(args[ARGS_OFILE].arg.s)); } /*{{{ Many settings, taken from example files...*/ strcpy(local_arg->EEG.rev, "Version 3.0"); local_arg->EEG.AdditionalFiles=local_arg->EEG.NextFile=local_arg->EEG.PrevFile=0; switch (local_arg->output_format) { case FORMAT_EEGFILE: local_arg->EEG.review = 1; local_arg->EEG.savemode=NSM_EEGF; local_arg->EEG.type = NTY_EPOCHED; local_arg->EEG.ContinousType=0; local_arg->EEG.nsweeps=local_arg->EEG.compsweeps=local_arg->EEG.acceptcnt=0; break; case FORMAT_CNTFILE: local_arg->EEG.review = 1; local_arg->EEG.savemode=NSM_CONT; local_arg->EEG.type = 0; local_arg->EEG.ContinousType=NST_SYNAMPS-NST_CONT0; local_arg->EEG.nsweeps=1; local_arg->EEG.compsweeps=local_arg->EEG.acceptcnt=0; break; case FORMAT_AVGFILE: local_arg->EEG.review = 0; local_arg->EEG.savemode=NSM_AVGD; local_arg->EEG.type = NTY_AVERAGED; local_arg->EEG.ContinousType=0; local_arg->EEG.nsweeps=local_arg->EEG.compsweeps=local_arg->EEG.acceptcnt=(tinfo->nrofaverages>0 ? tinfo->nrofaverages : 1); break; } /* Since the comment can be of arbitrary length and thus also larger than the * rest of the header, we should limit ourselves to the size of the id field */ strncpy(local_arg->EEG.id, tinfo->comment, sizeof(local_arg->EEG.id)); /* The date is coded in the comment, and read_synamps appends the date and time * from the corresponding fields and the contents of the id field, so that * the comment2time reader could be confused by the two date/time fields if we * would not somehow invalidate remnants of the date field here... */ {char *slash; while ((slash=strchr(local_arg->EEG.id, '/'))!=NULL) { *slash='|'; } } strcpy(local_arg->EEG.oper, "Unspecified"); strcpy(local_arg->EEG.doctor, "Unspecified"); strcpy(local_arg->EEG.referral, "Unspecified"); strcpy(local_arg->EEG.hospital, "Unspecified"); strcpy(local_arg->EEG.patient, "Unspecified"); local_arg->EEG.age = 0; local_arg->EEG.sex = 'U'; local_arg->EEG.hand = 'U'; strcpy(local_arg->EEG.med, "Unspecified"); strcpy(local_arg->EEG.category, "Unspecified"); strcpy(local_arg->EEG.state, "Unspecified"); strcpy(local_arg->EEG.label, "Unspecified"); {short dd, mm, yy, yyyy, hh, mi, ss; if (comment2time(tinfo->comment, &dd, &mm, &yy, &yyyy, &hh, &mi, &ss)) { char buffer[16]; /* Must be long enough to fit date (10) and time (12) +1 */ /* This is necessary because the date field was devised for 2-digit years. * With 4-digit years it uses all 10 bytes and the trailing zero * does not fit in any more. */ snprintf(buffer, 16, "%02d/%02d/%04d", mm, dd, yyyy); strncpy(local_arg->EEG.date, buffer, sizeof(local_arg->EEG.date)); snprintf(buffer, 16, "%02d:%02d:%02d", hh, mi, ss); strncpy(local_arg->EEG.time, buffer, sizeof(local_arg->EEG.time)); } } local_arg->EEG.rejectcnt = 0; local_arg->EEG.pnts=(tinfo->data_type==FREQ_DATA ? tinfo->nroffreq : tinfo->nr_of_points); local_arg->EEG.nchannels=NoOfChannels; local_arg->EEG.avgupdate=1; local_arg->EEG.domain=(tinfo->data_type==FREQ_DATA ? 1 : 0); local_arg->EEG.variance=0; local_arg->EEG.rate=(uint16_t)rint(tinfo->sfreq); if (tinfo->data_type==FREQ_DATA) { /* I know that this field is supposed to contain the taper window size in %, but we need some way to store basefreq and 'rate' is only integer... */ local_arg->EEG.SpectWinLength=tinfo->basefreq; } if (local_arg->EEG.rate==0) { local_arg->EEG.rate=1; TRACEMS(tinfo->emethods, 0, "write_synamps_init: Rate was zero, corrected to 1!\n"); } local_arg->EEG.scale=3.4375; /* This is a common sensitivity factor, used if sensitivities for channels are zero */ local_arg->EEG.veogcorrect=0; local_arg->EEG.heogcorrect=0; local_arg->EEG.aux1correct=0; local_arg->EEG.aux2correct=0; local_arg->EEG.veogtrig=15; /* Trigger threshold in percent of the maximum */ local_arg->EEG.heogtrig=10; local_arg->EEG.aux1trig=10; local_arg->EEG.aux2trig=10; local_arg->EEG.veogchnl=find_channel_number(tinfo, "VEOG"); local_arg->EEG.heogchnl=find_channel_number(tinfo, "HEOG"); local_arg->EEG.veogdir=0; /* 0=positive, 1=negative */ local_arg->EEG.veog_n=10; /* "Number of points per waveform", really: minimum acceptable # averages */ local_arg->EEG.heog_n=10; local_arg->EEG.veogmaxcnt=(int16_t)rint(0.3*tinfo->sfreq); /* "Number of observations per point", really: event window size in points */ local_arg->EEG.heogmaxcnt=(int16_t)rint(0.5*tinfo->sfreq); local_arg->EEG.AmpSensitivity=10; /* External Amplifier gain */ local_arg->EEG.baseline=0; local_arg->EEG.reject=0; local_arg->EEG.trigtype=2; /* 2=Port */ local_arg->EEG.trigval=255; /* Hold */ local_arg->EEG.dir=0; /* Invert (negative up)=0 */ local_arg->EEG.dispmin= -1; /* displayed y range */ local_arg->EEG.dispmax= +1; local_arg->EEG.DisplayXmin=local_arg->EEG.AutoMin=local_arg->EEG.rejstart=local_arg->EEG.offstart=local_arg->EEG.xmin= -tinfo->beforetrig/tinfo->sfreq; local_arg->EEG.DisplayXmax=local_arg->EEG.AutoMax=local_arg->EEG.rejstop=local_arg->EEG.offstop=local_arg->EEG.xmax= tinfo->aftertrig/tinfo->sfreq; local_arg->EEG.zmin=0.0; local_arg->EEG.zmax=0.1; strcpy(local_arg->EEG.ref, "A1-A2"); strcpy(local_arg->EEG.screen, "--------"); local_arg->EEG.CalMode=2; local_arg->EEG.CalMethod=0; local_arg->EEG.CalUpdate=1; local_arg->EEG.CalBaseline=0; local_arg->EEG.CalSweeps=5; local_arg->EEG.CalAttenuator=1; local_arg->EEG.CalPulseVolt=1; local_arg->EEG.CalPulseStart=0; local_arg->EEG.CalPulseStop=0; local_arg->EEG.CalFreq=10; strcpy(local_arg->EEG.taskfile, "--------"); strcpy(local_arg->EEG.seqfile, "--------"); /* Otherwise tries to read a seqfile */ local_arg->EEG.HeadGain=150; local_arg->EEG.FspFValue=2.5; local_arg->EEG.FspBlockSize=200; local_arg->EEG.fratio=1.0; local_arg->EEG.minor_rev=12; /* Necessary ! Otherwise a different file structure is assumed... */ local_arg->EEG.eegupdate=1; local_arg->EEG.xscale=local_arg->EEG.yscale=0; local_arg->EEG.xsize=40; local_arg->EEG.ysize=20; local_arg->EEG.ACmode=0; local_arg->EEG.XScaleValue=XSCALEVALUE; local_arg->EEG.XScaleInterval=XSCALEINTERVAL; local_arg->EEG.YScaleValue=YSCALEVALUE; local_arg->EEG.YScaleInterval=YSCALEINTERVAL; local_arg->EEG.ScaleToolX1=20; local_arg->EEG.ScaleToolY1=170; local_arg->EEG.ScaleToolX2=23.1535; local_arg->EEG.ScaleToolY2=153.87; local_arg->EEG.port=715; local_arg->EEG.NumSamples=0; local_arg->EEG.FilterFlag=0; local_arg->EEG.LowCutoff=4; local_arg->EEG.LowPoles=2; local_arg->EEG.HighCutoff=50; local_arg->EEG.HighPoles=2; local_arg->EEG.FilterType=3; local_arg->EEG.FilterDomain=1; local_arg->EEG.SnrFlag=0; local_arg->EEG.CoherenceFlag=0; local_arg->EEG.ContinousSeconds=4; local_arg->EEG.ChannelOffset=sizeof(int16_t); local_arg->EEG.AutoCorrectFlag=0; local_arg->EEG.DCThreshold='F'; /*}}} */ /*{{{ Write SETUP structure*/ # ifndef LITTLE_ENDIAN change_byteorder((char *)&local_arg->EEG, sm_SETUP); # endif write_struct((char *)&local_arg->EEG, sm_SETUP, local_arg->SCAN); # ifndef LITTLE_ENDIAN change_byteorder((char *)&local_arg->EEG, sm_SETUP); # endif /*}}} */ if ((local_arg->Channels=(ELECTLOC *)calloc(NoOfChannels,sizeof(ELECTLOC)))==NULL) { ERREXIT(tinfo->emethods, "write_synamps_init: Error allocating Channels list\n"); } for (channel=0; channel<NoOfChannels; channel++) { /*{{{ Settings in the channel structure*/ strncpy(local_arg->Channels[channel].lab, tinfo->channelnames[channel],sizeof(local_arg->Channels[channel].lab)); local_arg->Channels[channel].reference=0; local_arg->Channels[channel].skip=0; local_arg->Channels[channel].reject=0; local_arg->Channels[channel].display=1; local_arg->Channels[channel].bad=0; local_arg->Channels[channel].n=(local_arg->output_format==FORMAT_AVGFILE ? local_arg->EEG.acceptcnt : (local_arg->output_format==FORMAT_CNTFILE ? 0 : 1)); local_arg->Channels[channel].avg_reference=0; local_arg->Channels[channel].ClipAdd=0; local_arg->Channels[channel].x_coord= (tinfo->probepos[3*channel ]-xmin)/(xmax-xmin)*RANGE_TO_COVER+XOFFSET; local_arg->Channels[channel].y_coord=((ymax-tinfo->probepos[3*channel+1])/(ymax-ymin)*RANGE_TO_COVER+YOFFSET)/3; local_arg->Channels[channel].veog_wt=0; local_arg->Channels[channel].veog_std=0; local_arg->Channels[channel].heog_wt=0; local_arg->Channels[channel].heog_std=0; local_arg->Channels[channel].baseline=0; local_arg->Channels[channel].Filtered=0; local_arg->Channels[channel].sensitivity=204.8/args[ARGS_CONVFACTOR].arg.d; /* This arranges for conv_factor to act as the expected product before integer truncation */ local_arg->Channels[channel].Gain=5; local_arg->Channels[channel].HiPass=0; /* 0=DC */ local_arg->Channels[channel].LoPass=4; local_arg->Channels[channel].Page=0; local_arg->Channels[channel].Size=0; local_arg->Channels[channel].Impedance=0; local_arg->Channels[channel].PhysicalChnl=channel; /* Channel mapping */ local_arg->Channels[channel].Rectify=0; local_arg->Channels[channel].calib=1.0; /*}}} */ /*{{{ Write ELECTLOC struct*/ # ifndef LITTLE_ENDIAN change_byteorder((char *)&local_arg->Channels[channel], sm_ELECTLOC); # endif write_struct((char *)&local_arg->Channels[channel], sm_ELECTLOC, local_arg->SCAN); # ifndef LITTLE_ENDIAN change_byteorder((char *)&local_arg->Channels[channel], sm_ELECTLOC); # endif /*}}} */ } local_arg->SizeofHeader = ftell(local_arg->SCAN); TRACEMS2(tinfo->emethods, 1, "write_synamps_init: Creating file %s, format `%s'\n", MSGPARM(args[ARGS_OFILE].arg.s), MSGPARM(neuroscan_subtype_names[NEUROSCAN_SUBTYPE(&local_arg->EEG)])); /*}}} */ } else { /*{{{ Append to file*/ enum NEUROSCAN_SUBTYPES SubType; if (read_struct((char *)&local_arg->EEG, sm_SETUP, local_arg->SCAN)==0) { ERREXIT(tinfo->emethods, "write_synamps_init: Can't read file header.\n"); } # ifndef LITTLE_ENDIAN change_byteorder((char *)&local_arg->EEG, sm_SETUP); # endif NoOfChannels = local_arg->EEG.nchannels; /*{{{ Allocate channel header*/ if ((local_arg->Channels=(ELECTLOC *)malloc(NoOfChannels*sizeof(ELECTLOC)))==NULL) { ERREXIT(tinfo->emethods, "write_synamps_init: Error allocating Channels list\n"); } /*}}} */ for (channel=0; channel<NoOfChannels; channel++) { if (read_struct((char *)&local_arg->Channels[channel], sm_ELECTLOC, local_arg->SCAN)==0) { ERREXIT(tinfo->emethods, "write_synamps_init: Can't read channel headers.\n"); } # ifndef LITTLE_ENDIAN change_byteorder((char *)&local_arg->Channels[channel], sm_ELECTLOC); # endif } local_arg->SizeofHeader = ftell(local_arg->SCAN); SubType=NEUROSCAN_SUBTYPE(&local_arg->EEG); switch (SubType) { case NST_EPOCHS: if (local_arg->output_format!=FORMAT_EEGFILE) { TRACEMS(tinfo->emethods, 0, "write_synamps_init: Appending to epoch file, discarding option -c\n"); local_arg->output_format=FORMAT_EEGFILE; } fseek(local_arg->SCAN, 0, SEEK_END); break; case NST_CONTINUOUS: case NST_SYNAMPS: { TEEG TagType; EVENT1 event; if (local_arg->output_format!=FORMAT_CNTFILE) { TRACEMS(tinfo->emethods, 0, "write_synamps_init: Appending to continuous file, assuming option -c\n"); local_arg->output_format=FORMAT_CNTFILE; } fseek(local_arg->SCAN, local_arg->EEG.EventTablePos, SEEK_SET); /* Here we face two evils in one header: Coding enums as chars and * allowing longs at odd addresses. Well... */ if (1==read_struct((char *)&TagType, sm_TEEG, local_arg->SCAN)) { # ifndef LITTLE_ENDIAN change_byteorder((char *)&TagType, sm_TEEG); # endif if (TagType.Teeg==TEEG_EVENT_TAB1) { /*{{{ Read the event table*/ int tag; int const ntags=TagType.Size/sm_EVENT1[0].offset; /* sm_EVENT1[0].offset is sizeof(EVENT1) in the file. */ for (tag=0; tag<ntags; tag++) { if (1!=read_struct((char *)&event, sm_EVENT1, local_arg->SCAN)) { ERREXIT(tinfo->emethods, "write_synamps_init: Can't read an event table entry.\n"); break; } # ifndef LITTLE_ENDIAN change_byteorder((char *)&event, sm_EVENT1); # endif { int const TrigVal=event.StimType &0xff; int const KeyBoard=event.KeyBoard&0xf; int const KeyPad=Event_KeyPad_value(event); int const Accept=Event_Accept_value(event); int code=TrigVal-KeyPad+neuroscan_accept_translation[Accept]; if (code==0) { code= -((KeyBoard+1)<<4); } push_trigger(&local_arg->triggers,offset2point(tinfo, event.Offset),code,NULL); } } /*}}} */ } else { ERREXIT(tinfo->emethods, "write_synamps_init: Type 2 events are not yet supported.\n"); } } else { ERREXIT(tinfo->emethods, "write_synamps_init: Can't read the event table header.\n"); } fseek(local_arg->SCAN, local_arg->EEG.EventTablePos, SEEK_SET); } break; default: ERREXIT1(tinfo->emethods, "write_synamps: Cannot append to file type `%s'\n", MSGPARM(neuroscan_subtype_names[SubType])); break; } /* Conformance to the incoming epochs is checked in write_synamps */ TRACEMS1(tinfo->emethods, 1, "write_synamps_init: Appending to file %s\n", MSGPARM(args[ARGS_OFILE].arg.s)); /*}}} */ } tinfo->methods->init_done=TRUE; }
/*{{{ read_neurofile_init(transform_info_ptr tinfo) {*/ METHODDEF void read_neurofile_init(transform_info_ptr tinfo) { struct read_neurofile_storage *local_arg=(struct read_neurofile_storage *)tinfo->methods->local_storage; transform_argument *args=tinfo->methods->arguments; int channel; FILE *dsc; #ifdef __GNUC__ char filename[strlen(args[ARGS_IFILE].arg.s)+5]; #else char filename[MAX_PATHLEN]; #endif growing_buf_init(&local_arg->triggers); strcpy(filename, args[ARGS_IFILE].arg.s); strcat(filename, ".dsc"); if((dsc=fopen(filename, "rb"))==NULL) { ERREXIT1(tinfo->emethods, "read_neurofile_init: Can't open dsc file >%s<\n", MSGPARM(filename)); } if (read_struct((char *)&local_arg->seq, sm_sequence, dsc)==0) { ERREXIT1(tinfo->emethods, "read_neurofile_init: Can't read header in file >%s<\n", MSGPARM(filename)); } fclose(dsc); #ifndef LITTLE_ENDIAN change_byteorder((char *)&local_arg->seq, sm_sequence); #endif local_arg->points_in_file = 256L*local_arg->seq.length; tinfo->points_in_file=local_arg->points_in_file; tinfo->sfreq=local_arg->sfreq=neurofile_map_sfreq(local_arg->seq.fastrate); local_arg->nr_of_channels=local_arg->seq.nfast; local_arg->factor=local_arg->seq.gain/1000.0; local_arg->stringlength=0; for (channel=0; channel<local_arg->nr_of_channels; channel++) { local_arg->stringlength+=strlen((char *)local_arg->seq.elnam[channel])+1; } /*{{{ Process options*/ local_arg->fromepoch=(args[ARGS_FROMEPOCH].is_set ? args[ARGS_FROMEPOCH].arg.i : 1); local_arg->epochs=(args[ARGS_EPOCHS].is_set ? args[ARGS_EPOCHS].arg.i : -1); /*}}} */ /*{{{ Parse arguments that can be in seconds*/ local_arg->beforetrig=tinfo->beforetrig=gettimeslice(tinfo, args[ARGS_BEFORETRIG].arg.s); local_arg->aftertrig=tinfo->aftertrig=gettimeslice(tinfo, args[ARGS_AFTERTRIG].arg.s); local_arg->offset=(args[ARGS_OFFSET].is_set ? gettimeslice(tinfo, args[ARGS_OFFSET].arg.s) : 0); /*}}} */ strcpy(filename+strlen(args[ARGS_IFILE].arg.s), ".eeg"); if((local_arg->infile=fopen(filename, "rb"))==NULL) { ERREXIT1(tinfo->emethods, "read_neurofile_init: Can't open file >%s<\n", MSGPARM(filename)); } if ((local_arg->last_values=(DATATYPE *)calloc(local_arg->nr_of_channels, sizeof(DATATYPE)))==NULL) { ERREXIT(tinfo->emethods, "read_neurofile_init: Error allocating last_values memory\n"); } local_arg->trigcodes=NULL; if (!args[ARGS_CONTINUOUS].is_set) { /* The actual trigger file is read when the first event is accessed! */ if (args[ARGS_TRIGLIST].is_set) { local_arg->trigcodes=get_trigcode_list(args[ARGS_TRIGLIST].arg.s); if (local_arg->trigcodes==NULL) { ERREXIT(tinfo->emethods, "read_neurofile_init: Error allocating triglist memory\n"); } } } else { if (local_arg->aftertrig==0) { /* Continuous mode: If aftertrig==0, automatically read up to the end of file */ if (local_arg->points_in_file==0) { ERREXIT(tinfo->emethods, "read_neurofile: Unable to determine the number of samples in the input file!\n"); } local_arg->aftertrig=local_arg->points_in_file-local_arg->beforetrig; } } read_neurofile_reset_triggerbuffer(tinfo); local_arg->current_trigger=0; local_arg->current_point=0; tinfo->filetriggersp=&local_arg->triggers; tinfo->methods->init_done=TRUE; }
/*{{{ read_freiburg_init(transform_info_ptr tinfo) {*/ METHODDEF void read_freiburg_init(transform_info_ptr tinfo) { struct read_freiburg_storage *local_arg=(struct read_freiburg_storage *)tinfo->methods->local_storage; transform_argument *args=tinfo->methods->arguments; struct stat statbuf; /*{{{ Process options*/ local_arg->fromepoch=(args[ARGS_FROMEPOCH].is_set ? args[ARGS_FROMEPOCH].arg.i : 1); local_arg->epochs=(args[ARGS_EPOCHS].is_set ? args[ARGS_EPOCHS].arg.i : -1); /*}}} */ local_arg->channelnames=NULL; local_arg->uV_per_bit=NULL; growing_buf_init(&local_arg->segment_table); /* This sets buffer_start=NULL */ local_arg->nr_of_channels=0; if (args[ARGS_CONTINUOUS].is_set) { /*{{{ Open a continuous (sleep, Bernd Tritschler) file*/ FILE *infile; local_arg->in_channels= &sleep_channels[0]; if (stat(args[ARGS_IFILE].arg.s, &statbuf)!= 0 || !S_ISREG(statbuf.st_mode)) { /* File does not exist or isn't a regular file: Try BT format */ #ifdef __GNUC__ char co_name[strlen(args[ARGS_IFILE].arg.s)+4]; char coa_name[strlen(args[ARGS_IFILE].arg.s)+5]; #else char co_name[MAX_PATHLEN]; char coa_name[MAX_PATHLEN]; #endif char coa_buf[MAX_COALINE]; FILE *coafile; strcpy(co_name, args[ARGS_IFILE].arg.s); strcat(co_name, ".co"); if((infile=fopen(co_name,"rb"))==NULL) { ERREXIT1(tinfo->emethods, "read_freiburg_init: Can't open file %s\n", MSGPARM(co_name)); } local_arg->infile=infile; if (args[ARGS_REPAIR_OFFSET].is_set) { fseek(infile, args[ARGS_REPAIR_OFFSET].arg.i, SEEK_SET); } else { if (read_struct((char *)&local_arg->btfile, sm_BT_file, infile)==0) { ERREXIT1(tinfo->emethods, "read_freiburg_init: Header read error in file %s\n", MSGPARM(co_name)); } # ifndef LITTLE_ENDIAN change_byteorder((char *)&local_arg->btfile, sm_BT_file); # endif } strcpy(coa_name, args[ARGS_IFILE].arg.s); strcat(coa_name, ".coa"); if((coafile=fopen(coa_name,"rb"))==NULL) { TRACEMS1(tinfo->emethods, 0, "read_freiburg_init: No file %s found\n", MSGPARM(coa_name)); } else { while (!feof(coafile)) { Bool repeat; fgets(coa_buf, MAX_COALINE-1, coafile); do { repeat=FALSE; if (strncmp(coa_buf, "Channel_Table ", 14)==0) { int havechannels=0, stringlength=0; long tablepos=ftell(coafile); char *innames; while (!feof(coafile)) { char *eol; fgets(coa_buf, MAX_COALINE-1, coafile); if (!isdigit(*coa_buf)) break; if (strncmp(coa_buf, "0 0 ", 4)==0) { /* Empty channel descriptors: Don't generate channelnames */ } else { for (eol=coa_buf+strlen(coa_buf)-1; eol>=coa_buf && (*eol=='\n' || *eol=='\r'); eol--) *eol='\0'; /* This includes 1 for the zero at the end: */ stringlength+=strlen(strrchr(coa_buf, ' ')); } havechannels++; } if (havechannels==0) continue; /* Channel table is unuseable */ local_arg->nr_of_channels=havechannels; innames=NULL; if ((stringlength!=0 && ((local_arg->channelnames=(char **)malloc(havechannels*sizeof(char *)))==NULL || (innames=(char *)malloc(stringlength))==NULL)) || (local_arg->uV_per_bit=(float *)malloc(havechannels*sizeof(float)))==NULL) { ERREXIT(tinfo->emethods, "read_freiburg_init: Error allocating .coa memory\n"); } fseek(coafile, tablepos, SEEK_SET); havechannels=0; while (!feof(coafile)) { char *eol; fgets(coa_buf, MAX_COALINE-1, coafile); if (!isdigit(*coa_buf)) break; for (eol=coa_buf+strlen(coa_buf)-1; eol>=coa_buf && (*eol=='\n' || *eol=='\r'); eol--) *eol='\0'; if (innames!=NULL) { strcpy(innames, strrchr(coa_buf, ' ')+1); local_arg->channelnames[havechannels]=innames; innames+=strlen(innames)+1; } /* The sensitivity in .coa files is given as nV/Bit */ local_arg->uV_per_bit[havechannels]=atoi(strchr(coa_buf, ' ')+1)/1000.0; if (local_arg->uV_per_bit[havechannels]==0.0) { local_arg->uV_per_bit[havechannels]=0.086; TRACEMS1(tinfo->emethods, 1, "read_freiburg_init: Sensitivity for channel %d set to 86 nV/Bit\n", MSGPARM(havechannels)); } havechannels++; } repeat=TRUE; } else if (strncmp(coa_buf, SEGMENT_TABLE_STRING, strlen(SEGMENT_TABLE_STRING))==0) { long current_offset=0; char *inbuf=coa_buf; Bool havesomething=FALSE; growing_buf_allocate(&local_arg->segment_table, 0); while (!feof(coafile)) { int const nextchar=fgetc(coafile); if (nextchar=='\r' || nextchar=='\n' || nextchar==' ') { if (havesomething) { *inbuf = '\0'; current_offset+=atoi(coa_buf); growing_buf_append(&local_arg->segment_table, (char *)¤t_offset, sizeof(long)); inbuf=coa_buf; havesomething=FALSE; } if (nextchar=='\n') break; } else { *inbuf++ = nextchar; havesomething=TRUE; } } repeat=FALSE; } } while (repeat); } fclose(coafile); if (local_arg->uV_per_bit==NULL) { TRACEMS1(tinfo->emethods, 0, "read_freiburg_init: No channel table found in file %s\n", MSGPARM(coa_name)); } if (local_arg->segment_table.buffer_start==NULL) { TRACEMS1(tinfo->emethods, 0, "read_freiburg_init: No segment table found in file %s\n", MSGPARM(coa_name)); } /* Determine the exact number of points in file: Start with the previous * segment and add the last segment. */ fstat(fileno(infile),&statbuf); //printf("File size is %ld\n", statbuf.st_size); //printf("Last segment (EOF) at %ld\n", ((long *)local_arg->segment_table.buffer_start)[local_arg->segment_table.current_length/sizeof(long)-1]); while (local_arg->segment_table.current_length>=1 && ((long *)local_arg->segment_table.buffer_start)[local_arg->segment_table.current_length/sizeof(long)-1]>=statbuf.st_size) { //printf("%ld - Removing last segment!\n", ((long *)local_arg->segment_table.buffer_start)[local_arg->segment_table.current_length/sizeof(long)-1]); local_arg->segment_table.current_length--; } /* Size without the last segment */ tinfo->points_in_file=(local_arg->segment_table.current_length/sizeof(long)-1)*SEGMENT_LENGTH; /* Count the points in the last segment */ { array myarray; int length_of_last_segment=0; myarray.element_skip=tinfo->itemsize=1; myarray.nr_of_vectors=1; myarray.nr_of_elements=local_arg->nr_of_channels; if (array_allocate(&myarray)==NULL) { ERREXIT(tinfo->emethods, "read_freiburg_init: Error allocating myarray\n"); } fseek(infile, ((long *)local_arg->segment_table.buffer_start)[local_arg->segment_table.current_length/sizeof(long)-1], SEEK_SET); //printf("Seeking to %ld\n", ((long *)local_arg->segment_table.buffer_start)[local_arg->segment_table.current_length/sizeof(long)-1]); tinfo->nr_of_channels=local_arg->nr_of_channels; /* This is used by freiburg_get_segment_init! */ freiburg_get_segment_init(tinfo); while (freiburg_get_segment(tinfo, &myarray)==0) length_of_last_segment++; freiburg_get_segment_free(tinfo); tinfo->points_in_file+=length_of_last_segment; TRACEMS1(tinfo->emethods, 1, "read_freiburg_init: Last segment has %ld points\n",length_of_last_segment); array_free(&myarray); } } if (local_arg->channelnames==NULL && local_arg->btfile.text[0]=='\0') { local_arg->in_channels= &goeppi_channels[0]; TRACEMS(tinfo->emethods, 0, "read_freiburg_init: Assuming Goeppingen style setup!\n"); } local_arg->continuous_type=SLEEP_BT_TYPE; TRACEMS(tinfo->emethods, 1, "read_freiburg_init: Opened file in BT format\n"); } else { if((infile=fopen(args[ARGS_IFILE].arg.s,"rb"))==NULL) { ERREXIT1(tinfo->emethods, "read_freiburg_init: Can't open file %s\n", MSGPARM(args[ARGS_IFILE].arg.s)); } if (args[ARGS_REPAIR_OFFSET].is_set) { fseek(infile, args[ARGS_REPAIR_OFFSET].arg.i, SEEK_SET); } else { if (read_struct((char *)&local_arg->btfile, sm_BT_file, infile)==0) { ERREXIT1(tinfo->emethods, "read_freiburg_init: Header read error in file %s\n", MSGPARM(args[ARGS_IFILE].arg.s)); } # ifdef LITTLE_ENDIAN change_byteorder((char *)&local_arg->btfile, sm_BT_file); # endif } local_arg->continuous_type=SLEEP_KL_TYPE; /* Year and day are swapped in KL format with respect to BT format... */ {short buf=local_arg->btfile.start_year; local_arg->btfile.start_year=local_arg->btfile.start_day; local_arg->btfile.start_day=buf;} /* Well, sometimes or most of the time, in KL files the sampling interval * was not set correctly... */ if (!args[ARGS_SFREQ].is_set && local_arg->btfile.sampling_interval_us!=9765 && local_arg->btfile.sampling_interval_us!=9766) { TRACEMS1(tinfo->emethods, 0, "read_freiburg_init: sampling_interval_us was %d, corrected!\n", MSGPARM(local_arg->btfile.sampling_interval_us)); local_arg->btfile.sampling_interval_us=9766; } TRACEMS(tinfo->emethods, 1, "read_freiburg_init: Opened file in KL format\n"); } if (args[ARGS_REPAIR_CHANNELS].is_set) local_arg->btfile.nr_of_channels=args[ARGS_REPAIR_CHANNELS].arg.i; tinfo->nr_of_channels=local_arg->btfile.nr_of_channels; if (tinfo->nr_of_channels<=0 || tinfo->nr_of_channels>MAX_NUMBER_OF_CHANNELS_IN_EP) { ERREXIT1(tinfo->emethods, "read_freiburg_init: Impossible: %d channels?\n", MSGPARM(tinfo->nr_of_channels)); } if (local_arg->nr_of_channels==0) { local_arg->nr_of_channels=tinfo->nr_of_channels; } else { if (local_arg->nr_of_channels!=tinfo->nr_of_channels) { ERREXIT2(tinfo->emethods, "read_freiburg_init: Setup has %d channels, but the file has %d!\n", MSGPARM(local_arg->nr_of_channels), MSGPARM(tinfo->nr_of_channels)); } } local_arg->sfreq=(args[ARGS_SFREQ].is_set ? args[ARGS_SFREQ].arg.d : 1.0e6/local_arg->btfile.sampling_interval_us); tinfo->sfreq=local_arg->sfreq; if (tinfo->sfreq<=0.0 || tinfo->sfreq>MAX_POSSIBLE_SFREQ) { ERREXIT1(tinfo->emethods, "read_freiburg_init: Impossible: sfreq=%gHz?\n", MSGPARM(tinfo->sfreq)); } /*{{{ Parse arguments that can be in seconds*/ tinfo->nr_of_points=gettimeslice(tinfo, args[ARGS_NCHANNELS].arg.s); if (tinfo->nr_of_points<=0) { /* Read the whole file as one epoch */ TRACEMS1(tinfo->emethods, 1, "read_freiburg_init: Reading %ld points\n",tinfo->points_in_file); tinfo->nr_of_points=tinfo->points_in_file; } local_arg->offset=(args[ARGS_OFFSET].is_set ? gettimeslice(tinfo, args[ARGS_OFFSET].arg.s) : 0); local_arg->epochlength=tinfo->nr_of_points; /*}}} */ tinfo->beforetrig= -local_arg->offset; tinfo->aftertrig=tinfo->nr_of_points+local_arg->offset; /*}}} */ } else { local_arg->in_channels= &freiburg_channels[0]; local_arg->current_trigger=0; if (stat(args[ARGS_IFILE].arg.s, &statbuf)!=0) { ERREXIT1(tinfo->emethods, "read_freiburg_init: Can't stat file %s\n", MSGPARM(args[ARGS_IFILE].arg.s)); } local_arg->nr_of_channels=atoi(args[ARGS_NCHANNELS].arg.s); /* average mode if the name does not belong to a directory */ local_arg->average_mode= !S_ISDIR(statbuf.st_mode); tinfo->nr_of_channels=MAX_NUMBER_OF_CHANNELS_IN_EP; } freiburg_get_segment_init(tinfo); local_arg->current_point=0; tinfo->methods->init_done=TRUE; }
/*{{{ project_init(transform_info_ptr tinfo)*/ METHODDEF void project_init(transform_info_ptr tinfo) { struct project_args_struct *project_args=(struct project_args_struct *)tinfo->methods->local_storage; transform_argument *args=tinfo->methods->arguments; transform_info_ptr side_tinfo= &project_args->side_tinfo; array *vectors= &project_args->vectors; growing_buf buf; #define BUFFER_SIZE 80 char buffer[BUFFER_SIZE]; side_tinfo->methods= &project_args->methods; side_tinfo->emethods=tinfo->emethods; select_readasc(side_tinfo); growing_buf_init(&buf); growing_buf_allocate(&buf, 0); if (args[ARGS_FROMEPOCH].is_set) { snprintf(buffer, BUFFER_SIZE, "-f %ld ", args[ARGS_FROMEPOCH].arg.i); growing_buf_appendstring(&buf, buffer); } if (args[ARGS_EPOCHS].is_set) { project_args->epochs=args[ARGS_EPOCHS].arg.i; if (project_args->epochs<=0) { ERREXIT(tinfo->emethods, "project_init: The number of epochs must be positive.\n"); } } else { project_args->epochs=1; } snprintf(buffer, BUFFER_SIZE, "-e %d ", project_args->epochs); growing_buf_appendstring(&buf, buffer); growing_buf_appendstring(&buf, args[ARGS_PROJECTFILE].arg.s); if (!buf.can_be_freed || !setup_method(side_tinfo, &buf)) { ERREXIT(tinfo->emethods, "project_init: Error setting readasc arguments.\n"); } project_args->points=(args[ARGS_POINTS].is_set ? args[ARGS_POINTS].arg.i : 1); project_args->nr_of_item=(args[ARGS_NROFITEM].is_set ? args[ARGS_NROFITEM].arg.i : 0); project_args->orthogonalize_vectors_first=args[ARGS_ORTHOGONALIZE].is_set; if (args[ARGS_SUBSPACE].is_set) { project_args->project_mode=PROJECT_MODE_SSP; } else if (args[ARGS_SUBTRACT_SUBSPACE].is_set) { project_args->project_mode=PROJECT_MODE_SSPS; } else if (args[ARGS_MULTIPLY].is_set) { project_args->project_mode=PROJECT_MODE_MULTIPLY; } else { project_args->project_mode=PROJECT_MODE_SCALAR; } if (args[ARGS_CHANNELNAMES].is_set) { project_args->channel_list=expand_channel_list(tinfo, args[ARGS_CHANNELNAMES].arg.s); if (project_args->channel_list==NULL) { ERREXIT(tinfo->emethods, "project_init: Zero channels were selected by -N!\n"); } } else { project_args->channel_list=NULL; } (*side_tinfo->methods->transform_init)(side_tinfo); /*{{{ Read first project_file epoch and allocate vectors array accordingly*/ if ((side_tinfo->tsdata=(*side_tinfo->methods->transform)(side_tinfo))==NULL) { ERREXIT(tinfo->emethods, "project_init: Can't get the first project epoch.\n"); } if (project_args->project_mode==PROJECT_MODE_MULTIPLY) { /* Save channel names and positions for later */ project_args->save_side_tinfo.nr_of_channels=side_tinfo->nr_of_channels; copy_channelinfo(&project_args->save_side_tinfo, side_tinfo->channelnames, side_tinfo->probepos); } if (project_args->points==0) project_args->points=side_tinfo->nr_of_points; if (project_args->points>side_tinfo->nr_of_points) { ERREXIT1(tinfo->emethods, "project_init: There are only %d points in the project_file epoch.\n", MSGPARM(side_tinfo->nr_of_points)); } if (args[ARGS_AT_XVALUE].is_set) { project_args->nr_of_point=find_pointnearx(side_tinfo, (DATATYPE)atof(args[ARGS_NROFPOINT].arg.s)); } else { project_args->nr_of_point=gettimeslice(side_tinfo, args[ARGS_NROFPOINT].arg.s); } vectors->nr_of_vectors=project_args->epochs*project_args->points; vectors->nr_of_elements=side_tinfo->nr_of_channels; vectors->element_skip=1; if (array_allocate(vectors)==NULL) { ERREXIT(tinfo->emethods, "project_init: Error allocating vectors memory\n"); } /*}}} */ do { /*{{{ Copy [points] vectors from project_file to vectors array*/ array indata; int point; if (vectors->nr_of_elements!=side_tinfo->nr_of_channels) { ERREXIT(side_tinfo->emethods, "project_init: Varying channel numbers in project file!\n"); } if (project_args->nr_of_point>=side_tinfo->nr_of_points) { ERREXIT2(side_tinfo->emethods, "project_init: nr_of_point=%d, nr_of_points=%d\n", MSGPARM(project_args->nr_of_point), MSGPARM(side_tinfo->nr_of_points)); } if (project_args->nr_of_item>=side_tinfo->itemsize) { ERREXIT2(side_tinfo->emethods, "project_init: nr_of_item=%d, itemsize=%d\n", MSGPARM(project_args->nr_of_item), MSGPARM(side_tinfo->itemsize)); } for (point=0; point<project_args->points; point++) { tinfo_array(side_tinfo, &indata); array_transpose(&indata); /* Vector = map */ if (vectors->nr_of_elements!=indata.nr_of_elements) { ERREXIT(side_tinfo->emethods, "project_init: vector size doesn't match\n"); } indata.current_vector=project_args->nr_of_point+point; array_setto_vector(&indata); array_use_item(&indata, project_args->nr_of_item); array_copy(&indata, vectors); } /*}}} */ free_tinfo(side_tinfo); } while ((side_tinfo->tsdata=(*side_tinfo->methods->transform)(side_tinfo))!=NULL); if (vectors->message!=ARRAY_ENDOFSCAN) { ERREXIT1(tinfo->emethods, "project_init: Less than %d epochs in project file\n", MSGPARM(vectors->nr_of_vectors)); } /*{{{ Set unused channels to zero if requested*/ if (args[ARGS_ZERO_UNUSEDCOEFFICIENTS].is_set) { if (project_args->channel_list!=NULL) { do { do { if (is_in_channellist(vectors->current_element+1, project_args->channel_list)) { array_advance(vectors); } else { array_write(vectors, 0.0); } } while (vectors->message==ARRAY_CONTINUE); } while (vectors->message!=ARRAY_ENDOFSCAN); } else { ERREXIT(tinfo->emethods, "project_init: Option -z only makes sense in combination with -N!\n"); } } /*}}} */ /*{{{ De-mean vectors if requested*/ if (args[ARGS_CORRELATION].is_set) { do { DATATYPE mean=0.0; int nrofaverages=0; do { if (project_args->channel_list!=NULL && !is_in_channellist(vectors->current_element+1, project_args->channel_list)) { array_advance(vectors); } else { mean+=array_scan(vectors); nrofaverages++; } } while (vectors->message==ARRAY_CONTINUE); mean/=nrofaverages; array_previousvector(vectors); do { array_write(vectors, READ_ELEMENT(vectors)-mean); } while (vectors->message==ARRAY_CONTINUE); } while (vectors->message!=ARRAY_ENDOFSCAN); } /*}}} */ /*{{{ Orthogonalize vectors if requested*/ if (project_args->orthogonalize_vectors_first) { array_make_orthogonal(vectors); if (vectors->message==ARRAY_ERROR) { ERREXIT(tinfo->emethods, "project_init: Error orthogonalizing projection vectors\n"); } } /*}}} */ if (!args[ARGS_NONORMALIZATION].is_set) { /*{{{ Normalize vectors*/ do { DATATYPE length=0.0; do { if (project_args->channel_list!=NULL && !is_in_channellist(vectors->current_element+1, project_args->channel_list)) { array_advance(vectors); } else { const DATATYPE hold=array_scan(vectors); length+=hold*hold; } } while (vectors->message==ARRAY_CONTINUE); length=sqrt(length); array_previousvector(vectors); if (length==0.0) { ERREXIT1(tinfo->emethods, "project_init: Vector %d has zero length !\n", MSGPARM(vectors->current_vector)); } array_scale(vectors, 1.0/length); } while (vectors->message!=ARRAY_ENDOFSCAN); /*}}} */ } /*{{{ Dump vectors if requested*/ if (args[ARGS_DUMPVECTORS].is_set) { FILE * const fp=fopen(args[ARGS_DUMPVECTORS].arg.s, "w"); if (fp==NULL) { ERREXIT1(tinfo->emethods, "project_init: Error opening output file >%s<.\n", MSGPARM(args[ARGS_DUMPVECTORS].arg.s)); } array_transpose(vectors); /* We want one vector to be one column */ array_dump(fp, vectors, ARRAY_MATLAB); array_transpose(vectors); fclose(fp); } /*}}} */ (*side_tinfo->methods->transform_exit)(side_tinfo); free_methodmem(side_tinfo); growing_buf_free(&buf); tinfo->methods->init_done=TRUE; }
/*{{{ recode_init(transform_info_ptr tinfo) {*/ METHODDEF void recode_init(transform_info_ptr tinfo) { struct recode_storage *local_arg=(struct recode_storage *)tinfo->methods->local_storage; transform_argument *args=tinfo->methods->arguments; growing_buf buf, tokenbuf; struct blockdef *inblocks; int nr_of_blocks=0, block; Bool havearg; if (args[ARGS_BYNAME].is_set) { /* Note that this is NULL if no channel matched, which is why we need have_channel_list as well... */ local_arg->channel_list=expand_channel_list(tinfo, args[ARGS_BYNAME].arg.s); local_arg->have_channel_list=TRUE; } else { local_arg->channel_list=NULL; local_arg->have_channel_list=FALSE; } local_arg->fromitem=0; local_arg->toitem=tinfo->itemsize-tinfo->leaveright-1; if (args[ARGS_ITEMPART].is_set) { local_arg->fromitem=local_arg->toitem=args[ARGS_ITEMPART].arg.i; if (local_arg->fromitem<0 || local_arg->fromitem>=tinfo->itemsize) { ERREXIT1(tinfo->emethods, "recode_init: No item number %d in file\n", MSGPARM(local_arg->fromitem)); } } growing_buf_init(&buf); growing_buf_takethis(&buf, args[ARGS_BLOCKS].arg.s); growing_buf_init(&tokenbuf); growing_buf_allocate(&tokenbuf,0); havearg=growing_buf_get_firsttoken(&buf,&tokenbuf); while (havearg) { nr_of_blocks++; havearg=growing_buf_get_nexttoken(&buf,&tokenbuf); } havearg=growing_buf_get_firsttoken(&buf,&tokenbuf); if (!havearg || nr_of_blocks%4!=0) { ERREXIT(tinfo->emethods, "recode_init: Number of args must be divisible by 4.\n"); } nr_of_blocks/=4; if ((local_arg->blockdefs=(struct blockdef *)malloc(nr_of_blocks*sizeof(struct blockdef)))==NULL) { ERREXIT(tinfo->emethods, "recode_init: Error allocating blockdefs memory\n"); } for (inblocks=local_arg->blockdefs, block=0; havearg; block++, inblocks++) { inblocks->fromstart=get_value(tokenbuf.buffer_start, NULL); growing_buf_get_nexttoken(&buf,&tokenbuf); inblocks->fromend=get_value(tokenbuf.buffer_start, NULL); growing_buf_get_nexttoken(&buf,&tokenbuf); inblocks->tostart=get_value(tokenbuf.buffer_start, NULL); growing_buf_get_nexttoken(&buf,&tokenbuf); inblocks->toend=get_value(tokenbuf.buffer_start, NULL); havearg=growing_buf_get_nexttoken(&buf,&tokenbuf); inblocks->last_block=(block==nr_of_blocks-1); if (isnan(inblocks->fromstart) || isnan(inblocks->fromend)) { if (!isnan(inblocks->fromstart) || !isnan(inblocks->fromend)) { ERREXIT(tinfo->emethods, "recode_init: NaN cannot be mixed in from block!\n"); } if (inblocks->tostart!=inblocks->toend) { ERREXIT(tinfo->emethods, "recode_init: NaN can only be recoded to one value!\n"); } } if (isnan(inblocks->tostart) || isnan(inblocks->toend)) { if (!isnan(inblocks->tostart) || !isnan(inblocks->toend)) { ERREXIT(tinfo->emethods, "recode_init: NaN cannot be mixed in to block!\n"); } } } growing_buf_free(&tokenbuf); growing_buf_free(&buf); tinfo->methods->init_done=TRUE; }
/*{{{ write_vitaport_init(transform_info_ptr tinfo) {*/ METHODDEF void write_vitaport_init(transform_info_ptr tinfo) { struct write_vitaport_storage *local_arg=(struct write_vitaport_storage *)tinfo->methods->local_storage; transform_argument *args=tinfo->methods->arguments; int channel, NoOfChannels=tinfo->nr_of_channels; int tempnamelength, tempnum; short dd, mm, yy, yyyy, hh, mi, ss; char const *lastslash; struct stat statbuff; growing_buf_init(&local_arg->triggers); if ((local_arg->outfile=fopen(args[ARGS_OFILE].arg.s, "wb"))==NULL) { ERREXIT1(tinfo->emethods, "write_vitaport_init: Can't open %s\n", MSGPARM(args[ARGS_OFILE].arg.s)); } /*{{{ Initialize the file header*/ local_arg->fileheader.Sync=VITAPORT_SYNCMAGIC; local_arg->fileheader.chnoffs=sm_vitaport_fileheader[0].offset+sm_vitaportII_fileheader[0].offset+sm_vitaportII_fileext[0].offset; local_arg->fileext.chdlen=sm_vitaport_channelheader[0].offset+sm_vitaportIIrchannelheader[0].offset; local_arg->fileheader.hdlen=local_arg->fileheader.chnoffs+NoOfChannels*local_arg->fileext.chdlen+2; local_arg->fileheader.hdtyp=HDTYP_VITAPORT2; local_arg->fileheader.knum=NoOfChannels; if (comment2time(tinfo->comment, &dd, &mm, &yy, &yyyy, &hh, &mi, &ss)) { local_arg->fileheaderII.Hour=hh; local_arg->fileheaderII.Minute=mi; local_arg->fileheaderII.Second=ss; local_arg->fileheaderII.Day=dd; local_arg->fileheaderII.Month=mm; local_arg->fileheaderII.Year=yy; convert_tohex(&local_arg->fileheaderII.Hour); convert_tohex(&local_arg->fileheaderII.Minute); convert_tohex(&local_arg->fileheaderII.Second); convert_tohex(&local_arg->fileheaderII.Day); convert_tohex(&local_arg->fileheaderII.Month); convert_tohex(&local_arg->fileheaderII.Year); } local_arg->fileheaderII.Sysvers=56; local_arg->fileheaderII.scnrate=(short int)rint(VITAPORT_CLOCKRATE/tinfo->sfreq); local_arg->fileext.swvers=311; local_arg->fileext.hwvers=1286; local_arg->fileext.recorder= -1; local_arg->fileext.timer1=0; local_arg->fileext.sysflg12=512; /*}}} */ /*{{{ Initialize channel temp files and storage*/ lastslash=strrchr(args[ARGS_OFILE].arg.s, PATHSEP); if (lastslash==NULL) lastslash=args[ARGS_OFILE].arg.s-1; /* Up to slash, 8.3 for name, 1 for null */ tempnamelength=lastslash-args[ARGS_OFILE].arg.s+(1+8+1+3+1); if ((local_arg->channelfilename=(char *)malloc(tempnamelength))==NULL || (local_arg->channelmax=(DATATYPE *)malloc(NoOfChannels*sizeof(DATATYPE)))==NULL || (local_arg->channelmin=(DATATYPE *)malloc(NoOfChannels*sizeof(DATATYPE)))==NULL || (local_arg->channelheaders=(struct vitaport_channelheader *)malloc(NoOfChannels*sizeof(struct vitaport_channelheader)))==NULL || (local_arg->channelheadersII=(struct vitaportIIrchannelheader *)malloc(NoOfChannels*sizeof(struct vitaportIIrchannelheader)))==NULL) { ERREXIT(tinfo->emethods, "write_vitaport_init: Error allocating memory\n"); } tempnum=0; do { /* While the targeted tempfile already exists... */ strncpy(local_arg->channelfilename, args[ARGS_OFILE].arg.s, lastslash-args[ARGS_OFILE].arg.s+1); local_arg->channelfilename[lastslash-args[ARGS_OFILE].arg.s+1]='\0'; sprintf(local_arg->channelfilename+strlen(local_arg->channelfilename), "%08d.tmp", tempnum); tempnum++; } while (stat(local_arg->channelfilename, &statbuff)==0); if ((local_arg->channelfile=fopen(local_arg->channelfilename, "wb"))==NULL) { ERREXIT1(tinfo->emethods, "write_vitaport_init: Can't open temp file %s\n", MSGPARM(local_arg->channelfilename)); } for (channel=0; channel<NoOfChannels; channel++) { local_arg->channelmax[channel]= -FLT_MAX; local_arg->channelmin[channel]= FLT_MAX; strncpy(local_arg->channelheaders[channel].kname, tinfo->channelnames[channel], 6); strcpy(local_arg->channelheaders[channel].kunit, "uV"); local_arg->channelheaders[channel].datype=VP_DATYPE_SIGNED; local_arg->channelheaders[channel].dasize=VP_DATATYPE_SHORT; local_arg->channelheaders[channel].scanfc=1; local_arg->channelheaders[channel].fltmsk=0; local_arg->channelheaders[channel].stofac=1; local_arg->channelheaders[channel].resvd1=0; local_arg->channelheaders[channel].resvd2=0; local_arg->channelheadersII[channel].mval=1000; local_arg->channelheadersII[channel].chflg=1; local_arg->channelheadersII[channel].hpass=0; local_arg->channelheadersII[channel].ampl=1; local_arg->channelheadersII[channel].tpass=0; } /*}}} */ local_arg->total_points=0; local_arg->sfreq=tinfo->sfreq; tinfo->methods->init_done=TRUE; }