Exemplo n.º 1
0
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;
}
Exemplo n.º 2
0
GLOBAL DATATYPE
array_sum(array *thisarray) {
 DATATYPE sum=0.0;

 do {
  sum+=array_scan(thisarray);
 } while (thisarray->message==ARRAY_CONTINUE);

 return sum;
}
Exemplo n.º 3
0
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]);
    }
}
Exemplo n.º 4
0
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);
}
Exemplo n.º 5
0
/*{{{  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' */
}
Exemplo n.º 6
0
/*{{{  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' */
}
Exemplo n.º 7
0
/*{{{  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 {
Exemplo n.º 8
0
/*{{{  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;
}
Exemplo n.º 9
0
/*{{{  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;
}
Exemplo n.º 10
0
/*{{{  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' */
}
Exemplo n.º 11
0
/*{{{  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' */
}
Exemplo n.º 12
0
GLOBAL void
array_copy(array *array1, array *array2) {
 do {
  array_write(array2, array_scan(array1));
 } while (array1->message!=ARRAY_ENDOFSCAN && array2->message!=ARRAY_ENDOFSCAN);
}
Exemplo n.º 13
0
/*{{{  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;
}
Exemplo n.º 14
0
/*{{{  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);
}
Exemplo n.º 15
0
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;
}
Exemplo n.º 16
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;
}
Exemplo n.º 17
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;
}
Exemplo n.º 18
0
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);
}
Exemplo n.º 19
0
/*{{{  project_init(transform_info_ptr tinfo)*/
METHODDEF void
project_init(transform_info_ptr tinfo) {
 struct project_args_struct *project_args=(struct project_args_struct *)tinfo->methods->local_storage;
 transform_argument *args=tinfo->methods->arguments;
 transform_info_ptr side_tinfo= &project_args->side_tinfo;
 array *vectors= &project_args->vectors;
 growing_buf buf;
#define BUFFER_SIZE 80
 char buffer[BUFFER_SIZE];

 side_tinfo->methods= &project_args->methods;
 side_tinfo->emethods=tinfo->emethods;
 select_readasc(side_tinfo);
 growing_buf_init(&buf);
 growing_buf_allocate(&buf, 0);
 if (args[ARGS_FROMEPOCH].is_set) {
  snprintf(buffer, BUFFER_SIZE, "-f %ld ", args[ARGS_FROMEPOCH].arg.i);
  growing_buf_appendstring(&buf, buffer);
 }
 if (args[ARGS_EPOCHS].is_set) {
  project_args->epochs=args[ARGS_EPOCHS].arg.i;
  if (project_args->epochs<=0) {
   ERREXIT(tinfo->emethods, "project_init: The number of epochs must be positive.\n");
  }
 } else {
  project_args->epochs=1;
 }
 snprintf(buffer, BUFFER_SIZE, "-e %d ", project_args->epochs);
 growing_buf_appendstring(&buf, buffer);
 growing_buf_appendstring(&buf, args[ARGS_PROJECTFILE].arg.s);
 if (!buf.can_be_freed || !setup_method(side_tinfo, &buf)) {
  ERREXIT(tinfo->emethods, "project_init: Error setting readasc arguments.\n");
 }

 project_args->points=(args[ARGS_POINTS].is_set ? args[ARGS_POINTS].arg.i : 1);
 project_args->nr_of_item=(args[ARGS_NROFITEM].is_set ? args[ARGS_NROFITEM].arg.i : 0);
 project_args->orthogonalize_vectors_first=args[ARGS_ORTHOGONALIZE].is_set;
 if (args[ARGS_SUBSPACE].is_set) {
  project_args->project_mode=PROJECT_MODE_SSP;
 } else if (args[ARGS_SUBTRACT_SUBSPACE].is_set) {
  project_args->project_mode=PROJECT_MODE_SSPS;
 } else if (args[ARGS_MULTIPLY].is_set) {
  project_args->project_mode=PROJECT_MODE_MULTIPLY;
 } else {
  project_args->project_mode=PROJECT_MODE_SCALAR;
 }
 if (args[ARGS_CHANNELNAMES].is_set) {
  project_args->channel_list=expand_channel_list(tinfo, args[ARGS_CHANNELNAMES].arg.s);
  if (project_args->channel_list==NULL) {
   ERREXIT(tinfo->emethods, "project_init: Zero channels were selected by -N!\n");
  }
 } else {
  project_args->channel_list=NULL;
 }

 (*side_tinfo->methods->transform_init)(side_tinfo);

 /*{{{  Read first project_file epoch and allocate vectors array accordingly*/
 if ((side_tinfo->tsdata=(*side_tinfo->methods->transform)(side_tinfo))==NULL) {
  ERREXIT(tinfo->emethods, "project_init: Can't get the first project epoch.\n");
 }
 if (project_args->project_mode==PROJECT_MODE_MULTIPLY) {
  /* Save channel names and positions for later */
  project_args->save_side_tinfo.nr_of_channels=side_tinfo->nr_of_channels;
  copy_channelinfo(&project_args->save_side_tinfo, side_tinfo->channelnames, side_tinfo->probepos);
 }
 if (project_args->points==0) project_args->points=side_tinfo->nr_of_points;
 if (project_args->points>side_tinfo->nr_of_points) {
  ERREXIT1(tinfo->emethods, "project_init: There are only %d points in the project_file epoch.\n", MSGPARM(side_tinfo->nr_of_points));
 }
 if (args[ARGS_AT_XVALUE].is_set) {
  project_args->nr_of_point=find_pointnearx(side_tinfo, (DATATYPE)atof(args[ARGS_NROFPOINT].arg.s));
 } else {
 project_args->nr_of_point=gettimeslice(side_tinfo, args[ARGS_NROFPOINT].arg.s);
 }
 vectors->nr_of_vectors=project_args->epochs*project_args->points;
 vectors->nr_of_elements=side_tinfo->nr_of_channels;
 vectors->element_skip=1;
 if (array_allocate(vectors)==NULL) {
  ERREXIT(tinfo->emethods, "project_init: Error allocating vectors memory\n");
 }
 /*}}}  */

 do {
  /*{{{  Copy [points] vectors from project_file to vectors array*/
  array indata;
  int point;

  if (vectors->nr_of_elements!=side_tinfo->nr_of_channels) {
   ERREXIT(side_tinfo->emethods, "project_init: Varying channel numbers in project file!\n");
  }
  if (project_args->nr_of_point>=side_tinfo->nr_of_points) {
   ERREXIT2(side_tinfo->emethods, "project_init: nr_of_point=%d, nr_of_points=%d\n", MSGPARM(project_args->nr_of_point), MSGPARM(side_tinfo->nr_of_points));
  }
  if (project_args->nr_of_item>=side_tinfo->itemsize) {
   ERREXIT2(side_tinfo->emethods, "project_init: nr_of_item=%d, itemsize=%d\n", MSGPARM(project_args->nr_of_item), MSGPARM(side_tinfo->itemsize));
  }

  for (point=0; point<project_args->points; point++) {
   tinfo_array(side_tinfo, &indata);
   array_transpose(&indata);	/* Vector = map */
   if (vectors->nr_of_elements!=indata.nr_of_elements) {
    ERREXIT(side_tinfo->emethods, "project_init: vector size doesn't match\n");
   }
   indata.current_vector=project_args->nr_of_point+point;
   array_setto_vector(&indata);
   array_use_item(&indata, project_args->nr_of_item);
   array_copy(&indata, vectors);
  }
  /*}}}  */
  free_tinfo(side_tinfo);
 } while ((side_tinfo->tsdata=(*side_tinfo->methods->transform)(side_tinfo))!=NULL);

 if (vectors->message!=ARRAY_ENDOFSCAN) {
  ERREXIT1(tinfo->emethods, "project_init: Less than %d epochs in project file\n", MSGPARM(vectors->nr_of_vectors));
 }
 
 /*{{{  Set unused channels to zero if requested*/
 if (args[ARGS_ZERO_UNUSEDCOEFFICIENTS].is_set) {
  if (project_args->channel_list!=NULL) {
   do {
    do {
     if (is_in_channellist(vectors->current_element+1, project_args->channel_list)) {
      array_advance(vectors);
     } else {
      array_write(vectors, 0.0);
     }
    } while (vectors->message==ARRAY_CONTINUE);
   } while (vectors->message!=ARRAY_ENDOFSCAN);
  } else {
   ERREXIT(tinfo->emethods, "project_init: Option -z only makes sense in combination with -N!\n");
  }
 }
 /*}}}  */
 /*{{{  De-mean vectors if requested*/
 if (args[ARGS_CORRELATION].is_set) {
  do {
   DATATYPE mean=0.0;
   int nrofaverages=0;
   do {
    if (project_args->channel_list!=NULL && !is_in_channellist(vectors->current_element+1, project_args->channel_list)) {
     array_advance(vectors);
    } else {
     mean+=array_scan(vectors);
     nrofaverages++;
    }
   } while (vectors->message==ARRAY_CONTINUE);
   mean/=nrofaverages;
   array_previousvector(vectors);
   do {
    array_write(vectors, READ_ELEMENT(vectors)-mean);
   } while (vectors->message==ARRAY_CONTINUE);
  } while (vectors->message!=ARRAY_ENDOFSCAN);
 }
 /*}}}  */
 /*{{{  Orthogonalize vectors if requested*/
 if (project_args->orthogonalize_vectors_first) {
  array_make_orthogonal(vectors);
  if (vectors->message==ARRAY_ERROR) {
   ERREXIT(tinfo->emethods, "project_init: Error orthogonalizing projection vectors\n");
  }
 }
 /*}}}  */
 if (!args[ARGS_NONORMALIZATION].is_set) {
 /*{{{  Normalize vectors*/
 do {
  DATATYPE length=0.0;
  do {
   if (project_args->channel_list!=NULL && !is_in_channellist(vectors->current_element+1, project_args->channel_list)) {
    array_advance(vectors);
   } else {
    const DATATYPE hold=array_scan(vectors);
    length+=hold*hold;
   }
  } while (vectors->message==ARRAY_CONTINUE);
  length=sqrt(length);

  array_previousvector(vectors);
  if (length==0.0) {
   ERREXIT1(tinfo->emethods, "project_init: Vector %d has zero length !\n", MSGPARM(vectors->current_vector));
  }
  array_scale(vectors, 1.0/length);
 } while (vectors->message!=ARRAY_ENDOFSCAN);
 /*}}}  */
 }
 /*{{{  Dump vectors if requested*/
 if (args[ARGS_DUMPVECTORS].is_set) {
  FILE * const fp=fopen(args[ARGS_DUMPVECTORS].arg.s, "w");
  if (fp==NULL) {
   ERREXIT1(tinfo->emethods, "project_init: Error opening output file >%s<.\n", MSGPARM(args[ARGS_DUMPVECTORS].arg.s));
  }
  array_transpose(vectors); /* We want one vector to be one column */ 
  array_dump(fp, vectors, ARRAY_MATLAB);
  array_transpose(vectors);
  fclose(fp);
 }
 /*}}}  */

 (*side_tinfo->methods->transform_exit)(side_tinfo);
 free_methodmem(side_tinfo);
 growing_buf_free(&buf);

 tinfo->methods->init_done=TRUE;
}
Exemplo n.º 20
0
/*{{{  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;
}
Exemplo n.º 21
0
Arquivo: trim.c Projeto: berndf/avg_q
/*{{{  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;
}
Exemplo n.º 22
0
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);
}