void machdep()
{
   long seed ;
   static int first=1 ;

   if( !first ) return ; else first = 0 ;

   /*-- force use of mcw_malloc.c functions - 05 Nov 2001 --*/

#ifdef USING_MCW_MALLOC
   if( AFNI_yesenv("AFNI_FORCE_MCW_MALLOC") ) enable_mcw_malloc();
#endif

   /*-- disable mmap() in malloc() [21 Aug 2002: mostly] --*/

#if defined(LINUX) && defined(M_MMAP_MAX)
   mallopt( M_MMAP_MAX , 1 ) ;
#endif

   seed = (long)AFNI_numenv("AFNI_RANDOM_SEEDVAL") ;
   init_rand_seed(seed) ;

   be_quiet = AFNI_yesenv("AFNI_QUIET_STARTUP") ;  /* 08 Dec 2010 */

   if( AFNI_yesenv("AFNI_USE_FGETS") ) afni_fgets_setskip(1) ; /* 21 Dec 2011 */

   AFNI_do_nothing() ; /* 02 Oct 2012 */
   return ;
}
Exemple #2
0
DEFINE_MODEL_PROTOTYPE

MODEL_interface * initialize_model ()
{
  MODEL_interface * mi = NULL;

  /*----- first, see if the user wants help -----*/
  if( AFNI_yesenv("AFNI_MODEL_HELP_CONVDIFFGAM") ||
        AFNI_yesenv("AFNI_MODEL_HELP_ALL") ) model_help();

  /*----- allocate memory space for model interface -----*/

  mi = (MODEL_interface *) XtMalloc (sizeof(MODEL_interface));

  /*----- name of this model -----*/

  strcpy (mi->label, "ConvDiffGam");

  /*----- this is a signal model -----*/

  mi->model_type = MODEL_SIGNAL_TYPE;

  /*----- number of parameters in the model -----*/

  mi->params = 8;

  /*----- parameter labels -----*/

  strcpy (mi->plabel[0], "A0");
  strcpy (mi->plabel[1], "T0");
  strcpy (mi->plabel[2], "E0");
  strcpy (mi->plabel[3], "D0");
  strcpy (mi->plabel[4], "A1");
  strcpy (mi->plabel[5], "T1");
  strcpy (mi->plabel[6], "E1");
  strcpy (mi->plabel[7], "D1");

  /*----- minimum and maximum parameter constraints -----*/

  mi->min_constr[0] =     0.0;    mi->max_constr[0] =    10.0;
  mi->min_constr[1] =     0.0;    mi->max_constr[1] =    10.0;
  mi->min_constr[2] =     0.0;    mi->max_constr[2] =    10.0;
  mi->min_constr[3] =     0.0;    mi->max_constr[3] =    10.0;

  mi->min_constr[4] =     0.0;    mi->max_constr[4] =    10.0;
  mi->min_constr[5] =     0.0;    mi->max_constr[5] =    10.0;
  mi->min_constr[6] =     0.0;    mi->max_constr[6] =    10.0;
  mi->min_constr[7] =     0.0;    mi->max_constr[7] =    10.0;

  /*----- function which implements the model -----*/
  mi->call_func = conv_model;

  return (mi);
}
Exemple #3
0
/* get current value (maybe default value) for image globalrange */
int THD_get_image_globalrange()
{
   char *temp_envstr = NULL;

   if(image_globalrange<0) {
      if(AFNI_yesenv("AFNI_IMAGE_GLOBALRANGE")) image_globalrange = 1;
      else {
         temp_envstr = my_getenv("AFNI_IMAGE_GLOBALRANGE");
         if(temp_envstr){
            if((strcasecmp(temp_envstr,"VOLUME")==0) ||
               (strcasecmp(temp_envstr,"SUBBRICK")==0))
               image_globalrange = 1;   /* also same as "YES" */
            else if ((strcasecmp(temp_envstr,"DSET")==0) ||
                      (strcasecmp(temp_envstr,"DATASET")==0))
               image_globalrange = 2;   /* apply display LUT based on whole dataset */
         }
         if(image_globalrange < 0)
            image_globalrange = 0;   /* default to slice-based scaling */
      }
   }

   return(image_globalrange);
}
Exemple #4
0
char * commaized_integer_string( long long val )
{
   static char svals[9][128] ;   /* ZSS Aug. 2010 */
   char *sval;
   char qval[128] ;
   int qq,ss , qpos , qlen , pval = (val >= 0) ;
   static int k=0;

   /* without these three lines, a call like this:
      sprintf(str,"Hello %s, %s\n",
               commaized_integer_string(100),
               commaized_integer_string(500));
      would fail to write out both numbers.  ZSS Aug. 2010*/
   k = k % 9;
   sval = svals[k];
   ++k;

   sprintf(qval,"%lld",val) ; qlen = strlen(qval) ;

   if( AFNI_yesenv("AFNI_DONT_COMMAIZE") ||
       ( pval && qlen <= 3)              ||
       (!pval && qlen <= 4)                ){ strcpy(sval,qval); return sval; }

   if( pval ) qpos = (qlen-1) % 3 + 1 ;
   else       qpos = (qlen-2) % 3 + 2 ;

   for( qq=0 ; qq < qpos ; qq++ ) sval[qq] = qval[qq] ;
   ss = qpos ;
   for( ; qq < qlen ; ){
     sval[ss++] = ','        ;
     sval[ss++] = qval[qq++] ;
     sval[ss++] = qval[qq++] ;
     sval[ss++] = qval[qq++] ;
   }
   sval[ss] = '\0' ; return sval ;
}
Exemple #5
0
/*!\**
File : SUMA.c
\author : Ziad Saad
Date : Thu Dec 27 16:21:01 EST 2001
   
Purpose : 
   
   
   
Input paramters : 
\param   
\param   
   
Usage : 
      SUMA ( )
   
   
Returns : 
\return   
\return   
   
Support : 
\sa   OpenGL prog. Guide 3rd edition
\sa   varray.c from book's sample code
   
Side effects : 
   
   
   
***/
int main (int argc,char *argv[])
{/* Main */
   static char FuncName[]={"suma"}; 
   int kar, i;
   SUMA_SFname *SF_name;
   SUMA_Boolean brk, SurfIn;
   char  *NameParam, *AfniHostName = NULL, *s = NULL, *pdspec=NULL, *pdsv=NULL;
   char *specfilename[SUMA_MAX_N_GROUPS], *VolParName[SUMA_MAX_N_GROUPS];
   byte InMem[SUMA_MAX_N_GROUPS];
   SUMA_SurfSpecFile *Specp[SUMA_MAX_N_GROUPS];   
   SUMA_Axis *EyeAxis;    
   SUMA_EngineData *ED= NULL;
   DList *list = NULL;
   DListElmt *Element= NULL;
   int iv15[15], N_iv15, ispec, nspec;
   struct stat stbuf;
   float fff=0.0;
   int Start_niml = 0;
   SUMA_Boolean  Domemtrace = YUP;
   SUMA_GENERIC_ARGV_PARSE *ps=NULL;
   SUMA_Boolean LocalHead = NOPE;
   
    
   SUMA_STANDALONE_INIT;
   SUMA_mainENTRY;
   
   
   SUMAg_CF->isGraphical = YUP;
   
   ps = SUMA_Parse_IO_Args(argc, argv, "-i;-t;-dset;-do;");

   /* initialize Volume Parent and AfniHostName to nothing */
   for (ispec=0; ispec < SUMA_MAX_N_GROUPS; ++ispec) {
      specfilename[ispec] = NULL;
      VolParName[ispec] = NULL;
      Specp[ispec] = NULL;
      InMem[ispec] = 0;
   }
   AfniHostName = NULL; 
   
      
   /* Allocate space for DO structure */
   SUMAg_DOv = SUMA_Alloc_DisplayObject_Struct (SUMA_MAX_DISPLAYABLE_OBJECTS);
   
   /* call the function to parse the other surface mode inputs */
   ispec = 0;
   if (LocalHead) SUMA_Show_IO_args(ps);
   if (ps->i_N_surfnames || ps->t_N_surfnames || ps->N_DO) {
      SUMA_LH("-i and/or -t surfaces on command line!");
      Specp[ispec] = SUMA_IO_args_2_spec (ps, &nspec); 
      if (Specp[ispec]) {
         ++ispec;
         if (nspec != 1) {
            SUMA_S_Errv("-spec is being parsed separately here, "
                        "expecting one spec only from SUMA_IO_args_2_spec, \n"
                        "got %d\n", nspec);
            exit (1);
         }
      } else {
         SUMA_S_Err("Failed to load -i/-t surfaces");
         exit(1);
      }
      
   }
   /* Work the options */
   kar = 1;
   brk = NOPE;
   SurfIn = NOPE;
   Domemtrace = YUP; 
   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) {
         SUMA_usage (ps, strlen(argv[kar]) > 3 ? 2:1);
          exit (0); /* return a good status on -help   12 Jul 2013 [rickr] */
      }
      
      /* -list_ports list and quit */
      if( strncmp(argv[kar],"-list_ports", 8) == 0) {
         show_ports_list(); exit(0);
      }
      
      /* -port_number and quit */
      if( strncmp(argv[kar],"-port_number", 8) == 0) {
         int pp = 0;
         if( ++kar >= argc ) 
            ERROR_exit("need an argument after -port_number!"); 
         pp = get_port_named(argv[kar]);
         if (strcmp(argv[kar-1], "-port_number_quiet")) { 
            fprintf(stdout, "\nPort %s: %d\n", argv[kar], pp); 
         } else {
            fprintf(stdout, "%d\n", pp); 
         }
         if (pp < 1) exit(1);
         else exit(0);
      }
      
      if (strcmp(argv[kar], "-visuals") == 0) {
          SUMA_ShowAllVisuals ();
          exit (0);
      }
      
      if (strcmp(argv[kar], "-brethren_windows") == 0) {
          Display *dd=NULL; Window ww;
          if (!(dd = XOpenDisplay(NULL))) {
            SUMA_S_Err("No display "); exit(1);
          }
          ww = XDefaultRootWindow(dd);
          
          SUMA_WindowsOnRootDisplay(dd, ww , 0);
          exit (0);
      }
      
      if (strcmp(argv[kar], "-version") == 0) {
          s = SUMA_New_Additions (0.0, 1);
          fprintf (SUMA_STDOUT,"%s\n", s); 
          SUMA_free(s); s = NULL;
          exit (0);
      }
      
      if (strcmp(argv[kar], "-sources") == 0) {
          s = SUMA_sources_Info();
          fprintf (SUMA_STDOUT,"%s\n", s); 
          SUMA_free(s); s = NULL;
          exit (0);
      }
      
      if (strcmp(argv[kar], "-help_nido") == 0) {
         s = SUMA_NIDO_Info();
         fprintf (SUMA_STDOUT,"%s\n", s); 
         SUMA_free(s); s = NULL;
         exit (0);
      }
      
      if (strcmp(argv[kar], "-all_latest_news") == 0) {
          s = SUMA_New_Additions (-1.0, 0);
          fprintf (SUMA_STDOUT,"%s\n", s); 
          SUMA_free(s); s = NULL;
          exit (0);
      }
      
      if (strcmp(argv[kar], "-help_sphinx_interactive") == 0) {
         FILE *fout = NULL;
         if( ++kar >= argc ) 
            ERROR_exit("need a file name after -help_sphinx_interactive!");       
          fout = fopen(argv[kar],"w");
          if (!fout) {
            SUMA_S_Err("Failed to open %s for writing", argv[kar]);
            exit(1);
          }
          SUMA_help_message(fout,SPX);
          fclose(fout); fout = NULL;
          exit (0);
      }
      
      if (strcmp(argv[kar], "-help_interactive") == 0) {
          FILE *fout = fopen("Mouse_Keyboard_Controls.txt","w");
          if (!fout) {
            SUMA_S_Err("Failed to open Mouse_Keyboard_Controls.txt for writing");
            exit(1);
          }
          SUMA_help_message(fout,TXT);
          fclose(fout); fout = NULL;
          exit (0);
      }
      
      if (strcmp(argv[kar], "-test_help_string_edit") == 0) {
         SUMA_Sphinx_String_Edit_Help(SUMA_STDOUT, 0);
         exit(0);
      }
      if (strcmp(argv[kar], "-test_help_string_edit_web") == 0) {
         SUMA_Sphinx_String_Edit_Help(SUMA_STDOUT, 1);
         exit(0);
      }
      
      if (strcmp(argv[kar], "-environment") == 0) {
          s = SUMA_env_list_help (0, TXT);
          fprintf (SUMA_STDOUT,  
            "#SUMA ENVIRONMENT \n"
            "# If you do not have a ~/.sumarc file, cannot find a SUMA\n"
            "# environment variable that's been mentioned in documentation,\n"
            "# or fervently desire to update your current ~/.sumarc with  \n"
            "# all the latest variables that SUMA uses, you should run: \n"
            "# \n"
            "#    suma -update_env\n"
            "# \n"
            "# Unless you have setup SUMA environment variables outside of\n"
            "# your ~/.sumarc file, updating your ~/.sumarc file with \n"
            "# 'suma -update_env' WILL NOT ALTER changes you have already\n"
            "# made to the variables in your current ~/.sumarc. \n"
            "# For this reason consider running the update command after each \n"
            "# upgrade of your AFNI/SUMA binaries.\n" 
            "***ENVIRONMENT\n"
                  "%s\n", s); 
          SUMA_free(s); s = NULL;
          exit (0);
      }
      
      if (strcmp(argv[kar], "-default_env") == 0) {
          s = SUMA_env_list_help (1, NO_FORMAT);
          fprintf (SUMA_STDOUT,  
                  "#SUMA DEFAULT ENVIRONMENT (user settings ignored)\n"
                  "# see also suma -udate_env or suma -environment\n"
                  "# \n"
                  "***ENVIRONMENT\n"
                  "%s\n", s); 
          SUMA_free(s); s = NULL;
          exit (0);
      }
      
      if (strcmp(argv[kar], "-update_env") == 0) {
          if (system("suma -environment > ___sumarc")) {
            SUMA_S_Err("Failed to create env file.");
            exit(1);
          }
          if (SUMA_filexists("~/.sumarc")) {
            if (system("\\cp -f ~/.sumarc ~/.sumarc-bak")) {
               SUMA_S_Err("Failed to backup ~/.sumarc to ~/.sumarc-bak.");
               exit(1);
            }
          }
          if (system("\\mv ___sumarc ~/.sumarc")) {
            SUMA_S_Err("Failed to copy newrc (___sumarc) to ~/.sumarc");
            exit(1); 
          }
          SUMA_S_Note("Environment update done.");
          exit(0);
      }
      
      if (strcmp(argv[kar], "-latest_news") == 0) {
          s = SUMA_New_Additions (0.0, 0);
          fprintf (SUMA_STDOUT,"%s\n", s); 
          SUMA_free(s); s = NULL;
          exit (0);
      }
      
      if (strcmp(argv[kar], "-progs") == 0) {
          s = SUMA_All_Programs();
          fprintf (SUMA_STDOUT,"%s\n", s); 
          SUMA_free(s); s = NULL;
          exit (0);
      }
      
      if (strcmp(argv[kar], "-motif_ver") == 0) {  /* 9 Mar 2009 [rickr] */
         show_motif_version_string();
         exit (0);
      }
      
      if (!brk && (strcmp(argv[kar], "-iodbg") == 0)) {
         fprintf(SUMA_STDERR,"Error %s: Obsolete, use -trace\n", FuncName);
         exit (0);
         /*
         fprintf(SUMA_STDOUT,
                 "Warning %s: SUMA running in in/out debug mode.\n", FuncName);
         SUMA_INOUT_NOTIFY_ON; 
         brk = YUP;
         */
      }
      
      
      
      SUMA_SKIP_COMMON_OPTIONS(brk, kar);
      
      #if SUMA_MEMTRACE_FLAG
         if (!brk && (strcmp(argv[kar], "-memdbg") == 0)) {
            fprintf(SUMA_STDOUT,"Error %s: -memdbg is obsolete, use -trace\n", 
                                FuncName);
            exit (0);
            fprintf( SUMA_STDOUT,
                     "Warning %s: SUMA running in memory trace mode.\n", 
                     FuncName);
            SUMAg_CF->MemTrace = YUP;
            #ifdef USING_MCW_MALLOC
            #endif
            brk = YUP;
         }
      #endif
      
      if (!brk && (strcmp(argv[kar], "-dev") == 0)) {
         fprintf(SUMA_STDOUT,
                  "Warning %s: SUMA running in developer mode, "
                  "some options may malfunction.\n", FuncName);
         SUMAg_CF->Dev = YUP;
         brk = YUP;
      }
      
      if (!brk && (strcmp(argv[kar], "-fake_cmap") == 0)) {
         SUMA_S_Warn("-fake_cmap is for automatic selfies of the widgets.\n"
                     "You should not use this option for any other reason\n");
         SUMAg_CF->Fake_Cmap = YUP;
         brk = YUP;
      }
      
      if (!brk && SUMAg_CF->Dev && (strcmp(argv[kar], "-truth_table") == 0)) {
         kar ++;
         if (kar >= argc)  {
              fprintf (SUMA_STDERR, "need expression after -truth_table \n");
            exit (1);
         }
         SUMA_bool_eval_truth_table(argv[kar], 0);  exit(0);
         brk = YUP;
      }
      
      if (!brk && (strcmp(argv[kar], "-niml") == 0)) {
         Start_niml = 1;
         brk = YUP;
      }

      if (!brk && (strcmp(argv[kar], "-noniml") == 0)) {
         Start_niml = -1;
         brk = YUP;
      }
      
      if (!brk && (strcmp(argv[kar], "-vp") == 0 || 
                   strcmp(argv[kar], "-sa") == 0 || 
                   strcmp(argv[kar], "-sv") == 0))
      {
         kar ++;
         if (kar >= argc)  {
              fprintf (SUMA_STDERR, "need argument after -vp|-sa|-sv \n");
            exit (1);
         }
         if (ispec < 1) {
            fprintf (SUMA_STDERR, 
                     "a -spec option must precede the first -sv option\n");
            exit (1);
         }
         if (!specfilename[ispec-1] && !Specp[ispec-1]) {
            fprintf (SUMA_STDERR, 
                     "a -spec option must precede each -sv option\n");
            exit (1);
         }
         VolParName[ispec-1] = argv[kar]; 
         if (LocalHead) {
            fprintf(SUMA_STDOUT, "Found: %s\n", VolParName[ispec]);
         }
         
         brk = YUP;
      }      
      
      if (!brk && strcmp(argv[kar], "-drive_com") == 0)
      {
         kar ++;
         if (kar >= argc)  {
              fprintf (SUMA_STDERR, "need argument after -drive_com\n");
            exit (1);
         }
         SUMAg_CF->dcom = (char **)SUMA_realloc(SUMAg_CF->dcom,
                                          (SUMAg_CF->N_dcom+1)*sizeof(char *));
         SUMAg_CF->dcom[SUMAg_CF->N_dcom] = SUMA_copy_string(argv[kar]);
         ++SUMAg_CF->N_dcom;
         brk = YUP;
      }
      
      if (!brk && strcmp(argv[kar], "-ah") == 0)
      {
         kar ++;
         if (kar >= argc)  {
              fprintf (SUMA_STDERR, "need argument after -ah\n");
            exit (1);
         }
         if (strcmp(argv[kar],"localhost") != 0) {
            AfniHostName = argv[kar];
         }else {
           fprintf (SUMA_STDERR, 
                    "localhost is the default for -ah\n"
                    "No need to specify it.\n");
         }
         /*fprintf(SUMA_STDOUT, "Found: %s\n", AfniHostName);*/

         brk = YUP;
      }   
      
      if (!brk && strcmp(argv[kar], "-spec") == 0)
      { 
         kar ++;
         if (kar >= argc)  {
              fprintf (SUMA_STDERR, "need argument after -spec \n");
            exit (1);
         }
         
         if (ispec >= SUMA_MAX_N_GROUPS) {
            fprintf (SUMA_STDERR, 
                     "Cannot accept more than %d spec files.\n",     
                     SUMA_MAX_N_GROUPS);
            exit(1);
         }
         
         if (SUMA_is_predefined_SO_name(argv[kar], NULL, 
                                        &pdspec, &pdsv, NULL) == 3) {
            specfilename[ispec] = pdspec; pdspec = NULL; /* Memory leak! */
            VolParName[ispec] = pdsv; pdsv = NULL; /* Memory leak! */
         } else {
            specfilename[ispec] = argv[kar]; 
         }
         if (LocalHead) {
            fprintf(SUMA_STDOUT, "Found: %s\n", specfilename[ispec]);
         }
         ++ispec;
         brk = YUP;
      } 
      
      
      if (!brk && !ps->arg_checked[kar]) {
         if (  !strcmp(argv[kar], "-i") ||
               !strncmp(argv[kar], "-i_",3) ) {
            fprintf (SUMA_STDERR,
      "Error %s: Option %s not understood. \n"
      "  Make sure parameter after -i or -i_ is the full name of a surface.\n"
      "%s",
      FuncName, argv[kar], 
      strlen(argv[kar])==2 ? 
         "For -i to work, SUMA needs to guess at the surface type from\n"
         "  the filename extensions. If SUMA fails try the full -i_* option"
         " instead.\n" : ""
      );
         } else {
            fprintf (SUMA_STDERR,
                  "Error %s: Option %s not understood. Try -help for usage\n", 
                  FuncName, argv[kar]);
            suggest_best_prog_option(argv[0], argv[kar]);
         }
         exit (1);
      } else {   
         brk = NOPE;
         kar ++;
      }
      
   }/* loop accross command ine options */
   /* -ah option now checked for in ps */
   if (ps->cs->afni_host_name && !AfniHostName) {
      AfniHostName = SUMA_copy_string(ps->cs->afni_host_name);
   }
   
   #if 0
   SUMA_S_Note("KILL ME");
   { 
      int i,j, nl; 
      SUMA_TextBoxSize("Hello", &i,&j,&nl,NULL); 
      SUMA_TextBoxSize("", 
                        &i,&j,&nl,GLUT_BITMAP_8_BY_13); 
      SUMA_TextBoxSize("O", 
                        &i,&j,&nl,GLUT_BITMAP_8_BY_13); 
                        SUMA_TextBoxSize(NULL, 
                        &i,&j,&nl,GLUT_BITMAP_8_BY_13); 
   }
   SUMA_ReadNIDO("/Users/ziad/SUMA_test_dirs/DO/TextDO/sample.niml.do", NULL);   
   exit(1);
      
   #endif
      
   /* Make surface loading pacifying */
   SetLoadPacify(1);
   
   #if 0
   if (ps->N_DO) { /* Have DOs on command line */
      if (Specp[0]) { /* Add to Specp[0] */
         if (ps->N_DO + Specp[0]->N_DO > SUMA_MAX_DO_SPEC) {
            SUMA_S_Warn("Too many DOs, increase static limit..");
                                       /* ignore extras for now */
            ps->N_DO = SUMA_MAX_DO_SPEC - Specp[0]->N_DO;
         }
         for (i=0; i<ps->N_DO; ++i) {
            strcpy(Specp[0]->DO_name[Specp[0]->N_DO], ps->DO_name[i]);
            Specp[0]->DO_type[Specp[0]->N_DO] = ps->DO_type[i];
            ++Specp[0]->N_DO;
         }
      } else {
         Specp[0]
      }
   }
   #endif
      
   /* any Specp to be found ?*/
   if (specfilename[0] == NULL && Specp[0] == NULL) {
      SUMA_SurfaceObject **SOv=NULL;
      int N_SOv = 0;
      fprintf (SUMA_STDERR,
               "\n"
               "%s: \n"
               "     No input specified, loading some toy surfaces...\n"
               "     Use '.' and ',' to cycle between them.\n"
               "     See suma -help for assistance.\n"
               "\n", FuncName);
      /* create your own surface and put it in a spec file */
      SOv = SUMA_GimmeSomeSOs(&N_SOv);
      Specp[ispec] = SUMA_SOGroup_2_Spec (SOv, N_SOv);
      SUMA_free(SOv); SOv = NULL;
      InMem[ispec] = 1;
      ++ispec;
   }

   if(!SUMA_Assign_HostName (SUMAg_CF, AfniHostName, -1)) {
      fprintf (SUMA_STDERR, 
         "Error %s: Failed in SUMA_Assign_HostName\n", FuncName);
      exit (1);
   }
   
   #ifdef SUMA_DISASTER
   /* a function to test Memtracing */
   {
      int *jnk;
      jnk = SUMA_disaster();
      SUMA_free(jnk); /* without the -trace, you'll get a 
                           warning here if jnk is corrupted */
   }
   #endif
   
   /* create an Eye Axis DO */
   EyeAxis = SUMA_Alloc_Axis ("Eye Axis", AO_type);
   if (EyeAxis == NULL) {
      SUMA_error_message (FuncName,"Error Creating Eye Axis",1);
      exit(1);
   }

   /* Store it into SUMAg_DOv */
   if (!SUMA_AddDO(  SUMAg_DOv, &SUMAg_N_DOv, 
                     (void *)EyeAxis,  AO_type, SUMA_SCREEN)) {
      SUMA_error_message (FuncName,"Error Adding DO", 1);
      exit(1);
   }
   /*fprintf (SUMA_STDERR, "SUMAg_N_DOv = %d created\n", SUMAg_N_DOv);
   SUMA_Show_DOv(SUMAg_DOv, SUMAg_N_DOv, NULL);*/

   /* Allocate space (and initialize) Surface Viewer Structure */
   SUMAg_SVv = SUMA_Alloc_SurfaceViewer_Struct (SUMA_MAX_SURF_VIEWERS);
   
   /* SUMAg_N_SVv gets updated in SUMA_X_SurfaceViewer_Create
   and reflects not the number of elements in SUMAg_SVv which is
   SUMA_MAX_SURF_VIEWERS, but the number of viewers that were realized
   by X */
   
   /* Check on initialization */
   /*SUMA_Show_SurfaceViewer_Struct (SUMAg_cSV, stdout);*/

   /* Create the Surface Viewer Window */
   if (!SUMA_X_SurfaceViewer_Create ()) {
      fprintf(stderr,"Error in SUMA_X_SurfaceViewer_Create. Exiting\n");
      return 1;
   }
   
   for (i=0; i<ispec; ++i) {
      if (!list) list = SUMA_CreateList();
      ED = SUMA_InitializeEngineListData (SE_Load_Group);
      if (!( Element = SUMA_RegisterEngineListCommand (  list, ED, 
                                             SEF_cp, (void *)specfilename[i], 
                                             SES_Suma, NULL, NOPE, 
                                             SEI_Head, NULL ))) {
         fprintf(SUMA_STDERR,"Error %s: Failed to register command\n", FuncName);
         exit (1);
      }
      if (!( Element = SUMA_RegisterEngineListCommand (  list, ED, 
                                             SEF_ip, (void *)Specp[i], 
                                             SES_Suma, NULL, NOPE, 
                                             SEI_In, Element ))) {
         fprintf(SUMA_STDERR,"Error %s: Failed to register command\n", FuncName);
         exit (1);
      }
      fff = (float) InMem[i];
      if (!( Element = SUMA_RegisterEngineListCommand (  list, ED, 
                                             SEF_f, (void *)&fff, 
                                             SES_Suma, NULL, NOPE, 
                                             SEI_In, Element ))) {
         fprintf(SUMA_STDERR,"Error %s: Failed to register command\n", FuncName);
         exit (1);
      }
      if (!( Element = SUMA_RegisterEngineListCommand (  list, ED, 
                                             SEF_vp, (void *)VolParName[i], 
                                             SES_Suma, NULL, NOPE, 
                                             SEI_In, Element ))) {
         fprintf(SUMA_STDERR,"Error %s: Failed to register command\n", FuncName);
         exit (1);
      }

      N_iv15 = SUMA_MAX_SURF_VIEWERS;
      if (N_iv15 > 15) {
         fprintf( SUMA_STDERR,
                  "Error %s: trying to register more than 15 viewers!\n", 
                  FuncName);
         exit(1);
      }
      for (kar=0; kar<N_iv15; ++kar) iv15[kar] = kar;
      if (!( Element = SUMA_RegisterEngineListCommand (  list, ED, 
                                             SEF_iv15, (void *)iv15, 
                                             SES_Suma, NULL, NOPE, 
                                             SEI_In, Element ))) {
         fprintf(SUMA_STDERR,"Error %s: Failed to register command\n", FuncName);
         exit (1);
      }

      if (!( Element = SUMA_RegisterEngineListCommand (  list, ED, 
                                             SEF_i, (void *)&N_iv15, 
                                             SES_Suma, NULL, NOPE, 
                                             SEI_In, Element ))) {
         fprintf(SUMA_STDERR,"Error %s: Failed to register command\n", FuncName);
         exit (1);
      }
   }
   
   if (ispec > 0 && !SUMA_Engine (&list)) {
      fprintf(SUMA_STDERR,"Error %s: Failed in SUMA_Engine\n", FuncName);
      exit (1);
   }
   
   /* For some reason, I had to add the glLightfv line below
   to force the lightflipping done in SUMA_SetupSVforDOs to take place
   in the A viewer when first opened. I don't know why that is, especially
   since other controllers would show up lit correctly without this 
   glLightfv line below.
      To make matters worse, the A controller's light0_position is correctly 
   flipped.
      It is just that the shading is done as if the position was never flipped. 
   Actually, without the line below, the first time you hit the F key (to 
   manually flip the light), nothing changes, that's because the light's position    is unflipped, which is supposed to show the incorrect lighting. 
   You'll have to hit F again to have the lighting correctly flipped 
   and the shading reflecting it.... ZSS, Aug. 05 04 */
   glLightfv(GL_LIGHT0, GL_POSITION, SUMAg_SVv[0].light0_position); 

   if (Start_niml != -1 && (Start_niml == 1|| AFNI_yesenv("SUMA_START_NIML"))) {
      if (!list) list = SUMA_CreateList();
      SUMA_REGISTER_HEAD_COMMAND_NO_DATA( list, SE_StartListening, 
                                          SES_Suma, NULL);

      if (!SUMA_Engine (&list)) {
         fprintf(SUMA_STDERR, "Error %s: SUMA_Engine call failed.\n", FuncName);
         exit (1);   
      }
   }
   
   /* load the datasets onto the first SO, if any, else hope that dset 
      is some form of DO  */
   if (ps->N_dsetname>0) {
      SUMA_SurfaceObject *SO = SUMA_findanySOp_inDOv(SUMAg_DOv, 
                                                     SUMAg_N_DOv, NULL);
      if (!SO) {
         SUMA_LH("Could not find any SO, here is hoping dset is a DO");
      }
      for (i=0; i<ps->N_dsetname; ++i) {
         if (!(SUMA_LoadDsetOntoSO_eng(ps->dsetname[i], SO, 1, 1, 1, NULL))) {
            SUMA_S_Errv("Failed to load %s onto %s\n", 
                        ps->dsetname[i], SO?SO->Label:"NULL");
         }
      }
   }

   SUMA_FreeGenericArgParse(ps); ps = NULL;
 
   /* A Warning about no sumarc */
   if (NoSumaRcFound()) { 
         SUMA_S_Warn(
"\n"
" No sumarc file found. You should create one by running the following:\n"
"\n"
"              suma -update_env\n"
"\n"
" I also recommend you run 'suma -update_env' whenever you update AFNI.\n" 
"\n"
" See details for -environment and -update_env options in suma -help's output.\n"
"\n");
   }
   
   /*Main loop */
   XtAppMainLoop(SUMAg_CF->X->App);

   
   /* Done, clean up time */
   if (ispec) {
      int k=0; 
      for (k=0; k<ispec; ++k) {
         if (!SUMA_FreeSpecFields((Specp[k]))) { 
            SUMA_S_Err("Failed to free spec fields"); 
         } 
         Specp[k] = NULL;
      }
   } ispec = 0;
  
   if (!SUMA_Free_Displayable_Object_Vect (SUMAg_DOv, SUMAg_N_DOv)) 
      SUMA_error_message(FuncName,"DO Cleanup Failed!",1);
   if (!SUMA_Free_SurfaceViewer_Struct_Vect (SUMAg_SVv, SUMA_MAX_SURF_VIEWERS)) 
      SUMA_error_message(FuncName,"SUMAg_SVv Cleanup Failed!",1);
   if (!SUMA_Free_CommonFields(SUMAg_CF)) 
      SUMA_error_message(FuncName,"SUMAg_CF Cleanup Failed!",1);
  SUMA_RETURN(0);             /* ANSI C requires main to return int. */
}/* Main */ 
Exemple #6
0
int main( int argc , char * argv[] )
{
   int nim , ii , jj , kk , nx, narg, oform ;
   MRI_IMAGE **inim ;
   float *far;
   char *formatstr=NULL, *sel=NULL, *fname=NULL;
   int nonconst=0 , ncol,ncold , cc , nonfixed=0 , stack=0;
   intvec *ncv=NULL ;
   char *hline=NULL ;

   mainENTRY("1dcat:main");
   
   /*-- help? --*/

   if( argc < 2 || strcmp(argv[1],"-help") == 0 ){
     printf(
"Usage: 1dcat [options] a.1D b.1D ...\n"
"  where each file a.1D, b.1D, etc. is a 1D file.\n"
"  In the simplest form, a 1D file is an ASCII file of numbers\n"
"  arranged in rows and columns.\n"
"\n"
"1dcat takes as input one or more 1D files, and writes out a 1D file\n"
"containing the side-by-side concatenation of all or a subset of the\n"
"columns from the input files.\n"
"\n"
"* Output goes to stdout (the screen); redirect (e.g., '>') to save elsewhere.\n"
"* All files MUST have the same number of rows!\n"
"* Any header lines (i.e., lines that start with '#') will be lost.\n"
"* For generic 1D file usage help and information, see '1dplot -help'\n"
"\n"
"OPTIONS:\n"
"--------\n"
"  -nonconst: Columns that are identically constant should be omitted\n"
"             from the output.\n"
"\n"
"  -nonfixed: Keep only columns that are marked as 'free' in the \n"
"             3dAllineate header from '-1Dparam_save'.\n"
"             If there is no such header, all columns are kept.\n"
"\n"
"  -form FORM: Format of the numbers to be output.\n"
"              You can also substitute -form FORM with shortcuts such \n"
"              as -i, -f, or -c.\n"
"              For help on -form's usage, and its shortcut versions\n"
"              see ccalc's help for the option of the same name. \n"
"\n"
"  -stack: Stack the columns of the resultant matrix in the output.\n"
"\n"
"  -sel SEL: Apply the same column/row selection string to all filenames\n"
"            on the command line.\n"
"            For example:\n"
"              1dcat -sel '[0,2]' f1.1D f2.1D\n"
"            is the same as: 1dcat f1.1D'[1,2]' f2.1D'[1,2]'\n"
"            The advantage of the option is that it allows wildcard use\n"
"            in file specification so that you can run something like:\n"
"              1dcat -sel '[0,2]' f?.1D\n"
"\n"
"EXAMPLE:\n"
"--------\n"
"  Input file 1:\n   1\n   2\n   3\n   4\n"
"  Input file 2:\n   5\n   6\n   7\n   8\n"
"\n"
"  1dcat data1.1D data2.1D > catout.1D\n" 
"  Output file: \n   1 5\n   2 6\n   3 7\n   4 8\n"
"\n"
           ) ;
      PRINT_COMPILE_DATE ; exit(0) ;
   }

   machdep() ;

   /* do we have any options? */
   oform = CCALC_NOT_SET; 
   sel = NULL;
   stack = 0;
   narg = 1;
   while (narg < argc && argv[narg][0] == '-') {

      if( strncmp(argv[narg],"-nonconst",7) == 0 ){  /* 04 Dec 2010 */
        nonconst++ ; narg++ ; continue ;
      }

      if( strncmp(argv[narg],"-nonfixed",7) == 0 ){  /* 06 Dec 2010 */
        nonfixed++ ; narg++ ; continue ;
      }
      
      if( strncmp(argv[narg],"-stack",6) == 0 ){  /* 05 Sep 2013 */
        stack = 1 ; narg++ ; continue ;
      }
      
      if (strcmp(argv[narg],"-form") == 0) {
         ++narg;
         if (narg >= argc)  {
	         fprintf (stderr, "need argument after -form ");
	         exit (1);
         }
         if (strcmp(argv[narg],"double") == 0 ) oform = CCALC_DOUBLE;
         else if (strcmp(argv[narg],"nice") == 0 ) oform = CCALC_NICE;
         else if (strcmp(argv[narg],"int") == 0 ) oform = CCALC_INT;
         else if (strcmp(argv[narg],"rint") == 0 ) oform = CCALC_INT;
         else if (strcmp(argv[narg],"fint") == 0 ) oform = CCALC_FINT;
         else if (strcmp(argv[narg],"cint") == 0 ) oform = CCALC_CINT;
         else if (strlen(argv[narg])<=256) {
            oform = CCALC_CUSTOM;
            formatstr = argv[narg];
         }
         else {
            fprintf (stderr,  "Format type '%s' not supported.\n"
                              "See -help for details.\n", argv[narg]);
            exit (1);
         }
         ++narg;
      } else if (strcmp(argv[narg],"-sel") == 0) {
         ++narg;
         if (narg >= argc)  {
	         fprintf (stderr, "need argument after -sel ");
	         exit (1);
         }
         sel = argv[narg]; ++narg;
      } else if (strncmp(argv[narg],"-d",2) == 0) {
         oform = CCALC_DOUBLE; ++narg;
      } else if (strncmp(argv[narg],"-n",2) == 0) {
         oform = CCALC_NICE; ++narg;
      } else if (strncmp(argv[narg],"-i",2) == 0) {
         oform = CCALC_INT; ++narg;
      } else if (strncmp(argv[narg],"-r",2) == 0) {
         oform = CCALC_INT; ++narg;
      } else if (strncmp(argv[narg],"-f",2) == 0) {
         oform = CCALC_FINT; ++narg;
      } else if (strncmp(argv[narg],"-c",2) == 0) {
         oform = CCALC_CINT; ++narg;
      } else { /* break if option is not recognized */
         ++narg;
         break; 
      }
   }
   
   /* read input files */

   nim = argc-narg ;
   inim = (MRI_IMAGE **) malloc( sizeof(MRI_IMAGE *) * nim ) ;
   ncol = 0 ;
   if( nonconst || nonfixed ) MAKE_intvec(ncv,1) ;
   for( jj=0 ; jj < nim ; jj++ ){

#if 0                                   /** for testing only **/
      if( AFNI_yesenv("ragged") ){
        MRI_IMAGE *qim ;
        qim      = mri_read_ascii_ragged( argv[jj+narg] , 3.e+33 ) ;
        fprintf(stderr,"qim: nx=%d ny=%d\n",qim->nx,qim->ny) ;
        inim[jj] = mri_transpose(qim) ; mri_free(qim) ;
      } else
#endif

      if (sel) {
         fname = (char *)
                  calloc((strlen(argv[jj+narg])+strlen(sel)+1), sizeof(char));
         strcat(fname, argv[jj+narg]); strcat(fname, sel);
      } else {
         fname = argv[jj+narg];  
      }
      inim[jj] = mri_read_1D( fname ) ;
      if( inim[jj] == NULL )
        ERROR_exit("Can't read input file '%s'",fname) ;
      if( jj > 0 && inim[jj]->nx != inim[0]->nx )
        ERROR_exit("Input file %s doesn't match first file %s in length!",
                   fname,argv[1]) ;

      ncold = ncol ; ncol += inim[jj]->ny ;
      if( ncv != NULL ){     /* check for constant columns [04 Dec 2010] */
        RESIZE_intvec(ncv,ncol) ;
        for( kk=0 ; kk < inim[jj]->ny ; kk++ ) ncv->ar[ncold+kk] = 1 ;
        far = MRI_FLOAT_PTR(inim[jj]) ; nx = inim[jj]->nx ;
        if( nonconst ){
          for( kk=0 ; kk < inim[jj]->ny ; kk++ ){ /* loop over columns */
            for( ii=1 ; ii < nx ; ii++ ){         /* loop down column */
              if( far[ii+kk*nx] != far[kk*nx] ) break ;
            }
            if( ii == nx ) ncv->ar[ncold+kk] = 0 ; /* constant */
          }
        }
        if( nonfixed ){
          char *hl = mri_read_1D_headerlines( fname ) ;
          if( hl != NULL && *hl == '#' ){
            char *spt = strchr(hl,'\n') ;
            if( spt != NULL ) spt = strchr(spt,'#') ; /* start of line 2 */
            if( spt != NULL ){
              NI_str_array *sar = NI_decode_string_list( spt+1 , "~" ) ;
              if( sar != NULL && sar->num >= inim[jj]->ny ){
                for( kk=0 ; kk < inim[jj]->ny ; kk++ ){
                  spt = strchr(sar->str[kk],'$') ;
                  if( spt != NULL && spt[1] == '\0' ) ncv->ar[ncold+kk] = 0 ;
                  else {
                    if( hline == NULL ) hline = strdup("#") ;
                    hline = THD_zzprintf( hline , " %s" , sar->str[kk] ) ;
                  }
                }
              }
              NI_delete_str_array(sar) ;
            }
          }
        }
      } /* end of computing ncv = array marking non-constant vectors */
      if (sel) {
         free(fname); fname = NULL;
      }
   } /* end of input loop */

   /* now do the output */

   if( hline != NULL ) printf("%s\n",hline) ;

   nx = inim[0]->nx ;

   if (stack) {
      if (oform == CCALC_NOT_SET) {
         for( cc=jj=0 ; jj < nim ; jj++ ){
            far = MRI_FLOAT_PTR(inim[jj]) ;
            for( kk=0 ; kk < inim[jj]->ny ; kk++,cc++ ){
               for( ii=0 ; ii < nx ; ii++ ){
                  if( ncv == NULL || ncv->ar[cc] )
                    printf(" %g\n", far[ii+kk*nx] ) ; 
               }
            }
         }
      } else {
         for( cc=jj=0 ; jj < nim ; jj++ ){
            far = MRI_FLOAT_PTR(inim[jj]) ;
            for( kk=0 ; kk < inim[jj]->ny ; kk++,cc++ ){
               for( ii=0 ; ii < nx ; ii++ ){
                  if( ncv == NULL || ncv->ar[cc] )
                    printf(" %s\n", 
                        format_value_4print(far[ii+kk*nx], oform, formatstr )); 
               }
            }
         }
      }
   } else {
      if (oform == CCALC_NOT_SET) {
         for( ii=0 ; ii < nx ; ii++ ){
            for( cc=jj=0 ; jj < nim ; jj++ ){
               far = MRI_FLOAT_PTR(inim[jj]) ;
               for( kk=0 ; kk < inim[jj]->ny ; kk++,cc++ ){
                  if( ncv == NULL || ncv->ar[cc] )
                    printf(" %g", far[ii+kk*nx] ) ; 
                 /* printf(" %+.2f", far[ii+kk*nx] ) ;*/
               }
            }
            printf("\n") ;
         }
      } else {
         for( ii=0 ; ii < nx ; ii++ ){
            for( cc=jj=0 ; jj < nim ; jj++ ){
               far = MRI_FLOAT_PTR(inim[jj]) ;
               for( kk=0 ; kk < inim[jj]->ny ; kk++,cc++ ){
                  if( ncv == NULL || ncv->ar[cc] )
                    printf(" %s", 
                        format_value_4print(far[ii+kk*nx], oform, formatstr )); 
               }
            }
            printf("\n") ;
         }
      }
   }
   exit(0) ;
}
Exemple #7
0
static MRI_IMAGE * mri_psinv( MRI_IMAGE *imc , float *wt )
{
   float *rmat=MRI_FLOAT_PTR(imc) ;
   int m=imc->nx , n=imc->ny , ii,jj,kk ;
   double *amat , *umat , *vmat , *sval , *xfac , smax,del,ww ;
   MRI_IMAGE *imp ; float *pmat ;
   register double sum ;
   int do_svd=0 ;

   amat = (double *)calloc( sizeof(double),m*n ) ;  /* input matrix */
   xfac = (double *)calloc( sizeof(double),n   ) ;  /* column norms of [a] */

#define R(i,j) rmat[(i)+(j)*m]   /* i=0..m-1 , j=0..n-1 */
#define A(i,j) amat[(i)+(j)*m]   /* i=0..m-1 , j=0..n-1 */
#define P(i,j) pmat[(i)+(j)*n]   /* i=0..n-1 , j=0..m-1 */

   /* copy input matrix (float) into amat (double) */

   for( ii=0 ; ii < m ; ii++ )
     for( jj=0 ; jj < n ; jj++ ) A(ii,jj) = R(ii,jj) ;

   /* weight rows? */

   if( wt != NULL ){
     for( ii=0 ; ii < m ; ii++ ){
       ww = wt[ii] ;
       if( ww > 0.0 ) for( jj=0 ; jj < n ; jj++ ) A(ii,jj) *= ww ;
     }
   }

   /* scale each column to have norm 1 */

   for( jj=0 ; jj < n ; jj++ ){
     sum = 0.0 ;
     for( ii=0 ; ii < m ; ii++ ) sum += A(ii,jj)*A(ii,jj) ;
     if( sum > 0.0 ) sum = 1.0/sqrt(sum) ;
     else           { do_svd = 1 ; ERROR_message("mri_psinv[%d]=0\n",jj);}
     xfac[jj] = sum ;
     for( ii=0 ; ii < m ; ii++ ) A(ii,jj) *= sum ;
   }

   /*** compute using Choleski or SVD ***/

   if( do_svd || AFNI_yesenv("AFNI_WARPDRIVE_SVD") ){ /***--- SVD method ---***/

#define U(i,j) umat[(i)+(j)*m]
#define V(i,j) vmat[(i)+(j)*n]

     umat = (double *)calloc( sizeof(double),m*n ); /* left singular vectors */
     vmat = (double *)calloc( sizeof(double),n*n ); /* right singular vectors */
     sval = (double *)calloc( sizeof(double),n   ); /* singular values */

     /* compute SVD of scaled matrix */

     svd_double( m , n , amat , sval , umat , vmat ) ;

     free((void *)amat) ;  /* done with this */

     /* find largest singular value */

     smax = sval[0] ;
     for( ii=1 ; ii < n ; ii++ ) if( sval[ii] > smax ) smax = sval[ii] ;

     if( smax <= 0.0 ){                        /* this is bad */
       ERROR_message("SVD fails in mri_warp3D_align_setup!\n");
       free((void *)xfac); free((void *)sval);
       free((void *)vmat); free((void *)umat); return NULL;
     }

     for( ii=0 ; ii < n ; ii++ )
       if( sval[ii] < 0.0 ) sval[ii] = 0.0 ;  /* should not happen */

#define PSINV_EPS 1.e-8

     /* "reciprocals" of singular values:  1/s is actually s/(s^2+del) */

     del = PSINV_EPS * smax*smax ;
     for( ii=0 ; ii < n ; ii++ )
       sval[ii] = sval[ii] / ( sval[ii]*sval[ii] + del ) ;

     /* create pseudo-inverse */

     imp  = mri_new( n , m , MRI_float ) ;   /* recall that m > n */
     pmat = MRI_FLOAT_PTR(imp) ;

     for( ii=0 ; ii < n ; ii++ ){
       for( jj=0 ; jj < m ; jj++ ){
         sum = 0.0 ;
         for( kk=0 ; kk < n ; kk++ ) sum += sval[kk] * V(ii,kk) * U(jj,kk) ;
         P(ii,jj) = (float)sum ;
       }
     }
     free((void *)sval); free((void *)vmat); free((void *)umat);

   } else { /***----- Choleski method -----***/

     vmat = (double *)calloc( sizeof(double),n*n ); /* normal matrix */

     for( ii=0 ; ii < n ; ii++ ){
       for( jj=0 ; jj <= ii ; jj++ ){
         sum = 0.0 ;
         for( kk=0 ; kk < m ; kk++ ) sum += A(kk,ii) * A(kk,jj) ;
         V(ii,jj) = sum ;
       }
       V(ii,ii) += PSINV_EPS ;   /* note V(ii,ii)==1 before this */
     }

     /* Choleski factor */

     for( ii=0 ; ii < n ; ii++ ){
       for( jj=0 ; jj < ii ; jj++ ){
         sum = V(ii,jj) ;
         for( kk=0 ; kk < jj ; kk++ ) sum -= V(ii,kk) * V(jj,kk) ;
         V(ii,jj) = sum / V(jj,jj) ;
       }
       sum = V(ii,ii) ;
       for( kk=0 ; kk < ii ; kk++ ) sum -= V(ii,kk) * V(ii,kk) ;
       if( sum <= 0.0 ){
         ERROR_message("Choleski fails in mri_warp3D_align_setup!\n");
         free((void *)xfac); free((void *)amat); free((void *)vmat); return NULL ;
       }
       V(ii,ii) = sqrt(sum) ;
     }

     /* create pseudo-inverse */

     imp  = mri_new( n , m , MRI_float ) ;   /* recall that m > n */
     pmat = MRI_FLOAT_PTR(imp) ;

     sval = (double *)calloc( sizeof(double),n ) ; /* row #jj of A */

     for( jj=0 ; jj < m ; jj++ ){
       for( ii=0 ; ii < n ; ii++ ) sval[ii] = A(jj,ii) ; /* extract row */

       for( ii=0 ; ii < n ; ii++ ){  /* forward solve */
         sum = sval[ii] ;
         for( kk=0 ; kk < ii ; kk++ ) sum -= V(ii,kk) * sval[kk] ;
         sval[ii] = sum / V(ii,ii) ;
       }
       for( ii=n-1 ; ii >= 0 ; ii-- ){  /* backward solve */
         sum = sval[ii] ;
         for( kk=ii+1 ; kk < n ; kk++ ) sum -= V(kk,ii) * sval[kk] ;
         sval[ii] = sum / V(ii,ii) ;
       }

       for( ii=0 ; ii < n ; ii++ ) P(ii,jj) = (float)sval[ii] ;
     }
     free((void *)amat); free((void *)vmat); free((void *)sval);
   }

   /* rescale rows from norming */

   for( ii=0 ; ii < n ; ii++ ){
     for( jj=0 ; jj < m ; jj++ ) P(ii,jj) *= xfac[ii] ;
   }
   free((void *)xfac);

   /* rescale cols for weight? */

   if( wt != NULL ){
     for( ii=0 ; ii < m ; ii++ ){
       ww = wt[ii] ;
       if( ww > 0.0 ) for( jj=0 ; jj < n ; jj++ ) P(jj,ii) *= ww ;
     }
   }

   return imp;
}
Exemple #8
0
void AFNI_start_fetching_url( char *urlstring )
{
   pid_t child_pid ;

#ifdef CYGWIN  /* 18 Dec 2002 */
   FAIL_MESSAGE("not possible under Cygwin") ;
   return ;
#else

   /*-- decide if we are to do anything --*/

   if( ! AFNI_yesenv("AFNI_VERSION_CHECK") ){    /* never check */
     FAIL_MESSAGE("AFNI_VERSION_CHECK forbids") ;
     return ;
   }

#undef  VDELAY
#define VDELAY 1234567 /* about 2 weeks */
   /* check if we did this in the last VDELAY seconds */
   /* also, update global motd_old                    */
   if( vc_check_too_soon() ) {
      disabled = 1 ;
      return ;
   }

   /*-- OK, start the child process --*/

   child_pid = fork() ;
   if( child_pid == (pid_t)(-1) ){  /* bad */
     FAIL_MESSAGE("can't fork") ;
     return ;
   }

   /*---------------------------------------------------------*/
   if( child_pid > 0 ){                     /* I'm the parent */

     /*-- save PID of child for later use --*/

     vc_child_pid = child_pid ;

     /*-- open an IOCHAN to talk to child --*/

     vc_ioc = iochan_init( STR_CHILD , "accept" ) ;
     if( vc_ioc == NULL ){
       kill(child_pid,SIGTERM) ;            /* cf. Abraham and Isaac */
       vc_child_pid = (pid_t)(-1) ;
       FAIL_MESSAGE("can't open connection to child") ;
     } else {
       atexit( vc_exit ) ;                                       /* 12 Dec 2002 */
     }
     return ;

   /*---------------------------------------------------------*/
   } else {                                  /* I'm the child */
                                           /* (never returns) */
     int nbuf=0 , jj ;
     char *vbuf=NULL ;
     IOCHAN *ioc ;
     struct utsname ubuf ;
     char ua[512] ;

     iochan_enable_perror(0) ;   /* don't print TCP/IP error messages */
     signal( SIGTERM , vexit ) ; /* if parent kills us, call vexit()  */

     /*-- get information from the AFNI server --*/

#define USE_HTTP_10

#ifdef USE_HTTP_10
#  undef PCLAB
#  ifdef SHOWOFF
#    undef SHSH
#    undef SHSHSH
#    define SHSH(x)   #x
#    define SHSHSH(x) SHSH(x)
#    define PCLAB     SHSHSH(SHOWOFF)
#  else
#    define PCLAB     "Unknown"
#  endif
#endif

     /** 25 Mar 2005: send more info in the request header **/

#ifdef USE_HTTP_10
     ubuf.nodename[0] = ubuf.sysname[0] = ubuf.machine[0] = '\0' ;
     jj = uname( &ubuf ) ;
     if( jj >= 0 && ubuf.nodename[0] != '\0' )
       sprintf( ua ,
               "afni (avers='%s'; prec='%s' node='%s'; sys='%s'; mach='%s')" ,
                AVERZHN, PCLAB, ubuf.nodename, ubuf.sysname, ubuf.machine   ) ;
     else
       sprintf( ua , "afni (avers='%s'; prec='%s')" , AVERZHN , PCLAB ) ;

     set_HTTP_10( 1 ) ;
     set_HTTP_user_agent( ua ) ;
#else
     set_HTTP_10( 0 ) ;
#endif

     /* send the request */

     THD_death_setup( 34567 ) ;  /* die if 34.567 seconds passes away */

     nbuf = read_URL( urlstring , &vbuf ) ;  /* may take a while */

     set_HTTP_10( 0 ) ;

     /*-- if this failed, quit --*/

     if( nbuf <= 0 || vbuf == NULL || vbuf[0] == '\0' ) {
        /* block recheck until a new DELAY has passed    22 Mar 2016 [rickr] */
        /* - also so server is not flooded when there are issues             */
        AFNI_update_vctime(NULL, NULL);
        vexit(1);
     }

     /*-- talk to parent process thru IOCHAN --*/

     ioc = iochan_init( STR_CHILD , "create" ) ;
     if( ioc == NULL )                                  vexit(2);

     /*-- wait until ioc is ready for writing --*/

     jj = iochan_writecheck(ioc,-1) ;
     if( jj < 0 )                                       vexit(3);

     /*-- send the info in vbuf --*/

     iochan_sendall( ioc , vbuf , nbuf ) ;
     while( ! iochan_clearcheck(ioc,10) )  /* loop until cleared */
       AFNI_sleep(10) ;                   /* by parent process  */

     AFNI_sleep(10); /* a little extra napping, then death */
     _exit(0);
   }
#endif  /* not CYGWIN */
}
Exemple #9
0
MRI_IMAGE * mri_dup2D( int nup , MRI_IMAGE *imin )
{
   MRI_IMAGE *flim , *newim ;
   float     *flar , *newar , *cold , *cnew ;
   int nx,ny , nxup,nyup , ii,jj,kk, NNmode = 0 ;

ENTRY("mri_dup2D") ;
   /*-- sanity checks --*/

   if( nup < 1 || imin == NULL ) RETURN( NULL );

   if( nup == 1 ){ newim = mri_to_mri( imin->kind, imin ); RETURN(newim); }

   /* does the user want neighbor interpolation?     22 Feb 2004 [rickr] */
   if ( AFNI_yesenv("AFNI_IMAGE_ZOOM_NN") ) {
      mri_dup2D_mode(0);
      NNmode = 1;
   }

   /*-- complex-valued images: do each part separately --*/

   if( imin->kind == MRI_complex ){
      MRI_IMARR *impair ; MRI_IMAGE *rim, *iim, *tim ;

      impair = mri_complex_to_pair( imin ) ;
      if( impair == NULL ){
         fprintf(stderr,"*** mri_complex_to_pair fails in mri_dup2D!\n"); EXIT(1);
      }
      rim = IMAGE_IN_IMARR(impair,0) ;
      iim = IMAGE_IN_IMARR(impair,1) ;  FREE_IMARR(impair) ;
      tim = mri_dup2D( nup, rim ); mri_free( rim ); rim = tim ;
      tim = mri_dup2D( nup, iim ); mri_free( iim ); iim = tim ;
      newim = mri_pair_to_complex( rim , iim ) ;
      mri_free( rim ) ; mri_free( iim ) ;
      MRI_COPY_AUX(newim,imin) ;
      RETURN(newim) ;
   }

   /*-- 14 Mar 2002: RGB image up by 2..4, all colors at once --*/

   if( imin->kind == MRI_rgb ){
     MRI_IMAGE *qqim=NULL ;
     if ( NNmode )
         qqim = mri_dup2D_rgb_NN(imin, nup);  /* 22 Feb 2004 [rickr] */
     else {
       switch(nup){
         case 4: qqim = mri_dup2D_rgb4(imin); break; /* special purpose fast codes */
         case 3: qqim = mri_dup2D_rgb3(imin); break; /* using fixed pt arithmetic  */
         case 2: qqim = mri_dup2D_rgb2(imin); break;

        /*-- other factors: do each color separately as a byte image --*/
        default:{
           MRI_IMARR *imtriple ; MRI_IMAGE *rim, *gim, *bim, *tim ;

           imtriple = mri_rgb_to_3byte( imin ) ;
           if( imtriple == NULL ){
             fprintf(stderr,"*** mri_rgb_to_3byte fails in mri_dup2D!\n"); RETURN(NULL);
           }
           rim = IMAGE_IN_IMARR(imtriple,0) ;
           gim = IMAGE_IN_IMARR(imtriple,1) ;
           bim = IMAGE_IN_IMARR(imtriple,2) ; FREE_IMARR(imtriple) ;
           tim = mri_dup2D( nup, rim ); mri_free(rim); rim = tim;
           tim = mri_dup2D( nup, gim ); mri_free(gim); gim = tim;
           tim = mri_dup2D( nup, bim ); mri_free(bim); bim = tim;
           newim = mri_3to_rgb( rim, gim, bim ) ;
           mri_free(rim) ; mri_free(gim) ; mri_free(bim) ;
           MRI_COPY_AUX(newim,imin) ;
           qqim = newim ;
         }
         break ;
       }
     }

     RETURN(qqim) ;
   }

   /*-- Special case: byte-valued image upsampled by 2/3/4 [13 Mar 2002] --*/

   if( imin->kind == MRI_byte && nup <= 4 ){
     void (*usbyte)(int,byte *,byte *) = NULL ;
     byte *bar=MRI_BYTE_PTR(imin) , *bnew , *cold, *cnew ;
     nx = imin->nx; ny = imin->ny; nxup = nx*nup; nyup = ny*nup ;
     newim = mri_new( nxup,nyup , MRI_byte ); bnew = MRI_BYTE_PTR(newim);
     switch( nup ){
       case 2: usbyte = upsample_1by2 ; break ;  /* special fast codes */
       case 3: usbyte = upsample_1by3 ; break ;
       case 4: usbyte = upsample_1by4 ; break ;
     }
     for( jj=0 ; jj < ny ; jj++ )                      /* upsample rows */
       usbyte( nx , bar+jj*nx , bnew+jj*nxup ) ;
     cold = (byte *) malloc( sizeof(byte) * ny   ) ;
     cnew = (byte *) malloc( sizeof(byte) * nyup ) ;
     for( ii=0 ; ii < nxup ; ii++ ){                   /* upsample cols */
       for( jj=0 ; jj < ny ; jj++ ) cold[jj] = bnew[ii+jj*nxup] ;
       usbyte( ny , cold , cnew ) ;
       for( jj=0 ; jj < nyup ; jj++ ) bnew[ii+jj*nxup] = cnew[jj] ;
     }
     free(cold); free(cnew); MRI_COPY_AUX(newim,imin); RETURN(newim);
   }

   /*-- otherwise, make sure we operate on a float image --*/

   if( imin->kind == MRI_float ) flim = imin ;
   else                          flim = mri_to_float( imin ) ;

   flar = MRI_FLOAT_PTR(flim) ;

   nx = flim->nx ; ny = flim->ny ; nxup = nx*nup ; nyup = ny*nup ;
   newim = mri_new( nxup , nyup , MRI_float ) ;
   newar = MRI_FLOAT_PTR(newim) ;

   /*-- upsample rows --*/

   for( jj=0 ; jj < ny ; jj++ )
      usammer( nup , nx , flar + jj*nx , newar + jj*nxup ) ;

   if( flim != imin ) mri_free(flim) ;

   /*-- upsample columns --*/

   cold = (float *) malloc( sizeof(float) * ny ) ;
   cnew = (float *) malloc( sizeof(float) * nyup ) ;
   if( cold == NULL || cnew == NULL ){
      fprintf(stderr,"*** mri_dup2D malloc failure!\n"); EXIT(1);
   }

   for( ii=0 ; ii < nxup ; ii++ ){
      for( jj=0 ; jj < ny ; jj++ ) cold[jj] = newar[ii + jj*nxup] ;
      usammer( nup , ny , cold , cnew ) ;
      for( jj=0 ; jj < nyup ; jj++ ) newar[ii+jj*nxup] = cnew[jj] ;
   }

   free(cold) ; free(cnew) ;

   /*-- type convert output, if necessary --*/

   switch( imin->kind ){

      default: break ;

      case MRI_byte:{
         byte * bar ; MRI_IMAGE * bim ; float fmin , fmax ;

         bim = mri_new( nxup,nyup , MRI_byte ) ; bar = MRI_BYTE_PTR(bim) ;
         fmin = mri_min(imin) ; fmax = mri_max(imin) ;
         for( ii=0 ; ii < newim->nvox ; ii++ )
            bar[ii] =  (newar[ii] < fmin) ? fmin
                     : (newar[ii] > fmax) ? fmax : newar[ii] ;
         mri_free(newim) ; newim = bim ;
      }
      break ;

      case MRI_short:{
         short * sar ; MRI_IMAGE * sim ; float fmin , fmax ;

         sim = mri_new( nxup,nyup , MRI_short ) ; sar = MRI_SHORT_PTR(sim) ;
         fmin = mri_min(imin) ; fmax = mri_max(imin) ;
         for( ii=0 ; ii < newim->nvox ; ii++ )
            sar[ii] =  (newar[ii] < fmin) ? fmin
                     : (newar[ii] > fmax) ? fmax : newar[ii] ;
         mri_free(newim) ; newim = sim ;
      }
      break ;

      case MRI_float:{
         float fmin , fmax ;

         fmin = mri_min(imin) ; fmax = mri_max(imin) ;
         for( ii=0 ; ii < newim->nvox ; ii++ )
                 if( newar[ii] < fmin ) newar[ii] = fmin ;
            else if( newar[ii] > fmax ) newar[ii] = fmax ;
      }
   }

   /*-- finito --*/

   MRI_COPY_AUX(newim,imin) ;
   RETURN( newim );
}
Exemple #10
0
int main( int argc , char * argv[] )
{
   int do_norm=0 , qdet=2 , have_freq=0 , do_automask=0 ;
   float dt=0.0f , fbot=0.0f,ftop=999999.9f , blur=0.0f ;
   MRI_IMARR *ortar=NULL ; MRI_IMAGE *ortim=NULL ;
   THD_3dim_dataset **ortset=NULL ; int nortset=0 ;
   THD_3dim_dataset *inset=NULL , *outset ;
   char *prefix="bandpass" ;
   byte *mask=NULL ;
   int mask_nx=0,mask_ny=0,mask_nz=0,nmask , verb=1 , 
       nx,ny,nz,nvox , nfft=0 , kk ;
   float **vec , **ort=NULL ; int nort=0 , vv , nopt , ntime  ;
   MRI_vectim *mrv ;
   float pvrad=0.0f ; int nosat=0 ;
   int do_despike=0 ;

   /*-- help? --*/

   AFNI_SETUP_OMP(0) ;  /* 24 Jun 2013 */

   if( argc < 2 || strcmp(argv[1],"-help") == 0 ){
     printf(
       "\n"
       "** NOTA BENE:  For the purpose of preparing resting-state FMRI datasets **\n"
       "** for analysis (e.g., with 3dGroupInCorr),  this program is now mostly **\n"
       "** superseded by the afni_proc.py script.  See the 'afni_proc.py -help' **\n"
       "** section 'Resting state analysis (modern)' to get our current rs-FMRI **\n"
       "** pre-processing recommended sequence of steps. -- RW Cox, et alii.    **\n"
       "\n"
       "Usage: 3dBandpass [options] fbot ftop dataset\n"
       "\n"
       "* One function of this program is to prepare datasets for input\n"
       "   to 3dSetupGroupInCorr.  Other uses are left to your imagination.\n"
       "\n"
       "* 'dataset' is a 3D+time sequence of volumes\n"
       "   ++ This must be a single imaging run -- that is, no discontinuities\n"
       "       in time from 3dTcat-ing multiple datasets together.\n"
       "\n"
       "* fbot = lowest frequency in the passband, in Hz\n"
       "   ++ fbot can be 0 if you want to do a lowpass filter only;\n"
       "       HOWEVER, the mean and Nyquist freq are always removed.\n"
       "\n"
       "* ftop = highest frequency in the passband (must be > fbot)\n"
       "   ++ if ftop > Nyquist freq, then it's a highpass filter only.\n"
       "\n"
       "* Set fbot=0 and ftop=99999 to do an 'allpass' filter.\n"
       "  ++ Except for removal of the 0 and Nyquist frequencies, that is.\n"
       "\n"
       "* You cannot construct a 'notch' filter with this program!\n"
       "  ++ You could use 3dBandpass followed by 3dcalc to get the same effect.\n"
       "  ++ If you are understand what you are doing, that is.\n"
       "  ++ Of course, that is the AFNI way -- if you don't want to\n"
       "     understand what you are doing, use Some other PrograM, and\n"
       "     you can still get Fine StatisticaL maps.\n"
       "\n"
       "* 3dBandpass will fail if fbot and ftop are too close for comfort.\n"
       "  ++ Which means closer than one frequency grid step df,\n"
       "     where df = 1 / (nfft * dt) [of course]\n"
       "\n"
       "* The actual FFT length used will be printed, and may be larger\n"
       "   than the input time series length for the sake of efficiency.\n"
       "  ++ The program will use a power-of-2, possibly multiplied by\n"
       "     a power of 3 and/or 5 (up to and including the 3rd power of\n"
       "     each of these: 3, 9, 27, and 5, 25, 125).\n"
       "\n"
       "* Note that the results of combining 3dDetrend and 3dBandpass will\n"
       "   depend on the order in which you run these programs.  That's why\n"
       "   3dBandpass has the '-ort' and '-dsort' options, so that the\n"
       "   time series filtering can be done properly, in one place.\n"
       "\n"
       "* The output dataset is stored in float format.\n"
       "\n"
       "* The order of processing steps is the following (most are optional):\n"
       " (0) Check time series for initial transients [does not alter data]\n"
       " (1) Despiking of each time series\n"
       " (2) Removal of a constant+linear+quadratic trend in each time series\n"
       " (3) Bandpass of data time series\n"
       " (4) Bandpass of -ort time series, then detrending of data\n"
       "      with respect to the -ort time series\n"
       " (5) Bandpass and de-orting of the -dsort dataset,\n"
       "      then detrending of the data with respect to -dsort\n"
       " (6) Blurring inside the mask [might be slow]\n"
       " (7) Local PV calculation     [WILL be slow!]\n"
       " (8) L2 normalization         [will be fast.]\n"
       "\n"
       "--------\n"
       "OPTIONS:\n"
       "--------\n"
       " -despike        = Despike each time series before other processing.\n"
       "                   ++ Hopefully, you don't actually need to do this,\n"
       "                      which is why it is optional.\n"
       " -ort f.1D       = Also orthogonalize input to columns in f.1D\n"
       "                   ++ Multiple '-ort' options are allowed.\n"
       " -dsort fset     = Orthogonalize each voxel to the corresponding\n"
       "                    voxel time series in dataset 'fset', which must\n"
       "                    have the same spatial and temporal grid structure\n"
       "                    as the main input dataset.\n"
       "                   ++ At present, only one '-dsort' option is allowed.\n"
       " -nodetrend      = Skip the quadratic detrending of the input that\n"
       "                    occurs before the FFT-based bandpassing.\n"
       "                   ++ You would only want to do this if the dataset\n"
       "                      had been detrended already in some other program.\n"
       " -dt dd          = set time step to 'dd' sec [default=from dataset header]\n"
       " -nfft N         = set the FFT length to 'N' [must be a legal value]\n"
       " -norm           = Make all output time series have L2 norm = 1\n"
       "                   ++ i.e., sum of squares = 1\n"
       " -mask mset      = Mask dataset\n"
       " -automask       = Create a mask from the input dataset\n"
       " -blur fff       = Blur (inside the mask only) with a filter\n"
       "                    width (FWHM) of 'fff' millimeters.\n"
       " -localPV rrr    = Replace each vector by the local Principal Vector\n"
       "                    (AKA first singular vector) from a neighborhood\n"
       "                    of radius 'rrr' millimiters.\n"
       "                   ++ Note that the PV time series is L2 normalized.\n"
       "                   ++ This option is mostly for Bob Cox to have fun with.\n"
       "\n"
       " -input dataset  = Alternative way to specify input dataset.\n"
       " -band fbot ftop = Alternative way to specify passband frequencies.\n"
       "\n"
       " -prefix ppp     = Set prefix name of output dataset.\n"
       " -quiet          = Turn off the fun and informative messages. (Why?)\n"
       "\n"
       " -notrans        = Don't check for initial positive transients in the data:\n"
       "  *OR*             ++ The test is a little slow, so skipping it is OK,\n"
       " -nosat               if you KNOW the data time series are transient-free.\n"
       "                   ++ Or set AFNI_SKIP_SATCHECK to YES.\n"
       "                   ++ Initial transients won't be handled well by the\n"
       "                      bandpassing algorithm, and in addition may seriously\n"
       "                      contaminate any further processing, such as inter-voxel\n"
       "                      correlations via InstaCorr.\n"
       "                   ++ No other tests are made [yet] for non-stationary behavior\n"
       "                      in the time series data.\n"
     ) ;
     PRINT_AFNI_OMP_USAGE(
       "3dBandpass" ,
       "* At present, the only part of 3dBandpass that is parallelized is the\n"
       "  '-blur' option, which processes each sub-brick independently.\n"
     ) ;
     PRINT_COMPILE_DATE ; exit(0) ;
   }

   /*-- startup --*/

   mainENTRY("3dBandpass"); machdep();
   AFNI_logger("3dBandpass",argc,argv);
   PRINT_VERSION("3dBandpass"); AUTHOR("RW Cox");

   nosat =  AFNI_yesenv("AFNI_SKIP_SATCHECK") ;

   nopt = 1 ;
   while( nopt < argc && argv[nopt][0] == '-' ){

     if( strcmp(argv[nopt],"-despike") == 0 ){  /* 08 Oct 2010 */
       do_despike++ ; nopt++ ; continue ;
     }

     if( strcmp(argv[nopt],"-nfft") == 0 ){
       int nnup ;
       if( ++nopt >= argc ) ERROR_exit("need an argument after -nfft!") ;
       nfft = (int)strtod(argv[nopt],NULL) ;
       nnup = csfft_nextup_even(nfft) ;
       if( nfft < 16 || nfft != nnup )
         ERROR_exit("value %d after -nfft is illegal! Next legal value = %d",nfft,nnup) ;
       nopt++ ; continue ;
     }

     if( strcmp(argv[nopt],"-blur") == 0 ){
       if( ++nopt >= argc ) ERROR_exit("need an argument after -blur!") ;
       blur = strtod(argv[nopt],NULL) ;
       if( blur <= 0.0f ) WARNING_message("non-positive blur?!") ;
       nopt++ ; continue ;
     }

     if( strcmp(argv[nopt],"-localPV") == 0 ){
       if( ++nopt >= argc ) ERROR_exit("need an argument after -localpv!") ;
       pvrad = strtod(argv[nopt],NULL) ;
       if( pvrad <= 0.0f ) WARNING_message("non-positive -localpv?!") ;
       nopt++ ; continue ;
     }

     if( strcmp(argv[nopt],"-prefix") == 0 ){
       if( ++nopt >= argc ) ERROR_exit("need an argument after -prefix!") ;
       prefix = strdup(argv[nopt]) ;
       if( !THD_filename_ok(prefix) ) ERROR_exit("bad -prefix option!") ;
       nopt++ ; continue ;
     }

     if( strcmp(argv[nopt],"-automask") == 0 ){
       if( mask != NULL ) ERROR_exit("Can't use -mask AND -automask!") ;
       do_automask = 1 ; nopt++ ; continue ;
     }

     if( strcmp(argv[nopt],"-mask") == 0 ){
       THD_3dim_dataset *mset ;
       if( ++nopt >= argc ) ERROR_exit("Need argument after '-mask'") ;
       if( mask != NULL || do_automask ) ERROR_exit("Can't have two mask inputs") ;
       mset = THD_open_dataset( argv[nopt] ) ;
       CHECK_OPEN_ERROR(mset,argv[nopt]) ;
       DSET_load(mset) ; CHECK_LOAD_ERROR(mset) ;
       mask_nx = DSET_NX(mset); mask_ny = DSET_NY(mset); mask_nz = DSET_NZ(mset);
       mask = THD_makemask( mset , 0 , 0.5f, 0.0f ) ; DSET_delete(mset) ;
       if( mask == NULL ) ERROR_exit("Can't make mask from dataset '%s'",argv[nopt]) ;
       nmask = THD_countmask( mask_nx*mask_ny*mask_nz , mask ) ;
       if( verb ) INFO_message("Number of voxels in mask = %d",nmask) ;
       if( nmask < 1 ) ERROR_exit("Mask is too small to process") ;
       nopt++ ; continue ;
     }

     if( strcmp(argv[nopt],"-norm") == 0 ){
       do_norm = 1 ; nopt++ ; continue ;
     }

     if( strcmp(argv[nopt],"-quiet") == 0 ){
       verb = 0 ; nopt++ ; continue ;
     }

     if( strcmp(argv[nopt],"-notrans") == 0 || strcmp(argv[nopt],"-nosat") == 0 ){
       nosat = 1 ; nopt++ ; continue ;
     }

     if( strcmp(argv[nopt],"-ort") == 0 ){
       if( ++nopt >= argc ) ERROR_exit("need an argument after -ort!") ;
       if( ortar == NULL ) INIT_IMARR(ortar) ;
       ortim = mri_read_1D( argv[nopt] ) ;
       if( ortim == NULL ) ERROR_exit("can't read from -ort '%s'",argv[nopt]) ;
       mri_add_name(argv[nopt],ortim) ;
       ADDTO_IMARR(ortar,ortim) ;
       nopt++ ; continue ;
     }

     if( strcmp(argv[nopt],"-dsort") == 0 ){
       THD_3dim_dataset *qset ;
       if( ++nopt >= argc ) ERROR_exit("need an argument after -dsort!") ;
       if( nortset > 0 ) ERROR_exit("only 1 -dsort option is allowed!") ;
       qset = THD_open_dataset(argv[nopt]) ;
       CHECK_OPEN_ERROR(qset,argv[nopt]) ;
       ortset = (THD_3dim_dataset **)realloc(ortset,
                                       sizeof(THD_3dim_dataset *)*(nortset+1)) ;
       ortset[nortset++] = qset ;
       nopt++ ; continue ;
     }

     if( strncmp(argv[nopt],"-nodetrend",6) == 0 ){
       qdet = 0 ; nopt++ ; continue ;
     }

     if( strcmp(argv[nopt],"-dt") == 0 ){
       if( ++nopt >= argc ) ERROR_exit("need an argument after -dt!") ;
       dt = (float)strtod(argv[nopt],NULL) ;
       if( dt <= 0.0f ) WARNING_message("value after -dt illegal!") ;
       nopt++ ; continue ;
     }

     if( strcmp(argv[nopt],"-input") == 0 ){
       if( inset != NULL ) ERROR_exit("Can't have 2 -input options!") ;
       if( ++nopt >= argc ) ERROR_exit("need an argument after -input!") ;
       inset = THD_open_dataset(argv[nopt]) ;
       CHECK_OPEN_ERROR(inset,argv[nopt]) ;
       nopt++ ; continue ;
     }

     if( strncmp(argv[nopt],"-band",5) == 0 ){
       if( ++nopt >= argc-1 ) ERROR_exit("need 2 arguments after -band!") ;
       if( have_freq ) WARNING_message("second -band option replaces first one!") ;
       fbot = strtod(argv[nopt++],NULL) ;
       ftop = strtod(argv[nopt++],NULL) ;
       have_freq = 1 ; continue ;
     }

     ERROR_exit("Unknown option: '%s'",argv[nopt]) ;
   }

   /** check inputs for reasonablositiness **/

   if( !have_freq ){
     if( nopt+1 >= argc )
       ERROR_exit("Need frequencies on command line after options!") ;
     fbot = (float)strtod(argv[nopt++],NULL) ;
     ftop = (float)strtod(argv[nopt++],NULL) ;
   }

   if( inset == NULL ){
     if( nopt >= argc )
       ERROR_exit("Need input dataset name on command line after options!") ;
     inset = THD_open_dataset(argv[nopt]) ;
     CHECK_OPEN_ERROR(inset,argv[nopt]) ; nopt++ ;
   }
   DSET_UNMSEC(inset) ;

   if( fbot < 0.0f  ) ERROR_exit("fbot value can't be negative!") ;
   if( ftop <= fbot ) ERROR_exit("ftop value %g must be greater than fbot value %g!",ftop,fbot) ;

   ntime = DSET_NVALS(inset) ;
   if( ntime < 9 ) ERROR_exit("Input dataset is too short!") ;

   if( nfft <= 0 ){
     nfft = csfft_nextup_even(ntime) ;
     if( verb ) INFO_message("Data length = %d  FFT length = %d",ntime,nfft) ;
     (void)THD_bandpass_set_nfft(nfft) ;
   } else if( nfft < ntime ){
     ERROR_exit("-nfft %d is less than data length = %d",nfft,ntime) ;
   } else {
     kk = THD_bandpass_set_nfft(nfft) ;
     if( kk != nfft && verb )
       INFO_message("Data length = %d  FFT length = %d",ntime,kk) ;
   }

   if( dt <= 0.0f ){
     dt = DSET_TR(inset) ;
     if( dt <= 0.0f ){
       WARNING_message("Setting dt=1.0 since input dataset lacks a time axis!") ;
       dt = 1.0f ;
     }
   }

   if( !THD_bandpass_OK(ntime,dt,fbot,ftop,1) ) ERROR_exit("Can't continue!") ;

   nx = DSET_NX(inset); ny = DSET_NY(inset); nz = DSET_NZ(inset); nvox = nx*ny*nz;

   /* check mask, or create it */

   if( verb ) INFO_message("Loading input dataset time series" ) ;
   DSET_load(inset) ;

   if( mask != NULL ){
     if( mask_nx != nx || mask_ny != ny || mask_nz != nz )
       ERROR_exit("-mask dataset grid doesn't match input dataset") ;

   } else if( do_automask ){
     mask = THD_automask( inset ) ;
     if( mask == NULL )
       ERROR_message("Can't create -automask from input dataset?") ;
     nmask = THD_countmask( DSET_NVOX(inset) , mask ) ;
     if( verb ) INFO_message("Number of voxels in automask = %d",nmask);
     if( nmask < 1 ) ERROR_exit("Automask is too small to process") ;

   } else {
     mask = (byte *)malloc(sizeof(byte)*nvox) ; nmask = nvox ;
     memset(mask,1,sizeof(byte)*nvox) ;
     if( verb ) INFO_message("No mask ==> processing all %d voxels",nvox);
   }

   /* A simple check of dataset quality [08 Feb 2010] */

   if( !nosat ){
     float val ;
     INFO_message(
      "Checking dataset for initial transients [use '-notrans' to skip this test]") ;
     val = THD_saturation_check(inset,mask,0,0) ; kk = (int)(val+0.54321f) ;
     if( kk > 0 )
       ININFO_message(
        "Looks like there %s %d non-steady-state initial time point%s :-(" ,
        ((kk==1) ? "is" : "are") , kk , ((kk==1) ? " " : "s") ) ;
     else if( val > 0.3210f )  /* don't ask where this threshold comes from! */
       ININFO_message(
        "MAYBE there's an initial positive transient of 1 point, but it's hard to tell\n") ;
     else
       ININFO_message("No widespread initial positive transient detected :-)") ;
   }

   /* check -dsort inputs for match to inset */

   for( kk=0 ; kk < nortset ; kk++ ){
     if( DSET_NX(ortset[kk])    != nx ||
         DSET_NY(ortset[kk])    != ny ||
         DSET_NZ(ortset[kk])    != nz ||
         DSET_NVALS(ortset[kk]) != ntime )
       ERROR_exit("-dsort %s doesn't match input dataset grid" ,
                  DSET_BRIKNAME(ortset[kk]) ) ;
   }

   /* convert input dataset to a vectim, which is more fun */

   mrv = THD_dset_to_vectim( inset , mask , 0 ) ;
   if( mrv == NULL ) ERROR_exit("Can't load time series data!?") ;
   DSET_unload(inset) ;

   /* similarly for the ort vectors */

   if( ortar != NULL ){
     for( kk=0 ; kk < IMARR_COUNT(ortar) ; kk++ ){
       ortim = IMARR_SUBIM(ortar,kk) ;
       if( ortim->nx < ntime )
         ERROR_exit("-ort file %s is shorter than input dataset time series",
                    ortim->name ) ;
       ort  = (float **)realloc( ort , sizeof(float *)*(nort+ortim->ny) ) ;
       for( vv=0 ; vv < ortim->ny ; vv++ )
         ort[nort++] = MRI_FLOAT_PTR(ortim) + ortim->nx * vv ;
     }
   }

   /* check whether processing leaves any DoF remaining  18 Mar 2015 [rickr] */
   {
      int nbprem = THD_bandpass_remain_dim(ntime, dt, fbot, ftop, 1);
      int bpused, nremain;
      int wlimit;               /* warning limit */

      bpused = ntime - nbprem;  /* #dim lost in bandpass step */

      nremain = nbprem - nort;  /* #dim left in output */
      if( nortset == 1 ) nremain--;
      nremain -= (qdet+1);

      if( verb ) INFO_message("%d dimensional data reduced to %d by:\n"
                    "    %d (bandpass), %d (-ort), %d (-dsort), %d (detrend)",
                    ntime, nremain, bpused, nort, nortset?1:0, qdet+1);

      /* possibly warn (if 95% lost) user or fail */
      wlimit = ntime/20;
      if( wlimit < 3 ) wlimit = 3;
      if( nremain < wlimit && nremain > 0 )
         WARNING_message("dimensionality reduced from %d to %d, be careful!",
                         ntime, nremain);
      if( nremain <= 0 ) /* FAILURE */
         ERROR_exit("dimensionality reduced from %d to %d, failing!",
                    ntime, nremain);
   }

   /* all the real work now */

   if( do_despike ){
     int_pair nsp ;
     if( verb ) INFO_message("Testing data time series for spikes") ;
     nsp = THD_vectim_despike9( mrv ) ;
     if( verb ) ININFO_message(" -- Squashed %d spikes from %d voxels",nsp.j,nsp.i) ;
   }

   if( verb ) INFO_message("Bandpassing data time series") ;
   (void)THD_bandpass_vectim( mrv , dt,fbot,ftop , qdet , nort,ort ) ;

   /* OK, maybe a little more work */

   if( nortset == 1 ){
     MRI_vectim *orv ;
     orv = THD_dset_to_vectim( ortset[0] , mask , 0 ) ;
     if( orv == NULL ){
       ERROR_message("Can't load -dsort %s",DSET_BRIKNAME(ortset[0])) ;
     } else {
       float *dp , *mvv , *ovv , ff ;
       if( verb ) INFO_message("Orthogonalizing to bandpassed -dsort") ;
       (void)THD_bandpass_vectim( orv , dt,fbot,ftop , qdet , nort,ort ) ;
       THD_vectim_normalize( orv ) ;
       dp = malloc(sizeof(float)*mrv->nvec) ;
       THD_vectim_vectim_dot( mrv , orv , dp ) ;
       for( vv=0 ; vv < mrv->nvec ; vv++ ){
         ff = dp[vv] ;
         if( ff != 0.0f ){
           mvv = VECTIM_PTR(mrv,vv) ; ovv = VECTIM_PTR(orv,vv) ;
           for( kk=0 ; kk < ntime ; kk++ ) mvv[kk] -= ff*ovv[kk] ;
         }
       }
       VECTIM_destroy(orv) ; free(dp) ;
     }
   }

   if( blur > 0.0f ){
     if( verb )
       INFO_message("Blurring time series data spatially; FWHM=%.2f",blur) ;
     mri_blur3D_vectim( mrv , blur ) ;
   }
   if( pvrad > 0.0f ){
     if( verb )
       INFO_message("Local PV-ing time series data spatially; radius=%.2f",pvrad) ;
     THD_vectim_normalize( mrv ) ;
     THD_vectim_localpv( mrv , pvrad ) ;
   }
   if( do_norm && pvrad <= 0.0f ){
     if( verb ) INFO_message("L2 normalizing time series data") ;
     THD_vectim_normalize( mrv ) ;
   }

   /* create output dataset, populate it, write it, then quit */

   if( verb ) INFO_message("Creating output dataset in memory, then writing it") ;
   outset = EDIT_empty_copy(inset) ;
   /* do not copy scalars    11 Sep 2015 [rickr] */
   EDIT_dset_items( outset , ADN_prefix,prefix ,
                             ADN_brick_fac,NULL ,
                    ADN_none ) ;
   tross_Copy_History( inset , outset ) ;
   tross_Make_History( "3dBandpass" , argc,argv , outset ) ;

   for( vv=0 ; vv < ntime ; vv++ )
     EDIT_substitute_brick( outset , vv , MRI_float , NULL ) ;

#if 1
   THD_vectim_to_dset( mrv , outset ) ;
#else
 AFNI_OMP_START ;
#pragma omp parallel
 { float *far , *var ; int *ivec=mrv->ivec ; int vv,kk ;
#pragma omp for
   for( vv=0 ; vv < ntime ; vv++ ){
     far = DSET_BRICK_ARRAY(outset,vv) ; var = mrv->fvec + vv ;
     for( kk=0 ; kk < nmask ; kk++ ) far[ivec[kk]] = var[kk*ntime] ;
   }
 }
 AFNI_OMP_END ;
#endif
   VECTIM_destroy(mrv) ;
   DSET_write(outset) ; if( verb ) WROTE_DSET(outset) ;

   exit(0) ;
}
Exemple #11
0
void read_options ( int argc , char * argv[] )
{
  int nopt = 1 ;           /* count of input arguments */
  char message[80];        /* error message */


  if( AFNI_yesenv("AFNI_FLOATIZE") ) FDR_float = 1 ;
  
  /*----- main loop over input options -----*/
  while( nopt < argc )
    {

      /*-----   -input fname   -----*/
      if (strcmp(argv[nopt], "-input") == 0)
	{
	  nopt++;
	  if (nopt >= argc)  FDR_error ("need argument after -input ");
	  FDR_input_filename = (char *) malloc (sizeof(char)*THD_MAX_NAME);
	  MTEST (FDR_input_filename);
	  strcpy (FDR_input_filename, argv[nopt]);
	  nopt++;
	  continue;
	}
      
      
      /*-----   -input1D dname   -----*/
      if (strcmp(argv[nopt], "-input1D") == 0)
	{
	  nopt++;
	  if (nopt >= argc)  FDR_error ("need argument after -input1D ");
	  FDR_input1D_filename = (char *) malloc (sizeof(char)*THD_MAX_NAME);
	  MTEST (FDR_input1D_filename);
	  strcpy (FDR_input1D_filename, argv[nopt]);
	  nopt++;
	  continue;
	}
      
      
      /*-----   -mask_file mname   -----*/
      if (strcmp(argv[nopt], "-mask_file") == 0 || strcmp(argv[nopt],"-mask") == 0)
	{
	  nopt++;
	  if (nopt >= argc)  FDR_error ("need argument after -mask_file ");
	  FDR_mask_filename = (char *) malloc (sizeof(char)*THD_MAX_NAME);
	  MTEST (FDR_mask_filename);
	  strcpy (FDR_mask_filename, argv[nopt]);
	  nopt++;
	  continue;
	}
      

      /*----- -mask_thr m -----*/
      if( strcmp(argv[nopt],"-mask_thr") == 0 ){
	 float fval;
         nopt++ ;
         if( nopt >= argc ){
            FDR_error (" need 1 argument after -mask_thr"); 
         }
	 sscanf (argv[nopt], "%f", &fval); 
	 if (fval < 0.0){
            FDR_error (" Require mask_thr >= 0.0 ");
         }
	 FDR_mask_thr = fval;
	 nopt++;  continue;
      }

      /*---- -force & -old & -pmask & -float etc. [18 Jan 2008] -----*/

      if( strcmp(argv[nopt],"-force") == 0 ){
        FDR_force = 1 ; nopt++ ; continue ;
      }
      if( strcmp(argv[nopt],"-qval") == 0 ){
        FDR_qval = 1 ; nopt++ ; continue ;
      }
      if( strcmp(argv[nopt],"-old") == 0 ){
        FDR_old = 1 ; FDR_pmask = 0 ; nopt++ ; continue ;
      }
      if( strcmp(argv[nopt],"-new") == 0 ){
        FDR_old = -1 ; FDR_pmask = 1 ; nopt++ ; continue ;
      }
      if( strcmp(argv[nopt],"-pmask") == 0 ){
        FDR_pmask = 1 ; nopt++ ; continue ;
      }
      if( strcmp(argv[nopt],"-nopmask") == 0 ){
        FDR_pmask = 0 ; nopt++ ; continue ;
      }
      if( strcmp(argv[nopt],"-float") == 0 ){
        FDR_float = 1 ; nopt++ ; continue ;
      }
#if 0
      if( strcmp(argv[nopt],"-curve") == 0 ){  /* hidden option */
        FDR_curve = 1 ; nopt++ ; continue ;
      }
#endif

      /*----- -cind -----*/
      if( strcmp(argv[nopt],"-cind") == 0 ){
         FDR_cn = 1.0;
         nopt++ ; continue ;
      }

      
      /*----- -cdep -----*/
      if( strcmp(argv[nopt],"-cdep") == 0 ){
         FDR_cn = -1.0;
         nopt++ ; continue ;
      }

      
      /*----- -quiet -----*/
      if( strcmp(argv[nopt],"-quiet") == 0 ){
         FDR_quiet = 1;
         nopt++ ; continue ;
      }
      if( strcmp(argv[nopt],"-verb") == 0 ){
         FDR_quiet = 0 ; nopt++ ; continue ;
      }

      
      /*----- -list -----*/
      if( strcmp(argv[nopt],"-list") == 0 ){
         FDR_list = 1;
         nopt++ ; continue ;
      }

      
      /*----- -prefix prefix -----*/
      if( strcmp(argv[nopt],"-prefix") == 0 ||
          strcmp(argv[nopt],"-output") == 0   ){
         nopt++ ;
         if( nopt >= argc ){
            FDR_error (" need argument after -prefix!");
         }
	 FDR_output_prefix = (char *) malloc (sizeof(char) * THD_MAX_PREFIX); 
         MCW_strncpy( FDR_output_prefix , argv[nopt++] , THD_MAX_PREFIX ) ;
         continue ;
      }


      /*----- unknown command -----*/
      sprintf(message,"Unrecognized command line option: %s\n", argv[nopt]);
      FDR_error (message);
      

   }  /*----- end of loop over command line arguments -----*/


   if( FDR_old == 0 && FDR_pmask ){  /* the new way is on by default */
     fprintf(stderr,"\n"
       "++ The 'new' method of FDR calculation is on by default; in particular:\n"
       " + * Voxel p-values of exactly 1 (e.g., from t=0 or F=0 or correlation=0)\n"
       " +   are ignored by default; in the old mode of operation, they were\n"
       " +   included in the count which goes into the FDR algorithm.  The old\n"
       " +   process tends to increase the q-values and so decrease the z-scores.\n"
       " + * If you wish to do the FDR conversion using the old mode, use '-old'\n"
       " +   on the command line.  For more information, use '3dFDR -help'.\n"
       " + * If you don't want to see this message again, use the '-new' option.\n"
       "++ RWCox - 18 Jan 2008\n\n"
     ) ;
   }

   if( FDR_old < 1 && FDR_pmask == 0 && FDR_mask != NULL ){  /* 29 Jan 2008 */
     fprintf(stderr,"\n"
       "++ In the 'new' method of FDR calculation, options '-nopmask' and\n"
       " +  -mask_file are incompatible.  Am now turning '-pmask' back on\n"
       " +  so that the mask can be used.\n"
       "++ RWCox - 29 Jan 2008\n\n"
     ) ;
     FDR_pmask = 1 ;
   }

   return ;
}
int main( int argc , char *argv[] )
{
   char *aname ;
   THD_3dim_dataset *dset ;
   int ii , scl ;
   MRI_IMAGE *im , *qim ;
   char *fname ;
   float fac ;

   int do_4D=0 , iarg=1 ;    /* 30 Sep 2002 */
   FILE *ifp=NULL ;

   int xxor=-1,yyor=0,zzor=0 , xdir=0,ydir=0,zdir=0;  /* 19 Mar 2003 */
   float                   xdel=0.0  ,ydel=0.0,zdel=0.0;
   char orient_code[4] ;

   /*-- help me if you can --*/

WARNING_message("This program (3dAFNItoANALYZE) is old, not maintained, and probably useless!") ;

   if( argc < 3 || strcmp(argv[1],"-help") == 0 ){
      printf("Usage: 3dAFNItoANALYZE [-4D] [-orient code] aname dset\n"
             "Writes AFNI dataset 'dset' to 1 or more ANALYZE 7.5 format\n"
             ".hdr/.img file pairs (one pair for each sub-brick in the\n"
             "AFNI dataset).  The ANALYZE files will be named\n"
             "  aname_0000.hdr aname_0000.img   for sub-brick #0\n"
             "  aname_0001.hdr aname_0001.img   for sub-brick #1\n"
             "and so forth.  Each file pair will contain a single 3D array.\n"
             "\n"
             "* If the AFNI dataset does not include sub-brick scale\n"
             "  factors, then the ANALYZE files will be written in the\n"
             "  datum type of the AFNI dataset.\n"
             "* If the AFNI dataset does have sub-brick scale factors,\n"
             "  then each sub-brick will be scaled to floating format\n"
             "  and the ANALYZE files will be written as floats.\n"
             "* The .hdr and .img files are written in the native byte\n"
             "  order of the computer on which this program is executed.\n"
             "\n"
             "Options\n"
             "-------\n"
             "-4D [30 Sep 2002]:\n"
             " If you use this option, then all the data will be written to\n"
             " one big ANALYZE file pair named aname.hdr/aname.img, rather\n"
             " than a series of 3D files.  Even if you only have 1 sub-brick,\n"
             " you may prefer this option, since the filenames won't have\n"
             " the '_0000' appended to 'aname'.\n"
             "\n"
             "-orient code [19 Mar 2003]:\n"
             " This option lets you flip the dataset to a different orientation\n"
             " when it is written to the ANALYZE files.  The orientation code is\n"
             " formed as follows:\n"
             "   The code must be 3 letters, one each from the\n"
             "   pairs {R,L} {A,P} {I,S}.  The first letter gives\n"
             "   the orientation of the x-axis, the second the\n"
             "   orientation of the y-axis, the third the z-axis:\n"
             "      R = Right-to-Left          L = Left-to-Right\n"
             "      A = Anterior-to-Posterior  P = Posterior-to-Anterior\n"
             "      I = Inferior-to-Superior   S = Superior-to-Inferior\n"
             "   For example, 'LPI' means\n"
             "      -x = Left       +x = Right\n"
             "      -y = Posterior  +y = Anterior\n"
             "      -z = Inferior   +z = Superior\n"
             " * For display in SPM, 'LPI' or 'RPI' seem to work OK.\n"
             "    Be careful with this: you don't want to confuse L and R\n"
             "    in the SPM display!\n"
             " * If you DON'T use this option, the dataset will be written\n"
             "    out in the orientation in which it is stored in AFNI\n"
             "    (e.g., the output of '3dinfo dset' will tell you this.)\n"
             " * The dataset orientation is NOT stored in the .hdr file.\n"
             " * AFNI and ANALYZE data are stored in files with the x-axis\n"
             "    varying most rapidly and the z-axis most slowly.\n"
             " * Note that if you read an ANALYZE dataset into AFNI for\n"
             "    display, AFNI assumes the LPI orientation, unless you\n"
             "    set environment variable AFNI_ANALYZE_ORIENT.\n"
            ) ;
      PRINT_COMPILE_DATE; exit(0) ;
   }

   mainENTRY("3dAFNItoANALYZE main"); machdep(); PRINT_VERSION("3dAFNItoANALYZE");

   /*-- read inputs --*/

   while( iarg < argc && argv[iarg][0] == '-' ){

     if( strcmp(argv[iarg],"-4D") == 0 ){    /* 30 Sep 2002 */
       do_4D = 1 ; iarg++ ; continue ;
     }

     if( strcmp(argv[iarg],"-orient") == 0 ){ /* 19 Mar 2003 */
       char acod ;

       if( iarg+1 >= argc ){
         fprintf(stderr,"** Need something after -orient!\n"); exit(1);
       }

       MCW_strncpy(orient_code,argv[++iarg],4) ;
       if( strlen(orient_code) != 3 ){
         fprintf(stderr,"** Illegal code '%s' after -orient!\n",argv[iarg]); exit(1);
       }

       acod = toupper(orient_code[0]) ; xxor = ORCODE(acod) ;
       acod = toupper(orient_code[1]) ; yyor = ORCODE(acod) ;
       acod = toupper(orient_code[2]) ; zzor = ORCODE(acod) ;

       if( xxor<0 || yyor<0 || zzor<0 || !OR3OK(xxor,yyor,zzor) ){
         fprintf(stderr,"** Unusable code after -orient!\n"); exit(1);
       }
       iarg++ ; continue ;
     }

     fprintf(stderr,"** Illegal option: %s\n",argv[iarg]); exit(1);
   }

   if( iarg >= argc-1 ){
     fprintf(stderr,"** Not enough arguments on command line!\n"); exit(1);
   }

   aname = argv[iarg++] ;
   if( !THD_filename_ok(aname) ){
     fprintf(stderr,"** Illegal aname string %s\n",aname) ;
     exit(1) ;
   }
   fname = malloc( strlen(aname)+16 ) ;

   dset = THD_open_dataset( argv[iarg++] ); CHECK_OPEN_ERROR(dset,argv[iarg-1]);

   if( xxor >= 0 ){  /* 19 Mar 2003: figure how to flip */
     xdir = THD_get_axis_direction( dset->daxes , xxor ) ;
     ydir = THD_get_axis_direction( dset->daxes , yyor ) ;
     zdir = THD_get_axis_direction( dset->daxes , zzor ) ;
     if(              ydir == 0 || zdir == 0 ) xdir = 0 ;
     if( xdir == 1 && ydir == 2 && zdir == 3 ) xdir = 0 ;
   }
   if( xdir != 0 ){
     float dx=fabs(DSET_DX(dset)) ,
           dy=fabs(DSET_DY(dset)) ,
           dz=fabs(DSET_DZ(dset))  ;
     DSET_mallocize(dset) ;
     switch( xdir ){
       case 1: case -1: xdel = dx ; break ;
       case 2: case -2: xdel = dy ; break ;
       case 3: case -3: xdel = dz ; break ;
     }
     switch( ydir ){
       case 1: case -1: ydel = dx ; break ;
       case 2: case -2: ydel = dy ; break ;
       case 3: case -3: ydel = dz ; break ;
     }
     switch( zdir ){
       case 1: case -1: zdel = dx ; break ;
       case 2: case -2: zdel = dy ; break ;
       case 3: case -3: zdel = dz ; break ;
     }
   } else {
     xdel = fabs(DSET_DX(dset)) ;
     ydel = fabs(DSET_DY(dset)) ;
     zdel = fabs(DSET_DZ(dset)) ;
   }

   DSET_load(dset) ; CHECK_LOAD_ERROR(dset) ;

   /* determine if we scale to floats */

   scl = THD_need_brick_factor( dset ) ;

   /* 30 Sep 2002: if doing a 4D file, write single .hdr now */

   if( do_4D ){
     im = mri_empty_conforming( DSET_BRICK(dset,0) ,
                                (scl) ? MRI_float
                                      : DSET_BRICK_TYPE(dset,0) ) ;

     if( xdir != 0 ){
       qim = mri_flip3D( xdir,ydir,zdir , im ) ;
       if( qim == NULL){
         fprintf(stderr,"mri_flip3D fails?!\n"); exit(1);
       }
       mri_free(im); im = qim;
     }

     im->dx = xdel ;                    /* load voxel sizes */
     im->dy = ydel ;
     im->dz = zdel ;
     im->dw = 1.0 ;

     if( AFNI_yesenv("AFNI_ANALYZE_ORIGINATOR") ){
       im->xo = dset->daxes->xxorg ;                    /* load voxel origin */
       im->yo = dset->daxes->yyorg ;                    /* 03/11/04 KRH added this bit for SPM */
       im->zo = dset->daxes->zzorg ;
       if( ORIENT_sign[dset->daxes->xxorient] == '-' ){
         im->dx = -im->dx ;
         /* im->xo = -im->xo ; */
       }
       if( ORIENT_sign[dset->daxes->yyorient] == '-' ){
         im->dy = -im->dy ;
         /* im->yo = -im->yo ; */
       }
       if( ORIENT_sign[dset->daxes->zzorient] == '-' ){
         im->dz = -im->dz ;
         /* im->zo = -im->zo ; */
       }
     }

     im->nt = DSET_NVALS(dset) ;        /* add a time axis */
     im->dt = DSET_TR(dset) ;
     if( im->dt <= 0.0 ) im->dt = 1.0 ;
     if( DSET_TIMEUNITS(dset) == UNITS_MSEC_TYPE ) im->dt *= 0.001 ; /* 05 Jul 2005 */

     mri_write_analyze( aname , im ) ;  /* output 4D .hdr file */
     mri_free(im) ;

     sprintf(fname,"%s.img",aname) ;    /* open output .img file */
     ifp = fopen( fname , "wb" ) ;
     if( ifp == NULL ){
       fprintf(stderr,"** Can't open file %s for output!\n",fname) ;
       exit(1) ;
     }
   }

   /* loop over sub-bricks */

   for( ii=0 ; ii < DSET_NVALS(dset) ; ii++ ){

      im = DSET_BRICK(dset,ii) ;             /* get the sub-brick */

      if( scl ){                             /* scale it to floats */
        fac = DSET_BRICK_FACTOR(dset,ii) ;
        if( fac == 0.0 ) fac = 1.0 ;
        qim = mri_scale_to_float( fac , im ) ;
      } else {
        qim = im ;
      }

      if( xdir != 0 ){                       /* 19 Mar 2003: flip it */
        MRI_IMAGE *fim ;
        fim = mri_flip3D( xdir,ydir,zdir , qim ) ;
        if( fim == NULL ){
          fprintf(stderr,"mri_flip3D fails at ii=%d ?!\n",ii); exit(1);
        }
        if( qim != im ) mri_free(qim) ;
        qim = fim ;
      }

      if( do_4D ){                           /* 30 Sep 2002: write into 4D .img file */

        fwrite( mri_data_pointer(qim) , qim->nvox , qim->pixel_size , ifp ) ;

      } else {                               /* write separate 3D .hdr/.img files */

        qim->dx = xdel ;    /* load voxel sizes */
        qim->dy = ydel ;
        qim->dz = zdel ;
        qim->dw = 1.0 ;

        if( AFNI_yesenv("AFNI_ANALYZE_ORIGINATOR") ){
          qim->xo = dset->daxes->xxorg ;                    /* load voxel origin */
          qim->yo = dset->daxes->yyorg ;                    /* 03/11/04 KRH added this bit for SPM */
          qim->zo = dset->daxes->zzorg ;

          if( ORIENT_sign[dset->daxes->xxorient] == '-' ){
            qim->dx   = -qim->dx   ;
            /* qim->xo = -qim->xo ; */
          }
          if( ORIENT_sign[dset->daxes->yyorient] == '-' ){
            qim->dy   = -qim->dy   ;
            /* qim->yo = -qim->yo ; */
          }
          if( ORIENT_sign[dset->daxes->zzorient] == '-' ){
            qim->dz   = -qim->dz   ;
            /* qim->zo = -qim->zo ; */
          }
        }

        sprintf(fname,"%s_%04d",aname,ii) ;  /* make up a filename */
        mri_write_analyze( fname , qim ) ;   /* do the real work */
      }

      if( qim != im ) mri_free(qim) ;
      DSET_unload_one(dset,ii) ;             /* clean up the trash */
   }

   if( ifp != NULL ) fclose(ifp) ;           /* 30 Sep 2002 */

   free(fname) ; exit(0) ;
}
Exemple #13
0
int main( int argc , char *argv[] )
{
   THD_3dim_dataset *dset , *oset=NULL , *tset=NULL ;
   int nvals , iv , nxyz , ii,jj,kk , iarg , kz,kzold ;
   float cut1=2.5,cut2=4.0 , sq2p,sfac , fq ;
   MRI_IMAGE *flim ;
   char *prefix="despike" , *tprefix=NULL ;

   int corder=-1 , nref , ignore=0 , polort=2 , nuse , nomask=0 ;
   int nspike, nbig, nproc ;
   float **ref ;
   float  c21,ic21 , pspike,pbig ;
   short  *sar , *qar ;
   byte   *tar , *mask=NULL ;
   float  *zar , *yar ;
   int     datum ;
   int     localedit=0 ;  /* 04 Apr 2007 */
   int     verb=1 ;

   int     do_NEW = 0 ;   /* 29 Nov 2013 */
   MRI_IMAGE *NEW_psinv=NULL ;
   int     dilate = 4 ;   /* 04 Dec 2013 */
   int     ctim   = 0 ;

   /*----- Read command line -----*/

   AFNI_SETUP_OMP(0) ;  /* 24 Jun 2013 */

   if( argc < 2 || strcmp(argv[1],"-help") == 0 ){
      printf("Usage: 3dDespike [options] dataset\n"
             "Removes 'spikes' from the 3D+time input dataset and writes\n"
             "a new dataset with the spike values replaced by something\n"
             "more pleasing to the eye.\n"
             "\n"
             "Method:\n"
             " * L1 fit a smooth-ish curve to each voxel time series\n"
             "    [see -corder option for description of the curve]\n"
             "    [see -NEW option for a different & faster fitting method]\n"
             " * Compute the MAD of the difference between the curve and\n"
             "    the data time series (the residuals).\n"
             " * Estimate the standard deviation 'sigma' of the residuals\n"
             "    as sqrt(PI/2)*MAD.\n"
             " * For each voxel value, define s = (value-curve)/sigma.\n"
             " * Values with s > c1 are replaced with a value that yields\n"
             "    a modified s' = c1+(c2-c1)*tanh((s-c1)/(c2-c1)).\n"
             " * c1 is the threshold value of s for a 'spike' [default c1=2.5].\n"
             " * c2 is the upper range of the allowed deviation from the curve:\n"
             "    s=[c1..infinity) is mapped to s'=[c1..c2)   [default c2=4].\n"
             "\n"
             "Options:\n"
             " -ignore I  = Ignore the first I points in the time series:\n"
             "               these values will just be copied to the\n"
             "               output dataset [default I=0].\n"
             " -corder L  = Set the curve fit order to L:\n"
             "               the curve that is fit to voxel data v(t) is\n"
             "\n"
             "                       k=L [        (2*PI*k*t)          (2*PI*k*t) ]\n"
             " f(t) = a+b*t+c*t*t + SUM  [ d * sin(--------) + e * cos(--------) ]\n"
             "                       k=1 [  k     (    T   )    k     (    T   ) ]\n"
             "\n"
             "               where T = duration of time series;\n"
             "               the a,b,c,d,e parameters are chosen to minimize\n"
             "               the sum over t of |v(t)-f(t)| (L1 regression);\n"
             "               this type of fitting is is insensitive to large\n"
             "               spikes in the data.  The default value of L is\n"
             "               NT/30, where NT = number of time points.\n"
             "\n"
             " -cut c1 c2 = Alter default values for the spike cut values\n"
             "               [default c1=2.5, c2=4.0].\n"
             " -prefix pp = Save de-spiked dataset with prefix 'pp'\n"
             "               [default pp='despike']\n"
             " -ssave ttt = Save 'spikiness' measure s for each voxel into a\n"
             "               3D+time dataset with prefix 'ttt' [default=no save]\n"
             " -nomask    = Process all voxels\n"
             "               [default=use a mask of high-intensity voxels, ]\n"
             "               [as created via '3dAutomask -dilate 4 dataset'].\n"
             " -dilate nd = Dilate 'nd' times (as in 3dAutomask).  The default\n"
             "               value of 'nd' is 4.\n"
             " -q[uiet]   = Don't print '++' informational messages.\n"
             "\n"
             " -localedit = Change the editing process to the following:\n"
             "                If a voxel |s| value is >= c2, then replace\n"
             "                the voxel value with the average of the two\n"
             "                nearest non-spike (|s| < c2) values; the first\n"
             "                one previous and the first one after.\n"
             "                Note that the c1 cut value is not used here.\n"
             "\n"
             " -NEW       = Use the 'new' method for computing the fit, which\n"
             "              should be faster than the L1 method for long time\n"
             "              series (200+ time points); however, the results\n"
             "              are similar but NOT identical. [29 Nov 2013]\n"
             "              * You can also make the program use the 'new'\n"
             "                method by setting the environment variable\n"
             "                  AFNI_3dDespike_NEW\n"
             "                to the value YES; as in\n"
             "                  setenv AFNI_3dDespike_NEW YES  (csh)\n"
             "                  export AFNI_3dDespike_NEW=YES  (bash)\n"
             "              * If this variable is set to YES, you can turn off\n"
             "                the '-NEW' processing by using the '-OLD' option.\n"
             "          -->>* For time series more than 500 points long, the\n"
             "                '-OLD' algorithm is tremendously slow.  You should\n"
             "                use the '-NEW' algorith in such cases.\n"
             "             ** At some indeterminate point in the future, the '-NEW'\n"
             "                method will become the default!\n"
             "          -->>* As of 29 Sep 2016, '-NEW' is the default if there\n"
             "                is more than 500 points in the time series dataset.\n"
             "\n"
             " -NEW25     = A slightly more aggressive despiking approach than\n"
             "              the '-NEW' method.\n"
             "\n"
             "Caveats:\n"
             "* Despiking may interfere with image registration, since head\n"
             "   movement may produce 'spikes' at the edge of the brain, and\n"
             "   this information would be used in the registration process.\n"
             "   This possibility has not been explored or calibrated.\n"
             "* [LATER] Actually, it seems like the registration problem\n"
             "   does NOT happen, and in fact, despiking seems to help!\n"
             "* Check your data visually before and after despiking and\n"
             "   registration!\n"
             "   [Hint: open 2 AFNI controllers, and turn Time Lock on.]\n"
            ) ;

      PRINT_AFNI_OMP_USAGE("3dDespike",NULL) ;
      PRINT_COMPILE_DATE ; exit(0) ;
   }

   /** AFNI package setup and logging **/

   mainENTRY("3dDespike main"); machdep(); AFNI_logger("3dDespike",argc,argv);
   PRINT_VERSION("3dDespike") ; AUTHOR("RW Cox") ;

   /** parse options **/

   if( AFNI_yesenv("AFNI_3dDespike_NEW") ) do_NEW = 1 ;  /* 29 Nov 2013 */

   iarg = 1 ;
   while( iarg < argc && argv[iarg][0] == '-' ){

      if( strncmp(argv[iarg],"-q",2) == 0 ){       /* 04 Apr 2007 */
        verb = 0 ; iarg++ ; continue ;
      }
      if( strncmp(argv[iarg],"-v",2) == 0 ){
        verb++ ; iarg++ ; continue ;
      }

      if( strcmp(argv[iarg],"-NEW") == 0 ){       /* 29 Nov 2013 */
        do_NEW = 1 ; iarg++ ; continue ;
      }
      if( strcmp(argv[iarg],"-NEW25") == 0 ){     /* 29 Sep 2016 */
        do_NEW = 1 ; use_des25 = 1 ; cut1 = 2.5f ; cut2 = 3.2f ; iarg++ ; continue ;
      }
      if( strcmp(argv[iarg],"-OLD") == 0 ){
        do_NEW = 0 ; iarg++ ; continue ;
      }

      /** -localedit **/

      if( strcmp(argv[iarg],"-localedit") == 0 ){  /* 04 Apr 2007 */
        localedit = 1 ; iarg++ ; continue ;
      }

      /** don't use masking **/

      if( strcmp(argv[iarg],"-nomask") == 0 ){
        nomask = 1 ; iarg++ ; continue ;
      }

      /** dilation count [04 Dec 2013] **/

      if( strcmp(argv[iarg],"-dilate") == 0 ){
        dilate = (int)strtod(argv[++iarg],NULL) ;
             if( dilate <=  0 ) dilate = 1 ;
        else if( dilate >  99 ) dilate = 99 ;
        iarg++ ; continue ;
      }

      /** output dataset prefix **/

      if( strcmp(argv[iarg],"-prefix") == 0 ){
        prefix = argv[++iarg] ;
        if( !THD_filename_ok(prefix) ) ERROR_exit("-prefix is not good");
        iarg++ ; continue ;
      }

      /** ratio dataset prefix **/

      if( strcmp(argv[iarg],"-ssave") == 0 ){
        tprefix = argv[++iarg] ;
        if( !THD_filename_ok(tprefix) ) ERROR_exit("-ssave prefix is not good");
        iarg++ ; continue ;
      }

      /** trigonometric polynomial order **/

      if( strcmp(argv[iarg],"-corder") == 0 ){
        corder = strtol( argv[++iarg] , NULL , 10 ) ;
        if( corder < 0 ) ERROR_exit("Illegal value of -corder");
        iarg++ ; continue ;
      }

      /** how much to ignore at start **/

      if( strcmp(argv[iarg],"-ignore") == 0 ){
        ignore = strtol( argv[++iarg] , NULL , 10 ) ;
        if( ignore < 0 ) ERROR_exit("Illegal value of -ignore");
        iarg++ ; continue ;
      }

      /** thresholds for s ratio **/

      if( strcmp(argv[iarg],"-cut") == 0 ){
        cut1 = strtod( argv[++iarg] , NULL ) ;
        cut2 = strtod( argv[++iarg] , NULL ) ;
        if( cut1 < 1.0 || cut2 < cut1+0.5 )
          ERROR_exit("Illegal values after -cut");
        iarg++ ; continue ;
      }

      ERROR_exit("Unknown option: %s",argv[iarg]) ;
   }

   c21 = cut2-cut1 ; ic21 = 1.0/c21 ;

   /*----- read input dataset -----*/

   if( iarg >= argc ) ERROR_exit("No input dataset!!??");

   dset = THD_open_dataset( argv[iarg] ) ;
   CHECK_OPEN_ERROR(dset,argv[iarg]) ;
   datum = DSET_BRICK_TYPE(dset,0) ;
   if( (datum != MRI_short && datum != MRI_float) || !DSET_datum_constant(dset) )
     ERROR_exit("Can't process non-short, non-float dataset!") ;

   if( verb ) INFO_message("Input data type = %s\n",MRI_TYPE_name[datum]) ;
   nvals = DSET_NUM_TIMES(dset) ; nuse = nvals - ignore ;
   if( nuse < 15 )
     ERROR_exit("Can't use dataset with < 15 time points per voxel!") ;

   if( nuse > 500 && !do_NEW ){
     INFO_message("Switching to '-NEW' method since number of time points = %d > 500",nuse) ;
     do_NEW = 1 ;
   }
   if( use_des25 && nuse < 99 ) use_des25 = 0 ;

   if( verb ) INFO_message("ignoring first %d time points, using last %d",ignore,nuse);
   if( corder > 0 && 4*corder+2 > nuse ){
     ERROR_exit("-corder %d is too big for NT=%d",corder,nvals) ;
   } else if( corder < 0 ){
     corder = rint(nuse/30.0) ; if( corder > 50 && !do_NEW ) corder = 50 ;
     if( verb ) INFO_message("using %d time points => -corder %d",nuse,corder) ;
   } else {
     if( verb ) INFO_message("-corder %d set from command line",corder) ;
   }
   nxyz = DSET_NVOX(dset) ;
   if( verb ) INFO_message("Loading dataset %s",argv[iarg]) ;
   DSET_load(dset) ; CHECK_LOAD_ERROR(dset) ;

   /*-- create automask --*/

   if( !nomask ){
     mask = THD_automask( dset ) ;
     if( verb ){
       ii = THD_countmask( DSET_NVOX(dset) , mask ) ;
       INFO_message("%d voxels in the automask [out of %d in dataset]",ii,DSET_NVOX(dset)) ;
     }
     for( ii=0 ; ii < dilate ; ii++ )
       THD_mask_dilate( DSET_NX(dset), DSET_NY(dset), DSET_NZ(dset), mask, 3 ) ;
     if( verb ){
       ii = THD_countmask( DSET_NVOX(dset) , mask ) ;
       INFO_message("%d voxels in the dilated automask [out of %d in dataset]",ii,DSET_NVOX(dset)) ;
     }
   } else {
     if( verb ) INFO_message("processing all %d voxels in dataset",DSET_NVOX(dset)) ;
   }

   /*-- create empty despiked dataset --*/

   oset = EDIT_empty_copy( dset ) ;
   EDIT_dset_items( oset ,
                      ADN_prefix    , prefix ,
                      ADN_brick_fac , NULL ,
                      ADN_datum_all , datum ,
                    ADN_none ) ;

   if( THD_deathcon() && THD_is_file(DSET_HEADNAME(oset)) )
     ERROR_exit("output dataset already exists: %s",DSET_HEADNAME(oset));

   tross_Copy_History( oset , dset ) ;
   tross_Make_History( "3dDespike" , argc , argv , oset ) ;

   /* create bricks (will be filled with zeros) */

   for( iv=0 ; iv < nvals ; iv++ )
     EDIT_substitute_brick( oset , iv , datum , NULL ) ;

   /* copy the ignored bricks */

   switch( datum ){
     case MRI_short:
       for( iv=0 ; iv < ignore ; iv++ ){
         sar = DSET_ARRAY(oset,iv) ;
         qar = DSET_ARRAY(dset,iv) ;
         memcpy( sar , qar , DSET_BRICK_BYTES(dset,iv) ) ;
         DSET_unload_one(dset,iv) ;
       }
     break ;
     case MRI_float:
       for( iv=0 ; iv < ignore ; iv++ ){
         zar = DSET_ARRAY(oset,iv) ;
         yar = DSET_ARRAY(dset,iv) ;
         memcpy( zar , yar , DSET_BRICK_BYTES(dset,iv) ) ;
         DSET_unload_one(dset,iv) ;
       }
     break ;
   }

   /*-- setup to save a threshold statistic dataset, if desired --*/

   if( tprefix != NULL ){
     float *fac ;
     tset = EDIT_empty_copy( dset ) ;
     fac  = (float *) malloc( sizeof(float) * nvals ) ;
     for( ii=0 ; ii < nvals ; ii++ ) fac[ii] = TFAC ;
     EDIT_dset_items( tset ,
                        ADN_prefix    , tprefix ,
                        ADN_brick_fac , fac ,
                        ADN_datum_all , MRI_byte ,
                        ADN_func_type , FUNC_FIM_TYPE ,
                      ADN_none ) ;
     free(fac) ;

     tross_Copy_History( tset , dset ) ;
     tross_Make_History( "3dDespike" , argc , argv , tset ) ;

#if 0
     if( THD_is_file(DSET_HEADNAME(tset)) )
       ERROR_exit("-ssave dataset already exists");
#endif

     tross_Copy_History( tset , dset ) ;
     tross_Make_History( "3dDespike" , argc , argv , tset ) ;

     for( iv=0 ; iv < nvals ; iv++ )
       EDIT_substitute_brick( tset , iv , MRI_byte , NULL ) ;
   }

   /*-- setup to find spikes --*/

   sq2p  = sqrt(0.5*PI) ;
   sfac  = sq2p / 1.4826f ;

   /* make ref functions */

   nref = 2*corder+3 ;
   ref  = (float **) malloc( sizeof(float *) * nref ) ;
   for( jj=0 ; jj < nref ; jj++ )
     ref[jj] = (float *) malloc( sizeof(float) * nuse ) ;

   /* r(t) = 1 */

   for( iv=0 ; iv < nuse ; iv++ ) ref[0][iv] = 1.0 ;
   jj = 1 ;

   /* r(t) = t - tmid */

   { float tm = 0.5 * (nuse-1.0) ; float fac = 2.0 / nuse ;
     for( iv=0 ; iv < nuse ; iv++ ) ref[1][iv] = (iv-tm)*fac ;
     jj = 2 ;

     /* r(t) = (t-tmid)**jj */

     for( ; jj <= polort ; jj++ )
       for( iv=0 ; iv < nuse ; iv++ )
         ref[jj][iv] = pow( (iv-tm)*fac , (double)jj ) ;
   }

   for( kk=1 ; kk <= corder ; kk++ ){
     fq = (2.0*PI*kk)/nuse ;

     /* r(t) = sin(2*PI*k*t/N) */

     for( iv=0 ; iv < nuse ; iv++ )
       ref[jj][iv] = sin(fq*iv) ;
     jj++ ;

     /* r(t) = cos(2*PI*k*t/N) */

     for( iv=0 ; iv < nuse ; iv++ )
       ref[jj][iv] = cos(fq*iv) ;
     jj++ ;
   }

   /****** setup for the NEW solution method [29 Nov 2013] ******/

   if( do_NEW ){
     NEW_psinv = DES_get_psinv(nuse,nref,ref) ;
     INFO_message("Procesing time series with NEW model fit algorithm") ;
   } else {
     INFO_message("Procesing time series with OLD model fit algorithm") ;
   }

   /*--- loop over voxels and do work ---*/

#define Laplace_t2p(val) ( 1.0 - nifti_stat2cdf( (val), 15, 0.0, 1.4427 , 0.0 ) )

   if( verb ){
    if( !localedit ){
      INFO_message("smash edit thresholds: %.1f .. %.1f MADs",cut1*sq2p,cut2*sq2p) ;
      ININFO_message("  [ %.3f%% .. %.3f%% of normal distribution]",
                     200.0*qg(cut1*sfac) , 200.0*qg(cut2*sfac) ) ;
      ININFO_message("  [ %.3f%% .. %.3f%% of Laplace distribution]" ,
                   100.0*Laplace_t2p(cut1) , 100.0*Laplace_t2p(cut2) ) ;
    } else {
      INFO_message("local edit threshold:  %.1f MADS",cut2*sq2p) ;
      ININFO_message("  [ %.3f%% of normal distribution]",
                    200.0*qg(cut2*sfac) ) ;
      ININFO_message("  [ %.3f%% of Laplace distribution]",
                   100.0*Laplace_t2p(cut1) ) ;
    }
    INFO_message("%d slices to process",DSET_NZ(dset)) ;
   }
   kzold  = -1 ;
   nspike =  0 ; nbig = 0 ; nproc = 0 ; ctim = NI_clock_time() ;

 AFNI_OMP_START ;
#pragma omp parallel if( nxyz > 6666 )
 { int ii , iv , iu , id , jj ;
   float *far , *dar , *var , *fitar , *ssp , *fit , *zar ;
   short *sar , *qar ; byte *tar ;
   float fsig , fq , cls , snew , val ;
   float *NEW_wks=NULL ;

#pragma omp critical (DESPIKE_malloc)
  { far   = (float *) malloc( sizeof(float) * nvals ) ;
    dar   = (float *) malloc( sizeof(float) * nvals ) ;
    var   = (float *) malloc( sizeof(float) * nvals ) ;
    fitar = (float *) malloc( sizeof(float) * nvals ) ;
    ssp   = (float *) malloc( sizeof(float) * nvals ) ;
    fit   = (float *) malloc( sizeof(float) * nref  ) ;
    if( do_NEW ) NEW_wks = (float *)malloc(sizeof(float)*DES_workspace_size(nuse,nref)) ;
  }

#ifdef USE_OMP
   INFO_message("start OpenMP thread #%d",omp_get_thread_num()) ;
#endif

#pragma omp for
   for( ii=0 ; ii < nxyz ; ii++ ){   /* ii = voxel index */

      if( mask != NULL && mask[ii] == 0 ) continue ;   /* skip this voxel */

#ifndef USE_OMP
      kz = DSET_index_to_kz(dset,ii) ;       /* starting a new slice */
      if( kz != kzold ){
        if( verb ){
          fprintf(stderr, "++ start slice %2d",kz ) ;
          if( nproc > 0 ){
            pspike = (100.0*nspike)/nproc ;
            pbig   = (100.0*nbig  )/nproc ;
            fprintf(stderr,
                    "; so far %d data points, %d edits [%.3f%%], %d big edits [%.3f%%]",
                    nproc,nspike,pspike,nbig,pbig ) ;
          }
          fprintf(stderr,"\n") ;
        }
        kzold = kz ;
      }
#else
      if( verb && ii % 2345 == 1234 ) fprintf(stderr,".") ;
#endif

      /*** extract ii-th time series into far[] ***/

      switch( datum ){
        case MRI_short:
          for( iv=0 ; iv < nuse ; iv++ ){
            qar = DSET_ARRAY(dset,iv+ignore) ;   /* skip ignored data */
            far[iv] = (float)qar[ii] ;
          }
        break ;
        case MRI_float:
          for( iv=0 ; iv < nuse ; iv++ ){
            zar = DSET_ARRAY(dset,iv+ignore) ;
            far[iv] = zar[ii] ;
          }
        break ;
      }

      AAmemcpy(dar,far,sizeof(float)*nuse) ;   /* copy time series into dar[] */

      /*** solve for L1 fit ***/

      if( do_NEW )
        cls = DES_solve( NEW_psinv , far , fit , NEW_wks ) ; /* 29 Nov 2013 */
      else
        cls = cl1_solve( nuse , nref , far , ref , fit,0 ) ; /* the slow part */

      if( cls < 0.0f ){                      /* fit failed! */
#if 0
        fprintf(stderr,"curve fit fails at voxel %d %d %d\n",
                DSET_index_to_ix(dset,ii) ,
                DSET_index_to_jy(dset,ii) ,
                DSET_index_to_kz(dset,ii)  ) ;
#endif
        continue ;                           /* skip this voxel */
      }

      for( iv=0 ; iv < nuse ; iv++ ){        /* detrend */
        val =  fit[0]
             + fit[1]*ref[1][iv]             /* quadratic part of curve fit */
             + fit[2]*ref[2][iv] ;
        for( jj=3 ; jj < nref ; jj++ )       /* rest of curve fit */
          val += fit[jj] * ref[jj][iv] ;

        fitar[iv] = val ;                    /* save curve fit value */
        var[iv]   = dar[iv]-val ;            /* remove fitted value = resid */
        far[iv]   = fabsf(var[iv]) ;         /* abs value of resid */
      }

      /*** compute estimate standard deviation of detrended data ***/

      fsig = sq2p * qmed_float(nuse,far) ;   /* also mangles far array */

      /*** process time series for spikes, editing data in dar[] ***/

      if( fsig > 0.0f ){                     /* data wasn't fit perfectly */

        /* find spikiness for each point in time */

        fq = 1.0f / fsig ;
        for( iv=0 ; iv < nuse ; iv++ ){
          ssp[iv] = fq * var[iv] ;           /* spikiness s = how many sigma out */
        }

        /* save spikiness in -ssave datset */

        if( tset != NULL ){
          for( iv=0 ; iv < nuse ; iv++ ){
            tar     = DSET_ARRAY(tset,iv+ignore) ;
            snew    = ITFAC*fabsf(ssp[iv]) ;  /* scale for byte storage */
            tar[ii] = BYTEIZE(snew) ;         /* cf. mrilib.h */
          }
        }

        /* process values of |s| > cut1, editing dar[] */

        for( iv=0 ; iv < nuse ; iv++ ){ /* loop over time points */
          if( !localedit ){             /** classic 'smash' edit **/
            if( ssp[iv] > cut1 ){
              snew = cut1 + c21*mytanh((ssp[iv]-cut1)*ic21) ;   /* edit s down */
              dar[iv] = fitar[iv] + snew*fsig ;
#pragma omp critical (DESPIKE_counter)
              { nspike++ ; if( ssp[iv] > cut2 ) nbig++ ; }
            } else if( ssp[iv] < -cut1 ){
              snew = -cut1 + c21*mytanh((ssp[iv]+cut1)*ic21) ;  /* edit s up */
              dar[iv] = fitar[iv] + snew*fsig ;
#pragma omp critical (DESPIKE_counter)
              { nspike++ ; if( ssp[iv] < -cut2 ) nbig++ ; }
            }
          } else {                      /** local edit: 04 Apr 2007 **/
            if( ssp[iv] >= cut2 || ssp[iv] <= -cut2 ){
              for( iu=iv+1 ; iu < nuse ; iu++ )  /* find non-spike above */
                if( ssp[iu] < cut2 && ssp[iu] > -cut2 ) break ;
              for( id=iv-1 ; id >= 0   ; id-- )  /* find non-spike below */
                if( ssp[id] < cut2 && ssp[id] > -cut2 ) break ;
              switch( (id>=0) + 2*(iu<nuse) ){   /* compute replacement val */
                case 3: val = 0.5*(dar[iu]+dar[id]); break; /* iu and id OK */
                case 2: val =      dar[iu]         ; break; /* only iu OK   */
                case 1: val =              dar[id] ; break; /* only id OK   */
               default: val = fitar[iv]            ; break; /* shouldn't be */
              }
              dar[iv] = val ;
#pragma omp critical (DESPIKE_counter)
              { nspike++ ; nbig++ ; }
            }
          }
        } /* end of loop over time points */
#pragma omp atomic
        nproc += nuse ;  /* number data points processed */

      } /* end of processing time series when fsig is positive */

      /* put dar[] time series (possibly edited above) into output bricks */

      switch( datum ){
        case MRI_short:
          for( iv=0 ; iv < nuse ; iv++ ){
            sar = DSET_ARRAY(oset,iv+ignore) ; /* output brick */
            sar[ii] = (short)dar[iv] ;         /* original or mutated data */
          }
        break ;
        case MRI_float:
          for( iv=0 ; iv < nuse ; iv++ ){
            zar = DSET_ARRAY(oset,iv+ignore) ; /* output brick */
            zar[ii] = dar[iv] ;                /* original or mutated data */
          }
        break ;
      }

   } /* end of loop over voxels #ii */

#pragma omp critical (DESPIKE_malloc)
   { free(fit); free(ssp); free(fitar); free(var); free(dar); free(far);
     if( do_NEW ) free(NEW_wks) ; }

 } /* end OpenMP */
 AFNI_OMP_END ;

#ifdef USE_OMP
   if( verb ) fprintf(stderr,"\n") ;
#endif
   ctim = NI_clock_time() - ctim ;
   INFO_message( "Elapsed despike time = %s" , nice_time_string(ctim) ) ;
   if( ctim > 345678 && !do_NEW )
     ININFO_message("That was SLOW -- try the '-NEW' option for a speedup") ;

#ifdef USE_OMP
   if( verb ) fprintf(stderr,"\n") ;
#endif

   /*--- finish up ---*/

   if( do_NEW ) mri_free(NEW_psinv) ;

   DSET_delete(dset) ; /* delete input dataset */

   if( verb ){
     if( nproc > 0 ){
       pspike = (100.0*nspike)/nproc ;
       pbig   = (100.0*nbig  )/nproc ;
       INFO_message("FINAL: %d data points, %d edits [%.3f%%], %d big edits [%.3f%%]",
               nproc,nspike,pspike,nbig,pbig ) ;
     } else {
       INFO_message("FINAL: no good voxels found to process!!??") ;
     }
   }

   /* write results */

   DSET_write(oset) ;
   if( verb ) WROTE_DSET(oset) ;
   DSET_delete(oset) ;

   if( tset != NULL ){
     DSET_write(tset) ;
     if( verb ) WROTE_DSET(tset) ;
     DSET_delete(tset) ;
   }

   exit( THD_get_write_error_count() ) ;
}
Exemple #14
0
/*
   A slightly modified version of MCW_get_intlist, which 
   can scan for label matching instead of just numbers.
   If labels == NULL, then it functions just like 
   MCW_get_intlist
   
                              ZSS Dec 09
*/  
int * MCW_get_labels_intlist (char **labels, int nvals, char *str)
{   
   int *subv = NULL ;
   int ii , ipos , nout , slen ;
   int ibot,itop,istep , nused ;
   char *cpt ;
   static int show_labs = -1;
      
   /* Meaningless input? */
   if( nvals < 1 ) return NULL ;

   /* No selection list? */

   if( str == NULL || str[0] == '\0' ) return NULL ;

   if( show_labs == -1 ) show_labs = AFNI_yesenv("AFNI_SHOW_LABEL_TO_INDEX");

   /* skip initial '[' or '{' or '#'*/

   subv    = (int *) malloc( sizeof(int) * 2 ) ;
   subv[0] = nout = 0 ;

   ipos = 0 ;
   if( str[ipos] == '[' || str[ipos] == '{' || str[ipos] == '#') ipos++ ;

   /* do we have a 1dcat string in there ZSS ? */
   if (strstr(str,"1dcat ")) {
      return(get_1dcat_intlist ( str, &ii, nvals-1 ));
   }
   /* do we have a count string in there ZSS ? */
   if (strstr(str,"count ")) {
      return(get_count_intlist ( str, &ii, nvals-1 ));
   }
     
   /*** loop through each sub-selector until end of input ***/
   slen = strlen(str) ;
   while( ipos < slen && !ISEND(str[ipos]) ){
      while( isspace(str[ipos]) ) ipos++ ;   /* skip blanks */
      if( ISEND(str[ipos]) ) break ;         /* done */

      /** get starting value **/

      if( str[ipos] == '$' ){  /* special case */
         ibot = nvals-1 ; ipos++ ;
      } else if ( !labels || 
                  !(nused = is_in_labels(str+ipos, labels, nvals, &ibot))){
                                                      /* decode integer */
         ibot = strtol( str+ipos , &cpt , 10 ) ;
         if( ibot < 0 && !allow_negative ){
           fprintf(stderr,
                   "** ERROR: selector index %d is out of range 0..%d\n",
                   ibot,nvals-1) ;
           free(subv) ; return NULL ;
         }
         if( ibot >= nvals ){
           fprintf(stderr,
                   "** ERROR: selector index %d is out of range 0..%d\n",
                   ibot,nvals-1) ;
           free(subv) ; return NULL ;
         }
         nused = (cpt-(str+ipos)) ;
         if( ibot == 0 && nused == 0 ){
           fprintf(stderr,
                   "** ERROR: selector syntax error 5 '%s'\n",str+ipos) ;
           free(subv) ; return NULL ;
         }
         ipos += nused ;
      } else {
         if( show_labs )
            fprintf(stderr,"-- label select: sub-brick %d is from label %s\n",
                        ibot, labels[ibot]);
         ipos+=nused;
      }

      while( isspace(str[ipos]) ) ipos++ ;   /* skip blanks */

      /** if that's it for this sub-selector, add one value to list **/

      if( str[ipos] == ',' || ISEND(str[ipos]) ){
         nout++ ;
         subv = (int *) realloc( (char *)subv , sizeof(int) * (nout+1) ) ;
         subv[0]    = nout ;
         subv[nout] = ibot ;
         if( ISEND(str[ipos]) ) break ; /* done */
         ipos++ ; continue ;            /* re-start loop at next sub-selector */
      }

      /** otherwise, must have '..' or '-' as next inputs **/

      if( str[ipos] == '-' || str[ipos] == ':' ){
         ipos++ ;
      } else if( str[ipos] == '.' && str[ipos+1] == '.' ){
         ipos++ ; ipos++ ;
      } else {
         fprintf(stderr,"** ERROR: selector selector syntax is bad: '%s'\n",
                 str+ipos) ;
         free(subv) ; return NULL ;
      }

      /** get ending value for loop now **/

      if( str[ipos] == '$' ){  /* special case */
         itop = nvals-1 ; ipos++ ;
      } else if ( !labels ||
                  !(nused = is_in_labels(str+ipos,labels, nvals, &itop))){  
                                                      /* decode integer */
         itop = strtol( str+ipos , &cpt , 10 ) ;
         if( itop < 0 && !allow_negative ){
           fprintf(stderr,"** ERROR: selector index %d is out of range 0..%d\n",
                   itop,nvals-1) ;
           free(subv) ; return NULL ;
         }
         if( itop >= nvals ){
           fprintf(stderr,"** ERROR: selector index %d is out of range 0..%d\n",
                   itop,nvals-1) ;
           free(subv) ; return NULL ;
         }
         nused = (cpt-(str+ipos)) ;
         if( itop == 0 && nused == 0 ){
           fprintf(stderr,"** ERROR: selector syntax error 6 '%s'\n",str+ipos) ;
           free(subv) ; return NULL ;
         }
         ipos += nused ;
      } else {
         /* have a label */
         if( show_labs )
            fprintf(stderr,"-- label select: sub-brick %d is from label %s\n",
                        itop, labels[itop]);
         ipos+=nused;
      }

      /** set default loop step **/

      istep = (ibot <= itop) ? 1 : -1 ;

      while( isspace(str[ipos]) ) ipos++ ;                  /* skip blanks */

      /** check if we have a non-default loop step **/

      if( str[ipos] == '(' ){  /* decode an integer */
         ipos++ ;
         istep = strtol( str+ipos , &cpt , 10 ) ;
         if( istep == 0 ){
           fprintf(stderr,"** ERROR: selector loop step is 0!\n") ;
           free(subv) ; return NULL ;
         }
         nused = (cpt-(str+ipos)) ;
         ipos += nused ;
         if( str[ipos] == ')' ) ipos++ ;
         if( (ibot-itop)*istep > 0 ){
           fprintf(  stderr,
                     "** WARNING: selector count '%d..%d(%d)' means nothing!\n",
                     ibot,itop,istep ) ;
         }
      }

      /** add values to output **/

      for( ii=ibot ; (ii-itop)*istep <= 0 ; ii += istep ){
         nout++ ;
         subv = (int *) realloc( (char *)subv , sizeof(int) * (nout+1) ) ;
         subv[0]    = nout ;
         subv[nout] = ii ;
      }

      /** check if we have a comma to skip over **/

      while( isspace(str[ipos]) ) ipos++ ;                  /* skip blanks */
      if( str[ipos] == ',' ) ipos++ ;                       /* skip commas */

   }  /* end of loop through selector string */

   if( subv[0] == 0 ){ free(subv); subv = NULL; }
   return subv ;
}
Exemple #15
0
THD_3dim_dataset * THD_open_nifti( char *pathname )
{
   THD_3dim_dataset *dset=NULL ;
   nifti_image *nim ;
   int ntt , nbuc , nvals ;
   int use_qform = 0 , use_sform = 0, form_code = 0 ;
   int statcode = 0 , datum , iview , ibr ;
   int scale_data = 0 ;  /* flag based on scl_slope and inter  20 Jun 2008 */
   int xform_data = 0;
   THD_ivec3 orixyz , nxyz ;
   THD_fvec3 dxyz , orgxyz ;
   THD_mat33 R ;
   mat44 ijk_to_dicom44 ;
   char *ppp , prefix[THD_MAX_PREFIX] ;
   char form_priority = 'S' ;             /* 23 Mar 2006 */
   static int n_xform_warn=0;
   
ENTRY("THD_open_nifti") ;

   /*-- open input file --*/

   { /* set the nifti_io debug level       8 Apr 2005 [rickr] */
      char * ept = my_getenv("AFNI_NIFTI_DEBUG");
      if( ept != NULL ) nifti_set_debug_level(atoi(ept));
   }

   nifti_set_alter_cifti(1) ;  /* if CIFTI, shift dims   23 Jul 2015 [rickr] */
   nim = nifti_image_read( pathname, 0 ) ;

   if( nim == NULL || nim->nifti_type == 0 ) RETURN(NULL) ;

   /*-- extract some useful AFNI-ish information from the nim struct --*/

   /* we must have at least 2 spatial dimensions */

   /* this should be okay                 11 Jun 2007 */
   /* if( nim->nx < 2 || nim->ny < 2 ) RETURN(NULL) ; */

   /* 4th dimension = time; 5th dimension = bucket:
      these are mutually exclusive in AFNI at present */

   ntt = nim->nt ; nbuc = nim->nu ;

   /* nt and nu might be 0 now (see irritating niftilib 1.17 update)  */
   /* so ensure that ntt and nbuc are positive    02 Mar 2006 [rickr] */

   if( ntt  <= 0 ) ntt  = 1;
   if( nbuc <= 0 ) nbuc = 1;

   if( nim->nz <= 0 ) nim->nz = 1 ;  /* 03 Mar 2006: RWCox */

   if( ntt > 1 && nbuc > 1 ){
     fprintf(stderr,
             "** AFNI can't deal with 5 dimensional NIfTI(%s)\n",
             pathname ) ;
     RETURN(NULL) ;
   }

   nvals = MAX(ntt,nbuc) ;

   /* collapse higher-dimensional datasets    23 Jul 2015 [rickr] */
   /* (this includes CIFTI)                                       */
   if( nim->nv > 1 ) nvals *= nim->nv;
   if( nim->nw > 1 ) nvals *= nim->nw;
   if( ntt > 1 ) ntt = nvals;
   else          nbuc = nvals;

   /* determine type of dataset values:
      if we are scaling, or if the data type in the NIfTI file
      is something AFNI can't handle, then the result will be floats */

   /* do not scale if slope is 0 or if slope is 1 and inter is 0 */
   if( !isfinite(nim->scl_slope) || !isfinite(nim->scl_inter) ){
      fprintf(stderr,"** bad scl_slope and inter = %f, %f, ignoring...\n",
              nim->scl_slope, nim->scl_inter);
   } else {
       scale_data = nim->scl_slope != 0.0 &&
                        (nim->scl_slope != 1.0 || nim->scl_inter != 0.0) ;
   }
   { char *eee = getenv("AFNI_NIFTI_SCALE") ;
     if( eee != NULL && toupper(*eee) == 'N' ) scale_data = 0 ;
   }

   switch( nim->datatype ){
     default:
       fprintf(stderr,
               "** AFNI can't handle NIFTI datatype=%d (%s) in file %s\n",
               nim->datatype, nifti_datatype_string(nim->datatype), pathname );
       RETURN(NULL) ;
     break ;

     case DT_UINT8:     datum = scale_data ? MRI_float : MRI_byte  ;
                        xform_data = scale_data;
                        break ;
     case DT_INT16:     datum = scale_data ? MRI_float : MRI_short ;
                        xform_data = scale_data;
                        break ;
     case DT_FLOAT32:   datum = MRI_float   ; break ;
     case DT_COMPLEX64: datum = MRI_complex ; break ;
     case DT_RGB24:     datum = MRI_rgb     ; break ;

     case DT_INT8:      /* NIfTI-1 data types that AFNI can't handle directly */
     case DT_UINT16:
     case DT_INT32:
     case DT_UINT32:
     case DT_FLOAT64:   datum = MRI_float ; xform_data = 1 ; break ;

#if 0
     case DT_COMPLEX128:  /* this case would be too much like real work */
       fprintf(stderr,
               "** AFNI convert NIFTI_datatype=%d (%s) in file %s to COMPLEX64\n",
               nim->datatype, nifti_datatype_string(nim->datatype), pathname );
       datum = MRI_complex ;
     break ;
#endif
   }

   if( xform_data && !AFNI_noenv("AFNI_NIFTI_TYPE_WARN")) {
      if (!n_xform_warn || AFNI_yesenv("AFNI_NIFTI_TYPE_WARN")) {/* ZSS 04/11 */
         fprintf(stderr,
             "** AFNI converts NIFTI_datatype=%d (%s) in file %s to FLOAT32\n",
             nim->datatype, nifti_datatype_string(nim->datatype), pathname );
         if (!AFNI_yesenv("AFNI_NIFTI_TYPE_WARN")) {
            fprintf(stderr,
               "     Warnings of this type will be muted for this session.\n"
      "     Set AFNI_NIFTI_TYPE_WARN to YES to see them all, NO to see none.\n");
         }
      }
      ++n_xform_warn;
   }
   /* check for statistics code */

   if( nim->intent_code >= NIFTI_FIRST_STATCODE &&
       nim->intent_code <= NIFTI_LAST_STATCODE    ){

     if( nim->intent_code > FUNC_PT_TYPE ){
       fprintf(stderr,
               "** AFNI doesn't understand NIFTI statistic type %d (%s) in file %s\n",
               nim->intent_code , nifti_intent_string(nim->intent_code) , pathname ) ;
     } else {
       statcode = nim->intent_code ;
       if( nbuc > 1 ){
         fprintf(stderr,
                 "** AFNI doesn't support NIFTI voxel-dependent statistic parameters"
                 " in file %s\n" , pathname ) ;
         statcode = 0 ;
       }
     }
   }

   /* 23 Mar 2006: set qform or sform as having priority -- RWCox */

   ppp = my_getenv("NIFTI_FORM_PRIORITY") ;
   if( ppp == NULL ) ppp = getenv("AFNI_FORM_PRIORITY") ;
   if( ppp == NULL ) ppp = getenv("AFNI_NIFTI_PRIORITY") ;
   if( ppp == NULL ) ppp = getenv("AFNI_NIFTI_FORM") ;
   if( ppp == NULL ) ppp = getenv("AFNI_NIFTI_FORM_PRIORITY") ;
   if( ppp != NULL ){
     char fp = toupper(*ppp) ;
     if( fp == 'S' || fp == 'Q' ) form_priority = fp ;
     else WARNING_message("Illegal NIFTI_FORM_PRIORITY='%s'",ppp) ;
   }

   /** 24 Mar 2006: check determs of qform and sform, if have both **/

   if( nim->qform_code > 0 && nim->sform_code > 0 ){
     float qdet , sdet ;
     LOAD_MAT(R, nim->qto_xyz.m[0][0] ,
                 nim->qto_xyz.m[0][1] ,
                 nim->qto_xyz.m[0][2] ,
                 nim->qto_xyz.m[1][0] ,
                 nim->qto_xyz.m[1][1] ,
                 nim->qto_xyz.m[1][2] ,
                 nim->qto_xyz.m[2][0] ,
                 nim->qto_xyz.m[2][1] ,
                 nim->qto_xyz.m[2][2]  ) ; qdet = MAT_DET(R) ;

     LOAD_MAT(R, nim->sto_xyz.m[0][0] ,
                 nim->sto_xyz.m[0][1] ,
                 nim->sto_xyz.m[0][2] ,
                 nim->sto_xyz.m[1][0] ,
                 nim->sto_xyz.m[1][1] ,
                 nim->sto_xyz.m[1][2] ,
                 nim->sto_xyz.m[2][0] ,
                 nim->sto_xyz.m[2][1] ,
                 nim->sto_xyz.m[2][2]  ) ; sdet = MAT_DET(R) ;

     if( qdet*sdet < 0.0f )
       WARNING_message("NIfTI('%s'): Qform/Sform handedness differ; %c wins!",
                       pathname , form_priority ) ;
   }

   /* KRH 07/11/05 -- adding ability to choose spatial transform
      from the options of qform, sform, bothform, or noform.

      If qform is present, it will be used.

      If qform is absent, but sform present, then the sform
        will be modified to be an orthogonal rotation and used.

      If both qform and sform are absent, then we will have
        an error.

      Previously assumed qform present.  */

   /* 23 Mar 2006: use form_priority to choose between them */

   if ((nim->qform_code > 0) && (nim->sform_code > 0) ) {
     if( form_priority == 'Q' )   { use_qform = 1 ; use_sform = 0 ; }
     else                         { use_qform = 0 ; use_sform = 1 ; }
   } else if (nim->qform_code > 0){ use_qform = 1 ; use_sform = 0 ; }
     else if (nim->sform_code > 0){ use_qform = 0 ; use_sform = 1 ; }
     else {
                                    use_qform = 0 ; use_sform = 0 ;
     WARNING_message(
      "NO spatial transform (neither qform nor sform), in NIfTI file '%s'" ,
      pathname ) ;
   }

   /** now take NIfTI-1.1 coords and transform to AFNI codes **/

   if (use_qform) {

     float orgx, orgy, orgz ;

     form_code = nim->qform_code;

     /* determine orientation from the qto_xyz matrix,
      which transforms (i,j,k) voxel indexes to (x,y,z) LPI coordinates */

     LOAD_MAT(R, -nim->qto_xyz.m[0][0] ,  /* negate x and y   */
                 -nim->qto_xyz.m[0][1] ,  /* coefficients,    */
                 -nim->qto_xyz.m[0][2] ,  /* since AFNI works */
                 -nim->qto_xyz.m[1][0] ,  /* with RAI coords, */
                 -nim->qto_xyz.m[1][1] ,  /* but NIFTI uses   */
                 -nim->qto_xyz.m[1][2] ,  /* LPI coordinates. */
                  nim->qto_xyz.m[2][0] ,  /* [Which is my own] */
                  nim->qto_xyz.m[2][1] ,  /* [damn fault!!!!!] */
                  nim->qto_xyz.m[2][2]  ) ;

     LOAD_MAT44(ijk_to_dicom44,
                 -nim->qto_xyz.m[0][0] ,  /* negate x and y   */
                 -nim->qto_xyz.m[0][1] ,  /* coefficients,    */
                 -nim->qto_xyz.m[0][2] ,  /* since AFNI works */
                 -nim->qto_xyz.m[0][3] ,
                 -nim->qto_xyz.m[1][0] ,  /* with RAI coords, */
                 -nim->qto_xyz.m[1][1] ,  /* but NIFTI uses   */
                 -nim->qto_xyz.m[1][2] ,  /* LPI coordinates. */
                 -nim->qto_xyz.m[1][3] ,
                  nim->qto_xyz.m[2][0] ,  /* [Which is my own] */
                  nim->qto_xyz.m[2][1] ,  /* [damn fault!!!!!] */
                  nim->qto_xyz.m[2][2] ,  
                  nim->qto_xyz.m[2][3] ) ;

     orixyz = THD_matrix_to_orientation( R ) ;   /* compute orientation codes */

     iview = NIFTI_code_to_view(nim->qform_code);

     /* load the offsets and the grid spacings */

     if (ORIENT_xyz[orixyz.ijk[0]] == 'z' )  {
       orgx = nim->qto_xyz.m[ORIENT_xyzint[orixyz.ijk[0]] - 1][3] ;
     } else {
       orgx = - nim->qto_xyz.m[ORIENT_xyzint[orixyz.ijk[0]] - 1][3] ;
     }

     if (ORIENT_xyz[orixyz.ijk[1]] == 'z' )  {
       orgy = nim->qto_xyz.m[ORIENT_xyzint[orixyz.ijk[1]] - 1][3] ;
     } else {
       orgy = - nim->qto_xyz.m[ORIENT_xyzint[orixyz.ijk[1]] - 1][3] ;
     }

     if (ORIENT_xyz[orixyz.ijk[2]] == 'z' )  {
       orgz = nim->qto_xyz.m[ORIENT_xyzint[orixyz.ijk[2]] - 1][3] ;
     } else {
       orgz = - nim->qto_xyz.m[ORIENT_xyzint[orixyz.ijk[2]] - 1][3] ;
     }


     LOAD_FVEC3( orgxyz ,  orgx ,
                           orgy ,
                           orgz  ) ;
#if 0
     LOAD_FVEC3( orgxyz , -nim->qto_xyz.m[0][3] ,    /* again, negate  */
                        -nim->qto_xyz.m[1][3] ,    /* x and y coords */
                         nim->qto_xyz.m[2][3]  ) ;
#endif

     /* AFNI space units are always mm */

     if( nim->xyz_units == NIFTI_UNITS_METER ){
       nim->dx *= 1000.0 ; nim->dy *= 1000.0 ; nim->dz *= 1000.0 ;
     } else if(  nim->xyz_units == NIFTI_UNITS_MICRON ){
       nim->dx *= 0.001  ; nim->dy *= 0.001  ; nim->dz *= 0.001  ;
     }

     LOAD_FVEC3( dxyz , (ORIENT_sign[orixyz.ijk[0]]=='+') ? nim->dx : -nim->dx ,
                        (ORIENT_sign[orixyz.ijk[1]]=='+') ? nim->dy : -nim->dy ,
                        (ORIENT_sign[orixyz.ijk[2]]=='+') ? nim->dz : -nim->dz  ) ;

   } else if (use_sform) {

     int orimap[7] = { 6 , 1 , 0 , 2 , 3 , 4 , 5 } ;
     int oritmp[3] ;
     float dxtmp, dytmp, dztmp ;
     float xmax, ymax, zmax ;
     float orgx, orgy, orgz ;
     float fig_merit, ang_merit ;

     form_code = nim->sform_code;

     /* convert sform to nifti orientation codes */

     /* n2   10 Jul, 2015 [rickr] */
     nifti_dmat44_to_orientation(nim->sto_xyz,
                                 &oritmp[0], &oritmp[1], &oritmp[2] ) ;

     /* convert nifti orientation codes to AFNI codes and store in vector */

     LOAD_IVEC3( orixyz , orimap[oritmp[0]] ,
                          orimap[oritmp[1]] ,
                          orimap[oritmp[2]] ) ;

     /* assume original view if there's no talairach id present */
     iview = NIFTI_code_to_view(nim->sform_code);

     /* load the offsets and the grid spacings */

     if (ORIENT_xyz[orixyz.ijk[0]] == 'z' )  {
       orgx = nim->sto_xyz.m[ORIENT_xyzint[orixyz.ijk[0]] - 1][3] ;
     } else {
       orgx = - nim->sto_xyz.m[ORIENT_xyzint[orixyz.ijk[0]] - 1][3] ;
     }

     if (ORIENT_xyz[orixyz.ijk[1]] == 'z' )  {
       orgy = nim->sto_xyz.m[ORIENT_xyzint[orixyz.ijk[1]] - 1][3] ;
     } else {
       orgy = - nim->sto_xyz.m[ORIENT_xyzint[orixyz.ijk[1]] - 1][3] ;
     }

     if (ORIENT_xyz[orixyz.ijk[2]] == 'z' )  {
       orgz = nim->sto_xyz.m[ORIENT_xyzint[orixyz.ijk[2]] - 1][3] ;
     } else {
       orgz = - nim->sto_xyz.m[ORIENT_xyzint[orixyz.ijk[2]] - 1][3] ;
     }


     LOAD_FVEC3( orgxyz ,  orgx ,
                           orgy ,
                           orgz  ) ;

#if 0
     LOAD_FVEC3( orgxyz , -nim->sto_xyz.m[0][3] ,    /* again, negate  */
                          -nim->sto_xyz.m[1][3] ,    /* x and y coords */
                           nim->sto_xyz.m[2][3] ) ;
#endif

#define MAXNUM(a,b) ( (a) > (b) ? (a):(b))
#define MAX3(a,b,c) ( (MAXNUM(a,b)) > (MAXNUM(a,c)) ? (MAXNUM(a,b)):(MAXNUM(a,c)))
#define MINNUM(a,b) ( (a) < (b) ? (a):(b))
#define MIN3(a,b,c) ( (MINNUM(a,b)) < (MINNUM(a,c)) ? (MINNUM(a,b)):(MINNUM(a,c)))

     dxtmp = sqrt ( nim->sto_xyz.m[0][0] * nim->sto_xyz.m[0][0] +
                    nim->sto_xyz.m[1][0] * nim->sto_xyz.m[1][0] +
                    nim->sto_xyz.m[2][0] * nim->sto_xyz.m[2][0] ) ;

     xmax = MAX3(fabs(nim->sto_xyz.m[0][0]),fabs(nim->sto_xyz.m[1][0]),fabs(nim->sto_xyz.m[2][0])) / dxtmp ;

     dytmp = sqrt ( nim->sto_xyz.m[0][1] * nim->sto_xyz.m[0][1] +
                    nim->sto_xyz.m[1][1] * nim->sto_xyz.m[1][1] +
                    nim->sto_xyz.m[2][1] * nim->sto_xyz.m[2][1] ) ;

     ymax = MAX3(fabs(nim->sto_xyz.m[0][1]),fabs(nim->sto_xyz.m[1][1]),fabs(nim->sto_xyz.m[2][1])) / dytmp ;

     dztmp = sqrt ( nim->sto_xyz.m[0][2] * nim->sto_xyz.m[0][2] +
                    nim->sto_xyz.m[1][2] * nim->sto_xyz.m[1][2] +
                    nim->sto_xyz.m[2][2] * nim->sto_xyz.m[2][2] ) ;

     zmax = MAX3(fabs(nim->sto_xyz.m[0][2]),fabs(nim->sto_xyz.m[1][2]),fabs(nim->sto_xyz.m[2][2])) / dztmp ;

     fig_merit = MIN3(xmax,ymax,zmax) ;
     ang_merit = acos (fig_merit) * 180.0 / 3.141592653 ;
#if 0
     if (fabs(ang_merit) > .01) {
       WARNING_message (
         "qform not present in:\n"
         "   '%s'\n"
         "  oblique sform used, and the worst axis is\n"
         "  %f degrees from plumb.\n"
         "  If you are performing spatial transformations on this dset, \n"
         "  or viewing/combining it with volumes of differing obliquity,\n"
         "  you should consider running: \n"
         "     3dWarp -deoblique \n"
         "  on this and  other oblique datasets in the same session.\n"
         ,pathname, ang_merit ) ;
     }
#endif

     if( nim->xyz_units == NIFTI_UNITS_METER ){
       dxtmp *= 1000.0 ; dytmp *= 1000.0 ; dztmp *= 1000.0 ;
     } else if(  nim->xyz_units == NIFTI_UNITS_MICRON ){
       dxtmp *= 0.001  ; dytmp *= 0.001  ; dztmp *= 0.001  ;
     }

     LOAD_FVEC3( dxyz , (ORIENT_sign[orixyz.ijk[0]]=='+') ? dxtmp : -dxtmp ,
                        (ORIENT_sign[orixyz.ijk[1]]=='+') ? dytmp : -dytmp ,
                        (ORIENT_sign[orixyz.ijk[2]]=='+') ? dztmp : -dztmp ) ;

     LOAD_MAT44(ijk_to_dicom44, -nim->sto_xyz.m[0][0] ,  /* negate x and y   */
                 -nim->sto_xyz.m[0][1] ,  /* coefficients,    */
                 -nim->sto_xyz.m[0][2] ,  /* since AFNI works */
                 -nim->sto_xyz.m[0][3] ,
                 -nim->sto_xyz.m[1][0] ,  /* with RAI coords, */
                 -nim->sto_xyz.m[1][1] ,  /* but NIFTI uses   */
                 -nim->sto_xyz.m[1][2] ,  /* LPI coordinates. */
                 -nim->sto_xyz.m[1][3] ,
                  nim->sto_xyz.m[2][0] ,  /* [Which is my own] */
                  nim->sto_xyz.m[2][1] ,  /* [damn fault!!!!!] */
                  nim->sto_xyz.m[2][2] ,  
                  nim->sto_xyz.m[2][3] ) ;

   } else { /* NO SPATIAL XFORM. BAD BAD BAD BAD BAD BAD. */

     float dxtmp, dytmp, dztmp ;

     /* if pixdim data are present, use them in order to set pixel
        dimensions.  otherwise, set the dimensions to 1 unit.         */

     dxtmp = ((nim->pixdim[1] > 0) ? nim->pixdim[1] : 1) ;
     dytmp = ((nim->pixdim[2] > 0) ? nim->pixdim[2] : 1) ;
     dztmp = ((nim->pixdim[3] > 0) ? nim->pixdim[3] : 1) ;

     if( nim->xyz_units == NIFTI_UNITS_METER ){
       dxtmp *= 1000.0 ; dytmp *= 1000.0 ; dztmp *= 1000.0 ;
     } else if(  nim->xyz_units == NIFTI_UNITS_MICRON ){
       dxtmp *= 0.001  ; dytmp *= 0.001  ; dztmp *= 0.001  ;
     }

     /* set orientation to LPI by default    */

     LOAD_IVEC3( orixyz , 1 ,
                          2 ,
                          4 ) ;

     LOAD_FVEC3( dxyz , (ORIENT_sign[orixyz.ijk[0]]=='+') ? dxtmp : -dxtmp ,
                        (ORIENT_sign[orixyz.ijk[1]]=='+') ? dytmp : -dytmp ,
                        (ORIENT_sign[orixyz.ijk[2]]=='+') ? dztmp : -dztmp ) ;

     iview = NIFTI_default_view();

     /* set origin to 0,0,0   */

     LOAD_FVEC3( orgxyz , 0 ,
                          0 ,
                          0 ) ;
     /* put scaled identity matrix by default */
     LOAD_MAT44(ijk_to_dicom44, dxtmp, 0.0, 0.0, 0.0,  
                                0.0, dytmp, 0.0, 0.0,
                                0.0, 0.0, dztmp, 0.0 );
   }



   /*-- make an AFNI dataset! --*/

   dset = EDIT_empty_copy(NULL) ;

   ppp  = THD_trailname(pathname,0) ;               /* strip directory */
   MCW_strncpy( prefix , ppp , THD_MAX_PREFIX ) ;   /* to make prefix */
   
   /* You need to set the path too
      before, if you loaded ~/tmp/joe.nii the path appeared
      to be ./joe.nii, troubling in multiple instances.
                                                      ZSS Dec 2011 */
   THD_init_diskptr_names( dset->dblk->diskptr ,
                           THD_filepath(pathname) ,
                           NULL , prefix ,
                           dset->view_type , True );
                           
   nxyz.ijk[0] = nim->nx ;                          /* grid dimensions */
   nxyz.ijk[1] = nim->ny ;
   nxyz.ijk[2] = nim->nz ;

   dset->idcode.str[0] = 'N' ;  /* overwrite 1st 3 bytes with something special */
   dset->idcode.str[1] = 'I' ;
   dset->idcode.str[2] = 'I' ;

   MCW_hash_idcode( pathname , dset ) ;  /* 06 May 2005 */

   EDIT_dset_items( dset ,
                      ADN_prefix      , prefix ,
                      ADN_datum_all   , datum ,
                      ADN_nxyz        , nxyz ,
                      ADN_xyzdel      , dxyz ,
                      ADN_xyzorg      , orgxyz ,
                      ADN_xyzorient   , orixyz ,
                      ADN_malloc_type , DATABLOCK_MEM_MALLOC ,
                      ADN_view_type   , iview ,
                      ADN_type        , (statcode != 0) ? HEAD_FUNC_TYPE
                                                        : HEAD_ANAT_TYPE ,
                    ADN_none ) ;

   /* copy transformation matrix to dataset structure */
   /* moved after setting grid     4 Apr 2014 [rickr,drg] */
   dset->daxes->ijk_to_dicom_real = ijk_to_dicom44;

   /* not a time dependent dataset */

   if( ntt < 2 ){
     EDIT_dset_items( dset ,
                        ADN_nvals     , nbuc ,
                        ADN_datum_all , datum ,
                        ADN_func_type , (statcode != 0) ? FUNC_BUCK_TYPE
                                                        : ANAT_BUCK_TYPE ,
                      ADN_none ) ;

   } else {  /* is a time dependent dataset */

     if( nim->time_units == NIFTI_UNITS_MSEC ){
            nim->dt *= 0.001 ;
            nim->toffset *= 0.001 ;
     } else if( nim->time_units == NIFTI_UNITS_USEC ){
            nim->dt *= 1.e-6 ;
            nim->toffset *= 1.e-6 ;
     }
     EDIT_dset_items( dset ,
                        ADN_nvals     , ntt ,
                        ADN_ntt       , ntt ,
                        ADN_datum_all , datum ,
                        ADN_ttorg     , nim->toffset , /* 12 Oct 2007 [rickr] */
                        ADN_ttdel     , nim->dt ,
                        ADN_ttdur     , 0.0 ,
                        ADN_tunits    , UNITS_SEC_TYPE ,
                        ADN_func_type , (statcode != 0) ? FUNC_FIM_TYPE
                                                        : ANAT_EPI_TYPE ,
                      ADN_none ) ;

     /* if present, add stuff about the slice-timing offsets */

     if( nim->slice_dim      == 3               && /* AFNI can only deal with */
         nim->slice_code     >  0               && /* slice timing offsets    */
         nim->slice_duration >  0.0             && /* along the k-axis of     */
         nim->slice_start    >= 0               && /* the dataset volume      */
         nim->slice_start    < nim->nz          &&
         nim->slice_end      > nim->slice_start &&
         nim->slice_end      < nim->nz             ){

       float *toff=(float *)calloc(sizeof(float),nim->nz) , tsl ;
       int kk ;

            if( nim->time_units == NIFTI_UNITS_MSEC ) nim->slice_duration *= 0.001;
       else if( nim->time_units == NIFTI_UNITS_USEC ) nim->slice_duration *= 1.e-6;

       /* set up slice time offsets in the divers orders */

       switch( nim->slice_code ){
         case NIFTI_SLICE_SEQ_INC:
           tsl = 0.0 ;
           for( kk=nim->slice_start ; kk <= nim->slice_end ; kk++ ){
             toff[kk] = tsl ; tsl += nim->slice_duration ;
           }
         break ;
         case NIFTI_SLICE_SEQ_DEC:
           tsl = 0.0 ;
           for( kk=nim->slice_end ; kk >= nim->slice_end ; kk-- ){
             toff[kk] = tsl ; tsl += nim->slice_duration ;
           }
         break ;
         case NIFTI_SLICE_ALT_INC:
           tsl = 0.0 ;
           for( kk=nim->slice_start ; kk <= nim->slice_end ; kk+=2 ){
             toff[kk] = tsl ; tsl += nim->slice_duration ;
           }
           for( kk=nim->slice_start+1 ; kk <= nim->slice_end ; kk+=2 ){
             toff[kk] = tsl ; tsl += nim->slice_duration ;
           }
         break ;
         case NIFTI_SLICE_ALT_INC2:
           tsl = 0.0 ;
           for( kk=nim->slice_start+1 ; kk <= nim->slice_end ; kk+=2 ){
             toff[kk] = tsl ; tsl += nim->slice_duration ;
           }
           for( kk=nim->slice_start ; kk <= nim->slice_end ; kk+=2 ){
             toff[kk] = tsl ; tsl += nim->slice_duration ;
           }
         break ;
         case NIFTI_SLICE_ALT_DEC:
           tsl = 0.0 ;
           for( kk=nim->slice_end ; kk >= nim->slice_start ; kk-=2 ){
             toff[kk] = tsl ; tsl += nim->slice_duration ;
           }
           for( kk=nim->slice_end-1 ; kk >= nim->slice_start ; kk-=2 ){
             toff[kk] = tsl ; tsl += nim->slice_duration ;
           }
         break ;
         case NIFTI_SLICE_ALT_DEC2:
           tsl = 0.0 ;
           for( kk=nim->slice_end-1 ; kk >= nim->slice_start ; kk-=2 ){
             toff[kk] = tsl ; tsl += nim->slice_duration ;
           }
           for( kk=nim->slice_end ; kk >= nim->slice_start ; kk-=2 ){
             toff[kk] = tsl ; tsl += nim->slice_duration ;
           }
         break ;
       }

       EDIT_dset_items( dset ,
                          ADN_nsl     , nim->nz       ,
                          ADN_zorg_sl , orgxyz.xyz[2] ,
                          ADN_dz_sl   , dxyz.xyz[2]   ,
                          ADN_toff_sl , toff          ,
                        ADN_none ) ;

       free(toff) ;

     } /* end of slice timing stuff */

   } /* end of 3D+time dataset stuff */


   /* set atlas space based on NIFTI s/qform code */
   NIFTI_code_to_space(form_code,dset);

   /* add statistics, if present */

   if( statcode != 0 ){
     for( ibr=0 ; ibr < nvals ; ibr++ )
       EDIT_STATAUX4(dset,ibr,statcode,nim->intent_p1,nim->intent_p2,nim->intent_p3,0) ;
   }

   /*-- flag to read data from disk using NIFTI functions --*/

   dset->dblk->diskptr->storage_mode = STORAGE_BY_NIFTI ;
   strcpy( dset->dblk->diskptr->brick_name , pathname ) ;
   dset->dblk->diskptr->byte_order = nim->byteorder ;

#if 0
   for( ibr=0 ; ibr < nvals ; ibr++ ){     /* make sub-brick labels */
     sprintf(prefix,"%s[%d]",tname,ibr) ;
     EDIT_BRICK_LABEL( dset , ibr , prefix ) ;
   }
#endif

   /** 10 May 2005: see if there is an AFNI extension;
                    if so, load attributes from it and
                    then edit the dataset appropriately **/

   { int ee ;  /* extension index */

     /* scan extension list to find the first AFNI extension */

     for( ee=0 ; ee < nim->num_ext ; ee++ )
       if( nim->ext_list[ee].ecode == NIFTI_ECODE_AFNI &&
           nim->ext_list[ee].esize > 32                &&
           nim->ext_list[ee].edata != NULL               ) break ;

     /* if found an AFNI extension ... */

     if( ee < nim->num_ext ){
       char *buf = nim->ext_list[ee].edata , *rhs , *cpt ;
       int  nbuf = nim->ext_list[ee].esize - 8 ;
       NI_stream ns ;
       void     *nini ;
       NI_group *ngr , *nngr ;

       /* if have data, it's long enough, and starts properly, then ... */

       if( buf != NULL && nbuf > 32 && strncmp(buf,"<?xml",5)==0 ){
         if( buf[nbuf-1] != '\0' ) buf[nbuf-1] = '\0' ;         /* for safety */
         cpt = strstr(buf,"?>") ;                    /* find XML prolog close */
         if( cpt != NULL ){                          /* if found it, then ... */
           ns = NI_stream_open( "str:" , "r" ) ;
           NI_stream_setbuf( ns , cpt+2 ) ;        /* start just after prolog */
           nini = NI_read_element(ns,1) ;                 /* get root element */
           NI_stream_close(ns) ;
           if( NI_element_type(nini) == NI_GROUP_TYPE ){   /* must be a group */
             ngr = (NI_group *)nini ;
             if( strcmp(ngr->name,"AFNI_attributes") == 0 ){    /* root is OK */
               nngr = ngr ;
             } else {                   /* search in group for proper element */
               int nn ; void **nnini ;
               nn = NI_search_group_deep( ngr , "AFNI_attributes" , &nnini ) ;
               if( nn <= 0 ) nngr = NULL ;
               else        { nngr = (NI_group *)nnini[0]; NI_free(nnini); }
             }

             if( NI_element_type(nngr) == NI_GROUP_TYPE ){ /* have  good name */
               rhs = NI_get_attribute( nngr , "self_idcode" ) ;
               if( rhs == NULL )
                 rhs = NI_get_attribute( nngr , "AFNI_idcode" ) ;
               if( rhs != NULL )    /* set dataset ID code from XML attribute */
                 MCW_strncpy( dset->idcode.str , rhs , MCW_IDSIZE ) ;
               rhs = NI_get_attribute( nngr , "NIfTI_nums" ) ;    /* check if */
               if( rhs != NULL ){                       /* dataset dimensions */
                 char buf[128] ;                              /* were altered */
                 sprintf(buf,"%ld,%ld,%ld,%ld,%ld,%d" ,        /* 12 May 2005 */
                   nim->nx, nim->ny, nim->nz, nim->nt, nim->nu, nim->datatype );
                 if( strcmp(buf,rhs) != 0 ){
                   static int nnn=0 ;
                   if(nnn==0){fprintf(stderr,"\n"); nnn=1;}
                   fprintf(stderr,
                     "** WARNING: NIfTI file %s dimensions altered since "
                                 "AFNI extension was added\n",pathname ) ;
                 }
               }
               THD_dblkatr_from_niml( nngr , dset->dblk ); /* load attributes */
               THD_datablock_apply_atr( dset ) ;   /* apply to dataset struct */
             }
             NI_free_element( ngr ) ;          /* get rid of the root element */

           } /* end of if found a group element at the root */
         } /* end of if extension data array had an XML prolog close */
       } /* end of if had a good extension data array */
     } /* end of if had an AFNI extension */
   } /* end of processing extensions */

   /* return unpopulated dataset */

   nifti_image_free(nim) ; RETURN(dset) ;
}
Exemple #16
0
int main( int argc , char *argv[] )
{
   THD_3dim_dataset *inset=NULL ;
   byte *mask=NULL ; int mask_nx=0,mask_ny=0,mask_nz=0 , automask=0 , masknum=0 ;
   int iarg=1 , verb=1 , ntype=0 , nev,kk,ii,nxyz,nt ;
   float na,nb,nc , dx,dy,dz ;
   MRI_IMARR *imar=NULL ; int *ivox ; MRI_IMAGE *pim ;
   int do_vmean=0 , do_vnorm=0 , sval_itop=0 ;
   int polort=-1 ; float *ev ;
   MRI_IMARR *ortar ; MRI_IMAGE *ortim ; int nyort=0 ;
   float bpass_L=0.0f , bpass_H=0.0f , dtime ; int do_bpass=0 ;

   if( argc < 2 || strcmp(argv[1],"-help") == 0 ){
     printf(
       "Usage:  3dmaskSVD [options] inputdataset\n"
       "Author: Zhark the Gloriously Singular\n"
       "\n"
       "* Computes the principal singular vector of the time series\n"
       "    vectors extracted from the input dataset over the input mask.\n"
       "  ++ You can use the '-sval' option to change which singular\n"
       "     vectors are output.\n"
       "* The sign of the output vector is chosen so that the average\n"
       "    of arctanh(correlation coefficient) over all input data\n"
       "    vectors (from the mask) is positive.\n"
       "* The output vector is normalized: the sum of its components\n"
       "    squared is 1.\n"
       "* You probably want to use 3dDetrend (or something similar) first,\n"
       "    to get rid of annoying artifacts, such as motion, breathing,\n"
       "    dark matter interactions with the brain, etc.\n"
       "  ++ If you are lazy scum like Zhark, you might be able to get\n"
       "     away with using the '-polort' option.\n"
       "  ++ In particular, if your data time series has a nonzero mean,\n"
       "     then you probably want at least '-polort 0' to remove the\n"
       "     mean, otherwise you'll pretty much just get a constant\n"
       "     time series as the principal singular vector!\n"
       "* An alternative to this program would be 3dmaskdump followed\n"
       "    by 1dsvd, which could give you all the singular vectors you\n"
       "    could ever want, and much more -- enough to confuse you for days.\n"
       "  ++ In particular, although you COULD input a 1D file into\n"
       "     3dmaskSVD, the 1dsvd program would make much more sense.\n"
       "* This program will be pretty slow if there are over about 2000\n"
       "    voxels in the mask.  It could be made more efficient for\n"
       "    such cases, but you'll have to give Zhark some 'incentive'.\n"
       "* Result vector goes to stdout.  Redirect per your pleasures and needs.\n"
       "* Also see program 3dLocalSVD if you want to compute the principal\n"
       "    singular time series vector from a neighborhood of EACH voxel.\n"
       "  ++ (Which is a pretty slow operation!)\n"
       "* http://en.wikipedia.org/wiki/Singular_value_decomposition\n"
       "\n"
       "-------\n"
       "Options:\n"
       "-------\n"
       " -vnorm      = L2 normalize all time series before SVD [recommended!]\n"
       " -sval a     = output singular vectors 0 .. a [default a=0 = first one only]\n"
       " -mask mset  = define the mask [default is entire dataset == slow!]\n"
       " -automask   = you'll have to guess what this option does\n"
       " -polort p   = if you are lazy and didn't run 3dDetrend (like Zhark)\n"
       " -bpass L H  = bandpass [mutually exclusive with -polort]\n"
       " -ort xx.1D  = time series to remove from the data before SVD-ization\n"
       "               ++ You can give more than 1 '-ort' option\n"
       "               ++ 'xx.1D' can contain more than 1 column\n"
       " -input ddd  = alternative way to give the input dataset name\n"
       "\n"
       "-------\n"
       "Example:\n"
       "-------\n"
       " You have a mask dataset with discrete values 1, 2, ... 77 indicating\n"
       " some ROIs; you want to get the SVD from each ROI's time series separately,\n"
       " and then put these into 1 big 77 column .1D file.  You can do this using\n"
       " a csh shell script like the one below:\n"
       "\n"
       " # Compute the individual SVD vectors\n"
       " foreach mm ( `count 1 77` )\n"
       "   3dmaskSVD -vnorm -mask mymask+orig\"<${mm}..${mm}>\" epi+orig > qvec${mm}.1D\n"
       " end\n"
       " # Glue them together into 1 big file, then delete the individual files\n"
       " 1dcat qvec*.1D > allvec.1D\n"
       " /bin/rm -f qvec*.1D\n"
       " # Plot the results to a JPEG file, then compute their correlation matrix\n"
       " 1dplot -one -nopush -jpg allvec.jpg allvec.1D\n"
       " 1ddot -terse allvec.1D > allvec_COR.1D\n"
       "\n"
       " [[ If you use the bash shell,  you'll have to figure out the syntax ]]\n"
       " [[ yourself. Zhark has no sympathy for you bash shell infidels, and ]]\n"
       " [[ considers you only slightly better than those lowly Emacs users. ]]\n"
       " [[ And do NOT ever even mention 'nedit' in Zhark's august presence! ]]\n"
     ) ;
     PRINT_COMPILE_DATE ; exit(0) ;
   }

   /*---- official startup ---*/

   PRINT_VERSION("3dmaskSVD"); mainENTRY("3dmaskSVD main"); machdep();
   AFNI_logger("3dmaskSVD",argc,argv); AUTHOR("Zhark the Singular");

   /*---- loop over options ----*/

   INIT_IMARR(ortar) ;

   mpv_sign_meth = AFNI_yesenv("AFNI_3dmaskSVD_meansign") ;

   while( iarg < argc && argv[iarg][0] == '-' ){

     if( strcasecmp(argv[iarg],"-bpass") == 0 ){
       if( iarg+2 >= argc ) ERROR_exit("need 2 args after -bpass") ;
       bpass_L = (float)strtod(argv[++iarg],NULL) ;
       bpass_H = (float)strtod(argv[++iarg],NULL) ;
       if( bpass_L < 0.0f || bpass_H <= bpass_L )
         ERROR_exit("Illegal values after -bpass: %g %g",bpass_L,bpass_H) ;
       iarg++ ; continue ;
     }

     if( strcmp(argv[iarg],"-ort") == 0 ){  /* 01 Oct 2009 */
       int nx,ny ;
       if( ++iarg >= argc ) ERROR_exit("Need argument after '-ort'") ;
       ortim = mri_read_1D( argv[iarg] ) ;
       if( ortim == NULL ) ERROR_exit("-ort '%s': Can't read 1D file",argv[iarg]) ;
       nx = ortim->nx ; ny = ortim->ny ;
       if( nx == 1 && ny > 1 ){
         MRI_IMAGE *tim=mri_transpose(ortim); mri_free(ortim); ortim = tim; ny = 1;
       }
       mri_add_name(argv[iarg],ortim) ; ADDTO_IMARR(ortar,ortim) ; nyort += ny ;
       iarg++ ; continue ;
     }

     if( strcmp(argv[iarg],"-polort") == 0 ){
       char *qpt ;
       if( ++iarg >= argc ) ERROR_exit("Need argument after '-polort'") ;
       polort = (int)strtod(argv[iarg],&qpt) ;
       if( *qpt != '\0' ) WARNING_message("Illegal non-numeric value after -polort") ;
       iarg++ ; continue ;
     }

     if( strcmp(argv[iarg],"-vnorm") == 0 ){
       do_vnorm = 1 ; iarg++ ; continue ;
     }

     if( strcmp(argv[iarg],"-input") == 0 ){
       if( inset != NULL  ) ERROR_exit("Can't have two -input options") ;
       if( ++iarg >= argc ) ERROR_exit("Need argument after '-input'") ;
       inset = THD_open_dataset( argv[iarg] ) ;
       CHECK_OPEN_ERROR(inset,argv[iarg]) ;
       iarg++ ; continue ;
     }

     if( strcmp(argv[iarg],"-sval") == 0 ){
       if( ++iarg >= argc ) ERROR_exit("Need argument after '-sval'") ;
       sval_itop = (int)strtod(argv[iarg],NULL) ;
       if( sval_itop < 0 ){ sval_itop = 0 ; WARNING_message("'-sval' reset to 0") ; }
       iarg++ ; continue ;
     }

     if( strcmp(argv[iarg],"-mask") == 0 ){
       THD_3dim_dataset *mset ; int mmm ;
       if( ++iarg >= argc ) ERROR_exit("Need argument after '-mask'") ;
       if( mask != NULL || automask ) ERROR_exit("Can't have two mask inputs") ;
       mset = THD_open_dataset( argv[iarg] ) ;
       CHECK_OPEN_ERROR(mset,argv[iarg]) ;
       DSET_load(mset) ; CHECK_LOAD_ERROR(mset) ;
       mask_nx = DSET_NX(mset); mask_ny = DSET_NY(mset); mask_nz = DSET_NZ(mset);
       mask = THD_makemask( mset , 0 , 0.5f, 0.0f ) ; DSET_delete(mset) ;
       if( mask == NULL ) ERROR_exit("Can't make mask from dataset '%s'",argv[iarg]) ;
       masknum = mmm = THD_countmask( mask_nx*mask_ny*mask_nz , mask ) ;
       INFO_message("Number of voxels in mask = %d",mmm) ;
       if( mmm < 2 ) ERROR_exit("Mask is too small to process") ;
       iarg++ ; continue ;
     }

     if( strcmp(argv[iarg],"-automask") == 0 ){
       if( mask != NULL ) ERROR_exit("Can't have two mask inputs!") ;
       automask = 1 ; iarg++ ; continue ;
     }

     ERROR_exit("Unknown option '%s'",argv[iarg]) ;

   } /*--- end of loop over options ---*/

   /*---- deal with input dataset ----*/

   if( inset == NULL ){
     if( iarg >= argc ) ERROR_exit("No input dataset on command line?") ;
     inset = THD_open_dataset( argv[iarg] ) ;
     CHECK_OPEN_ERROR(inset,argv[iarg]) ;
   }
   nt = DSET_NVALS(inset) ;  /* vector lengths */
   if( nt < 9 )
     ERROR_exit("Must have at least 9 values per voxel") ;
   if( polort+1 >= nt )
     ERROR_exit("'-polort %d' too big for time series length = %d",polort,nt) ;

   DSET_load(inset) ; CHECK_LOAD_ERROR(inset) ;
   nxyz = DSET_NVOX(inset) ;

   DSET_UNMSEC(inset) ;
   dtime = DSET_TR(inset) ;
   if( dtime <= 0.0f ) dtime = 1.0f ;
   do_bpass = (bpass_L < bpass_H) ;
   if( do_bpass ){
     kk = THD_bandpass_OK( nt , dtime , bpass_L , bpass_H , 1 ) ;
     if( kk <= 0 ) ERROR_exit("Can't continue since -bpass setup is illegal") ;
     polort = -1 ;
   }

   /*--- deal with the masking ---*/

   if( mask != NULL ){
     if( mask_nx != DSET_NX(inset) ||
         mask_ny != DSET_NY(inset) ||
         mask_nz != DSET_NZ(inset)   )
       ERROR_exit("-mask dataset grid doesn't match input dataset") ;

   } else if( automask ){
     int mmm ;
     mask = THD_automask( inset ) ;
     if( mask == NULL )
       ERROR_message("Can't create -automask from input dataset?") ;
     masknum = mmm = THD_countmask( DSET_NVOX(inset) , mask ) ;
     INFO_message("Number of voxels in automask = %d",mmm) ;
     if( mmm < 9 ) ERROR_exit("Automask is too small to process") ;
   } else {
     mask = (byte *)malloc(sizeof(byte)*nxyz) ; masknum = nxyz ;
     memset( mask , 1 , sizeof(byte)*nxyz ) ;
     INFO_message("Using all %d voxels in dataset",nxyz) ;
   }

   nev = MIN(nt,masknum) ;  /* max possible number of eigenvalues */
   if( sval_itop >= nev ){
     sval_itop = nev-1 ;
     WARNING_message("'-sval' reset to '%d'",sval_itop) ;
   }
   mri_principal_vector_params( 0 , do_vnorm , sval_itop ) ;
   mri_principal_setev(nev) ;

   /*-- get data vectors --*/

   ivox = (int *)malloc(sizeof(int)*masknum) ;
   for( kk=ii=0 ; ii < nxyz ; ii++ ) if( mask[ii] ) ivox[kk++] = ii ;
   INFO_message("Extracting data vectors") ;
   imar = THD_extract_many_series( masknum, ivox, inset ) ; DSET_unload(inset) ;
   if( imar == NULL ) ERROR_exit("Can't get data vector?!") ;

   /*-- detrending --*/

   if( polort >= 0 || nyort > 0 || do_bpass ){
     float **polref=NULL ; float *tsar ;
     int nort=IMARR_COUNT(ortar) , nref=0 ;

     if( polort >= 0 ){  /* polynomials */
       nref = polort+1 ; polref = THD_build_polyref(nref,nt) ;
     }

     if( nort > 0 ){     /* other orts */
       float *oar , *par ; int nx,ny , qq,tt ;
       for( kk=0 ; kk < nort ; kk++ ){  /* loop over input -ort files */
         ortim = IMARR_SUBIM(ortar,kk) ;
         nx = ortim->nx ; ny = ortim->ny ;
         if( nx < nt )
           ERROR_exit("-ort '%s' length %d shorter than dataset length %d" ,
                      ortim->name , nx , nt ) ;
         polref = (float **)realloc(polref,(nref+ny)*sizeof(float *)) ;
         oar    = MRI_FLOAT_PTR(ortim) ;
         for( qq=0 ; qq < ny ; qq++,oar+=nx ){
           par = polref[nref+qq] = (float *)malloc(sizeof(float)*nt) ;
           for( tt=0 ; tt < nt ; tt++ ) par[tt] = oar[tt] ;
                if( polort == 0 ) THD_const_detrend (nt,par,NULL) ;
           else if( polort >  0 ) THD_linear_detrend(nt,par,NULL,NULL) ;
         }
         nref += ny ;
       }
       DESTROY_IMARR(ortar) ;
     }

     if( !do_bpass ){            /* old style ort-ification */

       MRI_IMAGE *imq , *imp ; float *qar ;
       INFO_message("Detrending data vectors") ;
#if 1
       imq = mri_new( nt , nref , MRI_float) ; qar = MRI_FLOAT_PTR(imq) ;
       for( kk=0 ; kk < nref ; kk++ )
         memcpy( qar+kk*nt , polref[kk] , sizeof(float)*nt ) ;
       imp = mri_matrix_psinv( imq , NULL , 1.e-8 ) ;
       for( kk=0 ; kk < IMARR_COUNT(imar) ; kk++ ){
         mri_matrix_detrend( IMARR_SUBIM(imar,kk) , imq , imp ) ;
       }
       mri_free(imp) ; mri_free(imq) ;
#else
       for( kk=0 ; kk < IMARR_COUNT(imar) ; kk++ ){
         tsar = MRI_FLOAT_PTR(IMARR_SUBIM(imar,kk)) ;
         THD_generic_detrend_LSQ( nt , tsar , -1 , nref , polref , NULL ) ;
       }
#endif

     } else {                   /* bandpass plus (maybe) orts */

       float **vec = (float **)malloc(sizeof(float *)*IMARR_COUNT(imar)) ;
       INFO_message("Bandpassing data vectors") ;
       for( kk=0 ; kk < IMARR_COUNT(imar) ; kk++ )
         vec[kk] = MRI_FLOAT_PTR(IMARR_SUBIM(imar,kk)) ;
       (void)THD_bandpass_vectors( nt    , IMARR_COUNT(imar) , vec     ,
                                   dtime , bpass_L           , bpass_H ,
                                   2     , nref              , polref   ) ;
       free(vec) ;
     }

     for( kk=0 ; kk < nref; kk++ ) free(polref[kk]) ;
     free(polref) ;
   } /* end of detrendization */

   /*--- the actual work ---*/

   INFO_message("Computing SVD") ;
   pim  = mri_principal_vector( imar ) ; DESTROY_IMARR(imar) ;
   if( pim == NULL ) ERROR_exit("SVD failure!?!") ;
   ev = mri_principal_getev() ;
   switch(sval_itop+1){
     case 1:
       INFO_message("First singular value: %g",ev[0]) ; break ;
     case 2:
       INFO_message("First 2 singular values: %g %g",ev[0],ev[1]) ; break ;
     case 3:
       INFO_message("First 3 singular values: %g %g %g",ev[0],ev[1],ev[2]) ; break ;
     case 4:
       INFO_message("First 4 singular values: %g %g %g %g",ev[0],ev[1],ev[2],ev[3]) ; break ;
     default:
     case 5:
       INFO_message("First 5 singular values: %g %g %g %g %g",ev[0],ev[1],ev[2],ev[3],ev[4]) ; break ;
   }
   mri_write_1D(NULL,pim) ;

   exit(0) ;
}
Boolean THD_write_datablock( THD_datablock *blk , Boolean write_brick )
{
   THD_diskptr *dkptr ;
   Boolean good ;
   int id , nx , ny , nz , nv , nxy , nxyz , ibr ;
   int atrank[ATRSIZE_DATASET_RANK] , atdims[ATRSIZE_DATASET_DIMENSIONS] ;
   MRI_IMAGE *im ;
   int save_order ;
   int64_t nb , idone ;
   int do_mripurge ;

   /*-- sanity checks --*/

   if( ! ISVALID_DATABLOCK(blk) ) return False ;
   if( DBLK_IS_MASTERED(blk) )    return False ;  /* 11 Jan 1999 */
   if( DBLK_IS_MINC(blk) ) WRITE_ERR("MINC with bad name extension?") ;
                                                               /* 29 Oct 2001 */
   if( DBLK_IS_ANALYZE(blk) ) WRITE_ERR("ANALYZE but bad name extension?") ; 
                                                               /* 27 Aug 2002 */
   if( DBLK_IS_NIFTI(blk) ) WRITE_ERR("NIFTI but bad name extension?") ;  
                                                               /* 28 Aug 2003 */

   dkptr = blk->diskptr ;
   if( ! ISVALID_DISKPTR(dkptr) ) WRITE_ERR("illegal file type") ;

   if( strlen(dkptr->directory_name) == 0 ||
       strlen(dkptr->header_name)    == 0 ||
       strlen(dkptr->filecode)       == 0   )
     WRITE_ERR("illegal file names stored in dataset") ;

   if( dkptr->rank != 3 )
     WRITE_ERR("cannot write non-3D datablock") ;

   /*-- create directory if necessary --*/

   if( ! THD_is_directory(dkptr->directory_name) ){
     id = mkdir( dkptr->directory_name , THD_MKDIR_MODE ) ;
     if( id != 0 ){
       fprintf(stderr,
            "\n"
            "*** cannot mkdir new directory: %s\n"
            "  - Do you have permission to write to this disk?\n"
            "  - Is the disk full?\n" ,
            dkptr->directory_name) ;
       return False ;
     }
   }

   /* 25 April 1998: deal with byte order issues */

   if( native_order < 0 ){                /* initialization */
     native_order = mri_short_order() ;
     if( output_order < 0 ) THD_enviro_write_order() ;
   }
   if( dkptr->byte_order <= 0 ) dkptr->byte_order = native_order ;
   save_order = (output_order > 0) ? output_order
                                   : dkptr->byte_order ;

#if 0
fprintf(stderr,"THD_write_datablock: save_order=%d  dkptr->byte_order=%d\n",
               save_order, dkptr->byte_order ) ;
#endif

   if( save_order != LSB_FIRST && save_order != MSB_FIRST )
     save_order = native_order ;

   if( save_order == LSB_FIRST )
     THD_set_string_atr( blk , ATRNAME_BYTEORDER , LSB_FIRST_STRING ) ;
   else if( save_order == MSB_FIRST )
     THD_set_string_atr( blk , ATRNAME_BYTEORDER , MSB_FIRST_STRING ) ;

   /*-- actually write attributes to disk --*/

   good = THD_write_atr( blk ) ;
   if( good == False )
     WRITE_ERR(
     "failure to write attributes - is disk full? do you have write permission?");

   /*-- if not writing data, can exit --*/

   if( write_brick == False || blk->brick == NULL ||
       dkptr->storage_mode == STORAGE_UNDEFINED     ) return True ;

   if( dkptr->storage_mode == STORAGE_BY_VOLUMES ){  /* 20 Jun 2002 */
     fprintf(stderr,"** Writing dataset by VOLUMES not yet supported.\n") ;
     return False ;
   }

   /*-- check each brick for existence:
          if none exist, cannot write, but is OK
          if some but not all exist, cannot write, and is an error --*/

   id = THD_count_potential_databricks( blk ) ;
   if( id <= 0 )         return True ;
   if( id < blk->nvals ){
     ERROR_message("Write dataset error: only %d out of %d bricks in memory",
                   id,blk->nvals) ; return False ;
   }

   if( blk->malloc_type == DATABLOCK_MEM_UNDEFINED )
     WRITE_ERR("undefined data exists in memory") ;

   /*-- 13 Mar 2006: check for free disk space --*/

   { int mm = THD_freemegabytes( dkptr->header_name ) ;
     int rr = blk->total_bytes / (1024l * 1024l) ;
     if( mm >= 0 && mm <= rr )
       WARNING_message("Disk space: writing file %s (%d MB),"
                       " but only %d free MB on disk"        ,
         dkptr->brick_name , rr , mm ) ;
   }

   /*-- write data out in whatever format is ordered --*/

   nx = dkptr->dimsizes[0] ;
   ny = dkptr->dimsizes[1] ;  nxy  = nx * ny ;
   nz = dkptr->dimsizes[2] ;  nxyz = nxy * nz ;
   nv = dkptr->nvals ;        nb   = blk->total_bytes ;

   switch( dkptr->storage_mode ){

      default: WRITE_ERR("illegal storage_mode!") ; break ;

      case STORAGE_BY_BRICK:{
         FILE *far ;
         Boolean purge_when_done = False , ok ;
         int force_gzip=0 , csave=COMPRESS_NONE ;

         /** if we have a mmap-ed file, copy into RAM (ugh) **/

         if( blk->malloc_type == DATABLOCK_MEM_MMAP ){
            char *bnew , *bold ;
            int offset ;

            bnew = (char *) malloc( (size_t)nb ) ;  /* work space */
            bold = DBLK_ARRAY(blk,0) ;              /* start of mapped file */

            if( bnew == NULL )
              WRITE_ERR("cannot rewrite due to malloc failure - is memory exhausted?") ;

            memcpy( bnew , bold , (size_t)nb ) ;    /* make a copy,    */
            munmap( (void *) bold , (size_t)nb ) ;  /* then unmap file */

            /* fix sub-brick pointers */

            offset = 0 ;
            for( ibr=0 ; ibr < nv ; ibr++ ){
               mri_fix_data_pointer( (void *)(bnew+offset) , DBLK_BRICK(blk,ibr) ) ;
               offset += DBLK_BRICK_BYTES(blk,ibr) ;
               DBLK_BRICK(blk,ibr)->fondisk = 0 ;   /* 31 Jan 2007 */
            }

            purge_when_done = True ;

         } /** fall thru to here if have a malloc-ed dataset **/

         if( save_order != native_order ) purge_when_done = True ;

         /** delete old file, if any **/

         COMPRESS_unlink( dkptr->brick_name ) ; /* Feb 1998 */

         /** create new file **/

         id = strlen(dkptr->directory_name) ;
         ok = ( dkptr->directory_name[id-1] == '/' ) ;
         if( ok ) sprintf( dkptr->brick_name , "%s%s.%s",
                           dkptr->directory_name ,
                           dkptr->filecode , DATASET_BRICK_SUFFIX );

         else     sprintf( dkptr->brick_name , "%s/%s.%s",
                           dkptr->directory_name ,
                           dkptr->filecode , DATASET_BRICK_SUFFIX );

      /** COMPRESS for output added Feb 1998 */

         if( compress_mode == COMPRESS_NOFILE ) THD_enviro_write_compression() ;

#ifdef COMPRESS_GZIP
         /*-- 02 Mar 2001: check if we will force gzip --*/

         if( compress_mode == COMPRESS_NONE && AFNI_yesenv("AFNI_AUTOGZIP") ){
            double entrop = ENTROPY_datablock(blk) ;
            force_gzip = (entrop < 2.7) ;
#if 0
fprintf(stderr,"Entropy=%g ==> forcing write gzip on %s\n",entrop,dkptr->brick_name) ;
#endif
         } else {
            force_gzip = 0 ;
         }
         if( force_gzip ){
            csave = compress_mode ; compress_mode = COMPRESS_GZIP ;
         }
#endif

         far = COMPRESS_fopen_write( dkptr->brick_name , compress_mode ) ;
         if( far == NULL ){
           if( compress_mode != COMPRESS_NONE ){
             compress_mode = COMPRESS_NONE ; force_gzip = 0 ;
             far = COMPRESS_fopen_write( dkptr->brick_name , compress_mode ) ;
           }
         }
         if( far == NULL )
           WRITE_ERR("cannot open output brick file - do you have write permission?") ;

         /** write each brick out in a separate operation **/

         idone = 0 ;
         for( ibr=0 ; ibr < nv ; ibr++ ){

           do_mripurge = MRI_IS_PURGED( DBLK_BRICK(blk,ibr) ) ;
           if( do_mripurge ) mri_unpurge( DBLK_BRICK(blk,ibr) ) ;

           if( save_order != native_order ){       /* 25 April 1998 */
             switch( DBLK_BRICK_TYPE(blk,ibr) ){
               default: break ;
               case MRI_short:
                 mri_swap2( DBLK_BRICK_NVOX(blk,ibr) , DBLK_ARRAY(blk,ibr) ) ;
               break ;

               case MRI_complex:   /* 23 Nov 1999 */
                 mri_swap4( 2*DBLK_BRICK_NVOX(blk,ibr), DBLK_ARRAY(blk,ibr)) ;
               break ;

               case MRI_float:     /* 23 Nov 1999 */
               case MRI_int:
                 mri_swap4( DBLK_BRICK_NVOX(blk,ibr) , DBLK_ARRAY(blk,ibr) ) ;
               break ;
             }
           }

           idone += fwrite( DBLK_ARRAY(blk,ibr), 1, DBLK_BRICK_BYTES(blk,ibr), far );

           if( do_mripurge ){                    /* 31 Jan 2007 */
             if( !purge_when_done ) mri_purge( DBLK_BRICK(blk,ibr) ) ;
             else                   mri_clear( DBLK_BRICK(blk,ibr) ) ;
           }
         } /* end of loop over sub-bricks */

         COMPRESS_fclose(far) ;

         if( purge_when_done ){
           if( blk->malloc_type == DATABLOCK_MEM_MMAP ){
             free( DBLK_ARRAY(blk,0) ) ;
             for( ibr=0 ; ibr < nv ; ibr++ )
               mri_clear_data_pointer( DBLK_BRICK(blk,ibr) ) ;
           } else {
             THD_purge_datablock( blk , DATABLOCK_MEM_MALLOC ) ;
           }
         }

         if( compress_mode >= 0 || save_order != native_order ){
           blk->malloc_type = DATABLOCK_MEM_MALLOC ;
         }
         DBLK_mmapfix(blk) ;  /* 28 Mar 2005 */

         if( force_gzip ) compress_mode = csave ; /* 02 Mar 2001 */

         if( idone != blk->total_bytes )
           WRITE_ERR("Write error in brick file: Is disk full, or write_protected?") ;

         dkptr->byte_order = save_order ;  /* 23 Nov 1999 */

         return True ;
      }
      break ;

   }  /* end of switch over data storage mode */

   return False ;  /* should NEVER be reached */
}
Exemple #18
0
int main (int argc,char *argv[])
{/* Main */
   static char FuncName[]={"FSread_annot"};
   int kar, Showct, testmode;
   char *fname = NULL, *fcmap = NULL, *fdset = NULL, 
         *froi = NULL, *fcol = NULL, *ctfile=NULL, sbuf[1024]={""};
   SUMA_Boolean SkipCoords = NOPE, brk;
   SUMA_DSET *dset=NULL;
   int lbl1,lbl2, ver, hemi, FSdefault;
   SUMA_Boolean LocalHead = NOPE;	
   
   SUMA_STANDALONE_INIT;
	SUMA_mainENTRY;
   
	/* allocate space for CommonFields structure */
	SUMAg_CF = SUMA_Create_CommonFields ();
	if (SUMAg_CF == NULL) {
		fprintf( SUMA_STDERR,
               "Error %s: Failed in SUMA_Create_CommonFields\n", FuncName);
		exit(1);
	}

   /* parse command line */
   kar = 1;
   fname = NULL;
   froi = NULL;
   fcmap = NULL;
   fcol = NULL;
	brk = NOPE;
   ctfile = NULL;
   Showct = 0;
   testmode = 0;
   lbl1 = -1;
   lbl2 = -1;
   ver = -1;
   FSdefault = 0;
   hemi=0;
	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_FSread_annot_Main();
          exit (0);
		}
      
      if (!brk && (strcmp(argv[kar], "-show_FScmap") == 0)) {
         Showct = 1;
			brk = YUP;
		}
      
      if (!brk && (strcmp(argv[kar], "-testmode") == 0)) {
         testmode = 1;
			brk = YUP;
		}
      
      if (!brk && (strcmp(argv[kar], "-input") == 0)) {
         kar ++;
			if (kar >= argc)  {
		  		fprintf (SUMA_STDERR, "need argument after -input\n");
				exit (1);
			}
         fname = argv[kar];
			brk = YUP;
		}

      if (!brk && (strcmp(argv[kar], "-FScmap") == 0)) {
         kar ++;
			if (kar >= argc)  {
		  		fprintf (SUMA_STDERR, "need argument after -FScmap\n");
				exit (1);
			}
         ctfile = argv[kar];
         if (!strcmp(ctfile,"FS_DEFAULT")) {
            char *eee = getenv("FREESURFER_HOME");
            if (!eee) {
               SUMA_S_Err("Environment variable FREESURFER_HOME not set.\n"
                          "Cannot locate FreeSurferColorLUT.txt\n");
               exit (1);
            } else {
               sprintf(sbuf, "%s/FreeSurferColorLUT.txt", eee);
               ctfile = sbuf;
               FSdefault = 1;
               SUMA_S_Notev("Using %s\n", ctfile);
            }              
         }
			brk = YUP;
		}
      
      if (!brk && (strcmp(argv[kar], "-FSversion") == 0)) {
         kar ++;
			if (kar >= argc)  {
		  		fprintf (SUMA_STDERR, "need argument after -FSversion\n");
				exit (1);
			}
         if (strstr(argv[kar],"2009")) ver = 2009;
         else if (strstr(argv[kar],"2005")) ver = 2005;
         else {
            fprintf (SUMA_STDERR, 
                  "Bad value for -FSversion of %s (looking for 2005 or 2009)\n",
                  argv[kar]);
				exit (1);
         }
			brk = YUP;
		}

      if (!brk && (strcmp(argv[kar], "-hemi") == 0)) {
         kar ++;
			if (kar >= argc)  {
		  		fprintf (SUMA_STDERR, "need argument after -hemi\n");
				exit (1);
			}
         if (strstr(argv[kar],"lh")) hemi = -1;
         else if (strstr(argv[kar],"rh")) hemi = 1;
         else {
            fprintf (SUMA_STDERR, 
                  "Bad value for -hemi of %s (looking for lh or rh)\n",
                  argv[kar]);
				exit (1);
         }
			brk = YUP;
		}
      
      if (!brk && (strcmp(argv[kar], "-FScmaprange") == 0)) {
         kar ++;
			if (kar+1 >= argc)  {
		  		fprintf (SUMA_STDERR, "need 2 argument after -FScmaprange\n");
				exit (1);
			}
         lbl1 = atoi(argv[kar]); ++kar;
         lbl2 = atoi(argv[kar]); 
         
         if (lbl1 > lbl2 || lbl1 < -1) {
            fprintf (SUMA_STDERR, 
                  "Bad value for -FScmaprange of [%d %d]\n",
                  lbl1, lbl2);
				exit (1);
         }
			brk = YUP;
		}
      
      if (!brk && (strcmp(argv[kar], "-roi_1D") == 0)) {
         kar ++;
			if (kar >= argc)  {
		  		fprintf (SUMA_STDERR, "need argument after -ROI_1D\n");
				exit (1);
			}
         froi = argv[kar];
			brk = YUP;
		}
      
      if (!brk && ( (strcmp(argv[kar], "-prefix") == 0) ||
                    (strcmp(argv[kar], "-dset") == 0) ) ) {
         kar ++;
			if (kar >= argc)  {
		  		fprintf (SUMA_STDERR, "need argument after -dset\n");
				exit (1);
			}
         fdset = argv[kar];
			brk = YUP;
		}
      
      if (!brk && (strcmp(argv[kar], "-cmap_1D") == 0)) {
         kar ++;
			if (kar >= argc)  {
		  		fprintf (SUMA_STDERR, "need argument after -cmap_1D\n");
				exit (1);
			}
         fcmap = argv[kar];
			brk = YUP;
		}
      
      if (!brk && (strcmp(argv[kar], "-col_1D") == 0)) {
         kar ++;
			if (kar >= argc)  {
		  		fprintf (SUMA_STDERR, "need argument after -col_1D\n");
				exit (1);
			}
         fcol = argv[kar];
			brk = YUP;
		}
      
      if (!brk) {
			fprintf (SUMA_STDERR,
                  "Error %s:\n"
                  "Option %s not understood. Try -help for usage\n", 
                  FuncName, argv[kar]);
			exit (1);
		} else {	
			brk = NOPE;
			kar ++;
		}
   }
   
   if (!fname) {
      SUMA_SL_Err("No input file specified.");
      exit(1);
   }
   
   if (ver == -1) {
      /* guess at version */
      if (strstr(fname,"2009")) {
         ver = 2009;
         SUMA_S_Notev("Guessed FS annot version of %d\n", ver);
      } else if (strstr(fname,"2005")) {
         ver = 2005;
         SUMA_S_Notev("Guessed FS annot version of %d\n", ver);
      } else {
         SUMA_S_Notev("Assuming FS annot version of %d\n", ver);
      }
   }
   
   if (hemi == 0) {
      if (strstr(fname,"lh.")) {
         hemi = -1;
         SUMA_S_Note("Guessed left hemisphere");
      } else if (strstr(fname,"rh.")) {
         SUMA_S_Note("Guessed right hemisphere");
         hemi = 1;
      } else {
         if (ver == 2009) {
            hemi = -1;
            SUMA_S_Note("Assuming left hemisphere.\n");
         } else {
            /* leave it not set */
         }
      }
   }
   
   if (ver == 2009 && !ctfile) {
      char *eee = getenv("FREESURFER_HOME");
      if (!eee) {
         SUMA_S_Warn("Environment variable FREESURFER_HOME not set.\n"
                    "Cannot locate FreeSurferColorLUT.txt\n");
      } else {
         sprintf(sbuf, "%s/FreeSurferColorLUT.txt", eee);
         ctfile = sbuf;
         SUMA_S_Notev("Using %s\n", ctfile);
      }  
   }
   
   if (lbl1 < 0 && lbl2 < 0) {
      /* need some setup */
      if (ver == 2009) {
         if (hemi == -1) {
            lbl1 = 13100;
            lbl2 = 13199;
            SUMA_S_Notev("Setting -FScmaprange to [%d %d]\n",
                        lbl1, lbl2);
         } else if (hemi == 1) {
            lbl1 = 14100;
            lbl2 = 14199;
            SUMA_S_Notev("Setting -FScmaprange to [%d %d]\n",
                        lbl1, lbl2);
         } else {
            SUMA_S_Warn("-FScmaprange is not set.\n"
                         "You may need to set it, check results.\n");
         }
      } else if (ver == 2005 && FSdefault) {
         if (hemi == -1) {
            lbl1 = 3100;
            lbl2 = 3199;
            SUMA_S_Notev("Setting -FScmaprange to [%d %d]\n",
                        lbl1, lbl2);
         } else if (hemi == 1) {
            lbl1 = 4100;
            lbl2 = 4199;
            SUMA_S_Notev("Setting -FScmaprange to [%d %d]\n",
                        lbl1, lbl2);
         } else {
            SUMA_S_Warn("-FScmaprange is not set.\n"
                         "You may need to set it, check results.\n");
         }
      }
   }
   
   if (!fcmap && !froi && !fcol && !Showct && !fdset) {
      SUMA_SL_Err("Nothing to do.\n"
                  "Use either -cmap_1D or \n"
                  " -roi_1D or -col_1D or \n"
                  " -show_FScmap options.");
      exit(1);
   }

   if (fdset) {
      int exists = 0;
      char *ooo=NULL;
      exists = SUMA_WriteDset_NameCheck_s (fdset, NULL, 
                                           SUMA_ASCII_NIML, 0, &ooo);
      if (exists != 0 && !THD_ok_overwrite()) {
         SUMA_S_Errv("Output dataset %s exists.\n", ooo);
         SUMA_free(ooo); ooo=NULL;
         exit(1);
      }
   }

   if (froi) {
      if (SUMA_filexists(froi) && !THD_ok_overwrite()) { 
         fprintf( SUMA_STDERR,
                  "Error %s: File %s exists, will not overwrite.\n", 
                  FuncName, froi);
	      SUMA_RETURN (NOPE);
      }
   }
     
   if (fcmap) {
      if (SUMA_filexists(fcmap) && !THD_ok_overwrite()) { 
         fprintf( SUMA_STDERR,
                  "Error %s: File %s exists, will not overwrite.\n", 
                  FuncName, fcmap);
	      SUMA_RETURN (NOPE);
      }
   }
     
   if (fcol) {
      if (SUMA_filexists(fcol) && !THD_ok_overwrite()) { 
         fprintf( SUMA_STDERR,
                  "Error %s: File %s exists, will not overwrite.\n", 
                  FuncName, fcol);
	      SUMA_RETURN (NOPE);
      }
   }
     
   if (!SUMA_readFSannot (fname, froi, fcmap, fcol, Showct, ctfile, 
                          lbl1, lbl2, &dset)) {
      SUMA_S_Err("Failed reading annotation file (or output file exists)");
      exit(1);
   }
   
   if (!dset && fdset) {
      SUMA_S_Err("Have no dset to write");
      exit(1);
   }
   
   if (fdset) {
      if (AFNI_yesenv("AFNI_NIML_TEXT_DATA")) {
         SUMA_WriteDset_eng(fdset, dset, SUMA_ASCII_NIML, 1, 1, 1);
      } else {
         SUMA_WriteDset_eng(fdset, dset, SUMA_BINARY_NIML, 1, 1, 1);      
      }
   }
   
   if (testmode) {
      int key, indx, ism, suc;
      SUMA_COLOR_MAP *SM2=NULL, *SM=NULL;
      char *s=NULL, stmp[256];
      SUMA_PARSED_NAME *sname=NULL;
      NI_group *ngr=NULL;
      
      SUMA_S_Note("Testing Chunk Begins");
      
      /* check */
      if (!SUMA_is_Label_dset(dset, &ngr)) {
         SUMA_S_Err("Dset is no label dset");
         exit(1);
      }
      /* write it */
      
      /* play with the colormap */
      if (ngr) {
         if (!(SM = SUMA_NICmapToCmap(ngr))){
            SUMA_S_Err("Failed to create SUMA colormap");
            exit(1);
         }
         ngr = NULL; /* that's a copy of what was in dset, do not free it */
         if (!SUMA_CreateCmapHash(SM)) {
            SUMA_S_Err("Failed to create hash");
            exit(1);
         }
         /* Now pretend you are retrieving the index in cmap of some key */
         for (ism=0; ism < SM->N_M[0]; ++ism) {
            /* the key is coming from SM, because I store all keys there
              But key normally comes from a certain node's value */
            key = SM->idvec[ism];
            indx = SUMA_ColMapKeyIndex(key, SM);
            if (indx < 0) {
               SUMA_S_Errv("Hashkey %d not found\n", key);
            } else {
               fprintf(SUMA_STDERR,
                        "hashed id %d --> index %d\n"
                        "known  id %d --> index %d\n",
                        key, indx,
                        key, ism);
            }
         }

         /* Now try it with an unknown key */
         key = -13;
         indx = SUMA_ColMapKeyIndex(key, SM);
         if (indx < 0) {
            fprintf(SUMA_STDERR,
                     "id %d is not in the hash table, as expected\n", key);
         } else {
            SUMA_S_Errv("Should not have found %d\n", key);
         }      

         SUMA_S_Note("Now Show it to me");
         s = SUMA_ColorMapVec_Info (&SM, 1, 2);
         if (s) {
            fprintf(SUMA_STDERR,"%s", s); SUMA_free(s); s = NULL;
         }

         SUMA_S_Notev("Now turn it to niml (%s)\n", SM->Name);
         ngr = SUMA_CmapToNICmap(SM);
         sname = SUMA_ParseFname(SM->Name, NULL);
         snprintf(stmp, 128*sizeof(char), 
                  "file:%s.niml.cmap", sname->FileName_NoExt); 
         NEL_WRITE_TX(ngr, stmp, suc);
         if (!suc) {
            SUMA_S_Errv("Failed to write %s\n", stmp);
         }
         SUMA_Free_Parsed_Name(sname); sname = NULL;

         SUMA_S_Note("Now turn niml colormap to SUMA's colormap");
         SM2 = SUMA_NICmapToCmap(ngr);
         SUMA_S_Note("Now Show it to me2");
         s = SUMA_ColorMapVec_Info (&SM2, 1, 2);
         if (s) {
            fprintf(SUMA_STDERR,"%s", s); SUMA_free(s); s = NULL;
         }

         NI_free_element(ngr); ngr=NULL;
         SUMA_Free_ColorMap(SM); SM = NULL;
         SUMA_Free_ColorMap(SM2); SM2 = NULL;
      }
      
      SUMA_S_Note("Testing Chunk End");
   }

   if (dset) SUMA_FreeDset(dset); dset = NULL;
   
   exit(0);
}
int main( int argc , char *argv[] )
{
   MRI_IMAGE *imin, *imout , *imout_orig;
   THD_3dim_dataset *iset, *oset , *ooset;
   char *prefix = "SpatNorm", *bottom_cuts = NULL;
   int iarg , verb=0, OrigSpace = 0 , specie = HUMAN;
   float SpatNormDxyz= 0.0, iset_scaled=1.0;
   THD_ivec3 orixyz , nxyz ;
   THD_fvec3 dxyz , orgxyz, originRAIfv, fv2;


   mainENTRY("3dSpatNorm main") ; machdep() ; 
   if (argc == 1) { usage_3dSpatNorm(1); exit(0); }

   /*--- options ---*/

   iarg = 1 ;
   OrigSpace = 0;
   while( iarg < argc && argv[iarg][0] == '-' ){
      if (strcmp(argv[iarg],"-h") == 0 || strcmp(argv[iarg],"-help") == 0 ) { 
         usage_3dSpatNorm(strlen(argv[iarg]) > 3 ? 2:1);
         exit(0); 
      }
      
     /* -prefix */

     if( strcmp(argv[iarg],"-prefix") == 0 ){
       if( ++iarg >= argc ){
         fprintf(stderr,"**ERROR: -prefix requires another argument!\n") ;
         exit(1) ;
       }
       prefix = strdup(argv[iarg]) ;
       if( !THD_filename_ok(prefix) ){
         fprintf(stderr,"**ERROR: -prefix value contains forbidden characters!\n") ;
         exit(1) ;
       }
       iarg++ ; continue ;
     }

     if( strcmp(argv[iarg],"-dxyz") == 0 ){
       if( ++iarg >= argc ){
         fprintf(stderr,"**ERROR: -dxyz requires another argument!\n") ;
         exit(1) ;
       }
       SpatNormDxyz = atof(argv[iarg]) ;
       
       iarg++ ; continue ;
     }
     if( strcmp(argv[iarg],"-bottom_cuts") == 0 ){
       if( ++iarg >= argc ){
         fprintf(stderr,"**ERROR: -bottom_cuts requires another argument!\n") ;
         exit(1) ;
       }
       bottom_cuts = argv[iarg] ;
       
       iarg++ ; continue ;
     }
     if( strncmp(argv[iarg],"-verb",5) == 0 ){
       verb++ ; iarg++ ; continue ;
     }
     if( strncmp(argv[iarg],"-human",5) == 0 ){
       specie = HUMAN ; iarg++ ; continue ;
     }
     if( strncmp(argv[iarg],"-monkey",5) == 0 ){
       specie = MONKEY ; iarg++ ; continue ;
     }
     if( strncmp(argv[iarg],"-marmoset",5) == 0 ){
       specie = MARMOSET ; iarg++ ; continue ;
     }
     if( strncmp(argv[iarg],"-rat",5) == 0 ){
       specie = RAT ; iarg++ ; continue ;
     }
     if( strncmp(argv[iarg],"-orig_space",10) == 0 ){
       OrigSpace = 1 ; iarg++ ; continue ;
     }
     
     fprintf(stderr,"**ERROR: %s is unknown option!\n",argv[iarg]) ;
     suggest_best_prog_option(argv[0], argv[iarg]);
     exit(1) ;
   }

   if( iarg >= argc ){
     fprintf(stderr,"**ERROR: no input dataset name on command line?!\n") ;
     exit(1) ;
   }

   /*--- read dataset ---*/

   iset = THD_open_dataset( argv[iarg] ) ;
   if( !ISVALID_DSET(iset) ){
     fprintf(stderr,"**ERROR: can't open dataset %s\n",argv[iarg]) ;
     exit(1) ;
   }

   /*--- get median brick --*/

   if( verb ) fprintf(stderr,"++3dSpatNorm: loading dataset\n") ;

   if (specie == MARMOSET) {
      iset_scaled = 2.5;
      THD_volDXYZscale(iset->daxes, iset_scaled, 0);
      specie = MONKEY;
   }
   imin = THD_median_brick( iset ) ;
   if( imin == NULL ){
     fprintf(stderr,"**ERROR: can't load dataset %s\n",argv[iarg]) ;
     exit(1) ;
   }
   imin->dx = fabs(iset->daxes->xxdel) ;
   imin->dy = fabs(iset->daxes->yydel) ;
   imin->dz = fabs(iset->daxes->zzdel) ;
   
   
   mri_speciebusiness(specie);
   mri_brain_normalize_cuts(bottom_cuts);
   
   if (SpatNormDxyz) {
      if (verb) fprintf(stderr,"Overriding default resampling\n");
      mri_brainormalize_initialize(SpatNormDxyz, SpatNormDxyz, SpatNormDxyz);
   } else {
      float xxdel, yydel, zzdel, minres;
      if (specie == MONKEY) minres = 0.5;
      else if (specie == MARMOSET) minres = 0.2;
      else if (specie == RAT) minres = 0.1;
      else minres = 0.5;
      /* don't allow for too low a resolution, please */
      if (imin->dx < minres) xxdel = minres;
      else xxdel = imin->dx;
      if (imin->dy < minres) yydel = minres;
      else yydel = imin->dy;
      if (imin->dz < minres) zzdel = minres;
      else zzdel = imin->dz;
      if (verb) {
         fprintf(stderr,
                  "%s:\n"
                  " Original resolution %f, %f, %f\n"
                  " SpatNorm resolution %f, %f, %f\n",
                  "3dSpatnorm", imin->dx, imin->dy, imin->dz, 
                     xxdel, yydel, zzdel);
      }   
      mri_brainormalize_initialize(xxdel, yydel, zzdel);
   }
   
      /* To get around the #define for voxel counts and dimensions */
   mri_brainormalize_initialize(imin->dz, imin->dy, imin->dz); 
   
   /* me needs the origin of this dset in RAI world */
   LOAD_FVEC3( originRAIfv , 
               iset->daxes->xxorg , iset->daxes->yyorg , iset->daxes->zzorg) ;
   originRAIfv = THD_3dmm_to_dicomm( iset , originRAIfv ) ;

   LOAD_FVEC3(fv2, iset->daxes->xxorg + (iset->daxes->nxx-1)*iset->daxes->xxdel ,
                   iset->daxes->yyorg + (iset->daxes->nyy-1)*iset->daxes->yydel ,
                   iset->daxes->zzorg + (iset->daxes->nzz-1)*iset->daxes->zzdel);
   fv2 = THD_3dmm_to_dicomm( iset , fv2 ) ;

   if( originRAIfv.xyz[0] > fv2.xyz[0] ) { 
      float tf; tf = originRAIfv.xyz[0]; 
                originRAIfv.xyz[0] = fv2.xyz[0];  fv2.xyz[0] = tf; } 
   if( originRAIfv.xyz[1] > fv2.xyz[1] ) { 
      float tf; tf = originRAIfv.xyz[1]; 
                originRAIfv.xyz[1] = fv2.xyz[1]; fv2.xyz[1] = tf; }
   if( originRAIfv.xyz[2] > fv2.xyz[2] ) { 
      float tf; tf = originRAIfv.xyz[2]; 
                originRAIfv.xyz[2] = fv2.xyz[2]; fv2.xyz[2] = tf; }
   
   if (verb) {
      fprintf(stderr,"++3dSpatNorm (ZSS): RAI origin info: %f %f %f\n", 
                     originRAIfv.xyz[0], originRAIfv.xyz[1], originRAIfv.xyz[2]);
   }
   
   
   DSET_unload( iset ) ;  /* don't need this data no more */

   /*-- convert image to shorts, if appropriate --*/

   if( DSET_BRICK_TYPE(iset,0) == MRI_short ||
       DSET_BRICK_TYPE(iset,0) == MRI_byte    ){

     imout = mri_to_short(0.0,imin) ; /* ZSS Oct 2012: Let function set scaling*/
     mri_free(imin) ; imin = imout ;
   }

   /*--- normalize image spatially ---*/

   mri_brainormalize_verbose( verb ) ;
   if (OrigSpace) {
      imout = mri_brainormalize( imin , iset->daxes->xxorient,
                                     iset->daxes->yyorient,
                                     iset->daxes->zzorient , &imout_orig, NULL) ;
   } else {
      imout = mri_brainormalize( imin , iset->daxes->xxorient,
                                     iset->daxes->yyorient,
                                     iset->daxes->zzorient , NULL, NULL) ;
   }
   mri_free( imin ) ;

   if( imout == NULL ){
     fprintf(stderr,"**ERROR: normalization fails!?\n"); exit(1);
   }
   
   if (OrigSpace) {
      if( verb ) fprintf(stderr,"++3dSpatNorm: Output in Orignal space\n") ;
      mri_free( imout ) ;
      imout = imout_orig; 
      imout->xo = originRAIfv.xyz[0]; 
      imout->yo = originRAIfv.xyz[1]; 
      imout->zo = originRAIfv.xyz[2]; 
      imout_orig = NULL;
   } else {
      if( verb ) fprintf(stderr,"++3dSpatNorm: Output in SpatNorm space\n") ;
   }
   
#if 0
   if( AFNI_yesenv("WATERSHED") ){
     imin = mri_watershedize( imout , 0.10 ) ;
     if( imin != NULL ){ mri_free(imout); imout = imin; }
   }
#endif

   /*--- create output dataset ---*/
   if( verb )
     fprintf(stderr,"++3dSpatNorm: Creating output dset\n") ;

   oset = EDIT_empty_copy( NULL ) ;

   tross_Copy_History( iset , oset ) ;
   tross_Make_History( "3dSpatNorm" , argc,argv , oset ) ;

   LOAD_IVEC3( nxyz   , imout->nx    , imout->ny    , imout->nz    ) ;
   LOAD_FVEC3( dxyz   , imout->dx    , imout->dy    , imout->dz    ) ;
   LOAD_FVEC3( orgxyz , imout->xo    , imout->yo    , imout->zo    ) ;
   LOAD_IVEC3( orixyz , ORI_R2L_TYPE , ORI_A2P_TYPE , ORI_I2S_TYPE ) ;

   if( verb )
     fprintf(stderr,"++3dSpatNorm: EDIT_dset_items\n") ;
   EDIT_dset_items( oset ,
                      ADN_prefix      , prefix ,
                      ADN_datum_all   , imout->kind ,
                      ADN_nxyz        , nxyz ,
                      ADN_xyzdel      , dxyz ,
                      ADN_xyzorg      , orgxyz ,
                      ADN_xyzorient   , orixyz ,
                      ADN_malloc_type , DATABLOCK_MEM_MALLOC ,
                      ADN_view_type   , VIEW_ORIGINAL_TYPE ,
                      ADN_type        , HEAD_ANAT_TYPE ,
                      ADN_func_type   , ANAT_BUCK_TYPE ,
                    ADN_none ) ;

   if( verb )
     fprintf(stderr,"++3dSpatNorm: EDIT_substitute_brick\n") ;
   EDIT_substitute_brick( oset , 0 , imout->kind , mri_data_pointer(imout) ) ;

   if (OrigSpace) {
      if( verb )
         fprintf(stderr,"++3dSpatNorm: Changing orientation from RAI\n") ;
      ooset = r_new_resam_dset ( oset, iset, 0, 0, 0, NULL, MRI_NN, NULL, 1, 0);
      if (!ooset) {
         fprintf(stderr,"**ERROR: Failed to reslice!?\n"); exit(1);
      }
      /* put prefix back, r_new_resam_dset puts dummy prefix */
      EDIT_dset_items( ooset ,
                       ADN_prefix      , prefix,
                       ADN_none ) ;

      DSET_delete(oset); oset = ooset; ooset = NULL;
   }

   if (iset_scaled != 1.0f) 
      THD_volDXYZscale(oset->daxes,
                      1/iset_scaled, 0);

   DSET_write(oset) ;
   if( verb )
     fprintf(stderr,"++3dSpatNorm: wrote dataset %s\n",DSET_BRIKNAME(oset)) ;
   
   exit(0) ;
}
Exemple #20
0
int AFNI_check_pbar_lock()
{
   return AFNI_yesenv("AFNI_PBAR_LOCK") ;
}
Boolean THD_write_atr( THD_datablock *blk )
{
   THD_diskptr *dkptr ;
   int ia , code , ii ;
   ATR_any *atr_any ;
   Boolean good = True ;
   FILE *header_file ;

ENTRY("THD_write_atr") ;

   /*--- sanity checks ---*/

   if( ! ISVALID_DATABLOCK(blk) ) RETURN( False );

   dkptr = blk->diskptr ;
   if( ! ISVALID_DISKPTR(dkptr) || strlen(dkptr->header_name) == 0 ) RETURN( False );

   if( DBLK_IS_MINC(blk)    ) RETURN( False ); /* 29 Oct 2001 */
   if( DBLK_IS_ANALYZE(blk) ) RETURN( False ); /* 27 Aug 2002 */
   if( DBLK_IS_NIFTI(blk)   ) RETURN( False ); /* 28 Aug 2003 */
   if( DBLK_IS_CTFMRI(blk)  ) RETURN( False );
   if( DBLK_IS_CTFSAM(blk)  ) RETURN( False );
   if( DBLK_IS_MPEG(blk)    ) RETURN( False );

   /** 01 Jun 2005: perhaps write in the new NIML format? **/

   if( AFNI_yesenv("AFNI_WRITE_NIML") ){
     return THD_write_nimlatr( blk ) ;
   }

   /** Write the old AFNI format **/

   header_file = fopen( dkptr->header_name , "w" ) ;
   if( header_file == NULL ){
      fprintf(stderr,
              "*** ERROR: failed to open file %s for attribute writing;\n"
              "         - Do you have permission to write to this disk?\n"
              "         - Is the disk full?\n" ,
              dkptr->header_name) ;
      RETURN( False );
   }

   for( ia=0 ; ia < blk->natr ; ia++ ){

      atr_any = &(blk->atr[ia]) ;
      if( ATR_COUNT(atr_any) <= 0 ) continue ;

      code = SUCCESS ;
      switch( atr_any->type ){

         case ATR_FLOAT_TYPE:{
            ATR_float * atr_flo = (ATR_float *) atr_any ;

            code = fprintf( header_file ,
                            "\ntype  = %s\nname  = %s\ncount = %d\n" ,
                            ATR_typestr[ATR_FLOAT_TYPE] ,
                            atr_flo->name , atr_flo->nfl ) ;

            if( code < 1 ){ code = FAIL ; break ; }

            for( ii=0 ; ii < atr_flo->nfl ; ii++ ){
               code = fprintf( header_file , " %14.7g" , atr_flo->fl[ii] ) ;
               if( ii % 5 == 4 && ii < atr_flo->nfl-1 )
                  fprintf( header_file , "\n" ) ;
            }

            code = (code < 1 ) ? FAIL : SUCCESS ;
         }
         break ;

         case ATR_INT_TYPE:{
            ATR_int * atr_int = (ATR_int *) atr_any ;

            code = fprintf( header_file ,
                            "\ntype = %s\nname = %s\ncount = %d\n" ,
                            ATR_typestr[ATR_INT_TYPE] ,
                            atr_int->name , atr_int->nin ) ;

            if( code < 1 ){ code = FAIL ; break ; }

            for( ii=0 ; ii < atr_int->nin ; ii++ ){
               code = fprintf( header_file , " %d" , atr_int->in[ii] ) ;
               if( ii % 5 == 4 && ii < atr_int->nin-1 )
                  fprintf( header_file , "\n" ) ;
            }

            code = (code < 1 ) ? FAIL : SUCCESS ;
         }
         break ;

         case ATR_STRING_TYPE:{
            ATR_string * atr_str = (ATR_string *) atr_any ;

            code = fprintf( header_file ,
                            "\ntype = %s\nname = %s\ncount = %d\n" ,
                            ATR_typestr[ATR_STRING_TYPE] ,
                            atr_str->name , atr_str->nch ) ;


            if( code < 1 ){ code = FAIL ; break ; }

            THD_zblock( atr_str->nch , atr_str->ch ) ;

            fprintf( header_file , "'" ) ;
            for( ii=0 ; ii < atr_str->nch ; ii++ ){
               code = fprintf( header_file , "%c" , atr_str->ch[ii] ) ;
            }

            code = (code < 1) ? FAIL : SUCCESS ;

            THD_unzblock( atr_str->nch , atr_str->ch ) ;
         }
         break ;

      } /* end of switch on atr type */

      good = good && (code != FAIL) ;  /* all must not FAIL */
      fprintf(header_file,"\n") ;

   } /* end of loop over all atr's */

   if( good == False ){
      fprintf(stderr,
              "*** WARNING: error in output to attribute file %s;\n"
              "           - Is the disk full?\n" ,
              dkptr->header_name) ;
   }

   /*--- close it down ---*/

   fclose( header_file ) ;
   RETURN( True );
}
Exemple #22
0
int AFNI_check_range_lock()
{
   if( AFNI_yesenv("AFNI_RANGE_LOCK")           ) return 1 ;
   if( PBAR_FULLRANGE && AFNI_check_pbar_lock() ) return 1 ;
   return 0 ;
}
Exemple #23
0
int main( int argc , char * argv[] )
{
   int do_norm=0 , qdet=2 , have_freq=0 , do_automask=0 ;
   float dt=0.0f , fbot=0.0f,ftop=999999.9f , blur=0.0f ;
   MRI_IMARR *ortar=NULL ; MRI_IMAGE *ortim=NULL ;
   THD_3dim_dataset **ortset=NULL ; int nortset=0 ;
   THD_3dim_dataset *inset=NULL , *outset=NULL;
   char *prefix="RSFC" ;
   byte *mask=NULL ;
   int mask_nx=0,mask_ny=0,mask_nz=0,nmask , verb=1 , 
		nx,ny,nz,nvox , nfft=0 , kk ;
   float **vec , **ort=NULL ; int nort=0 , vv , nopt , ntime  ;
   MRI_vectim *mrv ;
   float pvrad=0.0f ; int nosat=0 ;
   int do_despike=0 ;

	// @@ non-BP variables
	float fbotALL=0.0f, ftopALL=999999.9f; // do full range version
	int NumDen = 0; // switch for doing numerator or denom
	THD_3dim_dataset *outsetALL=NULL ; 	
	int m, mm;
	float delf; // harmonics
	int ind_low,ind_high,N_ny, ctr;
	float sqnt,nt_fac;
	gsl_fft_real_wavetable *real1, *real2; // GSL stuff
	gsl_fft_real_workspace *work;
	double *series1, *series2;	
	double *xx1,*xx2;
	float numer,denom,val;
	float *alff=NULL,*malff=NULL,*falff=NULL,
         *rsfa=NULL,*mrsfa=NULL,*frsfa=NULL; // values
	float meanALFF=0.0f,meanRSFA=0.0f; // will be for mean in brain region
	THD_3dim_dataset *outsetALFF=NULL;
	THD_3dim_dataset *outsetmALFF=NULL;
	THD_3dim_dataset *outsetfALFF=NULL;
	THD_3dim_dataset *outsetRSFA=NULL;
	THD_3dim_dataset *outsetmRSFA=NULL;
	THD_3dim_dataset *outsetfRSFA=NULL;
	char out_lff[300];
	char out_alff[300];
	char out_malff[300];
	char out_falff[300];
	char out_rsfa[300];
	char out_mrsfa[300];
	char out_frsfa[300];
	char out_unBP[300];
	int SERIES_OUT = 1;
	int UNBP_OUT = 0; 
	int DO_RSFA = 1;
	int BP_LAST = 0; // option for only doing filter to LFFs at very end of proc
	float de_rsfa=0.0f,nu_rsfa=0.0f;
	double pow1=0.0,pow2=0.0;

   /*-- help? --*/

   if( argc < 2 || strcmp(argv[1],"-help") == 0 ){
		printf(
"\n  Program to calculate common resting state functional connectivity (RSFC)\n"
"  parameters (ALFF, mALFF, fALFF, RSFA, etc.) for resting state time\n"
"  series.  This program is **heavily** based on the existing\n"
"  3dBandPass by RW Cox, with the amendments to calculate RSFC\n"
"  parameters written by PA Taylor (July, 2012).\n"
"  This program is part of FATCAT (Taylor & Saad, 2013) in AFNI. Importantly,\n"
"  its functionality can be included in the `afni_proc.py' processing-script \n"
"  generator; see that program's help file for an example including RSFC\n"
"  and spectral parameter calculation via the `-regress_RSFC' option.\n"
"\n"
"* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *\n"
"\n"
"  All options of 3dBandPass may be used here (with a couple other\n"
"  parameter options, as well): essentially, the motivation of this\n"
"  program is to produce ALFF, etc. values of the actual RSFC time\n"
"  series that you calculate.  Therefore, all the 3dBandPass processing\n"
"  you normally do en route to making your final `resting state time\n"
"  series' is done here to generate your LFFs, from which the\n"
"  amplitudes in the LFF band are calculated at the end.  In order to\n"
"  calculate fALFF, the same initial time series are put through the\n"
"  same processing steps which you have chosen but *without* the\n"
"  bandpass part; the spectrum of this second time series is used to\n"
"  calculate the fALFF denominator.\n"
" \n"
"  For more information about each RSFC parameter, see, e.g.:   \n"
"  ALFF/mALFF -- Zang et al. (2007),\n"
"  fALFF --      Zou et al. (2008),\n"
"  RSFA --       Kannurpatti & Biswal (2008).\n"
"\n"
"* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *\n"
"\n"
" + USAGE: 3dRSFC [options] fbot ftop dataset\n"
"\n"
"* One function of this program is to prepare datasets for input\n"
"   to 3dSetupGroupInCorr.  Other uses are left to your imagination.\n"
"\n"
"* 'dataset' is a 3D+time sequence of volumes\n"
"   ++ This must be a single imaging run -- that is, no discontinuities\n"
"       in time from 3dTcat-ing multiple datasets together.\n"
"\n"
"* fbot = lowest frequency in the passband, in Hz\n"
"   ++ fbot can be 0 if you want to do a lowpass filter only;\n"
"       HOWEVER, the mean and Nyquist freq are always removed.\n"
"\n"
"* ftop = highest frequency in the passband (must be > fbot)\n"
"   ++ if ftop > Nyquist freq, then it's a highpass filter only.\n"
"\n"
"* Set fbot=0 and ftop=99999 to do an 'allpass' filter.\n"
"  ++ Except for removal of the 0 and Nyquist frequencies, that is.\n"
"\n"
"* You cannot construct a 'notch' filter with this program!\n"
"  ++ You could use 3dRSFC followed by 3dcalc to get the same effect.\n"
"  ++ If you are understand what you are doing, that is.\n"
"  ++ Of course, that is the AFNI way -- if you don't want to\n"
"     understand what you are doing, use Some other PrograM, and\n"
"     you can still get Fine StatisticaL maps.\n"
"\n"
"* 3dRSFC will fail if fbot and ftop are too close for comfort.\n"
"  ++ Which means closer than one frequency grid step df,\n"
"     where df = 1 / (nfft * dt) [of course]\n"
"\n"
"* The actual FFT length used will be printed, and may be larger\n"
"   than the input time series length for the sake of efficiency.\n"
"  ++ The program will use a power-of-2, possibly multiplied by\n"
"     a power of 3 and/or 5 (up to and including the 3rd power of\n"
"     each of these: 3, 9, 27, and 5, 25, 125).\n"
"\n"
"* Note that the results of combining 3dDetrend and 3dRSFC will\n"
"   depend on the order in which you run these programs.  That's why\n"
"   3dRSFC has the '-ort' and '-dsort' options, so that the\n"
"   time series filtering can be done properly, in one place.\n"
"\n"
"* The output dataset is stored in float format.\n"
"\n"
"* The order of processing steps is the following (most are optional), and\n"
"  for the LFFs, the bandpass is done between the specified fbot and ftop,\n"
"  while for the `whole spectrum' (i.e., fALFF denominator) the bandpass is:\n"
"  done only to exclude the time series mean and the Nyquist frequency:\n"
" (0) Check time series for initial transients [does not alter data]\n"
" (1) Despiking of each time series\n"
" (2) Removal of a constant+linear+quadratic trend in each time series\n"
" (3) Bandpass of data time series\n"
" (4) Bandpass of -ort time series, then detrending of data\n"
"      with respect to the -ort time series\n"
" (5) Bandpass and de-orting of the -dsort dataset,\n"
"      then detrending of the data with respect to -dsort\n"
" (6) Blurring inside the mask [might be slow]\n"
" (7) Local PV calculation     [WILL be slow!]\n"
" (8) L2 normalization         [will be fast.]\n"
" (9) Calculate spectrum and amplitudes, for RSFC parameters.\n"
"\n"
"* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *\n"
"--------\n"
"OPTIONS:\n"
"--------\n"
" -despike        = Despike each time series before other processing.\n"
"                   ++ Hopefully, you don't actually need to do this,\n"
"                      which is why it is optional.\n"
" -ort f.1D       = Also orthogonalize input to columns in f.1D\n"
"                   ++ Multiple '-ort' options are allowed.\n"
" -dsort fset     = Orthogonalize each voxel to the corresponding\n"
"                    voxel time series in dataset 'fset', which must\n"
"                    have the same spatial and temporal grid structure\n"
"                    as the main input dataset.\n"
"                   ++ At present, only one '-dsort' option is allowed.\n"
" -nodetrend      = Skip the quadratic detrending of the input that\n"
"                    occurs before the FFT-based bandpassing.\n"
"                   ++ You would only want to do this if the dataset\n"
"                      had been detrended already in some other program.\n"
" -dt dd          = set time step to 'dd' sec [default=from dataset header]\n"
" -nfft N         = set the FFT length to 'N' [must be a legal value]\n"
" -norm           = Make all output time series have L2 norm = 1\n"
"                   ++ i.e., sum of squares = 1\n"
" -mask mset      = Mask dataset\n"
" -automask       = Create a mask from the input dataset\n"
" -blur fff       = Blur (inside the mask only) with a filter\n"
"                    width (FWHM) of 'fff' millimeters.\n"
" -localPV rrr    = Replace each vector by the local Principal Vector\n"
"                    (AKA first singular vector) from a neighborhood\n"
"                    of radius 'rrr' millimiters.\n"
"                   ++ Note that the PV time series is L2 normalized.\n"
"                   ++ This option is mostly for Bob Cox to have fun with.\n"
"\n"
" -input dataset  = Alternative way to specify input dataset.\n"
" -band fbot ftop = Alternative way to specify passband frequencies.\n"
"\n"
" -prefix ppp     = Set prefix name of output dataset. Name of filtered time\n"
"                   series would be, e.g., ppp_LFF+orig.*, and the parameter\n"
"                   outputs are named with obvious suffices.\n"
" -quiet          = Turn off the fun and informative messages. (Why?)\n"
" -no_rs_out      = Don't output processed time series-- just output\n"
"                   parameters (not recommended, since the point of\n"
"                   calculating RSFC params here is to have them be quite\n"
"                   related to the time series themselves which are used for\n"
"                   further analysis)."
" -un_bp_out      = Output the un-bandpassed series as well (default is not \n"
"                   to).  Name would be, e.g., ppp_unBP+orig.* .\n"
"                   with suffix `_unBP'.\n"
" -no_rsfa        = If you don't want RSFA output (default is to do so).\n"
" -bp_at_end      = A (probably unnecessary) switch to have bandpassing be \n"
"                   the very last processing step that is done in the\n"
"                   sequence of steps listed above; at Step 3 above, only \n"
"                   the time series mean and nyquist are BP'ed out, and then\n"
"                   the LFF series is created only after Step 9.  NB: this \n"
"                   probably makes only very small changes for most\n"
"                   processing sequences (but maybe not, depending usage).\n"
"\n"
" -notrans        = Don't check for initial positive transients in the data:\n"
"  *OR*             ++ The test is a little slow, so skipping it is OK,\n"
" -nosat               if you KNOW the data time series are transient-free.\n"
"                   ++ Or set AFNI_SKIP_SATCHECK to YES.\n"
"                   ++ Initial transients won't be handled well by the\n"
"                      bandpassing algorithm, and in addition may seriously\n"
"                      contaminate any further processing, such as inter-\n"
"                      voxel correlations via InstaCorr.\n"
"                   ++ No other tests are made [yet] for non-stationary \n"
"                      behavior in the time series data.\n"
"\n"
"* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *\n"
"\n"
"  If you use this program, please reference the introductory/description\n"
"  paper for the FATCAT toolbox:\n"
"        Taylor PA, Saad ZS (2013).  FATCAT: (An Efficient) Functional\n"
"        And Tractographic Connectivity Analysis Toolbox. Brain \n"
"        Connectivity 3(5):523-535.\n"
"____________________________________________________________________________\n"
);
		PRINT_AFNI_OMP_USAGE(
" 3dRSFC" ,
" * At present, the only part of 3dRSFC that is parallelized is the\n"
"   '-blur' option, which processes each sub-brick independently.\n"
									) ;
		PRINT_COMPILE_DATE ; exit(0) ;
   }
	
   /*-- startup --*/
	
   mainENTRY("3dRSFC"); machdep();
   AFNI_logger("3dRSFC",argc,argv);
   PRINT_VERSION("3dRSFC (from 3dBandpass by RW Cox): version THETA"); 
	AUTHOR("PA Taylor");
	
   nosat =  AFNI_yesenv("AFNI_SKIP_SATCHECK") ;
	
   nopt = 1 ;
   while( nopt < argc && argv[nopt][0] == '-' ){

		if( strcmp(argv[nopt],"-despike") == 0 ){  /* 08 Oct 2010 */
			do_despike++ ; nopt++ ; continue ;
		}

		if( strcmp(argv[nopt],"-nfft") == 0 ){
			int nnup ;
			if( ++nopt >= argc ) ERROR_exit("need an argument after -nfft!") ;
			nfft = (int)strtod(argv[nopt],NULL) ;
			nnup = csfft_nextup_even(nfft) ;
			if( nfft < 16 || nfft != nnup )
				ERROR_exit("value %d after -nfft is illegal! Next legal value = %d",nfft,nnup) ;
			nopt++ ; continue ;
		}

		if( strcmp(argv[nopt],"-blur") == 0 ){
			if( ++nopt >= argc ) ERROR_exit("need an argument after -blur!") ;
			blur = strtod(argv[nopt],NULL) ;
			if( blur <= 0.0f ) WARNING_message("non-positive blur?!") ;
			nopt++ ; continue ;
		}

		if( strcmp(argv[nopt],"-localPV") == 0 ){
			if( ++nopt >= argc ) ERROR_exit("need an argument after -localpv!") ;
			pvrad = strtod(argv[nopt],NULL) ;
			if( pvrad <= 0.0f ) WARNING_message("non-positive -localpv?!") ;
			nopt++ ; continue ;
		}

		if( strcmp(argv[nopt],"-prefix") == 0 ){
			if( ++nopt >= argc ) ERROR_exit("need an argument after -prefix!") ;
			prefix = strdup(argv[nopt]) ;
			if( !THD_filename_ok(prefix) ) ERROR_exit("bad -prefix option!") ;
			nopt++ ; continue ;
		}

		if( strcmp(argv[nopt],"-automask") == 0 ){
			if( mask != NULL ) ERROR_exit("Can't use -mask AND -automask!") ;
			do_automask = 1 ; nopt++ ; continue ;
		}

		if( strcmp(argv[nopt],"-mask") == 0 ){
			THD_3dim_dataset *mset ;
			if( ++nopt >= argc ) ERROR_exit("Need argument after '-mask'") ;
			if( mask != NULL || do_automask ) ERROR_exit("Can't have two mask inputs") ;
			mset = THD_open_dataset( argv[nopt] ) ;
			CHECK_OPEN_ERROR(mset,argv[nopt]) ;
			DSET_load(mset) ; CHECK_LOAD_ERROR(mset) ;
			mask_nx = DSET_NX(mset); mask_ny = DSET_NY(mset); mask_nz = DSET_NZ(mset);
			mask = THD_makemask( mset , 0 , 0.5f, 0.0f ) ; DSET_delete(mset) ;
			if( mask == NULL ) ERROR_exit("Can't make mask from dataset '%s'",argv[nopt]) ;
			nmask = THD_countmask( mask_nx*mask_ny*mask_nz , mask ) ;
			if( verb ) INFO_message("Number of voxels in mask = %d",nmask) ;
			if( nmask < 1 ) ERROR_exit("Mask is too small to process") ;
			nopt++ ; continue ;
		}

		if( strcmp(argv[nopt],"-norm") == 0 ){
			do_norm = 1 ; nopt++ ; continue ;
		}

		if( strcmp(argv[nopt],"-quiet") == 0 ){
			verb = 0 ; nopt++ ; continue ;
		}

		if( strcmp(argv[nopt],"-no_rs_out") == 0 ){ // @@
			SERIES_OUT = 0 ; nopt++ ; continue ;
		}

		if( strcmp(argv[nopt],"-un_bp_out") == 0 ){ // @@
			UNBP_OUT = 1 ; nopt++ ; continue ;
		}

		if( strcmp(argv[nopt],"-no_rsfa") == 0 ){ // @@
			DO_RSFA = 0 ; nopt++ ; continue ;
		}

		if( strcmp(argv[nopt],"-bp_at_end") == 0 ){ // @@
			BP_LAST = 1 ; nopt++ ; continue ;
		}




		if( strcmp(argv[nopt],"-notrans") == 0 || strcmp(argv[nopt],"-nosat") == 0 ){
			nosat = 1 ; nopt++ ; continue ;
		}

		if( strcmp(argv[nopt],"-ort") == 0 ){
			if( ++nopt >= argc ) ERROR_exit("need an argument after -ort!") ;
			if( ortar == NULL ) INIT_IMARR(ortar) ;
			ortim = mri_read_1D( argv[nopt] ) ;
			if( ortim == NULL ) ERROR_exit("can't read from -ort '%s'",argv[nopt]) ;
			mri_add_name(argv[nopt],ortim) ;
			ADDTO_IMARR(ortar,ortim) ;
			nopt++ ; continue ;
		}

		if( strcmp(argv[nopt],"-dsort") == 0 ){
			THD_3dim_dataset *qset ;
			if( ++nopt >= argc ) ERROR_exit("need an argument after -dsort!") ;
			if( nortset > 0 ) ERROR_exit("only 1 -dsort option is allowed!") ;
			qset = THD_open_dataset(argv[nopt]) ;
			CHECK_OPEN_ERROR(qset,argv[nopt]) ;
			ortset = (THD_3dim_dataset **)realloc(ortset,
															  sizeof(THD_3dim_dataset *)*(nortset+1)) ;
			ortset[nortset++] = qset ;
			nopt++ ; continue ;
		}

		if( strncmp(argv[nopt],"-nodetrend",6) == 0 ){
			qdet = 0 ; nopt++ ; continue ;
		}

		if( strcmp(argv[nopt],"-dt") == 0 ){
			if( ++nopt >= argc ) ERROR_exit("need an argument after -dt!") ;
			dt = (float)strtod(argv[nopt],NULL) ;
			if( dt <= 0.0f ) WARNING_message("value after -dt illegal!") ;
			nopt++ ; continue ;
		}

		if( strcmp(argv[nopt],"-input") == 0 ){
			if( inset != NULL ) ERROR_exit("Can't have 2 -input options!") ;
			if( ++nopt >= argc ) ERROR_exit("need an argument after -input!") ;
			inset = THD_open_dataset(argv[nopt]) ;
			CHECK_OPEN_ERROR(inset,argv[nopt]) ; 

			nopt++ ; continue ;
		}

		if( strncmp(argv[nopt],"-band",5) == 0 ){
			if( ++nopt >= argc-1 ) ERROR_exit("need 2 arguments after -band!") ;
			if( have_freq ) WARNING_message("second -band option replaces first one!") ;
			fbot = strtod(argv[nopt++],NULL) ;
			ftop = strtod(argv[nopt++],NULL) ;
			have_freq = 1 ; continue ;
		}

		ERROR_exit("Unknown option: '%s'",argv[nopt]) ;
   }

   /** check inputs for reasonablositiness **/

   if( !have_freq ){
		if( nopt+1 >= argc )
			ERROR_exit("Need frequencies on command line after options!") ;
		fbot = (float)strtod(argv[nopt++],NULL) ;
		ftop = (float)strtod(argv[nopt++],NULL) ;
   }

   if( inset == NULL ){
		if( nopt >= argc )
			ERROR_exit("Need input dataset name on command line after options!") ;
		inset = THD_open_dataset(argv[nopt]) ;
		CHECK_OPEN_ERROR(inset,argv[nopt]) ;	 

		nopt++ ;
   }
   DSET_UNMSEC(inset) ;

   if( fbot < 0.0f  ) ERROR_exit("fbot value can't be negative!") ;
   if( ftop <= fbot ) ERROR_exit("ftop value %g must be greater than fbot value %g!",ftop,fbot) ;

   ntime = DSET_NVALS(inset) ;
   if( ntime < 9 ) ERROR_exit("Input dataset is too short!") ;

   if( nfft <= 0 ){
		nfft = csfft_nextup_even(ntime) ;
		if( verb ) INFO_message("Data length = %d  FFT length = %d",ntime,nfft) ;
		(void)THD_bandpass_set_nfft(nfft) ;
   } else if( nfft < ntime ){
		ERROR_exit("-nfft %d is less than data length = %d",nfft,ntime) ;
   } else {
		kk = THD_bandpass_set_nfft(nfft) ;
		if( kk != nfft && verb )
			INFO_message("Data length = %d  FFT length = %d",ntime,kk) ;
   }

   if( dt <= 0.0f ){
		dt = DSET_TR(inset) ;
		if( dt <= 0.0f ){
			WARNING_message("Setting dt=1.0 since input dataset lacks a time axis!") ;
			dt = 1.0f ;
		}
   }
   ftopALL = 1./dt ;// Aug,2016: should solve problem of a too-large
                    // value for THD_bandpass_vectors(), while still
                    // being >f_{Nyquist}

   if( !THD_bandpass_OK(ntime,dt,fbot,ftop,1) ) ERROR_exit("Can't continue!") ;

   nx = DSET_NX(inset); ny = DSET_NY(inset); nz = DSET_NZ(inset); nvox = nx*ny*nz;

   /* check mask, or create it */

   if( verb ) INFO_message("Loading input dataset time series" ) ;
   DSET_load(inset) ;

   if( mask != NULL ){
		if( mask_nx != nx || mask_ny != ny || mask_nz != nz )
			ERROR_exit("-mask dataset grid doesn't match input dataset") ;

   } else if( do_automask ){
		mask = THD_automask( inset ) ;
		if( mask == NULL )
			ERROR_message("Can't create -automask from input dataset?") ;
		nmask = THD_countmask( DSET_NVOX(inset) , mask ) ;
		if( verb ) INFO_message("Number of voxels in automask = %d",nmask);
		if( nmask < 1 ) ERROR_exit("Automask is too small to process") ;

   } else {
		mask = (byte *)malloc(sizeof(byte)*nvox) ; nmask = nvox ;
		memset(mask,1,sizeof(byte)*nvox) ;
		// if( verb ) // @@ alert if aaaalllllll vox are going to be analyzed!
		INFO_message("No mask ==> processing all %d voxels",nvox);
   }

   /* A simple check of dataset quality [08 Feb 2010] */

   if( !nosat ){
		float val ;
		INFO_message(
						 "Checking dataset for initial transients [use '-notrans' to skip this test]") ;
		val = THD_saturation_check(inset,mask,0,0) ; kk = (int)(val+0.54321f) ;
		if( kk > 0 )
			ININFO_message(
								"Looks like there %s %d non-steady-state initial time point%s :-(" ,
								((kk==1) ? "is" : "are") , kk , ((kk==1) ? " " : "s") ) ;
		else if( val > 0.3210f )  /* don't ask where this threshold comes from! */
			ININFO_message(
								"MAYBE there's an initial positive transient of 1 point, but it's hard to tell\n") ;
		else
			ININFO_message("No widespread initial positive transient detected :-)") ;
   }

   /* check -dsort inputs for match to inset */

   for( kk=0 ; kk < nortset ; kk++ ){
		if( DSET_NX(ortset[kk])    != nx ||
			 DSET_NY(ortset[kk])    != ny ||
			 DSET_NZ(ortset[kk])    != nz ||
			 DSET_NVALS(ortset[kk]) != ntime )
			ERROR_exit("-dsort %s doesn't match input dataset grid" ,
						  DSET_BRIKNAME(ortset[kk]) ) ;
   }

   /* convert input dataset to a vectim, which is more fun */

	// @@ convert BP'ing ftop/bot into indices for the DFT (below)
	delf = 1.0/(ntime*dt); 
	ind_low = (int) rint(fbot/delf);
	ind_high = (int) rint(ftop/delf);
	if( ntime % 2 ) // nyquist number
		N_ny = (ntime-1)/2;
	else
		N_ny = ntime/2;
	sqnt = sqrt(ntime);
	nt_fac = sqrt(ntime*(ntime-1));

	// @@ if BP_LAST==0:
	// now we go through twice, doing LFF bandpass for NumDen==0 and
	// `full spectrum' processing for NumDen==1.
	// if BP_LAST==1:
	// now we go through once, doing only `full spectrum' processing
	for( NumDen=0 ; NumDen<2 ; NumDen++) {
		//if( NumDen==1 ){ // full spectrum
		//	fbot = fbotALL;
		//	ftop = ftopALL;
		//}
		
		// essentially, just doesn't BP here, and the perfect filtering at end
		// is used for both still; this makes the final output spectrum
		// contain only frequencies in range of 0.01-0.08
		if( BP_LAST==1 )
			INFO_message("Only doing filtering to LFFs at end!");
		
		
		mrv = THD_dset_to_vectim( inset , mask , 0 ) ;
		if( mrv == NULL ) ERROR_exit("Can't load time series data!?") ;
		if( NumDen==1 )
			DSET_unload(inset) ; // @@ only unload on 2nd pass

		/* similarly for the ort vectors */

		if( ortar != NULL ){
			for( kk=0 ; kk < IMARR_COUNT(ortar) ; kk++ ){
				ortim = IMARR_SUBIM(ortar,kk) ;
				if( ortim->nx < ntime )
					ERROR_exit("-ort file %s is shorter than input dataset time series",
								  ortim->name ) ;
				ort  = (float **)realloc( ort , sizeof(float *)*(nort+ortim->ny) ) ;
				for( vv=0 ; vv < ortim->ny ; vv++ )
					ort[nort++] = MRI_FLOAT_PTR(ortim) + ortim->nx * vv ;
			}
		}

		/* all the real work now */

		if( do_despike ){
			int_pair nsp ;
			if( verb ) INFO_message("Testing data time series for spikes") ;
			nsp = THD_vectim_despike9( mrv ) ;
			if( verb ) ININFO_message(" -- Squashed %d spikes from %d voxels",nsp.j,nsp.i) ;
		}

		if( verb ) INFO_message("Bandpassing data time series") ;

		if( (BP_LAST==0) && (NumDen==0) )
			(void)THD_bandpass_vectim( mrv , dt,fbot,ftop , qdet , nort,ort ) ;
		else
			(void)THD_bandpass_vectim( mrv , dt,fbotALL,ftopALL, qdet,nort,ort ) ;

		/* OK, maybe a little more work */

		if( nortset == 1 ){
			MRI_vectim *orv ;
			orv = THD_dset_to_vectim( ortset[0] , mask , 0 ) ;
			if( orv == NULL ){
				ERROR_message("Can't load -dsort %s",DSET_BRIKNAME(ortset[0])) ;
			} else {
				float *dp , *mvv , *ovv , ff ;
				if( verb ) INFO_message("Orthogonalizing to bandpassed -dsort") ;
				//(void)THD_bandpass_vectim( orv , dt,fbot,ftop , qdet , nort,ort ) ; //@@
				if( (BP_LAST==0) && (NumDen==0) )
					(void)THD_bandpass_vectim(orv,dt,fbot,ftop,qdet,nort,ort);
				else
					(void)THD_bandpass_vectim(orv,dt,fbotALL,ftopALL,qdet,nort,ort);

				THD_vectim_normalize( orv ) ;
				dp = malloc(sizeof(float)*mrv->nvec) ;
				THD_vectim_vectim_dot( mrv , orv , dp ) ;
				for( vv=0 ; vv < mrv->nvec ; vv++ ){
					ff = dp[vv] ;
					if( ff != 0.0f ){
						mvv = VECTIM_PTR(mrv,vv) ; ovv = VECTIM_PTR(orv,vv) ;
						for( kk=0 ; kk < ntime ; kk++ ) mvv[kk] -= ff*ovv[kk] ;
					}
				}
				VECTIM_destroy(orv) ; free(dp) ;
			}
		}

		if( blur > 0.0f ){
			if( verb )
				INFO_message("Blurring time series data spatially; FWHM=%.2f",blur) ;
			mri_blur3D_vectim( mrv , blur ) ;
		}
		if( pvrad > 0.0f ){
			if( verb )
				INFO_message("Local PV-ing time series data spatially; radius=%.2f",pvrad) ;
			THD_vectim_normalize( mrv ) ;
			THD_vectim_localpv( mrv , pvrad ) ;
		}
		if( do_norm && pvrad <= 0.0f ){
			if( verb ) INFO_message("L2 normalizing time series data") ;
			THD_vectim_normalize( mrv ) ;
		}

		/* create output dataset, populate it, write it, then quit */
		if( (NumDen==0) ) { // @@ BP'ed version;  will do filt if BP_LAST

			if(BP_LAST) // do bandpass here for BP_LAST
				(void)THD_bandpass_vectim(mrv,dt,fbot,ftop,qdet,0,NULL);

			if( verb ) INFO_message("Creating output dataset in memory, then writing it") ;
			outset = EDIT_empty_copy(inset) ;
			if(SERIES_OUT){
				sprintf(out_lff,"%s_LFF",prefix); 
				EDIT_dset_items( outset , ADN_prefix,out_lff , ADN_none ) ;
				tross_Copy_History( inset , outset ) ;
				tross_Make_History( "3dBandpass" , argc,argv , outset ) ;
			}
			for( vv=0 ; vv < ntime ; vv++ )
				EDIT_substitute_brick( outset , vv , MRI_float , NULL ) ;
		
#if 1
			THD_vectim_to_dset( mrv , outset ) ;
#else
			AFNI_OMP_START ;
#pragma omp parallel
			{ float *far , *var ; int *ivec=mrv->ivec ; int vv,kk ;
#pragma omp for
				for( vv=0 ; vv < ntime ; vv++ ){
					far = DSET_BRICK_ARRAY(outset,vv) ; var = mrv->fvec + vv ;
					for( kk=0 ; kk < nmask ; kk++ ) far[ivec[kk]] = var[kk*ntime] ;
				}
			}
			AFNI_OMP_END ;
#endif
			VECTIM_destroy(mrv) ;
			if(SERIES_OUT){ // @@
				DSET_write(outset) ; if( verb ) WROTE_DSET(outset) ;
			}
		}
		else{ // @@ non-BP'ed version
			if( verb ) INFO_message("Creating output dataset 2 in memory") ;

			// do this here because LFF version was also BP'ed at end.
			if(BP_LAST) // do bandpass here for BP_LAST
				(void)THD_bandpass_vectim(mrv,dt,fbotALL,ftopALL,qdet,0,NULL);

			outsetALL = EDIT_empty_copy(inset) ;
			if(UNBP_OUT){ 
				sprintf(out_unBP,"%s_unBP",prefix); 
				EDIT_dset_items( outsetALL, ADN_prefix, out_unBP, ADN_none );
				tross_Copy_History( inset , outsetALL ) ;
				tross_Make_History( "3dRSFC" , argc,argv , outsetALL ) ;
			}
			for( vv=0 ; vv < ntime ; vv++ )
				EDIT_substitute_brick( outsetALL , vv , MRI_float , NULL ) ;
		
#if 1
			THD_vectim_to_dset( mrv , outsetALL ) ;
#else
			AFNI_OMP_START ;
#pragma omp parallel
			{ float *far , *var ; int *ivec=mrv->ivec ; int vv,kk ;
#pragma omp for
				for( vv=0 ; vv < ntime ; vv++ ){
					far = DSET_BRICK_ARRAY(outsetALL,vv) ; var = mrv->fvec + vv ;
					for( kk=0 ; kk < nmask ; kk++ ) far[ivec[kk]] = var[kk*ntime] ;
				}
			}
			AFNI_OMP_END ;
#endif
			VECTIM_destroy(mrv) ;
			if(UNBP_OUT){ 
				DSET_write(outsetALL) ; if( verb ) WROTE_DSET(outsetALL) ;
			}
		}
	}// end of NumDen loop


	// @@
	INFO_message("Starting the (f)ALaFFel calcs") ;

	// allocations
	series1 = (double *)calloc(ntime,sizeof(double)); 
	series2 = (double *)calloc(ntime,sizeof(double)); 
	xx1 = (double *)calloc(2*ntime,sizeof(double)); 
	xx2 = (double *)calloc(2*ntime,sizeof(double)); 
	alff = (float *)calloc(nvox,sizeof(float)); 
	malff = (float *)calloc(nvox,sizeof(float)); 
	falff = (float *)calloc(nvox,sizeof(float)); 

	if( (series1 == NULL) || (series2 == NULL) 
		 || (xx1 == NULL) || (xx2 == NULL) 
		 || (alff == NULL) || (malff == NULL) || (falff == NULL)) { 
		fprintf(stderr, "\n\n MemAlloc failure.\n\n");
		exit(122);
	}
	if(DO_RSFA) {
		rsfa = (float *)calloc(nvox,sizeof(float)); 
		mrsfa = (float *)calloc(nvox,sizeof(float)); 
		frsfa = (float *)calloc(nvox,sizeof(float)); 
		if( (rsfa == NULL) || (mrsfa == NULL) || (frsfa == NULL)) { 
			fprintf(stderr, "\n\n MemAlloc failure.\n\n");
			exit(123);
		}	
	}
	
	
	work = gsl_fft_real_workspace_alloc (ntime);
	real1 = gsl_fft_real_wavetable_alloc (ntime);
	real2 = gsl_fft_real_wavetable_alloc (ntime);
	gsl_complex_packed_array compl_freqs1 = xx1;
	gsl_complex_packed_array compl_freqs2 = xx2;




	// *********************************************************************
	// *********************************************************************
	// **************    Falafelling = ALFF/fALFF calcs    *****************
	// *********************************************************************
	// *********************************************************************

	// Be now have the BP'ed data set (outset) and the non-BP'ed one
	// (outsetALL).  now we'll FFT both, get amplitudes in appropriate
	// ranges, and calculate:  ALFF, mALFF, fALFF,

	ctr = 0;
	for( kk=0; kk<nvox ; kk++) {
		if(mask[kk]) {
			
			// BP one, and unBP one, either for BP_LAST or !BP_LAST
			for( m=0 ; m<ntime ; m++ ) {
				series1[m] = THD_get_voxel(outset,kk,m);
				series2[m] = THD_get_voxel(outsetALL,kk,m);
			}
			
			
			mm = gsl_fft_real_transform(series1, 1, ntime, real1, work);
			mm = gsl_fft_halfcomplex_unpack(series1, compl_freqs1, 1, ntime);
			mm = gsl_fft_real_transform(series2, 1, ntime, real2, work);
			mm = gsl_fft_halfcomplex_unpack(series2, compl_freqs2, 1, ntime);

			numer = 0.0f; 
			denom = 0.0f;
			de_rsfa = 0.0f;
			nu_rsfa = 0.0f;
			for( m=1 ; m<N_ny ; m++ ) {
				mm = 2*m;
				pow2 = compl_freqs2[mm]*compl_freqs2[mm] +
					compl_freqs2[mm+1]*compl_freqs2[mm+1]; // power
				//pow2*=2;// factor of 2 since ampls are even funcs
				denom+= (float) sqrt(pow2); // amplitude 
				de_rsfa+= (float) pow2;
				
				if( ( m>=ind_low ) && ( m<=ind_high ) ){
					pow1 = compl_freqs1[mm]*compl_freqs1[mm]+
						compl_freqs1[mm+1]*compl_freqs1[mm+1];
					//pow1*=2;
					numer+= (float) sqrt(pow1);
					nu_rsfa+= (float) pow1;
				}
			}

			if( denom>0.000001 )
			  falff[kk] = numer/denom;
			else
			  falff[kk] = 0.;
			alff[kk] = 2*numer/sqnt;// factor of 2 since ampl is even funct
			meanALFF+= alff[kk];

			if(DO_RSFA){
			  nu_rsfa = sqrt(2*nu_rsfa); // factor of 2 since ampls 
			  de_rsfa = sqrt(2*de_rsfa); // are even funcs
			  if( de_rsfa>0.000001 )
			    frsfa[kk] = nu_rsfa/de_rsfa;
			  else
			    frsfa[kk]=0.;
			  rsfa[kk] = nu_rsfa/nt_fac;
			  meanRSFA+= rsfa[kk];
			}
			
			ctr+=1;
		}
	}
	meanALFF/= ctr;
	meanRSFA/= ctr;

	gsl_fft_real_wavetable_free(real1);
	gsl_fft_real_wavetable_free(real2);
	gsl_fft_real_workspace_free(work);

	// ALFFs divided by mean of brain value
	for( kk=0 ; kk<nvox ; kk++ ) 
		if(mask[kk]){
			malff[kk] = alff[kk]/meanALFF;
			if(DO_RSFA)
				mrsfa[kk] = rsfa[kk]/meanRSFA;
		}
	// **************************************************************
	// **************************************************************
	//                 Store and output
	// **************************************************************
	// **************************************************************
	
	outsetALFF = EDIT_empty_copy( inset ) ; 
	sprintf(out_alff,"%s_ALFF",prefix); 
	EDIT_dset_items( outsetALFF,
                    ADN_nvals, 1,
						  ADN_datum_all , MRI_float , 
						  ADN_prefix    , out_alff,
						  ADN_none ) ;
	if( !THD_ok_overwrite() && THD_is_ondisk(DSET_HEADNAME(outsetALFF)) )
		ERROR_exit("Can't overwrite existing dataset '%s'",
					  DSET_HEADNAME(outsetALFF));
	EDIT_substitute_brick(outsetALFF, 0, MRI_float, alff); 
	alff=NULL;
	THD_load_statistics(outsetALFF);
	tross_Make_History("3dRSFC", argc, argv, outsetALFF);
	THD_write_3dim_dataset(NULL, NULL, outsetALFF, True);

	outsetfALFF = EDIT_empty_copy( inset ) ;
	sprintf(out_falff,"%s_fALFF",prefix); 
	EDIT_dset_items( outsetfALFF,
                    ADN_nvals, 1,
						  ADN_datum_all , MRI_float , 
						  ADN_prefix    , out_falff,
						  ADN_none ) ;
	if( !THD_ok_overwrite() && THD_is_ondisk(DSET_HEADNAME(outsetfALFF)) )
		ERROR_exit("Can't overwrite existing dataset '%s'",
					  DSET_HEADNAME(outsetfALFF));
	EDIT_substitute_brick(outsetfALFF, 0, MRI_float, falff); 
	falff=NULL;
	THD_load_statistics(outsetfALFF);
	tross_Make_History("3dRSFC", argc, argv, outsetfALFF);
	THD_write_3dim_dataset(NULL, NULL, outsetfALFF, True);



	outsetmALFF = EDIT_empty_copy( inset ) ;
	sprintf(out_malff,"%s_mALFF",prefix); 
	EDIT_dset_items( outsetmALFF,
                    ADN_nvals, 1,
                    ADN_datum_all , MRI_float , 
						  ADN_prefix    , out_malff,
						  ADN_none ) ;
	if( !THD_ok_overwrite() && THD_is_ondisk(DSET_HEADNAME(outsetmALFF)) )
		ERROR_exit("Can't overwrite existing dataset '%s'",
					  DSET_HEADNAME(outsetmALFF));
	EDIT_substitute_brick(outsetmALFF, 0, MRI_float, malff); 
	malff=NULL;
	THD_load_statistics(outsetmALFF);
	tross_Make_History("3dRSFC", argc, argv, outsetmALFF);
	THD_write_3dim_dataset(NULL, NULL, outsetmALFF, True);

	if(DO_RSFA){
     outsetRSFA = EDIT_empty_copy( inset ) ;
		sprintf(out_rsfa,"%s_RSFA",prefix); 
		EDIT_dset_items( outsetRSFA,
                       ADN_nvals, 1,
                       ADN_datum_all , MRI_float , 
							  ADN_prefix    , out_rsfa,
							  ADN_none ) ;
		if( !THD_ok_overwrite() && THD_is_ondisk(DSET_HEADNAME(outsetRSFA)) )
			ERROR_exit("Can't overwrite existing dataset '%s'",
						  DSET_HEADNAME(outsetRSFA));
		EDIT_substitute_brick(outsetRSFA, 0, MRI_float, rsfa); 
		rsfa=NULL;
		THD_load_statistics(outsetRSFA);
		tross_Make_History("3dRSFC", argc, argv, outsetRSFA);
		THD_write_3dim_dataset(NULL, NULL, outsetRSFA, True);
		
      outsetfRSFA = EDIT_empty_copy( inset ) ;
		sprintf(out_frsfa,"%s_fRSFA",prefix); 
		EDIT_dset_items( outsetfRSFA,
                       ADN_nvals, 1,
                       ADN_datum_all , MRI_float , 
							  ADN_prefix    , out_frsfa,
							  ADN_none ) ;
		if( !THD_ok_overwrite() && THD_is_ondisk(DSET_HEADNAME(outsetfRSFA)) )
			ERROR_exit("Can't overwrite existing dataset '%s'",
						  DSET_HEADNAME(outsetfRSFA));
		EDIT_substitute_brick(outsetfRSFA, 0, MRI_float, frsfa); 
		frsfa=NULL;
		THD_load_statistics(outsetfRSFA);
		tross_Make_History("3dRSFC", argc, argv, outsetfRSFA);
		THD_write_3dim_dataset(NULL, NULL, outsetfRSFA, True);
		
		outsetmRSFA = EDIT_empty_copy( inset ) ; 
		sprintf(out_mrsfa,"%s_mRSFA",prefix); 
		EDIT_dset_items( outsetmRSFA,
                       ADN_nvals, 1,
                       ADN_datum_all , MRI_float , 
							  ADN_prefix    , out_mrsfa,
							  ADN_none ) ;
		if( !THD_ok_overwrite() && THD_is_ondisk(DSET_HEADNAME(outsetmRSFA)) )
			ERROR_exit("Can't overwrite existing dataset '%s'",
						  DSET_HEADNAME(outsetmRSFA));
		EDIT_substitute_brick(outsetmRSFA, 0, MRI_float, mrsfa); 
		mrsfa=NULL;
		THD_load_statistics(outsetmRSFA);
		tross_Make_History("3dRSFC", argc, argv, outsetmRSFA);
		THD_write_3dim_dataset(NULL, NULL, outsetmRSFA, True);
	}



	// ************************************************************
	// ************************************************************
	//                    Freeing
	// ************************************************************
	// ************************************************************

	DSET_delete(inset);
	DSET_delete(outsetALL);
	DSET_delete(outset);
	DSET_delete(outsetALFF);
	DSET_delete(outsetmALFF);
	DSET_delete(outsetfALFF);
	DSET_delete(outsetRSFA);
	DSET_delete(outsetmRSFA);
	DSET_delete(outsetfRSFA);

	free(inset);
	free(outsetALL);
	free(outset);
	free(outsetALFF);
	free(outsetmALFF);
	free(outsetfALFF);
	free(outsetRSFA);
	free(outsetmRSFA);
	free(outsetfRSFA);

	free(rsfa);
	free(mrsfa);
	free(frsfa);
	free(alff);
	free(malff);
	free(falff);
	free(mask);
	free(series1);
	free(series2);
	free(xx1);
	free(xx2);

	exit(0) ;
}
int THD_datablock_from_atr( THD_datablock *dblk, char *dirname, char *headname )
{
   THD_diskptr       *dkptr ;
   ATR_int           *atr_rank , *atr_dimen , *atr_scene , *atr_btype ;
   ATR_float         *atr_flt ;
   ATR_string        *atr_labs ;
   int   ii , view_type , func_type , dset_type , 
         nx,ny,nz,nvox , nvals , ibr,typ ;
   Boolean ok ;
   char prefix[THD_MAX_NAME]="Unknown" ;
   MRI_IMAGE *qim ;
   int brick_ccode ;
   char name[666] ;

ENTRY("THD_datablock_from_atr") ;

   if( dblk == NULL || dblk->natr <= 0 ) RETURN(0) ; /* bad input */

   dkptr = dblk->diskptr ;

   /*-- get relevant attributes: rank, dimensions, view_type & func_type --*/

   atr_rank  = THD_find_int_atr( dblk , ATRNAME_DATASET_RANK ) ;
   atr_dimen = THD_find_int_atr( dblk , ATRNAME_DATASET_DIMENSIONS ) ;
   atr_scene = THD_find_int_atr( dblk , ATRNAME_SCENE_TYPE ) ;

   /*-- missing an attribute ==> quit now --*/

   if( atr_rank == NULL || atr_dimen == NULL || atr_scene == NULL ) RETURN(0) ;

   /*-- load type codes from SCENE attribute --*/

   STATUS("loading *_type from SCENE") ;

   view_type = atr_scene->in[0] ;
   func_type = atr_scene->in[1] ;
   dset_type = atr_scene->in[2] ;

   /*-- load other values from attributes into relevant places --*/

   ok   = True ;
   nvox = 1 ;

   STATUS("loading from RANK") ;

   dkptr->rank = atr_rank->in[0] ;                /* N.B.: rank isn't used much */
   dkptr->nvals = dblk->nvals = nvals = atr_rank->in[1] ;  /* but nvals is used */

   STATUS("loading from DIMENSIONS") ;

   for( ii=0 ; ii < dkptr->rank ; ii++ ){
     dkptr->dimsizes[ii] = atr_dimen->in[ii] ;
     ok                  = ( ok && dkptr->dimsizes[ii] >= 1 ) ;
     nvox               *= dkptr->dimsizes[ii] ;
   }

#if 0
   if( PRINT_TRACING ){
     char str[256] ;
     sprintf(str,"rank=%d nvals=%d dim[0]=%d dim[1]=%d dim[2]=%d nvox=%d",
             dkptr->rank , dkptr->nvals ,
             dkptr->dimsizes[0] , dkptr->dimsizes[1] , dkptr->dimsizes[2] , nvox ) ;
     STATUS(str) ;
   }
#endif

   if( !ok || nvals < 1 ||
       dkptr->rank < THD_MIN_RANK || dkptr->rank > THD_MAX_RANK ){
     STATUS("bad rank!!??") ;
     RETURN(0) ;
   }

   /*-- create the storage filenames --*/

   STATUS("creating storage filenames") ;

   if( headname != NULL && strchr(headname,'+') != NULL ){
     FILENAME_TO_PREFIX(headname,prefix) ;
     THD_init_diskptr_names( dkptr, dirname,NULL,prefix , view_type , True ) ;
   } else {
     if( headname != NULL ) MCW_strncpy(prefix,headname,THD_MAX_NAME) ;
     THD_init_diskptr_names( dkptr, dirname,NULL,prefix , view_type , True ) ;
   }

   /*-- determine if the BRIK file exists --*/

   STATUS("checking if .BRIK file exists") ;

   brick_ccode = COMPRESS_filecode(dkptr->brick_name) ;
   if (dkptr->storage_mode == STORAGE_UNDEFINED) { /* ZSS: Oct. 2011 
               the next line was being called all the time before */
      if( brick_ccode != COMPRESS_NOFILE )
        dkptr->storage_mode = STORAGE_BY_BRICK ;  /* a .BRIK file */
   }
   
   /*-- if VOLUME_FILENAMES attribute exists, make it so [20 Jun 2002] --*/

   if( headname != NULL && dkptr->storage_mode == STORAGE_UNDEFINED ){
     atr_labs = THD_find_string_atr(dblk,"VOLUME_FILENAMES") ;
     if( atr_labs != NULL ){
       dkptr->storage_mode = STORAGE_BY_VOLUMES ;
       dblk->malloc_type   = DATABLOCK_MEM_MALLOC ;
     }
   }

   /*-- now set the memory allocation codes, etc. --*/

   dblk->brick_fac = (float *) XtMalloc( sizeof(float) * nvals ) ;
   for( ibr=0 ; ibr < nvals ; ibr++ ) dblk->brick_fac[ibr] = 0.0 ;

   /* scaling factors from short type to float type, if nonzero */

   if( !AFNI_yesenv("AFNI_IGNORE_BRICK_FLTFAC") ){
     atr_flt = THD_find_float_atr( dblk , ATRNAME_BRICK_FLTFAC ) ;
     if( atr_flt != NULL ){
       for( ibr=0 ; ibr < nvals && ibr < atr_flt->nfl ; ibr++ )
         dblk->brick_fac[ibr] = atr_flt->fl[ibr] ;
     }
   }

   /** Now create an empty shell of the "brick" == the data structure
       that will hold all the voxel data.  Note that all datablocks
       will have a brick, even if they never actually contain data
       themselves (are only warp-on-demand).

       If the BRICK_TYPES input attribute doesn't exist, then all
       sub-bricks are shorts.  This makes the code work with old-style
       datasets, which were always made up of shorts.
   **/

   atr_btype = THD_find_int_atr( dblk , ATRNAME_BRICK_TYPES ) ;

   if( atr_btype == NULL ){
     THD_init_datablock_brick( dblk , MRI_short , NULL ) ;
   } else {
     THD_init_datablock_brick( dblk , atr_btype->nin , atr_btype->in ) ;
   }

   if( !THD_datum_constant(dblk) ){ /* 15 Sep 2004 */
     fprintf(stderr,
             "\n** WARNING: File %s has mixed-type sub-bricks. ", MYHEAD ) ;
   }

   /* 25 April 1998: check if the byte order is stored inside */

   atr_labs = THD_find_string_atr( dblk , ATRNAME_BYTEORDER ) ;
   if( atr_labs != NULL && atr_labs->nch > 0 ){

     if( strncmp(atr_labs->ch,LSB_FIRST_STRING,ORDER_LEN) == 0 )
       dkptr->byte_order = LSB_FIRST ;
     else if( strncmp(atr_labs->ch,MSB_FIRST_STRING,ORDER_LEN) == 0 )
       dkptr->byte_order = MSB_FIRST ;
     else
       fprintf(stderr,"*** Unknown %s found in dataset %s\n",
               ATRNAME_BYTEORDER , MYHEAD ) ;

   } else if( !no_ordwarn                         &&
              DBLK_BRICK_TYPE(dblk,0) != MRI_byte &&
              dblk->diskptr->storage_mode == STORAGE_BY_BRICK ){ /* 20 Sep 1999 */

     static int first=1 ;
     if( first ){
       fprintf(stderr,
         "\n*** The situation below can be rectified with program '3drefit -byteorder':\n");
       first = 0 ;
     }
     fprintf(stderr," ** Dataset %s: assuming byteorder %s\n",
             MYHEAD , BYTE_ORDER_STRING(dkptr->byte_order)  ) ;
   }

   /* if the data is not on disk, the flag remains at DATABLOCK_MEM_UNDEFINED,
      otherwise the flag says how the memory for the bricks is to be created. */

   if( dkptr->storage_mode == STORAGE_BY_BRICK ){
#if MMAP_THRESHOLD > 0
     dblk->malloc_type = (dblk->total_bytes > MMAP_THRESHOLD)
                         ? DATABLOCK_MEM_MMAP : DATABLOCK_MEM_MALLOC ;
     DBLK_mmapfix(dblk) ;  /* 18 Mar 2005 */
#else
     dblk->malloc_type = DATABLOCK_MEM_MALLOC ;
#endif

     /* must be malloc-ed if:
           data is compressed,
           data is not in native byte order, or
           user explicity forbids use of mmap   */

     if( brick_ccode >= 0 || dkptr->byte_order != native_order || no_mmap )
        dblk->malloc_type = DATABLOCK_MEM_MALLOC ;
   }

   /* 30 Nov 1997: create the labels for sub-bricks */

   THD_init_datablock_labels( dblk ) ;

   atr_labs = THD_find_string_atr( dblk , ATRNAME_BRICK_LABS ) ;
   if( atr_labs != NULL && atr_labs->nch > 0 ){  /* create labels from attribute */
     int ipos = -1 , ipold , ngood ;

     for( ibr=0 ; ibr < nvals ; ibr++ ){  /* loop over bricks */

       for( ipold = ipos++ ;                                     /* skip to */
            ipos < atr_labs->nch && atr_labs->ch[ipos] != '\0' ; /* next \0 */
            ipos++ ) /* nada */ ;                                /* or end. */

       ngood = ipos - ipold - 1 ;                   /* number of good chars */
       if( ngood > 0 ){
         XtFree(dblk->brick_lab[ibr]) ;
         /* 27 Oct 2011 - increase to 64 */
         if( ngood > THD_MAX_SBLABEL ) ngood = THD_MAX_SBLABEL;  
         dblk->brick_lab[ibr] = (char *) XtMalloc(sizeof(char)*(ngood+2)) ;
         memcpy( dblk->brick_lab[ibr] , atr_labs->ch+(ipold+1) , ngood ) ;
         dblk->brick_lab[ibr][ngood] = '\0' ;

       }

        if( ipos >= atr_labs->nch ) break ;  /* nothing more to do */
     } /* end of loop over sub-bricks */
   }

   /* create the keywords for sub-bricks */

   THD_init_datablock_keywords( dblk ) ;

   atr_labs = THD_find_string_atr( dblk , ATRNAME_BRICK_KEYWORDS ) ;

   if( atr_labs != NULL && atr_labs->nch > 0 ){  /* create keywords from attribute */
     int ipos = -1 , ipold , ngood ;

     for( ibr=0 ; ibr < nvals ; ibr++ ){  /* loop over bricks */

       for( ipold = ipos++ ;                                     /* skip to */
            ipos < atr_labs->nch && atr_labs->ch[ipos] != '\0' ; /* next \0 */
            ipos++ ) /* nada */ ;                                /* or end. */

       ngood = ipos - ipold - 1 ;                   /* number of good chars */
       if( ngood > 0 ){
         XtFree(dblk->brick_keywords[ibr]) ;
         dblk->brick_keywords[ibr] = (char *) XtMalloc(sizeof(char)*(ngood+2)) ;
         memcpy( dblk->brick_keywords[ibr] , atr_labs->ch+(ipold+1) , ngood ) ;
         dblk->brick_keywords[ibr][ngood] = '\0' ;
       }

       if( ipos >= atr_labs->nch ) break ;  /* nothing more to do */
     } /* end of loop over sub-bricks */
   }

   /* create the auxiliary statistics stuff for each brick, if present */

   atr_labs = THD_find_string_atr( dblk , "BRICK_STATSYM" ) ;  /* 01 Jun 2005 */
   if( atr_labs != NULL && atr_labs->nch > 0 ){
     NI_str_array *sar ; int scode,np ; float parm[3] ;
     sar = NI_decode_string_list( atr_labs->ch , ";" ) ;
     if( sar != NULL && sar->num > 0 ){
       for( ibr=0 ; ibr < nvals && ibr < sar->num ; ibr++ ){
         NI_stat_decode( sar->str[ibr] , &scode , parm,parm+1,parm+2 ) ;
         if( scode >= AFNI_FIRST_STATCODE && scode <= AFNI_LAST_STATCODE ){
           np = NI_stat_numparam(scode) ;
           THD_store_datablock_stataux( dblk , ibr,scode,np,parm ) ;
         }
       }
       NI_delete_str_array(sar) ;
     }
   } else {          /*--- the olde way to get ye brick stataux parameters ---*/
     atr_flt = THD_find_float_atr( dblk , ATRNAME_BRICK_STATAUX ) ;
     if( atr_flt != NULL && atr_flt->nfl >= 3 ){
       int ipos=0 , iv,nv,jv ;

       /* attribute stores all stataux stuff as follows:
            sub-brick-index  statcode  no.-of-values value ... value
            sub-brick-index  statcode  no.-of-values value ... value, etc. */

       while( ipos <= atr_flt->nfl - 3 ){
         iv = (int) ( atr_flt->fl[ipos++] ) ;  /* which sub-brick */
         jv = (int) ( atr_flt->fl[ipos++] ) ;  /* statcode */
         nv = (int) ( atr_flt->fl[ipos++] ) ;  /* # of values that follow */

         if( nv > atr_flt->nfl - ipos ) nv = atr_flt->nfl - ipos ;

         THD_store_datablock_stataux( dblk , iv , jv , nv , atr_flt->fl + ipos ) ;
         ipos += nv ;
       }
     }
   }
#if 0
   if( PRINT_TRACING ){
     char str[256] ;
     sprintf(str,"rank=%d nvals=%d dim[0]=%d dim[1]=%d dim[2]=%d",
             dkptr->rank , dkptr->nvals ,
             dkptr->dimsizes[0] , dkptr->dimsizes[1] , dkptr->dimsizes[2] ) ;
     STATUS(str) ;
   }
#endif

   /*-- FDR curves [23 Jan 2008] --*/

   for( ibr=0 ; ibr < dblk->nvals ; ibr++ ){
     sprintf(name,"FDRCURVE_%06d",ibr) ;
     atr_flt = THD_find_float_atr( dblk , name ) ;
     if( atr_flt != NULL && atr_flt->nfl > 3 ){
       int nv = atr_flt->nfl - 2 ; floatvec *fv ;
       MAKE_floatvec(fv,nv) ;
       fv->x0 = atr_flt->fl[0] ; fv->dx = atr_flt->fl[1] ;
       memcpy( fv->ar , atr_flt->fl + 2 , sizeof(float)*nv ) ;
       if( dblk->brick_fdrcurve == NULL )
         dblk->brick_fdrcurve = (floatvec **)calloc(sizeof(floatvec *),dblk->nvals);
       dblk->brick_fdrcurve[ibr] = fv ;
     }
   }

   for( ibr=0 ; ibr < dblk->nvals ; ibr++ ){
     sprintf(name,"MDFCURVE_%06d",ibr) ;
     atr_flt = THD_find_float_atr( dblk , name ) ;
     if( atr_flt != NULL && atr_flt->nfl > 3 ){
       int nv = atr_flt->nfl - 2 ; floatvec *fv ;
       MAKE_floatvec(fv,nv) ;
       fv->x0 = atr_flt->fl[0] ; fv->dx = atr_flt->fl[1] ;
       memcpy( fv->ar , atr_flt->fl + 2 , sizeof(float)*nv ) ;
       if( dblk->brick_mdfcurve == NULL )
         dblk->brick_mdfcurve = (floatvec **)calloc(sizeof(floatvec *),dblk->nvals);
       dblk->brick_mdfcurve[ibr] = fv ;
     }
   }

   RETURN(1) ;
}
THD_datablock * THD_init_one_datablock( char *dirname , char *headname )
{
   THD_datablock *dblk ;
   THD_diskptr   *dkptr ;
   int ii ;
   char prefix[THD_MAX_NAME] = "\0" ;
   int default_order ;   /* 21 Jun 2000 */

ENTRY("THD_init_one_datablock") ;

   /*-- sanity checks --*/

   if( dirname  == NULL || strlen(dirname)  == 0 ||
       headname == NULL || strlen(headname) == 0   ) RETURN( NULL ) ;

   FILENAME_TO_PREFIX(headname,prefix) ;
   if( strlen(prefix) == 0 ||
       strstr(headname,DATASET_HEADER_SUFFIX) == NULL ) RETURN( NULL ) ;

   /*-- byte ordering stuff --*/

   if( native_order < 0 ) native_order = mri_short_order() ;

   no_mmap    = AFNI_yesenv("AFNI_NOMMAP") ;
   no_ordwarn = AFNI_yesenv("AFNI_NO_BYTEORDER_WARNING") ;

   { char *hh = getenv("AFNI_BYTEORDER_INPUT") ;    /* 21 Jun 2000 */
     default_order = native_order ;
     if( hh != NULL ){
       if( strncmp(hh,LSB_FIRST_STRING,ORDER_LEN) == 0 )
         default_order = LSB_FIRST ;
       else if( strncmp(hh,MSB_FIRST_STRING,ORDER_LEN) == 0 )
         default_order = MSB_FIRST ;
     }
   }

#if 1

   dblk  = EDIT_empty_datablock() ;    /* 11 Mar 2005 -- the new way */
   dkptr = dblk->diskptr ;

#else
   /*-- create output datablock (the old way) --*/

   dblk              = myXtNew( THD_datablock ) ;
   dblk->type        = DATABLOCK_TYPE ;
   dblk->brick       = NULL ;  /* will be filled in below */
   dblk->brick_bytes = NULL ;  /* ditto */
   dblk->brick_fac   = NULL ;  /* ditto */
   dblk->total_bytes = 0 ;     /* ditto */
   dblk->malloc_type = DATABLOCK_MEM_UNDEFINED ;
   dblk->parent      = NULL ;

   dblk->brick_lab      = NULL ;  /* 30 Nov 1997 */
   dblk->brick_keywords = NULL ;
   dblk->brick_statcode = NULL ;
   dblk->brick_stataux  = NULL ;

   dblk->master_nvals = 0 ;     /* 11 Jan 1999 */
   dblk->master_ival  = NULL ;
   dblk->master_bytes = NULL ;

   dblk->vedim = NULL ; /* 05 Sep 2006 */

   dblk->brick_fdrcurve = NULL ; /* 23 Jan 2008 */
   dblk->brick_mdfcurve = NULL ; /* 22 Oct 2008 */

   dblk->master_bot = 1.0 ;     /* 21 Feb 2001 */
   dblk->master_top = 0.0 ;

   DBLK_unlock(dblk) ;  /* Feb 1998 */

   dblk->shm_idcode[0] = '\0' ;  /* 02 May 2003 */

   INIT_KILL(dblk->kl) ;

   dblk->diskptr       = dkptr = myXtNew( THD_diskptr ) ;
   dkptr->type         = DISKPTR_TYPE ;
   dkptr->storage_mode = STORAGE_UNDEFINED ;
#if 0
   dkptr->byte_order   = native_order ;  /* 25 April 1998 */
#else
   dkptr->byte_order   = default_order;  /* 21 June 2000 */
#endif

   ADDTO_KILL(dblk->kl,dkptr) ;

#endif  /* end of initializing empty datablock and diskptr */

   /*-- read attributes from disk, store in the datablock --*/

   THD_read_all_atr( headname , dblk ) ;

   /*-- 09 Mar 2005: all the attribute processing is moved away --*/

   ii = THD_datablock_from_atr( dblk, dirname, headname ) ;
   if( ii == 0 ){
     THD_delete_datablock( dblk ) ;
     myXtFree(dblk) ;
     RETURN( NULL ) ;
   }

#if 0
   if( PRINT_TRACING ){
     char str[256] ;
     sprintf(str,"rank=%d nvals=%d dim[0]=%d dim[1]=%d dim[2]=%d",
             dkptr->rank , dkptr->nvals ,
             dkptr->dimsizes[0] , dkptr->dimsizes[1] , dkptr->dimsizes[2] ) ;
     STATUS(str) ;
   }
#endif

   RETURN( dblk ) ;
}
Exemple #26
0
PLUGIN_interface * ENV_init(void)
{
   PLUGIN_interface *plint ;     /* will be the output of this routine */

   char *helpstring=NULL , *ept , *eval ;
   int ii ;

   /*------- some environment variables for AFNI ------*/

   { static char buf[VAL_NMAX] = "AFNI_CWD=" ;      /* 22 Feb 2001 */
     ept = getcwd( buf+9 , VAL_NMAX-9 ) ;
     if( ept != NULL ){
        putenv(buf) ;
        ENV_add_string( "AFNI_CWD" ,
                        "Current working directory (gets output files)" ,
                        0,NULL , ENV_cwd ) ;
     }
   }

   ENV_add_string( "AFNI_ENFORCE_ASPECT" ,
                   "To make AFNI enforce image window aspect ratio?" ,
                   NUM_yesno_list , yesno_list , NULL  ) ;

   ENV_add_numeric( "AFNI_FIM_PERCENT_LIMIT" ,
                    "Upper limit on % Change in FIM" ,
                    10,1000,0,100 , NULL              ) ;

   ENV_add_numeric( "AFNI_IMAGE_MINFRAC" ,
                    "Minimum size of image window" ,
                    0,10,2,2 , NULL                 ) ;

   ENV_add_string( "AFNI_LEFT_IS_LEFT" ,
                   "To show subject's left on image left?" ,
                   NUM_yesno_list , yesno_list , ENV_leftisleft  ) ;

   ENV_add_string( "AFNI_NO_SIDES_LABELS" ,
                   "Skip showing image window left-side label?" ,
                   NUM_yesno_list , yesno_list , NULL  ) ;

   ENV_add_string( "AFNI_VIEW_ANAT_BRICK" ,
                   "Show OverLay brick whenever possible" ,
                   NUM_yesno_list , yesno_list , NULL  ) ;

   ENV_add_string( "AFNI_VIEW_FUNC_BRICK" ,
                   "Show UnderLay brick whenever possible" ,
                   NUM_yesno_list , yesno_list , NULL  ) ;

   ENV_add_string( "AFNI_ORIENT" ,
                   "Coordinate display orientation" ,
                   NUM_cord_strings,cord_strings , ENV_coorder ) ;

   ENV_add_string( "AFNI_MARKERS_NOQUAL" ,
                   "Skip markers quality checking?" ,
                   NUM_yesno_list , yesno_list , ENV_marksquality  ) ;

   ENV_add_string( "AFNI_COMPRESSOR" ,
                   "Output BRIK compression method" ,
                   NUM_COMPRESS_elist,COMPRESS_elist , ENV_compressor ) ;

   ENV_add_string( "AFNI_AUTOGZIP" ,
                   "Use gzip on output if BRIK seems highly compressible" ,
                   NUM_yesno_list , yesno_list , NULL  ) ;

#if 0
   ENV_add_string( "AFNI_BYTEORDER" ,
                   "Byte ordering for output BRIKs" ,
                   NUM_byteorder_list , byteorder_list , ENV_byteorder ) ;
#endif

#if 0
   ENV_add_string( "AFNI_NOMMAP" ,
                   "Whether to read BRIKs using mmap()" ,
                   NUM_yesno_list , yesno_list , NULL    ) ;
#endif

   ENV_add_string( "AFNI_FLOATSCAN" ,
                   "Scan floating BRIKs for errors on input?" ,
                   NUM_yesno_list , yesno_list , NULL          ) ;

#ifdef USE_SESSTRAIL
   ENV_add_numeric( "AFNI_SESSTRAIL" ,
                    "# directory levels seen in Switch Session, etc." ,
                    0,9,0,SESSTRAIL , ENV_sesstrail ) ;
#endif

   ENV_add_string( "AFNI_PBAR_IMXY" ,
                   "Sizes of 'Save to PPM' for color pbars" ,
                   0,NULL , NULL ) ;

   ENV_add_string( "AFNI_PSPRINT" ,
                   "Command to send stdin to PostScript printer" ,
                   0,NULL , NULL ) ;

   ENV_add_string( "AFNI_TRUSTHOST" ,
                   "Name of host to trust for plugouts and realtime data" ,
                   0,NULL , ENV_trusthost ) ;

   ENV_add_string( "AFNI_IMAGE_LABEL_COLOR" ,
                   "Name of color for image overlay labels" , /* 21 Sep 2001 */
                   0,NULL , NULL ) ;

   ENV_add_numeric( "AFNI_IMAGE_LABEL_SETBACK" ,
                    "Size of setback for image overlay labels" ,
                    0 , 40 , 3 , 3 , NULL ) ;

   if( SUMA_ENABLED ){
     ENV_add_string( "AFNI_SUMA_BOXCOLOR" ,                   /* 21 Sep 2001 */
                     "Color name for surface node overlays [or none]" ,
                     0,NULL , NULL ) ;

     ENV_add_numeric( "AFNI_SUMA_BOXSIZE" ,                   /* 10 Mar 2002 */
                      "Box size for surface node overlays" ,
                      1 , 10 , 1 , 2 , NULL ) ;

     ENV_add_string( "AFNI_SUMA_LINECOLOR" ,                  /* 10 Mar 2002 */
                     "Color name for surface line overlays [or none]" ,
                     0,NULL , NULL ) ;

     ENV_add_numeric( "AFNI_SUMA_LINESIZE" ,                  /* 15 Jan 2003 */
                      "Line thickness for surface intersection overlay" ,
                      0 , 30 , 3 , 0 , NULL ) ;
   }

#ifndef NO_FRIVOLITIES
   ENV_add_string( "AFNI_IMAGE_PGMFILE" ,
                   "Image file for AFNI splash window" ,
                   0,NULL , NULL ) ;
#endif

   /* 08 Aug 2001 */

   ENV_add_yesno( "AFNI_DONT_MOVE_MENUS" ,
                  "Move popup menus to enhance visibility?" ) ;

   /* 07 Mar 2002 */

   ENV_add_numeric( "AFNI_GRAPH_TEXTLIMIT" ,
                    "Max rows in Graph Button-3 popup" ,
                    1 , 99 , 0 , 40 , NULL ) ;

   /* 16 Mar 2002 */

   ENV_add_string( "AFNI_KEEP_PANNING" ,
                   "Keep 'pan' turned on in image viewers?" ,
                   NUM_yesno_list , yesno_list , NULL  ) ;

   /* 18 Mar 2002 */

   ENV_add_string( "AFNI_VALUE_LABEL" ,
                   "Turn on the Define Overlay dataset value label?" ,
                   NUM_yesno_list , yesno_list , NULL  ) ;

   /* 22 Mar 2002 */

   ENV_add_string( "AFNI_CROSSHAIR_LINES" ,
                   "Draw crosshairs with lines, not overlay voxels?" ,
                   NUM_yesno_list , yesno_list , NULL  ) ;

   /* 25 Mar 2002 */

   ENV_add_string( "AFNI_CROP_ZOOMSAVE" ,
                   "Crop zoomed images when saving to disk?" ,
                   NUM_yesno_list , yesno_list , NULL  ) ;

   /* 23 Aug 2003 */

   ENV_add_numeric( "AFNI_MAX_OPTMENU" ,
                    "Max buttons in an Option Menu" ,
                    100 , 100000 , 0 , 255 , NULL ) ;

   /* 23 Oct 2003 */

   ENV_add_numeric( "AFNI_STROKE_THRESHOLD" ,
                    "Coarseness of grayscale stroking" ,
                    8 , 99 , 0 , 32 , NULL ) ;

   ENV_add_string( "AFNI_STROKE_AUTOPLOT" ,
                   "To automatically draw grayscale-data value plot?" ,
                   NUM_yesno_list , yesno_list , NULL  ) ;

   /* 04 Nov 2003 */

   ENV_add_string( "AFNI_IMAGE_MINTOMAX" ,
                   "Set new image viewers to do min-to-max grayscaling?" ,
                   NUM_yesno_list , yesno_list , ENV_redisplay  ) ;

   ENV_add_string( "AFNI_IMAGE_GLOBALRANGE" ,
   "Set image viewers to use 3D global data range by slice, volume or dataset min-max?",
              NUM_globalrange_strings , globalrange_strings , ENV_globalrange_view  ) ;


   /* 19 Nov 2003 */

   ENV_add_numeric( "AFNI_DRAW_UNDOSIZE" ,
                    "Megabytes allowed for Drawing Undo" ,
                    1 , 999 , 0 , 6 , NULL ) ;

#if !defined(NO_FRIVOLITIES) && defined(DARWIN)
   ENV_add_yesno( "AFNI_SPEECH" , "Allow speech synthesis?" ) ; /* 03 Dec 2003 */
#endif

   ENV_add_numeric( "AFNI_VIDEO_DELAY" ,                        /* 04 Dec 2003 */
                    "Image redraw interval for 'V' or 'v' (ms)." ,
                    1,9000,0,1 , NULL              ) ;

   ENV_add_numeric( "AFNI_IMAGE_ENTROPY" ,
                    "Entropy threshold: below this, 2%-98% is off." ,
                    0,10,1,0 , NULL ) ;

   ENV_add_string( "AFNI_THRESH_LOCK" ,                           /* 06 Feb 2004 */
                   "Lock Threshold slider values together?" ,
                   NUM_threshlock_list , threshlock_list , ENV_thresh_lock  ) ;

   ENV_add_string( "AFNI_GRAPH_CX2R" ,                            /* 18 Apr 2011 */
                   "Graph display of complex time series" ,
                   NUM_cx2r_list , cx2r_list , NULL  ) ;

   ENV_add_string( "AFNI_GRAPH_BOXLAB" ,                          /* 18 Apr 2011 */
                   "Box graph display of brick labels" ,
                   NUM_boxlab_list , boxlab_list , NULL  ) ;

   ENV_add_yesno( "AFNI_PBAR_LOCK" , "Lock Color Pbars together?" ) ; /* 07 Feb 2004 */
   ENV_add_yesno( "AFNI_RANGE_LOCK", "Lock OLay Ranges together?" ) ; /* 23 Feb 2004 */

   ENV_add_yesno( "AFNI_DISP_SCROLLBARS" , "Image Disp menu get scrollbars?" ) ;

   /* 23 Feb 2004 [rickr] */
   ENV_add_yesno( "AFNI_IMAGE_ZOOM_NN" ,
	           "Use Nearest Neighbor interpolation for image Zoom?" ) ;

   /* 22 Mar 2004 [RWCox] */
   ENV_add_yesno( "AFNI_SLAVE_FUNCTIME" , "Time Index affects functional overlay?" ) ;
#if 0
   ENV_add_yesno( "AFNI_SLAVE_THRTIME"  , "Time Index affects threshold overlay?" ) ;
#endif

   ENV_add_string( "AFNI_REALTIME_MP_HOST_PORT" ,     /* 31 Mar 2004 [rickr] */
                   "Supply host:port string for realtime motion parameters." ,
                   0,NULL , NULL ) ;

   /* 07 Apr 2004 [RWCox] */
   ENV_add_yesno( "AFNI_X11_REDECORATE" , "Try to set X11 window 'decorations'?" ) ;

   /* 21 Dec 2004 [RWCox] */
   ENV_add_string( "AFNI_TITLE_LABEL2" ,
                   "Use 'label2' field for window titles?" ,
                   NUM_yesno_list , yesno_list , ENV_redraw_titles ) ;

   /* 21 Mar 2005 [RWCox] */
   ENV_add_string( "AFNI_EDGIZE_OVERLAY" ,
                   "Display color overlay as edges?" ,
                   NUM_yesno_list , yesno_list , ENV_redisplay ) ;

   /* 11 Dec 2014 [RWCox] */
   ENV_add_string( "AFNI_EDGIZE_COLOR" ,
                   "Name of color for EDGIZE+Alpha overlays." , /* 21 Sep 2001 */
                   0,NULL , NULL ) ;

   /* 08 Apr 2005 [rickr] */
   ENV_add_numeric( "AFNI_NIFTI_DEBUG" ,
                    "Set nifti_io debug level (should then do Rescan:This)" ,
                    0,5,0,0 , NULL ) ;

   /* 20 Apr 2005 [RWCox] */
   ENV_add_string( "AFNI_OVERLAY_ZERO" ,
                   "Do 0 values get color in an Overlay?" ,
                   NUM_yesno_list , yesno_list , ENV_redisplay ) ;

   /* 20 Oct 2005 [RWCox] */
   ENV_add_yesno("AFNI_TTATLAS_CAUTION","Add caution to 'Where Am I' output?");

   /* 10 May 2006 [drg] */
   ENV_add_numeric( "AFNI_JPEG_COMPRESS" ,
                    "JPEG compression quality %" ,
                    1,100,0,95 , ENV_setjpegquality ) ;

   /* 21 Feb 2007 [RWCox] */
   ENV_add_yesno( "AFNI_DATASET_BROWSE" , "Switch datasets upon selection?" ) ;

   /* 05 Mar 2007 [RWCox] */
   ENV_add_yesno( "AFNI_THRESH_AUTO" , "Reset threshold on Switch Overlay?" ) ;

   /* 18 Sep 2007 [RWCox] */
   ENV_add_string( "AFNI_IMAGE_CLIPPED" ,
                   "Set new image viewers to do clipped grayscaling?" ,
                   NUM_yesno_list , yesno_list , ENV_redisplay  ) ;

   ENV_add_numeric( "AFNI_IMAGE_CLIPBOT" ,
                    "Set clipped grayscale bottom = fraction of top default" ,
                    0,50,2,25 , ENV_redisplay ) ;

   ENV_add_numeric( "AFNI_IMAGE_CLIPTOP" ,
                    "Set clipped grayscale top = fraction of default" ,
                    60,190,2,100 , ENV_redisplay ) ;

   ENV_add_numeric( "AFNI_1DPLOT_THIK" ,
                    "Set 1dplot-style line thickness" ,
                    0,20,3,3 , NULL ) ;

#if 0
   /* 20 Dec 2007 [RWCox] */
   ENV_add_string( "AFNI_CLUSTER_PREFIX" ,
                   "Prefix for Clusterize 1D file Saves" , 0 , NULL , NULL ) ;
#endif

   /* 10 Jan 2008 [RWCox] */
   ENV_add_numeric( "AFNI_CLUSTER_REPMAX" ,
                    "Max number rows in Clusterize Rpt table" ,
                    10,99,0,15 , NULL ) ;

   /* 04 Aug 2010 [RWCox] */
   ENV_add_numeric( "AFNI_CLUSTER_WAMIMAX" ,
                    "Max clusters sent to 'whereami'" ,
                    1,99,0,20 , NULL ) ;

   /* 28 Feb 2011 [RWCox] */
   ENV_add_yesno( "AFNI_CLUSTER_EBAR" ,
                  "Error bars in Clusterize plots?" ) ;

   /* 03 Jun 2008 [RWCox] */
   ENV_add_yesno( "AFNI_IMAGE_TICK_DIV_IN_MM" ,
                  "Image tick divisions count is in mm?" ) ;

   /* 09 Feb 2009 [RWCox] */
   ENV_add_numeric( "AFNI_ANIM_DUP" ,
                    "Duplication factor for MPEG save" ,
                    1,99,0,1 , NULL ) ;

   /* 29 Apr 2009 [RWCox] */
   { static char *fsize[3] = { "Normal" , "Big" , "Small" } ;
     ENV_add_string( "AFNI_TTATLAS_FONTSIZE" ,
                     "Size of 'Where am I?' window font" ,
                     3 , fsize , NULL  ) ;
   }

   /* 11 May 2009 [RWCox] */
   ENV_add_yesno( "AFNI_INSTACORR_FDR" ,
                  "Compute FDR curve for InstaCorr correlations?" ) ;

   /* 27 Aug 2009 [RWCox] */
   ENV_add_numeric( "AFNI_IMAGE_CROPSTEP" ,
                    "Cropped image panning step size" ,
                    -9,9,0,1 , NULL ) ;

   /* 06 Oct 2010 [RWCox] */
   ENV_add_string( "AFNI_IDEAL_COLORS" ,
                   "Colors for the FIM Ideal in AFNI Graph viewer" ,
                   0,NULL , NULL ) ;
   ENV_add_string( "AFNI_ORT_COLORS" ,
                   "Colors for the FIM Ort in AFNI Graph viewer" ,
                   0,NULL , NULL ) ;

   /* 27 Jun 2011 [DRG] */
   ENV_add_numeric( "AFNI_WHEREAMI_DEC_PLACES" ,
                    "Number of decimal places for whereami output" ,
                    0,4,0,0 , NULL ) ;
   ENV_add_numeric( "AFNI_WHEREAMI_MAX_FIND" ,
                    "Maximum limit for structures from an atlas for whereami output" ,
                    1,50,0,9 , ENV_wami_maxfind ) ;
   ENV_add_string( "AFNI_WHEREAMI_MAX_SEARCH_RAD" ,
                "Maximum radius for structures from an atlas for whereami output" ,
                 0, NULL, ENV_wami_maxrad ) ;
   /* 01 Jul 2011 [DRG] */
   ENV_add_string( "AFNI_ATLAS_COLORS" ,
          "Atlas to use in Atlas colors, Draw Dataset,  Go to atlas location" ,
                 0, NULL, ENV_atlas_reset ) ;

   /* 08 Nov 2011 [RWC] */
   ENV_add_string( "AFNI_IMAGE_COLORANGLE" ,
                   "Image view color scale angle" ,
                   NUM_angle_strings,angle_strings , ENV_angle_string ) ;

   /* 23 Dec 2011 [RWC] */
   ENV_add_string( "AFNI_IMAGE_LABEL_STRING" ,
                   "Extra string for image view overlay labels" ,
                   0,NULL , NULL ) ;

   /* 21 Feb 2013 [RWC] */
   ENV_add_yesno( "AFNI_HISTOG_CUMULATIVE" ,
                  "Show cumulative histogram in plugins?" ) ;

   /* 25 Jun 2013 [RWC] */
   ENV_add_numeric( "AFNI_PBAR_TICK" ,
                    "Number of tick marks for colorscale" ,
                    0,63,0,9 , NULL ) ;

   /* 23 Jul 2013 [RWC] */
   ENV_add_yesno( "AFNI_RECENTER_VIEWING" ,
                  "Re-center xhairs when switching UnderLay?" ) ;
  
   ENV_add_string( "AFNI_JUMPTO_SPACE" ,
          "Space name to use in Jump to (spacename)" ,
                 0, NULL, ENV_jumpspace_reset ) ;

   /*--------- Sort list of variables [21 Feb 2007]  -----------*/

   if( !AFNI_yesenv("AFNI_DONT_SORT_ENVIRONMENT") )
     qsort( env_var , (size_t)NUM_env_var , sizeof(ENV_var) , ENV_compare ) ;

   /*---------------- compute helpstring -----------------------*/

   helpstring = THD_zzprintf( helpstring , "%s\n" , help_start ) ;

   for( ii=0 ; ii < NUM_env_fixed ; ii++ ){
      ept = getenv(env_fixed[ii]) ;
      if( ept == NULL )
         eval = "(Not set)" ;
      else if( ept[0] == '\0' )
         eval = "(Set to empty string)" ;
      else
         eval = ept ;
      helpstring = THD_zzprintf( helpstring, " %-25.25s= %s\n",
                                             env_fixed[ii],eval  ) ;
   }

   helpstring = THD_zzprintf( helpstring , "%s\n" , help_mid ) ;

   for( ii=0 ; ii < NUM_env_var ; ii++ ){
      helpstring = THD_zzprintf( helpstring, " %-25.25s: %s\n" ,
                                 env_var[ii].vname , env_var[ii].vhint ) ;
   }

   helpstring = THD_zzprintf( helpstring , "%s\n" , help_end ) ;

   /*---------------- set titles and call point ----------------*/

   plint = PLUTO_new_interface( "Environment" ,
                                "Environment variables control" ,
                                helpstring ,
                                PLUGIN_CALL_VIA_MENU , ENV_main  ) ;
   free(helpstring) ;

   PLUTO_add_hint( plint , "Environment variables control" ) ;

   PLUTO_set_runlabels( plint , "Set+Keep" , "Set+Close" ) ;  /* 04 Nov 2003 */

   /*--------- make interface lines: 1 for each variable -----------*/

   for( ii=0 ; ii < NUM_env_var ; ii++ ){

      PLUTO_add_option( plint ,
                        "" ,                 /* label at left of input line */
                        env_var[ii].vname ,  /* tag to return to plugin */
                        FALSE                /* is this mandatory? */
                      ) ;

      ept = getenv( env_var[ii].vname ) ;

      switch( env_var[ii].vtype ){

         default: break ;  /* should never happen */

         case ENV_NUMBER_FIXED:
         case ENV_NUMBER_EDITABLE:{
            double dval=env_var[ii].vdef ; int ival ;

            if( ept != NULL ){
               dval = strtod(ept,NULL) ;
               AV_SHIFT_VAL(-env_var[ii].vdecim,dval) ;
            }
            ival = rint(dval) ;
                 if( ival < env_var[ii].vbot ) ival = env_var[ii].vbot ;
            else if( ival > env_var[ii].vtop ) ival = env_var[ii].vtop ;

            PLUTO_add_number( plint ,
                              env_var[ii].vname ,
                              env_var[ii].vbot  ,
                              env_var[ii].vtop  ,
                              env_var[ii].vdecim,
                              ival,(env_var[ii].vtype==ENV_NUMBER_EDITABLE) ) ;
            PLUTO_add_hint( plint , env_var[ii].vhint ) ; /* 8 Apr 2005 rickr */
         }
         break ;

         case ENV_STRING:{
            if( env_var[ii].vcount <= 0 ){
               PLUTO_add_string( plint ,
                                 env_var[ii].vname ,
                                 0 , &ept , NAME_NMAX ) ;
               PLUTO_add_hint( plint , env_var[ii].vhint ) ;
            } else {
               int dval , jj ;
               char ** sval ;

               dval = 1 + PLUTO_string_index( ept , env_var[ii].vcount ,
                                                    env_var[ii].vlist   ) ;

               sval = (char **) malloc( sizeof(char *)*(1+env_var[ii].vcount) ) ;
               sval[0] = "(Not set)" ;
               for( jj=0 ; jj < env_var[ii].vcount ; jj++ )
                  sval[jj+1] = env_var[ii].vlist[jj] ;

               PLUTO_add_string( plint ,
                                 env_var[ii].vname  ,
                                 1+env_var[ii].vcount , sval , dval ) ;
               PLUTO_add_hint( plint , env_var[ii].vhint ) ;
               free(sval) ;
            }
         }
         break ;
      } /* end of switch over variable type */

   } /* end of loop over variables */

   /*--------- done with interface setup ---------*/

   return plint ;
}