Exemple #1
0
/* Convert a string to a JSON quoted string.  Note that newlines and other
control characters that cannot appear in JSON strings are converted to
spaces.  IMPORTANT:  the caller must free the string after use to avoid
memory leaks! */
char *strjson(char *s)
{
    char *js;
    int i, imax, j, q;

    /* Get the length of the input string and count the characters that must
       be escaped in it. */
    for (i = q = 0; s[i]; i++) {
	if (s[i] == '"' || s[i] == '\\') q++;
	else if (s[i] < ' ') s[i] = ' ';
    }    
    imax = i;

    /* Allocate memory for the output string. */
    SUALLOC(js, i+q+3, sizeof(char));

    /* Wrap the input string with '"' characters and escape any '"' characters
       embedded within it. */
    js[0] = '"';
    for (i = 0, j = 1; i < imax; i++, j++) {
	if (s[i] == '"' || s[i] == '\\') js[j++] = '\\';
	js[j] = s[i];
    }
    js[j++] = '"';
    js[j] = '\0';
    return (js);
}
Exemple #2
0
/* Expand command substitutions in VAR; needed if libcurl is included
   in LDFLAGS, so that we invoke the curl-config program rather than
   simply printing "`curl-config --libs`". */
static void expand_var(const char *var)
{
    char *buffer;
    SUALLOC(buffer, strlen(var) + 6, 1);
    sprintf(buffer, "echo %s", var);
    system(buffer);
    SFREE(buffer);
}
Exemple #3
0
void prep_signals()
{
    int n;

    SUALLOC(recpath, strlen(db) + strlen(record) + 2, sizeof(char));
    sprintf(recpath, "%s/%s", db, record);

    /* Discover the number of signals defined in the header, allocate
       memory for their signal information structures, open the signals. */
    if ((nsig = isigopen(recpath, NULL, 0)) > 0) {
	SUALLOC(s, nsig, sizeof(WFDB_Siginfo));
	nsig = isigopen(recpath, s, nsig);
    } 
    else {
	tfreq = ffreq = sampfreq(NULL);
	return;
    }

    /* Shorten signal names of the form "record xxx, signal N" to "v[N]" */
    for (n = 0; n < nsig; n++) {
	if (strncmp(s[n].desc, "record ", 7) == 0)
	    sprintf(s[n].desc, "v[%d]", n);
    }

    /* Make reasonably sure that signal names are distinct (see below). */
    force_unique_signames();

    /* Find the least common multiple of the sampling frequencies (which may not
       be exactly expressible as floating-point numbers).  In WFDB-compatible
       records, all signals are sampled at the same frequency or at a multiple
       of the frame frequency, but (especially in EDF records) there may be many
       samples of each signal in each frame.  The for loop below sets the "tick"
       frequency, tfreq, to the number of instants in each second when at least
       one sample is acquired. */
    setgvmode(WFDB_LOWRES);
    ffreq = sampfreq(NULL);
    if (ffreq <= 0.) ffreq = WFDB_DEFFREQ;
    for (n = 0, tfreq = ffreq; n < nsig; n++)
	tfreq = approx_LCM(ffreq * s[n].spf, tfreq);
}   
Exemple #4
0
void map_signals()
{
    char *p;
    int n;

    SUALLOC(sigmap, nsig, sizeof(int));
    for (n = 0; n < nsig; n++)
	sigmap[n] = -1;
    while (p = get_param_multiple("signal")) {
	if ((n = ufindsig(p)) >= 0) {
	    sigmap[n] = n; n++; nosig++;
	}
    }
}
/* Function putcal appends the caller's WFDB_Calinfo structure to the end of
   the calibration list. */
FINT putcal(WFDB_Calinfo *cal)
{
    SUALLOC(this_cle, 1, sizeof(struct cle));
    SSTRCPY(this_cle->sigtype, cal->sigtype);
    this_cle->caltype = cal->caltype;
    this_cle->low = cal->low;
    this_cle->high = cal->high;
    this_cle->scale = cal->scale;
    SSTRCPY(this_cle->units, cal->units);
    this_cle->next = NULL;

    if (first_cle) {
	prev_cle->next = this_cle;
	prev_cle = this_cle;
    }
    else
	first_cle = prev_cle = this_cle;
    return (0);
}
Exemple #6
0
/* force_unique_signames() tries to ensure that each signal has a unique name.
   By default, the name of signal i is s[i].desc.  The names of any signals
   that are not unique are modified by appending a unique suffix to each
   such signal.  For example, if there are five signals with default names
        A, A, B, C, B
   they are renamed as
        A:1*, A:2*, B:3*, C, B:4*

   For efficiency, this function makes two assumptions that may cause it
   to fail to achieve its intended purpose in rare cases.  First, the unique
   suffix is limited to five characters, so that at most 999 signals can be
   renamed.  Second, if any default name ends with a string that matches a
   unique suffix, it will not be recognized as non-unique.  For example, if
   the default names are
       A, A, A:0*
   they are renamed as
       A:0*, A:1*, A:0*
   The format of the suffix has been chosen to make this unlikely.
 */
void force_unique_signames(void) {
    int i, j;

    SALLOC(sname, sizeof(char *), nsig);

    for (i = 0; i < nsig; i++) {
	for (j = i+1; j < nsig; j++) {
	    if (strcmp(s[i].desc, s[j].desc) == 0) {
		sname[i] = sname[j] = "change";
	    }
	}
    }

    for (i = j =  0; i < nsig; i++) {
	if (sname[i] == NULL && j < 1000) {
	    SSTRCPY(sname[i], s[i].desc);
	}
	else {
	    SUALLOC(sname[i], sizeof(char), strlen(s[i].desc) + 6);
	    sprintf(sname[i], "%s:%d*", s[i].desc, j++);
	}
    }	
}
/* Function calopen reads the specified calibration file;  if called with
   a NULL argument, it takes the value of the environment variable WFDBCAL
   to be the name of the calibration file.  If the calibration file name
   does not begin with "+", calopen empties the calibration list first;
   otherwise, the "+" is discarded before attempting to open the file,
   which may be in any directory in the WFDB path.  If the file can be read,
   its contents are appended to the calibration list. */
FINT calopen(char *cfname)
{
    WFDB_FILE *cfile;
    char buf[128], *p1, *p2, *p3, *p4, *p5, *p6;

    /* If no calibration file is specified, return immediately. */
    if (cfname == NULL && (cfname = getenv("WFDBCAL")) == NULL &&
	(cfname = DEFWFDBCAL) == NULL)
	return (0);

    if (*cfname == '+')		/* don't empty the calibration list */
	cfname++;		/* discard the '+' prefix */
    else flushcal();		/* empty the calibration list */

    /* Quit if file can't be found or opened. */
    if ((cfile = wfdb_open(cfname, (char *)NULL, WFDB_READ)) == NULL) {
	wfdb_error("calopen: can't read calibration file %s\n", cfname);
	return (-2);
    }

    /* Read a line of the calibration file on each iteration.  See wfdbcal(5)
       for a description of the format. */
    while (wfdb_fgets(buf, 127, cfile)) {
	/* ignore leading whitespace */
	for (p1 = buf; *p1 == ' ' || *p1 == '\t' || *p1 == '\r'; p1++)
	    ;
	/* skip comments, empty lines, and improperly formatted lines */
	if (*p1 == '#' ||
	    (p1 = strtok(p1, "\t")) == NULL ||		    /* signal type */
	    (p2 = strtok((char *)NULL, " \t")) == NULL ||   /* low, or '-' */
	    (p3 = strtok((char *)NULL, " \t")) == NULL ||   /* high, or '-' */
	    (p4 = strtok((char *)NULL, " \t")) == NULL ||   /* pulse type */
	    (p5 = strtok((char *)NULL, " \t")) == NULL ||   /* scale */
	    (p6 = strtok((char *)NULL, " \t\r\n")) == NULL) /* units */
	    continue;

	/* This line appears to be a correctly formatted entry.  Allocate
	   memory for a calibration list entry. */
	SUALLOC(this_cle, 1, (sizeof(struct cle)));

	/* Fill in the fields of the new calibration list entry. */
	SSTRCPY(this_cle->sigtype, p1);
	if (strcmp(p2, "-") == 0) {
	    this_cle->caltype = WFDB_AC_COUPLED;
	    this_cle->low = 0.0;
	}
	else {
	    this_cle->caltype = WFDB_DC_COUPLED;
	    this_cle->low = atof(p2);
	}
	if (strcmp(p3, "-") == 0)
	    this_cle->high = this_cle->low = 0.0;
	else
	    this_cle->high = atof(p3);
	if (strcmp(p4, "square") == 0)
	    this_cle->caltype |= WFDB_CAL_SQUARE;
	else if (strcmp(p4, "sine") == 0)
	    this_cle->caltype |= WFDB_CAL_SINE;
	else if (strcmp(p4, "sawtooth") == 0)
	    this_cle->caltype |= WFDB_CAL_SAWTOOTH;
	/* otherwise pulse shape is undefined */
	this_cle->scale = atof(p5);
	SSTRCPY(this_cle->units, p6);
	this_cle->next = NULL;

	/* Append the new entry to the end of the list. */
	if (first_cle) {
	    prev_cle->next = this_cle;
	    prev_cle = this_cle;
	}
	else
	    first_cle = prev_cle = this_cle;
    }

    (void)wfdb_fclose(cfile);
    return (0);
}
Exemple #8
0
int fetchsignals(void)
{
    int first = 1, framelen, i, imax, imin, j, *m, *mp, n;
    WFDB_Calinfo cal;
    WFDB_Sample **sb, **sp, *sbo, *spo, *v;
    WFDB_Time t, ts0, tsf;

    /* Do nothing if no samples were requested. */ 
    if (nosig < 1 || t0 >= tf) return (0);

    /* Open the signal calibration database. */
    (void)calopen("wfdbcal");

    if (tfreq != ffreq) {
	ts0 = (WFDB_Time)(t0*tfreq/ffreq + 0.5);
	tsf = (WFDB_Time)(tf*tfreq/ffreq + 0.5);
    }
    else {
	ts0 = t0;
	tsf = tf;
    }

    /* Allocate buffers and buffer pointers for each selected signal. */
    SUALLOC(sb, nsig, sizeof(WFDB_Sample *));
    SUALLOC(sp, nsig, sizeof(WFDB_Sample *));
    for (n = framelen = 0; n < nsig; framelen += s[n++].spf)
	if (sigmap[n] >= 0) {
	    SUALLOC(sb[n], (int)((tf-t0)*s[n].spf + 0.5), sizeof(WFDB_Sample));
	    sp[n] = sb[n];
	}
    /* Allocate a frame buffer and construct the frame map. */
    SUALLOC(v, framelen, sizeof(WFDB_Sample));  /* frame buffer */
    SUALLOC(m, framelen, sizeof(int));	    /* frame map */
    for (i = n = 0; n < nsig; n++) {
	for (j = 0; j < s[n].spf; j++)
	    m[i++] = sigmap[n];
    }
    for (imax = framelen-1; imax > 0 && m[imax] < 0; imax--)
	;
    for (imin = 0; imin < imax && m[imin] < 0; imin++)
	;

    /* Fill the buffers. */
    isigsettime(t0);
    for (t = t0; t < tf && getframe(v) > 0; t++)
	for (i = imin, mp = m + imin; i <= imax; i++, mp++)
	    if ((n = *mp) >= 0) *(sp[n]++) = v[i];

    /* Generate output. */
    printf("  { \"signal\":\n    [\n");  
    for (n = 0; n < nsig; n++) {
	if (sigmap[n] >= 0) {
	    char *p;
	    int delta, prev; 

 	    if (!first) printf(",\n");
	    else first = 0;
	    printf("      { \"name\": %s,\n", p = strjson(sname[n])); SFREE(p);
	    if (s[n].units) {
		printf("        \"units\": %s,\n", p = strjson(s[n].units));
		SFREE(p);
	    }
	    else
		printf("        \"units\": \"mV\",\n");
	    printf("        \"t0\": %ld,\n", (long)ts0);
	    printf("        \"tf\": %ld,\n", (long)tsf);
	    printf("        \"gain\": %g,\n",
		   s[n].gain ? s[n].gain : WFDB_DEFGAIN);
	    printf("        \"base\": %d,\n", s[n].baseline);
	    printf("        \"tps\": %d,\n", (int)(tfreq/(ffreq*s[n].spf)+0.5));
	    if (getcal(sname[n], s[n].units, &cal) == 0)
		printf("        \"scale\": %g,\n", cal.scale);
	    else
		printf("        \"scale\": 1,\n");
	    printf("        \"samp\": [ ");
	    for (sbo = sb[n], prev = 0, spo = sp[n]-1; sbo < spo; sbo++) {
		delta = *sbo - prev;
		printf("%d,", delta);
		prev = *sbo;
	    }
	    printf("%d ]\n      }", *sbo - prev);
	}
    }
    printf("\n    ]%s", nann ? ",\n" : "\n  }\n");
    flushcal();
    for (n = 0; n < nsig; n++)
	SFREE(sb[n]);
    SFREE(sb);
    SFREE(sp);
    SFREE(v);
    SFREE(m);
    return (1);	/* output was written */
}