unsigned long scan_to_array(unsigned long (*func)(const char*,char*,unsigned long*), const char* src,array* dest) { unsigned long scanned; unsigned long needed=str_len(src); char* x=((char*)array_start(dest))+array_bytes(dest); if (!array_allocate(dest,1,array_bytes(dest)+needed-1)) return 0; return func(src,x,&scanned); }
void fmt_to_array(size_t (*func)(char*,const char*,size_t), array* a,const char* src,size_t len) { size_t needed=func(0,src,len); if (array_bytes(a)+needed>=needed && array_allocate(a,1,array_bytes(a)+needed-1)) { char* x=((char*)array_start(a))+array_bytes(a)-needed; func(x,src,len); } else array_fail(a); }
void fmt_tofrom_array(unsigned long (*func)(char*,const char*,unsigned long), array* dest,array* src) { unsigned long needed; char* x; if (array_failed(dest) || array_failed(src)) { array_fail(dest); return; } needed=func(0,array_start(src),array_bytes(src)); if (array_allocate(dest,1,array_bytes(dest)+needed-1)) { x=((char*)array_start(dest))+array_bytes(dest)-needed; func(x,array_start(src),array_bytes(src)); } else array_fail(dest); }
void fmt_tofrom_array(size_t (*func)(char*,const char*,size_t), array* dest,array* src) { size_t needed; char* x; if (array_failed(dest) || array_failed(src)) { array_fail(dest); return; } needed=func(0,array_start(src),array_bytes(src)); if (array_bytes(dest)+needed>needed && array_allocate(dest,1,array_bytes(dest)+needed-1)) { x=((char*)array_start(dest))+array_bytes(dest)-needed; func(x,array_start(src),array_bytes(src)); } else array_fail(dest); }
/*{{{ 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; }
size_t scan_tofrom_array(size_t (*func)(const char*,char*,size_t*), array* src,array* dest) { size_t scanned; size_t needed; char* x; array_cat0(src); if (array_failed(src) || array_failed(dest)) return 0; needed=array_bytes(src); x=((char*)array_start(dest))+array_bytes(dest); if (!array_allocate(dest,1,array_bytes(dest)+needed-1)) return 0; needed=func(array_start(src),x,&scanned); array_truncate(src,1,array_bytes(src)-1); return needed; }
void array_catb(array* to,const char* from,uint64 len) { long l; if (!len) return; if (to->allocated<0) return; if (to->initialized+len<to->initialized) { fail: array_fail(to); return; } l=to->initialized; if (!array_allocate(to,1,to->initialized+len-1)) goto fail; byte_copy(to->p+l,to->initialized-l,from); }
/*{{{ null_source(transform_info_ptr tinfo) {*/ METHODDEF DATATYPE * null_source(transform_info_ptr tinfo) { struct null_source_storage *local_arg=(struct null_source_storage *)tinfo->methods->local_storage; array myarray; if (local_arg->epochs--==0) return NULL; tinfo->beforetrig=local_arg->beforetrig; tinfo->aftertrig=local_arg->aftertrig; tinfo->nr_of_points=local_arg->beforetrig+local_arg->aftertrig; tinfo->nr_of_channels=local_arg->nr_of_channels; tinfo->nrofaverages=1; if (tinfo->nr_of_points<=0) { ERREXIT1(tinfo->emethods, "null_source: Invalid nr_of_points %d\n", MSGPARM(tinfo->nr_of_points)); } /*{{{ Configure myarray*/ myarray.element_skip=tinfo->itemsize=local_arg->itemsize; tinfo->multiplexed=FALSE; myarray.nr_of_elements=tinfo->nr_of_points; myarray.nr_of_vectors=tinfo->nr_of_channels; if (array_allocate(&myarray)==NULL || (tinfo->comment=(char *)malloc(MAX_COMMENTLEN))==NULL) { ERREXIT(tinfo->emethods, "null_source: Error allocating data\n"); } /*}}} */ snprintf(tinfo->comment, MAX_COMMENTLEN, "null_source"); /* Force create_channelgrid to really allocate the channel info anew. * Otherwise, free_tinfo will free someone else's data ! */ tinfo->channelnames=NULL; tinfo->probepos=NULL; create_channelgrid(tinfo); /* Create defaults for any missing channel info */ local_arg->current_epoch=0; tinfo->z_label=NULL; tinfo->sfreq=local_arg->sfreq; tinfo->tsdata=myarray.start; tinfo->length_of_output_region=tinfo->nr_of_channels*tinfo->nr_of_points*tinfo->itemsize; tinfo->leaveright=0; tinfo->data_type=TIME_DATA; local_arg->current_epoch++; return tinfo->tsdata; }
/*{{{ 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 {
int iob_addfile_close(io_batch* b,int64 fd,uint64 off,uint64 n) { iob_entry* e; if (n==0) { io_close(fd); return 1; } io_fd(fd); e=array_allocate(&b->b,sizeof(iob_entry), array_length(&b->b,sizeof(iob_entry))); if (!e) return 0; e->type=FROMFILE; e->fd=fd; e->buf=0; e->n=n; e->offset=off; e->cleanup=cleanup; b->bytesleft+=n; ++b->files; return 1; }
/*{{{ read_neurofile(transform_info_ptr tinfo) {*/ METHODDEF DATATYPE * read_neurofile(transform_info_ptr tinfo) { struct read_neurofile_storage *local_arg=(struct read_neurofile_storage *)tinfo->methods->local_storage; transform_argument *args=tinfo->methods->arguments; array myarray; FILE *infile=local_arg->infile; Bool not_correct_trigger=FALSE; long trigger_point, file_start_point, file_end_point; char *innamebuf; int channel; char *description=NULL; if (local_arg->epochs--==0) return NULL; tinfo->beforetrig=local_arg->beforetrig; tinfo->aftertrig=local_arg->aftertrig; tinfo->nr_of_points=local_arg->beforetrig+local_arg->aftertrig; tinfo->nr_of_channels=local_arg->nr_of_channels; tinfo->nrofaverages=1; if (tinfo->nr_of_points<=0) { ERREXIT1(tinfo->emethods, "read_neurofile: Invalid nr_of_points %d\n", MSGPARM(tinfo->nr_of_points)); } /*{{{ Find the next window that fits into the actual data*/ /* This is just for the Continuous option (no trigger file): */ file_end_point=local_arg->current_point-1; do { if (args[ARGS_CONTINUOUS].is_set) { /* Simulate a trigger at current_point+beforetrig */ file_start_point=file_end_point+1; trigger_point=file_start_point+tinfo->beforetrig; file_end_point=trigger_point+tinfo->aftertrig-1; if (local_arg->points_in_file>0 && file_end_point>=local_arg->points_in_file) return NULL; local_arg->current_trigger++; local_arg->current_point+=tinfo->nr_of_points; tinfo->condition=0; } else do { tinfo->condition=read_neurofile_read_trigger(tinfo, &trigger_point, &description); if (tinfo->condition==0) return NULL; /* No more triggers in file */ file_start_point=trigger_point-tinfo->beforetrig+local_arg->offset; file_end_point=trigger_point+tinfo->aftertrig-1-local_arg->offset; if (local_arg->trigcodes==NULL) { not_correct_trigger=FALSE; } else { int trigno=0; not_correct_trigger=TRUE; while (local_arg->trigcodes[trigno]!=0) { if (local_arg->trigcodes[trigno]==tinfo->condition) { not_correct_trigger=FALSE; break; } trigno++; } } } while (not_correct_trigger || file_start_point<0 || (local_arg->points_in_file>0 && file_end_point>=local_arg->points_in_file)); } while (--local_arg->fromepoch>0); if (description==NULL) { TRACEMS3(tinfo->emethods, 1, "read_neurofile: Reading around tag %d at %d, condition=%d\n", MSGPARM(local_arg->current_trigger), MSGPARM(trigger_point), MSGPARM(tinfo->condition)); } else { TRACEMS4(tinfo->emethods, 1, "read_neurofile: Reading around tag %d at %d, condition=%d, description=%s\n", MSGPARM(local_arg->current_trigger), MSGPARM(trigger_point), MSGPARM(tinfo->condition), MSGPARM(description)); } /*{{{ Handle triggers within the epoch (option -T)*/ if (args[ARGS_TRIGTRANSFER].is_set) { int trigs_in_epoch, code; long trigpoint; long const old_current_trigger=local_arg->current_trigger; char *thisdescription; /* First trigger entry holds file_start_point */ push_trigger(&tinfo->triggers, file_start_point, -1, NULL); read_neurofile_reset_triggerbuffer(tinfo); for (trigs_in_epoch=1; (code=read_neurofile_read_trigger(tinfo, &trigpoint, &thisdescription))!=0;) { if (trigpoint>=file_start_point && trigpoint<=file_end_point) { push_trigger(&tinfo->triggers, trigpoint-file_start_point, code, thisdescription); trigs_in_epoch++; } } push_trigger(&tinfo->triggers, 0, 0, NULL); /* End of list */ local_arg->current_trigger=old_current_trigger; } /*}}} */ fseek(infile, file_start_point*tinfo->nr_of_channels, SEEK_SET); /*{{{ Configure myarray*/ myarray.element_skip=tinfo->itemsize=1; tinfo->multiplexed=TRUE; myarray.nr_of_elements=tinfo->nr_of_channels; myarray.nr_of_vectors=tinfo->nr_of_points; if (array_allocate(&myarray)==NULL || (tinfo->channelnames=(char **)malloc(tinfo->nr_of_channels*sizeof(char *)))==NULL || (innamebuf=(char *)malloc(local_arg->stringlength))==NULL || (tinfo->comment=(char *)malloc(strlen((char *)local_arg->seq.comment)+(1+17+1)))==NULL) { ERREXIT(tinfo->emethods, "read_neurofile: Error allocating data\n"); } /*}}} */ sprintf(tinfo->comment, "%s %02d/%02d/%02d,%02d:%02d:%02d", local_arg->seq.comment, local_arg->seq.month, local_arg->seq.day, local_arg->seq.year, local_arg->seq.hour, local_arg->seq.minute, local_arg->seq.second); for (channel=0; channel<tinfo->nr_of_channels; channel++) { strcpy(innamebuf, (char *)local_arg->seq.elnam[channel]); tinfo->channelnames[channel]=innamebuf; innamebuf+=strlen(innamebuf)+1; } do { signed char exponent; short delta; if (fread(&exponent, sizeof(exponent), 1, infile)!=1) { ERREXIT(tinfo->emethods, "read_neurofile: Error reading data\n"); } delta=exponent; exponent&=0x03; if (exponent==0x03) { delta>>=2; } else { delta=(delta&0xfffc)<<(exponent*2); } local_arg->last_values[myarray.current_element]+=delta; array_write(&myarray, local_arg->last_values[myarray.current_element]*local_arg->factor); } while (myarray.message!=ARRAY_ENDOFSCAN);
/*{{{ 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; }
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; }
METHODDEF DATATYPE * read_freiburg(transform_info_ptr tinfo) { struct read_freiburg_storage *local_arg=(struct read_freiburg_storage *)tinfo->methods->local_storage; transform_argument *args=tinfo->methods->arguments; struct freiburg_channels_struct *in_channels=local_arg->in_channels; array myarray; FILE *infile; int i, point, channel; int trial_not_accepted; long length_of_data; short header[FREIBURG_HEADER_LENGTH/sizeof(short)]; char const *last_sep=strrchr(args[ARGS_IFILE].arg.s, PATHSEP); char const *last_component=(last_sep==NULL ? args[ARGS_IFILE].arg.s : last_sep+1); char comment[MAX_COMMENTLEN]; tinfo->nrofaverages=1; if (args[ARGS_CONTINUOUS].is_set) { /*{{{ Read an epoch from a continuous file*/ infile=local_arg->infile; if (local_arg->epochs--==0) return NULL; /*{{{ Configure myarray*/ myarray.element_skip=tinfo->itemsize=1; myarray.nr_of_vectors=tinfo->nr_of_points=local_arg->epochlength; myarray.nr_of_elements=tinfo->nr_of_channels=local_arg->nr_of_channels; if (array_allocate(&myarray)==NULL) { ERREXIT(tinfo->emethods, "read_freiburg: Error allocating data\n"); } tinfo->multiplexed=TRUE; /*}}} */ do { do { if (local_arg->segment_table.buffer_start!=NULL && local_arg->current_point%SEGMENT_LENGTH==0) { int const segment=local_arg->current_point/SEGMENT_LENGTH; long const nr_of_segments=local_arg->segment_table.current_length/sizeof(long); if (segment>=nr_of_segments) { array_free(&myarray); return NULL; } fseek(infile, ((long *)local_arg->segment_table.buffer_start)[segment], SEEK_SET); local_arg->no_last_values=TRUE; } if (freiburg_get_segment(tinfo, &myarray)!=0) { array_free(&myarray); return NULL; } } while (myarray.message!=ARRAY_ENDOFSCAN); } while (--local_arg->fromepoch>0); snprintf(comment, MAX_COMMENTLEN, "%s %s %02d/%02d/%04d,%02d:%02d:%02d", (local_arg->continuous_type==SLEEP_BT_TYPE ? "sleep_BT" : "sleep_KL"), last_component, local_arg->btfile.start_month, local_arg->btfile.start_day, local_arg->btfile.start_year, local_arg->btfile.start_hour, local_arg->btfile.start_minute, local_arg->btfile.start_second); tinfo->sfreq=local_arg->sfreq; /*}}} */ } else /*{{{ Read an epoch from a single (epoched or averaged) file*/ do { /* Return here if trial was not accepted */ trial_not_accepted=FALSE; if (local_arg->epochs--==0 || (local_arg->average_mode && local_arg->current_trigger>=1)) return NULL; if (local_arg->average_mode) { /*{{{ Prepare reading an averaged file*/ if((infile=fopen(args[ARGS_IFILE].arg.s,"rb"))==NULL) { ERREXIT1(tinfo->emethods, "read_freiburg: Can't open file %s\n", MSGPARM(args[ARGS_IFILE].arg.s)); } fseek(infile, 0, SEEK_END); length_of_data=ftell(infile)-FREIBURG_HEADER_LENGTH; local_arg->current_trigger++; snprintf(comment, MAX_COMMENTLEN, "Freiburg-avg %s", last_component); /*}}} */ } else { /*{{{ Build pathname of the single trial to read*/ /* A directory name was given. */ char const * const expnumber=args[ARGS_IFILE].arg.s+strlen(args[ARGS_IFILE].arg.s)-2; #ifdef __GNUC__ #define NEWFILENAME_SIZE (strlen(args[ARGS_IFILE].arg.s)+strlen(last_component)+20) #else #define NEWFILENAME_SIZE MAX_PATHLEN #endif char newfilename[NEWFILENAME_SIZE]; do { /* Files from which only the parameter part exists are rejected */ int div100=local_arg->current_trigger/100, mod100=local_arg->current_trigger%100; snprintf(newfilename, NEWFILENAME_SIZE, "%s%c%s%02d%c%c%s%02d%02d", args[ARGS_IFILE].arg.s, PATHSEP, last_component, div100, PATHSEP, tolower(expnumber[-1]), expnumber, div100, mod100); TRACEMS1(tinfo->emethods, 1, "read_freiburg: Constructed filename %s\n", MSGPARM(newfilename)); if((infile=fopen(newfilename,"rb"))==NULL) { if (local_arg->current_trigger==0) { ERREXIT1(tinfo->emethods, "read_freiburg: Can't open file %s\n", MSGPARM(newfilename)); } else { return NULL; } } fseek(infile, 0, SEEK_END); length_of_data=ftell(infile)-FREIBURG_HEADER_LENGTH; local_arg->current_trigger++; } while (length_of_data==0 || --local_arg->fromepoch>0); snprintf(comment, MAX_COMMENTLEN, "Freiburg-raw %s", last_component); /*}}} */ } /*{{{ Read the 64-Byte header*/ fseek(infile, 0, SEEK_SET); fread(header, 1, FREIBURG_HEADER_LENGTH, infile); for (i=0; i<18; i++) { # ifdef LITTLE_ENDIAN Intel_int16((uint16_t *)&header[i]); # endif TRACEMS2(tinfo->emethods, 3, "read_freiburg: Header %02d: %d\n", MSGPARM(i), MSGPARM(header[i])); } /*}}} */ if (local_arg->average_mode) { if ((length_of_data/sizeof(short))%local_arg->nr_of_channels!=0) { ERREXIT2(tinfo->emethods, "read_freiburg: length_of_data=%d does not fit with nr_of_channels=%d\n", MSGPARM(length_of_data), MSGPARM(local_arg->nr_of_channels)); } tinfo->nr_of_points=(length_of_data/sizeof(short))/local_arg->nr_of_channels; local_arg->sfreq=(args[ARGS_SFREQ].is_set ? args[ARGS_SFREQ].arg.d : 200.0); /* The most likely value */ } else { local_arg->nr_of_channels=header[14]; /* Note: In a lot of experiments, one point MORE is available in the data * than specified in the header, but this occurs erratically. We could only * check for this during decompression, but that's probably too much fuss. */ tinfo->nr_of_points=header[16]/header[15]; local_arg->sfreq=(args[ARGS_SFREQ].is_set ? args[ARGS_SFREQ].arg.d : 1000.0/header[15]); } tinfo->sfreq=local_arg->sfreq; /*{{{ Parse arguments that can be in seconds*/ local_arg->offset=(args[ARGS_OFFSET].is_set ? gettimeslice(tinfo, args[ARGS_OFFSET].arg.s) : 0); /*}}} */ tinfo->beforetrig= -local_arg->offset; tinfo->aftertrig=tinfo->nr_of_points+local_arg->offset; /*{{{ Configure myarray*/ myarray.element_skip=tinfo->itemsize=1; myarray.nr_of_vectors=tinfo->nr_of_points; myarray.nr_of_elements=tinfo->nr_of_channels=local_arg->nr_of_channels; if (array_allocate(&myarray)==NULL) { ERREXIT(tinfo->emethods, "read_freiburg: Error allocating data\n"); } tinfo->multiplexed=TRUE; /*}}} */ fseek(infile, FREIBURG_HEADER_LENGTH, SEEK_SET); if (local_arg->average_mode) { /*{{{ Read averaged epoch*/ for (point=0; point<tinfo->nr_of_points; point++) { #ifdef __GNUC__ short buffer[tinfo->nr_of_channels]; #else short buffer[MAX_NR_OF_CHANNELS]; #endif if ((int)fread(buffer, sizeof(short), tinfo->nr_of_channels, infile)!=tinfo->nr_of_channels) { ERREXIT1(tinfo->emethods, "read_freiburg: Error reading data point %d\n", MSGPARM(point)); } for (channel=0; channel<tinfo->nr_of_channels; channel++) { # ifdef LITTLE_ENDIAN Intel_int16((uint16_t *)&buffer[channel]); # endif array_write(&myarray, (DATATYPE)buffer[channel]); } } /*}}} */ } else { /*{{{ Read compressed single trial*/ # ifdef DISPLAY_ADJECTIVES char *adjektiv_ende=strchr(((char *)header)+36, ' '); if (adjektiv_ende!=NULL) *adjektiv_ende='\0'; printf("Single trial: nr_of_points=%d, nr_of_channels=%d, Adjektiv=%s\n", tinfo->nr_of_points, tinfo->nr_of_channels, ((char *)header)+36); # endif local_arg->infile=infile; do { if (freiburg_get_segment(tinfo, &myarray)!=0) { TRACEMS1(tinfo->emethods, 0, "read_freiburg: Decompression out of bounds for trial %d - skipped\n", MSGPARM(local_arg->current_trigger-1)); array_free(&myarray); trial_not_accepted=TRUE; break; } } while (myarray.message!=ARRAY_ENDOFSCAN); /*}}} */ } fclose(infile); } while (trial_not_accepted); /*}}} */ /*{{{ Look for a Freiburg channel setup for this number of channels*/ /* Force create_channelgrid to really allocate the channel info anew. * Otherwise, free_tinfo will free someone else's data ! */ tinfo->channelnames=NULL; tinfo->probepos=NULL; if (local_arg->channelnames!=NULL) { copy_channelinfo(tinfo, local_arg->channelnames, NULL); } else { while (in_channels->nr_of_channels!=0 && in_channels->nr_of_channels!=tinfo->nr_of_channels) in_channels++; if (in_channels->nr_of_channels==0) { TRACEMS1(tinfo->emethods, 1, "read_freiburg: Don't have a setup for %d channels.\n", MSGPARM(tinfo->nr_of_channels)); } else { copy_channelinfo(tinfo, in_channels->channelnames, NULL); } } create_channelgrid(tinfo); /* Create defaults for any missing channel info */ /*}}} */ if ((tinfo->comment=(char *)malloc(strlen(comment)+1))==NULL) { ERREXIT(tinfo->emethods, "read_freiburg: Error allocating comment memory\n"); } strcpy(tinfo->comment, comment); if (local_arg->zero_idiotism_warned==FALSE && local_arg->zero_idiotism_encountered) { TRACEMS(tinfo->emethods, 0, "read_freiburg: All-zero data points have been encountered and omitted!\n"); local_arg->zero_idiotism_warned=TRUE; } tinfo->z_label=NULL; tinfo->tsdata=myarray.start; tinfo->length_of_output_region=tinfo->nr_of_channels*tinfo->nr_of_points; tinfo->leaveright=0; tinfo->data_type=TIME_DATA; return tinfo->tsdata; }
/*{{{ read_freiburg_init(transform_info_ptr tinfo) {*/ METHODDEF void read_freiburg_init(transform_info_ptr tinfo) { struct read_freiburg_storage *local_arg=(struct read_freiburg_storage *)tinfo->methods->local_storage; transform_argument *args=tinfo->methods->arguments; struct stat statbuf; /*{{{ Process options*/ local_arg->fromepoch=(args[ARGS_FROMEPOCH].is_set ? args[ARGS_FROMEPOCH].arg.i : 1); local_arg->epochs=(args[ARGS_EPOCHS].is_set ? args[ARGS_EPOCHS].arg.i : -1); /*}}} */ local_arg->channelnames=NULL; local_arg->uV_per_bit=NULL; growing_buf_init(&local_arg->segment_table); /* This sets buffer_start=NULL */ local_arg->nr_of_channels=0; if (args[ARGS_CONTINUOUS].is_set) { /*{{{ Open a continuous (sleep, Bernd Tritschler) file*/ FILE *infile; local_arg->in_channels= &sleep_channels[0]; if (stat(args[ARGS_IFILE].arg.s, &statbuf)!= 0 || !S_ISREG(statbuf.st_mode)) { /* File does not exist or isn't a regular file: Try BT format */ #ifdef __GNUC__ char co_name[strlen(args[ARGS_IFILE].arg.s)+4]; char coa_name[strlen(args[ARGS_IFILE].arg.s)+5]; #else char co_name[MAX_PATHLEN]; char coa_name[MAX_PATHLEN]; #endif char coa_buf[MAX_COALINE]; FILE *coafile; strcpy(co_name, args[ARGS_IFILE].arg.s); strcat(co_name, ".co"); if((infile=fopen(co_name,"rb"))==NULL) { ERREXIT1(tinfo->emethods, "read_freiburg_init: Can't open file %s\n", MSGPARM(co_name)); } local_arg->infile=infile; if (args[ARGS_REPAIR_OFFSET].is_set) { fseek(infile, args[ARGS_REPAIR_OFFSET].arg.i, SEEK_SET); } else { if (read_struct((char *)&local_arg->btfile, sm_BT_file, infile)==0) { ERREXIT1(tinfo->emethods, "read_freiburg_init: Header read error in file %s\n", MSGPARM(co_name)); } # ifndef LITTLE_ENDIAN change_byteorder((char *)&local_arg->btfile, sm_BT_file); # endif } strcpy(coa_name, args[ARGS_IFILE].arg.s); strcat(coa_name, ".coa"); if((coafile=fopen(coa_name,"rb"))==NULL) { TRACEMS1(tinfo->emethods, 0, "read_freiburg_init: No file %s found\n", MSGPARM(coa_name)); } else { while (!feof(coafile)) { Bool repeat; fgets(coa_buf, MAX_COALINE-1, coafile); do { repeat=FALSE; if (strncmp(coa_buf, "Channel_Table ", 14)==0) { int havechannels=0, stringlength=0; long tablepos=ftell(coafile); char *innames; while (!feof(coafile)) { char *eol; fgets(coa_buf, MAX_COALINE-1, coafile); if (!isdigit(*coa_buf)) break; if (strncmp(coa_buf, "0 0 ", 4)==0) { /* Empty channel descriptors: Don't generate channelnames */ } else { for (eol=coa_buf+strlen(coa_buf)-1; eol>=coa_buf && (*eol=='\n' || *eol=='\r'); eol--) *eol='\0'; /* This includes 1 for the zero at the end: */ stringlength+=strlen(strrchr(coa_buf, ' ')); } havechannels++; } if (havechannels==0) continue; /* Channel table is unuseable */ local_arg->nr_of_channels=havechannels; innames=NULL; if ((stringlength!=0 && ((local_arg->channelnames=(char **)malloc(havechannels*sizeof(char *)))==NULL || (innames=(char *)malloc(stringlength))==NULL)) || (local_arg->uV_per_bit=(float *)malloc(havechannels*sizeof(float)))==NULL) { ERREXIT(tinfo->emethods, "read_freiburg_init: Error allocating .coa memory\n"); } fseek(coafile, tablepos, SEEK_SET); havechannels=0; while (!feof(coafile)) { char *eol; fgets(coa_buf, MAX_COALINE-1, coafile); if (!isdigit(*coa_buf)) break; for (eol=coa_buf+strlen(coa_buf)-1; eol>=coa_buf && (*eol=='\n' || *eol=='\r'); eol--) *eol='\0'; if (innames!=NULL) { strcpy(innames, strrchr(coa_buf, ' ')+1); local_arg->channelnames[havechannels]=innames; innames+=strlen(innames)+1; } /* The sensitivity in .coa files is given as nV/Bit */ local_arg->uV_per_bit[havechannels]=atoi(strchr(coa_buf, ' ')+1)/1000.0; if (local_arg->uV_per_bit[havechannels]==0.0) { local_arg->uV_per_bit[havechannels]=0.086; TRACEMS1(tinfo->emethods, 1, "read_freiburg_init: Sensitivity for channel %d set to 86 nV/Bit\n", MSGPARM(havechannels)); } havechannels++; } repeat=TRUE; } else if (strncmp(coa_buf, SEGMENT_TABLE_STRING, strlen(SEGMENT_TABLE_STRING))==0) { long current_offset=0; char *inbuf=coa_buf; Bool havesomething=FALSE; growing_buf_allocate(&local_arg->segment_table, 0); while (!feof(coafile)) { int const nextchar=fgetc(coafile); if (nextchar=='\r' || nextchar=='\n' || nextchar==' ') { if (havesomething) { *inbuf = '\0'; current_offset+=atoi(coa_buf); growing_buf_append(&local_arg->segment_table, (char *)¤t_offset, sizeof(long)); inbuf=coa_buf; havesomething=FALSE; } if (nextchar=='\n') break; } else { *inbuf++ = nextchar; havesomething=TRUE; } } repeat=FALSE; } } while (repeat); } fclose(coafile); if (local_arg->uV_per_bit==NULL) { TRACEMS1(tinfo->emethods, 0, "read_freiburg_init: No channel table found in file %s\n", MSGPARM(coa_name)); } if (local_arg->segment_table.buffer_start==NULL) { TRACEMS1(tinfo->emethods, 0, "read_freiburg_init: No segment table found in file %s\n", MSGPARM(coa_name)); } /* Determine the exact number of points in file: Start with the previous * segment and add the last segment. */ fstat(fileno(infile),&statbuf); //printf("File size is %ld\n", statbuf.st_size); //printf("Last segment (EOF) at %ld\n", ((long *)local_arg->segment_table.buffer_start)[local_arg->segment_table.current_length/sizeof(long)-1]); while (local_arg->segment_table.current_length>=1 && ((long *)local_arg->segment_table.buffer_start)[local_arg->segment_table.current_length/sizeof(long)-1]>=statbuf.st_size) { //printf("%ld - Removing last segment!\n", ((long *)local_arg->segment_table.buffer_start)[local_arg->segment_table.current_length/sizeof(long)-1]); local_arg->segment_table.current_length--; } /* Size without the last segment */ tinfo->points_in_file=(local_arg->segment_table.current_length/sizeof(long)-1)*SEGMENT_LENGTH; /* Count the points in the last segment */ { array myarray; int length_of_last_segment=0; myarray.element_skip=tinfo->itemsize=1; myarray.nr_of_vectors=1; myarray.nr_of_elements=local_arg->nr_of_channels; if (array_allocate(&myarray)==NULL) { ERREXIT(tinfo->emethods, "read_freiburg_init: Error allocating myarray\n"); } fseek(infile, ((long *)local_arg->segment_table.buffer_start)[local_arg->segment_table.current_length/sizeof(long)-1], SEEK_SET); //printf("Seeking to %ld\n", ((long *)local_arg->segment_table.buffer_start)[local_arg->segment_table.current_length/sizeof(long)-1]); tinfo->nr_of_channels=local_arg->nr_of_channels; /* This is used by freiburg_get_segment_init! */ freiburg_get_segment_init(tinfo); while (freiburg_get_segment(tinfo, &myarray)==0) length_of_last_segment++; freiburg_get_segment_free(tinfo); tinfo->points_in_file+=length_of_last_segment; TRACEMS1(tinfo->emethods, 1, "read_freiburg_init: Last segment has %ld points\n",length_of_last_segment); array_free(&myarray); } } if (local_arg->channelnames==NULL && local_arg->btfile.text[0]=='\0') { local_arg->in_channels= &goeppi_channels[0]; TRACEMS(tinfo->emethods, 0, "read_freiburg_init: Assuming Goeppingen style setup!\n"); } local_arg->continuous_type=SLEEP_BT_TYPE; TRACEMS(tinfo->emethods, 1, "read_freiburg_init: Opened file in BT format\n"); } else { if((infile=fopen(args[ARGS_IFILE].arg.s,"rb"))==NULL) { ERREXIT1(tinfo->emethods, "read_freiburg_init: Can't open file %s\n", MSGPARM(args[ARGS_IFILE].arg.s)); } if (args[ARGS_REPAIR_OFFSET].is_set) { fseek(infile, args[ARGS_REPAIR_OFFSET].arg.i, SEEK_SET); } else { if (read_struct((char *)&local_arg->btfile, sm_BT_file, infile)==0) { ERREXIT1(tinfo->emethods, "read_freiburg_init: Header read error in file %s\n", MSGPARM(args[ARGS_IFILE].arg.s)); } # ifdef LITTLE_ENDIAN change_byteorder((char *)&local_arg->btfile, sm_BT_file); # endif } local_arg->continuous_type=SLEEP_KL_TYPE; /* Year and day are swapped in KL format with respect to BT format... */ {short buf=local_arg->btfile.start_year; local_arg->btfile.start_year=local_arg->btfile.start_day; local_arg->btfile.start_day=buf;} /* Well, sometimes or most of the time, in KL files the sampling interval * was not set correctly... */ if (!args[ARGS_SFREQ].is_set && local_arg->btfile.sampling_interval_us!=9765 && local_arg->btfile.sampling_interval_us!=9766) { TRACEMS1(tinfo->emethods, 0, "read_freiburg_init: sampling_interval_us was %d, corrected!\n", MSGPARM(local_arg->btfile.sampling_interval_us)); local_arg->btfile.sampling_interval_us=9766; } TRACEMS(tinfo->emethods, 1, "read_freiburg_init: Opened file in KL format\n"); } if (args[ARGS_REPAIR_CHANNELS].is_set) local_arg->btfile.nr_of_channels=args[ARGS_REPAIR_CHANNELS].arg.i; tinfo->nr_of_channels=local_arg->btfile.nr_of_channels; if (tinfo->nr_of_channels<=0 || tinfo->nr_of_channels>MAX_NUMBER_OF_CHANNELS_IN_EP) { ERREXIT1(tinfo->emethods, "read_freiburg_init: Impossible: %d channels?\n", MSGPARM(tinfo->nr_of_channels)); } if (local_arg->nr_of_channels==0) { local_arg->nr_of_channels=tinfo->nr_of_channels; } else { if (local_arg->nr_of_channels!=tinfo->nr_of_channels) { ERREXIT2(tinfo->emethods, "read_freiburg_init: Setup has %d channels, but the file has %d!\n", MSGPARM(local_arg->nr_of_channels), MSGPARM(tinfo->nr_of_channels)); } } local_arg->sfreq=(args[ARGS_SFREQ].is_set ? args[ARGS_SFREQ].arg.d : 1.0e6/local_arg->btfile.sampling_interval_us); tinfo->sfreq=local_arg->sfreq; if (tinfo->sfreq<=0.0 || tinfo->sfreq>MAX_POSSIBLE_SFREQ) { ERREXIT1(tinfo->emethods, "read_freiburg_init: Impossible: sfreq=%gHz?\n", MSGPARM(tinfo->sfreq)); } /*{{{ Parse arguments that can be in seconds*/ tinfo->nr_of_points=gettimeslice(tinfo, args[ARGS_NCHANNELS].arg.s); if (tinfo->nr_of_points<=0) { /* Read the whole file as one epoch */ TRACEMS1(tinfo->emethods, 1, "read_freiburg_init: Reading %ld points\n",tinfo->points_in_file); tinfo->nr_of_points=tinfo->points_in_file; } local_arg->offset=(args[ARGS_OFFSET].is_set ? gettimeslice(tinfo, args[ARGS_OFFSET].arg.s) : 0); local_arg->epochlength=tinfo->nr_of_points; /*}}} */ tinfo->beforetrig= -local_arg->offset; tinfo->aftertrig=tinfo->nr_of_points+local_arg->offset; /*}}} */ } else { local_arg->in_channels= &freiburg_channels[0]; local_arg->current_trigger=0; if (stat(args[ARGS_IFILE].arg.s, &statbuf)!=0) { ERREXIT1(tinfo->emethods, "read_freiburg_init: Can't stat file %s\n", MSGPARM(args[ARGS_IFILE].arg.s)); } local_arg->nr_of_channels=atoi(args[ARGS_NCHANNELS].arg.s); /* average mode if the name does not belong to a directory */ local_arg->average_mode= !S_ISDIR(statbuf.st_mode); tinfo->nr_of_channels=MAX_NUMBER_OF_CHANNELS_IN_EP; } freiburg_get_segment_init(tinfo); local_arg->current_point=0; tinfo->methods->init_done=TRUE; }
#else #define __likely(x) x #define __unlikely(x) x #endif #include <sys/types.h> #include <stdlib.h> #include "safemult.h" #include "array.h" #include "byte.h" #if 0 static array x; t *p; int64 pos; p = array_allocate(&x,sizeof(t),pos); array_allocate makes sure that enough bytes are allocated in x for at least pos+1 objects of type t. (The size of t must be positive; otherwise the effects are undefined.) If not enough bytes are allocated (or x is unallocated), array_allocate allocates more bytes, moving the dynamically allocated region if necessary. array_allocate often allocates somewhat more bytes than necessary, to save time later. array_allocate then makes sure that the number of bytes initialized covers at least those pos+1 objects. If not enough bytes are initialized, array_allocate initializes more bytes (setting them to 0), up to exactly the end of the pos+1st object. array_allocate then returns a pointer to the pos+1st object; i.e.,
/*{{{ 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; }
/*{{{ 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; }
int64 io_waituntil2(int64 milliseconds) { #ifndef __MINGW32__ struct pollfd* p; #endif long i,j,r; if (!io_wanted_fds) return 0; #ifdef HAVE_EPOLL if (io_waitmode==EPOLL) { int n; struct epoll_event y[50]; if ((n=epoll_wait(io_master,y,50,milliseconds))==-1) return -1; int first_new = -1; int last_new = -1; for (i=n-1; i>=0; --i) { io_entry* e=array_get(&io_fds,sizeof(io_entry),y[i].data.fd); if (e) { if (y[i].events&(EPOLLERR|EPOLLHUP)) { /* error; signal whatever app is looking for */ if (e->wantread) y[i].events|=EPOLLIN; if (e->wantwrite) y[i].events|=EPOLLOUT; } #ifdef EPOLLRDNORM if (y[i].data.fd == io_master && !e->canread && (y[i].events&(EPOLLIN|EPOLLPRI|EPOLLRDNORM|EPOLLRDBAND))) { #else if (y[i].data.fd == io_master && !e->canread && (y[i].events&(EPOLLIN|EPOLLPRI))) { #endif e->canread=1; e->next_read=first_new; if(first_new == -1) last_new = y[i].data.fd; first_new=y[i].data.fd; } } } //if(n > 1) printf("n: %d\n", n); for (i=n-1; i>=0; --i) { //for (i=0; i < n; i++) { io_entry* e=array_get(&io_fds,sizeof(io_entry),y[i].data.fd); if (e) { #ifdef EPOLLRDNORM if (!e->canread && (y[i].events&(EPOLLIN|EPOLLPRI|EPOLLRDNORM|EPOLLRDBAND))) { #else if (!e->canread && (y[i].events&(EPOLLIN|EPOLLPRI))) { #endif e->canread=1; e->next_read=first_readable; first_readable=y[i].data.fd; } if (!e->canwrite && (y[i].events&EPOLLOUT)) { e->canwrite=-1; e->next_write=first_writeable; first_writeable=y[i].data.fd; } } else { epoll_ctl(io_master,EPOLL_CTL_DEL,y[i].data.fd,y+i); } } // if there are new connections, put them first... if(last_new != -1) { if(first_readable != -1) { io_entry* e=array_get(&io_fds,sizeof(io_entry),last_new); e->next_read=first_readable; } first_readable = first_new; } return n; } #endif #ifdef HAVE_KQUEUE if (io_waitmode==KQUEUE) { struct kevent y[100]; int n; struct timespec ts; ts.tv_sec=milliseconds/1000; ts.tv_nsec=(milliseconds%1000)*1000000; if ((n=kevent(io_master,0,0,y,100,milliseconds!=-1?&ts:0))==-1) return -1; for (i=n-1; i>=0; --i) { io_entry* e=array_get(&io_fds,sizeof(io_entry),y[--n].ident); #ifdef DEBUG if (!e) { e=e; } #endif if (e) { if (y[n].flags&EV_ERROR) { /* error; signal whatever app is looking for */ if (e->wantread) y[n].filter=EVFILT_READ; else if (e->wantwrite) y[n].filter=EVFILT_WRITE; } if (!e->canread && (y[n].filter==EVFILT_READ)) { e->canread=1; e->next_read=first_readable; first_readable=y[n].ident; } if (!e->canwrite && (y[n].filter==EVFILT_WRITE)) { e->canwrite=1; e->next_write=first_writeable; first_writeable=y[i].ident; } #ifdef DEBUG } else { fprintf(stderr,"got kevent on fd#%d, which is not in array!\n",y[n].ident); #endif } } return n; } #endif #ifdef HAVE_DEVPOLL if (io_waitmode==DEVPOLL) { dvpoll_t timeout; struct pollfd y[100]; int n; timeout.dp_timeout=milliseconds; timeout.dp_nfds=100; timeout.dp_fds=y; if ((n=ioctl(io_master,DP_POLL,&timeout))==-1) return -1; for (i=n-1; i>=0; --i) { io_entry* e=array_get(&io_fds,sizeof(io_entry),y[--n].fd); if (e) { if (y[n].revents&(POLLERR|POLLHUP|POLLNVAL)) { /* error; signal whatever app is looking for */ if (e->wantread) y[n].revents=POLLIN; if (e->wantwrite) y[n].revents=POLLOUT; } if (!e->canread && (y[n].revents&POLLIN)) { e->canread=1; if (e->next_read==-1) { e->next_read=first_readable; first_readable=y[n].fd; } } if (!e->canwrite && (y[n].revents&POLLOUT)) { e->canwrite=1; if (e->next_write==-1) { e->next_write=first_writeable; first_writeable=y[i].fd; } } #ifdef DEBUG } else { fprintf(stderr,"got kevent on fd#%d, which is not in array!\n",y[n].fd); #endif } } return n; } #endif #ifdef HAVE_SIGIO if (io_waitmode==_SIGIO) { siginfo_t info; struct timespec ts; int r; io_entry* e; if (alt_firstread>=0 && (e=array_get(&io_fds,sizeof(io_entry),alt_firstread)) && e->canread) return 1; if (alt_firstwrite>=0 && (e=array_get(&io_fds,sizeof(io_entry),alt_firstwrite)) && e->canwrite) return 1; if (milliseconds==-1) r=sigwaitinfo(&io_ss,&info); else { ts.tv_sec=milliseconds/1000; ts.tv_nsec=(milliseconds%1000)*1000000; r=sigtimedwait(&io_ss,&info,&ts); } switch (r) { case SIGIO: /* signal queue overflow */ signal(io_signum,SIG_DFL); goto dopoll; default: if (r==io_signum) { io_entry* e=array_get(&io_fds,sizeof(io_entry),info.si_fd); if (e) { if (info.si_band&(POLLERR|POLLHUP)) { /* error; signal whatever app is looking for */ if (e->wantread) info.si_band|=POLLIN; if (e->wantwrite) info.si_band|=POLLOUT; } if (info.si_band&POLLIN && !e->canread) { debug_printf(("io_waituntil2: enqueueing %ld in normal read queue before %ld\n",info.si_fd,first_readable)); e->canread=1; e->next_read=first_readable; first_readable=info.si_fd; } if (info.si_band&POLLOUT && !e->canwrite) { debug_printf(("io_waituntil2: enqueueing %ld in normal write queue before %ld\n",info.si_fd,first_writeable)); e->canwrite=1; e->next_write=first_writeable; first_writeable=info.si_fd; } #ifdef DEBUG } else { fprintf(stderr,"got kevent on fd#%d, which is not in array!\n",info.si_fd); #endif } } } return 1; } dopoll: #endif #ifdef __MINGW32__ DWORD numberofbytes; ULONG_PTR x; LPOVERLAPPED o; if (first_readable!=-1 || first_writeable!=-1) { fprintf(stderr,"io_waituntil2() returning immediately because first_readable(%p) or first_writeable(%p) are set\n",first_readable,first_writeable); return; } fprintf(stderr,"Calling GetQueuedCompletionStatus %p...",io_comport); if (GetQueuedCompletionStatus(io_comport,&numberofbytes,&x,&o,milliseconds==-1?milliseconds:INFINITE)) { io_entry* e=array_get(&io_fds,sizeof(io_entry),x); fprintf(stderr," OK. Got %x, e=%p\n",x,e); if (!e) return 0; e->errorcode=0; fprintf(stderr,"o=%p, e->or=%p, e->ow=%p, e->os=%p\n",o,&e->or,&e->ow,&e->os); fprintf(stderr,"e->readqueued=%d, e->writequeued=%d, e->acceptqueued=%d, e->connectqueued=%d, e->sendfilequeued=%d\n", e->readqueued,e->writequeued,e->acceptqueued,e->connectqueued,e->sendfilequeued); if (o==&e->or && e->readqueued==1) { e->readqueued=2; e->canread=1; e->bytes_read=numberofbytes; e->next_read=first_readable; first_readable=x; // printf("read %lu bytes on fd %lu: %p\n",numberofbytes,x,e); } else if (o==&e->ow && e->writequeued==1) { e->writequeued=2; e->canwrite=1; e->bytes_written=numberofbytes; e->next_write=first_writeable; first_writeable=x; } else if (o==&e->or && e->acceptqueued==1) { e->acceptqueued=2; e->canread=1; e->next_read=first_readable; first_readable=x; } else if (o==&e->ow && e->connectqueued==1) { e->connectqueued=2; e->canwrite=1; e->next_write=first_writeable; first_writeable=x; } else if (o==&e->os && e->sendfilequeued==1) { e->sendfilequeued=2; e->canwrite=1; e->bytes_written=numberofbytes; e->next_write=first_writeable; first_writeable=x; } return 1; } else { /* either the overlapped I/O request failed or we timed out */ DWORD err; io_entry* e; fprintf(stderr," failure, o=%p.\n",o); if (!o) return 0; /* timeout */ /* we got a completion packet for a failed I/O operation */ err=GetLastError(); if (err==WAIT_TIMEOUT) return 0; /* or maybe not */ e=array_get(&io_fds,sizeof(io_entry),x); if (!e) return 0; /* WTF?! */ e->errorcode=err; if (o==&e->or && (e->readqueued || e->acceptqueued)) { if (e->readqueued) e->readqueued=2; else if (e->acceptqueued) e->acceptqueued=2; e->canread=1; e->bytes_read=-1; e->next_read=first_readable; first_readable=x; } else if ((o==&e->ow || o==&e->os) && (e->writequeued || e->connectqueued || e->sendfilequeued)) { if (o==&e->ow) { if (e->writequeued) e->writequeued=2; else if (e->connectqueued) e->connectqueued=2; } else if (o==&e->os) e->sendfilequeued=2; e->canwrite=1; e->bytes_written=-1; e->next_write=first_writeable; first_writeable=x; } return 1; } #else for (i=r=0; i<array_length(&io_fds,sizeof(io_entry)); ++i) { io_entry* e=array_get(&io_fds,sizeof(io_entry),i); if (!e) return -1; e->canread=e->canwrite=0; if (e->wantread || e->wantwrite) { struct pollfd* p; if ((p=array_allocate(&io_pollfds,sizeof(struct pollfd),r))) { p->fd=i; p->events=(e->wantread?POLLIN:0) + (e->wantwrite?POLLOUT:0); ++r; } else return -1; } } p=array_start(&io_pollfds); if ((i=poll(array_start(&io_pollfds),r,milliseconds))<1) return -1; for (j=r-1; j>=0; --j) { io_entry* e=array_get(&io_fds,sizeof(io_entry),p->fd); if (p->revents&(POLLERR|POLLHUP|POLLNVAL)) { /* error; signal whatever app is looking for */ if (e->wantread) p->revents|=POLLIN; if (e->wantwrite) p->revents|=POLLOUT; } if (!e->canread && (p->revents&POLLIN)) { e->canread=1; e->next_read=first_readable; first_readable=p->fd; } if (!e->canwrite && (p->revents&POLLOUT)) { e->canwrite=1; e->next_write=first_writeable; first_writeable=p->fd; } p++; } return i; #endif }