#include "SUMA_suma.h"
#ifdef USE_DECOMPOSE_SHOEMAKE
#include "Decompose.c" /* For testing, put it in library if you'll be using it */
#endif
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_SUMA_ConvertSurface (SUMA_GENERIC_ARGV_PARSE *ps)
{/*Usage*/
static char FuncName[]={"usage_SUMA_ConvertSurface"};
char * s = NULL, *sio=NULL;
s = SUMA_help_basics();
sio = SUMA_help_IO_Args(ps);
printf ("\nUsage: ConvertSurface <-i_TYPE inSurf> <-o_TYPE outSurf> \n"
" [<-sv SurfaceVolume [VolParam for sf surfaces]>] [-tlrc] [-MNI_rai/-MNI_lpi]\n"
" reads in a surface and writes it out in another format.\n"
" Note: This is a not a general utility conversion program. \n"
" Only fields pertinent to SUMA are preserved.\n"
"%s"
/* " -i_TYPE inSurf specifies the input surface, TYPE is one of the following:\n"
" fs: FreeSurfer surface. \n"
" If surface name has .asc it is assumed to be\n"
" in ASCII format. Otherwise it is assumed to be\n"
" in BINARY_BE (Big Endian) format.\n"
" Patches in Binary format cannot be read at the moment.\n"
" sf: SureFit surface. \n"
" You must specify the .coord followed by the .topo file.\n"
" vec (or 1d): Simple ascii matrix format. \n"
" You must specify the NodeList file followed by the FaceSetList file.\n"
" NodeList contains 3 floats per line, representing X Y Z vertex coordinates.\n"
" FaceSetList contains 3 ints per line, representing v1 v2 v3 triangle vertices.\n"
" ply: PLY format, ascii or binary.\n"
" Only vertex and triangulation info is preserved.\n"
" bv: BrainVoyager format. \n"
" Only vertex and triangulation info is preserved.\n"
" -ipar_TYPE ParentSurf specifies the parent surface. Only used\n"
" when -o_fsp is used, see below.\n"
" -o_TYPE outSurf specifies the output surface, TYPE is one of the following:\n"
" fs: FreeSurfer ascii surface. \n"
" fsp: FeeSurfer ascii patch surface. \n"
" In addition to outSurf, you need to specify\n"
" the name of the parent surface for the patch.\n"
" using the -ipar_TYPE option\n"
" sf: SureFit surface. \n"
" You must specify the .coord followed by the .topo file.\n"
" vec (or 1D): Simple ascii matrix format. \n"
" see help for vec under -i_TYPE options for format specifications.\n"
" ply: PLY format, ascii or binary.\n"
" -sv SurfaceVolume [VolParam for sf surfaces]\n"
" This option must not come before the -i_TYPE option.\n"
" If you supply a surface volume, the coordinates of the input surface.\n"
" are modified to SUMA's convention and aligned with SurfaceVolume.\n"
" You must also specify a VolParam file for SureFit surfaces.\n" */
" -orient_out STR: Output coordinates in STR coordinate system. \n"
" STR is a three character string following AFNI's \n"
" naming convention. The program assumes that the native \n"
" orientation of the surface is RAI, unless you use the \n"
" -MNI_lpi option. The coordinate transformation is carried \n"
" out last, just before writing the surface to disk.\n"
" -native: Write the output surface in the coordinate system native to its format.\n"
" Option makes sense for BrainVoyager, Caret/SureFit and FreeSurfer surfaces.\n"
" But the implementation for Caret/Surefit is not finished yet (sorry).\n"
" -make_consistent: Check the consistency of the surface's mesh (triangle\n"
" winding). This option will write out a new surface even \n"
" if the mesh was consistent.\n"
" See SurfQual -help for mesh checks.\n"
" -radial_to_sphere rad: Push each node along the center-->node direction until\n"
" |center-->node| = rad.\n"
" -acpc: Apply acpc transform (which must be in acpc version of \n"
" SurfaceVolume) to the surface vertex coordinates. \n"
" This option must be used with the -sv option.\n"
" -tlrc: Apply Talairach transform (which must be a talairach version of \n"
" SurfaceVolume) to the surface vertex coordinates. \n"
" This option must be used with the -sv option.\n"
" -MNI_rai/-MNI_lpi: Apply Andreas Meyer Lindenberg's transform to turn \n"
" AFNI tlrc coordinates (RAI) into MNI coord space \n"
" in RAI (with -MNI_rai) or LPI (with -MNI_lpi)).\n"
" NOTE: -MNI_lpi option has not been tested yet (I have no data\n"
" to test it on. Verify alignment with AFNI and please report\n"
" any bugs.\n"
" This option can be used without the -tlrc option.\n"
" But that assumes that surface nodes are already in\n"
" AFNI RAI tlrc coordinates .\n"
" NOTE: The vertex coordinates coordinates of the input surfaces are only\n"
" transformed if -sv option is used. If you do transform surfaces, \n"
" take care not to load them into SUMA with another -sv option.\n"
"\n"
" -patch2surf: Change a patch, defined here as a surface with a mesh that\n"
" uses only a subset of the full nodelist, to a surface\n"
" where all the nodes in nodelist are used in the mesh.\n"
" Note that node indices will no longer correspond between\n"
" the input patch and the output surface.\n"
"\n"
" Options for applying arbitrary affine transform:\n"
" [xyz_new] = [Mr] * [xyz_old - cen] + D + cen\n"
" -xmat_1D mat: Apply transformation specified in 1D file mat.1D.\n"
" to the surface's coordinates.\n"
" [mat] = [Mr][D] is of the form:\n"
" r11 r12 r13 D1\n"
" r21 r22 r23 D2\n"
" r31 r32 r33 D3\n"
" -xcenter x y z: Use vector cen = [x y z]' for rotation center.\n"
" Default is cen = [0 0 0]'\n"
" -polar_decomp: Apply polar decomposition to mat and preserve\n"
" orthogonal component and shift only. \n"
" For more information, see cat_matvec's -P option.\n"
" This option can only be used in conjunction with\n"
" -xmat_1D\n"
"\n"
"%s\n"
, sio, s); SUMA_free(sio); sio = NULL; SUMA_free(s); s = NULL;
s = SUMA_New_Additions(0, 1); printf("%s\n", s);SUMA_free(s); s = NULL;
printf ("\t\t Ziad S. Saad SSCC/NIMH/NIH saadz@mail.nih.gov \t Wed Jan 8 13:44:29 EST 2003 \n");
exit (0);
}/*Usage*/
int main (int argc,char *argv[])
{/* Main */
static char FuncName[]={"ConvertSurface"};
int kar, volexists, i;
float xcen[3], M[3][4], DoR2S;
char *if_name = NULL, *of_name = NULL, *if_name2 = NULL,
*of_name2 = NULL, *sv_name = NULL, *vp_name = NULL,
*OF_name = NULL, *OF_name2 = NULL, *tlrc_name = NULL,
*acpc_name=NULL, *xmat_name = NULL, *ifpar_name = NULL, *ifpar_name2 = NULL;
SUMA_SO_File_Type iType = SUMA_FT_NOT_SPECIFIED, iparType = SUMA_FT_NOT_SPECIFIED,
oType = SUMA_FT_NOT_SPECIFIED;
SUMA_SO_File_Format iForm = SUMA_FF_NOT_SPECIFIED, iparForm = SUMA_FF_NOT_SPECIFIED;
SUMA_SurfaceObject *SO = NULL, *SOpar = NULL, *SOsurf = NULL;
SUMA_PARSED_NAME *of_name_strip = NULL, *of_name2_strip = NULL;
SUMA_SFname *SF_name = NULL;
void *SO_name = NULL;
char orsurf[3], orcode[3];
THD_warp *warp=NULL ;
THD_3dim_dataset *aset=NULL;
SUMA_Boolean brk, Do_tlrc, Do_mni_RAI, Do_mni_LPI, Do_acpc, Docen;
SUMA_Boolean Doxmat, Do_wind, Do_p2s, onemore, Do_native, Do_PolDec;
SUMA_GENERIC_ARGV_PARSE *ps=NULL;
SUMA_Boolean exists;
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, "-o;-i;-sv;-ipar;");
if (argc < 4)
{
usage_SUMA_ConvertSurface (ps);
exit (1);
}
kar = 1;
xmat_name = NULL;
xcen[0] = 0.0; xcen[1] = 0.0; xcen[2] = 0.0;
brk = NOPE;
orcode[0] = '\0';
sprintf(orsurf,"RAI");
Docen = NOPE;
Doxmat = NOPE;
Do_tlrc = NOPE;
Do_mni_RAI = NOPE;
Do_mni_LPI = NOPE;
Do_acpc = NOPE;
Do_wind = NOPE;
Do_p2s = NOPE;
Do_native = NOPE;
DoR2S = 0.0;
Do_PolDec = NOPE;
onemore = 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_SUMA_ConvertSurface(ps);
exit (0);
}
SUMA_SKIP_COMMON_OPTIONS(brk, kar);
SUMA_TO_LOWER(argv[kar]);
#if 0
if (!brk && (strcmp(argv[kar], "-i_bv") == 0)) {
kar ++;
if (kar >= argc) {
fprintf (SUMA_STDERR, "need argument after -i_bv\n ");
exit (1);
}
if_name = argv[kar];
iType = SUMA_BRAIN_VOYAGER;
iForm = SUMA_BINARY;
brk = YUP;
}
if (!brk && (strcmp(argv[kar], "-i_fs") == 0)) {
kar ++;
if (kar >= argc) {
fprintf (SUMA_STDERR, "need argument after -i_fs\n ");
exit (1);
}
if_name = argv[kar];
iType = SUMA_FREE_SURFER;
if (SUMA_isExtension(if_name, ".asc"))
iparForm = SUMA_ASCII;
else
iparForm = SUMA_BINARY_BE;
brk = YUP;
}
if (!brk && (strcmp(argv[kar], "-i_sf") == 0)) {
kar ++;
if (kar+1 >= argc) {
fprintf (SUMA_STDERR, "need 2 arguments after -i_sf\n");
exit (1);
}
if_name = argv[kar]; kar ++;
if_name2 = argv[kar];
iType = SUMA_SUREFIT;
iForm = SUMA_ASCII;
brk = YUP;
}
if (!brk && ( (strcmp(argv[kar], "-i_vec") == 0) || (strcmp(argv[kar], "-i_1d") == 0) ) ) {
kar ++;
if (kar+1 >= argc) {
fprintf (SUMA_STDERR, "need 2 argument after -i_vec (or -i_1D)\n");
exit (1);
}
if_name = argv[kar]; kar ++;
if_name2 = argv[kar];
iType = SUMA_VEC;
iForm = SUMA_ASCII;
brk = YUP;
}
if (!brk && (strcmp(argv[kar], "-i_ply") == 0)) {
kar ++;
if (kar >= argc) {
fprintf (SUMA_STDERR, "need argument after -i_ply \n");
exit (1);
}
if_name = argv[kar];
iType = SUMA_PLY;
iForm = SUMA_FF_NOT_SPECIFIED;
brk = YUP;
}
if (!brk && (strcmp(argv[kar], "-ipar_bv") == 0)) {
kar ++;
if (kar >= argc) {
fprintf (SUMA_STDERR, "need argument after -ipar_bv \n");
exit (1);
}
ifpar_name = argv[kar];
iparType = SUMA_BRAIN_VOYAGER;
iparForm = SUMA_BINARY;
brk = YUP;
}
if (!brk && (strcmp(argv[kar], "-ipar_fs") == 0)) {
kar ++;
if (kar >= argc) {
fprintf (SUMA_STDERR, "need argument after -ipar_fs \n");
exit (1);
}
ifpar_name = argv[kar];
iparType = SUMA_FREE_SURFER;
if (SUMA_isExtension(ifpar_name, ".asc"))
iparForm = SUMA_ASCII;
else
iparForm = SUMA_BINARY_BE;
brk = YUP;
}
if (!brk && (strcmp(argv[kar], "-ipar_sf") == 0)) {
kar ++;
if (kar+1 >= argc) {
fprintf (SUMA_STDERR, "need 2 arguments after -ipar_sf\n");
exit (1);
}
ifpar_name = argv[kar]; kar ++;
ifpar_name2 = argv[kar];
iparType = SUMA_SUREFIT;
iparForm = SUMA_ASCII;
brk = YUP;
}
if (!brk && ( (strcmp(argv[kar], "-ipar_vec") == 0) || (strcmp(argv[kar], "-ipar_1d") == 0) ) ) {
kar ++;
if (kar+1 >= argc) {
fprintf (SUMA_STDERR, "need 2 argument after -ipar_vec (or -ipar_1D)\n");
exit (1);
}
ifpar_name = argv[kar]; kar ++;
ifpar_name2 = argv[kar];
iparType = SUMA_VEC;
iparForm = SUMA_ASCII;
brk = YUP;
}
if (!brk && (strcmp(argv[kar], "-ipar_ply") == 0)) {
kar ++;
if (kar >= argc) {
fprintf (SUMA_STDERR, "need argument after -ipar_ply \n");
exit (1);
}
ifpar_name = argv[kar];
iparType = SUMA_PLY;
iparForm = SUMA_FF_NOT_SPECIFIED;
brk = YUP;
}
if (!brk && (strcmp(argv[kar], "-sv") == 0)) {
if (iType == SUMA_FT_NOT_SPECIFIED) {
fprintf (SUMA_STDERR, " -sv option must be preceeded by -i_TYPE option.\n");
exit(1);
}
kar ++;
if (iType == SUMA_SUREFIT) {
if (kar+1 >= argc) {
fprintf (SUMA_STDERR, "need 2 argument after -sv (SurfaceVolume and VolumeParent)\n");
exit (1);
}
sv_name = argv[kar]; kar ++;
vp_name = argv[kar];
} else {
if (kar >= argc) {
fprintf (SUMA_STDERR, "need argument after -sv \n");
exit (1);
}
sv_name = argv[kar];
}
brk = YUP;
}
if (!brk && (strcmp(argv[kar], "-o_fs") == 0)) {
kar ++;
if (kar >= argc) {
fprintf (SUMA_STDERR, "need argument after -o_fs \n");
exit (1);
}
of_name = argv[kar];
oType = SUMA_FREE_SURFER;
brk = YUP;
}
if (!brk && (strcmp(argv[kar], "-o_sf") == 0)) {
kar ++;
if (kar+1 >= argc) {
fprintf (SUMA_STDERR, "need 2 arguments after -o_sf\n");
exit (1);
}
of_name = argv[kar]; kar ++;
of_name2 = argv[kar];
oType = SUMA_SUREFIT;
brk = YUP;
}
if (!brk && (strcmp(argv[kar], "-o_fsp") == 0)) {
kar ++;
if (kar >= argc) {
fprintf (SUMA_STDERR, "need 1 argument after -o_fsp\n");
exit (1);
}
of_name = argv[kar];
oType = SUMA_FREE_SURFER_PATCH;
brk = YUP;
}
if (!brk && ( (strcmp(argv[kar], "-o_vec") == 0) || (strcmp(argv[kar], "-o_1d") == 0) ) ) {
kar ++;
if (kar+1 >= argc) {
fprintf (SUMA_STDERR, "need 2 argument after -o_vec\n");
exit (1);
}
of_name = argv[kar]; kar ++;
of_name2 = argv[kar];
oType = SUMA_VEC;
brk = YUP;
}
if (!brk && (strcmp(argv[kar], "-o_ply") == 0)) {
kar ++;
if (kar >= argc) {
fprintf (SUMA_STDERR, "need argument after -o_ply\n");
exit (1);
}
of_name = argv[kar];
oType = SUMA_PLY;
brk = YUP;
}
#endif
if (!brk && (strcmp(argv[kar], "-xmat_1d") == 0)) {
kar ++;
if (kar >= argc) {
fprintf (SUMA_STDERR, "need 1 argument after -xmat_1D\n");
exit (1);
}
xmat_name = argv[kar];
Doxmat = YUP;
brk = YUP;
}
if (!brk && (strcmp(argv[kar], "-polar_decomp") == 0)) {
Do_PolDec = YUP;
brk = YUP;
}
if (!brk && (strcmp(argv[kar], "-make_consistent") == 0)) {
Do_wind = YUP;
brk = YUP;
}
if (!brk && (strcmp(argv[kar], "-xcenter") == 0)) {
kar ++;
if (kar+2>= argc) {
fprintf (SUMA_STDERR, "need 3 arguments after -xcenter\n");
exit (1);
}
xcen[0] = atof(argv[kar]); ++kar;
xcen[1] = atof(argv[kar]); ++kar;
xcen[2] = atof(argv[kar]);
Docen = YUP;
brk = YUP;
}
if (!brk && (strcmp(argv[kar], "-native") == 0)) {
Do_native = YUP;
brk = YUP;
}
if (!brk && (strcmp(argv[kar], "-orient_out") == 0)) {
kar ++;
if (kar>= argc) {
fprintf (SUMA_STDERR, "need 1 argument after -orient_out\n");
exit (1);
}
snprintf(orcode, 4*sizeof(char), "%s", argv[kar]);
if (!SUMA_ok_orstring(orcode)) {
fprintf (SUMA_STDERR, "%s is a bad orientation string\n", orcode);
exit (1);
}
brk = YUP;
}
if (!brk && (strcmp(argv[kar], "-radial_to_sphere") == 0)) {
kar ++;
if (kar >= argc) {
fprintf (SUMA_STDERR, "need 1 argument after -radial_to_sphere\n");
exit (1);
}
DoR2S = atof(argv[kar]);
brk = YUP;
}
if (!brk && (strcmp(argv[kar], "-patch2surf") == 0)) {
Do_p2s = YUP;
brk = YUP;
}
if (!brk && (strcmp(argv[kar], "-tlrc") == 0)) {
Do_tlrc = YUP;
brk = YUP;
}
if (!brk && (strcmp(argv[kar], "-acpc") == 0)) {
Do_acpc = YUP;
brk = YUP;
}
if (!brk && (strcmp(argv[kar], "-mni_rai") == 0)) {
Do_mni_RAI = YUP;
brk = YUP;
}
if (!brk && (strcmp(argv[kar], "-mni_lpi") == 0)) {
Do_mni_LPI = YUP;
brk = YUP;
}
if (!brk && !ps->arg_checked[kar]) {
fprintf (SUMA_STDERR,"Error %s: Option %s not understood. Try -help for usage\n", FuncName, argv[kar]);
exit (1);
} else {
brk = NOPE;
kar ++;
}
}
/* transfer info from ps structure (backward compat) */
if (ps->o_N_surfnames) {
of_name = ps->o_surfnames[0];
of_name2 = ps->o_surftopo[0];
oType = ps->o_FT[0];
}
if (ps->i_N_surfnames) {
if_name = ps->i_surfnames[0];
if_name2 = ps->i_surftopo[0];
iType = ps->i_FT[0];
iForm = ps->i_FF[0];
}
if (ps->ipar_N_surfnames) {
ifpar_name = ps->ipar_surfnames[0];
ifpar_name2 = ps->ipar_surftopo[0];
iparType = ps->ipar_FT[0];
iparForm = ps->ipar_FF[0];
}
if (ps->N_sv) sv_name = ps->sv[0];
if (ps->N_vp) vp_name = ps->vp[0];
/* sanity checks */
if (Do_native && orcode[0] != '\0') {
SUMA_S_Err("Options -native and -orient_out are mutually exclusive");
exit(1);
}
if (Do_mni_LPI && Do_mni_RAI) {
fprintf (SUMA_STDERR,"Error %s:\nCombining -MNI_lpi and -MNI_rai options.\nNot good.", FuncName);
exit(1);
}
if (!if_name) {
fprintf (SUMA_STDERR,"Error %s: input surface not specified.\n", FuncName);
exit(1);
}
if (!of_name) {
fprintf (SUMA_STDERR,"Error %s: output surface not specified.\n", FuncName);
exit(1);
}
if (iType == SUMA_FT_NOT_SPECIFIED) {
fprintf (SUMA_STDERR,"Error %s: input type not recognized.\n", FuncName);
exit(1);
}
if (oType == SUMA_FT_NOT_SPECIFIED) {
fprintf (SUMA_STDERR,"Error %s: output type not recognized.\n", FuncName);
exit(1);
}
if (iType == SUMA_SUREFIT) {
if (!if_name2) {
fprintf (SUMA_STDERR,"Error %s: input SureFit surface incorrectly specified.\n", FuncName);
exit(1);
}
if (sv_name && !vp_name) {
fprintf (SUMA_STDERR,"Error %s: VolParent must specified with -sv potion for SureFit surfaces. \n", FuncName);
exit(1);
}
}
if (iType == SUMA_VEC) {
if (!if_name2) {
fprintf (SUMA_STDERR,"Error %s: input vec surface incorrectly specified.\n", FuncName);
exit(1);
}
}
if (( Do_mni_RAI || Do_mni_LPI) && !Do_tlrc) {
SUMA_SL_Warn ("I hope you know what you're doing.\nThe MNI transform should only be applied to a\nSurface in the AFNI tlrc coordinate space.\n");
}
if (Do_acpc && Do_tlrc) {
fprintf (SUMA_STDERR,"Error %s: You can't do -tlrc and -acpc simultaneously.\n", FuncName);
exit(1);
}
if ((Doxmat || Docen) && (Do_acpc || Do_tlrc)) {
fprintf (SUMA_STDERR,"Error %s: You can't do -tlrc or -acpc with -xmat_1D and -xcenter.\n", FuncName);
exit(1);
}
if ((!Doxmat && Docen)) {
fprintf (SUMA_STDERR,"Error %s: You can't use -xcenter without -xmat_1D.\n", FuncName);
exit(1);
}
if (oType == SUMA_SUREFIT) {
if (!of_name2) {
fprintf (SUMA_STDERR,"Error %s: output SureFit surface incorrectly specified. \n", FuncName);
exit(1);
}
}
if (oType == SUMA_VEC) {
if (!of_name2) {
fprintf (SUMA_STDERR,"Error %s: output vec surface incorrectly specified. \n", FuncName);
exit(1);
}
}
/* test for existence of input files */
if (!SUMA_filexists(if_name)) {
fprintf (SUMA_STDERR,"Error %s: %s not found.\n", FuncName, if_name);
exit(1);
}
if (if_name2) {
if (!SUMA_filexists(if_name2)) {
fprintf (SUMA_STDERR,"Error %s: %s not found.\n", FuncName, if_name2);
exit(1);
}
}
if (ifpar_name2) {
if (!SUMA_filexists(ifpar_name2)) {
fprintf (SUMA_STDERR,"Error %s: %s not found.\n", FuncName, ifpar_name2);
exit(1);
}
}
if (ifpar_name) {
if (!SUMA_filexists(ifpar_name)) {
fprintf (SUMA_STDERR,"Error %s: %s not found.\n", FuncName, ifpar_name);
exit(1);
}
}
if (xmat_name) {
if (!SUMA_filexists(xmat_name)) {
fprintf (SUMA_STDERR,"Error %s: %s not found.\n", FuncName, xmat_name);
exit(1);
}
} else {
if (Do_PolDec) {
SUMA_S_Err("-polar_decomp is useless without -xmat_1D");
exit(1);
}
}
if (sv_name) {
char *head = NULL, view[10];
head = SUMA_AfniPrefix(sv_name, view, NULL, &volexists);
if (!SUMA_AfniExistsView(volexists, view)) {
fprintf (SUMA_STDERR,"Error %s: volume %s not found.\n", FuncName, head);
exit(1);
}
if (head) SUMA_free(head); head = NULL;
}
if ((Do_tlrc || Do_acpc) && (!sv_name)) {
fprintf (SUMA_STDERR,"Error %s: -tlrc must be used with -sv option.\n", FuncName);
exit(1);
}
if (vp_name) {
if (!SUMA_filexists(vp_name)) {
fprintf (SUMA_STDERR,"Error %s: %s not found.\n", FuncName, vp_name);
exit(1);
}
}
/* check for existence of output files */
if (of_name2) {
SUMA_SFname *SFname;
SO_name = SUMA_2Prefix2SurfaceName (of_name, of_name2, NULL, vp_name, oType, &exists);
SFname = (SUMA_SFname *)SO_name;
OF_name2 = SUMA_copy_string(SFname->name_topo);
OF_name = SUMA_copy_string(SFname->name_coord);
} else {
SO_name = SUMA_Prefix2SurfaceName (of_name, vp_name, NULL, oType, &exists);
OF_name = SUMA_copy_string((char *) SO_name);
}
if (exists) {
if (OF_name2) fprintf (SUMA_STDERR,"Error %s: output file(s) %s and/or %s exist already.\n", FuncName, OF_name, OF_name2);
else fprintf (SUMA_STDERR,"Error %s: output file %s exists already.\n", FuncName, OF_name);
exit(1);
}
/* now for the real work */
if (Doxmat) {
MRI_IMAGE *im = NULL;
float *far=NULL;
int ncol, nrow;
im = mri_read_1D (xmat_name);
if (!im) {
SUMA_SLP_Err("Failed to read 1D file");
exit(1);
}
far = MRI_FLOAT_PTR(im);
ncol = im->nx;
nrow = im->ny;
if (nrow < 4 ) {
SUMA_SL_Err("Mat file must have\n"
"at least 4 columns.");
mri_free(im); im = NULL; /* done with that baby */
exit(1);
}
if (ncol < 3 ) {
SUMA_SL_Err("Mat file must have\n"
"at least 3 rows.");
mri_free(im); im = NULL; /* done with that baby */
exit(1);
}
if (nrow > 4) {
SUMA_SL_Warn( "Ignoring entries beyond 4th \n"
"column in transform file.");
}
if (ncol > 3) {
SUMA_SL_Warn( "Ignoring entries beyond 3rd\n"
"row in transform file.\n");
}
for (i=0; i < 3; ++i) {
M[i][0] = far[i];
M[i][1] = far[i+ncol];
M[i][2] = far[i+2*ncol];
M[i][3] = far[i+3*ncol];
}
mri_free(im); im = NULL;
if (Do_PolDec) {
#ifdef USE_DECOMPOSE_SHOEMAKE
/* a little something to do a polar decomposition on M into M = Q*S*/
{
float det, m[4][4], q[4][4], s[4][4];
char *stmp = SUMA_append_string("QS_",xmat_name);
FILE *fout = fopen(stmp,"w"); SUMA_free(stmp); stmp = NULL;
SUMA_S_Note("FixMe! #include above and if(1) here ...");
det = polar_decomp(M, q,s);
fprintf(fout,"#[M][D]: (D is the shift)\n");
for (i=0;i<3; ++i)
fprintf(fout,"#%.5f %.5f %.5f %.5f\n", M[i][0], M[i][1], M[i][2], M[i][3]);
fprintf(fout,"#Q:\n");
for (i=0;i<3; ++i)
fprintf(fout,"#%.5f %.5f %.5f %.5f\n", q[i][0], q[i][1], q[i][2], q[i][3]);
fprintf(fout,"#S:\n");
for (i=0;i<3; ++i)
fprintf(fout,"#%.5f %.5f %.5f %.5f\n", s[i][0], s[i][1], s[i][2], s[i][3]);
fprintf(fout,"#det: %f\n", det);
fprintf(fout,"#[Q][D]: A close xform to [M][D], without scaling.\n#M = Q*S\n");
for (i=0;i<3; ++i)
fprintf(fout,"%.5f %.5f %.5f %.5f\n", q[i][0], q[i][1], q[i][2], M[i][3]);
fclose(fout); SUMA_free(stmp); stmp = NULL;
}
/* replace user's xform with orthogonal one: */
fprintf(SUMA_STDOUT,"Replacing matrix:\n");
for (i=0;i<3; ++i)
fprintf(SUMA_STDOUT," %.5f %.5f %.5f %.5f\n", M[i][0], M[i][1], M[i][2], M[i][3]);
fprintf(SUMA_STDOUT," with matrix:\n");
for (i=0;i<3; ++i)
fprintf(SUMA_STDOUT," %.5f %.5f %.5f %.5f\n", q[i][0], q[i][1], q[i][2], M[i][3]);
for (i=0;i<3; ++i) { M[i][0] = q[i][0]; M[i][1] = q[i][1]; M[i][2] = q[i][2]; }
#else
{/* use the NIFTI polar decomposition function (same results as above)*/
mat33 Q, A;
for (i=0;i<3;++i) { A.m[i][0] = M[i][0]; A.m[i][1] = M[i][1]; A.m[i][2] = M[i][2]; }
Q = nifti_mat33_polar( A );
if (0) { /* save results to file for examination */
char *stmp = SUMA_append_string("Q2_",xmat_name);
FILE *fout = fopen(stmp,"w"); SUMA_free(stmp); stmp = NULL;
fprintf(fout,"#[M][D]: (D is the shift)\n");
for (i=0;i<3; ++i)
fprintf(fout,"#%.5f %.5f %.5f %.5f\n", M[i][0], M[i][1], M[i][2], M[i][3]);
fprintf(fout,"#Q:\n");
for (i=0;i<3; ++i)
fprintf(fout,"#%.5f %.5f %.5f \n", Q.m[i][0], Q.m[i][1], Q.m[i][2]);
fprintf(fout,"#[Q][D]: A close xform to [M][D], without scaling.\n");
for (i=0;i<3; ++i)
fprintf(fout,"%.5f %.5f %.5f %.5f\n", Q.m[i][0], Q.m[i][1], Q.m[i][2], M[i][3]);
fclose(fout); SUMA_free(stmp); stmp = NULL;
}
/* replace user's xform with orthogonal one: */
fprintf(SUMA_STDOUT,"Replacing matrix:\n");
for (i=0;i<3; ++i)
fprintf(SUMA_STDOUT," %.5f %.5f %.5f %.5f\n", M[i][0], M[i][1], M[i][2], M[i][3]);
fprintf(SUMA_STDOUT," with matrix:\n");
for (i=0;i<3; ++i)
fprintf(SUMA_STDOUT," %.5f %.5f %.5f %.5f\n", Q.m[i][0], Q.m[i][1], Q.m[i][2], M[i][3]);
for (i=0;i<3; ++i) { M[i][0] = Q.m[i][0]; M[i][1] = Q.m[i][1]; M[i][2] = Q.m[i][2]; }
}
#endif
}
}
/* prepare the name of the surface object to read*/
SO = SUMA_Load_Surface_Object_Wrapper ( if_name, if_name2, vp_name, iType, iForm, sv_name, 1);
if (!SO) {
fprintf (SUMA_STDERR,"Error %s: Failed to read input surface.\n", FuncName);
exit (1);
}
if (DoR2S > 0.0000001) {
if (!SUMA_ProjectSurfaceToSphere(SO, NULL , DoR2S , NULL)) {
SUMA_S_Err("Failed to project to surface");
exit(1);
}
}
if (ifpar_name) {
SOpar = SUMA_Load_Surface_Object_Wrapper ( ifpar_name, ifpar_name2, vp_name, iparType, iparForm, sv_name, 1);
if (!SOpar) {
fprintf (SUMA_STDERR,"Error %s: Failed to read input parent surface.\n", FuncName);
exit (1);
}
/* need edge list */
if (!SUMA_SurfaceMetrics_eng (SOpar,"EdgeList", NULL, 0, SUMAg_CF->DsetList)) {
SUMA_SL_Err("Failed to create edgelist for parent");
exit(1);
}
}
/* if Do_wind */
if (Do_wind) {
fprintf (SUMA_STDOUT,"Checking and repairing mesh's winding consistency...\n");
/* check the winding, but that won't fix the normals,
you'll have to recalculate those things, if need be ... */
if (!SUMA_SurfaceMetrics_eng (SO, "CheckWind", NULL, 0, SUMAg_CF->DsetList)) {
fprintf (SUMA_STDERR,"Error %s: Failed in SUMA_SurfaceMetrics.\n", FuncName);
exit(1);
}
}
if (Do_tlrc) {
fprintf (SUMA_STDOUT,"Performing talairach transform...\n");
/* form the tlrc version of the surface volume */
tlrc_name = (char *) SUMA_calloc (strlen(SO->VolPar->dirname)+strlen(SO->VolPar->prefix)+60, sizeof(char));
sprintf (tlrc_name, "%s%s+tlrc.HEAD", SO->VolPar->dirname, SO->VolPar->prefix);
if (!SUMA_filexists(tlrc_name)) {
fprintf (SUMA_STDERR,"Error %s: %s not found.\n", FuncName, tlrc_name);
exit(1);
}
/* read the tlrc header */
aset = THD_open_dataset(tlrc_name) ;
if( !ISVALID_DSET(aset) ){
fprintf (SUMA_STDERR,"Error %s: %s is not a valid data set.\n", FuncName, tlrc_name) ;
exit(1);
}
if( aset->warp == NULL ){
fprintf (SUMA_STDERR,"Error %s: tlrc_name does not contain a talairach transform.\n", FuncName);
exit(1);
}
warp = aset->warp ;
/* now warp the coordinates, one node at a time */
if (!SUMA_AFNI_forward_warp_xyz(warp, SO->NodeList, SO->N_Node)) {
fprintf (SUMA_STDERR,"Error %s: Failed in SUMA_AFNI_forward_warp_xyz.\n", FuncName);
exit(1);
}
}
if (Do_acpc) {
fprintf (SUMA_STDOUT,"Performing acpc transform...\n");
/* form the acpc version of the surface volume */
acpc_name = (char *) SUMA_calloc (strlen(SO->VolPar->dirname)+strlen(SO->VolPar->prefix)+60, sizeof(char));
sprintf (acpc_name, "%s%s+acpc.HEAD", SO->VolPar->dirname, SO->VolPar->prefix);
if (!SUMA_filexists(acpc_name)) {
fprintf (SUMA_STDERR,"Error %s: %s not found.\n", FuncName, acpc_name);
exit(1);
}
/* read the acpc header */
aset = THD_open_dataset(acpc_name) ;
if( !ISVALID_DSET(aset) ){
fprintf (SUMA_STDERR,"Error %s: %s is not a valid data set.\n", FuncName, acpc_name) ;
exit(1);
}
if( aset->warp == NULL ){
fprintf (SUMA_STDERR,"Error %s: acpc_name does not contain an acpc transform.\n", FuncName);
exit(1);
}
warp = aset->warp ;
/* now warp the coordinates, one node at a time */
if (!SUMA_AFNI_forward_warp_xyz(warp, SO->NodeList, SO->N_Node)) {
fprintf (SUMA_STDERR,"Error %s: Failed in SUMA_AFNI_forward_warp_xyz.\n", FuncName);
exit(1);
}
}
if (Do_mni_RAI) {
fprintf (SUMA_STDOUT,"Performing MNI_RAI transform...\n");
/* apply the mni warp */
if (!SUMA_AFNItlrc_toMNI(SO->NodeList, SO->N_Node, "RAI")) {
fprintf (SUMA_STDERR,"Error %s: Failed in SUMA_AFNItlrc_toMNI.\n", FuncName);
exit(1);
}
sprintf(orsurf,"RAI");
}
if (Do_mni_LPI) {
fprintf (SUMA_STDOUT,"Performing MNI_LPI transform...\n");
/* apply the mni warp */
if (!SUMA_AFNItlrc_toMNI(SO->NodeList, SO->N_Node, "LPI")) {
fprintf (SUMA_STDERR,"Error %s: Failed in SUMA_AFNItlrc_toMNI.\n", FuncName);
exit(1);
}
sprintf(orsurf,"LPI");
}
if (Doxmat) {
fprintf (SUMA_STDOUT,"Performing affine transform...\n");
if (LocalHead) {
for (i=0; i<3 ; ++i) {
fprintf (SUMA_STDERR,"M[%d][:] = %f %f %f %f\n", i, M[i][0], M[i][1], M[i][2], M[i][3]);
}
fprintf (SUMA_STDERR,"Cen[:] %f %f %f\n", xcen[0], xcen[1], xcen[2]);
}
if (Docen) {
if (!SUMA_ApplyAffine (SO->NodeList, SO->N_Node, M, xcen)) { SUMA_SL_Err("Failed to xform coordinates"); exit(1); }
} else {
if (!SUMA_ApplyAffine (SO->NodeList, SO->N_Node, M, NULL)) { SUMA_SL_Err("Failed to xform coordinates"); exit(1); }
}
}
if (orcode[0] != '\0') {
if (LocalHead) fprintf (SUMA_STDERR,"%s: Changing coordinates from %s to %s\n", FuncName, orsurf, orcode);
if (!SUMA_CoordChange(orsurf, orcode, SO->NodeList, SO->N_Node)) {
SUMA_S_Err("Failed to change coords.");
exit(1);
}
}
if (Do_p2s) {
SUMA_SurfaceObject *SOold = SO;
if (LocalHead) fprintf (SUMA_STDERR,"%s: Changing patch to surface...\n", FuncName);
SO = SUMA_Patch2Surf(SOold->NodeList, SOold->N_Node, SO->FaceSetList, SO->N_FaceSet, 3);
if (!SO) {
SUMA_S_Err("Failed to change patch to surface.");
exit(1);
}
/* get rid of old surface object */
SUMA_Free_Surface_Object(SOold);
}
if (Do_native) {
if (!SUMA_Delign_to_VolPar (SO, NULL)) {
SUMA_S_Err("Failed to transform coordinates to native space");
exit(1);
}
}
if (LocalHead) SUMA_Print_Surface_Object (SO, stderr);
fprintf (SUMA_STDOUT,"Writing surface...\n");
/* write the surface object */
switch (oType) {
case SUMA_SUREFIT:
if (!SUMA_Save_Surface_Object (SO_name, SO, SUMA_SUREFIT, SUMA_ASCII, NULL)) {
fprintf (SUMA_STDERR,"Error %s: Failed to write surface object.\n", FuncName);
exit (1);
}
break;
case SUMA_VEC:
if (!SUMA_Save_Surface_Object (SO_name, SO, SUMA_VEC, SUMA_ASCII, NULL)) {
fprintf (SUMA_STDERR,"Error %s: Failed to write surface object.\n", FuncName);
exit (1);
}
break;
case SUMA_FREE_SURFER:
if (!SUMA_Save_Surface_Object (SO_name, SO, SUMA_FREE_SURFER, SUMA_ASCII, NULL)) {
fprintf (SUMA_STDERR,"Error %s: Failed to write surface object.\n", FuncName);
exit (1);
}
break;
case SUMA_FREE_SURFER_PATCH:
if (!SUMA_Save_Surface_Object (SO_name, SO, SUMA_FREE_SURFER_PATCH, SUMA_ASCII, SOpar)) {
fprintf (SUMA_STDERR,"Error %s: Failed to write surface object.\n", FuncName);
exit (1);
}
break;
case SUMA_OPENDX_MESH:
if (!SUMA_Save_Surface_Object (SO_name, SO, SUMA_OPENDX_MESH, SUMA_ASCII, NULL)) {
fprintf (SUMA_STDERR,"Error %s: Failed to write surface object.\n", FuncName);
exit (1);
}
break;
case SUMA_PLY:
if (!SUMA_Save_Surface_Object (SO_name, SO, SUMA_PLY, SUMA_FF_NOT_SPECIFIED, NULL)) {
fprintf (SUMA_STDERR,"Error %s: Failed to write surface object.\n", FuncName);
exit (1);
}
break;
default:
fprintf (SUMA_STDERR,"Error %s: Bad format.\n", FuncName);
exit(1);
}
if (of_name_strip) of_name_strip = SUMA_Free_Parsed_Name (of_name_strip);
if (of_name2_strip) of_name2_strip = SUMA_Free_Parsed_Name (of_name2_strip);
if (OF_name) SUMA_free(OF_name);
if (OF_name2) SUMA_free(OF_name2);
if (SF_name) SUMA_free(SF_name);
if (SO_name) SUMA_free(SO_name);
if (SO) SUMA_Free_Surface_Object(SO);
if (SOpar) SUMA_Free_Surface_Object(SOpar);
if (ps) SUMA_FreeGenericArgParse(ps); ps = NULL;
return (0);
}
syntax highlighted by Code2HTML, v. 0.9.1