Exemple #1
0
/*
** _nrrdKeyValueWrite
**
** writes a given key and value to a file, starting with the given
** prefix (if non-NULL), and ending with "\n"
*/
int
_nrrdKeyValueWrite(FILE *file, char **stringP, const char *prefix, 
                   const char *key, const char *value) {
  
  if (!( (file || stringP) && key && value )) {
    return 1;
  }
  if (stringP) {
    /* 2*strlen() because at worst all characters will be escaped */
    *stringP = (char *)malloc(airStrlen(prefix) + 2*airStrlen(key)
                              + strlen(":=") + 2*airStrlen(value)
                              + strlen("\n") + 1);
    /* HEY error checking */
    strcpy(*stringP, "");
  }
  if (prefix) {
    if (file) {
      fprintf(file, "%s", prefix);
    } else {
      strcat(*stringP, prefix);
    }
  }
  if (file) {
    _nrrdWriteEscaped(file, NULL, key);
    fprintf(file, ":=");
    _nrrdWriteEscaped(file, NULL, value);
    fprintf(file, "\n");
  } else {
    _nrrdWriteEscaped(NULL, *stringP, key);
    strcat(*stringP, ":=");
    _nrrdWriteEscaped(NULL, *stringP, value);
    strcat(*stringP, "\n");
  }
  return 0;
}
Exemple #2
0
/*
** _nrrdKeyValueWrite
**
** writes a given key and value to a file, starting with the given
** prefix (if non-NULL), and ending with "\n"
*/
int
_nrrdKeyValueWrite(FILE *file, char **stringP, const char *prefix,
                   const char *key, const char *value) {

  if (!( (file || stringP) && key && value )) {
    return 1;
  }
  if (stringP) {
    /* 2*strlen() because at worst all characters will be escaped */
    *stringP = AIR_CALLOC(airStrlen(prefix) + 2*airStrlen(key)
                          + strlen(":=") + 2*airStrlen(value)
                          + strlen("\n") + 1, char);
    /* HEY error checking? */
  }
  if (prefix) {
    if (file) {
      fprintf(file, "%s", prefix);
    } else {
      strcat(*stringP, prefix);
    }
  }
  if (file) {
    _nrrdWriteEscaped(file, NULL, key, "\n\\", _NRRD_WHITESPACE_NOTAB);
    fprintf(file, ":=");
    _nrrdWriteEscaped(file, NULL, value, "\n\\", _NRRD_WHITESPACE_NOTAB);
    fprintf(file, "\n");
  } else {
    _nrrdWriteEscaped(NULL, *stringP, key, "\n\\", _NRRD_WHITESPACE_NOTAB);
    strcat(*stringP, ":=");
    _nrrdWriteEscaped(NULL, *stringP, value, "\n\\", _NRRD_WHITESPACE_NOTAB);
    strcat(*stringP, "\n");
  }
  return 0;
}
Exemple #3
0
int
_nrrdContentSet_nva(Nrrd *nout, const char *func,
                    char *content, const char *format, va_list arg) {
  char me[]="_nrrdContentSet_nva", err[BIFF_STRLEN], *buff;

  buff = (char *)malloc(128*AIR_STRLEN_HUGE);
  if (!buff) {
    sprintf(err, "%s: couln't alloc buffer!", me);
    biffAdd(NRRD, err); return 1;
  }
  nout->content = (char *)airFree(nout->content);

  /* we are currently praying that this won't overflow the "buff" array */
  /* HEY: replace with vsnprintf or whatever when its available */
  vsprintf(buff, format, arg);

  nout->content = (char *)calloc(strlen("(,)")
                                 + airStrlen(func)
                                 + 1                      /* '(' */
                                 + airStrlen(content)
                                 + 1                      /* ',' */
                                 + airStrlen(buff)
                                 + 1                      /* ')' */
                                 + 1, sizeof(char));      /* '\0' */
  if (!nout->content) {
    sprintf(err, "%s: couln't alloc output content!", me);
    biffAdd(NRRD, err); airFree(buff); return 1;
  }
  sprintf(nout->content, "%s(%s%s%s)", func, content,
          airStrlen(buff) ? "," : "", buff);
  airFree(buff);  /* no NULL assignment, else compile warnings */
  return 0;
}
Exemple #4
0
int
unrrdu_ccfindMain(int argc, char **argv, char *me, hestParm *hparm) {
  hestOpt *opt = NULL;
  char *out, *err, *valS;
  Nrrd *nin, *nout, *nval=NULL;
  airArray *mop;
  int type, pret;
  unsigned int conny;

  hestOptAdd(&opt, "v,values", "filename", airTypeString, 1, 1, &valS, "",
             "Giving a filename here allows you to save out the values "
             "associated with each connect component.  This can be used "
             "later with \"ccmerge -d\".  By default, no record of the "
             "original CC values is kept.");
  hestOptAdd(&opt, "t,type", "type", airTypeOther, 1, 1, &type, "default",
             "type to use for output, to store the CC ID values.  By default "
             "(not using this option), the type used will be the smallest of "
             "uchar, ushort, or int, that can represent all the CC ID values. "
             "Using this option allows one to specify the integral type to "
             "be used.",
             NULL, NULL, &unrrduHestMaybeTypeCB);
  hestOptAdd(&opt, "c,connect", "connectivity", airTypeUInt, 1, 1,
             &conny, NULL,
             "what kind of connectivity to use: the number of coordinates "
             "that vary in order to traverse the neighborhood of a given "
             "sample.  In 2D: \"1\": 4-connected, \"2\": 8-connected");
  OPT_ADD_NIN(nin, "input nrrd");
  OPT_ADD_NOUT(out, "output nrrd");

  mop = airMopNew();
  airMopAdd(mop, opt, (airMopper)hestOptFree, airMopAlways);

  USAGE(_unrrdu_ccfindInfoL);
  PARSE();
  airMopAdd(mop, opt, (airMopper)hestParseFree, airMopAlways);

  nout = nrrdNew();
  airMopAdd(mop, nout, (airMopper)nrrdNuke, airMopAlways);

  if (nrrdCCFind(nout, airStrlen(valS) ? &nval : NULL, nin, type, conny)) {
    airMopAdd(mop, err = biffGetDone(NRRD), airFree, airMopAlways);
    fprintf(stderr, "%s: error doing connected components:\n%s", me, err);
    airMopError(mop);
    return 1;
  }
  if (nval) {
    airMopAdd(mop, nval, (airMopper)nrrdNuke, airMopAlways);
  }

  if (airStrlen(valS)) {
    SAVE(valS, nval, NULL);
  }
  SAVE(out, nout, NULL);

  airMopOkay(mop);
  return 0;
}
Exemple #5
0
/*
******** nrrdDescribe
**
** writes verbose description of nrrd to given file
*/
void
nrrdDescribe(FILE *file, const Nrrd *nrrd) {
  unsigned int ai;
  char stmp[AIR_STRLEN_SMALL];

  if (file && nrrd) {
    fprintf(file, "Nrrd at 0x%p:\n", AIR_CVOIDP(nrrd));
    fprintf(file, "Data at 0x%p is %s elements of type %s.\n", nrrd->data,
            airSprintSize_t(stmp, nrrdElementNumber(nrrd)),
            airEnumStr(nrrdType, nrrd->type));
    if (nrrdTypeBlock == nrrd->type) {
      fprintf(file, "The blocks have size %s\n",
              airSprintSize_t(stmp, nrrd->blockSize));
    }
    if (airStrlen(nrrd->content)) {
      fprintf(file, "Content = \"%s\"\n", nrrd->content);
    }
    fprintf(file, "%d-dimensional array, with axes:\n", nrrd->dim);
    for (ai=0; ai<nrrd->dim; ai++) {
      if (airStrlen(nrrd->axis[ai].label)) {
        fprintf(file, "%d: (\"%s\") ", ai, nrrd->axis[ai].label);
      } else {
        fprintf(file, "%d: ", ai);
      }
      fprintf(file, "%s-centered, size=%s, ",
              airEnumStr(nrrdCenter, nrrd->axis[ai].center),
              airSprintSize_t(stmp, nrrd->axis[ai].size));
      airSinglePrintf(file, NULL, "spacing=%lg, \n", nrrd->axis[ai].spacing);
      airSinglePrintf(file, NULL, "thickness=%lg, \n",
                      nrrd->axis[ai].thickness);
      airSinglePrintf(file, NULL, "    axis(Min,Max) = (%lg,",
                       nrrd->axis[ai].min);
      airSinglePrintf(file, NULL, "%lg)\n", nrrd->axis[ai].max);
      if (airStrlen(nrrd->axis[ai].units)) {
        fprintf(file, "units=%s, \n", nrrd->axis[ai].units);
      }
    }
    /*
    airSinglePrintf(file, NULL, "The min, max values are %lg",
                     nrrd->min);
    airSinglePrintf(file, NULL, ", %lg\n", nrrd->max);
    */
    airSinglePrintf(file, NULL, "The old min, old max values are %lg",
                     nrrd->oldMin);
    airSinglePrintf(file, NULL, ", %lg\n", nrrd->oldMax);
    /* fprintf(file, "hasNonExist = %d\n", nrrd->hasNonExist); */
    if (nrrd->cmtArr->len) {
      fprintf(file, "Comments:\n");
      for (ai=0; ai<nrrd->cmtArr->len; ai++) {
        fprintf(file, "%s\n", nrrd->cmt[ai]);
      }
    }
    fprintf(file, "\n");
  }
}
Exemple #6
0
/*
** _nrrdHestNrrdParse()
**
** Converts a filename into a nrrd for the sake of hest.
** There is no HestMaybeNrrdParse because this already does that:
** when we get an empty string, we give back a NULL pointer, and
** that is just fine
*/
int
_nrrdHestNrrdParse(void *ptr, char *str, char err[AIR_STRLEN_HUGE]) {
  char me[] = "_nrrdHestNrrdParse", *nerr;
  Nrrd **nrrdP;
  airArray *mop;

  if (!(ptr && str)) {
    sprintf(err, "%s: got NULL pointer", me);
    return 1;
  }
  nrrdP = (Nrrd **)ptr;
  if (airStrlen(str)) {
    mop = airMopNew();
    *nrrdP = nrrdNew();
    airMopAdd(mop, *nrrdP, (airMopper)nrrdNuke, airMopOnError);
    if (nrrdLoad(*nrrdP, str, NULL)) {
      airMopAdd(mop, nerr = biffGetDone(NRRD), airFree, airMopOnError);
      airStrcpy(err, AIR_STRLEN_HUGE, nerr);
      airMopError(mop);
      return (strstr(err, "EOF") ? 2 : 1);
    }
    airMopOkay(mop);
  } else {
    /* they gave us an empty string, we give back no nrrd,
       but its not an error condition */
    *nrrdP = NULL;
  }
  return 0;
}
Exemple #7
0
int
tkwbReadFileToString(char **strP, int *hitEOF, FILE *file, char *stop) {
    char **all, line[AIR_STRLEN_HUGE];
    airArray *allArr;
    unsigned int allLen;
    unsigned int lineLen, lineIdx, totalLen;
    _tkwbU uu;

    uu.pc = &all;
    allArr = airArrayNew(uu.v, &allLen, sizeof(char*), tkwbArrayIncr);
    airArrayPointerCB(allArr, airNull, airFree);
    lineLen = airOneLine(file, line, AIR_STRLEN_HUGE);
    totalLen = 0;
    while (lineLen && (!( airStrlen(stop) && !strcmp(line, stop) )) ) {
        lineIdx = airArrayLenIncr(allArr, 1); /* HEY error checking */
        all[lineIdx] = (char *)calloc(strlen(line) + strlen("\n") + 1,
                                      sizeof(char));
        sprintf(all[lineIdx], "%s\n", line);
        totalLen += strlen(line) + 1;
        lineLen = airOneLine(file, line, AIR_STRLEN_HUGE);
    }
    if (hitEOF) {
        *hitEOF = !lineLen;
    }

    *strP = (char*)calloc(totalLen+1, sizeof(char));
    strcpy(*strP, "");
    for (lineIdx=0; lineIdx<allLen; lineIdx++) {
        strcat(*strP, all[lineIdx]);
    }

    airArrayNuke(allArr);
    return 0;
}
Exemple #8
0
void
airEnumPrint(FILE *file, const airEnum *enm) {
  int ii; /* this should arguable be unsigned int, but 
             airEnum values were kept as "int", even after
             the great unsigned conversion */

  if (!(file && enm)) {
    return;
  }

  if (airStrlen(enm->name)) {
    fprintf(file, "airEnum \"%s\":\n", enm->name);
  } else {
    fprintf(file, "airEnum (NO NAME!):\n");
  }
  fprintf(file, "(%s case sensitive)\n", (enm->sense ? "yes, is" : "is not"));
  if (enm->val) {
    fprintf(file, "Values (%u valid) given explicitly\n", enm->M);
    fprintf(file, "--- (0) %d: \"%s\"\n", enm->val[0], enm->str[0]);
    for (ii=1; ii<=AIR_CAST(int, enm->M); ii++) {
      fprintf(file, "--- (%d) %d: \"%s\" == \"%s\"\n", ii,
              enm->val[ii], enm->str[ii],
              airEnumStr(enm, enm->val[ii]));
      _enumPrintVal(file, enm, ii);
    }
  } else {
Exemple #9
0
int
unrrdu_ccsettleMain(int argc, char **argv, char *me, hestParm *hparm) {
  hestOpt *opt = NULL;
  char *out, *err, *valS;
  Nrrd *nin, *nout, *nval=NULL;
  airArray *mop;
  int pret;

  mop = airMopNew();
  hestOptAdd(&opt, "i,input", "nin", airTypeOther, 1, 1, &nin, NULL,
             "input nrrd",
             NULL, NULL, nrrdHestNrrd);
  hestOptAdd(&opt, "v,values", "filename", airTypeString, 1, 1, &valS, "",
             "Giving a filename here allows you to save out the mapping "
             "from new (settled) values to old values, in the form of a "
             "1-D lookup table");
  OPT_ADD_NOUT(out, "output nrrd");
  airMopAdd(mop, opt, (airMopper)hestOptFree, airMopAlways);

  USAGE(_unrrdu_ccsettleInfoL);
  PARSE();
  airMopAdd(mop, opt, (airMopper)hestParseFree, airMopAlways);

  nout = nrrdNew();
  airMopAdd(mop, nout, (airMopper)nrrdNuke, airMopAlways);

  if (nrrdCCSettle(nout, airStrlen(valS) ? &nval : NULL, nin)) {
    airMopAdd(mop, err = biffGetDone(NRRD), airFree, airMopAlways);
    fprintf(stderr, "%s: error settling connected components:\n%s", me, err);
    airMopError(mop);
    return 1;
  }
  if (nval) {
    airMopAdd(mop, nval, (airMopper)nrrdNuke, airMopAlways);
  }

  if (airStrlen(valS)) {
    SAVE(valS, nval, NULL);
  }
  SAVE(out, nout, NULL);

  airMopOkay(mop);
  return 0;
}
Exemple #10
0
/*
******** airOneLinify()
**
** converts all contiguous white space (as determined by isspace()) to
** a single ' ', entirely removes non-printable (as determined by
** isprint()) characters, and entirely removes white space contiguous
** with the end of the string, even if that means shrinking the string
** to "".
**
** Useful for cleaning up lines of text to be saved as strings in
** fields of other structs
*/
char *
airOneLinify(char *s) {
  size_t i, j, len; // to match the signature of airStrlen()

  len = airStrlen(s);
  if (!len) 
    return s;

  /* convert white space to space (' '), and delete unprintables */
  for (i=0; i<len; i++) {
    if (isspace((int) s[i])) {
      s[i] = ' ';
      continue;
    }
    if (!isprint((int) s[i])) {
      for (j=i; j<len; j++) {
        /* this will copy the '\0' at the end */
        s[j] = s[j+1];
      }
      i--;
      continue;
    }
  }

  /* compress all contiguous spaces into one */
  for (i=0; i<len; i++) {
    while (' ' == s[i] && ' ' == s[i+1]) {
      for (j=i+1; j<len; j++) {
        s[j] = s[j+1];
      }
    }
  }

  /* lose trailing white space */
  len = airStrlen(s);
  for (i=len-1; ((int)i)>=0 && ' ' == s[i]; i--) {
    s[i] = '\0';
  }

  return s;
}
Exemple #11
0
int
main(int argc, const char *argv[]) {
    airArray *mop;
    const char *me;
    char *aa, *aaCopy, *ab;
    size_t aaSize, abSize;

    AIR_UNUSED(argc);
    me = argv[0];
    mop = airMopNew();

    if (0 != airStrlen(NULL)) {
        fprintf(stderr, "%s: 0 != airStrlen(NULL)\n", me);
        airMopError(mop);
        exit(1);
    }
    if (0 != airStrlen("")) {
        fprintf(stderr, "%s: 0 != airStrlen(\"\")\n", me);
        airMopError(mop);
        exit(1);
    }
    if (1 != airStrlen("A")) {
        fprintf(stderr, "%s: 1 != airStrlen(\"A\")\n", me);
        airMopError(mop);
        exit(1);
    }
    if (NULL != airStrdup(NULL)) {
        fprintf(stderr, "%s: NULL != airStrdup(NULL)\n", me);
        airMopError(mop);
        exit(1);
    }
    if (strlen(STR_A) != airStrlen(STR_A)) {
        fprintf(stderr, "%s: strlen %u != airStrlen %u of |%s|\n", me,
                AIR_CAST(unsigned int, strlen(STR_A)),
                AIR_CAST(unsigned int, airStrlen(STR_A)), STR_A);
        airMopError(mop);
        exit(1);
    }
Exemple #12
0
/*
******** biffMsgMove
**
** "src" is not const because we clear it after moving things out
*/
void
biffMsgMove(biffMsg *dest, biffMsg *src, const char *err) {
  static const char me[]="biffMsgMove";
  unsigned int ii;
  char *buff;

  if (biffMsgNoop == dest || biffMsgNoop == src) {
    return;
  }
  if (!( dest && src )) {
    fprintf(stderr, "%s: PANIC got NULL msg (%p %p)\n", me,
            AIR_VOIDP(dest), AIR_VOIDP(src));
    /* exit(1); */
  }
  /* if src and dest are same, this degenerates to biffMsgAdd */
  if (dest == src && airStrlen(err)) {
    biffMsgAdd(dest, err);
    return;
  }

  buff = AIR_CALLOC(biffMsgLineLenMax(src)+1, char);
  if (!buff) {
    fprintf(stderr, "%s: PANIC: can't allocate buffer\n", me);
    /* exit(1); */
  }
  for (ii=0; ii<src->errNum; ii++) {
    sprintf(buff, "[%s] %s", src->key, src->err[ii]);
    biffMsgAdd(dest, buff);
  }
  free(buff);
  biffMsgClear(src);
  if (airStrlen(err)) {
    biffMsgAdd(dest, err);
  }
  return;
}
Exemple #13
0
/* 
** we try to use the oldest format that will hold the nrrd 
*/
int
_nrrdFormatNRRD_whichVersion(const Nrrd *nrrd, NrrdIoState *nio) {
  int ret;

  if (_nrrdFieldInteresting(nrrd, nio, nrrdField_measurement_frame)) {
    ret = 5;
  } else if (_nrrdFieldInteresting(nrrd, nio, nrrdField_thicknesses)
             || _nrrdFieldInteresting(nrrd, nio, nrrdField_space)
             || _nrrdFieldInteresting(nrrd, nio, nrrdField_space_dimension)
             || _nrrdFieldInteresting(nrrd, nio, nrrdField_sample_units)
             || airStrlen(nio->dataFNFormat) || nio->dataFNArr->len > 1) {
    ret = 4;
  } else if (_nrrdFieldInteresting(nrrd, nio, nrrdField_kinds)) {
    ret = 3;
  } else if (nrrdKeyValueSize(nrrd)) {
    ret = 2;
  } else {
    ret = 1;
  }
  return ret;
}
Exemple #14
0
static void
_enumPrintVal(FILE *file, const airEnum *enm, int ii) {

  if (enm->desc) {
    fprintf(file, "desc: %s\n", enm->desc[ii]);
  }
  if (enm->strEqv) {
    unsigned int jj;
    fprintf(file, "eqv:"); fflush(file);
    jj = 0;
    while (airStrlen(enm->strEqv[jj])) {
      if (enm->valEqv[jj] == (enm->val
                              ? enm->val[ii]
                              : ii)) {
        fprintf(file, " \"%s\"", enm->strEqv[jj]);
      }
      jj++;
    }
    fprintf(file, "\n");
  }
}
Exemple #15
0
/*
******** airEnumFmtDesc()
**
** Formats a description line for one element "val" of airEnum "enm",
** and puts the result in a NEWLY ALLOCATED string which is the return
** of this function.  The formatting is done via sprintf(), as governed
** by "fmt", which should contain to "%s" conversion sequences, the
** first for the string version "val", and the second for the
** description If "canon", then the canonical string representation
** will be used (the one in enm->str[]), otherwise the shortest string
** representation will be used (which differs from the canonical one
** when there is a strEqv[]/valEqv[] pair defining a shorter string)
*/
char *
airEnumFmtDesc(const airEnum *enm, int val, int canon, const char *fmt) {
  const char *desc;
  char *buff, ident[AIR_STRLEN_SMALL];
  const char *_ident;
  int i;
  size_t len;

  if (!(enm && enm->desc && fmt)) {
    return airStrdup("(airEnumDesc: invalid args)");
  }
  if (airEnumValCheck(enm, val)) {
    val = airEnumUnknown(enm);
  }
  _ident = airEnumStr(enm, val);
  if (!canon && enm->strEqv) {
    len = airStrlen(_ident);
    for (i=0; airStrlen(enm->strEqv[i]); i++) {
      if (val != enm->valEqv[i]) {
        /* this isn't a string representing the value we care about */
        continue;
      }
      if (airStrlen(enm->strEqv[i]) < len) {
        /* this one is shorter */
        len = airStrlen(enm->strEqv[i]);
        _ident = enm->strEqv[i];
      }
    }
  }
  strncpy(ident, _ident, AIR_STRLEN_SMALL);
  ident[AIR_STRLEN_SMALL-1] = '\0';
  if (!enm->sense) {
    airToLower(ident);
  }
  desc = enm->desc[_airEnumIndex(enm, val)];
  buff = AIR_CALLOC(airStrlen(fmt) + airStrlen(ident) +
                    airStrlen(desc) + 1, char);
  if (buff) {
    sprintf(buff, fmt, ident, desc);
  }
  return buff;
}
Exemple #16
0
/*
******** airStrtok()
**
** thread-safe strtok() replacement.  Use just like strtok(), but on
** each call to parse a given string, pass as the last argument the
** address of a char*, to be used for saving state while the string is
** traversed.  Like strtok(), this will alter the "s" array passed to
** it on the first call, and like strtok(), this returns pointers into
** this string (rather than allocating new strings for each token).
*/
char *
airStrtok(char *s, const char *ct, char **last) {
  char *h, *e, *q;
  
  if (!(ct && last)) {
    /* can't do any work, bail */
    return NULL;
  }
  h = s ? s : *last;
  if (!airStrlen(h))
    return NULL;
  h += strspn(h, ct);
  if ('\"' == *h && airStrtokQuoting) {
    /* something is trying to be quoted, and, we'll respect that */
    /* have to find the next un-escaped '\"' */
    h++;
    q = h;
    while (*q && !('\"' == *q && '\\' != q[-1])) {
      q++;
    }
    if (*q) {
      /* we found an unescaped '\"' */
      e = q;
    } else {
      /* give up; pretend we never tried to do this quoting stuff */
      e = h + strcspn(h, ct);
    }
  } else {
    e = h + strcspn(h, ct);
  }
  if ('\0' == *e) {
    *last = e;
  }
  else {
    *e = '\0';
    *last = e + 1;
  }
  return h;
}
Exemple #17
0
/*
******** airUnescape()
**
** unescapes \\ and \n in place in a given string.
**
*/
char *
airUnescape(char *s) {
  size_t i, j, len; // to match signature of strlen in 64 bits
  int found=0;

  len = airStrlen(s);
  if (!len) 
    return s;

  for (i=1, j=0; i<len; i++, j++) {
    if (s[i-1] == '\\' && s[i] == '\\') {
      s[j] = '\\'; i++; found = 1;
    } else if (s[i-1] == '\\' && s[i] == 'n') {
      s[j] = '\n'; i++; found = 1;
    } else {
      s[j] = s[i-1]; found = 0;
    }
  }
  if (i == len || !found) s[j++] = s[len-1];
  s[j] = 0;

  return s;
}
Exemple #18
0
void
hestGlossary(FILE *f, hestOpt *opt, hestParm *_parm) {
  int i, j, len, maxlen, numOpts;
  char buff[2*AIR_STRLEN_HUGE], tmpS[AIR_STRLEN_HUGE];
  hestParm *parm;

  parm = !_parm ? hestParmNew() : _parm;

  if (_hestPanic(opt, NULL, parm)) {
    /* we can't continue; the opt array is botched */
    parm = !_parm ? hestParmFree(parm) : NULL;
    return;
  }
    
  numOpts = _hestNumOpts(opt);

  maxlen = 0;
  if (numOpts) {
    fprintf(f, "\n");
  }
  for (i=0; i<numOpts; i++) {
    strcpy(buff, "");
    _hestSetBuff(buff, opt + i, parm, AIR_TRUE, AIR_FALSE);
    maxlen = AIR_MAX((int)strlen(buff), maxlen);
  }
  if (parm && parm->respFileEnable) {
    sprintf(buff, "%cfile ...", parm->respFileFlag);
    len = strlen(buff);
    for (j=len; j<maxlen; j++) {
      fprintf(f, " ");
    }
    fprintf(f, "%s = ", buff);
    strcpy(buff, "response file(s) containing command-line arguments");
    _hestPrintStr(f, maxlen + 3, maxlen + 3, parm->columns, buff, AIR_FALSE);
  }
  for (i=0; i<numOpts; i++) {
    strcpy(buff, "");
    _hestSetBuff(buff, opt + i, parm, AIR_TRUE, AIR_FALSE);
    airOneLinify(buff);
    len = strlen(buff);
    for (j=len; j<maxlen; j++) {
      fprintf(f, " ");
    }
    fprintf(f, "%s", buff);
    strcpy(buff, "");
#if 1
    if (opt[i].flag && strchr(opt[i].flag, parm->multiFlagSep)) {
      /* there is a long-form flag as well as short */
      _hestSetBuff(buff, opt + i, parm, AIR_FALSE, AIR_TRUE);
      strcat(buff, " = ");
      fprintf(f, " , ");
    } else {
      /* there is only a short-form flag */
      fprintf(f, " = ");
    }
#else
    fprintf(f, " = ");
#endif
    if (opt[i].info) {
      strcat(buff, opt[i].info);
    }
    if ((opt[i].min || _hestMax(opt[i].max))
        && (!( 2 == opt[i].kind
               && airTypeEnum == opt[i].type 
               && parm->elideSingleEnumType )) 
        && (!( 2 == opt[i].kind
               && airTypeOther == opt[i].type 
               && parm->elideSingleOtherType )) 
        ) {
      /* if there are newlines in the info, then we want to clarify the
         type by printing it on its own line */
      if (opt[i].info && strchr(opt[i].info, '\n')) {
        strcat(buff, "\n ");
      }
      else {
        strcat(buff, " ");
      }
      strcat(buff, "(");
      if (opt[i].min == 0 && _hestMax(opt[i].max) == 1) {
        strcat(buff, "optional\t");
      }
      else {
        if ((int)opt[i].min == _hestMax(opt[i].max) && _hestMax(opt[i].max) > 1) { /* HEY scrutinize casts */
          sprintf(tmpS, "%d\t", _hestMax(opt[i].max));
          strcat(buff, tmpS);
        }
        else if ((int)opt[i].min < _hestMax(opt[i].max)) { /* HEY scrutinize casts */
          if (-1 == opt[i].max) {
            sprintf(tmpS, "%d\tor\tmore\t", opt[i].min);
          }
          else {
            sprintf(tmpS, "%d..%d\t", opt[i].min, _hestMax(opt[i].max));
          }
          strcat(buff, tmpS);
        }
      }
      sprintf(tmpS, "%s%s", 
              (airTypeEnum == opt[i].type
               ? opt[i].enm->name
               : (airTypeOther == opt[i].type
                  ? opt[i].CB->type
                  : airTypeStr[opt[i].type])),
              (_hestMax(opt[i].max) > 1 
               ? (airTypeOther == opt[i].type
                  && 'y' == opt[i].CB->type[airStrlen(opt[i].CB->type)-1]
                  && parm->cleverPluralizeOtherY
                  ? "\bies" 
                  : "s")
               : ""));
      strcat(buff, tmpS);
      strcat(buff, ")");
    }
    /*
    fprintf(stderr, "!%s: parm->elideSingleOtherDefault = %d\n",
            "hestGlossary", parm->elideSingleOtherDefault);
    */
    if (opt[i].dflt 
        && (opt[i].min || _hestMax(opt[i].max))
        && (!( 2 == opt[i].kind
               && (airTypeFloat == opt[i].type || airTypeDouble == opt[i].type)
               && !AIR_EXISTS(airAtod(opt[i].dflt)) 
               && parm->elideSingleNonExistFloatDefault ))
        && (!( (3 == opt[i].kind || 5 == opt[i].kind) 
               && (airTypeFloat == opt[i].type || airTypeDouble == opt[i].type)
               && !AIR_EXISTS(airAtod(opt[i].dflt)) 
               && parm->elideMultipleNonExistFloatDefault ))
        && (!( 2 == opt[i].kind
               && airTypeOther == opt[i].type
               && parm->elideSingleOtherDefault ))
        && (!( 2 == opt[i].kind
               && airTypeString == opt[i].type
               && parm->elideSingleEmptyStringDefault 
               && 0 == airStrlen(opt[i].dflt) ))
        && (!( (3 == opt[i].kind || 5 == opt[i].kind) 
               && airTypeString == opt[i].type
               && parm->elideMultipleEmptyStringDefault 
               && 0 == airStrlen(opt[i].dflt) ))
        ) {
      /* if there are newlines in the info, then we want to clarify the
         default by printing it on its own line */
      if (opt[i].info && strchr(opt[i].info, '\n')) {
        strcat(buff, "\n ");
      }
      else {
        strcat(buff, "; ");
      }
      strcat(buff, "default:\t");
      strcpy(tmpS, opt[i].dflt);
      airStrtrans(tmpS, ' ', '\t');
      strcat(buff, "\"");
      strcat(buff, tmpS);
      strcat(buff, "\"");
    }
    _hestPrintStr(f, maxlen + 3, maxlen + 3, parm->columns, buff, AIR_FALSE);
  }
  parm = !_parm ? hestParmFree(parm) : NULL;

  return;
}
Exemple #19
0
/*
** used to set all the fields of pullVolume at once, including the
** gageContext inside the pullVolume
**
** used both for top-level volumes in the pullContext (pctx->vol[i])
** in which case pctx is non-NULL,
** and for the per-task volumes (task->vol[i]),
** in which case pctx is NULL
*/
int
_pullVolumeSet(pullContext *pctx, pullVolume *vol, char *name,
               const Nrrd *ninSingle,
               const Nrrd *const *ninScale, double *scalePos,
               unsigned int ninNum,
               const gageKind *kind, 
               const NrrdKernelSpec *ksp00,
               const NrrdKernelSpec *ksp11,
               const NrrdKernelSpec *ksp22,
               const NrrdKernelSpec *kspSS) {
  char me[]="_pullVolumeSet", err[BIFF_STRLEN];
  int E;
  unsigned int vi;

  if (!( vol && (ninSingle || ninScale) && kind 
         && airStrlen(name) && ksp00 && ksp11 && ksp22 )) {
    sprintf(err, "%s: got NULL pointer", me);
    biffAdd(PULL, err); return 1;
  }
  if (pctx) {
    for (vi=0; vi<pctx->volNum; vi++) {
      if (pctx->vol[vi] == vol) {
        sprintf(err, "%s: already got vol %p as vol[%u]", me, vol, vi);
        biffAdd(PULL, err); return 1;
      }
    }
  }
  if (ninScale && !scalePos) {
    sprintf(err, "%s: need scalePos array if using scale-space", me);
    biffAdd(PULL, err); return 1;
  }
  if (ninScale && !(ninNum >= 2)) {
    sprintf(err, "%s: need at least 2 volumes (not %u)", me, ninNum);
    biffAdd(PULL, err); return 1;
  }
  if (!(vol->gctx)) {
    sprintf(err, "%s: got NULL vol->gageContext", me);
    biffAdd(PULL, err); return 1;
  }
  gageParmSet(vol->gctx, gageParmRequireAllSpacings, AIR_TRUE);
  gageParmSet(vol->gctx, gageParmRenormalize, AIR_FALSE);
  gageParmSet(vol->gctx, gageParmCheckIntegrals, AIR_TRUE);
  E = 0;
  if (!E) E |= !(vol->gpvl = gagePerVolumeNew(vol->gctx, (ninSingle
                                                          ? ninSingle
                                                          : ninScale[0]),
                                              kind));
  if (!E) E |= gageKernelSet(vol->gctx, gageKernel00,
                             ksp00->kernel, ksp00->parm);
  if (!E) E |= gageKernelSet(vol->gctx, gageKernel11,
                             ksp11->kernel, ksp11->parm); 
  if (!E) E |= gageKernelSet(vol->gctx, gageKernel22,
                             ksp22->kernel, ksp22->parm);
  if (ninScale) {
    gagePerVolume **pvlSS;
    if (!kspSS) {
      sprintf(err, "%s: got NULL kspSS", me);
      biffAdd(PULL, err); return 1;
    }
    gageParmSet(vol->gctx, gageParmStackUse, AIR_TRUE);
    gageParmSet(vol->gctx, gageParmStackRenormalize, AIR_TRUE);
    if (!E) E |= gageStackPerVolumeNew(vol->gctx, &pvlSS,
                                       ninScale, ninNum, kind);
    if (!E) E |= gageStackPerVolumeAttach(vol->gctx, vol->gpvl, pvlSS,
                                          scalePos, ninNum);
    if (!E) E |= gageKernelSet(vol->gctx, gageKernelStack,
                               kspSS->kernel, kspSS->parm);
  } else {
    if (!E) E |= gagePerVolumeAttach(vol->gctx, vol->gpvl);
  }
  if (E) {
    sprintf(err, "%s: trouble", me);
    biffMove(PULL, err, GAGE); return 1;
  }

  vol->name = airStrdup(name);
  if (!vol->name) {
    sprintf(err, "%s: couldn't strdup name (len %u)", me,
            AIR_CAST(unsigned int, airStrlen(name)));
    biffAdd(PULL, err); return 1;
  }
Exemple #20
0
/*
** asserts all the properties associated with orientation information
**
** The most important part of this is asserting the per-axis mutual
** exclusion of min/max/spacing/units versus using spaceDirection.
*/
static int
_nrrdFieldCheckSpaceInfo(const Nrrd *nrrd, int useBiff) {
  static const char me[]="_nrrdFieldCheckSpaceInfo";
  unsigned int dd, ii;
  int exists;

  if (!( !nrrd->space || !airEnumValCheck(nrrdSpace, nrrd->space) )) {
    biffMaybeAddf(useBiff, NRRD, "%s: space %d invalid",
                  me, nrrd->space);
    return 1;
  }
  if (!( nrrd->spaceDim <= NRRD_SPACE_DIM_MAX )) {
    biffMaybeAddf(useBiff, NRRD, "%s: space dimension %d is outside "
                  "valid range [0,NRRD_SPACE_DIM_MAX] = [0,%d]",
                  me, nrrd->dim, NRRD_SPACE_DIM_MAX);
    return 1;
  }
  if (nrrd->spaceDim) {
    if (nrrd->space) {
      if (nrrdSpaceDimension(nrrd->space) != nrrd->spaceDim) {
        biffMaybeAddf(useBiff, NRRD,
                      "%s: space %s has dimension %d but spaceDim is %d",
                      me, airEnumStr(nrrdSpace, nrrd->space),
                      nrrdSpaceDimension(nrrd->space), nrrd->spaceDim);
        return 1;
      }
    }
    /* check that all coeffs of spaceOrigin have consistent existance */
    exists = AIR_EXISTS(nrrd->spaceOrigin[0]);
    for (ii=0; ii<nrrd->spaceDim; ii++) {
      if (exists ^ AIR_EXISTS(nrrd->spaceOrigin[ii])) {
        biffMaybeAddf(useBiff, NRRD,
                      "%s: existance of space origin coefficients must "
                      "be consistent (val[0] not like val[%d])", me, ii);
        return 1;
      }
    }
    /* check that all coeffs of measurementFrame have consistent existance */
    exists = AIR_EXISTS(nrrd->measurementFrame[0][0]);
    for (dd=0; dd<nrrd->spaceDim; dd++) {
      for (ii=0; ii<nrrd->spaceDim; ii++) {
        if (exists ^ AIR_EXISTS(nrrd->measurementFrame[dd][ii])) {
          biffMaybeAddf(useBiff, NRRD,
                        "%s: existance of measurement frame coefficients "
                        "must be consistent: [col][row] [%d][%d] not "
                        "like [0][0])", me, dd, ii);
          return 1;
        }
      }
    }
    /* check on space directions */
    for (dd=0; dd<nrrd->dim; dd++) {
      exists = AIR_EXISTS(nrrd->axis[dd].spaceDirection[0]);
      for (ii=1; ii<nrrd->spaceDim; ii++) {
        if (exists ^ AIR_EXISTS(nrrd->axis[dd].spaceDirection[ii])) {
          biffMaybeAddf(useBiff, NRRD,
                        "%s: existance of space direction %d coefficients "
                        "must be consistent (val[0] not like val[%d])", me,
                        dd, ii); return 1;
        }
      }
      if (exists) {
        if (AIR_EXISTS(nrrd->axis[dd].min)
            || AIR_EXISTS(nrrd->axis[dd].max)
            || AIR_EXISTS(nrrd->axis[dd].spacing)
            || !!airStrlen(nrrd->axis[dd].units)) {
          biffMaybeAddf(useBiff, NRRD,
                        "%s: axis[%d] has a direction vector, and so can't "
                        "have min, max, spacing, or units set", me, dd);
          return 1;
        }
      }
    }
  } else {
    /* else there's not supposed to be anything in "space" */
    if (nrrd->space) {
      biffMaybeAddf(useBiff, NRRD,
                    "%s: space %s can't be set with spaceDim %d",
                    me, airEnumStr(nrrdSpace, nrrd->space),
                    nrrd->spaceDim);
      return 1;
    }
    /* -------- */
    exists = AIR_FALSE;
    for (dd=0; dd<NRRD_SPACE_DIM_MAX; dd++) {
      exists |= !!airStrlen(nrrd->spaceUnits[dd]);
    }
    if (exists) {
      biffMaybeAddf(useBiff, NRRD,
                    "%s: spaceDim is 0, but space units is set", me);
      return 1;
    }
    /* -------- */
    exists = AIR_FALSE;
    for (dd=0; dd<NRRD_SPACE_DIM_MAX; dd++) {
      exists |= AIR_EXISTS(nrrd->spaceOrigin[dd]);
    }
    if (exists) {
      biffMaybeAddf(useBiff, NRRD,
                    "%s: spaceDim is 0, but space origin is set", me);
      return 1;
    }
    /* -------- */
    exists = AIR_FALSE;
    for (dd=0; dd<NRRD_SPACE_DIM_MAX; dd++) {
      for (ii=0; ii<NRRD_DIM_MAX; ii++) {
        exists |= AIR_EXISTS(nrrd->axis[ii].spaceDirection[dd]);
      }
    }
    if (exists) {
      biffMaybeAddf(useBiff, NRRD,
                    "%s: spaceDim is 0, but space directions are set", me);
      return 1;
    }
  }
  return 0;
}
Exemple #21
0
int
unrrdu_2opMain(int argc, char **argv, char *me, hestParm *hparm) {
  hestOpt *opt = NULL;
  char *out, *err, *seedS;
  NrrdIter *in1, *in2;
  Nrrd *nout, *ntmp=NULL;
  int op, type, E, pret;
  airArray *mop;
  unsigned int seed;

  hestOptAdd(&opt, NULL, "operator", airTypeEnum, 1, 1, &op, NULL,
             "Binary operator. Possibilities include:\n "
             "\b\bo \"+\", \"-\", \"x\", \"/\": "
             "add, subtract, multiply, divide\n "
             "\b\bo \"^\": exponentiation (pow)\n "
             "\b\bo \"spow\": signed exponentiation: sgn(x)pow(abs(x),p)\n "
             "\b\bo \"%\": integer modulo\n "
             "\b\bo \"fmod\": same as fmod() in C\n "
             "\b\bo \"atan2\": same as atan2() in C\n "
             "\b\bo \"min\", \"max\": minimum, maximum\n "
             "\b\bo \"lt\", \"lte\", \"gt\", \"gte\": same as C's <, <=, >, <=\n "
             "\b\bo \"eq\", \"neq\": same as C's == and !=\n "
             "\b\bo \"comp\": -1, 0, or 1 if 1st value is less than, "
             "equal to, or greater than 2nd value\n "
             "\b\bo \"if\": if 1st value is non-zero, use it, "
             "else use 2nd value\n "
             "\b\bo \"exists\": if 1st value exists, use it, "
             "else use 2nd value\n "
             "\b\bo \"nrand\": scale unit-stdv Gaussian noise by 2nd value "
             "and add to first value",
             NULL, nrrdBinaryOp);
  hestOptAdd(&opt, NULL, "in1", airTypeOther, 1, 1, &in1, NULL,
             "First input.  Can be a single value or a nrrd.",
             NULL, NULL, nrrdHestIter);
  hestOptAdd(&opt, NULL, "in2", airTypeOther, 1, 1, &in2, NULL,
             "Second input.  Can be a single value or a nrrd.",
             NULL, NULL, nrrdHestIter);
  hestOptAdd(&opt, "s,seed", "seed", airTypeString, 1, 1, &seedS, "",
             "seed value for RNG for nrand, so that you "
             "can get repeatable results between runs, or, "
             "by not using this option, the RNG seeding will be "
             "based on the current time");
  hestOptAdd(&opt, "t,type", "type", airTypeOther, 1, 1, &type, "default",
             "type to convert all INPUT nrrds to, prior to "
             "doing operation, useful for doing, for instance, the difference "
             "between two unsigned char nrrds.  This will also determine "
             "output type. By default (not using this option), the types of "
             "the input nrrds are left unchanged.",
             NULL, NULL, &unrrduHestMaybeTypeCB);
  OPT_ADD_NOUT(out, "output nrrd");

  mop = airMopNew();
  airMopAdd(mop, opt, (airMopper)hestOptFree, airMopAlways);

  USAGE(_unrrdu_2opInfoL);
  PARSE();
  airMopAdd(mop, opt, (airMopper)hestParseFree, airMopAlways);

  nout = nrrdNew();
  airMopAdd(mop, nout, (airMopper)nrrdNuke, airMopAlways);

  /*
  fprintf(stderr, "%s: op = %d\n", me, op);
  fprintf(stderr, "%s: in1->left = %d, in2->left = %d\n", me, 
          (int)(in1->left), (int)(in2->left));
  */
  if (nrrdTypeDefault != type) {
    /* they wanted to convert nrrds to some other type first */
    E = 0;
    if (in1->ownNrrd) {
      if (!E) E |= nrrdConvert(ntmp=nrrdNew(), in1->ownNrrd, type);
      if (!E) nrrdIterSetOwnNrrd(in1, ntmp);
    }
    if (in2->ownNrrd) {
      if (!E) E |= nrrdConvert(ntmp=nrrdNew(), in2->ownNrrd, type);
      if (!E) nrrdIterSetOwnNrrd(in2, ntmp);
    }
    if (E) {
      airMopAdd(mop, err = biffGetDone(NRRD), airFree, airMopAlways);
      fprintf(stderr, "%s: error converting input nrrd(s):\n%s", me, err);
      airMopError(mop);
      return 1;
    }
    /* this will still leave a nrrd in the NrrdIter for nrrdIterNix()
       (called by hestParseFree() called be airMopOkay()) to clear up */
  }
  if (nrrdBinaryOpNormalRandScaleAdd == op) {
    if (airStrlen(seedS)) {
      if (1 != sscanf(seedS, "%u", &seed)) {
        fprintf(stderr, "%s: couldn't parse seed \"%s\" as uint\n", me, seedS);
        airMopError(mop);
        return 1;
      } else {
        airSrandMT(seed);
      }
    } else {
      /* got no request for specific seed */
      airSrandMT(AIR_CAST(unsigned int, airTime()));
    }
  }
  if (nrrdArithIterBinaryOp(nout, op, in1, in2)) {
    airMopAdd(mop, err = biffGetDone(NRRD), airFree, airMopAlways);
    fprintf(stderr, "%s: error doing binary operation:\n%s", me, err);
    airMopError(mop);
    return 1;
  }
  
  SAVE(out, nout, NULL);

  airMopOkay(mop);
  return 0;
}
Exemple #22
0
int
tend_mfitMain(int argc, char **argv, char *me, hestParm *hparm) {
  int pret;
  hestOpt *hopt = NULL;
  char *perr, *err;
  airArray *mop;

  Nrrd *nin, *nout, *nterr;
  char *outS, *terrS, *modS;
  int knownB0, saveB0, verbose, mlfit, typeOut;
  unsigned int maxIter, minIter, starts;
  double sigma, eps;
  const tenModel *model;
  tenExperSpec *espec;

  hestOptAdd(&hopt, "v", "verbose", airTypeInt, 1, 1, &verbose, "0",
             "verbosity level");
  hestOptAdd(&hopt, "m", "model", airTypeString, 1, 1, &modS, NULL,
             "which model to fit. Use optional \"b0+\" prefix to "
             "indicate that the B0 image should also be saved.");
  hestOptAdd(&hopt, "ns", "# starts", airTypeUInt, 1, 1, &starts, "1",
             "number of random starting points at which to initialize "
             "fitting");
  hestOptAdd(&hopt, "ml", NULL, airTypeInt, 0, 0, &mlfit, NULL,
             "do ML fitting, rather than least-squares, which also "
             "requires setting \"-sigma\"");
  hestOptAdd(&hopt, "sigma", "sigma", airTypeDouble, 1, 1, &sigma, "nan",
             "Rician noise parameter");
  hestOptAdd(&hopt, "eps", "eps", airTypeDouble, 1, 1, &eps, "0.01",
             "convergence epsilon");
  hestOptAdd(&hopt, "mini", "min iters", airTypeUInt, 1, 1, &minIter, "3",
             "minimum required # iterations for fitting.");
  hestOptAdd(&hopt, "maxi", "max iters", airTypeUInt, 1, 1, &maxIter, "100",
             "maximum allowable # iterations for fitting.");
  hestOptAdd(&hopt, "knownB0", "bool", airTypeBool, 1, 1, &knownB0, NULL,
             "Indicates if the B=0 non-diffusion-weighted reference image "
             "is known (\"true\"), or if it has to be estimated along with "
             "the other model parameters (\"false\")");
  hestOptAdd(&hopt, "t", "type", airTypeEnum, 1, 1, &typeOut, "float",
             "output type of model parameters",
             NULL, nrrdType);
  hestOptAdd(&hopt, "i", "dwi", airTypeOther, 1, 1, &nin, "-",
             "all the diffusion-weighted images in one 4D nrrd",
             NULL, NULL, nrrdHestNrrd);
  hestOptAdd(&hopt, "o", "nout", airTypeString, 1, 1, &outS, "-",
             "output tensor volume");
  hestOptAdd(&hopt, "eo", "filename", airTypeString, 1, 1, &terrS, "",
             "Giving a filename here allows you to save out the per-sample "
             "fitting error.  By default, no such error is saved.");

  mop = airMopNew();
  airMopAdd(mop, hopt, (airMopper)hestOptFree, airMopAlways);
  USAGE(_tend_mfitInfoL);
  JUSTPARSE();
  airMopAdd(mop, hopt, (airMopper)hestParseFree, airMopAlways);

  nterr = NULL;
  espec = tenExperSpecNew();
  airMopAdd(mop, espec, (airMopper)tenExperSpecNix, airMopAlways);
  nout = nrrdNew();
  airMopAdd(mop, nout, (airMopper)nrrdNuke, airMopAlways);
  if (tenModelParse(&model, &saveB0, AIR_FALSE, modS)) {
    airMopAdd(mop, err=biffGetDone(TEN), airFree, airMopAlways);
    fprintf(stderr, "%s: trouble parsing model \"%s\":\n%s\n", me, modS, err);
    airMopError(mop); return 1;
  }
  if (tenExperSpecFromKeyValueSet(espec, nin)) {
    airMopAdd(mop, err=biffGetDone(TEN), airFree, airMopAlways);
    fprintf(stderr, "%s: trouble getting exper from kvp:\n%s\n", me, err);
    airMopError(mop); return 1;
  }  
  if (tenModelSqeFit(nout, 
                     airStrlen(terrS) ? &nterr : NULL, 
                     model, espec, nin,
                     knownB0, saveB0, typeOut, 
                     minIter, maxIter, starts, eps, NULL)) {
    airMopAdd(mop, err=biffGetDone(TEN), airFree, airMopAlways);
    fprintf(stderr, "%s: trouble fitting:\n%s\n", me, err);
    airMopError(mop); return 1;
  }  

  if (nrrdSave(outS, nout, NULL)
      || (airStrlen(terrS) && nrrdSave(terrS, nterr, NULL))) {
    airMopAdd(mop, err=biffGetDone(NRRD), airFree, airMopAlways);
    fprintf(stderr, "%s: trouble writing output:\n%s\n", me, err);
    airMopError(mop); return 1;
  }

  airMopOkay(mop);
  return 0;
}
Exemple #23
0
int
unrrdu_fftMain(int argc, const char **argv, const char *me,
               hestParm *hparm) {
  hestOpt *opt = NULL;
  char *out, *err;
  Nrrd *nin, *_nin, *nout;
  int pret;
  airArray *mop;

  int sign, rigor, rescale, realInput;
  char *wispath;
  FILE *fwise;
  unsigned int *axes, axesLen;

  hestOptAdd(&opt, NULL, "dir", airTypeEnum, 1, 1, &sign, NULL,
             "forward (\"forw\", \"f\") or backward/inverse "
             "(\"back\", \"b\") transform ", NULL, direction_enm);
  hestOptAdd(&opt, "a,axes", "ax0", airTypeUInt, 1, -1, &axes, NULL,
             "the one or more axes that should be transformed", &axesLen);
  hestOptAdd(&opt, "pr,planrigor", "pr", airTypeEnum, 1, 1, &rigor, "est",
             "rigor with which fftw plan is constructed. Options include:\n "
             "\b\bo \"e\", \"est\", \"estimate\": only an estimate\n "
             "\b\bo \"m\", \"meas\", \"measure\": standard amount of "
             "measurements of system properties\n "
             "\b\bo \"p\", \"pat\", \"patient\": slower, more measurements\n "
             "\b\bo \"x\", \"ex\", \"exhaustive\": slowest, most measurements",
             NULL, nrrdFFTWPlanRigor);
  hestOptAdd(&opt, "r,rescale", "bool", airTypeBool, 1, 1, &rescale, "true",
             "scale fftw output (by sqrt(1/N)) so that forward and backward "
             "transforms will get back to original values");
  hestOptAdd(&opt, "w,wisdom", "filename", airTypeString, 1, 1, &wispath, "",
             "A filename here is used to read in fftw wisdom (if the file "
             "exists already), and is used to save out updated wisdom "
             "after the transform.  By default (not using this option), "
             "no wisdom is read or saved. Note: no wisdom is gained "
             "(that is, learned by FFTW) with planning rigor \"estimate\".");
  OPT_ADD_NIN(_nin, "input nrrd");
  hestOptAdd(&opt, "ri,realinput", NULL, airTypeInt, 0, 0, &realInput, NULL,
             "input is real-valued, so insert new length-2 axis 0 "
             "and set complex component to 0.0.  Axes to transform "
             "(indicated by \"-a\") will be incremented accordingly.");
  OPT_ADD_NOUT(out, "output nrrd");

  mop = airMopNew();
  airMopAdd(mop, opt, (airMopper)hestOptFree, airMopAlways);

  if (nrrdFFTWEnabled) {
    USAGE(_unrrdu_fftInfoL_yes);
  } else {
    USAGE(_unrrdu_fftInfoL_no);
  }
  PARSE();
  airMopAdd(mop, opt, (airMopper)hestParseFree, airMopAlways);

  nout = nrrdNew();
  airMopAdd(mop, nout, (airMopper)nrrdNuke, airMopAlways);

  if (realInput) {
    ptrdiff_t minPad[NRRD_DIM_MAX], maxPad[NRRD_DIM_MAX];
    unsigned int axi;
    Nrrd *ntmp;
    ntmp = nrrdNew();
    airMopAdd(mop, ntmp, (airMopper)nrrdNuke, airMopAlways);
    if (nrrdAxesInsert(ntmp, _nin, 0)) {
      airMopAdd(mop, err = biffGetDone(NRRD), airFree, airMopAlways);
      fprintf(stderr, "%s: error creating complex axis:\n%s", me, err);
      airMopError(mop);
      return 1;
    }
    nin = nrrdNew();
    airMopAdd(mop, nin, (airMopper)nrrdNuke, airMopAlways);
    minPad[0] = 0;
    maxPad[0] = 1;
    for (axi=1; axi<ntmp->dim; axi++) {
      minPad[axi] = 0;
      maxPad[axi] = AIR_CAST(ptrdiff_t, ntmp->axis[axi].size-1);
    }
    if (nrrdPad_nva(nin, ntmp, minPad, maxPad, nrrdBoundaryPad, 0.0)) {
      airMopAdd(mop, err = biffGetDone(NRRD), airFree, airMopAlways);
      fprintf(stderr, "%s: error padding out complex axis:\n%s", me, err);
      airMopError(mop);
      return 1;
    }
    /* increment specified axes to transform */
    for (axi=0; axi<axesLen; axi++) {
      axes[axi]++;
    }
    /* ntmp is really done with, we can free up the space now; this
       is one of the rare times we want airMopSub */
    airMopSub(mop, ntmp, (airMopper)nrrdNuke);
    nrrdNuke(ntmp);
  } else {
    /* input is apparently already complex */
    nin = _nin;
  }

  if (airStrlen(wispath) && nrrdFFTWEnabled) {
    fwise = fopen(wispath, "r");
    if (fwise) {
      if (nrrdFFTWWisdomRead(fwise)) {
        airMopAdd(mop, err = biffGetDone(NRRD), airFree, airMopAlways);
        fprintf(stderr, "%s: error with fft wisdom:\n%s", me, err);
        airMopError(mop);
        return 1;
      }
      fclose(fwise);
    } else {
      fprintf(stderr, "%s: (\"%s\" couldn't be opened, will try to save "
              "wisdom afterwards)", me, wispath);
    }
  }

  if (nrrdFFT(nout, nin, axes, axesLen, sign, rescale, rigor)) {
    airMopAdd(mop, err = biffGetDone(NRRD), airFree, airMopAlways);
    fprintf(stderr, "%s: error with fft:\n%s", me, err);
    airMopError(mop);
    return 1;
  }

  if (airStrlen(wispath) && nrrdFFTWEnabled) {
    if (!(fwise = fopen(wispath, "w"))) {
      fprintf(stderr, "%s: couldn't open %s for writing: %s\n",
              me, wispath, strerror(errno));
      airMopError(mop);
      return 1;
    }
    if (nrrdFFTWWisdomWrite(fwise)) {
      airMopAdd(mop, err = biffGetDone(NRRD), airFree, airMopAlways);
      fprintf(stderr, "%s: error with fft wisdom:\n%s", me, err);
      airMopError(mop);
      return 1;
    }
    fclose(fwise);
  }

  SAVE(out, nout, NULL);

  airMopOkay(mop);
  return 0;
}
Exemple #24
0
int
tend_msimMain(int argc, const char **argv, const char *me,
              hestParm *hparm) {
  int pret;
  hestOpt *hopt = NULL;
  char *perr, *err;
  airArray *mop;

  tenExperSpec *espec;
  const tenModel *model;
  int E, seed, keyValueSet, outType, plusB0, insertB0;
  Nrrd *nin, *nT2, *_ngrad, *ngrad, *nout;
  char *outS, *modS;
  double bval, sigma;

  /* maybe this can go in tend.c, but for some reason its explicitly
     set to AIR_FALSE there */
  hparm->elideSingleOtherDefault = AIR_TRUE;

  hestOptAdd(&hopt, "sigma", "sigma", airTypeDouble, 1, 1, &sigma, "0.0",
             "Gaussian/Rician noise parameter");
  hestOptAdd(&hopt, "seed", "seed", airTypeInt, 1, 1, &seed, "42",
             "seed value for RNG which creates noise");
  hestOptAdd(&hopt, "g", "grad list", airTypeOther, 1, 1, &_ngrad, NULL,
             "gradient list, one row per diffusion-weighted image",
             NULL, NULL, nrrdHestNrrd);
  hestOptAdd(&hopt, "b0", "b0 image", airTypeOther, 1, 1, &nT2, "",
             "reference non-diffusion-weighted (\"B0\") image, which "
             "may be needed if it isn't part of give model param image",
             NULL, NULL, nrrdHestNrrd);
  hestOptAdd(&hopt, "i", "model image", airTypeOther, 1, 1, &nin, "-",
             "input model image", NULL, NULL, nrrdHestNrrd);
  hestOptAdd(&hopt, "m", "model", airTypeString, 1, 1, &modS, NULL,
             "model with which to simulate DWIs, which must be specified if "
             "it is not indicated by the first axis in input model image.");
  hestOptAdd(&hopt, "ib0", "bool", airTypeBool, 1, 1, &insertB0, "false",
             "insert a non-DW B0 image at the beginning of the experiment "
             "specification (useful if the given gradient list doesn't "
             "already have one) and hence also insert a B0 image at the "
             "beginning of the output simulated DWIs");
  hestOptAdd(&hopt, "b", "b", airTypeDouble, 1, 1, &bval, "1000",
             "b value for simulated scan");
  hestOptAdd(&hopt, "kvp", "bool", airTypeBool, 1, 1, &keyValueSet, "true",
             "generate key/value pairs in the NRRD header corresponding "
             "to the input b-value and gradients.");
  hestOptAdd(&hopt, "t", "type", airTypeEnum, 1, 1, &outType, "float",
             "output type of DWIs", NULL, nrrdType);
  hestOptAdd(&hopt, "o", "nout", airTypeString, 1, 1, &outS, "-",
             "output dwis");

  mop = airMopNew();
  airMopAdd(mop, hopt, (airMopper)hestOptFree, airMopAlways);
  USAGE(_tend_msimInfoL);
  PARSE();
  airMopAdd(mop, hopt, (airMopper)hestParseFree, airMopAlways);

  nout = nrrdNew();
  airMopAdd(mop, nout, (airMopper)nrrdNuke, airMopAlways);
  espec = tenExperSpecNew();
  airMopAdd(mop, espec, (airMopper)tenExperSpecNix, airMopAlways);

  airSrandMT(seed);
  if (nrrdTypeDouble == _ngrad->type) {
    ngrad = _ngrad;
  } else {
    ngrad = nrrdNew();
    airMopAdd(mop, ngrad, (airMopper)nrrdNuke, airMopAlways);
    if (nrrdConvert(ngrad, _ngrad, nrrdTypeDouble)) {
      airMopAdd(mop, err=biffGetDone(NRRD), airFree, airMopAlways);
      fprintf(stderr, "%s: trouble converting grads to %s:\n%s\n", me,
              airEnumStr(nrrdType, nrrdTypeDouble), err);
      airMopError(mop); return 1;
    }
  }
  plusB0 = AIR_FALSE;
  if (airStrlen(modS)) {
    if (tenModelParse(&model, &plusB0, AIR_FALSE, modS)) {
      airMopAdd(mop, err=biffGetDone(TEN), airFree, airMopAlways);
      fprintf(stderr, "%s: trouble parsing model \"%s\":\n%s\n",
              me, modS, err);
      airMopError(mop); return 1;
    }
  } else if (tenModelFromAxisLearnPossible(nin->axis + 0)) {
    if (tenModelFromAxisLearn(&model, &plusB0, nin->axis + 0)) {
      airMopAdd(mop, err=biffGetDone(TEN), airFree, airMopAlways);
      fprintf(stderr, "%s: trouble parsing model frmo axis 0 of nin:\n%s\n",
              me, err);
      airMopError(mop); return 1;
    }
  } else {
    fprintf(stderr, "%s: need model specified either via \"-m\" or input "
            "model image axis 0\n", me);
    airMopError(mop); return 1;
  }
  /* we have learned plusB0, but we don't actually need it;
     either: it describes the given model param image
     (which is courteous but not necessary since the logic inside
     tenModeSimulate will see this),
     or: it is trying to say something about including B0 amongst
     model parameters (which isn't actually meaningful in the
     context of simulated DWIs */
  E = 0;
  if (!E) E |= tenGradientCheck(ngrad, nrrdTypeDouble, 1);
  if (!E) E |= tenExperSpecGradSingleBValSet(espec, insertB0, bval,
                                             AIR_CAST(const double *,
                                                      ngrad->data),
                                             ngrad->axis[1].size);
  if (!E) E |= tenModelSimulate(nout, outType, espec,
                                model, nT2, nin, keyValueSet);
  if (E) {
    airMopAdd(mop, err=biffGetDone(TEN), airFree, airMopAlways);
    fprintf(stderr, "%s: trouble:\n%s\n", me, err);
    airMopError(mop); return 1;
  }
  if (nrrdSave(outS, nout, NULL)) {
    airMopAdd(mop, err=biffGetDone(NRRD), airFree, airMopAlways);
    fprintf(stderr, "%s: trouble writing:\n%s\n", me, err);
    airMopError(mop); return 1;
  }

  airMopOkay(mop);
  return 0;
}
Exemple #25
0
/*
** this is responsible for the header-relative path processing
**
** NOTE: if the filename is "-", then because it does not start with '/',
** it would normally be prefixed by nio->path, so it needs special handling
**
** NOTE: this should work okay with nio->headerStringRead, I think ...
*/
int
nrrdIoStateDataFileIterNext(FILE **fileP, NrrdIoState *nio, int reading) {
  char me[]="nrrdIoStateDataFileIterNext", *err;
  char *fname=NULL;
  int ii, needPath;
  unsigned int num, fi;
  size_t maxl;
  airArray *mop;

  mop = airMopNew();
  airMopAdd(mop, (void*)fileP, (airMopper)airSetNull, airMopOnError);

  if (!fileP) {
    if ((err = (char*)malloc(BIFF_STRLEN))) {
      sprintf(err, "%s: got NULL pointer", me);
      biffAdd(NRRD, err); free(err);
    }
    airMopError(mop); return 1;
  }
  if (!_nrrdDataFNNumber(nio)) {
    if ((err = (char*)malloc(BIFF_STRLEN))) {
      sprintf(err, "%s: there appear to be zero datafiles!", me);
      biffAdd(NRRD, err); free(err);
    }
    airMopError(mop); return 1;
  }

  nio->dataFNIndex++;
  if (nio->dataFNIndex >= (int)_nrrdDataFNNumber(nio)) {
    /* there is no next data file, but we don't make that an error */
    nio->dataFNIndex = _nrrdDataFNNumber(nio);
    airMopOkay(mop);
    *fileP = NULL;
    return 0;
  }

  /* HEY: some of this error checking is done far more often than needed */
  if (nio->dataFNFormat || nio->dataFNArr->len) {
    needPath = AIR_FALSE;
    maxl = 0;
    if (nio->dataFNFormat) {
      needPath = _NEED_PATH(nio->dataFNFormat);
      /* assuming 10-digit integers is plenty big */
      maxl = 10 + strlen(nio->dataFNFormat);
    } else {
      for (fi=0; fi<nio->dataFNArr->len; fi++) {
        needPath |= _NEED_PATH(nio->dataFN[fi]);
        maxl = AIR_MAX(maxl, strlen(nio->dataFN[fi]));
      }
    }
    if (needPath && !airStrlen(nio->path)) {
      if ((err = (char*)malloc(BIFF_STRLEN))) {
        sprintf(err, "%s: need nio->path for header-relative datafiles", me);
        biffAdd(NRRD, err); free(err);
      }
      airMopError(mop); return 1;
    }
    fname = (char*)malloc(airStrlen(nio->path) + strlen("/") + maxl + 1);
    if (!fname) {
      if ((err = (char*)malloc(BIFF_STRLEN))) {
        sprintf(err, "%s: couldn't allocate filename buffer", me);
        biffAdd(NRRD, err); free(err);
      }
      airMopError(mop); return 1;
    }
    airMopAdd(mop, fname, airFree, airMopAlways);
  }

  if (nio->dataFNFormat) {
    /* ---------------------------------------------------------- */
    /* --------- base.%d <min> <max> <step> [<dim>] ------------- */
    /* ---------------------------------------------------------- */
    num = 0;
    for (ii = nio->dataFNMin; 
         ((nio->dataFNStep > 0 && ii <= nio->dataFNMax)
          || (nio->dataFNStep < 0 && ii >= nio->dataFNMax));
         ii += nio->dataFNStep) {
      if ((int)num == nio->dataFNIndex) {  /* HEY scrutinize cast */
        break;
      }
      num += 1;
    }
    if (_NEED_PATH(nio->dataFNFormat)) {
      strcpy(fname, nio->path);
      strcat(fname, "/");
      sprintf(fname + strlen(nio->path) + strlen("/"), nio->dataFNFormat, ii);
    } else {
      sprintf(fname, nio->dataFNFormat, ii);
    }
  } else if (nio->dataFNArr->len) {
    /* ---------------------------------------------------------- */
    /* ------------------- LIST or single ----------------------- */
    /* ---------------------------------------------------------- */
    if (_NEED_PATH(nio->dataFN[nio->dataFNIndex])) {
      sprintf(fname, "%s/%s", nio->path, nio->dataFN[nio->dataFNIndex]);
    } else {
      strcpy(fname, nio->dataFN[nio->dataFNIndex]);
    }
  }
  /* else data file is attached */
  
  if (nio->dataFNFormat || nio->dataFNArr->len) {
    *fileP = airFopen(fname, reading ? stdin : stdout, reading ? "rb" : "wb");
    if (!(*fileP)) {
      if ((err = (char*)malloc(strlen(fname) + BIFF_STRLEN))) {
        sprintf(err, "%s: couldn't open \"%s\" (data file %d of %d) for %s",
                me, fname, nio->dataFNIndex+1, (int)_nrrdDataFNNumber(nio),
                reading ? "reading" : "writing");
        biffAdd(NRRD, err); free(err);
      }
      airMopError(mop); return 1;
    }
  } else {
    /* data file is attached */
    if (nio->headerStringRead) {
      /* except we were never reading from a file to begin with, but this
         isn't an error */
      *fileP = NULL;
    } else {
      *fileP = nio->headerFile;
    }
  }
  
  airMopOkay(mop);
  return 0;
}
Exemple #26
0
void
undosConvert(char *me, char *name, int reverse, int mac,
             int quiet, int noAction) {
  airArray *mop;
  FILE *fin, *fout;
  char *data=NULL;
  airArray *dataArr;
  unsigned int ci;
  int car, numBad, willConvert;
  _undosU uu;

  mop = airMopNew();
  if (!airStrlen(name)) {
    fprintf(stderr, "%s: empty filename\n", me);
    airMopError(mop); return;
  }

  /* -------------------------------------------------------- */
  /* open input file  */
  fin = airFopen(name, stdin, "rb");
  if (!fin) {
    if (!quiet) {
      fprintf(stderr, "%s: couldn't open \"%s\" for reading: \"%s\"\n", 
              me, name, strerror(errno));
    }
    airMopError(mop); return;
  }
  airMopAdd(mop, fin, (airMopper)airFclose, airMopOnError);

  /* -------------------------------------------------------- */
  /* create buffer */
  uu.c = &data;
  dataArr = airArrayNew(uu.v, NULL, sizeof(char), AIR_STRLEN_HUGE);
  if (!dataArr) {
    if (!quiet) {
      fprintf(stderr, "%s: internal allocation error #1\n", me);
    }
    airMopError(mop); return;
  }
  airMopAdd(mop, dataArr, (airMopper)airArrayNuke, airMopAlways);

  /* -------------------------------------------------------- */
  /* read input file, testing for binary-ness along the way */
  numBad = 0;
  car = getc(fin);
  if (EOF == car) {
    if (!quiet) {
      fprintf(stderr, "%s: \"%s\" is empty, skipping ...\n", me, name);
    }
    airMopError(mop); return;
  }
  do {
    ci = airArrayLenIncr(dataArr, 1);
    if (!dataArr->data) {
      if (!quiet) {
        fprintf(stderr, "%s: internal allocation error #2\n", me);
      }
      airMopError(mop); return;
    }
    data[ci] = car;
    numBad += !(isprint(data[ci]) || isspace(data[ci]));
    car = getc(fin);
  } while (EOF != car && BAD_PERC > 100.0*numBad/dataArr->len);
  if (EOF != car) {
    if (!quiet) {
      fprintf(stderr, "%s: more than %g%% of \"%s\" is non-printing, "
              "skipping ...\n", me, BAD_PERC, name);
    }
    airMopError(mop); return;    
  }
  fin = airFclose(fin);

  /* -------------------------------------------------------- */
  /* see if we really need to do anything */
  willConvert = AIR_FALSE;
  if (!strcmp("-", name)) {
    willConvert = AIR_TRUE;
  } else if (reverse) {
    for (ci=0; ci<dataArr->len; ci++) {
      if (mac) {
        if (CR == data[ci]) {
          willConvert = AIR_TRUE;
          break;
        }
      } else {
        if (CR == data[ci] && (ci && LF != data[ci-1])) {
          willConvert = AIR_TRUE;
          break;
        }
      }
    }
  } else {
    for (ci=0; ci<dataArr->len; ci++) {
      if (mac) {
        if (LF == data[ci]) {
          willConvert = AIR_TRUE;
          break;
        }
      } else {
        if (LF == data[ci] && (ci+1<dataArr->len && CR == data[ci+1])) {
          willConvert = AIR_TRUE;
          break;
        }
      }
    }
  }
  if (!willConvert) {
    /* no, we don't need to do anything; quietly quit */
    airMopOkay(mop);
    return;
  } else {
    if (!quiet) {
      fprintf(stderr, "%s: %s \"%s\" %s %s ... \n", me, 
              noAction ? "would convert" : "converting",
              name,
              reverse ? "to" : "from",
              mac ? "MAC" : "DOS");
    }
  }
  if (noAction) {
    /* just joking, we won't actually write anything.
       (yes, even if input was stdin) */
    airMopOkay(mop);
    return;
  }

  /* -------------------------------------------------------- */
  /* open output file */
  fout = airFopen(name, stdout, "wb");
  if (!fout) {
    if (!quiet) {
      fprintf(stderr, "%s: couldn't open \"%s\" for writing: \"%s\"\n", 
              me, name, strerror(errno));
    }
    airMopError(mop); return;
  }
  airMopAdd(mop, fout, (airMopper)airFclose, airMopOnError);

  /* -------------------------------------------------------- */
  /* write output file */
  car = 'a';
  if (reverse) {
    for (ci=0; ci<dataArr->len; ci++) {
      if ((mac && CR == data[ci])
          || (CR == data[ci] && (ci && LF != data[ci-1]))) {
        car = putc(LF, fout);
        if (!mac && EOF != car) {
          car = putc(CR, fout);
        }
      } else {
        car = putc(data[ci], fout);
      }
    }
  } else {
    for (ci=0; EOF != car && ci<dataArr->len; ci++) {
      if ((mac && LF == data[ci])
          || (LF == data[ci] && (ci+1<dataArr->len && CR == data[ci+1]))) {
        car = putc(CR, fout);
        ci += !mac;
      } else {
        car = putc(data[ci], fout);
      }
    }
  }
  if (EOF == car) {
    if (!quiet) {
      fprintf(stderr, "%s: ERROR writing \"%s\" possible data loss !!! "
              "(sorry)\n", me, name);
    }
  }
  fout = airFclose(fout);

  airMopOkay(mop);
  return;
}
Exemple #27
0
/*
** _nrrdSprintFieldInfo
**
** this prints "<prefix><field>: <info>" into *strP (after allocating it for
** big enough, usually with a stupidly big margin of error), in a form
** suitable to be written to NRRD or other image headers.  This will always
** print something (for valid inputs), even stupid <info>s like
** "(unknown endian)".  It is up to the caller to decide which fields
** are worth writing, via _nrrdFieldInteresting().
**
** NOTE: some of these fields make sense in non-NRRD files (e.g. all
** the per-axis information), but many only make sense in NRRD files.
** This is just one example of NRRD-format-specific stuff that is not
** in formatNRRD.c
*/
void
_nrrdSprintFieldInfo(char **strP, char *prefix,
                     const Nrrd *nrrd, NrrdIoState *nio, int field)
{
    char me[]="_nrrdSprintFieldInfo", buff[AIR_STRLEN_MED], *fnb;
    double colvec[NRRD_SPACE_DIM_MAX];
    const char *fs;
    unsigned int ii, dd,
             uintStrlen = 11,
             size_tStrlen = 33,
             doubleStrlen = 513;
    int fslen, fdlen, endi, maxl;

    if (!( strP && prefix
            && nrrd
            && AIR_IN_CL(1, nrrd->dim, NRRD_DIM_MAX)
            && AIR_IN_OP(nrrdField_unknown, field, nrrdField_last) ))
    {
        return;
    }
    if (!_nrrdFieldInteresting(nrrd, nio, field))
    {
        *strP = airStrdup("");
    }

    fs = airEnumStr(nrrdField, field);
    fslen = strlen(prefix) + strlen(fs) + strlen(": ") + 1;
    switch (field)
    {
    case nrrdField_comment:
    case nrrdField_keyvalue:
        fprintf(stderr, "%s: CONFUSION: why are you calling me on \"%s\"?\n", me,
                airEnumStr(nrrdField, nrrdField_comment));
        *strP = airStrdup("");
        break;
    case nrrdField_content:
        airOneLinify(nrrd->content);
        *strP = (char *)calloc(fslen + strlen(nrrd->content), sizeof(char));
        sprintf(*strP, "%s%s: %s", prefix, fs, nrrd->content);
        break;
    case nrrdField_number:
        *strP = (char *)calloc(fslen + size_tStrlen, sizeof(char));
        sprintf(*strP, "%s%s: " _AIR_SIZE_T_CNV, prefix, fs,
                nrrdElementNumber(nrrd));
        break;
    case nrrdField_type:
        *strP = (char *)calloc(fslen + strlen(airEnumStr(nrrdType, nrrd->type)),
                               sizeof(char));
        sprintf(*strP, "%s%s: %s", prefix, fs, airEnumStr(nrrdType, nrrd->type));
        break;
    case nrrdField_block_size:
        *strP = (char *)calloc(fslen + size_tStrlen, sizeof(char));
        sprintf(*strP, "%s%s: " _AIR_SIZE_T_CNV, prefix, fs, nrrd->blockSize);
        break;
    case nrrdField_dimension:
        *strP = (char *)calloc(fslen + uintStrlen, sizeof(char));
        sprintf(*strP, "%s%s: %d", prefix, fs, nrrd->dim);
        break;
    case nrrdField_space:
        *strP = (char *)calloc(fslen + strlen(airEnumStr(nrrdSpace, nrrd->space)),
                               sizeof(char));
        sprintf(*strP, "%s%s: %s", prefix, fs, airEnumStr(nrrdSpace, nrrd->space));
        break;
    case nrrdField_space_dimension:
        *strP = (char *)calloc(fslen + uintStrlen, sizeof(char));
        sprintf(*strP, "%s%s: %d", prefix, fs, nrrd->spaceDim);
        break;
    /* ---- begin per-axis fields ---- */
    case nrrdField_sizes:
        *strP = (char *)calloc(fslen + nrrd->dim*(size_tStrlen + 1), sizeof(char));
        sprintf(*strP, "%s%s:", prefix, fs);
        for (ii=0; ii<nrrd->dim; ii++)
        {
            sprintf(buff, " " _AIR_SIZE_T_CNV, nrrd->axis[ii].size);
            strcat(*strP, buff);
        }
        break;
    case nrrdField_spacings:
        *strP = (char *)calloc(fslen + nrrd->dim*(doubleStrlen + 1), sizeof(char));
        sprintf(*strP, "%s%s:", prefix, fs);
        for (ii=0; ii<nrrd->dim; ii++)
        {
            airSinglePrintf(NULL, buff, " %g", nrrd->axis[ii].spacing);
            strcat(*strP, buff);
        }
        break;
    case nrrdField_thicknesses:
        *strP = (char *)calloc(fslen + nrrd->dim*(doubleStrlen + 1), sizeof(char));
        sprintf(*strP, "%s%s:", prefix, fs);
        for (ii=0; ii<nrrd->dim; ii++)
        {
            airSinglePrintf(NULL, buff, " %g", nrrd->axis[ii].thickness);
            strcat(*strP, buff);
        }
        break;
    case nrrdField_axis_mins:
        *strP = (char *)calloc(fslen + nrrd->dim*(doubleStrlen + 1), sizeof(char));
        sprintf(*strP, "%s%s:", prefix, fs);
        for (ii=0; ii<nrrd->dim; ii++)
        {
            airSinglePrintf(NULL, buff, " %g", nrrd->axis[ii].min);
            strcat(*strP, buff);
        }
        break;
    case nrrdField_axis_maxs:
        *strP = (char *)calloc(fslen + nrrd->dim*(doubleStrlen + 1), sizeof(char));
        sprintf(*strP, "%s%s:", prefix, fs);
        for (ii=0; ii<nrrd->dim; ii++)
        {
            airSinglePrintf(NULL, buff, " %g", nrrd->axis[ii].max);
            strcat(*strP, buff);
        }
        break;
    case nrrdField_space_directions:
        *strP = (char *)calloc(fslen +
                               nrrd->dim*nrrd->spaceDim*(doubleStrlen
                                       + strlen("(,) ")),
                               sizeof(char));
        sprintf(*strP, "%s%s: ", prefix, fs);
        for (ii=0; ii<nrrd->dim; ii++)
        {
            _nrrdStrcatSpaceVector(*strP, nrrd->spaceDim,
                                   nrrd->axis[ii].spaceDirection);
            if (ii < nrrd->dim-1)
            {
                strcat(*strP, " ");
            }
        }
        break;
    case nrrdField_centers:
        fdlen = 0;
        for (ii=0; ii<nrrd->dim; ii++)
        {
            fdlen += 1 + airStrlen(nrrd->axis[ii].center
                                   ? airEnumStr(nrrdCenter, nrrd->axis[ii].center)
                                   : NRRD_UNKNOWN);
        }
        *strP = (char *)calloc(fslen + fdlen, sizeof(char));
        sprintf(*strP, "%s%s:", prefix, fs);
        for (ii=0; ii<nrrd->dim; ii++)
        {
            sprintf(buff, " %s",
                    (nrrd->axis[ii].center
                     ? airEnumStr(nrrdCenter, nrrd->axis[ii].center)
                     : NRRD_UNKNOWN));
            strcat(*strP, buff);
        }
        break;
    case nrrdField_kinds:
        fdlen = 0;
        for (ii=0; ii<nrrd->dim; ii++)
        {
            fdlen += 1 + airStrlen(nrrd->axis[ii].kind
                                   ? airEnumStr(nrrdKind, nrrd->axis[ii].kind)
                                   : NRRD_UNKNOWN);
        }
        *strP = (char *)calloc(fslen + fdlen, sizeof(char));
        sprintf(*strP, "%s%s:", prefix, fs);
        for (ii=0; ii<nrrd->dim; ii++)
        {
            sprintf(buff, " %s",
                    (nrrd->axis[ii].kind
                     ? airEnumStr(nrrdKind, nrrd->axis[ii].kind)
                     : NRRD_UNKNOWN));
            strcat(*strP, buff);
        }
        break;
    case nrrdField_labels:
        fdlen = 0;
        for (ii=0; ii<nrrd->dim; ii++)
        {
            fdlen += airStrlen(nrrd->axis[ii].label) + 4;
        }
        *strP = (char *)calloc(fslen + fdlen, sizeof(char));
        sprintf(*strP, "%s%s:", prefix, fs);
        for (ii=0; ii<nrrd->dim; ii++)
        {
            strcat(*strP, " \"");
            if (airStrlen(nrrd->axis[ii].label))
            {
                strcat(*strP, nrrd->axis[ii].label);
            }
            strcat(*strP, "\"");
        }
        break;
    case nrrdField_units:
        fdlen = 0;
        for (ii=0; ii<nrrd->dim; ii++)
        {
            fdlen += airStrlen(nrrd->axis[ii].units) + 4;
        }
        *strP = (char *)calloc(fslen + fdlen, sizeof(char));
        sprintf(*strP, "%s%s:", prefix, fs);
        for (ii=0; ii<nrrd->dim; ii++)
        {
            strcat(*strP, " \"");
            if (airStrlen(nrrd->axis[ii].units))
            {
                strcat(*strP, nrrd->axis[ii].units);
            }
            strcat(*strP, "\"");
        }
        break;
    /* ---- end per-axis fields ---- */
    case nrrdField_min:
    case nrrdField_max:
        /* we're basically a no-op, now that these fields became meaningless */
        *strP = (char *)calloc(fslen + doubleStrlen, sizeof(char));
        sprintf(*strP, "%s%s: 0.0", prefix, fs);
        strcat(*strP, buff);
        break;
    case nrrdField_old_min:
        *strP = (char *)calloc(fslen + doubleStrlen, sizeof(char));
        sprintf(*strP, "%s%s: ", prefix, fs);
        airSinglePrintf(NULL, buff, "%g", nrrd->oldMin);
        strcat(*strP, buff);
        break;
    case nrrdField_old_max:
        *strP = (char *)calloc(fslen + doubleStrlen, sizeof(char));
        sprintf(*strP, "%s%s: ", prefix, fs);
        airSinglePrintf(NULL, buff, "%g", nrrd->oldMax);
        strcat(*strP, buff);
        break;
    case nrrdField_endian:
        if (airEndianUnknown != nio->endian)
        {
            /* we know a specific endianness because either it was recorded as
               part of "unu make -h", or it was set (and data was possibly
               altered) as part of "unu save" */
            endi = nio->endian;
        }
        else
        {
            /* we record our current architecture's endian because we're
               going to writing out data */
            endi = AIR_ENDIAN;
        }
        *strP = (char *)calloc(fslen + strlen(airEnumStr(airEndian, endi)),
                               sizeof(char));
        sprintf(*strP, "%s%s: %s", prefix, fs, airEnumStr(airEndian, endi));
        break;
    case nrrdField_encoding:
        *strP = (char *)calloc(fslen + strlen(nio->encoding->name),
                               sizeof(char));
        sprintf(*strP, "%s%s: %s", prefix, fs, nio->encoding->name);
        break;
    case nrrdField_line_skip:
        *strP = (char *)calloc(fslen + uintStrlen, sizeof(char));
        sprintf(*strP, "%s%s: %d", prefix, fs, nio->lineSkip);
        break;
    case nrrdField_byte_skip:
        *strP = (char *)calloc(fslen + uintStrlen, sizeof(char));
        sprintf(*strP, "%s%s: %d", prefix, fs, nio->byteSkip);
        break;
    case nrrdField_sample_units:
        airOneLinify(nrrd->sampleUnits);
        *strP = (char *)calloc(fslen + strlen(nrrd->sampleUnits), sizeof(char));
        sprintf(*strP, "%s%s: \"%s\"", prefix, fs, nrrd->sampleUnits);
        break;
    case nrrdField_space_units:
        fdlen = 0;
        for (ii=0; ii<nrrd->spaceDim; ii++)
        {
            fdlen += airStrlen(nrrd->spaceUnits[ii]) + 4;
        }
        *strP = (char *)calloc(fslen + fdlen, sizeof(char));
        sprintf(*strP, "%s%s:", prefix, fs);
        for (ii=0; ii<nrrd->spaceDim; ii++)
        {
            strcat(*strP, " \"");
            if (airStrlen(nrrd->spaceUnits[ii]))
            {
                strcat(*strP, nrrd->spaceUnits[ii]);
            }
            strcat(*strP, "\"");
        }
        break;
    case nrrdField_space_origin:
        *strP = (char *)calloc(fslen + nrrd->spaceDim*(doubleStrlen
                               + strlen("(,) ")),
                               sizeof(char));
        sprintf(*strP, "%s%s: ", prefix, fs);
        _nrrdStrcatSpaceVector(*strP, nrrd->spaceDim, nrrd->spaceOrigin);
        break;
    case nrrdField_measurement_frame:
        *strP = (char *)calloc(fslen + (nrrd->spaceDim*
                                        nrrd->spaceDim*(doubleStrlen
                                                + strlen("(,) "))),
                               sizeof(char));
        sprintf(*strP, "%s%s: ", prefix, fs);
        for (dd=0; dd<nrrd->spaceDim; dd++)
        {
            for (ii=0; ii<nrrd->spaceDim; ii++)
            {
                colvec[ii] = nrrd->measurementFrame[dd][ii];
            }
            _nrrdStrcatSpaceVector(*strP, nrrd->spaceDim, colvec);
            if (dd < nrrd->spaceDim-1)
            {
                strcat(*strP, " ");
            }
        }
        break;
    case nrrdField_data_file:
        /* NOTE: this comes last (nrrdField_data_file is the highest-valued
           member of the nrrdField* enum) because the "LIST" form of the
           data file specification requires that the following lines be
           the filenames */
        /* error checking elsewhere: assumes there is data file info */
        if (nio->dataFNFormat)
        {
            *strP = (char *)calloc(fslen + strlen(nio->dataFNFormat) + 4*uintStrlen,
                                   sizeof(char));
            if (nio->dataFileDim == nrrd->dim-1)
            {
                sprintf(*strP, "%s%s: %s %d %d %d", prefix, fs, nio->dataFNFormat,
                        nio->dataFNMin, nio->dataFNMax, nio->dataFNStep);
            }
            else
            {
                sprintf(*strP, "%s%s: %s %d %d %d %d", prefix, fs, nio->dataFNFormat,
                        nio->dataFNMin, nio->dataFNMax, nio->dataFNStep,
                        nio->dataFileDim);
            }
        }
        else if (nio->dataFNArr->len > 1)
        {
            maxl = 0;
            for (ii=0; ii<nio->dataFNArr->len; ii++)
            {
                maxl = AIR_MAX(maxl, (int)strlen(nio->dataFN[ii]));
            }
            *strP = (char *)calloc(fslen + strlen(NRRD_LIST_FLAG)
                                   + uintStrlen + nio->dataFNArr->len * (maxl + 1),
                                   sizeof(char));
            fnb = (char *)calloc(fslen + strlen(NRRD_LIST_FLAG)
                                 + uintStrlen + maxl + 1,
                                 sizeof(char));
            if (nio->dataFileDim == nrrd->dim-1)
            {
                sprintf(*strP, "%s%s: LIST\n", prefix, fs);
            }
            else
            {
                sprintf(*strP, "%s%s: LIST %d\n", prefix, fs, nio->dataFileDim);
            }
            for (ii=0; ii<nio->dataFNArr->len; ii++)
            {
                sprintf(fnb, "%s%s", nio->dataFN[ii],
                        ii<nio->dataFNArr->len-1 ? "\n" : "");
                strcat(*strP, fnb);
            }
            free(fnb);
        }
        else
        {
            /* there is some ambiguity between a "LIST" of length one,
               and a single explicit data filename, but that's harmless */
            *strP = (char *)calloc(fslen + strlen("./")
                                   + strlen(nio->dataFN[0]) + 1,
                                   sizeof(char));
            sprintf(*strP, "%s%s: %s%s", prefix, fs,
                    /* this is a favor to older readers that can deal with
                       this NRRD file because its being saved in a NRRD0003
                       (or below) version, so we don't want to confuse them
                       by not having the old explicit header-relative flag */
                    (_nrrdFormatNRRD_whichVersion(nrrd, nio) < 4 ? "./" : ""),
                    nio->dataFN[0]);
        }
        break;
    default:
        fprintf(stderr, "%s: CONFUSION: field %d unrecognized\n", me, field);
        break;
    }

    return;
}
/*
** _nrrdSprintFieldInfo
**
** this prints "<prefix><field>: <info>" into *strP (after allocating it for
** big enough, usually with a stupidly big margin of error), in a form
** suitable to be written to NRRD or other image headers.  This will always
** print something (for valid inputs), even stupid <info>s like
** "(unknown endian)".  It is up to the caller to decide which fields
** are worth writing, via _nrrdFieldInteresting().
**
** NOTE: some of these fields make sense in non-NRRD files (e.g. all
** the per-axis information), but many only make sense in NRRD files.
** This is just one example of NRRD-format-specific stuff that is not
** in formatNRRD.c
*/
void
_nrrdSprintFieldInfo(char **strP, const char *prefix,
                     const Nrrd *nrrd, NrrdIoState *nio, int field) {
  static const char me[]="_nrrdSprintFieldInfo";
  char buff[AIR_STRLEN_MED], *fnb, stmp[AIR_STRLEN_SMALL],
    *strtmp=NULL;
  double colvec[NRRD_SPACE_DIM_MAX];
  const char *fs;
  unsigned int ii, dd,
    uintStrlen = 11,
    size_tStrlen = 33,
    doubleStrlen = 513;
  size_t fslen, fdlen, maxl;
  int endi;

  if (!( strP && prefix
         && nrrd
         && AIR_IN_CL(1, nrrd->dim, NRRD_DIM_MAX)
         && AIR_IN_OP(nrrdField_unknown, field, nrrdField_last) )) {
    return;
  }
  /* As of Sun Dec  2 01:57:48 CST 2012 (revision 5832) the only
     places where this function is called is when it has been guarded
     by "if (_nrrdFieldInteresting())" (except for in formatText.c when
     its called on the dimension field, which is always interesting).
     So, the following:

     if (!_nrrdFieldInteresting(nrrd, nio, field)) {
       *strP = airStrdup("");
     }

     was redundant and confusingly created the appearance of a memory
     leak waiting to happen.  We now let the default switch statement
     set *strP to NULL (all the other cases set it), to smoke out
     errors in how this function is called */

  fs = airEnumStr(nrrdField, field);
  fslen = strlen(prefix) + strlen(fs) + strlen(": ") + 1;
  switch (field) {
  case nrrdField_comment:
  case nrrdField_keyvalue:
    fprintf(stderr, "%s: CONFUSION: why are you calling me on \"%s\"?\n", me,
            airEnumStr(nrrdField, nrrdField_comment));
    *strP = airStrdup("");
    break;
  case nrrdField_content:
    strtmp = airOneLinify(airStrdup(nrrd->content));
    *strP = AIR_CALLOC(fslen + strlen(strtmp), char);
    sprintf(*strP, "%s%s: %s", prefix, fs, strtmp);
    airFree(strtmp); strtmp = NULL;
    break;
  case nrrdField_number:
    *strP = AIR_CALLOC(fslen + size_tStrlen, char);
    sprintf(*strP, "%s%s: %s", prefix, fs,
            airSprintSize_t(stmp, nrrdElementNumber(nrrd)));
    break;
  case nrrdField_type:
    *strP = AIR_CALLOC(fslen + strlen(airEnumStr(nrrdType, nrrd->type)), char);
    sprintf(*strP, "%s%s: %s", prefix, fs, airEnumStr(nrrdType, nrrd->type));
    break;
  case nrrdField_block_size:
    *strP = AIR_CALLOC(fslen + size_tStrlen, char);
    sprintf(*strP, "%s%s: %s", prefix, fs,
            airSprintSize_t(stmp, nrrd->blockSize));
    break;
  case nrrdField_dimension:
    *strP = AIR_CALLOC(fslen + uintStrlen, char);
    sprintf(*strP, "%s%s: %d", prefix, fs, nrrd->dim);
    break;
  case nrrdField_space:
    *strP = AIR_CALLOC(fslen
                       + strlen(airEnumStr(nrrdSpace, nrrd->space)), char);
    sprintf(*strP, "%s%s: %s", prefix, fs, airEnumStr(nrrdSpace, nrrd->space));
    break;
  case nrrdField_space_dimension:
    *strP = AIR_CALLOC(fslen + uintStrlen, char);
    sprintf(*strP, "%s%s: %d", prefix, fs, nrrd->spaceDim);
    break;
    /* ---- begin per-axis fields ---- */
  case nrrdField_sizes:
    *strP = AIR_CALLOC(fslen + nrrd->dim*(size_tStrlen + 1), char);
    sprintf(*strP, "%s%s:", prefix, fs);
    for (ii=0; ii<nrrd->dim; ii++) {
      sprintf(buff, " %s", airSprintSize_t(stmp, nrrd->axis[ii].size));
      strcat(*strP, buff);
    }
    break;
  case nrrdField_spacings:
    *strP = AIR_CALLOC(fslen + nrrd->dim*(doubleStrlen + 1), char);
    sprintf(*strP, "%s%s:", prefix, fs);
    for (ii=0; ii<nrrd->dim; ii++) {
      airSinglePrintf(NULL, buff, " %.17g", nrrd->axis[ii].spacing);
      strcat(*strP, buff);
    }
    break;
  case nrrdField_thicknesses:
    *strP = AIR_CALLOC(fslen + nrrd->dim*(doubleStrlen + 1), char);
    sprintf(*strP, "%s%s:", prefix, fs);
    for (ii=0; ii<nrrd->dim; ii++) {
      airSinglePrintf(NULL, buff, " %.17g", nrrd->axis[ii].thickness);
      strcat(*strP, buff);
    }
    break;
  case nrrdField_axis_mins:
    *strP = AIR_CALLOC(fslen + nrrd->dim*(doubleStrlen + 1), char);
    sprintf(*strP, "%s%s:", prefix, fs);
    for (ii=0; ii<nrrd->dim; ii++) {
      airSinglePrintf(NULL, buff, " %.17g", nrrd->axis[ii].min);
      strcat(*strP, buff);
    }
    break;
  case nrrdField_axis_maxs:
    *strP = AIR_CALLOC(fslen + nrrd->dim*(doubleStrlen + 1), char);
    sprintf(*strP, "%s%s:", prefix, fs);
    for (ii=0; ii<nrrd->dim; ii++) {
      airSinglePrintf(NULL, buff, " %.17g", nrrd->axis[ii].max);
      strcat(*strP, buff);
    }
    break;
  case nrrdField_space_directions:
    *strP = AIR_CALLOC(fslen
                       + nrrd->dim*nrrd->spaceDim*(doubleStrlen
                                                   + strlen("(,) ")), char);
    sprintf(*strP, "%s%s: ", prefix, fs);
    for (ii=0; ii<nrrd->dim; ii++) {
      _nrrdStrcatSpaceVector(*strP, nrrd->spaceDim,
                             nrrd->axis[ii].spaceDirection);
      if (ii < nrrd->dim-1) {
        strcat(*strP, " ");
      }
    }
    break;
  case nrrdField_centers:
    fdlen = 0;
    for (ii=0; ii<nrrd->dim; ii++) {
      fdlen += 1 + airStrlen(nrrd->axis[ii].center
                             ? airEnumStr(nrrdCenter, nrrd->axis[ii].center)
                             : NRRD_UNKNOWN);
    }
    *strP = AIR_CALLOC(fslen + fdlen, char);
    sprintf(*strP, "%s%s:", prefix, fs);
    for (ii=0; ii<nrrd->dim; ii++) {
      sprintf(buff, " %s",
              (nrrd->axis[ii].center
               ? airEnumStr(nrrdCenter, nrrd->axis[ii].center)
               : NRRD_UNKNOWN));
      strcat(*strP, buff);
    }
    break;
  case nrrdField_kinds:
    fdlen = 0;
    for (ii=0; ii<nrrd->dim; ii++) {
      fdlen += 1 + airStrlen(nrrd->axis[ii].kind
                             ? airEnumStr(nrrdKind, nrrd->axis[ii].kind)
                             : NRRD_UNKNOWN);
    }
    *strP = AIR_CALLOC(fslen + fdlen, char);
    sprintf(*strP, "%s%s:", prefix, fs);
    for (ii=0; ii<nrrd->dim; ii++) {
      sprintf(buff, " %s",
              (nrrd->axis[ii].kind
               ? airEnumStr(nrrdKind, nrrd->axis[ii].kind)
               : NRRD_UNKNOWN));
      strcat(*strP, buff);
    }
    break;
  case nrrdField_labels:
  case nrrdField_units:
#define LABEL_OR_UNITS (nrrdField_labels == field \
                        ? nrrd->axis[ii].label \
                        : nrrd->axis[ii].units)
    fdlen = 0;
    for (ii=0; ii<nrrd->dim; ii++) {
      /* The "2*" is because at worst every character needs escaping.
         The "+ 3" for the |" "| between each part */
      fdlen += 2*airStrlen(LABEL_OR_UNITS) + 3;
    }
    fdlen += 1; /* for '\0' */
    *strP = AIR_CALLOC(fslen + fdlen, char);
    sprintf(*strP, "%s%s:", prefix, fs);
    for (ii=0; ii<nrrd->dim; ii++) {
      strcat(*strP, " \"");
      if (airStrlen(nrrd->axis[ii].label)) {
        _nrrdWriteEscaped(NULL, *strP, LABEL_OR_UNITS,
                          "\"", _NRRD_WHITESPACE_NOTAB);
      }
      strcat(*strP, "\"");
    }
#undef LABEL_OR_UNITS
    break;
    /* ---- end per-axis fields ---- */
  case nrrdField_min:
  case nrrdField_max:
    /* we're basically a no-op, now that these fields became meaningless */
    *strP = AIR_CALLOC(fslen + doubleStrlen, char);
    sprintf(*strP, "%s%s: 0.0", prefix, fs);
    strcat(*strP, buff);
    break;
  case nrrdField_old_min:
    *strP = AIR_CALLOC(fslen + doubleStrlen, char);
    sprintf(*strP, "%s%s: ", prefix, fs);
    airSinglePrintf(NULL, buff, "%.17g", nrrd->oldMin);
    strcat(*strP, buff);
    break;
  case nrrdField_old_max:
    *strP = AIR_CALLOC(fslen + doubleStrlen, char);
    sprintf(*strP, "%s%s: ", prefix, fs);
    airSinglePrintf(NULL, buff, "%.17g", nrrd->oldMax);
    strcat(*strP, buff);
    break;
  case nrrdField_endian:
    if (airEndianUnknown != nio->endian) {
      /* we know a specific endianness because either it was recorded as
         part of "unu make -h", or it was set (and data was possibly
         altered) as part of "unu save" */
      endi = nio->endian;
    } else {
      /* we record our current architecture's endian because we're
         going to writing out data */
      endi = airMyEndian();
    }
    *strP = AIR_CALLOC(fslen + strlen(airEnumStr(airEndian, endi)), char);
    sprintf(*strP, "%s%s: %s", prefix, fs, airEnumStr(airEndian, endi));
    break;
  case nrrdField_encoding:
    *strP = AIR_CALLOC(fslen + strlen(nio->encoding->name), char);
    sprintf(*strP, "%s%s: %s", prefix, fs, nio->encoding->name);
    break;
  case nrrdField_line_skip:
    *strP = AIR_CALLOC(fslen + uintStrlen, char);
    sprintf(*strP, "%s%s: %d", prefix, fs, nio->lineSkip);
    break;
  case nrrdField_byte_skip:
    *strP = AIR_CALLOC(fslen + uintStrlen, char);
    sprintf(*strP, "%s%s: %ld", prefix, fs, nio->byteSkip);
    break;
  case nrrdField_sample_units:
    strtmp = airOneLinify(airStrdup(nrrd->sampleUnits));
    *strP = AIR_CALLOC(fslen + strlen(strtmp), char);
    sprintf(*strP, "%s%s: \"%s\"", prefix, fs, strtmp);
    airFree(strtmp); strtmp = NULL;
    break;
  case nrrdField_space_units:
    fdlen = 0;
    for (ii=0; ii<nrrd->spaceDim; ii++) {
      /* The "2*" is because at worst every character needs escaping.
         See note in formatNRRD.c about how even though its not part
         of the format, we have worst-case scenario of having to
         escape a space units which is nothing but ". The "+ 3" for
         the |" "| between each part */
      fdlen += 2*airStrlen(nrrd->spaceUnits[ii]) + 3;
    }
    fdlen += 1; /* for '\0' */
    *strP = AIR_CALLOC(fslen + fdlen, char);
    sprintf(*strP, "%s%s:", prefix, fs);
    for (ii=0; ii<nrrd->spaceDim; ii++) {
      strcat(*strP, " \"");
      if (airStrlen(nrrd->spaceUnits[ii])) {
        _nrrdWriteEscaped(NULL, *strP, nrrd->spaceUnits[ii],
                          "\"", _NRRD_WHITESPACE_NOTAB);
      }
      strcat(*strP, "\"");
    }
    break;
  case nrrdField_space_origin:
    *strP = AIR_CALLOC(fslen + nrrd->spaceDim*(doubleStrlen
                                               + strlen("(,) ")), char);
    sprintf(*strP, "%s%s: ", prefix, fs);
    _nrrdStrcatSpaceVector(*strP, nrrd->spaceDim, nrrd->spaceOrigin);
    break;
  case nrrdField_measurement_frame:
    *strP = AIR_CALLOC(fslen + (nrrd->spaceDim*
                                nrrd->spaceDim*(doubleStrlen
                                                + strlen("(,) "))), char);
    sprintf(*strP, "%s%s: ", prefix, fs);
    for (dd=0; dd<nrrd->spaceDim; dd++) {
      for (ii=0; ii<nrrd->spaceDim; ii++) {
        colvec[ii] = nrrd->measurementFrame[dd][ii];
      }
      _nrrdStrcatSpaceVector(*strP, nrrd->spaceDim, colvec);
      if (dd < nrrd->spaceDim-1) {
        strcat(*strP, " ");
      }
    }
    break;
  case nrrdField_data_file:
    /* NOTE: this comes last (nrrdField_data_file is the highest-valued
       member of the nrrdField* enum) because the "LIST" form of the
       data file specification requires that the following lines be
       the filenames */
    /* error checking elsewhere: assumes there is data file info */
    if (nio->dataFNFormat) {
      *strP = AIR_CALLOC(fslen + strlen(nio->dataFNFormat) + 4*uintStrlen,
                         char);
      if (nio->dataFileDim == nrrd->dim-1) {
        sprintf(*strP, "%s%s: %s %d %d %d", prefix, fs, nio->dataFNFormat,
                nio->dataFNMin, nio->dataFNMax, nio->dataFNStep);
      } else {
        sprintf(*strP, "%s%s: %s %d %d %d %u", prefix, fs, nio->dataFNFormat,
                nio->dataFNMin, nio->dataFNMax, nio->dataFNStep,
                nio->dataFileDim);
      }
    } else if (nio->dataFNArr->len > 1) {
Exemple #29
0
int
_nrrdFieldInteresting(const Nrrd *nrrd, NrrdIoState *nio, int field)
{
    int ret;
    unsigned int ai;

    if (!( nrrd
            && AIR_IN_CL(1, nrrd->dim, NRRD_DIM_MAX)
            && nio
            && nio->encoding
            && AIR_IN_OP(nrrdField_unknown, field, nrrdField_last) ))
    {
        return 0;
    }

    ret = 0;
    switch (field)
    {
    case nrrdField_comment:
        /* comments and key/value pairs are always handled differently (by
           being printed explicity), so they are never "interesting" */
        break;
    case nrrdField_content:
        ret = !!(airStrlen(nrrd->content));
        break;
    case nrrdField_number:
        /* "number" is entirely redundant with "sizes", which is a
           required field.  Absolutely nothing is lost in eliding "number"
           from the header, so "number" is NEVER interesting.  Should this
           judgement later be found in error, this is the one place where
           the policy change can be implemented */
        break;
    case nrrdField_type:
        /* this is vital */
        ret = 1;
        break;
    case nrrdField_block_size:
        ret = (nrrdTypeBlock == nrrd->type);
        break;
    case nrrdField_dimension:
        /* this is vital */
        ret = 1;
        break;
    case nrrdField_space:
        /* its interesting if its known */
        ret = (nrrdSpaceUnknown != nrrd->space);
        break;
    case nrrdField_space_dimension:
        /* its interesting if its non-zero and if space is not known */
        ret = (nrrd->spaceDim > 0 && nrrdSpaceUnknown == nrrd->space);
        break;
    case nrrdField_sizes:
        /* this is vital */
        ret = 1;
        break;
    case nrrdField_spacings:
        for (ai=0; ai<nrrd->dim; ai++)
        {
            ret |= AIR_EXISTS(nrrd->axis[ai].spacing);
        }
        break;
    case nrrdField_thicknesses:
        for (ai=0; ai<nrrd->dim; ai++)
        {
            ret |= AIR_EXISTS(nrrd->axis[ai].thickness);
        }
        break;
    case nrrdField_axis_mins:
        for (ai=0; ai<nrrd->dim; ai++)
        {
            ret |= AIR_EXISTS(nrrd->axis[ai].min);
        }
        break;
    case nrrdField_axis_maxs:
        for (ai=0; ai<nrrd->dim; ai++)
        {
            ret |= AIR_EXISTS(nrrd->axis[ai].max);
        }
        break;
    case nrrdField_space_directions:
        ret = nrrd->spaceDim > 0;
        break;
    case nrrdField_centers:
        for (ai=0; ai<nrrd->dim; ai++)
        {
            ret |= (nrrdCenterUnknown != nrrd->axis[ai].center);
        }
        break;
    case nrrdField_kinds:
        for (ai=0; ai<nrrd->dim; ai++)
        {
            ret |= (nrrdKindUnknown != nrrd->axis[ai].kind);
        }
        break;
    case nrrdField_labels:
        for (ai=0; ai<nrrd->dim; ai++)
        {
            ret |= !!(airStrlen(nrrd->axis[ai].label));
        }
        break;
    case nrrdField_units:
        for (ai=0; ai<nrrd->dim; ai++)
        {
            ret |= !!(airStrlen(nrrd->axis[ai].units));
        }
        break;
    case nrrdField_min:
    case nrrdField_max:
        /* these no longer exist in the Nrrd struct; we never write them */
        ret = AIR_FALSE;
        break;
    case nrrdField_old_min:
        ret = AIR_EXISTS(nrrd->oldMin);
        break;
    case nrrdField_old_max:
        ret = AIR_EXISTS(nrrd->oldMax);
        break;
    case nrrdField_endian:
        ret = nio->encoding->endianMatters && 1 < nrrdElementSize(nrrd);
        break;
    case nrrdField_encoding:
        /* this is vital */
        ret = 1;
        break;
    case nrrdField_line_skip:
        ret = nio->lineSkip > 0;
        break;
    case nrrdField_byte_skip:
        ret = nio->byteSkip != 0;
        break;
    case nrrdField_keyvalue:
        /* comments and key/value pairs are always handled differently (by
           being printed explicity), so they are never "interesting" */
        break;
    case nrrdField_sample_units:
        ret = airStrlen(nrrd->sampleUnits);
        break;
    case nrrdField_space_units:
        for (ai=0; ai<nrrd->spaceDim; ai++)
        {
            ret |= !!(airStrlen(nrrd->spaceUnits[ai]));
        }
        break;
    case nrrdField_space_origin:
        /* we're trusting other validity checks to ensure that
           all the coeffs exist or not, together */
        ret = (nrrd->spaceDim > 0
               && AIR_EXISTS(nrrd->spaceOrigin[0]));
        break;
    case nrrdField_measurement_frame:
        /* we're trusting other validity checks to ensure that
           all the coeffs exist or not, together */
        ret = (nrrd->spaceDim > 0
               && AIR_EXISTS(nrrd->measurementFrame[0][0]));
        break;
    case nrrdField_data_file:
        /* detached header was either requested or is required */
        ret = (nio->detachedHeader
               || nio->dataFNFormat
               || nio->dataFNArr->len > 1);
        break;
    }

    return ret;
}
Exemple #30
0
int
unrrdu_heqMain(int argc, char **argv, char *me, hestParm *hparm) {
  hestOpt *opt = NULL;
  char *out, *err, *mapS;
  Nrrd *nin, *nout, *nmap;
  int smart, pret;
  unsigned int bins;
  airArray *mop;
  float amount;

  /* we want to facilitate saving out the mapping as a text file,
     but with the domain included */
  /* this is commented out with the 8 Aug 2003 advent of nrrdDefGetenv
  nrrdDefWriteBareTable = AIR_FALSE;
  */

  hestOptAdd(&opt, "b,bin", "bins", airTypeInt, 1, 1, &bins, NULL,
             "# bins to use in histogram that is created in order to "
             "calculate the mapping that achieves the equalization.");
  hestOptAdd(&opt, "s,smart", "bins", airTypeInt, 0, 1, &smart, "0",
             "# bins in value histogram to ignore in calculating the mapping. "
             "Bins are ignored when they get more hits than other bins, and "
             "when the values that fall in them are constant.  This is an "
             "effective way to prevent large regions of background value "
             "from distorting the equalization mapping.");
  hestOptAdd(&opt, "a,amount", "amount", airTypeFloat, 1, 1, &amount, "1.0",
             "extent to which the histogram equalizing mapping should be "
             "applied; 0.0: no change, 1.0: full equalization");
  hestOptAdd(&opt, "m,map", "filename", airTypeString, 1, 1, &mapS, "",
             "The value mapping used to achieve histogram equalization is "
             "represented by a univariate regular map.  By giving a filename "
             "here, that map can be saved out and applied to other nrrds "
             "with \"unu rmap\"");
  OPT_ADD_NIN(nin, "input nrrd");
  OPT_ADD_NOUT(out, "output nrrd");

  mop = airMopNew();
  airMopAdd(mop, opt, (airMopper)hestOptFree, airMopAlways);

  USAGE(_unrrdu_heqInfoL);
  PARSE();
  airMopAdd(mop, opt, (airMopper)hestParseFree, airMopAlways);

  nout = nrrdNew();
  airMopAdd(mop, nout, (airMopper)nrrdNuke, airMopAlways);
  
  if (nrrdHistoEq(nout, nin, airStrlen(mapS) ? &nmap : NULL,
                  bins, smart, amount)) {
    airMopAdd(mop, err = biffGetDone(NRRD), airFree, airMopAlways);
    fprintf(stderr, "%s: trouble histogram equalizing:\n%s", me, err);
    airMopError(mop);
    return 1;
  }

  if (airStrlen(mapS)) {
    SAVE(mapS, nmap, NULL);
  }
  SAVE(out, nout, NULL);

  airMopOkay(mop);
  return 0;
}