/*{{{ recode(transform_info_ptr tinfo) {*/ METHODDEF DATATYPE * recode(transform_info_ptr tinfo) { struct recode_storage *local_arg=(struct recode_storage *)tinfo->methods->local_storage; transform_info_ptr const tinfoptr=tinfo; array myarray; int itempart; int shift, nrofshifts=1; DATATYPE *save_tsdata; tinfo_array(tinfoptr, &myarray); /* The channels are the vectors */ save_tsdata=myarray.start; if (tinfoptr->data_type==FREQ_DATA) { nrofshifts=tinfoptr->nrofshifts; } for (shift=0; shift<nrofshifts; shift++) { myarray.start=save_tsdata+shift*tinfo->nroffreq*tinfo->nr_of_channels*tinfo->itemsize; array_setreadwrite(&myarray); for (itempart=local_arg->fromitem; itempart<=local_arg->toitem; itempart++) { array_use_item(&myarray, itempart); do { if (local_arg->have_channel_list && !is_in_channellist(myarray.current_vector+1, local_arg->channel_list)) { array_nextvector(&myarray); continue; } do { DATATYPE hold=READ_ELEMENT(&myarray); struct blockdef *inblocks=local_arg->blockdefs; while (inblocks!=NULL) { if (isnan(inblocks->fromstart) && isnan(hold)) { /* Recode NaN values */ hold=inblocks->tostart; } else if (hold>=inblocks->fromstart && hold<=inblocks->fromend) { if (inblocks->fromend==inblocks->fromstart || inblocks->toend==inblocks->tostart) { hold=inblocks->tostart; } else { hold=((hold-inblocks->fromstart)/(inblocks->fromend-inblocks->fromstart))*(inblocks->toend-inblocks->tostart)+inblocks->tostart; } break; } if (inblocks->last_block) break; inblocks++; } array_write(&myarray, hold); } while (myarray.message==ARRAY_CONTINUE); } while (myarray.message==ARRAY_ENDOFVECTOR); } } return tinfo->tsdata; }
/*{{{ export_point(transform_info_ptr tinfo) {*/ METHODDEF DATATYPE * export_point(transform_info_ptr tinfo) { struct export_point_info *exp_info=(struct export_point_info *)tinfo->methods->local_storage; transform_argument *args=tinfo->methods->arguments; array_dump_format format=(args[ARGS_MATLAB].is_set ? ARRAY_MATLAB : ARRAY_ASCII); int channel, itempart, i; double *channelpos; array myarray, newarray; if (exp_info->pointno<0 || exp_info->pointno>=tinfo->nr_of_points) { ERREXIT1(tinfo->emethods, "export_point: Point number %d is out of range.\n", MSGPARM(exp_info->pointno)); } TRACEMS2(tinfo->emethods, 1, "export_point: Exporting point number %d to file %s\n", MSGPARM(exp_info->pointno), MSGPARM(args[ARGS_OFILE].arg.s)); if (args[ARGS_CLOSE].is_set) export_file_open(tinfo); tinfo_array(tinfo, &myarray); myarray.current_element=exp_info->pointno; if (exp_info->channelcoords_to_display==0 && tinfo->itemsize==1) { /*{{{ Don't need to build new array, just access tinfo*/ newarray=myarray; array_transpose(&newarray); array_setto_vector(&newarray); /* Select only one element */ array_transpose(&newarray); /*}}} */ } else { /*{{{ Build new array containing the data*/ newarray.nr_of_vectors=myarray.nr_of_vectors; newarray.nr_of_elements=exp_info->channelcoords_to_display+tinfo->itemsize; newarray.element_skip=1; if (array_allocate(&newarray)==NULL) { ERREXIT(tinfo->emethods, "export_point: Can't allocate output array\n"); } for (channel=0; channel<tinfo->nr_of_channels; channel++) { channelpos=tinfo->probepos+3*channel; for (i=0; i<exp_info->channelcoords_to_display; i++) { array_write(&newarray, channelpos[i]); } myarray.current_vector=channel; for (itempart=0; itempart<tinfo->itemsize; itempart++) { array_use_item(&myarray, itempart); array_write(&newarray, READ_ELEMENT(&myarray)); } } /*}}} */ } array_dump(exp_info->file, &newarray, format); if (newarray.nr_of_elements>1) array_free(&newarray); if (args[ARGS_CLOSE].is_set) export_file_close(tinfo); return tinfo->tsdata; }
/*{{{ write_rec(transform_info_ptr tinfo) {*/ METHODDEF DATATYPE * write_rec(transform_info_ptr tinfo) { struct write_rec_storage *local_arg=(struct write_rec_storage *)tinfo->methods->local_storage; transform_argument *args=tinfo->methods->arguments; FILE *outfptr=local_arg->outfptr; short *inbuf; array myarray; if (tinfo->itemsize!=1) { ERREXIT(tinfo->emethods, "write_rec: Only itemsize=1 is supported.\n"); } if (args[ARGS_CLOSE].is_set) { write_rec_open_file(tinfo); outfptr=local_arg->outfptr; } /*{{{ Write epoch*/ tinfo_array(tinfo, &myarray); /* We read the data point by point, i.e. channels fastest */ array_transpose(&myarray); /* Within the record, writing is non-interlaced, ie points fastest */ do { do { inbuf=local_arg->outbuf+local_arg->samples_per_record*myarray.current_element+local_arg->current_sample; *inbuf= (short int)rint(array_scan(&myarray)/local_arg->resolution); if (!local_arg->overflow_has_occurred && (*inbuf<local_arg->digmin || *inbuf>local_arg->digmax)) { TRACEMS(tinfo->emethods, 0, "write_rec: Some output values exceed digitization bits!\n"); local_arg->overflow_has_occurred=TRUE; } #ifndef LITTLE_ENDIAN Intel_int16(inbuf); #endif } while (myarray.message==ARRAY_CONTINUE); if (++local_arg->current_sample>=local_arg->samples_per_record) { if ((int)fwrite(local_arg->outbuf, sizeof(short), tinfo->nr_of_channels*local_arg->samples_per_record, outfptr)!=tinfo->nr_of_channels*local_arg->samples_per_record) { ERREXIT(tinfo->emethods, "write_rec: Write error on data file.\n"); } /* If nr_of_records was -1 (can only happen while appending), * leave it that way */ if (local_arg->nr_of_records>=0) local_arg->nr_of_records++; local_arg->current_sample=0L; } } while (myarray.message!=ARRAY_ENDOFSCAN); /*}}} */ if (args[ARGS_CLOSE].is_set) write_rec_close_file(tinfo); return tinfo->tsdata; /* Simply to return something `useful' */ }
/*{{{ write_vitaport(transform_info_ptr tinfo) {*/ METHODDEF DATATYPE * write_vitaport(transform_info_ptr tinfo) { struct write_vitaport_storage *local_arg=(struct write_vitaport_storage *)tinfo->methods->local_storage; array myarray; int channel; /*{{{ Assert that epoch size didn't change & itemsize==1*/ if (tinfo->itemsize!=1) { ERREXIT(tinfo->emethods, "write_vitaport: Only itemsize=1 is supported.\n"); } if (local_arg->fileheader.knum!=tinfo->nr_of_channels) { ERREXIT2(tinfo->emethods, "write_vitaport: nr_of_channels was %d, now %d\n", MSGPARM(local_arg->fileheader.knum), MSGPARM(tinfo->nr_of_channels)); } /*}}} */ if (tinfo->data_type==FREQ_DATA) tinfo->nr_of_points=tinfo->nroffreq; tinfo_array(tinfo, &myarray); array_transpose(&myarray); /* channels are the elements: Temp file is interlaced */ do { channel=0; do { DATATYPE dat=array_scan(&myarray); if (fwrite(&dat, sizeof(DATATYPE), 1, local_arg->channelfile)!=1) { ERREXIT(tinfo->emethods, "write_vitaport: Error writing temp file.\n"); } /* Keep track of the scaling... */ if (dat>local_arg->channelmax[channel]) local_arg->channelmax[channel]=dat; if (dat<local_arg->channelmin[channel]) local_arg->channelmin[channel]=dat; channel++; } while (myarray.message==ARRAY_CONTINUE); } while (myarray.message!=ARRAY_ENDOFSCAN); if (tinfo->triggers.buffer_start!=NULL) { struct trigger *intrig=(struct trigger *)tinfo->triggers.buffer_start+1; while (intrig->code!=0) { push_trigger(&local_arg->triggers,local_arg->total_points+intrig->position,intrig->code,intrig->description); intrig++; } } local_arg->total_points+=tinfo->nr_of_points; return tinfo->tsdata; /* Simply to return something `useful' */ }
/*{{{ raw_fft(transform_info_ptr tinfo) {*/ METHODDEF DATATYPE * raw_fft(transform_info_ptr tinfo) { int i; array myarray, fftarray; long datasize, fftsize; if (tinfo->itemsize==2) { /*{{{ Do the inverse transform*/ if (tinfo->data_type==TIME_DATA) { tinfo->nroffreq=tinfo->nr_of_points; tinfo->nrofshifts=1; } datasize=tinfo->nroffreq; fftsize=datasize-3; for (i=0; fftsize>>=1; i++); fftsize=1<<(i+2); if (datasize!=fftsize/2+1 || tinfo->nrofshifts!=1) { ERREXIT(tinfo->emethods, "raw_fft: Input spectra must have 2^n+1 frequencies, 2 items and 1 shift\n"); } fftarray.nr_of_elements=fftsize; fftarray.element_skip=1; fftarray.nr_of_vectors=tinfo->nr_of_channels; if (array_allocate(&fftarray)==NULL) { ERREXIT(tinfo->emethods, "raw_fft: Error allocating memory\n"); } /* We access tsdata as 1-item data already now (this makes copying easier) */ tinfo->itemsize=1; tinfo->nr_of_points*=2; tinfo->data_type=TIME_DATA; tinfo_array(tinfo, &myarray); do { myarray.current_element=0; myarray.current_vector=fftarray.current_vector; realfft(ARRAY_ELEMENT(&myarray), fftsize, -1); do { array_write(&fftarray, array_scan(&myarray)); } while (fftarray.message==ARRAY_CONTINUE); } while (fftarray.message==ARRAY_ENDOFVECTOR); tinfo->nr_of_points=fftarray.nr_of_elements; /*}}} */ } else {
/*{{{ rereference(transform_info_ptr tinfo)*/ METHODDEF DATATYPE * rereference(transform_info_ptr tinfo) { struct rereference_args_struct *rereference_args=(struct rereference_args_struct *)tinfo->methods->local_storage; transform_argument *args=tinfo->methods->arguments; int itempart; transform_info_ptr const tinfoptr=tinfo; array indata; tinfo_array(tinfoptr, &indata); array_transpose(&indata); /* Vector=map */ for (itempart=0; itempart<tinfoptr->itemsize-tinfoptr->leaveright; itempart++) { array_use_item(&indata, itempart); do { DATATYPE mean=0; int n=0; do { if (is_in_channellist(indata.current_element+1, rereference_args->refchannel_numbers)) { mean+=array_scan(&indata); n++; } else { array_advance(&indata); } } while (indata.message==ARRAY_CONTINUE); mean/=n; array_previousvector(&indata); do { if ((args[ARGS_EXCLUDEOTHER].is_set && !is_in_channellist(indata.current_element+1, rereference_args->refchannel_numbers)) || is_in_channellist(indata.current_element+1, rereference_args->excludechannel_numbers)) { array_advance(&indata); } else { array_write(&indata, READ_ELEMENT(&indata)-mean); } } while (indata.message==ARRAY_CONTINUE); } while (indata.message!=ARRAY_ENDOFSCAN); } return tinfo->tsdata; }
/*{{{ 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(transform_info_ptr tinfo) {*/ METHODDEF DATATYPE * write_synamps(transform_info_ptr calltinfo) { struct write_synamps_storage *local_arg=(struct write_synamps_storage *)calltinfo->methods->local_storage; transform_argument *args=calltinfo->methods->arguments; NEUROSCAN_EPOCHED_SWEEP_HEAD sweephead; long tsdata_step, tsdata_steps, tsdata_stepwidth; array myarray; /* Note that 'tinfo' instead of 'tinfoptr' is used here so that we don't have to modify * all of the older code which stored only one epoch */ transform_info_ptr tinfo=calltinfo; if (args[ARGS_LINKED].is_set) { /* Go to the start: */ for (; tinfo->previous!=NULL; tinfo=tinfo->previous); } for (; tinfo!=NULL; tinfo=tinfo->next) { DATATYPE * const orig_tsdata=tinfo->tsdata; /*{{{ Assert that epoch size didn't change & itemsize==1*/ if (tinfo->itemsize!=1) { ERREXIT(tinfo->emethods, "write_synamps: Only itemsize=1 is supported.\n"); } if (local_arg->EEG.nchannels!=tinfo->nr_of_channels) { ERREXIT2(tinfo->emethods, "write_synamps: nr_of_channels was %d, now %d\n", MSGPARM(local_arg->EEG.nchannels), MSGPARM(tinfo->nr_of_channels)); } /*}}} */ if (tinfo->data_type==FREQ_DATA) { tinfo->nr_of_points=tinfo->nroffreq; tsdata_steps=tinfo->nrofshifts; tsdata_stepwidth=tinfo->nr_of_channels*tinfo->nroffreq*tinfo->itemsize; } else { tsdata_steps=1; tsdata_stepwidth=0; } for (tsdata_step=0; tsdata_step<tsdata_steps; tinfo->tsdata+=tsdata_stepwidth, tsdata_step++) { switch (local_arg->output_format) { case FORMAT_EEGFILE: if (local_arg->EEG.pnts!=tinfo->nr_of_points) { ERREXIT2(tinfo->emethods, "write_synamps: nr_of_points was %d, now %d\n", MSGPARM(local_arg->EEG.pnts), MSGPARM(tinfo->nr_of_points)); } /*{{{ Set sweephead values*/ sweephead.accept=1; sweephead.type=254; sweephead.correct=0; sweephead.rt=0; sweephead.response=0; if (tinfo->condition>0) { sweephead.type=tinfo->condition&0xff; } else if (tinfo->condition<0 && (-tinfo->condition)<=0xf) { sweephead.type=0; sweephead.response= -tinfo->condition; } else { /* KeyBoard event: Do it the same way 'Edit' does when epoching, * mapping F1 to type=1 and so on (overlap with stim codes, but they * should know how they want it...) */ sweephead.type= (-tinfo->condition)>>4; } /*}}} */ /*{{{ Write sweephead struct*/ # ifndef LITTLE_ENDIAN change_byteorder((char *)&sweephead, sm_NEUROSCAN_EPOCHED_SWEEP_HEAD); # endif write_struct((char *)&sweephead, sm_NEUROSCAN_EPOCHED_SWEEP_HEAD, local_arg->SCAN); # ifndef LITTLE_ENDIAN change_byteorder((char *)&sweephead, sm_NEUROSCAN_EPOCHED_SWEEP_HEAD); # endif /*}}} */ local_arg->EEG.nsweeps++; /* This gets patched into the header by write_synamps_exit */ local_arg->EEG.compsweeps++; local_arg->EEG.acceptcnt++; break; case FORMAT_AVGFILE: if (local_arg->EEG.NumSamples!=0) { ERREXIT(tinfo->emethods, "write_synamps: Only a single epoch may be written to an .AVG file!\n"); } case FORMAT_CNTFILE: if (tinfo->triggers.buffer_start!=NULL) { struct trigger *intrig=(struct trigger *)tinfo->triggers.buffer_start+1; while (intrig->code!=0) { push_trigger(&local_arg->triggers,local_arg->EEG.NumSamples+intrig->position,intrig->code,intrig->description); intrig++; } } local_arg->EEG.NumSamples+=tinfo->nr_of_points; break; } tinfo_array(tinfo, &myarray); if (local_arg->output_format==FORMAT_AVGFILE) { /* points are the elements */ float *pdata, * const buffer=(float *)malloc(myarray.nr_of_elements*sizeof(float)); const char *fill="\0\0\0\0\0"; if (buffer==NULL) { ERREXIT(tinfo->emethods, "write_synamps: Error allocating AVGFILE buffer\n"); } do { int const channel=myarray.current_vector; /* Write the `5-byte channel header that is no longer used' */ fwrite(fill, 1, 5, local_arg->SCAN); pdata=buffer; do { *pdata=NEUROSCAN_FLOATCONV(&local_arg->Channels[channel], array_scan(&myarray)); # ifndef LITTLE_ENDIAN Intel_float(pdata); # endif pdata++; } while (myarray.message==ARRAY_CONTINUE); if ((int)fwrite(buffer,sizeof(float),myarray.nr_of_elements,local_arg->SCAN)!=myarray.nr_of_elements) { ERREXIT(tinfo->emethods, "write_synamps: Error writing data point\n"); } } while (myarray.message!=ARRAY_ENDOFSCAN); free(buffer); } else { int16_t * const buffer=(int16_t *)malloc(myarray.nr_of_vectors*sizeof(int16_t)); if (buffer==NULL) { ERREXIT(tinfo->emethods, "write_synamps: Error allocating buffer\n"); } array_transpose(&myarray); /* channels are the elements */ do { int channel=0; do { DATATYPE hold=array_scan(&myarray), hold2; /* Code anything exceeding the representable range, including +-Inf, as min/max representable value. */ hold2=NEUROSCAN_SHORTCONV(&local_arg->Channels[channel], hold); if (hold2< -32768) hold2= -32768; else if (hold2> 32767) hold2= 32767; buffer[channel]=(int16_t)hold2; # ifndef LITTLE_ENDIAN Intel_int16(&buffer[channel]); # endif channel++; } while (myarray.message==ARRAY_CONTINUE); if ((int)fwrite(buffer,sizeof(int16_t),myarray.nr_of_elements,local_arg->SCAN)!=myarray.nr_of_elements) { ERREXIT(tinfo->emethods, "write_synamps: Error writing data point\n"); } } while (myarray.message!=ARRAY_ENDOFSCAN); free(buffer); } } /* FREQ_DATA shifts loop */ tinfo->tsdata=orig_tsdata; if (!args[ARGS_LINKED].is_set) { break; } } /* Linked epochs loop */ return calltinfo->tsdata; /* Simply to return something `useful' */ }
/*{{{ scale_by(transform_info_ptr tinfo)*/ METHODDEF DATATYPE * scale_by(transform_info_ptr tinfo) { struct scale_by_storage *local_arg=(struct scale_by_storage *)tinfo->methods->local_storage; DATATYPE factor; int itempart; array indata; tinfo_array(tinfo, &indata); switch (local_arg->type) { /* Operations which are done on maps */ case SCALE_BY_XDATA: case SCALE_BY_INVXDATA: if (tinfo->xdata==NULL) create_xaxis(tinfo, NULL); case SCALE_BY_NORMALIZE: case SCALE_BY_INVNORM: case SCALE_BY_INVSQUARENORM: case SCALE_BY_INVSUM: case SCALE_BY_INVMAX: case SCALE_BY_INVMAXABS: case SCALE_BY_INVQUANTILE: array_transpose(&indata); /* Vectors are maps */ if (local_arg->have_channel_list) { ERREXIT(tinfo->emethods, "scale_by: Channel subsets are not supported for map operations.\n"); } break; /* Operations which are done on channels */ case SCALE_BY_INVPOINTNORM: case SCALE_BY_INVPOINTSQUARENORM: case SCALE_BY_INVPOINTSUM: case SCALE_BY_INVPOINTMAX: case SCALE_BY_INVPOINTMAXABS: case SCALE_BY_INVPOINTQUANTILE: case SCALE_BY_FACTOR: break; /* Operations which involve a special but constant factor */ case SCALE_BY_PI: local_arg->factor= M_PI; break; case SCALE_BY_INVPI: local_arg->factor= 1.0/M_PI; break; case SCALE_BY_SFREQ: local_arg->factor= tinfo->sfreq; break; case SCALE_BY_INVSFREQ: local_arg->factor= 1.0/tinfo->sfreq; break; case SCALE_BY_NR_OF_POINTS: local_arg->factor= (tinfo->data_type==FREQ_DATA ? tinfo->nroffreq : tinfo->nr_of_points); break; case SCALE_BY_INVNR_OF_POINTS: local_arg->factor= 1.0/(tinfo->data_type==FREQ_DATA ? tinfo->nroffreq : tinfo->nr_of_points); break; case SCALE_BY_NR_OF_CHANNELS: local_arg->factor= tinfo->nr_of_channels; break; case SCALE_BY_INVNR_OF_CHANNELS: local_arg->factor= 1.0/tinfo->nr_of_channels; break; case SCALE_BY_NROFAVERAGES: local_arg->factor= tinfo->nrofaverages; break; case SCALE_BY_INVNROFAVERAGES: local_arg->factor= 1.0/tinfo->nrofaverages; break; case SCALE_BY_SQRTNROFAVERAGES: local_arg->factor= sqrt(tinfo->nrofaverages); break; case SCALE_BY_INVSQRTNROFAVERAGES: local_arg->factor= 1.0/sqrt(tinfo->nrofaverages); break; } for (itempart=local_arg->fromitem; itempart<=local_arg->toitem; itempart++) { array_use_item(&indata, itempart); do { if (local_arg->have_channel_list && !is_in_channellist(indata.current_vector+1, local_arg->channel_list)) { array_nextvector(&indata); continue; } switch (local_arg->type) { case SCALE_BY_NORMALIZE: case SCALE_BY_INVNORM: case SCALE_BY_INVPOINTNORM: factor=array_abs(&indata); if (factor==0.0) factor=1.0; factor=1.0/factor; array_previousvector(&indata); break; case SCALE_BY_INVSQUARENORM: case SCALE_BY_INVPOINTSQUARENORM: factor=array_square(&indata); if (factor==0.0) factor=1.0; factor=1.0/factor; array_previousvector(&indata); break; case SCALE_BY_INVSUM: case SCALE_BY_INVPOINTSUM: factor=array_sum(&indata); if (factor==0.0) factor=1.0; factor=1.0/factor; array_previousvector(&indata); break; case SCALE_BY_INVMAX: case SCALE_BY_INVPOINTMAX: factor=array_max(&indata); if (factor==0.0) factor=1.0; factor=1.0/factor; array_previousvector(&indata); break; case SCALE_BY_INVMAXABS: case SCALE_BY_INVPOINTMAXABS: { DATATYPE amax=fabs(array_scan(&indata)), hold; while (indata.message==ARRAY_CONTINUE) { hold=fabs(array_scan(&indata)); if (hold>amax) amax=hold; } factor=amax; } if (factor==0.0) factor=1.0; factor=1.0/factor; array_previousvector(&indata); break; case SCALE_BY_INVQUANTILE: case SCALE_BY_INVPOINTQUANTILE: factor=array_quantile(&indata,local_arg->factor); if (factor==0.0) factor=1.0; factor=1.0/factor; break; case SCALE_BY_XDATA: factor=tinfo->xdata[indata.current_vector]; break; case SCALE_BY_INVXDATA: factor=1.0/tinfo->xdata[indata.current_vector]; break; case SCALE_BY_PI: case SCALE_BY_INVPI: case SCALE_BY_SFREQ: case SCALE_BY_INVSFREQ: case SCALE_BY_NR_OF_POINTS: case SCALE_BY_INVNR_OF_POINTS: case SCALE_BY_NR_OF_CHANNELS: case SCALE_BY_INVNR_OF_CHANNELS: case SCALE_BY_NROFAVERAGES: case SCALE_BY_INVNROFAVERAGES: case SCALE_BY_SQRTNROFAVERAGES: case SCALE_BY_INVSQRTNROFAVERAGES: case SCALE_BY_FACTOR: factor=local_arg->factor; break; default: continue; } array_scale(&indata, factor); } while (indata.message!=ARRAY_ENDOFSCAN); } return tinfo->tsdata; }
int main(int argc, char *argv[]) { int i=1, start=0, end=0, freqno; DATATYPE *new_tsdata, hold; array D; OPT_DTYPE ax, bx, cx, fa, fb, fc, xmin, sumsq, weight, sumweight, ave, min_power, optimize_arg, *points; optimize_struct ostruct; struct minfunc_struct mfs; struct transform_info_struct firsttinfo; transform_info_ptr tinfo, tinfo_next; struct transform_methods_struct methods[2]; struct external_methods_struct emethod; tinfo= &firsttinfo; /*{{{ Process command line*/ while (*argv[1]=='-') { switch (argv[1][1]) { } argv++; argc--; } if (argc!=3) { fprintf(stderr, "Usage: %s ascdatafile outfile\n" , argv[0]); return 1; } if (start<0) start=0; if (end<=0) end=start; /*}}} */ clear_external_methods(&emethod); firsttinfo.methods= methods; firsttinfo.emethods= &emethod; /*{{{ Read all data sets*/ select_readasc(tinfo); (*tinfo->methods->transform_defaults)(tinfo); firsttinfo.filename=argv[1]; firsttinfo.epochs= -1; firsttinfo.fromepoch=1; (*tinfo->methods->transform_init)(tinfo); if (start!=0) { while (i<start) { (*tinfo->methods->transform)(tinfo); i++; } } while ((end==0 || i<=end) && (*tinfo->methods->transform)(tinfo)!=NULL) { if ((tinfo_next=malloc(sizeof(struct transform_info_struct)))==NULL) { ERREXIT(&emethod, "similarity: Error malloc'ing tinfo struct\n"); } *(tinfo_next)=firsttinfo; tinfo_next->previous=tinfo; tinfo_next->next=NULL; tinfo->next=tinfo_next; tinfo=tinfo_next; i++; } /* The last tinfo structure was allocated in vein, throw away */ tinfo=tinfo->previous; free(tinfo->next); tinfo->next=NULL; (*firsttinfo.methods->transform_exit)(&firsttinfo); /*}}} */ points=malloc(2*firsttinfo.nr_of_channels*sizeof(OPT_DTYPE)); for (freqno=0; freqno<firsttinfo.nr_of_channels; freqno++) { /*{{{ Construct symmetrical function*/ sumweight=ave=0.0; min_power=1e10; for (i=0, tinfo= &firsttinfo; tinfo!=NULL; tinfo=tinfo->next, i++) { tinfo_array(tinfo, &D); array_transpose(&D); array_reset(&D); D.current_vector=freqno; D.current_element=i; hold=array_readelement(&D); D.current_element=0; do { points[D.current_element*2]=100*channel_distance(tinfo, i, D.current_element); points[D.current_element*2+1]=array_scan(&D)/hold; } while (D.message==ARRAY_CONTINUE); ostruct.function= &minfunc; mfs.nr_of_points=firsttinfo.nr_of_channels; mfs.points=points; ostruct.fixed_args=(void *)&mfs; ostruct.num_opt_args=1; ostruct.opt_args=(void *)&optimize_arg; ax=0.1; bx=12; opt_mnbrak(&ostruct, &ax, &bx, &cx, &fa, &fb, &fc); sumsq=opt_brent(&ostruct, ax, bx, cx, 1e-4, &xmin); # ifdef VERBOSE printf("%d %g %g %g\n", i, xmin, sumsq, hold); # endif weight= 1.0/sumsq; sumweight+=weight; ave+=weight*xmin; if (hold<min_power) min_power=hold; } ave/=sumweight; # ifdef VERBOSE printf("Consensus: %g %g\n", ave, min_power); # endif /*}}} */ /*{{{ Subtract symmetrical function*/ for (i=0, tinfo= &firsttinfo; tinfo!=NULL; tinfo=tinfo->next, i++) { tinfo_array(tinfo, &D); array_transpose(&D); array_reset(&D); D.current_vector=freqno; D.current_element=0; do { hold= min_power*distfun(100*channel_distance(tinfo, i, D.current_element), ave); array_write(&D, array_readelement(&D)-hold); } while (D.message==ARRAY_CONTINUE); } /*}}} */ } free(points); /*{{{ Write all data sets*/ tinfo= &firsttinfo; select_extract_item(tinfo); /* Output real part only */ (*tinfo->methods->transform_defaults)(tinfo); tinfo->methods->local_storage=(void *)0; (*tinfo->methods->transform_init)(tinfo); tinfo->methods++; select_writeasc(tinfo); (*tinfo->methods->transform_defaults)(tinfo); tinfo->outfname=argv[2]; tinfo->methods->local_storage=(void *)1; (*tinfo->methods->transform_init)(tinfo); for (; tinfo!=NULL; tinfo=tinfo->next) { tinfo->outfptr=firsttinfo.outfptr; tinfo->methods=methods; if ((new_tsdata=(*tinfo->methods->transform)(tinfo))==NULL) { ERREXIT(tinfo->emethods, "extract_item failed !\n"); } free(tinfo->tsdata); tinfo->tsdata=new_tsdata; tinfo->methods++; (*tinfo->methods->transform)(tinfo); } tinfo= &firsttinfo; tinfo->methods=methods; (*tinfo->methods->transform_exit)(tinfo); tinfo->methods++; (*tinfo->methods->transform_exit)(tinfo); /*}}} */ return 0; }
/*{{{ 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; }
/*{{{ project(transform_info_ptr tinfo)*/ METHODDEF DATATYPE * project(transform_info_ptr tinfo) { struct project_args_struct *project_args=(struct project_args_struct *)tinfo->methods->local_storage; transform_argument *args=tinfo->methods->arguments; DATATYPE *retvalue=tinfo->tsdata; array indata, scalars, *vectors= &project_args->vectors; int itempart, itemparts=tinfo->itemsize-tinfo->leaveright; if (project_args->project_mode==PROJECT_MODE_MULTIPLY) { if (!(tinfo->nr_of_channels==vectors->nr_of_vectors ||(tinfo->nr_of_channels==1 && tinfo->itemsize==vectors->nr_of_vectors))) { ERREXIT(tinfo->emethods, "project: Number of scalars and maps doesn't match!\n"); } } else { if (vectors->nr_of_elements!=tinfo->nr_of_channels) { ERREXIT2(tinfo->emethods, "project: %d channels in epoch, but %d channels in project file.\n", MSGPARM(tinfo->nr_of_channels), MSGPARM(vectors->nr_of_elements)); } } array_reset(vectors); tinfo_array(tinfo, &indata); array_transpose(&indata); /* Vectors are maps */ /* Be sure that different output items are adjacent... */ scalars.nr_of_elements=vectors->nr_of_vectors; switch (project_args->project_mode) { case PROJECT_MODE_SCALAR: scalars.nr_of_vectors=tinfo->nr_of_points; scalars.element_skip=itemparts; break; case PROJECT_MODE_SSP: case PROJECT_MODE_SSPS: scalars.nr_of_vectors=1; scalars.element_skip=1; break; case PROJECT_MODE_MULTIPLY: scalars=indata; if (tinfo->nr_of_channels!=vectors->nr_of_vectors) { /* Ie, one channel and weights in the items: Convert from 1 element to * itemsize elements */ scalars.element_skip=1; scalars.nr_of_elements=tinfo->itemsize; itemparts=1; } indata.element_skip=itemparts; indata.nr_of_elements=vectors->nr_of_elements; /* New number of channels */ indata.nr_of_vectors=scalars.nr_of_vectors; /* New number of points */ if (array_allocate(&indata)==NULL) { ERREXIT(tinfo->emethods, "project: Can't allocate new indata array\n"); } break; } if (project_args->project_mode==PROJECT_MODE_MULTIPLY) { array_transpose(vectors); /* Now the elements are the subspace dimensions */ for (itempart=0; itempart<itemparts; itempart++) { array_use_item(&indata, itempart); array_use_item(&scalars, itempart); do { /*{{{ Build the signal subspace vector*/ do { array_write(&indata, array_multiply(vectors, &scalars, MULT_SAMESIZE)); } while (indata.message==ARRAY_CONTINUE); /*}}} */ } while (indata.message!=ARRAY_ENDOFSCAN); } array_transpose(vectors); } else { if (array_allocate(&scalars)==NULL) { ERREXIT(tinfo->emethods, "project: Can't allocate scalars array\n"); } for (itempart=0; itempart<itemparts; itempart++) { array_use_item(&indata, itempart); if (project_args->project_mode==PROJECT_MODE_SCALAR) { array_use_item(&scalars, itempart); } do { /*{{{ Calculate the projection scalars*/ do { /* With all vectors in turn: */ DATATYPE product=0.0; do { if (project_args->channel_list!=NULL && !is_in_channellist(vectors->current_element+1, project_args->channel_list)) { array_advance(vectors); array_advance(&indata); } else { product+=array_scan(&indata)*array_scan(vectors); } } while (vectors->message==ARRAY_CONTINUE); array_write(&scalars, product); if (scalars.message==ARRAY_CONTINUE) array_previousvector(&indata); } while (scalars.message==ARRAY_CONTINUE); /*}}} */ switch (project_args->project_mode) { case PROJECT_MODE_SCALAR: break; case PROJECT_MODE_SSP: /*{{{ Build the signal subspace vector*/ array_transpose(vectors); /* Now the elements are the subspace dimensions */ array_previousvector(&indata); do { array_write(&indata, array_multiply(vectors, &scalars, MULT_VECTOR)); } while (indata.message==ARRAY_CONTINUE); array_transpose(vectors); /*}}} */ break; case PROJECT_MODE_SSPS: /*{{{ Subtract the signal subspace vector*/ array_transpose(vectors); /* Now the elements are the subspace dimensions */ array_previousvector(&indata); do { array_write(&indata, READ_ELEMENT(&indata)-array_multiply(vectors, &scalars, MULT_VECTOR)); } while (indata.message==ARRAY_CONTINUE); array_transpose(vectors); /*}}} */ break; default: /* Can't happen, just to keep the compiler happy... */ ERREXIT(tinfo->emethods, "project: This cannot happen!\n"); break; } } while (indata.message!=ARRAY_ENDOFSCAN); } } /*{{{ Prepare tinfo to reflect the data structure returned*/ switch (project_args->project_mode) { case PROJECT_MODE_SCALAR: if (args[ARGS_USE_CHANNELS].is_set) { tinfo->nr_of_channels=vectors->nr_of_vectors; tinfo->itemsize=itemparts; } else { tinfo->nr_of_channels=1; tinfo->itemsize=itemparts*vectors->nr_of_vectors; } tinfo->length_of_output_region=scalars.nr_of_elements*scalars.element_skip*scalars.nr_of_vectors; tinfo->leaveright=0; tinfo->multiplexed=TRUE; if (tinfo->channelnames!=NULL) { free_pointer((void **)&tinfo->channelnames[0]); free_pointer((void **)&tinfo->channelnames); } free_pointer((void **)&tinfo->probepos); create_channelgrid(tinfo); retvalue=scalars.start; break; case PROJECT_MODE_SSP: case PROJECT_MODE_SSPS: array_free(&scalars); retvalue=tinfo->tsdata; break; case PROJECT_MODE_MULTIPLY: /* Note that we don't free `scalars' because it just points to the original tsdata! */ /* Have to set this correctly so that copy_channelinfo works... */ tinfo->nr_of_channels=indata.nr_of_elements; copy_channelinfo(tinfo, project_args->save_side_tinfo.channelnames, project_args->save_side_tinfo.probepos); tinfo->nr_of_points=indata.nr_of_vectors; tinfo->itemsize=indata.element_skip; tinfo->length_of_output_region=tinfo->nr_of_channels*tinfo->nr_of_points*tinfo->itemsize; retvalue=indata.start; tinfo->multiplexed=TRUE; break; } /*}}} */ return retvalue; }
/*{{{ writeasc(transform_info_ptr tinfo) {*/ METHODDEF DATATYPE * writeasc(transform_info_ptr calltinfo) { struct writeasc_storage *local_arg=(struct writeasc_storage *)calltinfo->methods->local_storage; transform_argument *args=calltinfo->methods->arguments; int i, channel, itempart; long tsdata_step, tsdata_steps, tsdata_stepwidth; FILE *outfptr=local_arg->outfptr; /* Note that 'tinfo' instead of 'tinfoptr' is used here so that we don't have to modify * all of the older code which stored only one epoch */ transform_info_ptr tinfo=calltinfo; if (args[ARGS_CLOSE].is_set) { writeasc_open_file(calltinfo); outfptr=local_arg->outfptr; } if (args[ARGS_LINKED].is_set) { /* Go to the start: */ for (; tinfo->previous!=NULL; tinfo=tinfo->previous); } for (; tinfo!=NULL; tinfo=tinfo->next) { DATATYPE * const orig_tsdata=tinfo->tsdata; if (tinfo->xdata==NULL) create_xaxis(tinfo,NULL); if (tinfo->data_type==FREQ_DATA) { tinfo->nr_of_points=tinfo->nroffreq; tsdata_steps=tinfo->nrofshifts; tsdata_stepwidth=tinfo->nr_of_channels*tinfo->nroffreq*tinfo->itemsize; } else { tsdata_steps=1; tsdata_stepwidth=0; } for (tsdata_step=0; tsdata_step<tsdata_steps; tinfo->tsdata+=tsdata_stepwidth, tsdata_step++) { if (tinfo->data_type==FREQ_DATA && tsdata_steps>1) { /* Multiple data sets to be written: Construct a different z_value for each. */ if (tinfo->basetime==0.0) { /* Assigning the same latency to all shifts would not be optimal... */ tinfo->z_label="Nr"; tinfo->z_value=tsdata_step+1; } else { tinfo->z_label="Lat[ms]"; tinfo->z_value=(tsdata_step*tinfo->basetime+(tinfo->windowsize-tinfo->beforetrig)/tinfo->sfreq)*1000; } } if (args[ARGS_BINARY].is_set) { /*{{{ Write binary*/ char outbuf[OUTBUFSIZE], *inoutbuf; int len; fwrite((void *)&tinfo->nr_of_channels, sizeof(int), 1, outfptr); fwrite((void *)&tinfo->nr_of_points, sizeof(int), 1, outfptr); if (tinfo->itemsize<=0) tinfo->itemsize=1; fwrite((void *)&tinfo->itemsize, sizeof(int), 1, outfptr); fwrite((void *)&tinfo->multiplexed, sizeof(int), 1, outfptr); *outbuf='\0'; inoutbuf=outbuf; if (tinfo->nrofaverages>0) { snprintf(inoutbuf, OUTBUFSIZE-(inoutbuf-outbuf), "Nr_of_averages=%d;", tinfo->nrofaverages); inoutbuf+=strlen(inoutbuf); } if (tinfo->sfreq!=local_arg->sfreq) { snprintf(inoutbuf, OUTBUFSIZE-(inoutbuf-outbuf), "Sfreq=%f;", (float)tinfo->sfreq); inoutbuf+=strlen(inoutbuf); } if (tinfo->beforetrig!=local_arg->beforetrig) { snprintf(inoutbuf, OUTBUFSIZE-(inoutbuf-outbuf), "BeforeTrig=%d;", tinfo->beforetrig); inoutbuf+=strlen(inoutbuf); } if (tinfo->leaveright!=local_arg->leaveright) { snprintf(inoutbuf, OUTBUFSIZE-(inoutbuf-outbuf), "Leaveright=%d;", tinfo->leaveright); inoutbuf+=strlen(inoutbuf); } if (tinfo->condition!=0) { snprintf(inoutbuf, OUTBUFSIZE-(inoutbuf-outbuf), "Condition=%d;", tinfo->condition); inoutbuf+=strlen(inoutbuf); } if (tinfo->triggers.buffer_start!=NULL) { struct trigger *intrig=(struct trigger *)tinfo->triggers.buffer_start; snprintf(inoutbuf, OUTBUFSIZE-(inoutbuf-outbuf), "Triggers=%ld", intrig->position); inoutbuf+=strlen(inoutbuf); intrig++; while (intrig->code!=0) { snprintf(inoutbuf, OUTBUFSIZE-(inoutbuf-outbuf), ",%ld:%d", intrig->position, intrig->code); inoutbuf+=strlen(inoutbuf); intrig++; } *inoutbuf++=';'; } if (tinfo->comment!=NULL) { snprintf(inoutbuf, OUTBUFSIZE-(inoutbuf-outbuf), "%s", tinfo->comment); inoutbuf+=strlen(inoutbuf); } if (tinfo->z_label!=NULL) { snprintf(inoutbuf, OUTBUFSIZE-(inoutbuf-outbuf), "%s%s=%g", ZAXIS_DELIMITER, tinfo->z_label, tinfo->z_value); inoutbuf+=strlen(inoutbuf); } len=inoutbuf-outbuf+1; len+=strlen(tinfo->xchannelname)+1; for (channel=0; channel<tinfo->nr_of_channels; channel++) { len+=strlen(tinfo->channelnames[channel])+1; } fwrite((void *)&len, sizeof(int), 1, outfptr); fwrite((void *)outbuf, strlen(outbuf)+1, 1, outfptr); fwrite((void *)tinfo->xchannelname, strlen(tinfo->xchannelname)+1, 1, outfptr); for (channel=0; channel<tinfo->nr_of_channels; channel++) { fwrite((void *)tinfo->channelnames[channel], strlen(tinfo->channelnames[channel])+1, 1, outfptr); } fwrite((void *)tinfo->probepos, sizeof(double), 3*tinfo->nr_of_channels, outfptr); fwrite((void *)tinfo->xdata, sizeof(DATATYPE), tinfo->nr_of_points, outfptr); fwrite((void *)tinfo->tsdata, sizeof(DATATYPE), tinfo->nr_of_channels*tinfo->nr_of_points*tinfo->itemsize, outfptr); /* 6 ints: channels/points/items/multiplexed/len_of_string_section/skipback */ len+=6*sizeof(int)+3*tinfo->nr_of_channels*sizeof(double)+tinfo->nr_of_points*(1+tinfo->nr_of_channels*tinfo->itemsize)*sizeof(DATATYPE); fwrite((void *)&len, sizeof(int), 1, outfptr); /*}}} */ } else { /*{{{ Write ascii*/ array myarray; if (tinfo->nrofaverages>0) fprintf(outfptr, "Nr_of_averages=%d;", tinfo->nrofaverages); if (tinfo->sfreq!=local_arg->sfreq) fprintf(outfptr, "Sfreq=%f;", (float)tinfo->sfreq); if (tinfo->beforetrig!=local_arg->beforetrig) fprintf(outfptr, "BeforeTrig=%d;", tinfo->beforetrig); if (tinfo->leaveright!=local_arg->leaveright) fprintf(outfptr, "Leaveright=%d;", tinfo->leaveright); if (tinfo->condition!=0) fprintf(outfptr, "Condition=%d;", tinfo->condition); if (tinfo->triggers.buffer_start!=NULL) { struct trigger *intrig=(struct trigger *)tinfo->triggers.buffer_start; fprintf(outfptr, "Triggers=%ld", intrig->position); intrig++; while (intrig->code!=0) { fprintf(outfptr, ",%ld:%d", intrig->position, intrig->code); intrig++; } fprintf(outfptr, ";"); } if (tinfo->comment!=NULL) fprintf(outfptr, "%s", tinfo->comment); if (tinfo->z_label!=NULL) fprintf(outfptr, "%s%s=%g", ZAXIS_DELIMITER, tinfo->z_label, tinfo->z_value); fprintf(outfptr,"\nchannels=%d, points=%d", tinfo->nr_of_channels, tinfo->nr_of_points); if (tinfo->itemsize<=1) { tinfo->itemsize=1; /* Make sure the itemsize is at least 1 */ } else { fprintf(outfptr, ", itemsize=%d", tinfo->itemsize); } fprintf(outfptr, "\n%s", tinfo->xchannelname); for (channel=0; channel<tinfo->nr_of_channels; channel++) { char buffer[MAX_CHANNEL_LEN+1], *inbuf; strncpy(buffer, tinfo->channelnames[channel], MAX_CHANNEL_LEN); buffer[MAX_CHANNEL_LEN]='\0'; /* Some characters can become hazardous, so we change them... */ for (inbuf=buffer; *inbuf!='\0'; inbuf++) { if (strchr(" \t\n", *inbuf)!=NULL) *inbuf='_'; } fprintf(outfptr, "\t%s", buffer); } for (i=0; i<3; i++) { fprintf(outfptr, "\n-"); for (channel=0; channel<tinfo->nr_of_channels; channel++) { fprintf(outfptr, "\t%g", tinfo->probepos[channel*3+i]); } } fprintf(outfptr, "\n"); tinfo_array(tinfo, &myarray); array_transpose(&myarray); /* Outer loop is for points */ i=0; do { fprintf(outfptr, "%g", tinfo->xdata[i]); do { if (tinfo->itemsize==1) { fprintf(outfptr, "\t%g", array_scan(&myarray)); } else { DATATYPE *itemptr=ARRAY_ELEMENT(&myarray); fprintf(outfptr, "\t(%g", *itemptr++); for (itempart=1; itempart<tinfo->itemsize; itempart++) { fprintf(outfptr, "\t%g", *itemptr++); } fprintf(outfptr, ")"); array_advance(&myarray); } } while (myarray.message==ARRAY_CONTINUE); fprintf(outfptr, "\n"); i++; } while (myarray.message!=ARRAY_ENDOFSCAN); /*}}} */ } } /* FREQ_DATA shifts loop */ tinfo->tsdata=orig_tsdata; if (!args[ARGS_LINKED].is_set) { break; } } /* Linked epochs loop */ if (args[ARGS_CLOSE].is_set) writeasc_close_file(tinfo); return calltinfo->tsdata; /* Simply to return something `useful' */ }