#include "SUMA_suma.h"
SUMA_SurfaceViewer *SUMAg_cSV = NULL; /*!< Global pointer to current Surface Viewer structure*/
SUMA_SurfaceViewer *SUMAg_SVv = NULL; /*!< Global pointer to the vector containing the various Surface Viewer Structures
SUMAg_SVv contains SUMA_MAX_SURF_VIEWERS structures */
int SUMAg_N_SVv = 0; /*!< Number of SVs realized by X */
SUMA_DO *SUMAg_DOv = NULL; /*!< Global pointer to Displayable Object structure vector*/
int SUMAg_N_DOv = 0; /*!< Number of DOs stored in DOv */
SUMA_CommonFields *SUMAg_CF = NULL; /*!< Global pointer to structure containing info common to all viewers */
void usage_3dBRAIN_VOYAGERtoAFNI (SUMA_GENERIC_ARGV_PARSE *ps)
{
static char FuncName[]={"usage_3dBRAIN_VOYAGERtoAFNI"};
char * s = NULL, *sio=NULL, *st = NULL, *sts = NULL;
int i;
s = SUMA_help_basics();
sio = SUMA_help_IO_Args(ps);
printf ( "\n"
"Usage: 3dBRAIN_VOYAGERtoAFNI <-input BV_VOLUME.vmr> [-bs] [-qx]\n"
" \n"
" Converts a BrainVoyager vmr dataset to AFNI's BRIK format\n"
" The conversion is based on information from BrainVoyager's\n"
" website: www.brainvoyager.com. \n"
" Sample data and information provided by \n"
" Adam Greenberg and Nikolaus Kriegeskorte.\n"
"\n"
" If you get error messages about the number of\n"
" voxels and file size, try the options below.\n"
" I hope to automate these options once I have\n"
" a better description of the BrainVoyager QX format.\n"
"\n"
" Optional Parameters:\n"
" -bs: Force byte swapping.\n"
" -qx: .vmr file is from BrainVoyager QX\n"
"%s"
"%s"
"\n", sio, s);
SUMA_free(s); s = NULL; SUMA_free(st); st = NULL; SUMA_free(sio); sio = NULL;
s = SUMA_New_Additions(0, 1); printf("%s\n", s);SUMA_free(s); s = NULL;
printf(" Ziad S. Saad SSCC/NIMH/NIH saadz@mail.nih.gov \n");
exit(0);
}
SUMA_GENERIC_PROG_OPTIONS_STRUCT *SUMA_3dBRAIN_VOYAGERtoAFNI_ParseInput(char *argv[], int argc, SUMA_GENERIC_ARGV_PARSE *ps)
{
static char FuncName[]={"SUMA_BrainWrap_ParseInput"};
SUMA_GENERIC_PROG_OPTIONS_STRUCT *Opt=NULL;
int kar;
SUMA_Boolean brk;
SUMA_Boolean LocalHead = NOPE;
SUMA_ENTRY;
Opt = SUMA_Alloc_Generic_Prog_Options_Struct();
Opt->b1 = 0;
Opt->b2 = 0;
kar = 1;
brk = NOPE;
while (kar < argc) { /* loop accross command ine options */
/*fprintf(stdout, "%s verbose: Parsing command line...\n", FuncName);*/
if (strcmp(argv[kar], "-h") == 0 || strcmp(argv[kar], "-help") == 0) {
usage_3dBRAIN_VOYAGERtoAFNI(ps);
exit (0);
}
SUMA_SKIP_COMMON_OPTIONS(brk, kar);
if (!brk && (strcmp(argv[kar], "-input") == 0)) {
kar ++;
if (kar >= argc) {
fprintf (SUMA_STDERR, "need argument after -input\n");
exit (1);
}
Opt->in_name = argv[kar];
brk = YUP;
}
if (!brk && (strcmp(argv[kar], "-bs") == 0)) {
Opt->b1 = 1;
brk = YUP;
}
if (!brk && (strcmp(argv[kar], "-qx") == 0)) {
Opt->b2 = 1;
brk = YUP;
}
if (!brk && (strcmp(argv[kar], "-debug") == 0)) {
kar ++;
if (kar >= argc) {
fprintf (SUMA_STDERR, "need integer argument after -debug\n");
exit (1);
}
Opt->debug = atoi(argv[kar]);
brk = YUP;
}
if (!brk && !ps->arg_checked[kar]) {
fprintf (SUMA_STDERR,"Error %s:\nOption %s not understood. Try -help for usage\n", FuncName, argv[kar]);
exit (1);
} else {
brk = NOPE;
kar ++;
}
}
SUMA_RETURN(Opt);
}
char * SUMA_BrainVoyager_Read_vmr(char *fnameorig, THD_3dim_dataset *dset, int LoadData, byte Qxforce, byte bsforce)
{
static char FuncName[]={"SUMA_BrainVoyager_Read_vmr"};
int i = 0, nf, iop, dchunk, End, bs, doff, ex,
data_type=SUMA_notypeset, view, endian, dblock;
THD_ivec3 iv3;
unsigned long len;
short qxver;
short nvox[3]; /* values are unsigned, so check for sign for bs... */
THD_mat33 m33;
THD_ivec3 orixyz , nxyz ;
THD_fvec3 dxyz , orgxyz ;
float ep[3], sp[3];
char sview[10], *fname = NULL, *scom=NULL, form[10], swp[10], orstr[10], xfov[100], yfov[100], zfov[100], *prefix = NULL, *dsetheadname = NULL;
FILE *fid = NULL;
SUMA_Boolean LocalHead = NOPE;
SUMA_ENTRY;
if (!dset || !fnameorig) {
SUMA_SL_Err("NULL fname || NULL dset!");
SUMA_RETURN(NOPE);
}
if (!SUMA_isExtension(fnameorig, ".vmr")) {
SUMA_SL_Err("vmr dset is expected to have .vmr for an extension");
SUMA_RETURN(NOPE);
}
if (!SUMA_filexists(fnameorig)) {
SUMA_SL_Err("file does not exist");
SUMA_RETURN(NOPE);
}
/* make fname be the new name without the extension*/
fname = SUMA_Extension(fnameorig,".vmr", YUP);
prefix = SUMA_AfniPrefix(fname, NULL, NULL, NULL);
if( !THD_filename_ok(prefix) ) {
SUMA_SL_Err("Bad prefix");
goto CLEAN_EXIT;
}
/* someday, guess format on your own...*/
qxver = 0;
if (Qxforce) {
SUMA_LH("Forcing qxver");
qxver = 1; /* set to 1 if qx format */
}
/* view ? */
view = VIEW_ORIGINAL_TYPE;
if (strstr(fname, "_tal")) { view = VIEW_TALAIRACH_TYPE; sprintf(sview,"+tlrc"); }
else if (strstr(fname, "_acpc")) { view = VIEW_ACPCALIGNED_TYPE; sprintf(sview,"+acpc"); }
else { view = VIEW_ORIGINAL_TYPE; sprintf(sview,"+orig"); }
if (LocalHead) fprintf(SUMA_STDERR,"%s: View %s, %d\n", FuncName, sview, view);
dsetheadname = SUMA_append_replace_string(prefix,".HEAD", sview, 0);
if (SUMA_filexists(dsetheadname)) {
SUMA_SL_Err("Bad prefix, output dset exists");
goto CLEAN_EXIT;
}
SUMA_free(dsetheadname); dsetheadname = NULL;
fid = fopen(fnameorig,"r");
if (!fid) {
SUMA_SL_Err("Could not open file for reading");
goto CLEAN_EXIT;
}
if (qxver) {
SUMA_LH("Reading dimensions, 2+ 1st 6 bytes and deciding on swap");
doff = 4*sizeof(short);/* data offset 2 + 6 bytes */
} else {
SUMA_LH("Reading dimensions, 1st 6 bytes and deciding on swap");
doff = 3*sizeof(short);/* data offset */
}
SUMA_WHAT_ENDIAN(endian);
bs = 0;
swp[0] = '\0';
data_type = SUMA_byte; /* voxel data is bytes */
dchunk = sizeof(byte); /* voxel data is bytes */
sprintf(form,"3Db");
if (qxver) { SUMA_READ_NUM(&(qxver), fid, ex, sizeof(short)); if (LocalHead) fprintf(SUMA_STDERR,"%s: QXver = %d\n", FuncName, qxver);}/* is this a QX format?*/
SUMA_READ_NUM(&(nvox[2]), fid, ex, sizeof(short)); /* Z first */
SUMA_READ_NUM(&(nvox[1]), fid, ex, sizeof(short));
SUMA_READ_NUM(&(nvox[0]), fid, ex, sizeof(short));
if ((nvox[0] < 0 || nvox[1] < 0 || nvox[2] < 0 )) {
SUMA_LH("Byte swapping needed");
bs = 1;
}
if (bsforce) {
SUMA_LH("Byte swapping forced");
bs = 1;
}
if (bs) {
if (qxver) SUMA_swap_2(&(qxver));
SUMA_swap_2(&(nvox[0]));
SUMA_swap_2(&(nvox[1]));
SUMA_swap_2(&(nvox[2]));
sprintf(swp,"-2swap");
SUMA_OTHER_ENDIAN(endian);
}
/* 1 1 1???? */
if (nvox[0] == nvox[1] && nvox[1] == nvox[2] && nvox[2] == 1) {
if (LocalHead) { fprintf(SUMA_STDERR,"Warning %s: Voxel nums all 1. Trying from file size\n", FuncName); }
len = THD_filesize( fnameorig ) ;
len -= doff;
len /= dchunk;
nvox[0] = (int)pow((double)len, 1.0/3.0);
if (nvox[0] * nvox[0] * nvox[0] != len) {
fprintf(SUMA_STDERR,"Error %s: Bad voxel numbers and could not infer number from filesize.\n"
"Size of file: %ld, data offset: %d, datum size: %d, data number: %ld\n"
"Inferred nvox:%d\n",
FuncName,
THD_filesize( fnameorig ), doff, dchunk, len,
nvox[0]);
goto CLEAN_EXIT;
}
nvox[2] = nvox[1] = nvox[0];
if (LocalHead) { fprintf(SUMA_STDERR,"Warning %s: Using filesize inferred number of voxels: %d %d %d\n",
FuncName, nvox[0], nvox[1], nvox[2]); }
}
if (LocalHead) fprintf(SUMA_STDERR,"Number of voxels: %d %d %d. qxver %d\n", nvox[0], nvox[1], nvox[2], qxver);
/* check against filesize */
len = THD_filesize( fnameorig ) ;
dblock = nvox[0]*nvox[1]*nvox[2]*dchunk;
if (len != (dblock + doff)) {
if (!qxver) {
fprintf(SUMA_STDERR, "Mismatch between file size %ld\n"
"and expected size %d = (%d*%d*%d*%d+%d) \n",
len, (dblock + doff), nvox[0], nvox[1], nvox[2], dchunk, doff);
goto CLEAN_EXIT;
}else if (len < dblock + doff) {
fprintf(SUMA_STDERR, "Mismatch between file size %ld\n"
"and minimum expected size %d = (%d*%d*%d*%d+%d) \n",
len, (dblock + doff), nvox[0], nvox[1], nvox[2], dchunk, doff);
goto CLEAN_EXIT;
}else {
SUMA_LH("Proceeding");
}
}
if (LocalHead) fprintf(SUMA_STDERR,"File size passes test\n");
/* orientation */
orixyz.ijk[0] = ORI_A2P_TYPE;
orixyz.ijk[1] = ORI_S2I_TYPE;
orixyz.ijk[2] = ORI_R2L_TYPE;
/* load number of voxels */
LOAD_IVEC3( nxyz , nvox[0] , nvox[1] , nvox[2] ) ;
/* form the command */
SUMA_LH("Forming command");
{
float delta[3]={1.0, 1.0, 1.0};
float origin[3]={0.0, 0.0, 0.0};
/* dimensions, same for vmr*/
LOAD_FVEC3( dxyz , delta[0], delta[1], delta[2] ) ;
SUMA_sizeto3d_2_deltaHEAD(orixyz, &dxyz);
/* origin */
LOAD_FVEC3( orgxyz , origin[0], origin[1], origin[2] ) ;
SUMA_originto3d_2_originHEAD(orixyz, &orgxyz);
}
/* start point (edge of origin voxel) and end point (opposite to start ) */
sp[0] = orgxyz.xyz[0] + SUMA_ABS(dxyz.xyz[0]) / 2.0;
sp[1] = orgxyz.xyz[1] + SUMA_ABS(dxyz.xyz[1]) / 2.0;
sp[2] = orgxyz.xyz[2] + SUMA_ABS(dxyz.xyz[2]) / 2.0;
ep[0] = orgxyz.xyz[0] + (nxyz.ijk[0] - 0.5) * SUMA_ABS(dxyz.xyz[0]);
ep[1] = orgxyz.xyz[1] + (nxyz.ijk[1] - 0.5) * SUMA_ABS(dxyz.xyz[1]);
ep[2] = orgxyz.xyz[2] + (nxyz.ijk[2] - 0.5) * SUMA_ABS(dxyz.xyz[2]);
SUMA_orcode_to_orstring (orixyz.ijk[0], orixyz.ijk[1], orixyz.ijk[2], orstr);
sprintf(xfov," -xFOV %.2f%c-%.2f%c", sp[0], orstr[0], ep[0], orstr[3]);
sprintf(yfov," -yFOV %.2f%c-%.2f%c", sp[1], orstr[1], ep[1], orstr[4]);
sprintf(zfov," -zFOV %.2f%c-%.2f%c", sp[2], orstr[2], ep[2], orstr[5]);
scom = (char *)SUMA_calloc((strlen(fnameorig)+500), sizeof(char));
sprintf(scom,"to3d %s %s %s %s -prefix %s %s:%d:0:%d:%d:%d:%s ",
swp, xfov, yfov, zfov, prefix, form, doff,
nvox[0], nvox[1], nvox[0], fnameorig);
SUMA_LH("HERE");
if (dset) { /* form the dset header */
int nvals_read = 0;
SUMA_LH("Filling header");
EDIT_dset_items( dset ,
ADN_prefix , prefix ,
ADN_datum_all , data_type ,
ADN_nxyz , nxyz ,
ADN_xyzdel , dxyz ,
ADN_xyzorg , orgxyz ,
ADN_xyzorient , orixyz ,
ADN_malloc_type , DATABLOCK_MEM_MALLOC ,
ADN_view_type , view ,
ADN_type , HEAD_ANAT_TYPE ,
ADN_func_type , ANAT_BUCK_TYPE ,
ADN_none ) ;
if (LoadData) {
void *vec=NULL;
SUMA_LH("Loading data");
if (!(vec = SUMA_BinarySuck(fnameorig, data_type, endian, 3*sizeof(short), -1, &nvals_read))) {
SUMA_SL_Err("Failed to read data file"); goto CLEAN_EXIT;
}
if (qxver) {
if (nvals_read < nvox[0]*nvox[1]*nvox[2]) {
SUMA_SL_Warn("Failed to read expected number of voxels\n proceeding...");
}
} else {
if (nvals_read != nvox[0]*nvox[1]*nvox[2]) {
SUMA_SL_Warn("Failed to read the appropriate number of voxels\n proceeding...");
}
}
EDIT_substitute_brick( dset , 0 , data_type , vec) ;
if (LocalHead) fprintf(SUMA_STDERR,"%s: Read %d values from file.\n", FuncName, nvals_read);
/* DSET_write(dset) ; */
}
}
CLEAN_EXIT:
if (prefix) SUMA_free(prefix); prefix = NULL;
if (fname) SUMA_free(fname); fname = NULL;
if (fid) fclose(fid); fid = NULL;
SUMA_RETURN(scom);
}
int main (int argc,char *argv[])
{/* Main */
static char FuncName[]={"3dBRAIN_VOYAGERtoAFNI"};
SUMA_GENERIC_PROG_OPTIONS_STRUCT *Opt;
SUMA_GENERIC_ARGV_PARSE *ps=NULL;
SUMA_OPEN_DX_STRUCT **dx = NULL;
THD_3dim_dataset *dset=NULL;
char *sto3d = NULL;
SUMA_Boolean LocalHead = NOPE;
SUMA_STANDALONE_INIT;
SUMA_mainENTRY;
/* Allocate space for DO structure */
SUMAg_DOv = SUMA_Alloc_DisplayObject_Struct (SUMA_MAX_DISPLAYABLE_OBJECTS);
ps = SUMA_Parse_IO_Args(argc, argv, "");
if (argc < 2) {
usage_3dBRAIN_VOYAGERtoAFNI(ps);
exit (1);
}
Opt = SUMA_3dBRAIN_VOYAGERtoAFNI_ParseInput (argv, argc, ps);
if (Opt->debug > 2) LocalHead = YUP;
dset = EDIT_empty_copy( NULL ) ;
tross_Make_History( "3dBRAIN_VOYAGERtoAFNI" , argc,argv , dset) ;
if (!(sto3d = SUMA_BrainVoyager_Read_vmr(Opt->in_name, dset, 1, Opt->b2, Opt->b1))) {
if (Opt->debug) SUMA_SL_Err("Failed in SUMA_BrainVoyager_Read_vmr");
exit(1);
}
if (dset) {
SUMA_LH("Writing Dset");
DSET_write(dset) ;
if (LocalHead) {
fprintf(SUMA_STDERR,"%s: Can use the following command to create dset with to3d:\n%s\n", FuncName,sto3d);
}
} else {
/* the olde way */
if (system(sto3d)) {
fprintf(SUMA_STDERR, "Error %s: Failed while executing shell command:\n%s\n"
"Check to3d's error messages, and disk writing permissions.\n", FuncName, sto3d);
}
}
if (sto3d) SUMA_free(sto3d); sto3d = NULL;
if (dset) { DSET_delete(dset); dset = NULL; }
if (Opt) Opt = SUMA_Free_Generic_Prog_Options_Struct(Opt);
if (!SUMA_Free_CommonFields(SUMAg_CF)) SUMA_error_message(FuncName,"SUMAg_CF Cleanup Failed!",1);
exit(0);
}
syntax highlighted by Code2HTML, v. 0.9.1