static Rel *pack(char *str, char *names[], Type types[], int len) { char *n[len]; Type t[len]; for (int i = 0; i < len; ++i) { n[i] = names[i]; t[i] = types[i]; } Head *head = head_new(n, t, len); TBuf *body = NULL; Error *err = pack_csv2rel(str, head, &body); if (err != NULL) fail(); Rel *res = NULL; if (body != NULL) { int idx = array_scan(vars->names, vars->len, "___param"); if (idx < 0) fail(); res = rel_load(head, "___param"); vars->vals[idx] = body; } mem_free(head); return res; }
GLOBAL DATATYPE array_sum(array *thisarray) { DATATYPE sum=0.0; do { sum+=array_scan(thisarray); } while (thisarray->message==ARRAY_CONTINUE); return sum; }
static void load_vars() { for (int i = 0; i < rvars->len; ++i) { int pos = array_scan(vars->names, vars->len, rvars->names[i]); if (pos < 0) fail(); vars->vals[pos] = vol_read(rvars->vols[i], rvars->names[i], rvars->vers[i]); } }
iterator scan( struct cog *cog, long low, long high ) { if( cog->type == COG_BTREE ) { struct cog *a = cog->data.btree.lhs; struct cog *b = cog->data.btree.rhs; long sep = cog->data.btree.sep; if( sep <= low ) { return scan(b, low, high); } } if( cog->type == COG_BTREE ) { struct cog *a = cog->data.btree.lhs; struct cog *b = cog->data.btree.rhs; long sep = cog->data.btree.sep; if( sep >= high ) { return scan(a, low, high); } } if( cog->type == COG_CONCAT || cog->type == COG_BTREE ) { struct cog *a; struct cog *b; if(cog->type == COG_CONCAT) { a = cog->data.concat.lhs; b = cog->data.concat.rhs; } else { a = cog->data.btree.lhs; b = cog->data.btree.rhs; } return iter_concat( scan(a, low, high), scan(b, low, high) ); } if( cog->type == COG_SORTEDARRAY ) { int start = cog->data.sortedarray.start; int len = cog->data.sortedarray.len; buffer b = cog->data.sortedarray.records; return array_binarysearch_scan(low, high, start, len, b); } if( cog->type == COG_ARRAY || cog->type == COG_SORTEDARRAY ) { int start = cog->data.array.start; int len = cog->data.array.len; buffer b = cog->data.array.records; return array_scan(low, high, start, len, b); } fprintf(stderr, "Unmatched case in 'scan'\n"); exit(-1); }
/*{{{ 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; }
/*{{{ histogram(transform_info_ptr tinfo) {*/ METHODDEF DATATYPE * histogram(transform_info_ptr tinfo) { struct histogram_local_struct *localp=(struct histogram_local_struct *)tinfo->methods->local_storage; transform_argument *args=tinfo->methods->arguments; HIST_TYPE *histogram_data=localp->boundaries.histogram; DATATYPE hist_min=localp->boundaries.hist_min, hist_resolution=localp->boundaries.hist_resolution; int nr_of_bins=localp->boundaries.nr_of_bins; int from_x=localp->from_x, to_x=localp->to_x; int outliers=args[ARGS_ASSIGN_OUTLIERS].is_set; int channels=tinfo->nr_of_channels, itemsize=tinfo->itemsize; int channelskip, freqskip, channel, point, points, freq, nfreq; int out_binskip, out_freqskip, out_pointskip, out_channelskip, out_shifts; int start_freq, end_freq, start_point, end_point; int freq_offset, channel_offset, point_offset; array tsdata; if (itemsize>1) { ERREXIT(tinfo->emethods, "histogram: Can't handle multiple items in input data.\n"); } /*{{{ Set up tsdata array: elements=points, vectors=items*/ tsdata.vector_skip=1; tsdata.nr_of_vectors=itemsize; if (from_x<0) from_x=0; if (tinfo->data_type==FREQ_DATA) { nfreq=tinfo->nroffreq; freqskip=itemsize; channelskip=nfreq*itemsize; tsdata.element_skip=channels*channelskip; out_shifts=points=tinfo->nrofshifts; if (to_x<0 || to_x>nfreq) to_x=nfreq; start_freq=from_x; end_freq=to_x; start_point=0; end_point=points; if (args[ARGS_COLLAPSE_POINTS].is_set) { out_pointskip=0; } else { out_pointskip=(end_freq-start_freq)*nr_of_bins*(args[ARGS_COLLAPSE_CHANNELS].is_set ? 1 : channels); } } else { nfreq=1; freqskip=0; points=tinfo->nr_of_points; if (tinfo->multiplexed) { tsdata.element_skip=channels*itemsize; channelskip=itemsize; } else { tsdata.element_skip=itemsize; channelskip=tinfo->nr_of_points*itemsize; } if (to_x<0 || to_x>points) to_x=points; start_freq=0; end_freq=1; start_point=from_x; end_point=to_x; out_shifts=1; out_pointskip=(args[ARGS_COLLAPSE_POINTS].is_set ? 0: 1); } tsdata.nr_of_elements=points; array_setreadwrite(&tsdata); if (to_x<=from_x) { ERREXIT(tinfo->emethods, "histogram: minx>=maxx. Please respecify these parameters.\n"); } out_binskip=(args[ARGS_COLLAPSE_POINTS].is_set ? 1 : to_x-from_x); out_channelskip=(args[ARGS_COLLAPSE_CHANNELS].is_set ? 0 : out_binskip*nr_of_bins); out_freqskip=1; /*}}} */ if (histogram_data==(HIST_TYPE *)NULL) { /*{{{ First incoming epoch: Initialize working memory*/ memcpy(&localp->tinfo, tinfo, sizeof(struct transform_info_struct)); /* Protect the memory spaces we may need: */ tinfo->comment=NULL; tinfo->probepos=NULL; if (args[ARGS_COLLAPSE_CHANNELS].is_set) { localp->tinfo.length_of_output_region=out_binskip*nr_of_bins*out_shifts; localp->tinfo.nr_of_channels=1; } else { tinfo->channelnames=NULL; localp->tinfo.length_of_output_region=channels*out_channelskip*out_shifts; } if ((histogram_data=(HIST_TYPE *)calloc(localp->tinfo.length_of_output_region, sizeof(DATATYPE)))==NULL) { ERREXIT(tinfo->emethods, "histogram: Error allocating epoch memory\n"); } localp->tinfo.tsdata=(DATATYPE *)(localp->boundaries.histogram=histogram_data); localp->tinfo.itemsize=out_binskip; localp->tinfo.leaveright=0; if (tinfo->data_type==FREQ_DATA) { localp->tinfo.nroffreq=nr_of_bins; /* nrofshifts remains unmodified */ } else { localp->tinfo.nr_of_points=nr_of_bins; } localp->tinfo.multiplexed=FALSE; localp->to_x=to_x; localp->from_x=from_x; /*}}} */ } /*{{{ Register the input data*/ freq_offset=0; for (freq=start_freq; freq<end_freq; freq++) { tsdata.start=tinfo->tsdata+freq*freqskip; channel_offset=freq_offset; for (channel=0; channel<channels; channel++) { array_setreadwrite(&tsdata); array_reset(&tsdata); tsdata.current_element=start_point; point_offset=channel_offset; for (point=start_point; point<end_point; point++) { int bin=(int)rint((array_scan(&tsdata)-hist_min)/hist_resolution); if (bin>=0 && bin<nr_of_bins) { histogram_data[point_offset+bin*out_binskip]++; } else if (outliers) { if (bin<0) histogram_data[point_offset]++; else histogram_data[point_offset+(nr_of_bins-1)*out_binskip]++; } point_offset+=out_pointskip; } tsdata.start+=channelskip; channel_offset+=out_channelskip; } freq_offset+=out_freqskip; } /*}}} */ free_tinfo(tinfo); /* Free everything from the old epoch */ tinfo->nrofaverages++; return localp->tinfo.tsdata; }
/*{{{ 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' */ }
/*{{{ 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' */ }
GLOBAL void array_copy(array *array1, array *array2) { do { array_write(array2, array_scan(array1)); } while (array1->message!=ARRAY_ENDOFSCAN && array2->message!=ARRAY_ENDOFSCAN); }
/*{{{ 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; }
/*{{{ is_inside(array *index, array *inpoints, DATATYPE x, DATATYPE y) {*/ LOCAL int is_inside(array *index, array *inpoints, DATATYPE x, DATATYPE y) { array x1, x2, x3; DATATYPE x3data[2], d, x3dist, hold, xminline=0, yminline=0; DATATYPE dist, mindist= -1, xline, yline; /*{{{ Prepare x3: x3 is an array that holds x and y*/ x3data[0]=x; x3data[1]=y; x3.nr_of_elements=2; x3.nr_of_vectors=x3.element_skip=1; x3.start=x3data; array_setreadwrite(&x3); array_reset(&x3); /*}}} */ /*{{{ x3dist:=distance between x3 and (xmean, ymean)*/ hold=x-xmean; x3dist=hold*hold; hold=y-ymean; x3dist+=hold*hold; /*}}} */ /*{{{ Select qhull segment at minimum distance from x*/ array_reset(inpoints); array_reset(index); do { x1=x2= *inpoints; x1.current_vector=array_scan(index); x2.current_vector=array_scan(index); array_setto_vector(&x1); array_setto_vector(&x2); x1.nr_of_elements=x2.nr_of_elements=2; d=array_parameter_linedist(&x1, &x2, &x3); /* Let the end points participate in the vote as well */ if (d>1) d=1; if (d<0) d=0; xline=array_scan(&x1)*(1.0-d)+array_scan(&x2)*d; yline=array_scan(&x1)*(1.0-d)+array_scan(&x2)*d; hold=xline-array_scan(&x3); dist=hold*hold; hold=yline-array_scan(&x3); dist+=hold*hold; if (mindist<=0 || dist<mindist) { mindist=dist; xminline=xline; yminline=yline; } } while (index->message!=ARRAY_ENDOFSCAN); /*}}} */ /*{{{ dist:=(line-mean)^2*/ hold=xminline-xmean; dist=hold*hold; hold=yminline-ymean; dist+=hold*hold; /*}}} */ return (dist>x3dist); }
int main(int argc, char **argv) { FILE *fp; surfspline_desc sspline; int err, npoints, itempart=0; int binary_output=FALSE, matlab_output=FALSE, mtv_output=FALSE, interpolate_only=FALSE; float fbuf, external_value=0.0; DATATYPE f, x, y, xmin, xmax, ymin, ymax, xstep, ystep; array index; pid_t pid; char outname[L_tmpnam], inname[L_tmpnam], **inargs, *infile; /*{{{ Read command line args*/ for (inargs=argv+1; inargs-argv<argc && **inargs=='-'; inargs++) { switch(inargs[0][1]) { case 'B': binary_output=TRUE; break; case 'I': if (inargs[0][2]!='\0') { itempart=atoi(*inargs+2); } break; case 'i': interpolate_only=TRUE; if (inargs[0][2]!='\0') { external_value=atof(*inargs+2); } break; case 'M': matlab_output=TRUE; break; case 'm': mtv_output=TRUE; break; default: fprintf(stderr, "%s: Ignoring unknown option %s\n", argv[0], *inargs); continue; } } if (argc-(inargs-argv)!=3) { fprintf(stderr, "Usage: %s array_filename degree npoints\n" "Options:\n" " -Iitem: Use item number item as z-axis (2+item'th column); default: 0\n" " -i[value]: Interpolate only; set external values to value (default: 0.0)\n" " -B: Binary output (gnuplot floats)\n" " -M: Matlab output (x, y vectors and z matrix)\n" " -m: Plotmtv output\n" , argv[0]); return -1; } infile= *inargs++; if ((fp=fopen(infile, "r"))==NULL) { fprintf(stderr, "Can't open %s\n", infile); return -2; } array_undump(fp, &sspline.inpoints); fclose(fp); if (sspline.inpoints.message==ARRAY_ERROR) { fprintf(stderr, "Error in array_undump\n"); return -3; } if (sspline.inpoints.nr_of_elements<3+itempart) { fprintf(stderr, "Not enough columns in array %s\n", *(inargs-1)); return -3; } sspline.degree=atoi(*inargs++);; npoints=atoi(*inargs++); /*}}} */ /*{{{ Get the index of qhull point pairs by running qhull*/ tmpnam(outname); tmpnam(inname); if ((pid=fork())==0) { /* I'm the child */ #define LINEBUF_SIZE 128 char linebuf[LINEBUF_SIZE]; array tmp_array; /*{{{ Dump xy positions to tmp file inname*/ tmp_array.nr_of_elements=2; tmp_array.nr_of_vectors=sspline.inpoints.nr_of_vectors; tmp_array.element_skip=1; if (array_allocate(&tmp_array)==NULL) { fprintf(stderr, "Error allocating tmp_array\n"); return -4; } array_reset(&sspline.inpoints); do { array_write(&tmp_array, array_scan(&sspline.inpoints)); array_write(&tmp_array, array_scan(&sspline.inpoints)); array_nextvector(&sspline.inpoints); } while (tmp_array.message!=ARRAY_ENDOFSCAN); if ((fp=fopen(inname, "w"))==NULL) { fprintf(stderr, "Can't open %s\n", inname); return -5; } array_dump(fp, &tmp_array, ARRAY_ASCII); fclose(fp); array_free(&tmp_array); /*}}} */ snprintf(linebuf, LINEBUF_SIZE, "qhull C0 i b <%s >%s", inname, outname); execl("/bin/sh", "sh", "-c", linebuf, 0); #undef LINEBUF_SIZE } else { wait(NULL); } unlink(inname); if ((fp=fopen(outname, "r"))==NULL) { fprintf(stderr, "Can't open %s\n", outname); return -6; } array_undump(fp, &index); fclose(fp); unlink(outname); /*}}} */ /*{{{ Find min, max and mean coordinates*/ array_transpose(&sspline.inpoints); array_reset(&sspline.inpoints); xmin=array_min(&sspline.inpoints); ymin=array_min(&sspline.inpoints); array_reset(&sspline.inpoints); xmax=array_max(&sspline.inpoints); ymax=array_max(&sspline.inpoints); array_reset(&sspline.inpoints); xmean=array_mean(&sspline.inpoints); ymean=array_mean(&sspline.inpoints); xstep=(xmax-xmin)/npoints; ystep=(ymax-ymin)/npoints; array_transpose(&sspline.inpoints); array_reset(&sspline.inpoints); /*}}} */ /*{{{ Copy itempart to 3rd location if necessary*/ /* Note: For this behavior it is essential that array_surfspline * will accept vectors of any size >=3 and only process the first three * elements ! */ if (itempart>0) { DATATYPE hold; do { sspline.inpoints.current_element=2+itempart; hold=READ_ELEMENT(&sspline.inpoints); sspline.inpoints.current_element=2; WRITE_ELEMENT(&sspline.inpoints, hold); array_nextvector(&sspline.inpoints); } while (sspline.inpoints.message!=ARRAY_ENDOFSCAN); } /*}}} */ /*{{{ Do surface spline*/ if ((err=array_surfspline(&sspline))!=0) { fprintf(stderr, "Error %d in array_surfspline\n", err); return err; } xmin-=xstep; xmax+=2*xstep; ymin-=ystep; ymax+=2*ystep; if (binary_output) { /*{{{ Gnuplot binary output*/ int n_xval=(xmax-xmin)/xstep+1, n; /* Number of x values */ fbuf=n_xval; fwrite(&fbuf, sizeof(float), 1, stdout); for (fbuf=xmin, n=0; n<n_xval; fbuf+=xstep, n++) { /* x values */ fwrite(&fbuf, sizeof(float), 1, stdout); } for (y=ymin; y<=ymax; y+=ystep) { fbuf=y; fwrite(&fbuf, sizeof(float), 1, stdout); for (x=xmin, n=0; n<n_xval; x+=xstep, n++) { if (interpolate_only && !is_inside(&index, &sspline.inpoints, x, y)) { f=external_value; } else { f=array_fsurfspline(&sspline, x, y); } fbuf=f; fwrite(&fbuf, sizeof(float), 1, stdout); } } /*}}} */ } else if (matlab_output) { /*{{{ Matlab output*/ array xm, ym, zm; xm.nr_of_elements=ym.nr_of_elements=1; xm.nr_of_vectors=zm.nr_of_elements=(xmax-xmin)/xstep+1; ym.nr_of_vectors=zm.nr_of_vectors=(ymax-ymin)/ystep+1; xm.element_skip=ym.element_skip=zm.element_skip=1; array_allocate(&xm); array_allocate(&ym); array_allocate(&zm); if (xm.message==ARRAY_ERROR || ym.message==ARRAY_ERROR || zm.message==ARRAY_ERROR) { fprintf(stderr, "Error allocating output arrays\n"); return -7; } x=xmin; do { array_write(&xm, x); x+=xstep; } while (xm.message!=ARRAY_ENDOFSCAN); y=ymin; do { array_write(&ym, y); x=xmin; do { if (interpolate_only && !is_inside(&index, &sspline.inpoints, x, y)) { f=external_value; } else { f=array_fsurfspline(&sspline, x, y); } array_write(&zm, f); x+=xstep; } while (zm.message==ARRAY_CONTINUE); y+=ystep; } while (zm.message!=ARRAY_ENDOFSCAN); array_dump(stdout, &xm, ARRAY_MATLAB); array_dump(stdout, &ym, ARRAY_MATLAB); array_dump(stdout, &zm, ARRAY_MATLAB); array_free(&xm); array_free(&ym); array_free(&zm); /*}}} */ } else if (mtv_output) { /*{{{ Plotmtv output*/ array zm; DATATYPE zmin=FLT_MAX, zmax= -FLT_MAX; zm.nr_of_elements=(xmax-xmin)/xstep+1; zm.nr_of_vectors=(ymax-ymin)/ystep+1; zm.element_skip=1; array_allocate(&zm); if (zm.message==ARRAY_ERROR) { fprintf(stderr, "Error allocating output arrays\n"); return -7; } y=ymin; do { x=xmin; do { if (interpolate_only && !is_inside(&index, &sspline.inpoints, x, y)) { f=external_value; } else { f=array_fsurfspline(&sspline, x, y); } array_write(&zm, f); if (f<zmin) zmin=f; if (f>zmax) zmax=f; x+=xstep; } while (zm.message==ARRAY_CONTINUE); y+=ystep; } while (zm.message!=ARRAY_ENDOFSCAN); /*{{{ Print file header*/ printf( "# Output of Spline_Gridder (C) Bernd Feige 1995\n\n" "$ DATA=CONTOUR\n\n" "%% toplabel = \"Spline_Gridder output\"\n" "%% subtitle = \"File: %s\"\n\n" "%% interp = 0\n" "%% contfill = on\n" "%% meshplot = off\n\n" "%% xmin = %g xmax = %g\n" "%% ymin = %g ymax = %g\n" "%% zmin = %g zmax = %g\n" "%% nx = %d\n" "%% ny = %d\n" , infile, xmin, xmax, ymin, ymax, zmin, zmax, zm.nr_of_elements, zm.nr_of_vectors); /*}}} */ array_dump(stdout, &zm, ARRAY_MATLAB); array_free(&zm); /*}}} */ } else { /*{{{ Gnuplot output*/ for (x=xmin; x<=xmax; x+=xstep) { for (y=ymin; y<=ymax; y+=ystep) { if (interpolate_only && !is_inside(&index, &sspline.inpoints, x, y)) { f=external_value; } else { f=array_fsurfspline(&sspline, x, y); } printf("%g %g %g\n", x, y, f); } printf("\n"); } /*}}} */ } /*}}} */ return 0; }
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(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; }
LOCAL void noise_time(struct dipole_desc *dipole) { double scale=((double)rand())/(RAND_MAX/2)-1; do { array_write(&dipole->dip_moment, array_scan(&dipole->initial_moment)*scale); } while (dipole->dip_moment.message==ARRAY_CONTINUE); }
/*{{{ 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; }
/*{{{ normalize_channelbox(transform_info_ptr tinfo) {*/ METHODDEF DATATYPE * normalize_channelbox(transform_info_ptr tinfo) { struct normalize_channelbox_storage *local_arg=(struct normalize_channelbox_storage *)tinfo->methods->local_storage; transform_argument *args=tinfo->methods->arguments; transform_info_ptr const tinfoptr=tinfo; int channel, xmaxchan, xminchan, ymaxchan, yminchan, zmaxchan, zminchan; DATATYPE value, value2, xmax, ymax, zmax, xmin, ymin, zmin, xmid, ymid, zmid; DATATYPE tval[9]; double phi; array myarray, t; local_arg->view_from_left=FALSE; /*{{{ Construct array myarray*/ myarray.start=(DATATYPE *)tinfoptr->probepos; myarray.nr_of_elements=3; myarray.nr_of_vectors=tinfoptr->nr_of_channels; myarray.vector_skip=3; myarray.element_skip=1; array_setreadwrite_double(&myarray); /*}}} */ /*{{{ Swap x and y if data set is 'Roma' (x=left->right)*/ if (strncmp(tinfo->comment, "Roma ", 5)==0) { /* This is the trace that vp2mfx leaves in Roma files. Though generality * lacks, this seems unavoidable in this module */ array_reset(&myarray); do { value=array_scan(&myarray); value2=array_scan(&myarray); myarray.current_element=0; array_write(&myarray, value2); array_write(&myarray, -value); array_advance(&myarray); } while (myarray.message!=ARRAY_ENDOFSCAN); } /*}}} */ /*{{{ Find min and max values of the box*/ array_reset(&myarray); xmax=xmin=array_scan(&myarray); ymax=ymin=array_scan(&myarray); zmax=zmin=array_scan(&myarray); xmaxchan=xminchan=ymaxchan=yminchan=zmaxchan=zminchan=0; channel=1; do { value=array_scan(&myarray); if (value>xmax) { xmax=value; xmaxchan=channel; } if (value<xmin) { xmin=value; xminchan=channel; } value=array_scan(&myarray); if (value>ymax) { ymax=value; ymaxchan=channel; } if (value<ymin) { ymin=value; yminchan=channel; } value=array_scan(&myarray); if (value>zmax) { zmax=value; zmaxchan=channel; } if (value<zmin) { zmin=value; zminchan=channel; } channel++; } while (myarray.message!=ARRAY_ENDOFSCAN); # ifdef DEBUG printf("zmaxchan=%s, xmaxchan=%s\n", tinfoptr->channelnames[zmaxchan], tinfoptr->channelnames[xmaxchan]); # endif /*}}} */ /*{{{ Subtract midpoint*/ xmid=(xmax+xmin)/2; ymid=(ymax+ymin)/2; zmid=(zmax+zmin)/2; # ifdef DEBUG printf("xmid=%g, ymid=%g, zmid=%g\n", xmid, ymid, zmid); # endif array_reset(&myarray); do { array_write(&myarray, READ_ELEMENT(&myarray)-xmid); array_write(&myarray, READ_ELEMENT(&myarray)-ymid); array_write(&myarray, READ_ELEMENT(&myarray)-zmid); } while (myarray.message!=ARRAY_ENDOFSCAN); /*}}} */ /*{{{ Construct array t to be used for rotations*/ t.start=tval; t.nr_of_elements=3; t.nr_of_vectors=3; t.element_skip=1; t.vector_skip=3; array_setreadwrite(&t); /*}}} */ /*{{{ rotate zmaxchan about the x axis by its angle to the y axis (maximize y)*/ /* By this rotation, the z component of zmaxchan is removed. */ array_reset(&t); myarray.current_vector=zmaxchan; myarray.current_element=1; value=array_scan(&myarray); /* y value */ value2=READ_ELEMENT(&myarray); /* z value */ value/=sqrt(value*value+value2*value2); phi=(value2>0 ? -acos(value) : acos(value)); # ifdef DEBUG printf("z=%g, cos phi=%g=%g, phi=%g\n", value2, value, cos(phi), phi); # endif array_write(&t, 1.0); array_write(&t, 0.0); array_write(&t, 0.0); array_write(&t, 0.0); array_write(&t, cos(phi)); array_write(&t, sin(phi)); array_write(&t, 0.0); array_write(&t, -sin(phi)); array_write(&t, cos(phi)); array_transpose(&t); array_reset(&myarray); do { DATATYPE x, y, z; x=array_multiply(&t, &myarray, MULT_SAMESIZE); y=array_multiply(&t, &myarray, MULT_SAMESIZE); z=array_multiply(&t, &myarray, MULT_SAMESIZE); array_previousvector(&myarray); array_write(&myarray, x); array_write(&myarray, y); array_write(&myarray, z); } while (myarray.message!=ARRAY_ENDOFSCAN); /*}}} */ /*{{{ rotate zmaxchan about the z axis by its angle to the y axis (maximize y)*/ /* Now remove the x component of zmaxchan. Coordinates should be 0, z, 0 */ array_reset(&t); myarray.current_element=0; myarray.current_vector=zmaxchan; value2=array_scan(&myarray); /* x value */ value=READ_ELEMENT(&myarray); /* y value */ value/=sqrt(value*value+value2*value2); phi=(value2>0 ? -acos(value) : acos(value)); # ifdef DEBUG printf("z=%g, cos phi=%g=%g, phi=%g\n", value2, value, cos(phi), phi); # endif array_write(&t, cos(phi)); array_write(&t, sin(phi)); array_write(&t, 0.0); array_write(&t, -sin(phi)); array_write(&t, cos(phi)); array_write(&t, 0.0); array_write(&t, 0.0); array_write(&t, 0.0); array_write(&t, 1.0); if (value2<0.0) array_transpose(&t); array_reset(&myarray); do { DATATYPE x, y, z; x=array_multiply(&t, &myarray, MULT_SAMESIZE); y=array_multiply(&t, &myarray, MULT_SAMESIZE); z=array_multiply(&t, &myarray, MULT_SAMESIZE); array_previousvector(&myarray); array_write(&myarray, x); array_write(&myarray, y); array_write(&myarray, z); } while (myarray.message!=ARRAY_ENDOFSCAN); /*}}} */ /*{{{ rotate xmaxchan about the y axis by its angle to the x axis (maximize x)*/ /* This is the only rotation that will leave zmaxchan at its position */ array_reset(&t); myarray.current_element=0; myarray.current_vector=(args[ARGS_DECIDE_LEFTRIGHT].is_set && ymid>0.0 ? local_arg->view_from_left=TRUE,xminchan : xmaxchan); value=array_scan(&myarray); /* x value */ array_advance(&myarray); value2=READ_ELEMENT(&myarray); /* z value */ value/=sqrt(value*value+value2*value2); phi=(value2>0 ? -acos(value) : acos(value)); # ifdef DEBUG printf("z=%g, cos phi=%g=%g, phi=%g\n", value2, value, cos(phi), phi); # endif array_write(&t, cos(phi)); array_write(&t, 0.0); array_write(&t, -sin(phi)); array_write(&t, 0.0); array_write(&t, 1.0); array_write(&t, 0.0); array_write(&t, sin(phi)); array_write(&t, 0.0); array_write(&t, cos(phi)); if (value2<0.0) array_transpose(&t); array_reset(&myarray); do { DATATYPE x, y, z; x=array_multiply(&t, &myarray, MULT_SAMESIZE); y=array_multiply(&t, &myarray, MULT_SAMESIZE); z=array_multiply(&t, &myarray, MULT_SAMESIZE); array_previousvector(&myarray); array_write(&myarray, x); array_write(&myarray, y); array_write(&myarray, z); } while (myarray.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; }
static void processor(const char *tx_addr, int port) { sys_init(1); sys_log('E', "started port=%d, tx=%s\n", port, tx_addr); /* connect to the control thread */ char addr[MAX_ADDR]; sys_address(addr, port); IO *io = sys_connect(addr, IO_CHUNK); tx_attach(tx_addr); /* get env code from the tx */ char *code = tx_program(); char *res = mem_alloc(MAX_BLOCK); while (!io->stop) { sys_iready(io, -1); int status = -1; long long sid = 0LL, time = sys_millis(); Env *env = NULL; Arg *arg = NULL; Vars *v = vars_new(0), *r = NULL, *w = NULL; Http_Req *req = http_parse_req(io); if (io->stop) goto exit; if (req == NULL) { status = http_400(io); goto exit; } if (req->method == OPTIONS) { status = http_opts(io); goto exit; } env = env_new("net", code); if (str_idx(req->path, "/fn") == 0) { int idx = (req->path[3] == '/') ? 4 : 3; int i = 0, len = 1, cnt = 0; Func **fns = env_funcs(env, req->path + idx, &cnt); status = http_200(io); while (status == 200 && len) { len = pack_fn2csv(fns, cnt, res, MAX_BLOCK, &i); status = http_chunk(io, res, len); } mem_free(fns); goto exit; } /* compare the request with the function defintion */ Func *fn = env_func(env, req->path + 1); if (fn == NULL) { Error *err = error_new("unknown function '%s'", req->path + 1); status = http_404(io, err->msg); mem_free(err); goto exit; } if (fn->rp.name != NULL && req->method != POST) { status = http_405(io, POST); goto exit; } if (fn->rp.name == NULL && req->method == POST) { status = http_405(io, GET); goto exit; } /* TODO: think what to do with duplicate parameter values */ for (int i = 0; i < req->args->len; ++i) { char *name = req->args->names[i]; if (array_freq(req->args->names, req->args->len, name) > 1) { Error *err = error_new("duplicate parameter '%s' " "(not supported)", name); status = http_404(io, err->msg); mem_free(err); goto exit; } } if (fn->pp.len != req->args->len) { Error *err = error_new("expected %d primitive parameters, got %d", fn->pp.len, req->args->len); status = http_404(io, err->msg); mem_free(err); goto exit; } arg = mem_alloc(sizeof(Arg)); for (int i = 0; i < fn->pp.len; ++i) { char *name = fn->pp.names[i]; Type t = fn->pp.types[i]; int idx = array_scan(req->args->names, req->args->len, name); if (idx < 0) { Error *err = error_new("unknown parameter '%s'", name); status = http_404(io, err->msg); mem_free(err); goto exit; } char *val = req->args->vals[idx]; int error = 0; if (t == Int) { arg->vals[i].v_int = str_int(val, &error); } else if (t == Real) arg->vals[i].v_real = str_real(val, &error); else if (t == Long) arg->vals[i].v_long = str_long(val, &error); else if (t == String) { error = str_len(val) > MAX_STRING; if (!error) str_cpy(arg->vals[i].v_str, val); } if (error) { Error *err = error_new("value '%s' (parameter '%s') " "is not of type '%s'", val, name, type_to_str(t)); status = http_404(io, err->msg); mem_free(err); goto exit; } } if (fn->rp.name != NULL) { TBuf *body = NULL; if (req->len > 0) { Error *err = pack_csv2rel(req->body, fn->rp.head, &body); if (err != NULL) { status = http_404(io, err->msg); mem_free(err); goto exit; } } else { body = tbuf_new(); } vars_add(v, fn->rp.name, 0, body); /* project the parameter */ Rel *param = rel_project(rel_load(fn->rp.head, fn->rp.name), fn->rp.head->names, fn->rp.head->len); rel_eval(param, v, arg); /* clean the previous version */ tbuf_clean(body); tbuf_free(body); /* replace with the new body */ int vpos = array_scan(v->names, v->len, fn->rp.name); v->vals[vpos] = param->body; param->body = NULL; rel_free(param); } /* start a transaction */ r = vars_new(fn->r.len); w = vars_new(fn->w.len); for (int i = 0; i < fn->r.len; ++i) vars_add(r, fn->r.names[i], 0, NULL); for (int i = 0; i < fn->w.len; ++i) vars_add(w, fn->w.names[i], 0, NULL); sid = tx_enter(addr, r, w); /* prepare variables */ for (int i = 0; i < r->len; ++i) { TBuf *body = vol_read(r->vols[i], r->names[i], r->vers[i]); vars_add(v, r->names[i], 0, body); } for (int i = 0; i < w->len; ++i) { int pos = array_scan(v->names, v->len, w->names[i]); if (pos < 0) vars_add(v, w->names[i], 0, NULL); } for (int i = 0; i < fn->t.len; ++i) vars_add(v, fn->t.names[i], 0, NULL); /* evaluate the function body */ for (int i = 0; i < fn->slen; ++i) rel_eval(fn->stmts[i], v, arg); /* prepare the return value. note, the resulting relation is just a container for the body, so it is not freed */ Rel *ret = NULL; if (fn->ret != NULL) ret = fn->stmts[fn->slen - 1]; /* persist the global variables */ for (int i = 0; i < w->len; ++i) { int idx = array_scan(v->names, v->len, w->names[i]); if (idx < 0) { status = http_500(io); goto exit; } vol_write(w->vols[i], v->vals[idx], w->names[i], w->vers[i]); tbuf_free(v->vals[idx]); v->vals[idx] = NULL; } /* confirm a success and send the result back */ status = http_200(io); if (status != 200) goto exit; tx_commit(sid); /* N.B. there is no explicit revert as the transaction manager handles nested tx_enter and a connectivity failure as a rollback */ int len = 1, i = 0; while (status == 200 && len) { len = pack_rel2csv(ret, res, MAX_BLOCK, i++); status = http_chunk(io, res, len); } exit: if (status != -1) sys_log('E', "%016llX method %c, path %s, time %lldms - %3d\n", sid, (req == NULL) ? '?' : req->method, (req == NULL) ? "malformed" : req->path, sys_millis() - time, status); if (r != NULL) vars_free(r); if (w != NULL) vars_free(w); if (arg != NULL) mem_free(arg); if (req != NULL) http_free_req(req); if (env != NULL) env_free(env); for (int i = 0; i < v->len; ++i) if (v->vals[i] != NULL) { tbuf_clean(v->vals[i]); tbuf_free(v->vals[i]); } vars_free(v); sys_term(io); } mem_free(code); mem_free(res); tx_detach(); sys_close(io); }