Logo Search packages:      
Sourcecode: caret version File versions  Download package

BrainSet.cxx

/*LICENSE_START*/
/*
 *  Copyright 1995-2002 Washington University School of Medicine
 *
 *  http://brainmap.wustl.edu
 *
 *  This file is part of CARET.
 *
 *  CARET is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 2 of the License, or
 *  (at your option) any later version.
 *
 *  CARET is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with CARET; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 *
 */
/*LICENSE_END*/


#include <QGlobalStatic>
#include <QMutexLocker>
#include <QTextStream>
#include <QTimer>

#include <algorithm>
#include <cstdlib>
#include <iostream>
#include <limits>
#include <set>
#include <sstream>

#include <QApplication>
#include <QDateTime>
#include <QDir>
#include <QGLWidget>
#include <QProgressDialog>

#include "vtkActor.h"
#include "vtkMath.h"
#include "vtkPolyDataMapper.h"
#include "vtkPointData.h"
#include "vtkRenderer.h"
#include "vtkRenderWindow.h"
#include "vtkVRMLExporter.h"

#define __BRAIN_SET_MAIN__
#include "BrainSet.h"
#undef __BRAIN_SET_MAIN__

#include "AreaColorFile.h"
#include "ArealEstimationFile.h"
#include "AtlasSurfaceDirectoryFile.h"
#include "BorderColorFile.h"
#include "BorderFile.h"
#include "BorderProjectionFile.h"
#include "BorderProjectionUnprojector.h"
#include "BrainModelBorderSet.h"
#include "BrainModelContours.h"
#include "BrainModelIdentification.h"
#include "BrainModelSurfaceAndVolume.h"
#include "BrainModelSurfaceCurvature.h"
#include "BrainModelSurfaceNodeColoring.h"
#include "BrainModelSurfaceROINodeSelection.h"
#include "BrainModelSurfaceResection.h"
#include "BrainModelVolume.h"
#include "BrainModelVolumeToSurfaceConverter.h"
#include "BrainModelVolumeVoxelColoring.h"
#include "BrainModelVolumeRegionOfInterest.h"
#include "BrainSetMultiThreadedSpecFileReader.h"
#include "BrainSetAutoLoaderManager.h"
#include "BrainVoyagerFile.h"
#include "CellColorFile.h"
#include "CellFile.h"
#include "CellProjectionFile.h"
#include "CellProjectionUnprojector.h"
#include "CocomacConnectivityFile.h"
#include "ColorFile.h"
#include "ContourCellColorFile.h"
#include "ContourCellFile.h"
#include "ContourFile.h"
#include "CutsFile.h"
#include "DebugControl.h"
#include "DeformationFieldFile.h"
#include "DeformationMapFile.h"
#include "DisplaySettingsArealEstimation.h"
#include "DisplaySettingsBorders.h"
#include "DisplaySettingsCells.h"
#include "DisplaySettingsContours.h"
#include "DisplaySettingsCuts.h"
#include "DisplaySettingsCoCoMac.h"
#include "DisplaySettingsDeformationField.h"
#include "DisplaySettingsFoci.h"
#include "DisplaySettingsGeodesicDistance.h"
#include "DisplaySettingsImages.h"
#include "DisplaySettingsMetric.h"
#include "DisplaySettingsModels.h"
#include "DisplaySettingsSection.h"
#include "DisplaySettingsSurface.h"
#include "DisplaySettingsPaint.h"
#include "DisplaySettingsProbabilisticAtlas.h"
#include "DisplaySettingsRgbPaint.h"
#include "DisplaySettingsScene.h"
#include "DisplaySettingsStudyMetaData.h"
#include "DisplaySettingsSurfaceShape.h"
#include "DisplaySettingsVectors.h"
#include "DisplaySettingsTopography.h"
#include "DisplaySettingsVolume.h"
#include "DisplaySettingsWustlRegion.h"
#include "FileUtilities.h"
#include "FociColorFile.h"
#include "FociFile.h"
#include "FociProjectionFile.h"
#include "FociSearchFile.h"
#include "GeodesicDistanceFile.h"
#include "ImageFile.h"
#include "LatLonFile.h"
#include "MDPlotFile.h"
#include "MetricFile.h"
#include "MniObjSurfaceFile.h"
#include "NeurolucidaFile.h"
#include "PaintFile.h"
#include "PaletteFile.h"
#include "ParamsFile.h"
#include "ProbabilisticAtlasFile.h"
#include "RgbPaintFile.h"
#include "SceneFile.h"
#include "SectionFile.h"
#include "StatisticRandomNumber.h"
#include "StringUtilities.h"
#include "StudyCollectionFile.h"
#include "StudyMetaDataFile.h"
#include "SurfaceShapeFile.h"
#include "TopographyFile.h"
#include "TopologyFile.h"
#include "TopologyHelper.h"
#include "TransformationMatrixFile.h"
#include "VectorFile.h"
#include "VocabularyFile.h"
#include "VtkModelFile.h"
#include "WustlRegionFile.h"

#include "vtkBYUReader.h"
#include "vtkBYUWriter.h"
#include "vtkFieldData.h"
#include "vtkIVWriter.h"
#include "vtkLight.h"
#include "vtkOBJExporter.h"
#include "vtkPolyDataNormals.h"
#include "vtkPolyDataReader.h"
#include "vtkPolyDataWriter.h"
#include "vtkSTLReader.h"
#include "vtkSTLWriter.h"
#include "vtkUnsignedCharArray.h"
#include "vtkXMLPolyDataReader.h"
#include "vtkXMLPolyDataWriter.h"

/**
 * The Constructor.
 */
00167 BrainSet::BrainSet(const bool primaryBrainSetFlagIn)
{
   constructBrainSet();
   primaryBrainSetFlag = primaryBrainSetFlagIn;
}

/**
 * Construct a brain set from a vtk surface file.
 */
00176 BrainSet::BrainSet(const QString& vtkSurfaceFileName,
                   const BrainModelSurface::SURFACE_TYPES surfaceType,
                   const TopologyFile::TOPOLOGY_TYPES topologyType)
{
   constructBrainSet();
   
   try {
      importVtkSurfaceFile(vtkSurfaceFileName,
                           true,   // import coords
                           true,   // import topology
                           true,   // import colors
                           surfaceType,
                           topologyType);
   }
   catch (FileException& e) {
      std::cout << "Error constructing brain set from VTK file: "
                << e.whatQString().toAscii().constData() << std::endl;
   }
}
      
/**
 * Construct a brain set from a topology file and a coordinate file.
 * For success, check to see if there is one brain model surface.
 */
00200 BrainSet::BrainSet(const QString& topoFileName,
                   const QString& coordFileName1,
                   const QString& coordFileName2,
                   const bool primaryBrainSetFlagIn)
{
   constructBrainSet();
   primaryBrainSetFlag = primaryBrainSetFlagIn;
   
   //
   // Create a spec file with the two files
   //
   SpecFile sf;
   std::vector<QString> coordFileNames;
   coordFileNames.push_back(coordFileName1);
   coordFileNames.push_back(coordFileName2);
   sf.setTopoAndCoordSelected(topoFileName, 
                              coordFileNames,
                              getStructure());
   
   //
   // Read the spec file
   //
   std::vector<QString> messages;
   readSpecFile(SPEC_FILE_READ_MODE_NORMAL, sf, "", messages, NULL, NULL);
   if (messages.empty() == false) {
      for (unsigned int i = 0; i < messages.size(); i++) {
         std::cout << "BrainSet construction error: "
                   << messages[i].toAscii().constData()
                   << std::endl;
      }
   }
   
   //
   // As a result of this call, the block of code below is probably unnecessary
   //
   setIgnoreTopologyFileInCoordinateFileHeaderFlag(true);
   
   //
   // Some coordinate files have a topology file name listed in the header
   // which causes the topology file to be loaded and assigned to the 
   // coordinate file.  So, force the topology file to the file passed to
   // this constructor.
   //
   if ((getNumberOfBrainModels() > 0) &&
       (getNumberOfTopologyFiles() > 0)) {
      //
      // loop through topology files
      //
      for (int i = 0; i < getNumberOfTopologyFiles(); i++) {
         //
         // Get the topology file and its name
         //
         TopologyFile* topoFile = getTopologyFile(i);
         const QString topoName = topoFile->getFileName();
         
         //
         // Is this the topology file that was passed to this constructor?
         //
         if (FileUtilities::basename(topoName) == FileUtilities::basename(topoFileName)) {
            //
            // Make all surfaces use the topology file
            //
            for (int j = 0; j < getNumberOfBrainModels(); j++) {
               BrainModelSurface* bms = getBrainModelSurface(j);
               if (bms != NULL) {
                  bms->setTopologyFile(topoFile);
               }
            }
            
            break;
         }
      }
   }
   
   //
   // Structure needs to be set
   //
   for (int i = 0; i < getNumberOfBrainModels(); i++) {
      const BrainModelSurface* bms = getBrainModelSurface(i);
      if (bms != NULL) {
         if (bms->getStructure().getType() != Structure::STRUCTURE_TYPE_INVALID) {
            setStructure(bms->getStructure());
            break;
         }
      }
   }
   
   updateDefaultFileNamePrefix();
}               

/**
 * Construct a brain set from all files in a spec file.
 * For success, check to see if there is one brain model surface.
 */
00294 BrainSet::BrainSet(const QString& specFileNameIn, 
                   const bool readAllFilesInSpecFile,
                   const bool primaryBrainSetFlagIn)
{
   constructBrainSet();
   primaryBrainSetFlag = primaryBrainSetFlagIn;
   
   //
   // Create and read spec file
   //
   SpecFile sf;
   try {
      sf.readFile(specFileNameIn);
   }
   catch (FileException&) {
      //return;
   }
   if (readAllFilesInSpecFile) {
      sf.setAllFileSelections(SpecFile::SPEC_TRUE);
   }
   else {
      sf.setAllFileSelections(SpecFile::SPEC_FALSE);
   }
   
   //
   // Read the spec file
   //
   std::vector<QString> messages;
   readSpecFile(SPEC_FILE_READ_MODE_NORMAL, sf, specFileNameIn, messages, NULL, NULL);
}               

/**
 * construct the brain set.
 */
void 
00329 BrainSet::constructBrainSet()
{
   specFileTimeOfLoading = QDateTime::currentDateTime();
   
   webCaretFlag = false;
   readingSpecFileFlag = false;
   ignoreTopologyFileInCoordinateFileHeaderFlag = false;
   numberOfSurfaceOverlays = 4;
   
   initializeStaticStuff();
   
   primaryBrainSetFlag = false;

   progressDialogParent = NULL;
   
   numNodesMessage = "Contains different number of nodes than ";   
   
   areaColorFile          = new AreaColorFile;
   arealEstimationFile    = new ArealEstimationFile;
   borderColorFile        = new BorderColorFile;
   cellColorFile          = new CellColorFile;
   cellProjectionFile     = new CellProjectionFile;
   volumeCellFile         = new CellFile;
   cocomacFile            = new CocomacConnectivityFile;
   contourCellFile        = new ContourCellFile;
   contourCellColorFile   = new ContourCellColorFile;
   cutsFile               = new CutsFile;
   deformationFieldFile   = new DeformationFieldFile;
   fociColorFile          = new FociColorFile;
   fociProjectionFile     = new FociProjectionFile;
   fociSearchFile         = new FociSearchFile;
   geodesicDistanceFile   = new GeodesicDistanceFile;
   latLonFile             = new LatLonFile;
   metricFile             = new MetricFile;
   probabilisticAtlasSurfaceFile = new ProbabilisticAtlasFile;
   paintFile              = new PaintFile;
   paletteFile            = new PaletteFile;
   paramsFile             = new ParamsFile;
   rgbPaintFile           = new RgbPaintFile;
   sceneFile              = new SceneFile;
   sectionFile            = new SectionFile;
   studyCollectionFile    = new StudyCollectionFile;
   studyMetaDataFile      = new StudyMetaDataFile;
   surfaceShapeFile       = new SurfaceShapeFile;
   topographyFile         = new TopographyFile;
   transformationMatrixFile = new TransformationMatrixFile;
   vocabularyFile         = new VocabularyFile;
   wustlRegionFile        = new WustlRegionFile;
      
   brainModelBorderSet    = new BrainModelBorderSet(this);
   
   brainModelIdentification       = new BrainModelIdentification(this);
   brainSetAutoLoaderManager     = new BrainSetAutoLoaderManager(this);

   nodeColoring                   = new BrainModelSurfaceNodeColoring(this);
   voxelColoring                  = new BrainModelVolumeVoxelColoring(this);
   brainModelSurfaceRegionOfInterestNodeSelection = new BrainModelSurfaceROINodeSelection(this);
   brainModelVolumeRegionOfInterest = new BrainModelVolumeRegionOfInterest(this);
   displaySettingsArealEstimation = new DisplaySettingsArealEstimation(this);
   displaySettingsBorders         = new DisplaySettingsBorders(this);
   displaySettingsContours      = new DisplaySettingsContours(this);
   displaySettingsDeformationField = new DisplaySettingsDeformationField(this);
   displaySettingsGeodesicDistance = new DisplaySettingsGeodesicDistance(this);
   displaySettingsImages          = new DisplaySettingsImages(this);
   displaySettingsMetric          = new DisplaySettingsMetric(this);
   displaySettingsModels          = new DisplaySettingsModels(this);
   displaySettingsSection         = new DisplaySettingsSection(this);
   displaySettingsSurface         = new DisplaySettingsSurface(this);
   displaySettingsPaint           = new DisplaySettingsPaint(this);
   displaySettingsProbabilisticAtlasSurface = new DisplaySettingsProbabilisticAtlas(this,
                                 DisplaySettingsProbabilisticAtlas::PROBABILISTIC_TYPE_SURFACE);
   displaySettingsRgbPaint        = new DisplaySettingsRgbPaint(this);
   displaySettingsScene           = new DisplaySettingsScene(this);
   displaySettingsStudyMetaData   = new DisplaySettingsStudyMetaData(this);
   displaySettingsSurfaceShape    = new DisplaySettingsSurfaceShape(this);
   displaySettingsVectors         = new DisplaySettingsVectors(this);
   displaySettingsCells           = new DisplaySettingsCells(this);
   displaySettingsCoCoMac         = new DisplaySettingsCoCoMac(this);
   displaySettingsCuts            = new DisplaySettingsCuts(this);
   displaySettingsFoci            = new DisplaySettingsFoci(this);
   displaySettingsTopography      = new DisplaySettingsTopography(this);
   displaySettingsVolume          = new DisplaySettingsVolume(this);
   displaySettingsWustlRegion     = new DisplaySettingsWustlRegion(this);
   displaySettingsProbabilisticAtlasVolume = new DisplaySettingsProbabilisticAtlas(this,
                                 DisplaySettingsProbabilisticAtlas::PROBABILISTIC_TYPE_VOLUME);
   
   for (int i = 0; i < getNumberOfSurfaceOverlays(); i++) {
      surfaceOverlays.push_back(new BrainModelSurfaceOverlay(this, i));
   }
   
   reset();   
   
   //
   // load the splash image
   //
   QString imageName(getCaretHomeDirectory());
   imageName.append(QDir::separator());
   imageName.append("data_files"); 
   imageName.append(QDir::separator());
   imageName.append("images"); 
   imageName.append(QDir::separator());
   imageName.append("caret5"); 
   QString jpegImageName(imageName);
   jpegImageName.append(".jpg");
   displaySplashImage = readImage(jpegImageName, "JPEG", splashImage);
   if (displaySplashImage == false) {
      QString pngImageName(imageName);
      pngImageName.append(".png");
      displaySplashImage = readImage(pngImageName, "PNG", splashImage);
/*
      if (displaySplashImage == false) {
         QString msg("Unable to open splash image files ");
         msg.append(jpegImageName);
         msg.append(" or ");
         msg.append(pngImageName);
         msg.append(".  CARET5_HOME may not be set correctly.");
         std::cerr << msg << std::endl;
      }
*/
   }
   
   displayCrossTimer = new QTimer(this);
   QObject::connect(displayCrossTimer, SIGNAL(timeout()),
                    this, SLOT(slotDisplayCrossTimerTimeout()));
}

/**
 * called when cross timer timesout.
 */
00458 void BrainSet::slotDisplayCrossTimerTimeout()
{
   setDisplayCrossForNode(-1, NULL);
   clearAllDisplayLists(); 
   emit signalGraphicsUpdate(this);
}
      
/**
 * set display cross for node.
 */
void 
00469 BrainSet::setDisplayCrossForNode(const int node, BrainModelSurface* surface) 
{ 
   displayCrossForNode = node; 
   displayNoCrossForSurface = surface; 
   if (displayCrossTimer->isActive()) {
      displayCrossTimer->stop();
   }
   if (node >= 0) {
      displayCrossTimer->setSingleShot(true);
      displayCrossTimer->start(2000);
   }
   clearAllDisplayLists(); 
}
           
/**
 * get the name of the bin directory.
 */
QString 
00487 BrainSet::getBinDirectoryName()
{
   QString binName("bin_other");
#ifdef  Q_OS_WIN32
   binName = "bin_windows";
#endif
#ifdef  Q_OS_FREEBSD
   binName = "bin_freebsd";
#endif
#ifdef  Q_OS_UNIX
   binName = "bin_linux";
#endif
#ifdef Q_OS_MACX
   binName = "bin_macosx";
#endif

   return binName;
}

/**
 * set the random seed.
 */
void 
00510 BrainSet::setRandomSeed(unsigned int randomSeed)
{
   StatisticRandomNumber::setRandomSeed(randomSeed);
}      

/**
 * get caret's home directory.
 */
QString 
00519 BrainSet::getCaretHomeDirectory() 
{ 
   static QString caretHomeDirectory;
   
   if (caretHomeDirectory.isEmpty()) {
      const char* caretHome = getenv("CARET5_HOME");
      if (caretHome != NULL) {
         caretHomeDirectory = caretHome;
      }
      else {
         caretHomeDirectory = qApp->applicationDirPath();
         if (caretHomeDirectory.isEmpty() == false) {
            caretHomeDirectory = FileUtilities::dirname(caretHomeDirectory);
#ifdef Q_OS_MACX
            const bool appFlag = (caretHomeDirectory.indexOf(".app/") > 0);
            if (appFlag) {
               caretHomeDirectory = FileUtilities::dirname(caretHomeDirectory);
               caretHomeDirectory = FileUtilities::dirname(caretHomeDirectory);
               caretHomeDirectory = FileUtilities::dirname(caretHomeDirectory);
            }
#endif
         }
      }

      if (DebugControl::getDebugOn()) {    
         std::cout << "Caret Home Directory: " << caretHomeDirectory.toAscii().constData() << std::endl;
      }
   }
   
   return caretHomeDirectory;
}
      
/**
 * get the preferences file.
 */
PreferencesFile*
00555 BrainSet::getPreferencesFile() {
   if (preferencesFile == NULL) {
       QString preferencesFileName = QDir::homePath();
       if (preferencesFileName.isEmpty() == false) {
          preferencesFileName.append("/");
       }
       preferencesFileName.append(".caret5_preferences");

       preferencesFile = new PreferencesFile;
       try {
          preferencesFile->readFile(preferencesFileName);
       }
       catch (FileException) {
       }
       preferencesFile->setFileName(preferencesFileName);
   }

   return preferencesFile;
}

/**
 * Read the user's caret5 preferences file and intialize other things.
 */
void
00579 BrainSet::initializeStaticStuff()
{
   if (staticStuffInitialized) {
      return;
   }
   staticStuffInitialized = true;

   //
   // Might be set at command line
   //
   const bool debugOn = DebugControl::getDebugOn();

   try {
      AbstractFile::setTextFileDigitsRightOfDecimal(
          getPreferencesFile()->getTextFileDigitsRightOfDecimal());
      AbstractFile::setPreferredWriteType(
          getPreferencesFile()->getPreferredWriteDataType());
   }
   catch (FileException& /*e*/) {
      //std::cerr << "Warning: reading caret preferences file: "
      //          << e.whatQString() << std::endl;
   }

   //
   // Random seed generator
   //
   if (getPreferencesFile()->getRandomSeedOverride()) {
      //
      // Use seed provided by user
      //
      setRandomSeed(getPreferencesFile()->getRandomSeedOverrideValue());
   }
   else {
      //
      // Use number of seconds since 1970
      //
      setRandomSeed(QDateTime::currentDateTime().toTime_t());
   }
   
   if (debugOn) {
      DebugControl::setDebugOn(true);
   }
}

/**
 * The destructor.
 */
00626 BrainSet::~BrainSet()
{
   reset();
   
   delete displayCrossTimer;
   displayCrossTimer = NULL;
   
   displayCrossForNode = -1;
   displayNoCrossForSurface = NULL;
   
   delete areaColorFile;
   delete arealEstimationFile;
   delete borderColorFile;
   delete cellColorFile;
   delete cellProjectionFile;
   delete volumeCellFile;
   delete cocomacFile;
   delete contourCellFile;
   delete contourCellColorFile;
   delete cutsFile;
   delete deformationFieldFile;
   delete fociColorFile;
   delete fociProjectionFile;
   delete geodesicDistanceFile;
   delete latLonFile;
   delete metricFile;
   delete probabilisticAtlasSurfaceFile;
   delete paintFile;
   delete paletteFile;
   delete paramsFile;
   delete rgbPaintFile;
   delete sceneFile;
   delete sectionFile;
   delete studyCollectionFile;
   delete studyMetaDataFile;
   delete surfaceShapeFile;
   delete topographyFile;
   delete transformationMatrixFile;
   delete vocabularyFile;
   delete wustlRegionFile;
   
   delete brainModelBorderSet;

   delete brainSetAutoLoaderManager;
   delete brainModelIdentification;
   delete nodeColoring;
   delete voxelColoring;
   delete brainModelVolumeRegionOfInterest;
   delete brainModelSurfaceRegionOfInterestNodeSelection;
   delete displaySettingsArealEstimation;  
   delete displaySettingsBorders;
   delete displaySettingsDeformationField;
   delete displaySettingsGeodesicDistance;
   delete displaySettingsImages;
   delete displaySettingsMetric;
   delete displaySettingsModels;
   delete displaySettingsSection;
   delete displaySettingsSurface;
   delete displaySettingsPaint;
   delete displaySettingsProbabilisticAtlasSurface;
   delete displaySettingsRgbPaint;  
   delete displaySettingsScene;
   delete displaySettingsStudyMetaData;
   delete displaySettingsSurfaceShape;  
   delete displaySettingsVectors;
   delete displaySettingsCells;
   delete displaySettingsCoCoMac;
   delete displaySettingsContours;
   delete displaySettingsCuts;
   delete displaySettingsFoci;
   delete displaySettingsTopography;
   delete displaySettingsVolume;
   delete displaySettingsProbabilisticAtlasVolume;
   delete displaySettingsWustlRegion;
}

/**
 * get the primary surface overlay.
 */
BrainModelSurfaceOverlay* 
00706 BrainSet::getPrimarySurfaceOverlay()
{
   return getSurfaceOverlay(getNumberOfSurfaceOverlays() - 1);
}

/**
 * get the primary surface overlay (const method).
 */
const BrainModelSurfaceOverlay* 
00715 BrainSet::getPrimarySurfaceOverlay() const
{
   return getSurfaceOverlay(getNumberOfSurfaceOverlays() - 1);
}

/**
 * get the secondary surface overlay.
 */
BrainModelSurfaceOverlay* 
00724 BrainSet::getSecondarySurfaceOverlay()
{
   return getSurfaceOverlay(getNumberOfSurfaceOverlays() - 2);
}

/**
 * get the secondary surface overlay (const method).
 */
const BrainModelSurfaceOverlay* 
00733 BrainSet::getSecondarySurfaceOverlay() const
{
   return getSurfaceOverlay(getNumberOfSurfaceOverlays() - 2);
}

/**
 * get the surface underlay.
 */
BrainModelSurfaceOverlay* 
00742 BrainSet::getSurfaceUnderlay()
{
   return getSurfaceOverlay(0);
}

/**
 * get the surface underlay (const method).
 */
const BrainModelSurfaceOverlay* 
00751 BrainSet::getSurfaceUnderlay() const
{
   return getSurfaceOverlay(0);
}
      
/**
 * get something is an overlay for any model.
 */
bool 
00760 BrainSet::isASurfaceOverlayForAnySurface(const BrainModelSurfaceOverlay::OVERLAY_SELECTIONS os) const
{
   for (int i = 0; i < getNumberOfSurfaceOverlays(); i++) {
      for (int m = 0; m < getNumberOfBrainModels(); m++) {
         if (getBrainModelSurface(m) != NULL) {
            if (getSurfaceOverlay(i)->getOverlay(m) == os) {
               return true;
            }
         }
      }
   }
   
   return false;
}
      
/**
 * get something is an overlay.
 */
bool 
00779 BrainSet::isASurfaceOverlay(const int modelIn,
                     const BrainModelSurfaceOverlay::OVERLAY_SELECTIONS os) const
{
   int model = modelIn;
   if (model < 0) {
      model = 0;
   }
   
   for (int i = 0; i < getNumberOfSurfaceOverlays(); i++) {
      if (getSurfaceOverlay(i)->getOverlay(model) == os) {
         return true;
      }
   }
   
   return false;
}
      
/**
 * copy the overlay selections from specified surface to all other surfaces.
 */
void 
00800 BrainSet::copyOverlaysFromSurface(const int surfaceModelIndex)
{
   for (int i = 0; i < getNumberOfSurfaceOverlays(); i++) {
      getSurfaceOverlay(i)->copyOverlaysFromSurface(surfaceModelIndex);
   }
}
      
/**
 * update the surface overlays due to change in brain models.
 */
void 
00811 BrainSet::updateSurfaceOverlaysDueToChangeInBrainModels()
{
   for (int i = 0; i < getNumberOfSurfaceOverlays(); i++) {
      getSurfaceOverlay(i)->update();
   }
}
      
/**
 * apply all projected files (foci, cells, borders).
 */
void 
00822 BrainSet::applyAllProjectedFiles()
{
   //
   // Unproject all borders
   //
   brainModelBorderSet->unprojectBordersForAllSurfaces();
}

/**
 * Clear all display list.
 */
void
00834 BrainSet::clearAllDisplayLists()
{
   const int num = getNumberOfBrainModels();
   
   //
   //  Clear all surface display lists
   //
   for (int i = 0; i < num; i++) {
      BrainModelSurface* bms = getBrainModelSurface(i);
      if (bms != NULL) {
         CoordinateFile* cf = bms->getCoordinateFile();
         cf->clearDisplayList();
      }
   }
   
   //
   // Clear surface and volume voxel cloud display list
   //
   BrainModelSurfaceAndVolume* bmsv = getBrainModelSurfaceAndVolume();
   if (bmsv != NULL) {
      CoordinateFile* cf = bmsv->getCoordinateFile();
      cf->clearDisplayList();
      bmsv->clearVoxelCloudDisplayList();
   }
   
   for (int i = 0; i < getNumberOfTopologyFiles(); i++) {
      topologyFiles[i]->clearDisplayList();
   }
   
   arealEstimationFile->clearDisplayList();
   
   areaColorFile->clearDisplayList();
   borderColorFile->clearDisplayList();
   cellColorFile->clearDisplayList();
   cellProjectionFile->clearDisplayList();
   volumeCellFile->clearDisplayList();
   fociColorFile->clearDisplayList();
   fociProjectionFile->clearDisplayList();
   fociSearchFile->clearDisplayList();
   cocomacFile->clearDisplayList();
   cutsFile->clearDisplayList();
   deformationFieldFile->clearDisplayList();
   geodesicDistanceFile->clearDisplayList();
   for (int i = 0; i < getNumberOfImageFiles(); i++) {
      imageFiles[i]->clearDisplayList();
   }
   latLonFile->clearDisplayList();
   metricFile->clearDisplayList();
   paintFile->clearDisplayList();
   paletteFile->clearDisplayList();
   paramsFile->clearDisplayList();
   probabilisticAtlasSurfaceFile->clearDisplayList();
   rgbPaintFile->clearDisplayList();
   sectionFile->clearDisplayList();
   studyCollectionFile->clearDisplayList();
   studyMetaDataFile->clearDisplayList();
   surfaceShapeFile->clearDisplayList();
   topographyFile->clearDisplayList();
   for (int i = 0; i < getNumberOfVtkModelFiles(); i++) {
      vtkModelFiles[i]->clearDisplayList();
   }
   for (int i = 0; i < getNumberOfTransformationDataFiles(); i++) {
      transformationDataFiles[i]->clearDisplayList();
   }
   vocabularyFile->clearDisplayList();
   wustlRegionFile->clearDisplayList();
}

/**
 * Delete all of the brain models
 */
void
00906 BrainSet::deleteAllBrainModels()
{
   deleteAllTopologyFiles();
   
   clearVolumeAnatomyFiles();
   clearVolumeFunctionalFiles();
   clearVolumePaintFiles();
   clearVolumeProbabilisticAtlasFiles();
   clearVolumeRgbFiles();
   clearVolumeSegmentationFiles();
   clearVolumeVectorFiles();
   
   for (unsigned int i = 0; i < brainModels.size(); i++) {
      if (brainModels[i] != NULL) {
         delete brainModels[i];
         brainModels[i] = NULL;
      }
   }
   brainModels.clear();

   updateDisplayedModelIndices();   
}

/**
 * Reset the brain surface.  Typically used prior to loading new files.
 */
void
00933 BrainSet::reset(const bool keepSceneData)
{
   for (int i = 0; i < BrainModel::NUMBER_OF_BRAIN_MODEL_VIEW_WINDOWS; i++) {
      displayedModelIndices[i] = 0;
   }
   
   SpecFile::Entry savedSceneFile = loadedFilesSpecFile.sceneFile;
   loadedFilesSpecFile.clear();
   specFileName = "";
   
   specDataFileTransformationMatrix.identity();
   
   stereotaxicSpace.reset();
   species.reset();
   setSubject("");
   
   deleteAllBrainModels();
   
   resetDataFiles(keepSceneData, false);
   if (keepSceneData) {
      loadedFilesSpecFile.sceneFile = savedSceneFile;
   }
   
   deleteAllBorders();

   brainSetAutoLoaderManager->reset();
   displaySettingsArealEstimation->reset();  
   displaySettingsBorders->reset();
   displaySettingsDeformationField->reset();
   displaySettingsGeodesicDistance->reset();
   displaySettingsImages->reset();
   displaySettingsMetric->reset();
   displaySettingsModels->reset();
   displaySettingsSection->reset();
   displaySettingsSurface->reset();
   displaySettingsPaint->reset();
   displaySettingsProbabilisticAtlasSurface->reset();
   displaySettingsRgbPaint->reset();  
   if (keepSceneData == false) {
      displaySettingsScene->reset();
   }
   displaySettingsStudyMetaData->reset();
   displaySettingsSurfaceShape->reset();  
   displaySettingsVectors->reset();
   displaySettingsCells->reset();
   displaySettingsCoCoMac->reset();
   displaySettingsContours->reset();
   displaySettingsCuts->reset();
   displaySettingsFoci->reset();
   displaySettingsTopography->reset();
   displaySettingsVolume->reset();
   displaySettingsProbabilisticAtlasVolume->reset();
   displaySettingsWustlRegion->reset();
   
   //resetNodeAttributeFiles();
   
   resetNodeAttributes();
   structure = Structure::STRUCTURE_TYPE_INVALID;
   
   activeFiducialSurface = NULL;
   leftFiducialVolumeInteractionSurface = NULL;
   rightFiducialVolumeInteractionSurface = NULL;
   cerebellumFiducialVolumeInteractionSurface = NULL;
   
   cerebralHullFileName = "";
   deleteAllImageFiles();
   deleteAllVtkModelFiles();
   
   nodesHaveBeenClassified = false;
   
   displayAllNodesFlag = true;
}

/**
 * Reset data files.
 */
void
01010 BrainSet::resetDataFiles(const bool keepSceneData,
                         const bool keepFociAndFociColorsAndStudyMetaData)
{
   deleteAllBorders();

   clearCocomacConnectivityFile();
   clearContourCellFile();
   clearContourCellColorFile();
   clearCutsFile();
   clearAreaColorFile();
   clearParamsFile();
   if (keepSceneData == false) {
      sceneFile->clear();
   }
   
   clearPaletteFile();
   paletteFile->addDefaultPalettes();
   paletteFile->clearModified();
   
   clearVectorFiles();

   clearBorderColorFile();
   
   clearCellColorFile();
   deleteAllCells(true, true);
   
   if (keepFociAndFociColorsAndStudyMetaData == false) {
      clearFociColorFile();
      deleteAllFociProjections();
      clearFociSearchFile();
      fociSearchFile->addDefaultSearch();
   }
   
   if (keepFociAndFociColorsAndStudyMetaData == false) {
      clearStudyCollectionFile();
      clearStudyMetaDataFile();
   }
   
   clearVocabularyFile();
   
   clearTransformationMatrixFile();
   
   clearTransformationDataFiles();
   
   deleteAllImageFiles();
   deleteAllVtkModelFiles();
   
   resetNodeAttributeFiles();
}

/** 
 * Reset node attribute files
 */
void
01064 BrainSet::resetNodeAttributeFiles()
{
   clearArealEstimationFile();
   arealEstimationFile->clearModified();
   deformationMapFileName = "";
   
   clearDeformationFieldFile();
   deformationFieldFile->clearModified();
   
   clearLatLonFile();
   clearSectionFile();
   
   clearMetricFile();
   metricFile->clearModified();
   clearProbabilisticAtlasFile();
   probabilisticAtlasSurfaceFile->clearModified();
   clearPaintFile();
   paintFile->clearModified();
   clearRgbPaintFile();
   rgbPaintFile->clearModified();
   
   clearSurfaceShapeFile();
   surfaceShapeFile->clearModified();
   
   clearTopographyFile();
   topographyFile->clearModified();
   
}

/** 
 * initialize data file static members
 */
void 
01097 BrainSet::initializeDataFileStaticMembers()
{
}

/**
 * Get the model for a window from a scene.
 */
BrainModel* 
01105 BrainSet::showSceneGetBrainModel(const int sceneIndex,
                                 const int viewingWindowNumberIn,
                                 int geometryOut[4],
                                 int glWidthHeightOut[2],
                                 bool& yokeOut,
                                 QString& errorMessageOut)
{
   SceneFile* sf = getSceneFile();
   if ((sceneIndex >= 0) && (sceneIndex < sf->getNumberOfScenes())) {
      return showSceneGetBrainModel(sf->getScene(sceneIndex), 
                                    viewingWindowNumberIn,
                                    geometryOut,
                                    glWidthHeightOut,
                                    yokeOut,
                                    errorMessageOut);
   }
   return NULL;
}

/**
 * Get the model for a window from a scene.
 */
BrainModel*
01128 BrainSet::showSceneGetBrainModel(const SceneFile::Scene* scene,
                                 const int viewingWindowNumber,
                                 int geometryOut[4],
                                 int glWidthHeightOut[2],
                                 bool& yokeOut,
                                 QString& errorMessageOut)
{
   geometryOut[0] = -1;
   geometryOut[1] = -1;
   geometryOut[2] = -1;
   geometryOut[3] = -1;
   glWidthHeightOut[0] = -1;
   glWidthHeightOut[1] = -1;
   yokeOut = false;
   errorMessageOut = "";
   
   //SceneFile* sf = getSceneFile();
   //if ((sceneIndex < 0) || (sceneIndex >= sf->getNumberOfScenes())) {
   //   return NULL;
   //}
   if (viewingWindowNumber < 0) {
      return NULL;
   }
   
   QString windowName("GuiMainWindow");
   if (viewingWindowNumber > 0) {
      std::ostringstream str;
      str << "ViewingWindow:"
          << (viewingWindowNumber + 1);
      windowName = str.str().c_str();
   }

   //const SceneFile::Scene* scene = sf->getScene(sceneIndex);
   
   const int numModels = getNumberOfBrainModels();
   
   BrainModel* brainModel = NULL;
   
   const int numClasses = scene->getNumberOfSceneClasses();
   for (int nc = 0; nc < numClasses; nc++) {
      const SceneFile::SceneClass* sc = scene->getSceneClass(nc);
      const QString className(sc->getName());
      if (className == windowName) {
         BrainModelVolume* bmv = NULL;
         BrainModelSurface* bms = NULL;
         const int num = sc->getNumberOfSceneInfo();
         for (int i = 0; i < num; i++) {
            const SceneFile::SceneInfo* si = sc->getSceneInfo(i);
            const QString infoName = si->getName();      
            
            if (infoName == "BrainModel") {
               const QString modelName = si->getModelName();
               const QString value = si->getValueAsString();
               brainModel = NULL;
               if (modelName == "BrainModelContours") {
                  brainModel = getBrainModelContours();
                  bmv = NULL;
               }
               else if (modelName == "BrainModelSurface") {
                  for (int j = 0; j < numModels; j++) {
                     BrainModelSurface* bms1 = getBrainModelSurface(j);
                     if (bms1 != NULL) {
                        if (value == FileUtilities::basename(bms1->getCoordinateFile()->getFileName())) {
                           brainModel = bms1;
                           bms = bms1;
                           break;
                        }
                     }
                  }
                  bmv = NULL;
               }
               else if (modelName == "BrainModelSurfaceAndVolume") {
                  brainModel = getBrainModelSurfaceAndVolume();
                  bmv = NULL;
               }
               else if (modelName == "BrainModelVolume") {
                  brainModel = getBrainModelVolume();
                  bmv = getBrainModelVolume();
               }
               
               if (brainModel == NULL) {
                  errorMessageOut.append("Unable to find brain model: ");
                  errorMessageOut.append(modelName);
                  errorMessageOut.append("\n");
                  return NULL;
               }
            }
            else if (infoName == "Transformation") {
               if (brainModel != NULL) {
                  brainModel->setTransformationsAsString(viewingWindowNumber, si->getValueAsString());
               }
            }
            else if (infoName == "Slices") {
               if (bmv != NULL) {
                  std::vector<QString> tokens;
                  StringUtilities::token(si->getValueAsString(), " ", tokens);
                  if (tokens.size() >= 3) {
                     const int slices[3] = {
                        StringUtilities::toInt(tokens[0]),
                        StringUtilities::toInt(tokens[1]),
                        StringUtilities::toInt(tokens[2])
                     };
                     bmv->setSelectedOrthogonalSlices(viewingWindowNumber, slices);
                  }
               }
            }
            else if (infoName == "viewStereotaxicCoordinatesFlag") {
               if (bmv != NULL) {
                  bmv->setViewStereotaxicCoordinatesFlag(viewingWindowNumber, si->getValueAsBool());
               }
            }
            else if (infoName == "Oblique-Trans") {
               if (bmv != NULL) {
                  bmv->setObliqueTransformationsAsString(viewingWindowNumber, si->getValueAsString());
               }
            }
            else if (infoName == "Oblique-Slices") {
               if (bmv != NULL) {
                  std::vector<QString> tokens;
                  StringUtilities::token(si->getValueAsString(), " ", tokens);
                  if (tokens.size() >= 3) {
                     const int slices[3] = {
                        StringUtilities::toInt(tokens[0]),
                        StringUtilities::toInt(tokens[1]),
                        StringUtilities::toInt(tokens[2])
                     };
                     bmv->setSelectedObliqueSlices(slices);
                  }
               }
            }
            else if (infoName == "Oblique-Slice-Offsets") {
               if (bmv != NULL) {
                  std::vector<QString> tokens;
                  StringUtilities::token(si->getValueAsString(), " ", tokens);
                  if (tokens.size() >= 3) {
                     const int slices[3] = {
                        StringUtilities::toInt(tokens[0]),
                        StringUtilities::toInt(tokens[1]),
                        StringUtilities::toInt(tokens[2])
                     };
                     bmv->setSelectedObliqueSliceOffsets(viewingWindowNumber, slices);
                  }
               }
            }
            else if (infoName == "Axis") {
               if (bmv != NULL) {
                  bmv->setSelectedAxis(viewingWindowNumber, 
                            static_cast<VolumeFile::VOLUME_AXIS>(si->getValueAsInt()));
               }
            }
            else if (infoName == "Topology") {
               const QString topoName(si->getValueAsString());
               for (int mm = 0; mm < getNumberOfTopologyFiles(); mm++) {
                  TopologyFile* tf = getTopologyFile(mm);
                  if (tf != NULL) {
                     if (FileUtilities::basename(tf->getFileName()) == topoName) {
                        if (bms != NULL) {
                           bms->setTopologyFile(tf);
                           break;
                        }
                     }
                  }
               }
            }
            else if (infoName == "Geometry") {
               std::vector<QString> tokens;
               StringUtilities::token(si->getValueAsString(), " ", tokens);
               if (tokens.size() >= 4) {
                  geometryOut[0] = StringUtilities::toInt(tokens[0]);
                  geometryOut[1] = StringUtilities::toInt(tokens[1]);
                  geometryOut[2] = StringUtilities::toInt(tokens[2]);
                  geometryOut[3] = StringUtilities::toInt(tokens[3]);
               }
            }
            else if (infoName == "GLWidgetSize") {
               std::vector<QString> tokens;
               StringUtilities::token(si->getValueAsString(), " ", tokens);
               if (tokens.size() >= 2) {
                  glWidthHeightOut[0] = StringUtilities::toInt(tokens[0]);
                  glWidthHeightOut[1] = StringUtilities::toInt(tokens[1]);
               }
            }
            else if (infoName == "Yoke") {
               yokeOut = si->getValueAsBool();
            }
         }
      }
   }

   return brainModel;
}

/**
 * Save the model for a window from a scene
 */
void
01324 BrainSet::saveSceneForBrainModelWindow(const int viewingWindowNumber,
                                       const int geometry[4],
                                       const int glWidthHeight[2],
                                       const BrainModel* bm,
                                       const bool yokeIn,
                                       SceneFile::SceneClass& sceneClass)
{
   if (viewingWindowNumber < 0) {
      return;
   }
   if (bm == NULL) {
      return;
   }
   
   QString windowName("GuiMainWindow");
   if (viewingWindowNumber > 0) {
      std::ostringstream str;
      str << "ViewingWindow:"
          << (viewingWindowNumber + 1);
      windowName = str.str().c_str();
   }

   QString modelName;
   QString modelValue;
   BrainModelSurface* bms = NULL;
   BrainModelVolume* bmv = NULL;
   if (getBrainModelContours() == bm) {
      modelName = "BrainModelContours";
      modelValue = modelName;
   }
   else if (getBrainModelSurfaceAndVolume() == bm) {
      modelName = "BrainModelSurfaceAndVolume";
      modelValue = modelName;
   }
   else if (getBrainModelVolume() == bm) {
      modelName = "BrainModelVolume";
      modelValue = modelName;
      bmv = getBrainModelVolume();
   }
   else {
      for (int i = 0; i < getNumberOfBrainModels(); i++) {
         if (getBrainModelSurface(i) == bm) {
            bms = getBrainModelSurface(i);
            modelName = "BrainModelSurface";
            modelValue = FileUtilities::basename(bms->getCoordinateFile()->getFileName());
            break;
         }
      }
   }
   
   if (modelName.isEmpty() == false) {
      sceneClass.setName(windowName);    
      sceneClass.addSceneInfo(SceneFile::SceneInfo("BrainModel", modelName, modelValue));
      if (bm != NULL) {
         sceneClass.addSceneInfo(SceneFile::SceneInfo("Transformation", bm->getTransformationsAsString(viewingWindowNumber)));
      }
      if (bms != NULL) {
         const TopologyFile* tf = bms->getTopologyFile();
         if (tf != NULL) {
            sceneClass.addSceneInfo(SceneFile::SceneInfo("Topology",
                                    FileUtilities::basename(tf->getFileName())));
         }
      }
      if (bmv != NULL) {
         int slices[3];
         bmv->getSelectedOrthogonalSlices(viewingWindowNumber, slices);
         std::ostringstream str;
         str << slices[0] << " " << slices[1] << " " << slices[2];
         sceneClass.addSceneInfo(SceneFile::SceneInfo("Slices", str.str().c_str()));
         sceneClass.addSceneInfo(SceneFile::SceneInfo("Axis", bmv->getSelectedAxis(viewingWindowNumber)));
         sceneClass.addSceneInfo(SceneFile::SceneInfo("Oblique-Trans", bmv->getObliqueTransformationsAsString(viewingWindowNumber)));
         sceneClass.addSceneInfo(SceneFile::SceneInfo("viewStereotaxicCoordinatesFlag", bmv->getViewStereotaxicCoordinatesFlag(viewingWindowNumber)));
         str.str("");
         int obliqueSlices[3];
         bmv->getSelectedObliqueSlices(obliqueSlices);
         str << obliqueSlices[0] << " " << obliqueSlices[1] << " " << obliqueSlices[2];
         sceneClass.addSceneInfo(SceneFile::SceneInfo("Oblique-Slices", str.str().c_str()));

         str.str("");
         int obliqueSliceOffsets[3];
         bmv->getSelectedObliqueSliceOffsets(viewingWindowNumber, obliqueSliceOffsets);
         str << obliqueSliceOffsets[0] << " " << obliqueSliceOffsets[1] << " " << obliqueSliceOffsets[2];
         sceneClass.addSceneInfo(SceneFile::SceneInfo("Oblique-Slice-Offsets", str.str().c_str()));
      }
      
      std::ostringstream str;
      str << geometry[0] << " "
          << geometry[1] << " "
          << geometry[2] << " "
          << geometry[3];
      sceneClass.addSceneInfo(SceneFile::SceneInfo("Geometry", str.str().c_str()));
      
      str.str("");
      str << glWidthHeight[0] << " "
          << glWidthHeight[1];
      sceneClass.addSceneInfo(SceneFile::SceneInfo("GLWidgetSize", str.str().c_str()));

      sceneClass.addSceneInfo(SceneFile::SceneInfo("Yoke", yokeIn));
   }
}

/**
 * apply a scene (set display settings).
 */
void 
01429 BrainSet::showScene(const int sceneIndex, 
                    QString& errorMessage,
                    QString& warningMessage)
{
   SceneFile* sf = getSceneFile();
   if ((sceneIndex >= 0) && (sceneIndex < sf->getNumberOfScenes())) {
      showScene(sf->getScene(sceneIndex), false, errorMessage, warningMessage);
   }
}

/**
 * load identification filters from a scene.
 */
void 
01443 BrainSet::showSceneIdentificationFilters(const SceneFile::Scene* ss,
                                         QString& errorMessage)
{
   errorMessage = "";
   
   if (ss != NULL) {
      brainModelIdentification->showScene(*ss, errorMessage);
   }
}

/**
 * apply a scene (set display settings).
 */
void 
01457 BrainSet::showScene(const SceneFile::Scene* ss, 
                    const bool checkSpecFlag,
                    QString& errorMessage,
                    QString& warningMessage)
{
   errorMessage = "";
   
   //const SceneFile::Scene* ss = sceneFile->getScene(sceneIndex);
   if (ss != NULL) {
      //
      // Find out which files are needed for this scene
      //
      SpecFile sf;
      sf.showScene(*ss, errorMessage);
      
      //
      // Should the spec file be checked
      //
      if (checkSpecFlag) {
         SpecFile userSpec;
         try {
            userSpec.readFile(getSpecFileName());
            QString msg;
            if (sf.isSubsetOfOtherSpecFile(userSpec, msg) == false) {
               errorMessage.append("Spec File Errors for Spec File ");
               errorMessage.append(FileUtilities::basename(getSpecFileName()));
               errorMessage.append(": \n");
               errorMessage.append(msg);
            }
         }
         catch (FileException&) {
         }
      }
      
/*
      //
      // clear colors
      //
      clearAreaColorFile();
      clearBorderColorFile();
      clearCellColorFile();
      clearContourCellColorFile();
      clearFociColorFile();
      
      //
      // Clear all borders, cells, cuts, and foci
      //
      deleteAllBorders();
      deleteAllCells(true, true);
      deleteAllFociProjections();
      clearCutsFile();
      clearContourCellFile();
      
      //
      // Clear cocomac
      //
      clearCocomacConnectivityFile();
      
      //
      // Clear probabilistic atlas files
      //
      clearProbabilisticAtlasFile();
      probabilisticAtlasSurfaceFile->clearModified();
*/
      //
      // Clear data files
      //      
      resetDataFiles(true,
                     displaySettingsScene->getPreserveFociAndFociColorsAndStudyMetaDataFlag());

      //
      // Get rid of volume prob atlas files
      //   
      clearVolumeProbabilisticAtlasFiles();   
 
      //
      // Clear node identify symbols
      //
      clearNodeHighlightSymbols();
      
      //
      // Do not load any files that are already loaded
      //
      sf.deselectFilesSelectedInOtherSpecFile(loadedFilesSpecFile);
      
      //
      // Read any files that are part of scene but not already loaded
      //
      QString specMsg;
      readSpecFile(SPEC_FILE_READ_MODE_APPEND,
                   sf,
                   "scene",
                   specMsg,
                   NULL,
                   NULL);
      errorMessage.append(specMsg);
      paletteFile->clearModified();

      //
      // Auto-Loaded Files
      //
      brainSetAutoLoaderManager->showScene(*ss, errorMessage);

      //
      // Update overlays
      //
      for (int i = 0; i < getNumberOfSurfaceOverlays(); i++) {
         getSurfaceOverlay(i)->showScene(*ss, errorMessage);
      }
       
      //
      // Update node/voxel coloring
      //
      brainModelIdentification->showScene(*ss, errorMessage);
      nodeColoring->showScene(*ss, errorMessage);
      voxelColoring->showScene(*ss, errorMessage);
      
      //
      // surface and volume settings
      //
      BrainModelSurfaceAndVolume* bmsv = getBrainModelSurfaceAndVolume();
      if (bmsv != NULL) {
         bmsv->showScene(*ss, errorMessage);
      }
      
      //
      // transformation matrices
      //
      transformationMatrixFile->showScene(*ss, errorMessage);

      //
      // display settings
      //
      displaySettingsArealEstimation->showScene(*ss, errorMessage);
      displaySettingsBorders->showScene(*ss, errorMessage);
      displaySettingsCells->showScene(*ss, errorMessage);
      displaySettingsCoCoMac->showScene(*ss, errorMessage);
      displaySettingsContours->showScene(*ss, errorMessage);
      displaySettingsCuts->showScene(*ss, errorMessage);
      displaySettingsFoci->showScene(*ss, errorMessage);
      displaySettingsGeodesicDistance->showScene(*ss, errorMessage);
      displaySettingsDeformationField->showScene(*ss, errorMessage);
      displaySettingsImages->showScene(*ss, errorMessage);
      displaySettingsMetric->showScene(*ss, errorMessage);
      displaySettingsModels->showScene(*ss, errorMessage);
      displaySettingsPaint->showScene(*ss, errorMessage);
      displaySettingsProbabilisticAtlasSurface->showScene(*ss, errorMessage);
      displaySettingsProbabilisticAtlasVolume->showScene(*ss, errorMessage);
      displaySettingsRgbPaint->showScene(*ss, errorMessage);
      displaySettingsScene->showScene(*ss, errorMessage);
      displaySettingsSection->showScene(*ss, errorMessage);
      displaySettingsStudyMetaData->showScene(*ss, errorMessage);
      displaySettingsSurface->showScene(*ss, errorMessage);
      displaySettingsSurfaceShape->showScene(*ss, errorMessage);
      displaySettingsVectors->showScene(*ss, errorMessage);
      displaySettingsTopography->showScene(*ss, errorMessage);
      displaySettingsVolume->showScene(*ss, errorMessage);
      displaySettingsWustlRegion->showScene(*ss, errorMessage);
      
      assignBorderColors();
      assignCellColors();
      assignFociColors();
      
      displaySettingsBorders->determineDisplayedBorders();
      displaySettingsCells->determineDisplayedCells();
      displaySettingsFoci->determineDisplayedCells(true);
      
      clearNodeHighlightSymbols();

      const int numClasses = ss->getNumberOfSceneClasses();
      for (int nc = 0; nc < numClasses; nc++) {
         const SceneFile::SceneClass* sc = ss->getSceneClass(nc);
         const int num = sc->getNumberOfSceneInfo();
         
         //
         // Node highlighting
         //
         if (sc->getName() == "NodeHighlighting") {
            clearNodeHighlightSymbols();

            const int numNodes = getNumberOfNodes();
            for (int i = 0; i < num; i++) {
               const SceneFile::SceneInfo* si = sc->getSceneInfo(i);
               const int nodeNum = StringUtilities::toInt(si->getModelName());
               if (numNodes > 0) {      
                  BrainSetNodeAttribute* bna = getNodeAttributes(nodeNum);
                  bna->setHighlighting(
                     static_cast<BrainSetNodeAttribute::HIGHLIGHT_NODE_TYPE>(si->getValueAsInt()));
               }
            }
         }
         else if ((sc->getName() == "BrainSet") ||
                  (sc->getName() == "BrainSet")) {
            for (int i = 0; i < num; i++) {
               const SceneFile::SceneInfo* si = sc->getSceneInfo(i);
               if (si->getName() == "ActiveFiducial") {
                  const QString activeFiducialName(si->getValueAsString());
                  bool found = false;
                  const int numModels = getNumberOfBrainModels();
                  for (int i = 0; i < numModels; i++) {
                     BrainModelSurface* bms = getBrainModelSurface(i);
                     if (bms != NULL) {
                        const CoordinateFile* cf = bms->getCoordinateFile();
                        const QString name(FileUtilities::basename(cf->getFileName()));
                        if (name == activeFiducialName) {
                           setActiveFiducialSurface(bms);
                           found = true;
                           break;
                        }
                     }
                  }
                  if (found == false) {
                     errorMessage.append("Unable to set active fiducial surface to: ");
                     errorMessage.append(activeFiducialName);
                     errorMessage.append("\n");
                  }
               }  
               else if (si->getName() == "LeftVolumeFiducialInteraction") {
                  const QString fiducialName(si->getValueAsString());
                  bool found = false;
                  const int numModels = getNumberOfBrainModels();
                  for (int i = 0; i < numModels; i++) {
                     BrainModelSurface* bms = getBrainModelSurface(i);
                     if (bms != NULL) {
                        const CoordinateFile* cf = bms->getCoordinateFile();
                        const QString name(FileUtilities::basename(cf->getFileName()));
                        if (name == fiducialName) {
                           setLeftFiducialVolumeInteractionSurface(bms);
                           found = true;
                           break;
                        }
                     }
                  }
                  if (found == false) {
                     errorMessage.append("Unable to set left fiducial volume interaction surface to: ");
                     errorMessage.append(fiducialName);
                     errorMessage.append("\n");
                  }
               }  
               else if (si->getName() == "RightVolumeFiducialInteraction") {
                  const QString fiducialName(si->getValueAsString());
                  bool found = false;
                  const int numModels = getNumberOfBrainModels();
                  for (int i = 0; i < numModels; i++) {
                     BrainModelSurface* bms = getBrainModelSurface(i);
                     if (bms != NULL) {
                        const CoordinateFile* cf = bms->getCoordinateFile();
                        const QString name(FileUtilities::basename(cf->getFileName()));
                        if (name == fiducialName) {
                           setRightFiducialVolumeInteractionSurface(bms);
                           found = true;
                           break;
                        }
                     }
                  }
                  if (found == false) {
                     errorMessage.append("Unable to set right fiducial volume interaction surface to: ");
                     errorMessage.append(fiducialName);
                     errorMessage.append("\n");
                  }
               }  
               else if (si->getName() == "CerebellumVolumeFiducialInteraction") {
                  const QString fiducialName(si->getValueAsString());
                  bool found = false;
                  const int numModels = getNumberOfBrainModels();
                  for (int i = 0; i < numModels; i++) {
                     BrainModelSurface* bms = getBrainModelSurface(i);
                     if (bms != NULL) {
                        const CoordinateFile* cf = bms->getCoordinateFile();
                        const QString name(FileUtilities::basename(cf->getFileName()));
                        if (name == fiducialName) {
                           setCerebellumFiducialVolumeInteractionSurface(bms);
                           found = true;
                           break;
                        }
                     }
                  }
                  if (found == false) {
                     errorMessage.append("Unable to set cerebellum fiducial volume interaction surface to: ");
                     errorMessage.append(fiducialName);
                     errorMessage.append("\n");
                  }
               }  
            }
         }
         else if (sc->getName() == "TransformationDataFile") {
            TransformationMatrixFile* tmf = getTransformationMatrixFile();
            const int numMatrices = tmf->getNumberOfMatrices();
            for (int i = 0; i < num; i++) {
               const SceneFile::SceneInfo* si = sc->getSceneInfo(i);
               const QString fileName = si->getName();
               const QString matrixName = si->getValueAsString();
               
               bool fileFound = false;
               for (int i = 0; i < getNumberOfTransformationDataFiles(); i++) {
                  AbstractFile* af = getTransformationDataFile(i);
                  const QString name = FileUtilities::basename(af->getFileName());
                  if (fileName == name) {
                     fileFound = true;
                     bool matrixFound = true;
                     TransformationMatrix* tm = NULL;
                     if (matrixName != "NULL") {
                        matrixFound = false;
                        for (int i = 0; i < numMatrices; i++) {
                           TransformationMatrix* matrix = tmf->getTransformationMatrix(i);
                           if (matrix->getMatrixName() == matrixName) {
                              tm = matrix;
                              matrixFound = true;
                              break;
                           }
                        }
                     }
                     af->setAssociatedTransformationMatrix(tm);
                     if (matrixFound == false) {
                        errorMessage.append("Unable to find matrix for transformation data file ");
                        errorMessage.append(fileName);
                        errorMessage.append(", matrix ");
                        errorMessage.append(matrixName);
                     }
                     fileFound = true;
                     break;
                  }
               }
               if (fileFound == false) {
                  errorMessage.append("Transformation data file in scene but not loaded ");
                  errorMessage.append(fileName);
               }
            }
         }
      }

      //
      // Assign node/voxel colors
      //
      nodeColoring->assignColors();
      voxelColoring->setVolumeAllColoringInvalid();
   }
   
   checkNodeAttributeFilesForDuplicateColumnNames(warningMessage);
}

/**
 * create a scene (read display settings).
 */
void 
01802 BrainSet::saveScene(SceneFile* sf,
                    const std::vector<SceneFile::SceneClass>& mainWindowSceneClasses,
                    const QString& sceneName, const bool onlyIfSelectedFlag,
                    QString& errorMessageOut,
                    QString& warningMessageOut)
{
   SceneFile::Scene scene(sceneName);
   
   saveReplaceSceneHelper(scene, mainWindowSceneClasses, onlyIfSelectedFlag, errorMessageOut, warningMessageOut);
   
   if (errorMessageOut.isEmpty()) {
      sf->addScene(scene);
   }
   else {
      errorMessageOut.append("Scene HAS NOT been saved.");
   }
}

/**
 * insert after scene (read display settings).
 */
void 
01824 BrainSet::insertScene(SceneFile* sf,
                      const int insertAfterIndex,
                      const std::vector<SceneFile::SceneClass>& mainWindowSceneClasses,
                      const QString& sceneName, const bool onlyIfSelectedFlag,
                      QString& errorMessageOut,
                      QString& warningMessageOut)
{
   SceneFile::Scene scene(sceneName);
   
   saveReplaceSceneHelper(scene, mainWindowSceneClasses, onlyIfSelectedFlag, errorMessageOut, warningMessageOut);
   
   if (errorMessageOut.isEmpty()) {
      sf->insertScene(insertAfterIndex, scene);
   }
   else {
      errorMessageOut.append("Scene HAS NOT been saved.");
   }
}
      
/**
 * replace a scene (read display settings).
 */
void 
01847 BrainSet::replaceScene(SceneFile* sf,
                       const int sceneIndex,
                       const std::vector<SceneFile::SceneClass>& mainWindowSceneClasses,
                       const QString& sceneName, const bool onlyIfSelectedFlag,
                       QString& errorMessageOut,
                       QString& warningMessageOut)
{
   SceneFile::Scene scene(sceneName);
   
   saveReplaceSceneHelper(scene, mainWindowSceneClasses, onlyIfSelectedFlag, errorMessageOut, warningMessageOut);
   
   if (errorMessageOut.isEmpty()) {
      sf->replaceScene(sceneIndex, scene);
   }
   else {
      errorMessageOut.append("Scene HAS NOT been saved.");
   }
}
      
/**
 * save/replace scene helper.
 */
void 
01870 BrainSet::saveReplaceSceneHelper(SceneFile::Scene& scene,
                                 const std::vector<SceneFile::SceneClass>& mainWindowSceneClasses,
                                 const bool onlyIfSelectedFlag,
                                 QString& errorMessageOut,
                                 QString& warningMessageOut)
{
   errorMessageOut = "";
   warningMessageOut = "";
   
   if (mainWindowSceneClasses.empty() == false) {
      for (unsigned int i = 0; i < mainWindowSceneClasses.size(); i++) {
         scene.addSceneClass(mainWindowSceneClasses[i]);
      }
   }
   
   //
   // Update overlays
   //
   for (int i = 0; i < getNumberOfSurfaceOverlays(); i++) {
      getSurfaceOverlay(i)->saveScene(scene, onlyIfSelectedFlag);
   }
   brainModelIdentification->saveScene(scene);
   nodeColoring->saveScene(scene, onlyIfSelectedFlag);
   voxelColoring->saveScene(scene, onlyIfSelectedFlag);
   
   BrainModelSurfaceAndVolume* bmsv = getBrainModelSurfaceAndVolume();
   if (bmsv != NULL) {
      bmsv->saveScene(scene, false);
   }
   
   //
   // Transformation matrices
   //
   transformationMatrixFile->saveScene(scene, onlyIfSelectedFlag);
   
   //
   // Matrices associated with transform data files
   //
   SceneFile::SceneClass tsc("TransformationDataFile");
   for (int i = 0; i < getNumberOfTransformationDataFiles(); i++) {
      const AbstractFile* af = getTransformationDataFile(i);
      const QString name = FileUtilities::basename(af->getFileName());
      const TransformationMatrix* tm = af->getAssociatedTransformationMatrix();
      QString matrixName("NULL");
      if (tm != NULL) {
         matrixName = tm->getMatrixName();
      }
      tsc.addSceneInfo(SceneFile::SceneInfo(name, matrixName));
   }
   if (tsc.getNumberOfSceneInfo() > 0) {
      scene.addSceneClass(tsc);
   }
   
   //
   // display settings
   //
   displaySettingsArealEstimation->saveScene(scene, onlyIfSelectedFlag, errorMessageOut);
   displaySettingsBorders->saveScene(scene, onlyIfSelectedFlag, errorMessageOut);
   displaySettingsCells->saveScene(scene, onlyIfSelectedFlag, errorMessageOut);
   displaySettingsCoCoMac->saveScene(scene, onlyIfSelectedFlag, errorMessageOut);
   displaySettingsContours->saveScene(scene, onlyIfSelectedFlag, errorMessageOut);
   displaySettingsCuts->saveScene(scene, onlyIfSelectedFlag, errorMessageOut);
   displaySettingsFoci->saveScene(scene, onlyIfSelectedFlag, errorMessageOut);
   displaySettingsGeodesicDistance->saveScene(scene, onlyIfSelectedFlag, errorMessageOut);
   displaySettingsDeformationField->saveScene(scene, onlyIfSelectedFlag, errorMessageOut);
   displaySettingsImages->saveScene(scene, onlyIfSelectedFlag, errorMessageOut);
   displaySettingsMetric->saveScene(scene, onlyIfSelectedFlag, errorMessageOut);
   displaySettingsModels->saveScene(scene, onlyIfSelectedFlag, errorMessageOut);
   displaySettingsPaint->saveScene(scene, onlyIfSelectedFlag, errorMessageOut);
   displaySettingsProbabilisticAtlasSurface->saveScene(scene, onlyIfSelectedFlag, errorMessageOut);
   displaySettingsProbabilisticAtlasVolume->saveScene(scene, onlyIfSelectedFlag, errorMessageOut);
   displaySettingsRgbPaint->saveScene(scene, onlyIfSelectedFlag, errorMessageOut);
   displaySettingsScene->saveScene(scene, onlyIfSelectedFlag, errorMessageOut);
   displaySettingsSection->saveScene(scene, onlyIfSelectedFlag, errorMessageOut);
   displaySettingsStudyMetaData->saveScene(scene, onlyIfSelectedFlag, errorMessageOut);
   displaySettingsSurface->saveScene(scene, onlyIfSelectedFlag, errorMessageOut);
   displaySettingsSurfaceShape->saveScene(scene, onlyIfSelectedFlag, errorMessageOut);
   displaySettingsVectors->saveScene(scene, onlyIfSelectedFlag, errorMessageOut);
   displaySettingsTopography->saveScene(scene, onlyIfSelectedFlag, errorMessageOut);
   displaySettingsVolume->saveScene(scene, onlyIfSelectedFlag, errorMessageOut);
   displaySettingsWustlRegion->saveScene(scene, onlyIfSelectedFlag, errorMessageOut);

   brainSetAutoLoaderManager->saveScene(scene, onlyIfSelectedFlag, errorMessageOut);
   
   SceneFile::SceneClass sc("NodeHighlighting");   
   const int numNodes = getNumberOfNodes();
   for (int n = 0; n < numNodes; n++) {
      const BrainSetNodeAttribute* bna = getNodeAttributes(n);
      const BrainSetNodeAttribute::HIGHLIGHT_NODE_TYPE hnt = bna->getHighlighting();
      if (hnt != BrainSetNodeAttribute::HIGHLIGHT_NODE_NONE) {
         sc.addSceneInfo(SceneFile::SceneInfo("nh", StringUtilities::fromNumber(n), hnt));
      }
   }
   if (sc.getNumberOfSceneInfo() > 0) {
      scene.addSceneClass(sc);
   }
   
   loadedFilesSpecFile.saveScene(scene, true);   
   
   SceneFile::SceneClass sca("BrainSet");
   const BrainModelSurface* bms = getActiveFiducialSurface();
   if (bms != NULL) {
      const CoordinateFile* cf = bms->getCoordinateFile();
      const QString name(FileUtilities::basename(cf->getFileName()));
      if (name.isEmpty() == false) {
         sca.addSceneInfo(SceneFile::SceneInfo("ActiveFiducial", name));
      }
   }
   
   const BrainModelSurface* bmsLeft = getLeftFiducialVolumeInteractionSurface();
   if (bmsLeft != NULL) {
      const CoordinateFile* cf = bmsLeft->getCoordinateFile();
      const QString name(FileUtilities::basename(cf->getFileName()));
      if (name.isEmpty() == false) {
         sca.addSceneInfo(SceneFile::SceneInfo("LeftVolumeFiducialInteraction", name));
      }
   }
   
   const BrainModelSurface* bmsRight = getRightFiducialVolumeInteractionSurface();
   if (bmsRight != NULL) {
      const CoordinateFile* cf = bmsRight->getCoordinateFile();
      const QString name(FileUtilities::basename(cf->getFileName()));
      if (name.isEmpty() == false) {
         sca.addSceneInfo(SceneFile::SceneInfo("RightVolumeFiducialInteraction", name));
      }
   }
   
   const BrainModelSurface* bmsCerebellum = getCerebellumFiducialVolumeInteractionSurface();
   if (bmsCerebellum != NULL) {
      const CoordinateFile* cf = bmsCerebellum->getCoordinateFile();
      const QString name(FileUtilities::basename(cf->getFileName()));
      if (name.isEmpty() == false) {
         sca.addSceneInfo(SceneFile::SceneInfo("CerebellumVolumeFiducialInteraction", name));
      }
   }
   
   if (sca.getNumberOfSceneInfo() > 0) {
      scene.addSceneClass(sca);
   }
   
   checkNodeAttributeFilesForDuplicateColumnNames(warningMessageOut);
}                     

/**
 * check node attribute columns for columns with same name.
 */
void 
02017 BrainSet::checkNodeAttributeFilesForDuplicateColumnNames(QString& errorMessageOut)
{
   nodeAttribteDuplicateNamesHelper("Areal Estimation File", arealEstimationFile, errorMessageOut);
   nodeAttribteDuplicateNamesHelper("Deformation Field File", deformationFieldFile, errorMessageOut);
   nodeAttribteDuplicateNamesHelper("Geodesic Distance File", geodesicDistanceFile, errorMessageOut);
   nodeAttribteDuplicateNamesHelper("Lat Lon File", latLonFile, errorMessageOut);
   niftiNodeDataFileDuplicateNamesHelper("Metric File", metricFile, errorMessageOut);
   niftiNodeDataFileDuplicateNamesHelper("Paint File", paintFile, errorMessageOut);
   nodeAttribteDuplicateNamesHelper("Rgb Paint File", rgbPaintFile, errorMessageOut);
   nodeAttribteDuplicateNamesHelper("Section File", sectionFile, errorMessageOut);
   niftiNodeDataFileDuplicateNamesHelper("Shape File", surfaceShapeFile, errorMessageOut);
   nodeAttribteDuplicateNamesHelper("Topography File", topographyFile, errorMessageOut);
}

/**
 * check for duplicate column names in a mode attribute file.
 */
void 
02035 BrainSet::nodeAttribteDuplicateNamesHelper(const QString& fileTypeName,
                                           NodeAttributeFile* naf,
                                           QString& errorMessageOut) const
{
   std::vector<QString> duplicateNames;
   
   if (naf->checkForColumnsWithSameName(duplicateNames)) {
      errorMessageOut.append(fileTypeName);
      errorMessageOut.append(" has the following duplicate column names:\n");
      for (unsigned int i = 0; i < duplicateNames.size(); i++) {
         errorMessageOut.append("   ");
         errorMessageOut.append(duplicateNames[i]);
         errorMessageOut.append("\n");
      }
      errorMessageOut.append("\n");
   }   
}

/**
 * check for duplicate column names in a mode attribute file.
 */
void 
02057 BrainSet::niftiNodeDataFileDuplicateNamesHelper(const QString& fileTypeName,
                                           GiftiNodeDataFile* naf,
                                           QString& errorMessageOut) const
{
   std::vector<QString> duplicateNames;
   
   if (naf->checkForColumnsWithSameName(duplicateNames)) {
      errorMessageOut.append(fileTypeName);
      errorMessageOut.append(" has the following duplicate column names:\n");
      for (unsigned int i = 0; i < duplicateNames.size(); i++) {
         errorMessageOut.append("   ");
         errorMessageOut.append(duplicateNames[i]);
         errorMessageOut.append("\n");
      }
      errorMessageOut.append("\n");
   }   
}

/**
 * Get rid of all topology files
 */
void
02079 BrainSet::deleteAllTopologyFiles()
{
   for (unsigned int j= 0; j < topologyFiles.size(); j++) {
      if (topologyFiles[j] != NULL) {
         loadedFilesSpecFile.closedTopoFile.clearSelectionStatus(topologyFiles[j]->getFileName());
         loadedFilesSpecFile.openTopoFile.clearSelectionStatus(topologyFiles[j]->getFileName());
         loadedFilesSpecFile.cutTopoFile.clearSelectionStatus(topologyFiles[j]->getFileName());
         loadedFilesSpecFile.lobarCutTopoFile.clearSelectionStatus(topologyFiles[j]->getFileName());
         loadedFilesSpecFile.unknownTopoFile.clearSelectionStatus(topologyFiles[j]->getFileName());
         delete topologyFiles[j];
         topologyFiles[j] = NULL;
      }
   }
   topologyFiles.clear();

   topologyClosed   = NULL;
   topologyOpen     = NULL;
   topologyCut      = NULL;
   topologyLobarCut = NULL;
   topologyUnknown  = NULL;
   
}


/**
 * Set the visited flag on all nodes
 */
void
02107 BrainSet::setAllNodesVisited(const bool value)
{
   const int numNodes = getNumberOfNodes();
   for (int i = 0; i < numNodes; i++) {
      nodeAttributes[i].visited = value;
   }
}

/**
 * Set the structure and update in the spec file.
 */
void
02119 BrainSet::setStructure(const Structure::STRUCTURE_TYPE hem)
{
   structure.setType(hem);
   updateDefaultFileNamePrefix();
}

/**
 * Set the structure and update in the spec file.
 */
void
02129 BrainSet::setStructure(const Structure& hem)
{
   structure = hem;
   updateDefaultFileNamePrefix();
}

/**
 * set the subject.
 */
void 
02139 BrainSet::setSubject(const QString& s) 
{ 
   subject = s; 
   updateDefaultFileNamePrefix();
}

/**
 * set the stereotaxic space (const method).
 */
void 
02149 BrainSet::setStereotaxicSpace(const StereotaxicSpace& ss) 
{
   stereotaxicSpace = ss;
}
      
/**
 * set the species.
 */
void 
02158 BrainSet::setSpecies(const Species& s)
{
   species = s;
   updateDefaultFileNamePrefix();
}

/**
 * guess subject, species, and structure if not specified.
 */
void 
02168 BrainSet::guessSubjectSpeciesStructureFromCoordTopoFileNames()
{
   if ((species.getType() == Species::TYPE_UNKNOWN) ||
       subject.isEmpty() ||
       (structure.getType() == Structure::STRUCTURE_TYPE_INVALID)) {
      //
      // Get names of topo and coord files
      //
      std::vector<QString> fileNames;
      for (int i = 0; i < getNumberOfTopologyFiles(); i++) {
         fileNames.push_back(FileUtilities::basename(getTopologyFile(i)->getFileName()));
      }
      for (int i = 0; i < getNumberOfBrainModels(); i++) {
         const BrainModelSurface* bms = getBrainModelSurface(i);
         if (bms != NULL) {
            fileNames.push_back(FileUtilities::basename(bms->getCoordinateFile()->getFileName()));
         }
      }
      
      //
      // Loop through file names
      //
      for (int i = 0; i < static_cast<int>(fileNames.size()); i++) {
         QString fDir, fSpecies, fCasename, fAnatomy, fHemisphere,
                 fDescription, fDescriptionNoTypeName, fTheDate,
                 fNumNodes, fExtension;
         //
         // Is this a valid caret data file name
         //
         if (FileUtilities::parseCaretDataFileName(fileNames[i],
                                                   fDir, 
                                                   fSpecies, 
                                                   fCasename, 
                                                   fAnatomy, 
                                                   fHemisphere,
                                                   fDescription, 
                                                   fDescriptionNoTypeName, 
                                                   fTheDate,
                                                   fNumNodes, 
                                                   fExtension)) {
            //
            // Update data
            //
            if ((species.getType() == Species::TYPE_UNKNOWN) &&
                (fSpecies != "")) {
               species.setUsingName(fSpecies);
            }
            if (subject.isEmpty() &&
                (fCasename.isEmpty() == false)) {
               subject = fCasename;
            }
            if ((structure.getType() == Structure::STRUCTURE_TYPE_INVALID) &&
                (fHemisphere.isEmpty() == false)) {
               const Structure s(fHemisphere);
               if (s.getType() != Structure::STRUCTURE_TYPE_INVALID) {
                  structure = s;
               }
            }
         }
         
         //
         // See if done
         //
         if ((species.getType() != Species::TYPE_UNKNOWN) &&
             (subject.isEmpty() == false) &&
             (structure.getType() == Structure::STRUCTURE_TYPE_INVALID)) {
            break;
         }
      }
   }
}
      
/**
 * update the default file naming prefix.
 */
void 
02244 BrainSet::updateDefaultFileNamePrefix()
{
   if (primaryBrainSetFlag) {
      QString defaultFileNamePrefix;

      guessSubjectSpeciesStructureFromCoordTopoFileNames();
            
      const QString hem = structure.getTypeAsAbbreviatedString();
      if ((hem != "U") && 
          (hem.isEmpty() == false) && 
          (species.getType() != Species::TYPE_UNKNOWN) && 
          (subject.isEmpty() == false)) {
         defaultFileNamePrefix.append(species.getName());
         defaultFileNamePrefix.append(".");
         defaultFileNamePrefix.append(subject);
         defaultFileNamePrefix.append(".");
         defaultFileNamePrefix.append(hem);
      }
      
      AbstractFile::setDefaultFileNamePrefix(defaultFileNamePrefix, getNumberOfNodes());
   }
}
      
/**
 * get a brain model contours (if negative index first one found is returned).
 */
BrainModelContours* 
02271 BrainSet::getBrainModelContours(const int modelIndex) 
{
   if (modelIndex < 0) {
      for (int i = 0; i < getNumberOfBrainModels(); i++) {
         BrainModelContours* bmc = getBrainModelContours(i);
         if (bmc != NULL) {
            return bmc;
         }
      }
   }
   else if (modelIndex < getNumberOfBrainModels()) {
      return dynamic_cast<BrainModelContours*>(brainModels[modelIndex]);
   }
   return NULL;
}

/**
 * get a brain model contours (const method) (if negative index first one found is returned).
 */
const BrainModelContours* 
02291 BrainSet::getBrainModelContours(const int modelIndex) const 
{
   if (modelIndex < 0) {
      for (int i = 0; i < getNumberOfBrainModels(); i++) {
         const BrainModelContours* bmc = getBrainModelContours(i);
         if (bmc != NULL) {
            return bmc;
         }
      }
   }
   else if (modelIndex < getNumberOfBrainModels()) {
      return dynamic_cast<BrainModelContours*>(brainModels[modelIndex]);
   }
   return NULL;
}

/**
 * Get a brain model volume (if negative index first one found is returned).
 */
BrainModelVolume* 
02311 BrainSet::getBrainModelVolume(const int modelIndex) 
{
   if (modelIndex < 0) {
      for (int i = 0; i < getNumberOfBrainModels(); i++) {
         BrainModelVolume* bmv = getBrainModelVolume(i);
         if (bmv != NULL) {
            return bmv;
         }
      }
   }
   else if (modelIndex < getNumberOfBrainModels()) {
      return dynamic_cast<BrainModelVolume*>(brainModels[modelIndex]);
   }
   return NULL;
}
 
/**
 * Get a brain model volume (if negative index first one found is returned) CONST method
 */
const BrainModelVolume* 
02331 BrainSet::getBrainModelVolume(const int modelIndex) const
{
   if (modelIndex < 0) {
      for (int i = 0; i < getNumberOfBrainModels(); i++) {
         const BrainModelVolume* bmv = getBrainModelVolume(i);
         if (bmv != NULL) {
            return bmv;
         }
      }
   }
   else if (modelIndex < getNumberOfBrainModels()) {
      return dynamic_cast<BrainModelVolume*>(brainModels[modelIndex]);
   }
   return NULL;
}
 
/**
 * Get a brain model surface and volume (if negative index first one found is returned).
 */
BrainModelSurfaceAndVolume* 
02351 BrainSet::getBrainModelSurfaceAndVolume(const int modelIndex) 
{
   if (modelIndex < 0) {
      for (int i = 0; i < getNumberOfBrainModels(); i++) {
         BrainModelSurfaceAndVolume* bmsv = getBrainModelSurfaceAndVolume(i);
         if (bmsv != NULL) {
            return bmsv;
         }
      }
   }
   else if (modelIndex < getNumberOfBrainModels()) {
      return dynamic_cast<BrainModelSurfaceAndVolume*>(brainModels[modelIndex]);
   }
   return NULL;
}
 
/**
 * Get a brain model surface and volume (if negative index first one found is returned) CONST method
 */
const BrainModelSurfaceAndVolume* 
02371 BrainSet::getBrainModelSurfaceAndVolume(const int modelIndex) const
{
   if (modelIndex < 0) {
      for (int i = 0; i < getNumberOfBrainModels(); i++) {
         const BrainModelSurfaceAndVolume* bmsv = getBrainModelSurfaceAndVolume(i);
         if (bmsv != NULL) {
            return bmsv;
         }
      }
   }
   else if (modelIndex < getNumberOfBrainModels()) {
      return dynamic_cast<BrainModelSurfaceAndVolume*>(brainModels[modelIndex]);
   }
   return NULL;
}
 
/**
 * add nodes to all surfaces at the origin
 */
void 
02391 BrainSet::addNodes(const int numNodesToAdd)
{
   const float origin[3] = { 0.0, 0.0, 0.0 };
   
   //
   // Add nodes to all coordinate files
   //
   const int numModels = getNumberOfBrainModels();
   for (int i = 0; i < numModels; i++) {
      BrainModelSurface* bms = getBrainModelSurface(i);
      if (bms != NULL) {
         CoordinateFile* cf = bms->getCoordinateFile();
         for (int j = 0; j < numNodesToAdd; j++) {
            cf->addCoordinate(origin);
         }
      }
   }
   
   //
   // Update all topology files
   //
   const int numTopo = getNumberOfTopologyFiles();
   for (int i = 0; i < numTopo; i++) {
      TopologyFile* tf = getTopologyFile(i);
      const int oldNumNodes = tf->getNumberOfNodes();
      const int newNumNodes = oldNumNodes + numNodesToAdd;
      if (newNumNodes > oldNumNodes) {
         tf->setNumberOfNodes(newNumNodes);
      }
   }
   
   //
   // Update the display flags
   //
   updateNodeDisplayFlags();
   
   //
   // Update the node attribute files
   //
   std::vector<NodeAttributeFile*> nodeAttributeFiles;
   nodeAttributeFiles.push_back(arealEstimationFile);
   nodeAttributeFiles.push_back(deformationFieldFile);
   nodeAttributeFiles.push_back(latLonFile);
   nodeAttributeFiles.push_back(rgbPaintFile);
   nodeAttributeFiles.push_back(sectionFile);
   nodeAttributeFiles.push_back(topographyFile);
   for (int i = 0; i < static_cast<int>(nodeAttributeFiles.size()); i++) {
      NodeAttributeFile* naf = nodeAttributeFiles[i];
      if (naf != NULL) {
         if ((naf->getNumberOfNodes() > 0) && (naf->getNumberOfColumns() > 0)) {
            naf->addNodes(numNodesToAdd);
         }
      }
   }
   
   std::vector<GiftiNodeDataFile*> niftiNodeDataFiles;
   niftiNodeDataFiles.push_back(metricFile);
   niftiNodeDataFiles.push_back(paintFile);
   niftiNodeDataFiles.push_back(surfaceShapeFile);
   for (int i = 0; i < static_cast<int>(niftiNodeDataFiles.size()); i++) {
      GiftiNodeDataFile* naf = niftiNodeDataFiles[i];
      if (naf != NULL) {
         if ((naf->getNumberOfNodes() > 0) && (naf->getNumberOfColumns() > 0)) {
            naf->addNodes(numNodesToAdd);
         }
      }
   }

   //
   // Assign node coloring
   //
   nodeColoring->assignColors();
}      

/**
 * Create a brain model surface and volume.
 */
void
02469 BrainSet::createBrainModelSurfaceAndVolume()
{
   //
   // Prevent more than one thread from executing this code
   //
   QMutexLocker locker(&mutexCreateSurfaceAndVolume);
   
   BrainModelSurfaceAndVolume* bmsv = getBrainModelSurfaceAndVolume();
   if (bmsv != NULL) {
      //
      // If no surface attached to surf&vol, add one
      //
      const CoordinateFile* cf = bmsv->getCoordinateFile();
      if (cf->getNumberOfCoordinates() <= 0) {
         const BrainModelSurface* fiducialSurface = 
            getBrainModelSurfaceOfType(BrainModelSurface::SURFACE_TYPE_FIDUCIAL);
         if (fiducialSurface != NULL) {
            bmsv->setSurface();
         }
      }
      return;
   }
   
   if (getNumberOfVolumeAnatomyFiles() > 0) {
      BrainModelSurfaceAndVolume* bmsv = new BrainModelSurfaceAndVolume(this);
      bmsv->initializeSelectedSlices();
      addBrainModel(bmsv);
   }
}

/**
 * get a brain model surface.
 */
BrainModelSurface* 
02503 BrainSet::getBrainModelSurface(const int modelIndex) 
{ 
   if (modelIndex < getNumberOfBrainModels()) {
      if (brainModels[modelIndex]->getModelType() == BrainModel::BRAIN_MODEL_SURFACE) {
         return dynamic_cast<BrainModelSurface*>(brainModels[modelIndex]); 
      }
   }
   return NULL;
}

/**
 * get a brain model surface (const method).
 */
const BrainModelSurface* 
02517 BrainSet::getBrainModelSurface(const int modelIndex) const 
{ 
   if (modelIndex < getNumberOfBrainModels()) {
      if (brainModels[modelIndex]->getModelType() == BrainModel::BRAIN_MODEL_SURFACE) {
         return dynamic_cast<BrainModelSurface*>(brainModels[modelIndex]); 
      }
   }
   return NULL;
}
      
/**
 * get the index of the first brain model surface (returns -1 if not found).
 */
int 
02531 BrainSet::getFirstBrainModelSurfaceIndex() const
{
   for (int i = 0; i < getNumberOfBrainModels(); i++) {
      if (getBrainModelSurface(i) != NULL) {
         return i;
      }
   }
   return -1;
}
      
/**
 * Set the name of the spec file.  Also sets the current directory
 * to the directory of the spec file.  If name is empty, the
 * spec file is cleared.
 */
void
02547 BrainSet::setSpecFileName(const QString& name, const bool readOldSpecFileFlag)
{ 
   //
   // MUST read with the old spec file name and then
   // write with the new spec file name
   //
   const QString oldSpecFileName(specFileName);
   SpecFile sf;
   bool specValidFlag = false;
   if (readOldSpecFileFlag) {
       try {
          sf.readFile(specFileName);
          specValidFlag = true;
       }
       catch (FileException&) {
       }
   }

   specFileName = name;
   if (name.isEmpty() == false) {
      QDir::setCurrent(FileUtilities::dirname(name));
   }
   
   if (specValidFlag) {
      try {
         sf.writeFile(specFileName);
      }
      catch (FileException&) {
      }
   }
}

/**
 * Classify the nodes as interior/edges.  If the topology file is NULL
 * the most appropriate (cut) file will be used.
 */
void
02584 BrainSet::classifyNodes(TopologyFile* tfIn,
                        const bool onlyDoClassificationIfNeeded)
{
   if (onlyDoClassificationIfNeeded) {
      if (nodesHaveBeenClassified) {
         return;
      }
   }
   
   QTime timer;
   timer.start();
   
   TopologyFile* tf = tfIn;
   if (tf == NULL) {
      //
      // Pick most appropriate topology file
      //
      if (topologyCut != NULL) {
         tf = topologyCut;
      }
      else if (topologyLobarCut != NULL) {
         tf = topologyLobarCut;
      }
      else if (topologyOpen != NULL) {
         tf = topologyOpen;
      }
      else if (topologyClosed != NULL) {
         tf = topologyClosed;
      }
      else if (topologyUnknown != NULL) {
         tf = topologyUnknown;
      }
   }
   
   if (tf != NULL) {
      //
      // Default to interior nodes
      //
      const int numNodes = getNumberOfNodes();
      for (int i = 0; i < numNodes; i++) {
         nodeAttributes[i].classification = BrainSetNodeAttribute::CLASSIFICATION_TYPE_INTERIOR;
      }
      
      //
      // Any nodes used by an edge with only one tile is an edge node
      //
      const TopologyHelper* th = tf->getTopologyHelper(true, true, false);
      const std::set<TopologyEdgeInfo>& edges = th->getEdgeInfo();   
      for (std::set<TopologyEdgeInfo>::const_iterator iter = edges.begin();
         iter != edges.end(); iter++) {
         int node1, node2;
         iter->getNodes(node1, node2);
         int tile1, tile2;
         iter->getTiles(tile1, tile2);
         if (tile2 < 0) {
            nodeAttributes[node1].classification = BrainSetNodeAttribute::CLASSIFICATION_TYPE_EDGE;
            nodeAttributes[node2].classification = BrainSetNodeAttribute::CLASSIFICATION_TYPE_EDGE;
         }
      }
      
      //
      // Corner have only two neighbors
      //
      for (int i = 0; i < numNodes; i++) {
         std::vector<int> neighbors;
         th->getNodeNeighbors(i, neighbors);
         if (static_cast<int>(neighbors.size()) == 2) {
            nodeAttributes[i].classification = BrainSetNodeAttribute::CLASSIFICATION_TYPE_CORNER;
         }
      }
      
      nodesHaveBeenClassified = true;
   }
      
   if (DebugControl::getDebugOn()) {
      std::cout << "Time to classify nodes: " 
                << (static_cast<float>(timer.elapsed()) / 1000.0) << std::endl;
   }
   
   updateSurfaceOverlaysDueToChangeInBrainModels();
   clearAllDisplayLists();
}

/**
 * Disconnect the specified nodes and move them to the origin.
 */
void
02671 BrainSet::disconnectNodes(TopologyFile* tf, const std::vector<bool>& nodesToDisconnect)
{
   if (tf == NULL) {
      return;
   }
   tf->deleteTilesWithMarkedNodes(nodesToDisconnect);
   
   //
   // Move disconnected nodes to origin in all surfaces that use the topology file
   //
   const int numDisconnectNodes = static_cast<int>(nodesToDisconnect.size());   
   const float origin[3] = { 0.0, 0.0, 0.0 };
   for (int i = 0; i < getNumberOfBrainModels(); i++) {
      BrainModelSurface* bms = getBrainModelSurface(i);
      if (bms != NULL) {
         if (bms->getTopologyFile() == tf) {
            CoordinateFile* cf = bms->getCoordinateFile();
            int numNodesInCoord = bms->getNumberOfNodes();
            if (numNodesInCoord == numDisconnectNodes) {
               for (int j = 0; j < numNodesInCoord; j++) {
                  if (nodesToDisconnect[j]) {
                     cf->setCoordinate(j, origin);
                  }
               }
            }
         }
      }
   }
}

/**
 * Disconnect the nodes with the specified paint names in the specified paint column.
 */
void 
02705 BrainSet::disconnectNodes(TopologyFile* tf, const std::vector<QString>& paintNames,
                          const int paintColumn)
{
   //
   // Convert the paint names to paint indices
   //
   const PaintFile* pf = getPaintFile();
   std::vector<int> paintIndices;
   for (int i = 0; i < static_cast<int>(paintNames.size()); i++) {
      const int paintIndex = pf->getPaintIndexFromName(paintNames[i]);
      if (paintIndex >= 0) {
         paintIndices.push_back(paintIndex);
      }
   }
   
   //
   // Disconnect nodes with the specified paint indices
   //
   if (paintIndices.empty() == false) {
      disconnectNodes(tf, paintIndices, paintColumn);
   }
}
      
/**
 * Disconnect the nodes with the specified paint indices in the specified paint column.
 */
void 
02732 BrainSet::disconnectNodes(TopologyFile* tf, const std::vector<int>& paintIndices,
                          const int paintColumn)
{
   //
   // Make sure there is something in the paint file
   //
   const PaintFile* pf = getPaintFile();
   const int numNodes = pf->getNumberOfNodes();
   if (numNodes == 0) {
      return;
   }
   
   //
   // Check for valid paint column
   //
   if ((paintColumn >= 0) && (paintColumn < pf->getNumberOfColumns())) {
      //
      // Find the nodes with the paintIndices that should be disconnected
      //
      std::vector<bool> nodesToDisconnect(numNodes, false);
      for (int i = 0; i < numNodes; i++) {
         if (std::find(paintIndices.begin(), paintIndices.end(), pf->getPaint(i, paintColumn))
             != paintIndices.end()) {
            nodesToDisconnect[i] = true;
         }
      }
      
      //
      // Disconnect the nodes
      //
      disconnectNodes(tf, nodesToDisconnect);
   }
}                            

/**
 * convert volume borders to cells.
 */
void 
02770 BrainSet::convertVolumeBordersToFiducialCells()
{
   //
   // Get the border file
   //
   const BorderFile* bf = getVolumeBorderFile();
   const int numBorders = bf->getNumberOfBorders();

   //
   // Get the border and cell color files
   //
   const ColorFile* borderColors = getBorderColorFile();
   ColorFile* cellColors = getCellColorFile();
   
   //
   // Get the fiducial cell files
   //
   CellFile cf;
      
   //
   // Convert the border link points to cells
   //
   for (int i = 0; i < numBorders; i++) {
      //
      // Get the border and info
      //
      const Border* b = bf->getBorder(i);
      const QString borderName(b->getName());
      const int numLinks = b->getNumberOfLinks();
      
      //
      // Transfer color if needed
      //
      const int borderColorIndex = b->getBorderColorIndex();
      if (borderColorIndex >= 0) {
         const QString colorName = borderColors->getColorNameByIndex(borderColorIndex);
         bool exactMatch = false;
         const int colorIndex = cellColors->getColorIndexByName(colorName, exactMatch);
         if (colorIndex < 0) {
            unsigned char r, g, b;
            borderColors->getColorByIndex(borderColorIndex, r, g, b);
            cellColors->addColor(borderName, r, g, b);
         }
      }
      
      //
      // Convert link points to cells
      //
      for (int j = 0; j < numLinks; j++) {
         const float* xyz = b->getLinkXYZ(j);
         cf.addCell(CellData(borderName, xyz[0], xyz[1], xyz[2], 0));
      }
   }
   
   //
   // Append to existing cells
   //
   cellProjectionFile->appendFiducialCellFile(cf);
   
   //
   // Update cell display settings
   //
   displaySettingsCells->update();
}

/**
 * Set the selected topology files
 */
void
02839 BrainSet::setSelectedTopologyFiles()
{
   topologyClosed   = NULL;
   topologyOpen     = NULL;
   topologyCut      = NULL;
   topologyLobarCut = NULL;
   topologyUnknown  = NULL;
   
   const int numTopo = getNumberOfTopologyFiles();
   
   for (int i = 0; i < numTopo; i++) {
      TopologyFile* tf = getTopologyFile(i);
      
      switch(tf->getTopologyType()) {
          case TopologyFile::TOPOLOGY_TYPE_CLOSED:
             if (topologyClosed == NULL) {
                topologyClosed = tf;
             }
             break;
          case TopologyFile::TOPOLOGY_TYPE_OPEN:
             if (topologyOpen == NULL) {
                topologyOpen = tf;
             }
             break;
          case TopologyFile::TOPOLOGY_TYPE_CUT:
             if (topologyCut == NULL) {
                topologyCut = tf;
             }
             break;
          case TopologyFile::TOPOLOGY_TYPE_LOBAR_CUT:
             if (topologyLobarCut == NULL) {
                topologyLobarCut = tf;
             }
             break;
          case TopologyFile::TOPOLOGY_TYPE_UNKNOWN:
          case TopologyFile::TOPOLOGY_TYPE_UNSPECIFIED:
             if (topologyUnknown == NULL) {
                topologyUnknown = tf;
             }
             break;
      }
   }
   
   if (topologyClosed == NULL) {
      if (topologyOpen != NULL) {
         topologyClosed = topologyOpen;
      }
      else if (topologyCut != NULL) {
         topologyClosed = topologyCut;
      }
      else if (topologyLobarCut != NULL) {
         topologyClosed = topologyLobarCut;
      }
      else if (topologyUnknown != NULL) {
         topologyClosed = topologyUnknown;
      }
   }
   
   if (topologyOpen == NULL) {
      if (topologyClosed != NULL) {
         topologyOpen = topologyClosed;
      }
      else if (topologyCut != NULL) {
         topologyOpen = topologyCut;
      }
      else if (topologyLobarCut != NULL) {
         topologyOpen = topologyLobarCut;
      }
      else if (topologyUnknown != NULL) {
         topologyOpen = topologyUnknown;
      }
   }
   
   if (topologyCut == NULL) {
      if (topologyClosed != NULL) {
         topologyCut = topologyClosed;
      }
      else if (topologyOpen != NULL) {
         topologyCut = topologyOpen;
      }
      else if (topologyLobarCut != NULL) {
         topologyCut = topologyLobarCut;
      }
      else if (topologyUnknown != NULL) {
         topologyCut = topologyUnknown;
      }
   }
   
   if (topologyLobarCut == NULL) {
      if (topologyClosed != NULL) {
         topologyLobarCut = topologyClosed;
      }
      else if (topologyOpen != NULL) {
         topologyLobarCut = topologyOpen;
      }
      else if (topologyCut != NULL) {
         topologyLobarCut = topologyCut;
      }
      else if (topologyUnknown != NULL) {
         topologyLobarCut = topologyUnknown;
      }
   }
   
   if (topologyUnknown == NULL) {
      if (topologyClosed != NULL) {
         topologyUnknown = topologyClosed;
      }
      else if (topologyOpen != NULL) {
         topologyUnknown = topologyOpen;
      }
      else if (topologyCut != NULL) {
         topologyUnknown = topologyCut;
      }
      else if (topologyLobarCut != NULL) {
         topologyUnknown = topologyLobarCut;
      }
   }

/*   
   if (getNumberOfClosedTopologyFiles() > 0) {
      topologyClosed   = topologyClosedFiles[0];
      topologyOpen     = topologyClosed;
      topologyCut      = topologyClosed;
      topologyLobarCut = topologyClosed;
   }
   
   if (getNumberOfOpenTopologyFiles() > 0) {
      topologyOpen     = topologyOpenFiles[0];
      topologyCut      = topologyOpen;
      topologyLobarCut = topologyOpen;
      if (topologyClosed == NULL) {
         topologyClosed = topologyOpen;
      }
   }
   
   if (getNumberOfCutTopologyFiles() > 0) {
      topologyCut      = topologyCutFiles[0];
      topologyLobarCut = topologyCut;
      if (topologyClosed == NULL) {
         topologyClosed = topologyCut;
      }
      if (topologyOpen == NULL) {
         topologyOpen = topologyCut;
      }
   }
   
   if (getNumberOfLobarCutTopologyFiles() > 0) {
      topologyLobarCut = topologyLobarCutFiles[0];
      if (topologyClosed == NULL) {
         topologyClosed = topologyLobarCut;
      }
      if (topologyOpen == NULL) {
         topologyOpen = topologyLobarCut;
      }
      if (topologyCut == NULL) {
         topologyCut = topologyLobarCut;
      }
   }
   
   if (getNumberOfUnknownTopologyFiles() > 0) {
      if (topologyLobarCut == NULL) {
         topologyLobarCut = topologyUnknownFiles[0];
      }
      if (topologyClosed == NULL) {
         topologyClosed = topologyUnknownFiles[0];
      }
      if (topologyOpen == NULL) {
         topologyOpen = topologyUnknownFiles[0];
      }
      if (topologyCut == NULL) {
         topologyCut = topologyUnknownFiles[0];
      }
   }
*/
}

/**
 *  Update the file reading progress dialog.  Returns true if the cancel button was pressed
 *  and reading of files should terminate.
 */
bool
03020 BrainSet::updateFileReadProgressDialog(const QString& filename,
                                          int& progressFileCounter,
                                          QProgressDialog* progressDialog)
{
   if (progressDialog != NULL) {
      if (progressDialog->wasCanceled()) {
         readingSpecFileFlag = false;
         return true;
      }
      
      QString s("Reading: ");
      s.append(FileUtilities::basename(filename));
      progressDialog->setLabelText(s);
      progressFileCounter++;
      progressDialog->setValue(progressFileCounter);
      qApp->processEvents();  // note: qApp is global in QApplication
   }
   
   return false;
}

/**
 * create a spec file from all files in the selected scenes.
 */
void 
03045 BrainSet::createSpecFromScenes(const std::vector<int>& sceneIndices,
                               const QString& newSpecFileName,
                               const QString& newSceneFileName,
                               QString& errorMessageOut)
{
   //
   // The new scene file
   //
   SceneFile newSceneFile;
   
   //
   // Create a spec file
   //
   SpecFile newSpecFile;
   
   //
   // Set metadata
   //
   newSpecFile.setStructure(structure.getTypeAsString());
   newSpecFile.setSpecies(species.getName());
   newSpecFile.setSubject(subject);
   newSpecFile.setSpace(stereotaxicSpace);

   //
   // Loop through the scene file
   //
   const int numScenes = static_cast<int>(sceneIndices.size());
   for (int i = 0; i < numScenes; i++) {
      //
      // Get the scene
      //
      const SceneFile::Scene* scene = sceneFile->getScene(sceneIndices[i]);
      
      //
      // Add the scene to the new scene file
      //
      newSceneFile.addScene(*scene);
      
      //
      // Get the scenes spec file entries and add to new spec file
      //
      SpecFile sf;
      sf.showScene(*scene, errorMessageOut);
      newSpecFile.append(sf);
   }
   
   //
   // Write the new scene file
   //
   try {
      newSceneFile.writeFile(newSceneFileName);
   }
   catch (FileException& e) {
      errorMessageOut = e.whatQString();
      return;
   }
   
   //
   // Add the scene to the spec file 
   //
   newSpecFile.addToSpecFile(SpecFile::getSceneFileTag(),
                             FileUtilities::basename(newSceneFileName),
                             "",
                             false);

   //
   // Write the new spec file
   //
   try {
      newSpecFile.writeFile(newSpecFileName);
   }
   catch (FileException& e) {
      errorMessageOut = e.whatQString();
      return;
   }   
}

/**
 * Add a tag and file to the spec file.
 */
void
03126 BrainSet::addToSpecFile(const QString& specFileTag, const QString& fileName,
                        const QString& fileName2)
{
   //
   // The remainder of this routine must not be run by more than one thread
   //
   QMutexLocker locker(&mutexAddToSpecFile);
   
   //
   // Do not call sf.setStructure() since Unknown screws things up.
   //
   switch (structure.getType()) {
      case Structure::STRUCTURE_TYPE_CEREBELLUM:
         loadedFilesSpecFile.setStructure(Structure::getCerebellumAsString());
         break;
      case Structure::STRUCTURE_TYPE_CEREBELLUM_OR_CORTEX_LEFT:
         loadedFilesSpecFile.setStructure(Structure::getCerebellumOrLeftCerebralAsString());
         break;
      case Structure::STRUCTURE_TYPE_CEREBELLUM_OR_CORTEX_RIGHT:
         loadedFilesSpecFile.setStructure(Structure::getCerebellumOrRightCerebralAsString());
         break;
      case Structure::STRUCTURE_TYPE_CORTEX_LEFT:
         loadedFilesSpecFile.setStructure(Structure::getCortextLeftAsString());
         break;
      case Structure::STRUCTURE_TYPE_CORTEX_RIGHT:
         loadedFilesSpecFile.setStructure(Structure::getCortexRightAsString());
         break;
      case Structure::STRUCTURE_TYPE_CORTEX_BOTH:
         loadedFilesSpecFile.setStructure(Structure::getCortexBothAsString());
         break;
      case Structure::STRUCTURE_TYPE_CORTEX_LEFT_OR_CEREBELLUM:
         loadedFilesSpecFile.setStructure(Structure::getLeftCerebralOrCerebellumAsString());
         break;
      case Structure::STRUCTURE_TYPE_CORTEX_RIGHT_OR_CEREBELLUM:
         loadedFilesSpecFile.setStructure(Structure::getRightCerebralOrCerebellumAsString());
         break;
      case Structure::STRUCTURE_TYPE_CEREBRUM_CEREBELLUM:
         loadedFilesSpecFile.setStructure(Structure::getCerebrumAndCerebellumAsString());
         break;
      case Structure::STRUCTURE_TYPE_SUBCORTICAL:
         loadedFilesSpecFile.setStructure(Structure::getSubCorticalAsString());
         break;
      case Structure::STRUCTURE_TYPE_ALL:
         loadedFilesSpecFile.setStructure(Structure::getAllAsString());
         break;
      case Structure::STRUCTURE_TYPE_INVALID:
         // do not override if unknown
         break;
   }
   loadedFilesSpecFile.setSpecies(getSpecies().getName());
   loadedFilesSpecFile.setSubject(getSubject());
   //sf.setSpace(getSpace());
   //sf.setCategory(getCategory());
   
   //
   // add to spec file that keeps track of loaded files but do not write the spec file
   //
   loadedFilesSpecFile.addToSpecFile(specFileTag, fileName, fileName2, false);
   
   //
   // Update the spec file on the disk
   //
   if (readingSpecFileFlag == false) {
      if (specFileName.isEmpty() == false) {
         SpecFile sf;
         try {
            sf.readFile(specFileName);
         }
         catch (FileException& /*e*/) {
            // since file may not yet exist, ignore read error
         }
         sf.setFileName(specFileName);
         if (loadedFilesSpecFile.getStructure().isValid()) {
            sf.setStructure(loadedFilesSpecFile.getStructure());
         }
         if (loadedFilesSpecFile.getSpecies().isValid()) {
            sf.setSpecies(loadedFilesSpecFile.getSpecies().getName());
         }
         if (loadedFilesSpecFile.getSubject().isEmpty() == false) {
            sf.setSubject(loadedFilesSpecFile.getSubject());
         }
         sf.addToSpecFile(specFileTag, fileName, fileName2, true);
      }
   }
}
 
/** 
 * Write the node color file.
 */ 
void
03216 BrainSet::writeAreaColorFile(const QString& name) throw (FileException)
{
   loadedFilesSpecFile.areaColorFile.setAllSelections(SpecFile::SPEC_FALSE);
   areaColorFile->writeFile(name);
   addToSpecFile(SpecFile::getAreaColorFileTag(), name);
}
/**
 * Read the area color data file file
 */
void 
03226 BrainSet::readAreaColorFile(const QString& name, const bool append,
                            const bool updateSpec) throw (FileException)
{
   QMutexLocker locker(&mutexAreaColorFile);   
   
   if (append == false) {
      clearAreaColorFile();
   }
   const unsigned long modified = areaColorFile->getModified();
   
   if (areaColorFile->getNumberOfColors() == 0) {         
      try {
         areaColorFile->readFile(name);
      }
      catch (FileException& e) {
         clearAreaColorFile();
         throw FileException(FileUtilities::basename(name), e.whatQString());
      }
   }
   else {
      // Append to existing 
      AreaColorFile cf;
      cf.readFile(name);
      QString msg;
      areaColorFile->append(cf);
   }
   
   areaColorFile->setModifiedCounter(modified);
   
   if (updateSpec) {
      addToSpecFile(SpecFile::getAreaColorFileTag(), name);
   }
}

/**
 * add a document file.
 */
void 
03264 BrainSet::addDocumentFile(const QString& documentFileName)
{
   addToSpecFile(SpecFile::getDocumentFileTag(), documentFileName);
}
      
/** 
 * Write the areal estimation data file.
 */ 
void
03273 BrainSet::writeArealEstimationFile(const QString& name) throw (FileException)
{
   loadedFilesSpecFile.arealEstimationFile.setAllSelections(SpecFile::SPEC_FALSE);
   arealEstimationFile->writeFile(name);
   addToSpecFile(SpecFile::getArealEstimationFileTag(), name);
}

/**      
 * Read the areal estimation data file file
 */
void 
03284 BrainSet::readArealEstimationFile(const QString& name, const bool append,
                            const bool updateSpec) throw (FileException)
{
   QMutexLocker locker(&mutexArealEstimationFile);
   
   if (append == false) {
      clearArealEstimationFile();
   }
   const unsigned long modified = arealEstimationFile->getModified();
      
   if (arealEstimationFile->getNumberOfColumns() == 0) {         
      try {
         arealEstimationFile->readFile(name);
         if (arealEstimationFile->getNumberOfNodes() != getNumberOfNodes()) {
            throw FileException(FileUtilities::basename(name), numNodesMessage);
         }
      }
      catch (FileException& e) {
         clearArealEstimationFile();
         throw FileException(FileUtilities::basename(name), e.whatQString());
      }
   }
   else {
      // Append to existing areal estimations
      ArealEstimationFile aef;
      aef.readFile(name);
      if (aef.getNumberOfNodes() != getNumberOfNodes()) {
         throw FileException(FileUtilities::basename(name), numNodesMessage);
      }
      try {
         arealEstimationFile->append(aef);
      }
      catch (FileException& e) {
         throw FileException(FileUtilities::basename(name), e.whatQString());
      }
   }
   
   arealEstimationFile->setModifiedCounter(modified);
   displaySettingsArealEstimation->update();  

   if (updateSpec) {
      addToSpecFile(SpecFile::getArealEstimationFileTag(), name);
   }
}
      
/**
 * read the areal estimation data file file (only selected columns).
 */
void 
03333 BrainSet::readArealEstimationFile(const QString& name, 
                         const std::vector<int>& columnDestination,
                         const std::vector<QString>& fileBeingReadColumnNames,
                         const AbstractFile::FILE_COMMENT_MODE fcm,
                         const bool updateSpec) throw (FileException)
{
   QMutexLocker locker(&mutexArealEstimationFile);
   
   const bool arealEstimationFileEmpty = arealEstimationFile->empty();
   
   ArealEstimationFile aef;
   aef.readFile(name);
   if (aef.getNumberOfNodes() != getNumberOfNodes()) {
      throw FileException(FileUtilities::basename(name), numNodesMessage);
   }
   try {
      for (int i = 0; i < aef.getNumberOfColumns(); i++) {
         if (i < static_cast<int>(fileBeingReadColumnNames.size())) {
            aef.setColumnName(i, fileBeingReadColumnNames[i]);
         }
      }
      std::vector<int> columnDestination2 = columnDestination;
      arealEstimationFile->append(aef, columnDestination2, fcm);
   }
   catch (FileException& e) {
      throw FileException(FileUtilities::basename(name), e.whatQString());
   }
   if (arealEstimationFileEmpty) {
      arealEstimationFile->clearModified();
   }
   else {
      arealEstimationFile->setModified();
   }

   if (readingSpecFileFlag == false) {
      displaySettingsArealEstimation->update(); 
   }
   
   if (updateSpec) {
      addToSpecFile(SpecFile::getArealEstimationFileTag(), name);
   }
}

/**
 * read a volume border file.
 */
void 
03380 BrainSet::readVolumeBorderFile(const QString& name,
                               const bool append,
                               const bool updateSpec) throw (FileException)
{
   BorderFile* borderFile = getVolumeBorderFile();
   
   QMutexLocker locker(&mutexVolumeBorderFile);
   
   if (append || (borderFile->getNumberOfBorders() <= 0)) {
   
      borderFile->readFile(name);
   }
   else {
      BorderFile bf;
      bf.readFile(name);
      borderFile->append(bf);
   }

   if (updateSpec) {
      addToSpecFile(SpecFile::getVolumeBorderFileTag(), name);
   }
}

/**
 * write a volume border file.
 */
void 
03407 BrainSet::writeVolumeBorderFile(const QString& name,
                                const bool removeDuplicates) throw (FileException)
{
   loadedFilesSpecFile.volumeBorderFile.setAllSelections(SpecFile::SPEC_FALSE);
   BorderFile* borderFile = getVolumeBorderFile();
   
   if (removeDuplicates) {
      std::vector<int> indices;
      borderFile->getDuplicateBorderIndices(indices);
      borderFile->removeBordersWithIndices(indices);
   }
   
   borderFile->setHeaderTag(AbstractFile::headerTagConfigurationID, "VOLUME");
   
   borderFile->writeFile(name);
   addToSpecFile(SpecFile::getVolumeBorderFileTag(), name);
}                                 

/** 
 * Write the border data file.
 */ 
void
03429 BrainSet::writeBorderFile(const QString& name,
                          const BrainModelSurface* bms,
                          const BrainModelSurface::SURFACE_TYPES borderFileType,
                          const QString& commentText,
                          const QString& pubMedID,
                          const bool removeDuplicates) throw (FileException)
{
   //
   // Find borders that are used on the specified surface
   //
   BorderFile borderFile;   
   borderFile.setFileComment(commentText);
   borderFile.setFilePubMedID(pubMedID);
   brainModelBorderSet->copyBordersToBorderFile(bms, borderFile);
   if (removeDuplicates) {
      std::vector<int> indices;
      borderFile.getDuplicateBorderIndices(indices);
      borderFile.removeBordersWithIndices(indices);
   }
   borderFile.setHeaderTag(AbstractFile::headerTagConfigurationID,
      BrainModelSurface::getSurfaceConfigurationIDFromType(borderFileType));
   
   if (borderFile.getNumberOfBorders() <= 0) {
      QString msg("There are no borders for surface ");
      msg.append(FileUtilities::basename(bms->getFileName()));
      throw FileException(name, msg);
   }
   
   QString tag;
   
   switch(borderFileType) {
      case BrainModelSurface::SURFACE_TYPE_RAW:
         tag = SpecFile::getRawBorderFileTag();
         loadedFilesSpecFile.rawBorderFile.setAllSelections(SpecFile::SPEC_FALSE);
         break;
      case BrainModelSurface::SURFACE_TYPE_FIDUCIAL:
         tag = SpecFile::getFiducialBorderFileTag();
         loadedFilesSpecFile.fiducialBorderFile.setAllSelections(SpecFile::SPEC_FALSE);
         break;
      case BrainModelSurface::SURFACE_TYPE_INFLATED:
         tag = SpecFile::getInflatedBorderFileTag();
         loadedFilesSpecFile.inflatedBorderFile.setAllSelections(SpecFile::SPEC_FALSE);
         break;
      case BrainModelSurface::SURFACE_TYPE_VERY_INFLATED:
         tag = SpecFile::getVeryInflatedBorderFileTag();
         loadedFilesSpecFile.veryInflatedBorderFile.setAllSelections(SpecFile::SPEC_FALSE);
         break;
      case BrainModelSurface::SURFACE_TYPE_SPHERICAL:
         tag = SpecFile::getSphericalBorderFileTag();
         loadedFilesSpecFile.sphericalBorderFile.setAllSelections(SpecFile::SPEC_FALSE);
         break;
      case BrainModelSurface::SURFACE_TYPE_ELLIPSOIDAL:
         tag = SpecFile::getEllipsoidBorderFileTag();
         loadedFilesSpecFile.ellipsoidBorderFile.setAllSelections(SpecFile::SPEC_FALSE);
         break;
      case BrainModelSurface::SURFACE_TYPE_COMPRESSED_MEDIAL_WALL:
         tag = SpecFile::getCompressedBorderFileTag();
         loadedFilesSpecFile.compressedBorderFile.setAllSelections(SpecFile::SPEC_FALSE);
         break;
      case BrainModelSurface::SURFACE_TYPE_FLAT:
         tag = SpecFile::getFlatBorderFileTag();
         loadedFilesSpecFile.flatBorderFile.setAllSelections(SpecFile::SPEC_FALSE);
         break;
      case BrainModelSurface::SURFACE_TYPE_FLAT_LOBAR:
         tag = SpecFile::getLobarFlatBorderFileTag();
         loadedFilesSpecFile.lobarFlatBorderFile.setAllSelections(SpecFile::SPEC_FALSE);
         break;
      case BrainModelSurface::SURFACE_TYPE_HULL:
         tag = SpecFile::getHullCoordFileTag();
         loadedFilesSpecFile.hullBorderFile.setAllSelections(SpecFile::SPEC_FALSE);
         break;
      case BrainModelSurface::SURFACE_TYPE_UNKNOWN:
      case BrainModelSurface::SURFACE_TYPE_UNSPECIFIED:
      default:
         tag = SpecFile::getUnknownBorderFileMatchTag();
         loadedFilesSpecFile.unknownBorderFile.setAllSelections(SpecFile::SPEC_FALSE);
         break;
   }
   
   borderFile.setHeaderTag(AbstractFile::headerTagConfigurationID,
                  BrainModelSurface::getSurfaceConfigurationIDFromType(bms->getSurfaceType()));
                            
   borderFile.writeFile(name);
   addToSpecFile(tag, name);
   BrainModelBorderFileInfo* bmi = brainModelBorderSet->getBorderFileInfo(borderFileType);
   bmi->setFileName(name);
   bmi->setFileComment(commentText);
   bmi->setPubMedID(pubMedID);
   brainModelBorderSet->setSurfaceBordersModified(bms, false);
}

/**      
 * Read the border data file file
 */
void 
03524 BrainSet::readBorderFile(const QString& name, const BrainModelSurface::SURFACE_TYPES stin,
                         const bool append,
                         const bool updateSpec) throw (FileException)
{
   BrainModelSurface::SURFACE_TYPES st = stin;
   if (st == BrainModelSurface::SURFACE_TYPE_UNSPECIFIED) {
      BorderFile b;
      b.readFileMetaDataOnly(name);
      const QString typeTag = b.getHeaderTag(AbstractFile::headerTagConfigurationID);
      if (typeTag.isEmpty() == false) {
         st = BrainModelSurface::getSurfaceTypeFromConfigurationID(typeTag);
      }
   }
   
   QString tag;
   
   switch(st) {
      case BrainModelSurface::SURFACE_TYPE_RAW:
         tag = SpecFile::getRawBorderFileTag();
         break;
      case BrainModelSurface::SURFACE_TYPE_FIDUCIAL:
         tag = SpecFile::getFiducialBorderFileTag();
         break;
      case BrainModelSurface::SURFACE_TYPE_INFLATED:
         tag = SpecFile::getInflatedBorderFileTag();
         break;
      case BrainModelSurface::SURFACE_TYPE_VERY_INFLATED:
         tag = SpecFile::getVeryInflatedBorderFileTag();
         break;
      case BrainModelSurface::SURFACE_TYPE_SPHERICAL:
         tag = SpecFile::getSphericalBorderFileTag();
         break;
      case BrainModelSurface::SURFACE_TYPE_ELLIPSOIDAL:
         tag = SpecFile::getEllipsoidBorderFileTag();
         break;
      case BrainModelSurface::SURFACE_TYPE_COMPRESSED_MEDIAL_WALL:
         tag = SpecFile::getCompressedBorderFileTag();
         break;
      case BrainModelSurface::SURFACE_TYPE_FLAT:
         tag = SpecFile::getFlatBorderFileTag();
         break;
      case BrainModelSurface::SURFACE_TYPE_FLAT_LOBAR:
         tag = SpecFile::getLobarFlatBorderFileTag();
         break;
      case BrainModelSurface::SURFACE_TYPE_HULL:
         tag = SpecFile::getHullBorderFileTag();
         break;
      case BrainModelSurface::SURFACE_TYPE_UNKNOWN:
      case BrainModelSurface::SURFACE_TYPE_UNSPECIFIED:
         tag = SpecFile::getUnknownBorderFileMatchTag();
         break;
   }
   
   BorderFile borderFile;
   try {
      borderFile.readFile(name);
   }
   catch (FileException& e) {
      borderFile.clear();
      throw FileException(FileUtilities::basename(name), e.whatQString());
   }
   
   //
   // Update configuration ID in the border file
   //
   const QString configID = 
      BrainModelSurface::getSurfaceConfigurationIDFromType(st);
   borderFile.setHeaderTag(AbstractFile::headerTagConfigurationID, configID);
   borderFile.clearModified();

   //
   // If transformation matrix should be applied
   //
   if ((st == BrainModelSurface::SURFACE_TYPE_RAW) ||
       (st == BrainModelSurface::SURFACE_TYPE_FIDUCIAL)) {
      if (specDataFileTransformationMatrix.isIdentity() == false) {
         borderFile.applyTransformationMatrix(specDataFileTransformationMatrix);
         borderFile.clearModified();
      }
   }
   
   //
   // Add to current borders.
   //
   QMutexLocker locker(&mutexBorderAndBorderProjectionFile);

   if (append == false) {
      deleteAllBorders();
   }
   
   brainModelBorderSet->copyBordersFromBorderFile(&borderFile, st);
   
   if (readingSpecFileFlag == false) {
      displaySettingsBorders->update();   
   }
   
   if (updateSpec) {
      addToSpecFile(tag, name);
   }
}
      
/** 
 * Write the border color data file.
 */ 
void
03629 BrainSet::writeBorderColorFile(const QString& name) throw (FileException)
{
   loadedFilesSpecFile.borderColorFile.setAllSelections(SpecFile::SPEC_FALSE);
   borderColorFile->writeFile(name);
   addToSpecFile(SpecFile::getBorderColorFileTag(), name);
}

/**      
 * Read the border color data file file
 */
void 
03640 BrainSet::readBorderColorFile(const QString& name, const bool append,
                            const bool updateSpec) throw (FileException)
{
   QMutexLocker locker(&mutexBorderColorFile);

   if (append == false) {
      clearBorderColorFile();
   }
   
   const unsigned long modified = borderColorFile->getModified();
   
   if (borderColorFile->getNumberOfColors() == 0) {         
      try {
         borderColorFile->readFile(name);
      }
      catch (FileException& e) {
         clearBorderColorFile();
         throw FileException(FileUtilities::basename(name), e.whatQString());
      }
   }
   else {
      // Append to existing 
      BorderColorFile cf;
      cf.readFile(name);
      borderColorFile->append(cf);
   }
   
   borderColorFile->setModifiedCounter(modified);
   
   if (updateSpec) {
      addToSpecFile(SpecFile::getBorderColorFileTag(), name);
   }
}
      
/** 
 * Write the border projection data file.
 */ 
void
03678 BrainSet::writeBorderProjectionFile(const QString& name,
                                    const QString& commentText,
                                    const QString& pubMedID,
                                    const bool removeDuplicates) throw (FileException)
{
   loadedFilesSpecFile.borderProjectionFile.setAllSelections(SpecFile::SPEC_FALSE);
   BorderProjectionFile borderProjFile;
   brainModelBorderSet->copyBordersToBorderProjectionFile(borderProjFile);
   if (removeDuplicates) {
      std::vector<int> indices;
      borderProjFile.getDuplicateBorderProjectionIndices(indices);
      borderProjFile.removeBordersWithIndices(indices);
   }
   borderProjFile.setFileComment(commentText);
   borderProjFile.setFilePubMedID(pubMedID);
   borderProjFile.writeFile(name);
   addToSpecFile(SpecFile::getBorderProjectionFileTag(), name);
   BrainModelBorderFileInfo* bmi = brainModelBorderSet->getBorderProjectionFileInfo();
   bmi->setFileName(name);
   bmi->setFileComment(commentText);
   bmi->setPubMedID(pubMedID);
   brainModelBorderSet->setProjectionsModified(false);
}

/**      
 * Read the border projection data file file
 */
void 
03706 BrainSet::readBorderProjectionFile(const QString& name, 
                                   const bool append,
                                   const bool updateSpec) throw (FileException)
{
   BorderProjectionFile borderProjFile;         
   try {
      borderProjFile.readFile(name);
   }
   catch (FileException& e) {
      throw FileException(FileUtilities::basename(name), e.whatQString());
   }

   QMutexLocker locker(&mutexBorderAndBorderProjectionFile);
   
   if (append == false) {
      deleteAllBorders();
   }
   bool modified = brainModelBorderSet->getProjectionsModified();
   
   const bool hadBorders = (brainModelBorderSet->getNumberOfBorders() > 0);
   brainModelBorderSet->copyBordersFromBorderProjectionFile(&borderProjFile);
   brainModelBorderSet->setProjectionsModified(modified);

   if (readingSpecFileFlag == false) {
      displaySettingsBorders->update();   
   }
   
   if (hadBorders == false) {
      brainModelBorderSet->setAllBordersModifiedStatus(false);
      brainModelBorderSet->setProjectionsModified(false);
   }
   
   if (updateSpec) {
      addToSpecFile(SpecFile::getBorderProjectionFileTag(), name);
   }
}
     
/** 
 * Write the cell data file.
 */ 
void
03747 BrainSet::writeCellFile(const QString& name,
                        const BrainModelSurface* bms,
                        const AbstractFile::FILE_FORMAT fileFormat,
                        const QString& commentText) throw (FileException)
{
   //
   // Check for fiducial surface
   //
   const bool fiducialSurfaceFlag = 
      ((bms->getSurfaceType() == BrainModelSurface::SURFACE_TYPE_RAW) ||
       (bms->getSurfaceType() == BrainModelSurface::SURFACE_TYPE_FIDUCIAL));
       
   //
   // Get cells for surface
   //
   CellFile cf;
   cellProjectionFile->getCellFile(bms->getCoordinateFile(),
                                   bms->getTopologyFile(),
                                   fiducialSurfaceFlag,
                                   cf);
   if (cf.getNumberOfCells() <= 0) {
      throw FileException("There are no cells that project to the selected surface.");
   }
   cf.setFileComment(commentText);
   cf.setFileWriteType(fileFormat);
   cf.writeFile(name);
   addToSpecFile(SpecFile::getCellFileTag(), name);
}

/**      
 * Read the cell data file file
 */
void 
03780 BrainSet::readCellFile(const QString& name, 
                       const bool append,
                       const bool updateSpec) throw (FileException)
{
   QMutexLocker locker(&mutexCellAndCellProjectionFile);
   
   if (append == false) {
      //deleteCellsOfType(st);
      deleteAllCells(true, true);
   }
   
   CellFile cellFile;
   try {
      cellFile.readFile(name);
      //
      // If transformation should be applied
      //
      if (specDataFileTransformationMatrix.isIdentity() == false) {
         cellFile.applyTransformationMatrix(std::numeric_limits<int>::min(),
                                             std::numeric_limits<int>::max(),
                                             specDataFileTransformationMatrix,
                                             false);
      }
   }
   catch (FileException& e) {
      throw FileException(FileUtilities::basename(name), e.whatQString());
   }

   cellProjectionFile->appendFiducialCellFile(cellFile);

   if (updateSpec) {
      addToSpecFile(SpecFile::getCellFileTag(), name);
   }
}
      
/** 
 * Write the cell data file.
 */ 
void
03819 BrainSet::writeVolumeCellFile(const QString& name) throw (FileException)
{
   loadedFilesSpecFile.volumeCellFile.setAllSelections(SpecFile::SPEC_FALSE);

   CellFile* cf = getVolumeCellFile();
   if (cf != NULL) {
      cf->writeFile(name);
      addToSpecFile(SpecFile::getVolumeCellFileTag(), name);
   }
   else {
      throw FileException("", "There is no volume cell file to write.");
   }
}

/**      
 * Read the cell data file file
 */
void 
03837 BrainSet::readVolumeCellFile(const QString& name, 
                             const bool append,
                             const bool updateSpec) throw (FileException)
{
   QMutexLocker locker(&mutexVolumeCellFile);
   
   if (append == false) {
      deleteAllCells(false, true);
   }
   
   const unsigned long modified = volumeCellFile->getModified();
   
   if (volumeCellFile->getNumberOfCells() == 0) {         
      try {
         volumeCellFile->readFile(name);
         //
         // If transformation should be applied
         //
         if (specDataFileTransformationMatrix.isIdentity() == false) {
            volumeCellFile->applyTransformationMatrix(std::numeric_limits<int>::min(),
                                                std::numeric_limits<int>::max(),
                                                specDataFileTransformationMatrix,
                                                false);
         }
      }
      catch (FileException& e) {
         deleteAllCells(false, true);
         throw FileException(FileUtilities::basename(name), e.whatQString());
      }
   }
   else {
      // Append to existing 
      CellFile cf;
      cf.readFile(name);
      //
      // If transformation should be applied
      //
      if (specDataFileTransformationMatrix.isIdentity() == false) {
         cf.applyTransformationMatrix(std::numeric_limits<int>::min(),
                                             std::numeric_limits<int>::max(),
                                             specDataFileTransformationMatrix,
                                             false);
      }
      volumeCellFile->append(cf);
   }
   volumeCellFile->setModifiedCounter(modified);

   displaySettingsCells->update();

   if (updateSpec) {
      addToSpecFile(SpecFile::getVolumeCellFileTag(), name);
   }
}
      
/** 
 * Write the cell color data file.
 */ 
void
03895 BrainSet::writeCellColorFile(const QString& name) throw (FileException)
{
   loadedFilesSpecFile.cellColorFile.setAllSelections(SpecFile::SPEC_FALSE);
   cellColorFile->writeFile(name);
   addToSpecFile(SpecFile::getCellColorFileTag(), name);
}

/**      
 * Read the cell color data file file
 */
void 
03906 BrainSet::readCellColorFile(const QString& name, const bool append,
                            const bool updateSpec) throw (FileException)
{
   QMutexLocker locker(&mutexCellColorFile);
   
   if (append == false) {
      clearCellColorFile();
   }
   const unsigned long modified = cellColorFile->getModified();
   
   if (cellColorFile->getNumberOfColors() == 0) {         
      try {
         cellColorFile->readFile(name);
      }
      catch (FileException& e) {
         clearCellColorFile();
         throw FileException(FileUtilities::basename(name), e.whatQString());
      }
   }
   else {
      // Append to existing 
      CellColorFile cf;
      cf.readFile(name);
      //QString msg;
      cellColorFile->append(cf);
   }
   
   cellColorFile->setModifiedCounter(modified);
   
   if (updateSpec) {
      addToSpecFile(SpecFile::getCellColorFileTag(), name);
   }
}
      
/** 
 * Write the cell projection data file.
 */ 
void
03944 BrainSet::writeCellProjectionFile(const QString& name) throw (FileException)
{
   loadedFilesSpecFile.cellProjectionFile.setAllSelections(SpecFile::SPEC_FALSE);
   cellProjectionFile->writeFile(name);
   addToSpecFile(SpecFile::getCellProjectionFileTag(), name);
}

/**      
 * Read the cell projection data file file
 */
void 
03955 BrainSet::readCellProjectionFile(const QString& name, 
                                 const bool append,
                                 const bool updateSpec) throw (FileException)
{
   QMutexLocker locker(&mutexCellAndCellProjectionFile);
   
   if (append == false) {
      deleteAllCellProjections();
   }
   const unsigned long modified = cellProjectionFile->getModified();
   
   if (cellProjectionFile->getNumberOfCellProjections() == 0) {         
      try {
         cellProjectionFile->readFile(name);
      }
      catch (FileException& e) {
         deleteAllCellProjections();
         throw FileException(FileUtilities::basename(name), e.whatQString());
      }
   }
   else {
      // Append to existing 
      CellProjectionFile cf;
      cf.readFile(name);
      QString msg;
      cellProjectionFile->append(cf);
   }
   
   cellProjectionFile->setModifiedCounter(modified);
   displaySettingsCells->update();
   
   if (updateSpec) {
      addToSpecFile(SpecFile::getCellProjectionFileTag(), name);
   }
}

/** 
 * Write the CocomacConnectivity data file.
 */ 
void
03995 BrainSet::writeCocomacConnectivityFile(const QString& name) throw (FileException)
{
   loadedFilesSpecFile.cocomacConnectivityFile.setAllSelections(SpecFile::SPEC_FALSE);
   cocomacFile->writeFile(name);
   addToSpecFile(SpecFile::getCocomacConnectivityFileTag(), name);
}

/**
 * Read a Cocomac Connectivity file.
 */
void
04006 BrainSet::readCocomacConnectivityFile(const QString& name, const bool append,
                                      const bool updateSpec) throw (FileException)
{
   QMutexLocker locker(&mutexCocomacFile);
   
   if (append == false) {
      clearCocomacConnectivityFile();
   }
   const unsigned long modified = cocomacFile->getModified();
   
   if (cocomacFile->getNumberOfCocomacProjections() == 0) {         
      try {
         cocomacFile->readFile(name);
      }
      catch (FileException& e) {
         clearCocomacConnectivityFile();
         throw FileException(FileUtilities::basename(name), e.whatQString());
      }
   }
   else {
      // Append to existing 
      CocomacConnectivityFile cf;
      cf.readFile(name);
      QString msg;
      cocomacFile->append(cf, msg);
      if (msg.isEmpty() == false) {
         throw FileException(FileUtilities::basename(name), msg);
      }
   }
   
   cocomacFile->setModifiedCounter(modified);
   displaySettingsCoCoMac->update();
   
   if (updateSpec) {
      addToSpecFile(SpecFile::getCocomacConnectivityFileTag(), name);
   }
}

/** 
 * Write the contour data file.
 */ 
void
04048 BrainSet::writeContourFile(const QString& name, ContourFile* cf) throw (FileException)
{
   loadedFilesSpecFile.contourFile.setAllSelections(SpecFile::SPEC_FALSE);
   cf->writeFile(name);
   addToSpecFile(SpecFile::getContourFileTag(), name);
}

/**
 * Read a Contour file.
 */
void
04059 BrainSet::readContourFile(const QString& name, 
                          const bool append,
                          const bool updateSpec) throw (FileException)
{
   QMutexLocker locker(&mutexContourFile);
   
   if (append == false) {
      clearContourFile(false);
   }
   
   BrainModelContours* bmc = getBrainModelContours(-1);
   bool createdBrainModelContours = false;
   if (bmc == NULL) {
      bmc = new BrainModelContours(this);
      createdBrainModelContours = true;
   }
   try {
      bmc->readContourFile(name, append);
      if (createdBrainModelContours) {
         addBrainModel(bmc);
      }
      if (updateSpec) {
         addToSpecFile(SpecFile::getContourFileTag(), name);
      }
   }
   catch (FileException& e) {
      if (createdBrainModelContours) {
         delete bmc;
      }
      throw e;
   }
   displaySettingsContours->update();
}

/** 
 * Write the contour cell data file.
 */ 
void
04097 BrainSet::writeContourCellFile(const QString& name) throw (FileException)
{
   loadedFilesSpecFile.contourCellFile.setAllSelections(SpecFile::SPEC_FALSE);
   contourCellFile->writeFile(name);
   addToSpecFile(SpecFile::getContourCellFileTag(), name);
}

/**      
 * Read the contour cell data file
 */
void 
04108 BrainSet::readContourCellFile(const QString& name, 
                              const bool append,
                              const bool updateSpec) throw (FileException)
{
   QMutexLocker locker(&mutexContourCellFile);     
   
   if (append == false) {
      clearContourCellFile();
   }
   const unsigned long modified = contourCellFile->getModified();
   
   if (contourCellFile->getNumberOfCells() == 0) {    
      try {
         contourCellFile->readFile(name);
      }
      catch (FileException& e) {
         clearContourCellFile();
         throw FileException(FileUtilities::basename(name), e.whatQString());
      }
   }
   else {
      // Append to existing 
      ContourCellFile cf;
      cf.readFile(name);
      contourCellFile->append(cf);
   }

   contourCellFile->setModifiedCounter(modified);
   displaySettingsCells->update();
   
   if (updateSpec) {
      addToSpecFile(SpecFile::getContourCellFileTag(), name);
   }
}

/** 
 * Write the contour cell color data file.
 */ 
void
04147 BrainSet::writeContourCellColorFile(const QString& name) throw (FileException)
{
   loadedFilesSpecFile.contourCellColorFile.setAllSelections(SpecFile::SPEC_FALSE);
   contourCellColorFile->writeFile(name);
   addToSpecFile(SpecFile::getContourCellColorFileTag(), name);
}

/**      
 * Read the contour cell color data file
 */
void 
04158 BrainSet::readContourCellColorFile(const QString& name, 
                                   const bool append,
                                   const bool updateSpec) throw (FileException)
{
   QMutexLocker locker(&mutexContourCellColorFile);
   
   if (append == false) {
      clearContourCellColorFile();
   }
   const unsigned long modified = contourCellColorFile->getModified();
   
   if (contourCellColorFile->getNumberOfColors() == 0) {         
      try {
         contourCellColorFile->readFile(name);
      }
      catch (FileException& e) {
         clearContourCellColorFile();
         throw FileException(FileUtilities::basename(name), e.whatQString());
      }
   }
   else {
      // Append to existing 
      ContourCellColorFile cf;
      cf.readFile(name);
      contourCellColorFile->append(cf);
   }
   contourCellColorFile->setModifiedCounter(modified);
   displaySettingsContours->update();
   
   if (updateSpec) {
      addToSpecFile(SpecFile::getContourCellColorFileTag(), name);
   }
}

/**
 * Set the deformation map file name.
 */
void 
04196 BrainSet::setDeformationMapFileName(const QString& name, const bool updateSpec)
{
   deformationMapFileName = name;
   if (updateSpec) {
      addToSpecFile(SpecFile::getDeformationMapFileTag(), name);
   }
}      
      
/** 
 * Write the cuts data file.
 */ 
void
04208 BrainSet::writeCutsFile(const QString& name) throw (FileException)
{
   loadedFilesSpecFile.cutsFile.setAllSelections(SpecFile::SPEC_FALSE);
   cutsFile->writeFile(name);
   addToSpecFile(SpecFile::getCutsFileTag(), name);
}

/**
 * Read a cuts  file.
 */
void
04219 BrainSet::readCutsFile(const QString& name, const bool append,
                       const bool updateSpec) throw (FileException)
{
   QMutexLocker locker(&mutexCutsFile);
   
   if (append == false) {
      clearCutsFile();
   }
   const unsigned long modified = cutsFile->getModified();
   
   if (cutsFile->getNumberOfBorders() == 0) {         
      try {
         cutsFile->readFile(name);
      }
      catch (FileException& e) {
         clearCutsFile();
         throw FileException(FileUtilities::basename(name), e.whatQString());
      }
   }
   else {
      // Append to existing 
      CutsFile cf;
      cf.readFile(name);
      QString msg;
      cutsFile->append(cf);
      if (msg.isEmpty() == false) {
         throw FileException(FileUtilities::basename(name), msg);
      }
   }
   cutsFile->setModifiedCounter(modified);
   displaySettingsCuts->update();
   
   if (updateSpec) {
      addToSpecFile(SpecFile::getCutsFileTag(), name);
   }
} 

/**
 * Remove any surfaces of the specified type from the brain models.
 */
void
04260 BrainSet::deleteSurfacesOfType(const BrainModelSurface::SURFACE_TYPES st)
{
   std::vector<BrainModelSurface*> modelsToDelete;
   
   for (int i = 0; i < getNumberOfBrainModels(); i++) {
      BrainModel* bm = getBrainModel(i);
      if (bm->getModelType() == BrainModel::BRAIN_MODEL_SURFACE) {
         BrainModelSurface* bms = dynamic_cast<BrainModelSurface*>(bm);
         if (bms->getSurfaceType() != st) {
            modelsToDelete.push_back(bms);
         }
      }
   }
   
   for (unsigned int i = 0; i < modelsToDelete.size(); i++) {
      deleteBrainModelSurface(modelsToDelete[i]);
   }
   
   nodeColoring->assignColors();
   clearAllDisplayLists();
}

/**
 * write the surface data file.
 */
void 
04286 BrainSet::writeSurfaceFile(const QString& name, 
                           const BrainModelSurface::SURFACE_TYPES st,
                           BrainModelSurface* bms,
                           const bool updateSpecFile,
                           const AbstractFile::FILE_FORMAT fileFormat) throw (FileException)
{
   QString oldFileName = FileUtilities::filenameWithoutExtension(
                                        bms->getCoordinateFile()->getFileName());
   oldFileName.append(SpecFile::getGiftiSurfaceFileExtension());
   
   const BrainModelSurface::SURFACE_TYPES st1 = bms->getSurfaceType();
   switch (st1) {
      case BrainModelSurface::SURFACE_TYPE_RAW:
         loadedFilesSpecFile.rawSurfaceFile.clearSelectionStatus(oldFileName);
         break;
      case BrainModelSurface::SURFACE_TYPE_FIDUCIAL:
         loadedFilesSpecFile.fiducialSurfaceFile.clearSelectionStatus(oldFileName);
         break;
      case BrainModelSurface::SURFACE_TYPE_INFLATED:
         loadedFilesSpecFile.inflatedSurfaceFile.clearSelectionStatus(oldFileName);
         break;
      case BrainModelSurface::SURFACE_TYPE_VERY_INFLATED:
         loadedFilesSpecFile.veryInflatedSurfaceFile.clearSelectionStatus(oldFileName);
         break;
      case BrainModelSurface::SURFACE_TYPE_SPHERICAL:
         loadedFilesSpecFile.sphericalSurfaceFile.clearSelectionStatus(oldFileName);
         break;
      case BrainModelSurface::SURFACE_TYPE_ELLIPSOIDAL:
         loadedFilesSpecFile.ellipsoidSurfaceFile.clearSelectionStatus(oldFileName);
         break;
      case BrainModelSurface::SURFACE_TYPE_COMPRESSED_MEDIAL_WALL:
         loadedFilesSpecFile.compressedSurfaceFile.clearSelectionStatus(oldFileName);
         break;
      case BrainModelSurface::SURFACE_TYPE_FLAT:
         loadedFilesSpecFile.flatSurfaceFile.clearSelectionStatus(oldFileName);
         break;
      case BrainModelSurface::SURFACE_TYPE_FLAT_LOBAR:
         loadedFilesSpecFile.lobarFlatSurfaceFile.clearSelectionStatus(oldFileName);
         break;
      case BrainModelSurface::SURFACE_TYPE_HULL:
         loadedFilesSpecFile.hullSurfaceFile.clearSelectionStatus(oldFileName);
         break;
      case BrainModelSurface::SURFACE_TYPE_UNKNOWN:
      case BrainModelSurface::SURFACE_TYPE_UNSPECIFIED:
         loadedFilesSpecFile.unknownSurfaceFile.clearSelectionStatus(oldFileName);
         break;
   }

   //
   // Update surface to new type
   //
   bms->setSurfaceType(st);
   
   //
   // Write the surface file
   //
   bms->writeSurfaceFile(name, fileFormat);
   
   if (updateSpecFile) {
      addToSpecFile(BrainModelSurface::getSurfaceSpecFileTagFromSurfaceType(st), name);
   }
}

/** 
 * Write the coordinate data file.
 */ 
void
04353 BrainSet::writeCoordinateFile(const QString& name, 
                              const BrainModelSurface::SURFACE_TYPES st,
                              CoordinateFile* cf,
                              const bool updateSpecFile) throw (FileException)
{
   const QString typeTag = cf->getHeaderTag(AbstractFile::headerTagConfigurationID);
   if (typeTag.isEmpty() == false) {
      const BrainModelSurface::SURFACE_TYPES st1 = 
                               BrainModelSurface::getSurfaceTypeFromConfigurationID(typeTag);
      switch (st1) {
         case BrainModelSurface::SURFACE_TYPE_RAW:
            loadedFilesSpecFile.rawCoordFile.clearSelectionStatus(cf->getFileName());
            break;
         case BrainModelSurface::SURFACE_TYPE_FIDUCIAL:
            loadedFilesSpecFile.fiducialCoordFile.clearSelectionStatus(cf->getFileName());
            break;
         case BrainModelSurface::SURFACE_TYPE_INFLATED:
            loadedFilesSpecFile.inflatedCoordFile.clearSelectionStatus(cf->getFileName());
            break;
         case BrainModelSurface::SURFACE_TYPE_VERY_INFLATED:
            loadedFilesSpecFile.veryInflatedCoordFile.clearSelectionStatus(cf->getFileName());
            break;
         case BrainModelSurface::SURFACE_TYPE_SPHERICAL:
            loadedFilesSpecFile.sphericalCoordFile.clearSelectionStatus(cf->getFileName());
            break;
         case BrainModelSurface::SURFACE_TYPE_ELLIPSOIDAL:
            loadedFilesSpecFile.ellipsoidCoordFile.clearSelectionStatus(cf->getFileName());
            break;
         case BrainModelSurface::SURFACE_TYPE_COMPRESSED_MEDIAL_WALL:
            loadedFilesSpecFile.compressedCoordFile.clearSelectionStatus(cf->getFileName());
            break;
         case BrainModelSurface::SURFACE_TYPE_FLAT:
            loadedFilesSpecFile.flatCoordFile.clearSelectionStatus(cf->getFileName());
            break;
         case BrainModelSurface::SURFACE_TYPE_FLAT_LOBAR:
            loadedFilesSpecFile.lobarFlatCoordFile.clearSelectionStatus(cf->getFileName());
            break;
         case BrainModelSurface::SURFACE_TYPE_HULL:
            loadedFilesSpecFile.hullCoordFile.clearSelectionStatus(cf->getFileName());
            break;
         case BrainModelSurface::SURFACE_TYPE_UNKNOWN:
         case BrainModelSurface::SURFACE_TYPE_UNSPECIFIED:
            loadedFilesSpecFile.unknownCoordFile.clearSelectionStatus(cf->getFileName());
            break;
      }
   }

   const QString configID = 
      BrainModelSurface::getSurfaceConfigurationIDFromType(st);
   cf->setHeaderTag(AbstractFile::headerTagConfigurationID, configID);
   
   //
   // Update the surface type for the BrainModelSurface that uses
   // this coordinate file that is being saved.
   //
   for (int i = 0; i < getNumberOfBrainModels(); i++) {
      BrainModel* bm = getBrainModel(i);
      if (bm->getModelType() == BrainModel::BRAIN_MODEL_SURFACE) {
         BrainModelSurface* bms = dynamic_cast<BrainModelSurface*>(bm);
         CoordinateFile* coordFile = bms->getCoordinateFile();
         if (coordFile == cf) {
            //
            // Get the name of the topology file
            //
            QString topoFileName;
            const TopologyFile* tf = bms->getTopologyFile();
            if (tf != NULL) {
               topoFileName = FileUtilities::basename(tf->getFileName());
               if (topoFileName.length() < 5) {
                  topoFileName = "";
               }
            }
   
            cf->setHeaderTag(SpecFile::getUnknownTopoFileMatchTag(), topoFileName);
            const Structure::STRUCTURE_TYPE hem = bms->getStructure().getType();
            if (hem != Structure::STRUCTURE_TYPE_INVALID) {
               cf->setHeaderTag(AbstractFile::headerTagStructure,
                                Structure::convertTypeToString(hem));
            }
            bms->setSurfaceType(st);
         }
      }
   }

   cf->writeFile(name);
   
   if (updateSpecFile) {
      addToSpecFile(BrainModelSurface::getCoordSpecFileTagFromSurfaceType(st), name);
   }
}

/**
 * Read the volume file data
 */
void
04448 BrainSet::readVolumeFile(const QString& name, 
                         const VolumeFile::VOLUME_TYPE vt,
                         const bool appendIn, 
                         const bool updateSpecIn) throw (FileException)
{
   bool updateSpec = updateSpecIn;
   bool append = appendIn;
   
   std::vector<VolumeFile*> volumes;
   VolumeFile::readFile(name, 
                        VolumeFile::VOLUME_READ_SELECTION_ALL,
                        volumes,
                        false);
                        
   for (unsigned int i = 0; i < volumes.size(); i++) {
      VolumeFile* vf = volumes[i];
      
      //
      // Should a transformation matrix be applied ?
      //
      if (specDataFileTransformationMatrix.isIdentity() == false) {
         vf->applyTransformationMatrix(specDataFileTransformationMatrix);
         vf->clearModified();
      }
      
      if (i > 0) {
         updateSpec = false;
         append = true;
      }
      addVolumeFile(vt, vf, name, append, updateSpec); 
   }
   
   //
   // If not reading a spec file, reading prob atlas volumes, and
   // appending volumes, then region names need to be synchronized
   //
   if (readingSpecFileFlag == false) {
      if (vt == VolumeFile::VOLUME_TYPE_PROB_ATLAS) {
         if (volumes.size() < volumeProbAtlasFiles.size()) {
            synchronizeProbAtlasVolumeRegionNames();
         }
      }
   }
}

/**
 * Add a volume file to this brain set and create a brain model volume if necessary.
 */
void
04497 BrainSet::addVolumeFile(const VolumeFile::VOLUME_TYPE vt, VolumeFile* vf, 
                        const QString& name,
                        const bool append, 
                        const bool updateSpec) throw (FileException)
{
   QMutexLocker locker(&mutexAddVolumeFile);
   
   QString tag;
   
   //
   // Add the volume file to this brain set.
   //
   switch (vt) {
      case VolumeFile::VOLUME_TYPE_ANATOMY:
         if (append == false) {
            clearVolumeAnatomyFiles();
         }
         volumeAnatomyFiles.push_back(vf);
         tag = SpecFile::getVolumeAnatomyFileTag();
         break;
      case VolumeFile::VOLUME_TYPE_FUNCTIONAL:
         if (append == false) {
            clearVolumeFunctionalFiles();
         }
         volumeFunctionalFiles.push_back(vf);
         tag = SpecFile::getVolumeFunctionalFileTag();
         break;
      case VolumeFile::VOLUME_TYPE_PAINT:
         if (append == false) {
            clearVolumePaintFiles();
         }
         volumePaintFiles.push_back(vf);
         tag = SpecFile::getVolumePaintFileTag();
         break;
      case VolumeFile::VOLUME_TYPE_PROB_ATLAS:
         if (append == false) {
            clearVolumeProbabilisticAtlasFiles();
         }
         else if (volumeProbAtlasFiles.size() > 0) {
            int dimOld[3];
            volumeProbAtlasFiles[0]->getDimensions(dimOld);
            int dimNew[3];
            vf->getDimensions(dimNew);
            if ((dimOld[0] != dimNew[0]) ||
                (dimOld[1] != dimNew[1]) ||
                (dimOld[2] != dimNew[2])) {
               throw FileException("Newly selected probabilistic atlas volume "
                                   "has different dimensions than previously "
                                   "loaded probabilistic atlas volume(s).  All "
                                   "probabilistic atlas volumes must have the "
                                   "same dimensions.");
            }
         }
         volumeProbAtlasFiles.push_back(vf);
         //if (volumeProbAtlasFiles.size() > 1) {
         //   volumeProbAtlasFiles[0]->setVoxelColoringInvalid();
         //}
         tag = SpecFile::getVolumeProbAtlasFileTag();
         displaySettingsProbabilisticAtlasVolume->update();
         break;
      case VolumeFile::VOLUME_TYPE_RGB:
         if (append == false) {
            clearVolumeRgbFiles();
         }
         volumeRgbFiles.push_back(vf);
         tag = SpecFile::getVolumeRgbFileTag();
         break;
      case VolumeFile::VOLUME_TYPE_ROI:
         return;
         break;
      case VolumeFile::VOLUME_TYPE_SEGMENTATION:
         {
            if (append == false) {
               clearVolumeSegmentationFiles();
            }
            const bool isModified = vf->getModified();
            vf->makeSegmentationZeroTwoFiftyFive();
            if (isModified == false) {
               vf->clearModified();
            }
            volumeSegmentationFiles.push_back(vf);
            tag = SpecFile::getVolumeSegmentationFileTag();
         }
         break;
      case VolumeFile::VOLUME_TYPE_VECTOR:
         {
            if (append == false) {
               clearVolumeVectorFiles();
            }
            volumeVectorFiles.push_back(vf);
            tag = SpecFile::getVolumeVectorFileTag();
         }
         break;
      case VolumeFile::VOLUME_TYPE_UNKNOWN:
         return;
         break;
   }
   
   //
   // Update the spec file
   //
   if (updateSpec) {
      if (name.isEmpty() == false) {
         addToSpecFile(tag, name, vf->getDataFileName());
      }
   }
   
   //
   // Set the volume's type
   //
   vf->setVolumeType(vt);
   
/*
   //
   // Adjust anatomy and segmentation volume ranges.
   //
   QTime timer;
   timer.start();
   vf->scaleAnatomyAndSegmentationVolumesTo255();
   if (DebugControl::getDebugOn()) {
      std::cout << "Time to read scale anatomy/segmentation volume "
                << FileUtilities::basename(vf->getFileName())
                << " was "
                << (static_cast<float>(timer.elapsed()) / 1000.0)
                << " seconds." << std::endl;
   }
*/

   //
   // Create a brain model volume if there is not one
   //
   BrainModelVolume* bmv = NULL;
   for (int i = 0; i < getNumberOfBrainModels(); i++) {
      bmv = getBrainModelVolume(i);
      if (bmv != NULL) {
         break;
      }
   }
   bool createdBrainModelVolume = false;
   if (bmv == NULL) {
      createdBrainModelVolume = true;
      bmv = new BrainModelVolume(this);
      addBrainModel(bmv);
      voxelColoring->initializeUnderlay();
   }
   
   switch (vt) {
      case VolumeFile::VOLUME_TYPE_ANATOMY:
         break;
      case VolumeFile::VOLUME_TYPE_FUNCTIONAL:
         break;
      case VolumeFile::VOLUME_TYPE_PAINT:
         break;
      case VolumeFile::VOLUME_TYPE_PROB_ATLAS:
         //
         // Update indices into name table
         //
    //     if (readingSpecFileFlag == false) {
    //        synchronizeProbAtlasVolumeRegionNames();
    //     }
         displaySettingsProbabilisticAtlasVolume->update();
         break;
      case VolumeFile::VOLUME_TYPE_RGB:
         break;
      case VolumeFile::VOLUME_TYPE_ROI:
         break;
      case VolumeFile::VOLUME_TYPE_SEGMENTATION:
         break;
      case VolumeFile::VOLUME_TYPE_VECTOR:
         break;
      case VolumeFile::VOLUME_TYPE_UNKNOWN:
         return;
         break;
   }
/*
   //
   // Color the voxels for this volume
   //
   QTime colorTime;
   colorTime.start();
   voxelColoring->updateVolumeFileColoring(vf);
   if (DebugControl::getDebugOn()) {
      std::cout << "Time to color volume: " 
                << vf->getFileName()
                << (static_cast<float>(colorTime.elapsed()) / 1000.0)
                << " seconds." << std::endl;
   }
*/
   
   if (readingSpecFileFlag == false) {
      displaySettingsVolume->update();
      displaySettingsWustlRegion->update();
   }
      
   if (createdBrainModelVolume) {
      bmv->initializeSelectedSlicesAllViews(true);
   }
   
   //
   // Possibly create a brain model surface and volume
   //
   createBrainModelSurfaceAndVolume();
}

/**
 * delete a volume file.
 */
void 
04705 BrainSet::deleteVolumeFile(const VolumeFile* vf)
{
   if (vf == NULL) {
      return;
   }
   
   if (getNumberOfVolumeFunctionalFiles() > 0) {
      std::vector<VolumeFile*> files;
      for (int i = 0; i < getNumberOfVolumeFunctionalFiles(); i++) {
         if (vf != getVolumeFunctionalFile(i)) {
            files.push_back(getVolumeFunctionalFile(i));
         }
      }
      volumeFunctionalFiles = files;
   }
   
   if (getNumberOfVolumePaintFiles() > 0) {
      std::vector<VolumeFile*> files;
      for (int i = 0; i < getNumberOfVolumePaintFiles(); i++) {
         if (vf != getVolumePaintFile(i)) {
            files.push_back(getVolumePaintFile(i));
         }
      }
      volumePaintFiles = files;
   }
   
   if (getNumberOfVolumeProbAtlasFiles() > 0) {
      std::vector<VolumeFile*> files;
      int indx = -1;
      for (int i = 0; i < getNumberOfVolumeProbAtlasFiles(); i++) {
         if (vf != getVolumeProbAtlasFile(i)) {
            files.push_back(getVolumeProbAtlasFile(i));
         }
         else {
            indx = i;
         }
      }
      volumeProbAtlasFiles = files;
   }
   
   if (getNumberOfVolumeRgbFiles() > 0) {
      std::vector<VolumeFile*> files;
      for (int i = 0; i < getNumberOfVolumeRgbFiles(); i++) {
         if (vf != getVolumeRgbFile(i)) {
            files.push_back(getVolumeRgbFile(i));
         }
      }
      volumeRgbFiles = files;
   }
   
   if (getNumberOfVolumeSegmentationFiles() > 0) {
      std::vector<VolumeFile*> files;
      for (int i = 0; i < getNumberOfVolumeSegmentationFiles(); i++) {
         if (vf != getVolumeSegmentationFile(i)) {
            files.push_back(getVolumeSegmentationFile(i));
         }
      }
      volumeSegmentationFiles = files;
   }
   
   if (getNumberOfVolumeAnatomyFiles() > 0) {
      std::vector<VolumeFile*> files;
      for (int i = 0; i < getNumberOfVolumeAnatomyFiles(); i++) {
         if (vf != getVolumeAnatomyFile(i)) {
            files.push_back(getVolumeAnatomyFile(i));
         }
      }
      volumeAnatomyFiles = files;
   }
   
   if (getNumberOfVolumeVectorFiles() > 0) {
      std::vector<VolumeFile*> files;
      for (int i = 0; i < getNumberOfVolumeVectorFiles(); i++) {
         if (vf != getVolumeVectorFile(i)) {
            files.push_back(getVolumeVectorFile(i));
         }
      }
      volumeVectorFiles = files;
   }
   
   if ((getNumberOfVolumeFunctionalFiles() == 0) &&
       (getNumberOfVolumeRgbFiles() == 0) &&
       (getNumberOfVolumePaintFiles() == 0) &&
       (getNumberOfVolumeSegmentationFiles() == 0) &&
       (getNumberOfVolumeAnatomyFiles() == 0) &&
       (getNumberOfVolumeVectorFiles() == 0)) {
      BrainModelVolume* bmv = getBrainModelVolume();
      if (bmv != NULL) {
         deleteBrainModel(bmv);
      }
      BrainModelSurfaceAndVolume* bmsv = getBrainModelSurfaceAndVolume();
      if (bmsv != NULL) {
         deleteBrainModel(bmsv);
      }
   }
   
   displaySettingsVolume->update();
   displaySettingsWustlRegion->update();
   
   loadedFilesSpecFile.volumeFunctionalFile.clearSelectionStatus(vf->getFileName());
   loadedFilesSpecFile.volumePaintFile.clearSelectionStatus(vf->getFileName());
   loadedFilesSpecFile.volumeProbAtlasFile.clearSelectionStatus(vf->getFileName());
   loadedFilesSpecFile.volumeRgbFile.clearSelectionStatus(vf->getFileName());
   loadedFilesSpecFile.volumeSegmentationFile.clearSelectionStatus(vf->getFileName());
   loadedFilesSpecFile.volumeAnatomyFile.clearSelectionStatus(vf->getFileName());
   loadedFilesSpecFile.volumeVectorFile.clearSelectionStatus(vf->getFileName());

   delete vf;
   
   nodeColoring->assignColors();
   clearAllDisplayLists();
}      

/**
 * Write the multi-volume file data.
 */
void
04822 BrainSet::writeMultiVolumeFile(const QString& name, 
                          const VolumeFile::VOLUME_TYPE volumeType,
                          const QString& comment,
                          std::vector<VolumeFile*>& subVolumes,
                          const VolumeFile::VOXEL_DATA_TYPE voxelDataTypeToWriteIn,
                          const bool zipAfniVolumeFile) throw (FileException)
{   
   VolumeFile::VOXEL_DATA_TYPE voxelDataTypeToWrite = voxelDataTypeToWriteIn;
   if (voxelDataTypeToWrite == VolumeFile::VOXEL_DATA_TYPE_UNKNOWN) {
      if (subVolumes.empty() == false) {
         voxelDataTypeToWrite = subVolumes[0]->getVoxelDataType();
      }
   }
   
   //
   // Set spec file tag
   //
   QString tag(SpecFile::getVolumeAnatomyFileTag());

   switch (volumeType) {
      case VolumeFile::VOLUME_TYPE_ANATOMY:
         tag = SpecFile::getVolumeAnatomyFileTag();
         break;
      case VolumeFile::VOLUME_TYPE_FUNCTIONAL:
         tag = SpecFile::getVolumeFunctionalFileTag();
         break;
      case VolumeFile::VOLUME_TYPE_PAINT:
         tag = SpecFile::getVolumePaintFileTag();
         break;
      case VolumeFile::VOLUME_TYPE_PROB_ATLAS:
         tag = SpecFile::getVolumeProbAtlasFileTag();
         break;
      case VolumeFile::VOLUME_TYPE_RGB:
         tag = SpecFile::getVolumeRgbFileTag();
         break;
      case VolumeFile::VOLUME_TYPE_ROI:
         throw FileException(FileUtilities::basename(name), "Unrecognized volume type");
         break;
      case VolumeFile::VOLUME_TYPE_SEGMENTATION:
         tag = SpecFile::getVolumeSegmentationFileTag();
         break;
      case VolumeFile::VOLUME_TYPE_VECTOR:
         tag = SpecFile::getVolumeVectorFileTag();
         break;
      case VolumeFile::VOLUME_TYPE_UNKNOWN:
         throw FileException(FileUtilities::basename(name), "Unrecognized volume type");
         break;
   }

   if (subVolumes.empty() == false) {
      subVolumes[0]->setFileComment(comment);
      VolumeFile::writeFile(name,
                            volumeType,
                            voxelDataTypeToWrite,
                            subVolumes,
                            zipAfniVolumeFile);
      addToSpecFile(tag, name, subVolumes[0]->getDataFileName());
   }   
/*
      const QString dataFileName =
         VolumeFile::writeMultiVolumeFile(name, writeFileType, comment, subVolumes);
*/
}

/**
 * Write the volume file data.
 */
void
04890 BrainSet::writeVolumeFile(const QString& nameIn, 
                          const VolumeFile::FILE_READ_WRITE_TYPE writeFileType,
                          const VolumeFile::VOLUME_TYPE volumeType,
                          VolumeFile* vf,
                          const VolumeFile::VOXEL_DATA_TYPE voxelDataTypeToWriteIn,
                          const bool zipAfniVolumeFile) throw (FileException)
{
   VolumeFile::VOXEL_DATA_TYPE voxelDataTypeToWrite = voxelDataTypeToWriteIn;
   if (voxelDataTypeToWrite == VolumeFile::VOXEL_DATA_TYPE_UNKNOWN) {
      voxelDataTypeToWrite = vf->getVoxelDataType();
   }
   
   QString name(nameIn);
   
   //
   // NIFTI GZIP
   //
   if (name.endsWith(SpecFile::getNiftiVolumeFileExtension()) &&
       zipAfniVolumeFile) {
      name += ".gz";
   }
   
   vf->setFileWriteType(writeFileType);
   
   //
   // Set spec file tag
   //
   QString tag(SpecFile::getVolumeAnatomyFileTag());

   switch (volumeType) {
      case VolumeFile::VOLUME_TYPE_ANATOMY:
         tag = SpecFile::getVolumeAnatomyFileTag();
         loadedFilesSpecFile.volumeAnatomyFile.clearSelectionStatus(vf->getFileName());
         break;
      case VolumeFile::VOLUME_TYPE_FUNCTIONAL:
         tag = SpecFile::getVolumeFunctionalFileTag();
         loadedFilesSpecFile.volumeFunctionalFile.clearSelectionStatus(vf->getFileName());
         break;
      case VolumeFile::VOLUME_TYPE_PAINT:
         tag = SpecFile::getVolumePaintFileTag();
         loadedFilesSpecFile.volumePaintFile.clearSelectionStatus(vf->getFileName());
         break;
      case VolumeFile::VOLUME_TYPE_PROB_ATLAS:
         tag = SpecFile::getVolumeProbAtlasFileTag();
         loadedFilesSpecFile.volumeProbAtlasFile.clearSelectionStatus(vf->getFileName());
         break;
      case VolumeFile::VOLUME_TYPE_RGB:
         tag = SpecFile::getVolumeRgbFileTag();
         loadedFilesSpecFile.volumeRgbFile.clearSelectionStatus(vf->getFileName());
         break;
      case VolumeFile::VOLUME_TYPE_ROI:
         throw FileException(FileUtilities::basename(name), "Unrecognized volume type=ROI");
         break;
      case VolumeFile::VOLUME_TYPE_SEGMENTATION:
         tag = SpecFile::getVolumeSegmentationFileTag();
         loadedFilesSpecFile.volumeSegmentationFile.clearSelectionStatus(vf->getFileName());
         break;
      case VolumeFile::VOLUME_TYPE_VECTOR:
         tag = SpecFile::getVolumeVectorFileTag();
         loadedFilesSpecFile.volumeVectorFile.clearSelectionStatus(vf->getFileName());
         break;
      case VolumeFile::VOLUME_TYPE_UNKNOWN:
         throw FileException(FileUtilities::basename(name), "Unrecognized volume type");
         break;
   }
   
   std::vector<VolumeFile*> volumesToWrite;
   volumesToWrite.push_back(vf);
   VolumeFile::writeFile(name,
                         volumeType,
                         voxelDataTypeToWrite,
                         volumesToWrite,
                         zipAfniVolumeFile);
/*                                               
   vf->writeFile(name);

   QString dataFileName(vf->getDataFileName());
   if (vf->getWriteFileGzip()) {
      if (dataFileName.right(3) != ".gz") {
         dataFileName.append(".gz");
      }
      
      if (writeFileType == VolumeFile::FILE_READ_WRITE_TYPE_NIFTI) {
         if (name.right(3) != ".gz") {
            name.append(".gz");
         }
      }
   }
*/
   addToSpecFile(tag, name, vf->getDataFileName());
}

/**
 * read the surface data file file.
 */
void 
04986 BrainSet::readSurfaceFile(const QString& name, 
                          const BrainModelSurface::SURFACE_TYPES surfaceTypeIn,
                          const bool readingSpecFile,
                          const bool append,
                          const bool updateSpec) throw (FileException)
{
   BrainModelSurface::SURFACE_TYPES surfaceType = surfaceTypeIn;
   
   BrainModelSurface* bms = new BrainModelSurface(this);
   bms->readSurfaceFile(name);
   if (surfaceType == BrainModelSurface::SURFACE_TYPE_UNKNOWN) {
      surfaceType = bms->getSurfaceType();
   }

   QMutexLocker mutex(&mutexReadSurfaceFile);
   
   bool needToInitialize = false;
   if (readingSpecFile == false) {
      needToInitialize = true;
      for (int i = 0; i < getNumberOfBrainModels(); i++) {
         if (getBrainModelSurface(i) != NULL) {
            needToInitialize = false;
         }
      }
   }
   
   if (append == false) {
      deleteSurfacesOfType(surfaceType);
   }
   
   if (getNumberOfNodes() == 0) {
      if (bms->getNumberOfNodes() > 0) {
         numNodesMessage = " contains a different number of nodes than ";
         numNodesMessage.append(FileUtilities::basename(name));
      }
      else {
         delete bms;
         bms = NULL;
         throw FileException(name, "Contains no nodes");
      }
   }
   else if (getNumberOfNodes() != bms->getNumberOfNodes()) {
      delete bms;
      bms = NULL;
      throw FileException(FileUtilities::basename(name), numNodesMessage);
   }
   
   //
   // Get the coordinate file
   //
   CoordinateFile* cf = bms->getCoordinateFile();
   
   QString tag;
   
   bool applyTransformFlag = false;
   switch(surfaceType) {
      case BrainModelSurface::SURFACE_TYPE_RAW:
         tag = SpecFile::getRawSurfaceFileTag();
         applyTransformFlag = (specDataFileTransformationMatrix.isIdentity() == false);
         break;
      case BrainModelSurface::SURFACE_TYPE_FIDUCIAL:
         tag = SpecFile::getFiducialSurfaceFileTag();
         applyTransformFlag = (specDataFileTransformationMatrix.isIdentity() == false);
         break;
      case BrainModelSurface::SURFACE_TYPE_INFLATED:
         tag = SpecFile::getInflatedSurfaceFileTag();
         break;
      case BrainModelSurface::SURFACE_TYPE_VERY_INFLATED:
         tag = SpecFile::getVeryInflatedSurfaceFileTag();
         break;
      case BrainModelSurface::SURFACE_TYPE_SPHERICAL:
         tag = SpecFile::getSphericalSurfaceFileTag();
         break;
      case BrainModelSurface::SURFACE_TYPE_ELLIPSOIDAL:
         tag = SpecFile::getEllipsoidSurfaceFileTag();
         break;
      case BrainModelSurface::SURFACE_TYPE_COMPRESSED_MEDIAL_WALL:
         tag = SpecFile::getCompressedSurfaceFileTag();
         break;
      case BrainModelSurface::SURFACE_TYPE_FLAT:
         tag = SpecFile::getFlatSurfaceFileTag();
         break;
      case BrainModelSurface::SURFACE_TYPE_FLAT_LOBAR:
         tag = SpecFile::getLobarFlatSurfaceFileTag();
         break;
      case BrainModelSurface::SURFACE_TYPE_HULL:
         tag = SpecFile::getHullSurfaceFileTag();
         break;
      case BrainModelSurface::SURFACE_TYPE_UNKNOWN:
      case BrainModelSurface::SURFACE_TYPE_UNSPECIFIED:
         tag = SpecFile::getUnknownSurfaceFileMatchTag();
         break;
      default:
         throw FileException(FileUtilities::basename(name),
                              "Unrecognized surface type");
         break;
   }
   
   //
   // If transformation matrix should be applied
   //
   if (applyTransformFlag) {
      cf->applyTransformationMatrix(specDataFileTransformationMatrix);
      cf->clearModified();
   }
      
   bms->computeNormals();
   bms->setSurfaceType(surfaceType);
   
   //
   // Only set the structure for the surface if the structure is unknown
   //
   if (bms->getStructure() == Structure::STRUCTURE_TYPE_INVALID) {
      if (structure.getType() != Structure::STRUCTURE_TYPE_INVALID) {
         bms->setStructure(structure.getType());
      }
      //cf->setHeaderTag(AbstractFile::headerTagHemisphere, "");
   }
   cf->clearModified(); // setSurfaceType causes modified flat to be set
   
   addBrainModel(bms, readingSpecFile);

   if (updateSpec) {
      addToSpecFile(tag, name);
   }
   
   if (needToInitialize) {
      postSpecFileReadInitializations();
   }
   
   //
   // Possibly create a brain model surface and volume
   //
   createBrainModelSurfaceAndVolume();
}      

/**      
 * Read the coordinate data file file
 */
void 
05126 BrainSet::readCoordinateFile(const QString& name, const BrainModelSurface::SURFACE_TYPES stin,
                             const bool readingSpecFile,
                             const bool append,
                             const bool updateSpec) throw (FileException)
{
   //
   // get type of surface from file, if needed
   //
   BrainModelSurface::SURFACE_TYPES st = stin;
   if ((st == BrainModelSurface::SURFACE_TYPE_UNSPECIFIED) ||
       (st == BrainModelSurface::SURFACE_TYPE_UNKNOWN)) {
      CoordinateFile cf;
      cf.readFileMetaDataOnly(name);
      const QString typeTag = cf.getHeaderTag(AbstractFile::headerTagConfigurationID);
      if (typeTag.isEmpty() == false) {
         st = BrainModelSurface::getSurfaceTypeFromConfigurationID(typeTag);
      }
   }
   
   //
   // Read the coordinate file
   //
   BrainModelSurface* bms = new BrainModelSurface(this);
   bms->readCoordinateFile(name);
   
   //
   // The remainder of this routine must not be run by more than one thread
   //
   QMutexLocker locker(&mutexReadCoordinateFile);
   
   //
   // See if initialization needed
   //
   bool needToInitialize = false;
   if (readingSpecFile == false) {
      needToInitialize = true;
      for (int i = 0; i < getNumberOfBrainModels(); i++) {
         if ((getBrainModelSurface(i) != NULL) &&
             (getBrainModelSurface(i) != bms)) {
            needToInitialize = false;
         }
      }
   }
   
   //
   // Check nodes
   //
   if (getNumberOfNodes() == 0) {
      if (bms->getNumberOfNodes() > 0) {
         numNodesMessage = " contains a different number of nodes than ";
         numNodesMessage.append(FileUtilities::basename(name));
      }
      else {
         delete bms;
         bms = NULL;
         throw FileException(name, "Contains no nodes");
      }
   }
   else if (getNumberOfNodes() != bms->getNumberOfNodes()) {
      delete bms;
      bms = NULL;
      throw FileException(FileUtilities::basename(name), numNodesMessage);
   }
   
   if (append == false) {
      deleteSurfacesOfType(st);
   }
   
   //
   // Get the coordinate file
   //
   CoordinateFile* cf = bms->getCoordinateFile();
   
   //
   // May automatically set topology file
   //
   TopologyFile* useThisTopologyFile = NULL;

/*   
   if (readingSpecFile) {
      const QString topoFile = cf->getHeaderTag(SpecFile::UnknownTopoFileMatchTag);
      if (topoFile.empty() == false) {
         for (int i = 0; i < getNumberOfTopologyFiles(); i++) {
            if (FileUtilities::basename(topoFile) == 
                FileUtilities::basename(getTopologyFile(i)->getFileName())) {
               useThisTopologyFile = getTopologyFile(i);
               break;
            }
         }
      }
   }
   else {
*/
   
   //
   // Should topo file listed in coord file's header be used
   //
   if (ignoreTopologyFileInCoordinateFileHeaderFlag == false) {
      //
      // Load matching topo file if it is not already loaded
      //
      const QString topoFile = cf->getHeaderTag(SpecFile::getUnknownTopoFileMatchTag());
      if (topoFile.isEmpty() == false) {
         bool loadIt = true;
         for (int i = 0; i < getNumberOfTopologyFiles(); i++) {
            if (FileUtilities::basename(topoFile) == 
                FileUtilities::basename(getTopologyFile(i)->getFileName())) {
               loadIt = false;
               useThisTopologyFile = getTopologyFile(i);
               break;
            }
         }
         if (QFile::exists(topoFile) && loadIt) {
            try {
               //
               // Want to update spec file even if reading files from spec file
               //
               const bool readingSpecFileFlagCOPY = readingSpecFileFlag;
               readingSpecFileFlag = false;
               readTopologyFile(topoFile, TopologyFile::TOPOLOGY_TYPE_UNSPECIFIED, true, true);
               readingSpecFileFlag = readingSpecFileFlagCOPY;
               //const int topoIndex = getNumberOfTopologyFiles() - 1;
               //if ((topoIndex >= 0) && (topoIndex < getNumberOfTopologyFiles())) {
               //
               // Note that readTopologyFile() always places the just read topology
               // file as the first topology file
               //
               if (getNumberOfTopologyFiles() > 0) {
                  useThisTopologyFile = getTopologyFile(0);
               }
            }
            catch (FileException& /*e*/) {
            }
         }
      }
   }
/*
   }
*/   
   //
   // Update configuration ID in the coord file
   //
   const QString configID = 
      BrainModelSurface::getSurfaceConfigurationIDFromType(st);
   cf->setHeaderTag(AbstractFile::headerTagConfigurationID, configID);
   cf->clearModified();
   QString tag;
   
   bool applyTransformFlag = false;
   bool topoError = false; 
   switch(st) {
      case BrainModelSurface::SURFACE_TYPE_RAW:
         topoError = bms->setTopologyFile(topologyClosed);
         tag = SpecFile::getRawCoordFileTag();
         applyTransformFlag = (specDataFileTransformationMatrix.isIdentity() == false);
         break;
      case BrainModelSurface::SURFACE_TYPE_FIDUCIAL:
         topoError = bms->setTopologyFile(topologyClosed);
         tag = SpecFile::getFiducialCoordFileTag();
         applyTransformFlag = (specDataFileTransformationMatrix.isIdentity() == false);
         break;
      case BrainModelSurface::SURFACE_TYPE_INFLATED:
         topoError = bms->setTopologyFile(topologyClosed);
         tag = SpecFile::getInflatedCoordFileTag();
         break;
      case BrainModelSurface::SURFACE_TYPE_VERY_INFLATED:
         topoError = bms->setTopologyFile(topologyClosed);
         tag = SpecFile::getVeryInflatedCoordFileTag();
         break;
      case BrainModelSurface::SURFACE_TYPE_SPHERICAL:
         topoError = bms->setTopologyFile(topologyClosed);
         tag = SpecFile::getSphericalCoordFileTag();
         break;
      case BrainModelSurface::SURFACE_TYPE_ELLIPSOIDAL:
         topoError = bms->setTopologyFile(topologyClosed);
         tag = SpecFile::getEllipsoidCoordFileTag();
         break;
      case BrainModelSurface::SURFACE_TYPE_COMPRESSED_MEDIAL_WALL:
         topoError = bms->setTopologyFile(topologyClosed);
         tag = SpecFile::getCompressedCoordFileTag();
         break;
      case BrainModelSurface::SURFACE_TYPE_FLAT:
         topoError = bms->setTopologyFile(topologyCut);
         tag = SpecFile::getFlatCoordFileTag();
         break;
      case BrainModelSurface::SURFACE_TYPE_FLAT_LOBAR:
         topoError = bms->setTopologyFile(topologyLobarCut);
         tag = SpecFile::getLobarFlatCoordFileTag();
         break;
      case BrainModelSurface::SURFACE_TYPE_HULL:
         topoError = bms->setTopologyFile(topologyClosed);
         tag = SpecFile::getHullCoordFileTag();
         break;
      case BrainModelSurface::SURFACE_TYPE_UNKNOWN:
      case BrainModelSurface::SURFACE_TYPE_UNSPECIFIED:
         topoError = bms->setTopologyFile(topologyClosed);
         tag = SpecFile::getUnknownCoordFileMatchTag();
         break;
      default:
         throw FileException(FileUtilities::basename(name),
                              "Unrecognized surface type");
         break;
   }
   
   //
   // If transformation matrix should be applied
   //
   if (applyTransformFlag) {
      cf->applyTransformationMatrix(specDataFileTransformationMatrix);
      cf->clearModified();
   }
   
   //
   // Use topology file coord file was using when it was saved
   //
   if (useThisTopologyFile != NULL) {
      topoError =  bms->setTopologyFile(useThisTopologyFile);
   }
   
   if (topoError) {
      std::ostringstream str;
      str << "Topology File "
          << FileUtilities::basename(bms->getTopologyFile()->getFileName()).toAscii().constData()
          << "\n is not for use with coordinate file "
          << FileUtilities::basename(name).toAscii().constData()
          << ".\n  Topo file has tiles with node numbers exceeding \n"
          << "the number of coordinates in the coordinate file.";
      delete bms;
      throw FileException(name, str.str().c_str());
   }
   
   bms->computeNormals();
   bms->setSurfaceType(st);
   
   //
   // Only set the structure for the surface if the structure is unknown
   //
   if (bms->getStructure() == Structure::STRUCTURE_TYPE_INVALID) {
      if (structure.getType() != Structure::STRUCTURE_TYPE_INVALID) {
         bms->setStructure(structure.getType());
      }
      //cf->setHeaderTag(AbstractFile::headerTagHemisphere, "");
   }
   cf->clearModified(); // setSurfaceType causes modified flat to be set
   
   addBrainModel(bms, readingSpecFile);

   if (updateSpec) {
      addToSpecFile(tag, name);
   }
   
   if (needToInitialize) {
      postSpecFileReadInitializations();
   }
   
   //
   // Possibly create a brain model surface and volume
   //
   createBrainModelSurfaceAndVolume();
}

/**
 * Add a brain model to this brain set
 */      
void
05391 BrainSet::addBrainModel(BrainModel* bm, const bool readingSpecFile)
{
   //
   // The remainder of this routine must not be run by more than one thread
   //
   QMutexLocker locker(&mutexAddBrainModel);

   brainModels.push_back(bm);
   brainModelBorderSet->addBrainModel(bm);
   
   updateDisplayedModelIndices();
   updateSurfaceOverlaysDueToChangeInBrainModels();
   updateAllDisplaySettings();
   
   if (readingSpecFile == false) {
      if (dynamic_cast<BrainModelSurface*>(bm) != NULL) {
         nodeColoring->assignColors();
      }
   }
}

/**
 * get the index for a brain model.
 */
int 
05416 BrainSet::getBrainModelIndex(const BrainModel* bm) const
{
   const int numBrainModels = getNumberOfBrainModels();
   for (int i = 0; i < numBrainModels; i++) {
      if (bm == getBrainModel(i)) {
         return i;
      }
   }
   return -1;
}

/**
 * Delete a brain model
 */
void 
05431 BrainSet::deleteBrainModel(const BrainModel* bm)
{
   std::vector<BrainModel*> models;

   const unsigned int num = brainModels.size();
   for (unsigned int i = 0; i < num; i++) {
      if (brainModels[i] != bm) {
         models.push_back(brainModels[i]);
      }
   }
   
   brainModelBorderSet->deleteBrainModel(bm);
   
   brainModels = models;
   delete bm;
   
   updateDisplayedModelIndices();
   updateSurfaceOverlaysDueToChangeInBrainModels();

   updateAllDisplaySettings();
   
   nodeColoring->assignColors();
   clearAllDisplayLists();
}

/** 
 * Write the foci data file of the specified type.
 */ 
void
05460 BrainSet::writeFociFile(const QString& name,
                        const BrainModelSurface* leftBMS,
                        const BrainModelSurface* rightBMS,
                        const BrainModelSurface* cerebellumBMS,
                        const AbstractFile::FILE_FORMAT fileFormat,
                        const QString& commentText) throw (FileException)
{
   FociFile ff;

   const CoordinateFile* leftCF = ((leftBMS != NULL) ?
                                   leftBMS->getCoordinateFile()
                                   : NULL);
   const TopologyFile* leftTF = ((leftBMS != NULL) ?
                                 leftBMS->getTopologyFile()
                                 : NULL);
   
   const CoordinateFile* rightCF = ((rightBMS != NULL) ?
                                   rightBMS->getCoordinateFile()
                                   : NULL);
   const TopologyFile* rightTF = ((rightBMS != NULL) ?
                                 rightBMS->getTopologyFile()
                                 : NULL);
   
   const CoordinateFile* cerebellumCF = ((cerebellumBMS != NULL) ?
                                   cerebellumBMS->getCoordinateFile()
                                   : NULL);
   const TopologyFile* cerebellumTF = ((cerebellumBMS != NULL) ?
                                 cerebellumBMS->getTopologyFile()
                                 : NULL);
   
   fociProjectionFile->getCellFileForRightLeftFiducials(leftCF,
                                                        leftTF,
                                                        rightCF,
                                                        rightTF,
                                                        cerebellumCF,
                                                        cerebellumTF,
                                                        ff);
   
   //
   // Check for foci
   //
   if (ff.getNumberOfCells() <= 0) {
      throw FileException("There are no foci that project to the selected surface(s).");
   }
   ff.setFileComment(commentText);
   ff.setFileWriteType(fileFormat);
   ff.writeFile(name);
   addToSpecFile(SpecFile::getFociFileTag(), name);
}

/**
 * write the Foci data file.
 */
void 
05514 BrainSet::writeFociFileOriginalCoordinates(const QString& name,
                                           const AbstractFile::FILE_FORMAT fileFormat,
                                           const QString& commentText) throw (FileException)
{
   FociFile ff;
   fociProjectionFile->getCellFileOriginalCoordinates(ff);
   
   ff.setFileComment(commentText);
   ff.setFileWriteType(fileFormat);
   ff.writeFile(name);

   addToSpecFile(SpecFile::getFociFileTag(), name);
}
      
/**      
 * Read the foci data file file
 */
void 
05532 BrainSet::readFociFile(const QString& name, 
                       const bool append,
                       const bool updateSpec) throw (FileException)
{
   FociFile fociFile;
   try {
      fociFile.readFile(name);
      
      //
      // If transformation should be applied
      //
      if (specDataFileTransformationMatrix.isIdentity() == false) {
         fociFile.applyTransformationMatrix(std::numeric_limits<int>::min(),
                                             std::numeric_limits<int>::max(),
                                             specDataFileTransformationMatrix,
                                             false);
      }
   }
   catch (FileException& e) {
      throw FileException(FileUtilities::basename(name), e.whatQString());
   }
   
   QMutexLocker locker(&mutexFociAndFociProjectionFile);
   
   if (append == false) {
      deleteAllFociProjections();
   }
   
   fociProjectionFile->appendFiducialCellFile(fociFile);

   if (updateSpec) {
      addToSpecFile(SpecFile::getFociFileTag(), name);
   }
}
      
/** 
 * Write the foci color data file.
 */ 
void
05571 BrainSet::writeFociColorFile(const QString& name) throw (FileException)
{
   loadedFilesSpecFile.fociColorFile.setAllSelections(SpecFile::SPEC_FALSE);
   fociColorFile->writeFile(name);
   addToSpecFile(SpecFile::getFociColorFileTag(), name);
}

/**      
 * Read the foci color data file file
 */
void 
05582 BrainSet::readFociColorFile(const QString& name, const bool append,
                            const bool updateSpec) throw (FileException)
{
   QMutexLocker locker(&mutexFociColorFile);
   
   if (append == false) {
      clearFociColorFile();
   }
   const unsigned long modified = fociColorFile->getModified();
   
   if (fociColorFile->getNumberOfColors() == 0) {         
      try {
         fociColorFile->readFile(name);
      }
      catch (FileException& e) {
         clearFociColorFile();
         throw FileException(FileUtilities::basename(name), e.whatQString());
      }
   }
   else {
      // Append to existing 
      FociColorFile cf;
      cf.readFile(name);
      QString msg;
      fociColorFile->append(cf);
   }
   fociColorFile->setModifiedCounter(modified);
   
   if (updateSpec) {
      addToSpecFile(SpecFile::getFociColorFileTag(), name);
   }
}
      
/** 
 * Write the Foci Projection data file.
 */ 
void
05619 BrainSet::writeFociProjectionFile(const QString& name) throw (FileException)
{
   loadedFilesSpecFile.fociProjectionFile.setAllSelections(SpecFile::SPEC_FALSE);
   fociProjectionFile->writeFile(name);
   addToSpecFile(SpecFile::getFociProjectionFileTag(), name);
}

/**      
 * Read the foci projection data file file
 */
void 
05630 BrainSet::readFociProjectionFile(const QString& name, 
                            const bool append,
                            const bool updateSpec) throw (FileException)
{
   QMutexLocker locker(&mutexFociAndFociProjectionFile);
   
   if (append == false) {
      deleteAllFociProjections();
   }
   const unsigned long modified = fociProjectionFile->getModified();
   
   if (fociProjectionFile->getNumberOfCellProjections() == 0) {         
      try {
         fociProjectionFile->readFile(name);
      }
      catch (FileException& e) {
         deleteAllFociProjections();
         throw FileException(FileUtilities::basename(name), e.whatQString());
      }
   }
   else {
      // Append to existing 
      FociProjectionFile cf;
      cf.readFile(name);
      QString msg;
      fociProjectionFile->append(cf);
   }
   fociProjectionFile->setModifiedCounter(modified);
   
   if (readingSpecFileFlag == false) {
      displaySettingsFoci->update();
   }
   
   if (updateSpec) {
      addToSpecFile(SpecFile::getFociProjectionFileTag(), name);
   }
}
      
/** 
 * Write the Foci Search data file.
 */ 
void
05672 BrainSet::writeFociSearchFile(const QString& name) throw (FileException)
{
   loadedFilesSpecFile.fociSearchFile.setAllSelections(SpecFile::SPEC_FALSE);
   fociSearchFile->writeFile(name);
   addToSpecFile(SpecFile::getFociSearchFileTag(), name);
}

/**      
 * Read the foci search data file file
 */
void 
05683 BrainSet::readFociSearchFile(const QString& name, 
                            const bool append,
                            const bool updateSpec) throw (FileException)
{
   QMutexLocker locker(&mutexFociSearchFile);
   
   if (append == false) {
      clearFociSearchFile();
   }
   const unsigned long modified = fociSearchFile->getModified();
   
   if (fociSearchFile->getNumberOfFociSearchSets() == 0) {         
      try {
         fociSearchFile->readFile(name);
      }
      catch (FileException& e) {
         deleteAllFociProjections();
         throw FileException(FileUtilities::basename(name), e.whatQString());
      }
   }
   else {
      // Append to existing 
      FociSearchFile fsf;
      fsf.readFile(name);
      QString msg;
      fociSearchFile->append(fsf);
   }
   fociSearchFile->setModifiedCounter(modified);
   
   if (readingSpecFileFlag == false) {
      displaySettingsFoci->update();
   }
   
   if (updateSpec) {
      addToSpecFile(SpecFile::getFociSearchFileTag(), name);
   }
}

/** 
 * Write the geodesic distance data file.
 */ 
void
05725 BrainSet::writeGeodesicDistanceFile(const QString& name) throw (FileException)
{
   loadedFilesSpecFile.geodesicDistanceFile.setAllSelections(SpecFile::SPEC_FALSE);
   geodesicDistanceFile->writeFile(name);
   addToSpecFile(SpecFile::getGeodesicDistanceFileTag(), name);
}

/**
 * read the geodesic distance data file file (only selected columns).
 */
void 
05736 BrainSet::readGeodesicDistanceFile(const QString& name, 
                         const std::vector<int>& columnDestination,
                         const std::vector<QString>& fileBeingReadColumnNames,
                         const AbstractFile::FILE_COMMENT_MODE fcm,
                         const bool updateSpec) throw (FileException)
{
   QMutexLocker locker(&mutexGeodesicDistanceFile);
   
   GeodesicDistanceFile gdf;
   gdf.readFile(name);
   if (gdf.getNumberOfNodes() != getNumberOfNodes()) {
      throw FileException(FileUtilities::basename(name), numNodesMessage);
   }
   try {
      for (int i = 0; i < gdf.getNumberOfColumns(); i++) {
         if (i < static_cast<int>(fileBeingReadColumnNames.size())) {
            gdf.setColumnName(i, fileBeingReadColumnNames[i]);
         }
      }
      geodesicDistanceFile->append(gdf, columnDestination, fcm);
   }
   catch (FileException& e) {
      throw FileException(FileUtilities::basename(name), e.whatQString());
   }
   geodesicDistanceFile->setModified();
   displaySettingsGeodesicDistance->update();
   
   if (updateSpec) {
      addToSpecFile(SpecFile::getGeodesicDistanceFileTag(), name);
   }
}

/**      
 * Read the geodesic distance data file file
 */
void 
05772 BrainSet::readGeodesicDistanceFile(const QString& name, const bool append,
                            const bool updateSpec) throw (FileException)
{
   QMutexLocker locker(&mutexGeodesicDistanceFile);
   
   if (append == false) {
      clearGeodesicDistanceFile();
   }
   const unsigned long modified = geodesicDistanceFile->getModified();
   
   if (geodesicDistanceFile->getNumberOfColumns() == 0) {         
      try {
         geodesicDistanceFile->readFile(name);
         if (geodesicDistanceFile->getNumberOfNodes() != getNumberOfNodes()) {
            throw FileException(FileUtilities::basename(name), numNodesMessage);
         }
      }
      catch (FileException& e) {
         clearGeodesicDistanceFile();
         throw FileException(FileUtilities::basename(name), e.whatQString());
      }
   }
   else {
      // Append to existing 
      GeodesicDistanceFile gdf;
      gdf.readFile(name);
      if (gdf.getNumberOfNodes() != getNumberOfNodes()) {
         throw FileException(FileUtilities::basename(name), numNodesMessage);
      }
      try {
         geodesicDistanceFile->append(gdf);
      }
      catch (FileException& e) {
         throw FileException(FileUtilities::basename(name), e.whatQString());
      }
   }
   geodesicDistanceFile->setModifiedCounter(modified);
   displaySettingsGeodesicDistance->update();
   
   if (updateSpec) {
      addToSpecFile(SpecFile::getGeodesicDistanceFileTag(), name);
   }
}
      
/** 
 * Write the lat lon data file.
 */ 
void
05820 BrainSet::writeLatLonFile(const QString& name) throw (FileException)
{
   loadedFilesSpecFile.latLonFile.setAllSelections(SpecFile::SPEC_FALSE);
   latLonFile->writeFile(name);
   addToSpecFile(SpecFile::getLatLonFileTag(), name);
}

/**
 * read the lat lon data file file (only selected columns).
 */
void 
05831 BrainSet::readLatLonFile(const QString& name, 
                         const std::vector<int>& columnDestination,
                         const std::vector<QString>& fileBeingReadColumnNames,
                         const AbstractFile::FILE_COMMENT_MODE fcm,
                         const bool updateSpec) throw (FileException)
{
   QMutexLocker locker(&mutexLatLonFile);
   
   LatLonFile llf;
   llf.readFile(name);
   if (llf.getNumberOfNodes() != getNumberOfNodes()) {
      throw FileException(FileUtilities::basename(name), numNodesMessage);
   }
   try {
      for (int i = 0; i < llf.getNumberOfColumns(); i++) {
         if (i < static_cast<int>(fileBeingReadColumnNames.size())) {
            llf.setColumnName(i, fileBeingReadColumnNames[i]);
         }
      }
      latLonFile->append(llf, columnDestination, fcm);
   }
   catch (FileException& e) {
      throw FileException(FileUtilities::basename(name), e.whatQString());
   }
   latLonFile->setModified();
   
   if (updateSpec) {
      addToSpecFile(SpecFile::getLatLonFileTag(), name);
   }
}

/**      
 * Read the lat lon data file file
 */
void 
05866 BrainSet::readLatLonFile(const QString& name, const bool append,
                            const bool updateSpec) throw (FileException)
{
   QMutexLocker locker(&mutexLatLonFile);
   
   if (append == false) {
      clearLatLonFile();
   }
   const unsigned long modified = latLonFile->getModified();
   
   if (latLonFile->getNumberOfColumns() == 0) {         
      try {
         latLonFile->readFile(name);
         if (latLonFile->getNumberOfNodes() != getNumberOfNodes()) {
            throw FileException(FileUtilities::basename(name), numNodesMessage);
         }
      }
      catch (FileException& e) {
         clearLatLonFile();
         throw FileException(FileUtilities::basename(name), e.whatQString());
      }
   }
   else {
      // Append to existing 
      LatLonFile llf;
      llf.readFile(name);
      if (llf.getNumberOfNodes() != getNumberOfNodes()) {
         throw FileException(FileUtilities::basename(name), numNodesMessage);
      }
      try {
         latLonFile->append(llf);
      }
      catch (FileException& e) {
         throw FileException(FileUtilities::basename(name), e.whatQString());
      }
   }
   latLonFile->setModifiedCounter(modified);
   
   if (updateSpec) {
      addToSpecFile(SpecFile::getLatLonFileTag(), name);
   }
}
      
/** 
 * Write the metric data file.
 */ 
void
05913 BrainSet::writeMetricFile(const QString& name) throw (FileException)
{
   loadedFilesSpecFile.metricFile.setAllSelections(SpecFile::SPEC_FALSE);
   metricFile->writeFile(name);
   addToSpecFile(SpecFile::getMetricFileTag(), name);
}

/**
 * read the metric data file file (only selected columns).
 */
void 
05924 BrainSet::readMetricFile(const QString& name, 
                         const std::vector<int>& columnDestination,
                         const std::vector<QString>& fileBeingReadColumnNames,
                         const AbstractFile::FILE_COMMENT_MODE fcm,
                         const bool updateSpec) throw (FileException)
{
   QMutexLocker locker(&mutexMetricFile);
   
   const bool metricFileEmpty = metricFile->empty();
   
   MetricFile mf;
   mf.setNumberOfNodesForSparseNodeIndexFiles(getNumberOfNodes());
   mf.readFile(name);
   if (mf.getNumberOfNodes() != getNumberOfNodes()) {
      throw FileException(FileUtilities::basename(name), numNodesMessage);
   }
   try {
      for (int i = 0; i < mf.getNumberOfColumns(); i++) {
         if (i < static_cast<int>(fileBeingReadColumnNames.size())) {
            if (fileBeingReadColumnNames[i].isEmpty() == false) {
               mf.setColumnName(i, fileBeingReadColumnNames[i]);
            }
         }
      }
      std::vector<int> columnDestination2 = columnDestination;
      metricFile->append(mf, columnDestination2, fcm);
   }
   catch (FileException& e) {
      throw FileException(FileUtilities::basename(name), e.whatQString());
   }
   if (metricFileEmpty) {
      metricFile->clearModified();
   }
   else {
      metricFile->setModified();
   }

   if (readingSpecFileFlag == false) {
      displaySettingsMetric->update();
      brainSetAutoLoaderManager->update();
   }
   
   if (updateSpec) {
      addToSpecFile(SpecFile::getMetricFileTag(), name);
   }
}


/**      
 * Read the metric data file file
 */
void 
05976 BrainSet::readMetricFile(const QString& name, const bool append,
                            const bool updateSpec) throw (FileException)
{
   QMutexLocker locker(&mutexMetricFile);
   
   if (append == false) {
      clearMetricFile();
   }
   const unsigned long modified = metricFile->getModified();
   
   if (metricFile->getNumberOfColumns() == 0) {         
      try {
         metricFile->readFile(name);
         if (metricFile->getNumberOfNodes() != getNumberOfNodes()) {
            throw FileException(FileUtilities::basename(name), numNodesMessage);
         }
      }
      catch (FileException& e) {
         clearMetricFile();
         throw FileException(FileUtilities::basename(name), e.whatQString());
      }
   }
   else {
      // Append to existing 
      MetricFile mf;
      mf.readFile(name);
      if (mf.getNumberOfNodes() != getNumberOfNodes()) {
         throw FileException(FileUtilities::basename(name), numNodesMessage);
      }
      try {
         metricFile->append(mf);
      }
      catch (FileException& e) {
         throw FileException(FileUtilities::basename(name), e.whatQString());
      }
   }
   metricFile->setModifiedCounter(modified);

   if (readingSpecFileFlag == false) {
      displaySettingsMetric->update();
      brainSetAutoLoaderManager->update();
   }
   
   if (updateSpec) {
      addToSpecFile(SpecFile::getMetricFileTag(), name);
   }
}
 
/** 
 * Write the deformation field data file.
 */ 
void
06028 BrainSet::writeDeformationFieldFile(const QString& name) throw (FileException)
{
   loadedFilesSpecFile.deformationMapFile.setAllSelections(SpecFile::SPEC_FALSE);
   deformationFieldFile->writeFile(name);
   addToSpecFile(SpecFile::getDeformationFieldFileTag(), name);
}

/**
 * read the deformation field data file (only selected columns).
 */
void 
06039 BrainSet::readDeformationFieldFile(const QString& name, 
                         const std::vector<int>& columnDestination,
                         const std::vector<QString>& fileBeingReadColumnNames,
                         const AbstractFile::FILE_COMMENT_MODE fcm,
                         const bool updateSpec) throw (FileException)
{
   QMutexLocker locker(&mutexDeformationFieldFile);
   
   DeformationFieldFile dff;
   dff.readFile(name);
   if (dff.getNumberOfNodes() != getNumberOfNodes()) {
      throw FileException(FileUtilities::basename(name), numNodesMessage);
   }
   try {
      for (int i = 0; i < dff.getNumberOfColumns(); i++) {
         if (i < static_cast<int>(fileBeingReadColumnNames.size())) {
            dff.setColumnName(i, fileBeingReadColumnNames[i]);
         }
      }
      deformationFieldFile->append(dff, columnDestination, fcm);
   }
   catch (FileException& e) {
      throw FileException(FileUtilities::basename(name), e.whatQString());
   }
   deformationFieldFile->setModified();
   displaySettingsDeformationField->update(); 
   
   if (updateSpec) {
      addToSpecFile(SpecFile::getDeformationFieldFileTag(), name);
   }
}


/**      
 * Read the deformation field data file file
 */
void 
06076 BrainSet::readDeformationFieldFile(const QString& name, const bool append,
                            const bool updateSpec) throw (FileException)
{
   QMutexLocker locker(&mutexDeformationFieldFile);
   
   if (append == false) {
      clearDeformationFieldFile();
   }
   const unsigned long modified = deformationFieldFile->getModified();
   
   if (deformationFieldFile->getNumberOfColumns() == 0) {         
      try {
         deformationFieldFile->readFile(name);
         if (deformationFieldFile->getNumberOfNodes() != getNumberOfNodes()) {
            throw FileException(FileUtilities::basename(name), numNodesMessage);
         }
      }
      catch (FileException& e) {
         clearDeformationFieldFile();
         throw FileException(FileUtilities::basename(name), e.whatQString());
      }
   }
   else {
      // Append to existing 
      DeformationFieldFile dff;
      dff.readFile(name);
      if (dff.getNumberOfNodes() != getNumberOfNodes()) {
         throw FileException(FileUtilities::basename(name), numNodesMessage);
      }
      try {
         deformationFieldFile->append(dff);
      }
      catch (FileException& e) {
         throw FileException(FileUtilities::basename(name), e.whatQString());
      }
   }
   deformationFieldFile->setModifiedCounter(modified);
   displaySettingsDeformationField->update(); 
   
   if (updateSpec) {
      addToSpecFile(SpecFile::getDeformationFieldFileTag(), name);
   }
}
      
/** 
 * Write the paint data file.
 */ 
void
06124 BrainSet::writePaintFile(const QString& name) throw (FileException)
{
   loadedFilesSpecFile.paintFile.setAllSelections(SpecFile::SPEC_FALSE);
   paintFile->writeFile(name);
   addToSpecFile(SpecFile::getPaintFileTag(), name);
}

/**
 * read the paint data file file (only selected columns).
 */
void 
06135 BrainSet::readPaintFile(const QString& name, 
                        const std::vector<int>& columnDestination,
                        const std::vector<QString>& fileBeingReadColumnNames,
                        const AbstractFile::FILE_COMMENT_MODE fcm,
                        const bool updateSpec) throw (FileException)
{
   QMutexLocker locker(&mutexPaintFile);
   
   const bool paintFileEmpty = paintFile->empty();
   
   PaintFile pf;
   pf.readFile(name);
   if (pf.getNumberOfNodes() != getNumberOfNodes()) {
      throw FileException(FileUtilities::basename(name), numNodesMessage);
   }
   try {
      for (int i = 0; i < pf.getNumberOfColumns(); i++) {
         if (i < static_cast<int>(fileBeingReadColumnNames.size())) {
            pf.setColumnName(i, fileBeingReadColumnNames[i]);
         }
      }
      std::vector<int> columnDestination2 = columnDestination;
      paintFile->append(pf, columnDestination2, fcm);
      paintFile->getLabelTable()->addColorsToColorFile(*areaColorFile);
   }
   catch (FileException& e) {
      throw FileException(FileUtilities::basename(name), e.whatQString());
   }
   if (paintFileEmpty) {
      paintFile->clearModified();
   }
   else {
      paintFile->setModified();
   }

   if (readingSpecFileFlag == false) {
      displaySettingsPaint->update();
   }
   
   if (updateSpec) {
      addToSpecFile(SpecFile::getPaintFileTag(), name);
   }
}

/**      
 * Read the paint data file file
 */
void 
06183 BrainSet::readPaintFile(const QString& name, const bool append,
                            const bool updateSpec) throw (FileException)
{
   QMutexLocker locker(&mutexPaintFile);
   
   if (append == false) {
      clearPaintFile();
   }
   const unsigned long modified = paintFile->getModified();
   
   if (paintFile->getNumberOfColumns() == 0) {         
      try {
         paintFile->readFile(name);
         if (paintFile->getNumberOfNodes() != getNumberOfNodes()) {
            throw FileException(FileUtilities::basename(name), numNodesMessage);
         }
         paintFile->getLabelTable()->addColorsToColorFile(*areaColorFile);
      }
      catch (FileException& e) {
         clearPaintFile();
         throw FileException(FileUtilities::basename(name), e.whatQString());
      }
   }
   else {
      // Append to existing 
      PaintFile pf;
      pf.readFile(name);
      if (pf.getNumberOfNodes() != getNumberOfNodes()) {
         throw FileException(FileUtilities::basename(name), numNodesMessage);
      }
      try {
         paintFile->append(pf);
         paintFile->getLabelTable()->addColorsToColorFile(*areaColorFile);
      }
      catch (FileException& e) {
         throw FileException(FileUtilities::basename(name), e.whatQString());
      }
   }
   paintFile->setModifiedCounter(modified);

   if (readingSpecFileFlag == false) {
      displaySettingsPaint->update();
   }
   
   if (updateSpec) {
      addToSpecFile(SpecFile::getPaintFileTag(), name);
   }
}

/**      
 * Read the study meta data file 
 */
void 
06236 BrainSet::readStudyMetaDataFile(const QString& name, const bool append,
                            const bool updateSpec) throw (FileException)
{
   QMutexLocker locker(&mutexStudyMetaDataFile);
   
   if (append == false) {
      clearStudyMetaDataFile();
   }
   const unsigned long modified = studyMetaDataFile->getModified();
   
   if (studyMetaDataFile->empty()) {
      try {
         studyMetaDataFile->readFile(name);
      }
      catch (FileException& e) {
         clearStudyMetaDataFile();
         throw e;
      }
   }
   else {
      StudyMetaDataFile smdf;
      smdf.readFile(name);
      studyMetaDataFile->append(smdf);
   }
   
   studyMetaDataFile->setModifiedCounter(modified);
   
   if (updateSpec) {
      addToSpecFile(SpecFile::getStudyMetaDataFileTag(), name);
   }
   
   if (readingSpecFileFlag == false) {
      displaySettingsStudyMetaData->update();
   }
}
      
/** 
 * Write the study meta data file.
 */ 
void
06276 BrainSet::writeStudyMetaDataFile(const QString& name) throw (FileException)
{
   loadedFilesSpecFile.studyMetaDataFile.setAllSelections(SpecFile::SPEC_FALSE);
   studyMetaDataFile->writeFile(name);
   addToSpecFile(SpecFile::getStudyMetaDataFileTag(), name);
}

/**      
 * Read the study collection file 
 */
void 
06287 BrainSet::readStudyCollectionFile(const QString& name, const bool append,
                                  const bool updateSpec) throw (FileException)
{
   QMutexLocker locker(&mutexStudyCollectionFile);
   
   if (append == false) {
      clearStudyCollectionFile();
   }
   const unsigned long modified = studyCollectionFile->getModified();
   
   if (studyCollectionFile->empty()) {
      try {
         studyCollectionFile->readFile(name);
      }
      catch (FileException& e) {
         clearStudyCollectionFile();
         throw e;
      }
   }
   else {
      StudyCollectionFile scf;
      scf.readFile(name);
      studyCollectionFile->append(scf);
   }
   
   studyCollectionFile->setModifiedCounter(modified);
   
   if (updateSpec) {
      addToSpecFile(SpecFile::getStudyCollectionFileTag(), name);
   }
   
   if (readingSpecFileFlag == false) {
///      displaySettingsStudyMetaData->update();
   }
}
      
/** 
 * Write the study collection file.
 */ 
void
06327 BrainSet::writeStudyCollectionFile(const QString& name) throw (FileException)
{
   loadedFilesSpecFile.studyCollectionFile.setAllSelections(SpecFile::SPEC_FALSE);
   studyCollectionFile->writeFile(name);
   addToSpecFile(SpecFile::getStudyCollectionFileTag(), name);
}

      
/**      
 * Read the vocabulary data file 
 */
void 
06339 BrainSet::readVocabularyFile(const QString& name, const bool append,
                            const bool updateSpec) throw (FileException)
{
   QMutexLocker locker(&mutexVocabularyFile);
   
   if (append == false) {
      clearVocabularyFile();
   }
   const unsigned long modified = vocabularyFile->getModified();
   
   if (vocabularyFile->empty()) {
      try {
         vocabularyFile->readFile(name);
      }
      catch (FileException& e) {
         clearVocabularyFile();
         throw e;
      }
   }
   else {
      VocabularyFile vf;
      vf.readFile(name);
      vocabularyFile->append(vf);
   }
   
   vocabularyFile->setModifiedCounter(modified);
   
   if (updateSpec) {
      addToSpecFile(SpecFile::getVocabularyFileTag(), name);
   }
}
      
/** 
 * Write the vocabulary data file.
 */ 
void
06375 BrainSet::writeVocabularyFile(const QString& name) throw (FileException)
{
   loadedFilesSpecFile.vocabularyFile.setAllSelections(SpecFile::SPEC_FALSE);
   vocabularyFile->writeFile(name);
   addToSpecFile(SpecFile::getVocabularyFileTag(), name);
}

/**      
 * Read the wustl region data file 
 */
void 
06386 BrainSet::readWustlRegionFile(const QString& name, const bool append,
                            const bool updateSpec) throw (FileException)
{
   QMutexLocker locker(&mutexWustlRegionFile);
   
   if (append == false) {
      clearWustlRegionFile();
   }
   const unsigned long modified = wustlRegionFile->getModified();
   
   if (wustlRegionFile->getNumberOfTimeCourses() == 0) {
      try {
         wustlRegionFile->readFile(name);
      }
      catch (FileException& e) {
         clearWustlRegionFile();
         throw e;
      }
   }
   else {
      WustlRegionFile wrf;
      wrf.readFile(name);
      wustlRegionFile->append(wrf);
   }
   
   wustlRegionFile->setModifiedCounter(modified);
   displaySettingsWustlRegion->update();
   
   if (updateSpec) {
      addToSpecFile(SpecFile::getWustlRegionFileTag(), name);
   }
}
      
/** 
 * Write the wustl region data file.
 */ 
void
06423 BrainSet::writeWustlRegionFile(const QString& name) throw (FileException)
{
   loadedFilesSpecFile.wustlRegionFile.setAllSelections(SpecFile::SPEC_FALSE);
   wustlRegionFile->writeFile(name);
   addToSpecFile(SpecFile::getWustlRegionFileTag(), name);
}

/** 
 * Write the Palette data file.
 */ 
void
06434 BrainSet::writePaletteFile(const QString& name) throw (FileException)
{
   loadedFilesSpecFile.paletteFile.setAllSelections(SpecFile::SPEC_FALSE);
   paletteFile->writeFile(name);
   addToSpecFile(SpecFile::getPaletteFileTag(), name);
}

/**      
 * Read the palette data file file
 */
void 
06445 BrainSet::readPaletteFile(const QString& name, const bool append,
                            const bool updateSpec) throw (FileException)
{
   QMutexLocker locker(&mutexPaletteFile);
   
   if (append == false) {
      clearPaletteFile();
   }
   const unsigned long modified = paletteFile->getModified();
   
   if (paletteFile->getNumberOfPalettes() == 0) {
      try {
         paletteFile->readFile(name);
      }
      catch (FileException& e) {
         clearPaletteFile();
         throw e;
      }
   }
   else {
      PaletteFile pf;
      pf.readFile(name);
      paletteFile->append(pf);
   }
   
   paletteFile->setModifiedCounter(modified);
   displaySettingsMetric->update(); 
   displaySettingsSurfaceShape->update();
   
   if (updateSpec) {
      addToSpecFile(SpecFile::getPaletteFileTag(), name);
   }
}
      
/** 
 * Write the params data file.
 */ 
void
06483 BrainSet::writeParamsFile(const QString& name) throw (FileException)
{
   loadedFilesSpecFile.paramsFile.setAllSelections(SpecFile::SPEC_FALSE);
   paramsFile->writeFile(name);
   addToSpecFile(SpecFile::getParamsFileTag(), name);
}

/**      
 * Read the params data file file
 */
void 
06494 BrainSet::readParamsFile(const QString& name, const bool append,
                         const bool updateSpec) throw (FileException)
{
   QMutexLocker locker(&mutexParamsFile);
   
   if (append == false) {
      clearParamsFile();
   }
   const unsigned long modified = paramsFile->getModified();
   
   if (paramsFile->empty() == 0) {
      try {
         paramsFile->readFile(name);
      }
      catch (FileException& e) {
         clearParamsFile();
         throw e;
      }
   }
   else {
      ParamsFile pf;
      pf.readFile(name);
      QString msg;
      paramsFile->append(pf, msg);
      if (msg.isEmpty() == false) {
         throw FileException(name, msg);
      }
   }
   
   paramsFile->setModifiedCounter(modified);
   
   if (updateSpec) {
      addToSpecFile(SpecFile::getParamsFileTag(), name);
   }
}
      
/** 
 * Write the probabilistic atlas data file.
 */ 
void
06534 BrainSet::writeProbabilisticAtlasFile(const QString& name) throw (FileException)
{
   loadedFilesSpecFile.atlasFile.setAllSelections(SpecFile::SPEC_FALSE);
   probabilisticAtlasSurfaceFile->writeFile(name);
   addToSpecFile(SpecFile::getAtlasFileTag(), name);
}

/**      
 * Read the prob atlas data file file
 */
void 
06545 BrainSet::readProbabilisticAtlasFile(const QString& name, const bool append,
                            const bool updateSpec) throw (FileException)
{
   QMutexLocker locker(&mutexProbAtlasFile);
   
   if (append == false) {
      clearProbabilisticAtlasFile();
   }
   const unsigned long modified = probabilisticAtlasSurfaceFile->getModified();
   
   if (probabilisticAtlasSurfaceFile->getNumberOfColumns() == 0) {         
      try {
         probabilisticAtlasSurfaceFile->readFile(name);
         if (probabilisticAtlasSurfaceFile->getNumberOfNodes() != getNumberOfNodes()) {
            throw FileException(FileUtilities::basename(name), numNodesMessage);
         }
      }
      catch (FileException& e) {
         clearProbabilisticAtlasFile();
         throw FileException(FileUtilities::basename(name), e.whatQString());
      }
   }
   else {
      // Append to existing 
      ProbabilisticAtlasFile paf;
      paf.readFile(name);
      if (paf.getNumberOfNodes() != getNumberOfNodes()) {
         throw FileException(FileUtilities::basename(name), numNodesMessage);
      }
      try {
         probabilisticAtlasSurfaceFile->append(paf);
      }
      catch (FileException& e) {
         throw FileException(FileUtilities::basename(name), e.whatQString());
      }
   }
   probabilisticAtlasSurfaceFile->setModifiedCounter(modified);
   displaySettingsProbabilisticAtlasSurface->update();
   
   if (updateSpec) {
      addToSpecFile(SpecFile::getAtlasFileTag(), name);
   }
}
      
/** 
 * Write the rgb paint data file.
 */ 
void
06593 BrainSet::writeRgbPaintFile(const QString& name) throw (FileException)
{
   loadedFilesSpecFile.rgbPaintFile.setAllSelections(SpecFile::SPEC_FALSE);
   rgbPaintFile->writeFile(name);
   addToSpecFile(SpecFile::getRgbPaintFileTag(), name);
}

/**      
 * Read the rgb paint data file file
 */
void 
06604 BrainSet::readRgbPaintFile(const QString& name, const bool append,
                            const bool updateSpec) throw (FileException)
{
   QMutexLocker locker(&mutexRgbPaintFile);
   
   if (append == false) {
      clearRgbPaintFile();
   }
   const unsigned long modified = rgbPaintFile->getModified();
   
   if (rgbPaintFile->getNumberOfColumns() == 0) {         
      try {
         rgbPaintFile->readFile(name);
         if (rgbPaintFile->getNumberOfNodes() != getNumberOfNodes()) {
            throw FileException(FileUtilities::basename(name), numNodesMessage);
         }
      }
      catch (FileException& e) {
         clearRgbPaintFile();
         throw FileException(FileUtilities::basename(name), e.whatQString());
      }
   }
   else {
      // Append to existing 
      RgbPaintFile rf;
      rf.readFile(name);
      if (rf.getNumberOfNodes() != getNumberOfNodes()) {
         throw FileException(FileUtilities::basename(name), numNodesMessage);
      }
      try {
         rgbPaintFile->append(rf);
      }
      catch (FileException& e) {
         throw FileException(FileUtilities::basename(name), e.whatQString());
      }
   }
   rgbPaintFile->setModifiedCounter(modified);
   displaySettingsRgbPaint->update();  
   
   if (updateSpec) {
      addToSpecFile(SpecFile::getRgbPaintFileTag(), name);
   }
}
      
/** 
 * Write the scene data file.
 */ 
void
06652 BrainSet::writeSceneFile(const QString& name) throw (FileException)
{
   loadedFilesSpecFile.sceneFile.setAllSelections(SpecFile::SPEC_FALSE);
   sceneFile->writeFile(name);
   addToSpecFile(SpecFile::getSceneFileTag(), name);
}

/**      
 * Read the scene data file file
 */
void 
06663 BrainSet::readSceneFile(const QString& name, const bool append,
                            const bool updateSpec) throw (FileException)
{
   QMutexLocker locker(&mutexSceneFile);
   
   if (append == false) {
      clearSceneFile();
   }
   const unsigned long modified = sceneFile->getModified();
   
   if (sceneFile->empty()) {
      sceneFile->readFile(name);
      //
      // Special processing for WebCaret.  In SuMS, a spec file and its data files are
      // stored in a single directory.  However, a scene file may still have relative paths
      // for data files loaded at the time of scene creation so strip the paths from the files
      //
      if (webCaretFlag) {
         sceneFile->removePathsFromAllSpecFileDataFileNames();
      }
   }
   else {
      try {
         SceneFile sf;
         sf.readFile(name);
         //
         // Special processing for WebCaret.  In SuMS, a spec file and its data files are
         // stored in a single directory.  However, a scene file may still have relative paths
         // for data files loaded at the time of scene creation so strip the paths from the files
         //
         if (webCaretFlag) {
            sf.removePathsFromAllSpecFileDataFileNames();
         }
         sceneFile->append(sf);
      }
      catch (FileException& e) {
         clearSceneFile();
         throw e;
      }
   }
   sceneFile->setModifiedCounter(modified);
   displaySettingsScene->update();
   
   if (updateSpec) {
      addToSpecFile(SpecFile::getSceneFileTag(), name);
   }
}
      
/** 
 * Write the section data file.
 */ 
void
06715 BrainSet::writeSectionFile(const QString& name) throw (FileException)
{
   loadedFilesSpecFile.sectionFile.setAllSelections(SpecFile::SPEC_FALSE);
   sectionFile->writeFile(name);
   addToSpecFile(SpecFile::getSectionFileTag(), name);
}

/**      
 * Read the section data file file
 */
void 
06726 BrainSet::readSectionFile(const QString& name, const bool append,
                            const bool updateSpec) throw (FileException)
{
   QMutexLocker locker(&mutexSectionFile);
   
   if (append == false) {
      clearSectionFile();
   }
   const unsigned long modified = sectionFile->getModified();
   
   if (sectionFile->getNumberOfColumns() == 0) {         
      try {
         sectionFile->readFile(name);
         if (sectionFile->getNumberOfNodes() != getNumberOfNodes()) {
            throw FileException(FileUtilities::basename(name), numNodesMessage);
         }
      }
      catch (FileException& e) {
         clearSectionFile();
         throw FileException(FileUtilities::basename(name), e.whatQString());
      }
   }
   else {
      // Append to existing 
      SectionFile sf;
      sf.readFile(name);
      if (sf.getNumberOfNodes() != getNumberOfNodes()) {
         throw FileException(FileUtilities::basename(name), numNodesMessage);
      }
      try {
         sectionFile->append(sf);
      }
      catch (FileException& e) {
         throw FileException(FileUtilities::basename(name), e.whatQString());
      }
   }
   sectionFile->setModifiedCounter(modified);
   
   if (updateSpec) {
      addToSpecFile(SpecFile::getSectionFileTag(), name);
   }
   displaySettingsSection->update();
}
      
/** 
 * Write the surface shape data file.
 */ 
void
06774 BrainSet::writeSurfaceShapeFile(const QString& name) throw (FileException)
{
   loadedFilesSpecFile.surfaceShapeFile.setAllSelections(SpecFile::SPEC_FALSE);
   surfaceShapeFile->writeFile(name);
   addToSpecFile(SpecFile::getSurfaceShapeFileTag(), name);
}

/**
 * read the surface shape data file file (only selected columns).
 */
void 
06785 BrainSet::readSurfaceShapeFile(const QString& name, 
                               const std::vector<int>& columnDestination,
                               const std::vector<QString>& fileBeingReadColumnNames,
                               const AbstractFile::FILE_COMMENT_MODE fcm,
                               const bool updateSpec) throw (FileException)
{
   QMutexLocker locker(&mutexSurfaceShapeFile);
   
   const bool shapeEmpty = surfaceShapeFile->empty();
   
   SurfaceShapeFile ssf;
   ssf.setNumberOfNodesForSparseNodeIndexFiles(getNumberOfNodes());
   ssf.readFile(name);
   if (ssf.getNumberOfNodes() != getNumberOfNodes()) {
      throw FileException(FileUtilities::basename(name), numNodesMessage);
   }
   try {
      for (int i = 0; i < ssf.getNumberOfColumns(); i++) {
         if (i < static_cast<int>(fileBeingReadColumnNames.size())) {
            ssf.setColumnName(i, fileBeingReadColumnNames[i]);
         }
      }
      std::vector<int> columnDestination2 = columnDestination;
      surfaceShapeFile->append(ssf, columnDestination2, fcm);
   }
   catch (FileException& e) {
      throw FileException(FileUtilities::basename(name), e.whatQString());
   }
   
   if (shapeEmpty) {
      surfaceShapeFile->clearModified();
   }
   else {
      surfaceShapeFile->setModified();
   }

   if (readingSpecFileFlag == false) {
      displaySettingsSurfaceShape->update();  
   }
   
   if (updateSpec) {
      addToSpecFile(SpecFile::getSurfaceShapeFileTag(), name);
   }
}

/**      
 * Read the surface shape data file file
 */
void 
06834 BrainSet::readSurfaceShapeFile(const QString& name, const bool append,
                            const bool updateSpec) throw (FileException)
{
   QMutexLocker locker(&mutexSurfaceShapeFile);
   
   if (append == false) {
      clearSurfaceShapeFile();
   }
   const unsigned long modified = surfaceShapeFile->getModified();
   
   if (surfaceShapeFile->getNumberOfColumns() == 0) {         
      try {
         surfaceShapeFile->readFile(name);
         if (surfaceShapeFile->getNumberOfNodes() != getNumberOfNodes()) {
            throw FileException(FileUtilities::basename(name), numNodesMessage);
         }
      }
      catch (FileException& e) {
         clearSurfaceShapeFile();
         throw FileException(FileUtilities::basename(name), e.whatQString());
      }
   }
   else {
      // Append to existing 
      SurfaceShapeFile ssf;
      ssf.readFile(name);
      if (ssf.getNumberOfNodes() != getNumberOfNodes()) {
         throw FileException(FileUtilities::basename(name), numNodesMessage);
      }
      try {
         surfaceShapeFile->append(ssf);
      }
      catch (FileException& e) {
         throw FileException(FileUtilities::basename(name), e.whatQString());
      }
   }
   surfaceShapeFile->setModifiedCounter(modified);

   if (readingSpecFileFlag == false) {
      displaySettingsSurfaceShape->update();  
   }
   
   if (updateSpec) {
      addToSpecFile(SpecFile::getSurfaceShapeFileTag(), name);
   }
}
      
/** 
 * Write the vector data file.
 */ 
void
06885 BrainSet::writeVectorFile(VectorFile* vf, const QString& name) throw (FileException)
{
   loadedFilesSpecFile.vectorFile.clearSelectionStatus(vf->getFileName());
   vf->writeFile(name);
   addToSpecFile(SpecFile::getVectorFileTag(), name);
}

/**      
 * Read the vector data file file
 */
void 
06896 BrainSet::readVectorFile(const QString& name, const bool append,
                            const bool updateSpec) throw (FileException)
{
   QMutexLocker locker(&mutexVectorFile);
   
   if (append == false) {
      clearVectorFiles();
   }
   VectorFile* vf = NULL;
   try {
      vf = new VectorFile();
      vf->readFile(name);
      addVectorFile(vf);
   }
   catch (FileException& e) {
      if (vf != NULL) {
         delete vf;
      }
      throw FileException(FileUtilities::basename(name), e.whatQString());
   }
   displaySettingsVectors->update();  
   
   if (updateSpec) {
      addToSpecFile(SpecFile::getVectorFileTag(), name);
   }
   clearAllDisplayLists();
}

/** 
 * Write the topography data file.
 */ 
void
06928 BrainSet::writeTopographyFile(const QString& name) throw (FileException)
{
   loadedFilesSpecFile.topographyFile.setAllSelections(SpecFile::SPEC_FALSE);
   topographyFile->writeFile(name);
   addToSpecFile(SpecFile::getTopographyFileTag(), name);
}

/**      
 *BrainSet::read the topography data file file
 */
void 
06939 BrainSet::readTopographyFile(const QString& name, const bool append,
                            const bool updateSpec) throw (FileException)
{
   QMutexLocker locker(&mutexTopographyFile);
   
   if (append == false) {
      clearTopographyFile();
   }
   const unsigned long modified = topographyFile->getModified();
   
   if (topographyFile->getNumberOfColumns() == 0) {         
      try {
         topographyFile->setNumberOfNodesVersion0File(getNumberOfNodes());
         topographyFile->readFile(name);
         if (topographyFile->getNumberOfNodes() != getNumberOfNodes()) {
            throw FileException(FileUtilities::basename(name), numNodesMessage);
         }
      }
      catch (FileException& e) {
         clearTopographyFile();
         throw FileException(FileUtilities::basename(name), e.whatQString());
      }
   }
   else {
      // Append to existing 
      TopographyFile tf;
      tf.setNumberOfNodesVersion0File(getNumberOfNodes());
      tf.readFile(name);
      if (tf.getNumberOfNodes() != getNumberOfNodes()) {
         throw FileException(FileUtilities::basename(name), numNodesMessage);
      }
      try {
         topographyFile->append(tf);
      }
      catch (FileException& e) {
         throw FileException(FileUtilities::basename(name), e.whatQString());
      }
   }
   topographyFile->setModifiedCounter(modified);
   displaySettingsTopography->update();
   
   if (updateSpec) {
      addToSpecFile(SpecFile::getTopographyFileTag(), name);
   }
}

/** 
 * Write the transformation matrix data file.
 */ 
void
06989 BrainSet::writeTransformationMatrixFile(const QString& name) throw (FileException)
{
   loadedFilesSpecFile.transformationMatrixFile.setAllSelections(SpecFile::SPEC_FALSE);
   transformationMatrixFile->writeFile(name);
   addToSpecFile(SpecFile::getTransformationMatrixFileTag(), name);
}

/**      
 * read the transformation matrix file
 */
void 
07000 BrainSet::readTransformationMatrixFile(const QString& name, const bool append,
                            const bool updateSpec) throw (FileException)
{
   QMutexLocker locker(&mutexTransformationMatrixFile);
   
   if (append == false) {
      clearTransformationMatrixFile();
   }
   const unsigned long modified = transformationMatrixFile->getModified();
   
   if (transformationMatrixFile->getNumberOfMatrices() == 0) {         
      try {
         transformationMatrixFile->readFile(name);
      }
      catch (FileException& e) {
         clearTransformationMatrixFile();
         throw FileException(FileUtilities::basename(name), e.whatQString());
      }
   }
   else {
      // Append to existing 
      TransformationMatrixFile tf;
      tf.readFile(name);
      transformationMatrixFile->append(tf);
   }
   transformationMatrixFile->setModifiedCounter(modified);
   
   if (updateSpec) {
      addToSpecFile(SpecFile::getTransformationMatrixFileTag(), name);
   }
}

/**      
 * read the transformation matrix data file
 */
void 
07036 BrainSet::readTransformationDataFile(const QString& name, const bool append,
                            const bool updateSpec) throw (FileException)
{
   QMutexLocker locker(&mutexTransformationDataFile);
   
   if (append == false) {
      transformationDataFiles.clear();
   }

   QString errorMessage;
   AbstractFile* ab = AbstractFile::readAnySubClassDataFile(name,
                                                            false,
                                                            errorMessage);
   if (ab == NULL) {
      throw FileException(FileUtilities::basename(name), errorMessage);
   }

   transformationDataFiles.push_back(ab);
   
   if (updateSpec) {
      addToSpecFile(SpecFile::getTransformationDataFileTag(), name);
   }
}

/** 
 * Write the topology data file.
 */ 
void
07064 BrainSet::writeTopologyFile(const QString& name,
                    const TopologyFile::TOPOLOGY_TYPES tt,
                    TopologyFile* tf) throw (FileException)
{
   switch(tf->getTopologyType()) {
      case TopologyFile::TOPOLOGY_TYPE_CLOSED:
         loadedFilesSpecFile.closedTopoFile.clearSelectionStatus(tf->getFileName());
         break;
      case TopologyFile::TOPOLOGY_TYPE_OPEN:
         loadedFilesSpecFile.openTopoFile.clearSelectionStatus(tf->getFileName());
         break;
      case TopologyFile::TOPOLOGY_TYPE_CUT:
         loadedFilesSpecFile.cutTopoFile.clearSelectionStatus(tf->getFileName());
         break;
      case TopologyFile::TOPOLOGY_TYPE_LOBAR_CUT:
         loadedFilesSpecFile.lobarCutTopoFile.clearSelectionStatus(tf->getFileName());
         break;
      case TopologyFile::TOPOLOGY_TYPE_UNKNOWN:
      case TopologyFile::TOPOLOGY_TYPE_UNSPECIFIED:
         loadedFilesSpecFile.unknownTopoFile.clearSelectionStatus(tf->getFileName());
         break;
   }


   tf->setTopologyType(tt);
   QString tag;
   switch(tt) {
      case TopologyFile::TOPOLOGY_TYPE_CLOSED:
         tag = SpecFile::getClosedTopoFileTag();
         break;
      case TopologyFile::TOPOLOGY_TYPE_OPEN:
         tag = SpecFile::getOpenTopoFileTag();
         break;
      case TopologyFile::TOPOLOGY_TYPE_CUT:
         tag = SpecFile::getCutTopoFileTag();
         break;
      case TopologyFile::TOPOLOGY_TYPE_LOBAR_CUT:
         tag = SpecFile::getLobarCutTopoFileTag();
         break;
      case TopologyFile::TOPOLOGY_TYPE_UNKNOWN:
      case TopologyFile::TOPOLOGY_TYPE_UNSPECIFIED:
         tag = SpecFile::getUnknownTopoFileMatchTag();
         break;
   }
   
   tf->writeFile(name);
   addToSpecFile(tag, name);
}

/**      
 * Read the topology data file file.  When reading spec file, new topology files are placed at
 * the end of the vector that holds them.  When not reading a spec file, the user is opening
 * a topology file so make it the active one.
 */
void 
07119 BrainSet::readTopologyFile(const QString& name, const TopologyFile::TOPOLOGY_TYPES ttin,
                            const bool append,
                            const bool updateSpec) throw (FileException)
{
   TopologyFile::TOPOLOGY_TYPES tt = ttin;
   if ((tt == TopologyFile::TOPOLOGY_TYPE_UNSPECIFIED) ||
       (tt == TopologyFile::TOPOLOGY_TYPE_UNKNOWN)) {
      TopologyFile tf;
      tf.readFileMetaDataOnly(name);
      const QString typeTag = tf.getHeaderTag(AbstractFile::headerTagPerimeterID);
      if (typeTag.isEmpty() == false) {
         tt = TopologyFile::getTopologyTypeFromPerimeterID(typeTag);
      }
   }
   
   TopologyFile* topoJustRead = new TopologyFile;
   try {
      topoJustRead->readFile(name);
   }
   catch (FileException& e) {
      delete topoJustRead;
      throw FileException(FileUtilities::basename(name), e.whatQString());
   }
   
   QString tag;
   
   //
   // This keeps track of any topology files that are being deleted (because append == false).
   // This allows the new topology file to be applied to coordinate files.
   //
   std::vector<TopologyFile*> replacedTopologyFiles;
   
   //
   // The remainder of this routine must not be run by more than one thread
   //
   QMutexLocker locker(&mutexReadTopologyFile);
   
   //
   // If not appending, remove any topology files that are the same type as
   // the topology file being read.  The newest file is always placed in the 
   // first spot.
   //
   if (append == false) {
      std::vector<TopologyFile*> tempFiles;
      tempFiles.push_back(topoJustRead);
      
      const int numTopo = getNumberOfTopologyFiles();
      for (int i = 0; i < numTopo; i++) {
         TopologyFile* tf = getTopologyFile(i);
         if (tt == tf->getTopologyType()) {
            replacedTopologyFiles.push_back(tf);
            delete tf;
         }
         else {
            tempFiles.push_back(tf);
         }
      }
      topologyFiles = tempFiles;
   }
   else {
      topologyFiles.insert(topologyFiles.begin(), topoJustRead);
   }
   
   //
   // Override topology type in the TopologyFile just read.
   //
   if (topoJustRead->getTopologyType() != tt) {
      topoJustRead->setTopologyType(tt);
   }

   switch(tt) {
      case TopologyFile::TOPOLOGY_TYPE_CLOSED:
         tag = SpecFile::getClosedTopoFileTag();
         break;
      case TopologyFile::TOPOLOGY_TYPE_OPEN:
         tag = SpecFile::getOpenTopoFileTag();
         break;
      case TopologyFile::TOPOLOGY_TYPE_CUT:
         tag = SpecFile::getCutTopoFileTag();
         break;
      case TopologyFile::TOPOLOGY_TYPE_LOBAR_CUT:
         tag = SpecFile::getLobarCutTopoFileTag();
         break;
      case TopologyFile::TOPOLOGY_TYPE_UNKNOWN:
      case TopologyFile::TOPOLOGY_TYPE_UNSPECIFIED:
      default:
         tag = SpecFile::getUnknownTopoFileMatchTag();
         break;
   }
   
   if (updateSpec) {
      addToSpecFile(tag, name);
   }
   
   //
   // If any surface was using a deleted topology file, replace it with
   // the topology file that was just read.
   //
   if (replacedTopologyFiles.size() > 0) {
      for (int i = 0; i < getNumberOfBrainModels(); i++) {
         BrainModel* bm = getBrainModel(i);
         if (bm->getModelType() == BrainModel::BRAIN_MODEL_SURFACE) {
            BrainModelSurface* bms = dynamic_cast<BrainModelSurface*>(bm);
            TopologyFile* stf = bms->getTopologyFile();
            if (std::find(replacedTopologyFiles.begin(), replacedTopologyFiles.end(), stf) !=
                replacedTopologyFiles.end()) {
               bms->setTopologyFile(topoJustRead);
            }
         }
      }
   }
   
   setSelectedTopologyFiles();
}

/**
 * Add a topology file
 */
void
07238 BrainSet::addTopologyFile(TopologyFile* tf)
{
   topologyFiles.push_back(tf);
}

/**
 * delete topology file.
 */
void 
07247 BrainSet::deleteTopologyFile(TopologyFile* tf)
{
   if (tf == NULL) {
      return;
   }
   
   loadedFilesSpecFile.closedTopoFile.clearSelectionStatus(tf->getFileName());
   loadedFilesSpecFile.openTopoFile.clearSelectionStatus(tf->getFileName());
   loadedFilesSpecFile.cutTopoFile.clearSelectionStatus(tf->getFileName());
   loadedFilesSpecFile.lobarCutTopoFile.clearSelectionStatus(tf->getFileName());
   loadedFilesSpecFile.unknownTopoFile.clearSelectionStatus(tf->getFileName());
                                            
   int topoIndex = -1;
   std::vector<TopologyFile*> savedTopologyFiles;
   for (int i = 0; i < getNumberOfTopologyFiles(); i++) {
      TopologyFile* topology = getTopologyFile(i);
      if (topology != tf) {
         savedTopologyFiles.push_back(topology);
      }
      else {
         topoIndex = i;
      }
   }
   topologyFiles = savedTopologyFiles;
   delete tf;

   setSelectedTopologyFiles();
   
   //
   // If delete topology was used by a surface, give the surface a new topo file
   //
   if ((topoIndex < 0) || (topoIndex >= getNumberOfTopologyFiles())) {
      topoIndex = 0;
   }
   TopologyFile* newTF = NULL;
   if ((topoIndex >= 0) && (topoIndex < getNumberOfTopologyFiles())) {
      newTF = getTopologyFile(topoIndex);
   }
   for (int i = 0; i < getNumberOfBrainModels(); i++) {
      BrainModelSurface* bms = getBrainModelSurface(i);
      if (bms != NULL) {
         if (bms->getTopologyFile() == tf) {
            bms->setTopologyFile(newTF);
         }
      }
   }
   clearAllDisplayLists();
}      

/**
 * Read in surface file group.
 */
bool 
07300 BrainSet::readSurfaceFileGroup(const SpecFile::Entry& surfaceFile,
                               const BrainModelSurface::SURFACE_TYPES surfaceType,
                               std::vector<QString>& errorMessages,
                               int& progressFileCounter,
                               QProgressDialog* progressDialog)
{
   for (unsigned i = 0; i < surfaceFile.files.size(); i++) {
      if (surfaceFile.files[i].selected) {
         if (updateFileReadProgressDialog(surfaceFile.files[i].filename, progressFileCounter, progressDialog)) {
            return true;
         }
         try {
            readSurfaceFile(surfaceFile.files[i].filename, surfaceType, true, true, true);
         }
         catch (FileException& e) {
            errorMessages.push_back(e.whatQString());
         }
      }
   }
   
   return false;
}      

/**
 * Read some coordinate files.  Returns true if file reading was aborted.
 */
bool
07327 BrainSet::readCoordinateFileGroup(const SpecFile::Entry& coordFile,
                               const BrainModelSurface::SURFACE_TYPES surfaceType,
                               std::vector<QString>& errorMessages,
                               int& progressFileCounter,
                               QProgressDialog* progressDialog)
{
   for (unsigned i = 0; i < coordFile.files.size(); i++) {
      if (coordFile.files[i].selected) {
         if (updateFileReadProgressDialog(coordFile.files[i].filename, progressFileCounter, progressDialog)) {
            return true;
         }
         try {
            readCoordinateFile(coordFile.files[i].filename, surfaceType, true, true, true);
         }
         catch (FileException& e) {
            errorMessages.push_back(e.whatQString());
         }
      }
   }
   
   return false;
}

/**
 * Read some border files.  Returns true if file reading was aborted.
 */
bool
07354 BrainSet::readBorderFiles(const SpecFile::Entry& borderFilesToRead,
                              const BrainModelSurface::SURFACE_TYPES bt,
                              std::vector<QString>& errorMessages,
                              int& progressFileCounter,
                              QProgressDialog* progressDialog)
{
   for (unsigned i = 0; i < borderFilesToRead.files.size(); i++) {
      if (borderFilesToRead.files[i].selected) {
         if (updateFileReadProgressDialog(borderFilesToRead.files[i].filename, progressFileCounter, progressDialog)) {
            return true;
         }
         try {
            readBorderFile(borderFilesToRead.files[i].filename, bt, true, true);
         }
         catch (FileException& e) {
            errorMessages.push_back(e.whatQString());
         }
      }
   }
   
   return false;
}

/**
 * read the spec file (returns true if reading was aborted by user).
 */
bool 
07381 BrainSet::readSpecFile(const SpecFile& specFileIn, 
                       const QString& specFileNameIn,
                       QString& errorMessagesOut)
{
   return readSpecFile(SPEC_FILE_READ_MODE_NORMAL,
                       specFileIn,
                       specFileNameIn,
                       errorMessagesOut,
                       NULL,
                       NULL);
}

/**
 * Read the BrainSet data files.  Any error message will be placed
 * into "errorMessageOut".  If "errorMessageOut" is empty, then there
 * were no errors reading the spec file's data files.
 *
 * Returns "true" if the user aborted loading files with the progress dialog.
 */
bool
07401 BrainSet::readSpecFile(const SPEC_FILE_READ_MODE specReadMode,
                       const SpecFile& specFileIn,
                       const QString& specFileNameIn,
                       QString& errorMessageOut,
                       const TransformationMatrix* specTransformationMatrixIn,
                       QProgressDialog* progressDialog)
{
   errorMessageOut = "";
   std::vector<QString> msg;
   const bool b = readSpecFile(specReadMode,
                               specFileIn,
                               specFileNameIn,
                               msg,
                               specTransformationMatrixIn,
                               progressDialog);
   if (msg.empty() == false) {
      errorMessageOut = StringUtilities::combine(msg, "\n");
   }
   return b;
}

/**
 * Read the BrainSet data files.  Any error message will be placed
 * into "errorMessages".  The size of errorMessages will correspond to
 * the number files that failed to read correctly.  If the size of 
 * errorMessages is 0, no file reading errors were encountered.
 *
 * Returns "true" if the user aborted loading files with the progress dialog.
 */
bool
07431 BrainSet::readSpecFile(const SPEC_FILE_READ_MODE specReadMode,
                       const SpecFile& specFileIn,
                       const QString& specFileNameIn,
                       std::vector<QString>& errorMessages,
                       const TransformationMatrix* specTransformationMatrixIn,
                       QProgressDialog* progressDialog)
{
   if (getPreferencesFile()->getNumberOfFileReadingThreads() > 1) {
      return readSpecFileMultiThreaded(specReadMode,
                                specFileIn,
                                specFileNameIn,
                                errorMessages,
                                specTransformationMatrixIn,
                                progressDialog);
   }
   
   specFileTimeOfLoading = QDateTime::currentDateTime();

   readingSpecFileFlag = true;
   
   switch (specReadMode) {
      case SPEC_FILE_READ_MODE_NORMAL:
         //
         // clear out "this" brain set
         //
         reset();
         break;
      case SPEC_FILE_READ_MODE_APPEND:
         break;
   }
   
   if (specTransformationMatrixIn != NULL) {
      specDataFileTransformationMatrix = *specTransformationMatrixIn;
   }
   
   errorMessages.clear();

   int progressFileCounter = 0;
   
   switch (specReadMode) {
      case SPEC_FILE_READ_MODE_NORMAL:
         //
         // Copy spec file passed and clear all selections in BrainSet::specFile
         //
         loadedFilesSpecFile = specFileIn;
         loadedFilesSpecFile.setAllFileSelections(SpecFile::SPEC_FALSE);
         //loadedFilesSpecFile.setFileName(specFileNameIn);
         loadedFilesSpecFile.setCurrentDirectoryToSpecFileDirectory();
         
         specFileName = specFileNameIn;
         
         structure = specFileIn.getStructure();
/*
         hemisphere = Hemisphere::HEMISPHERE_UNKNOWN;
         if (specFileIn.getStructure() == "right") {
            hemisphere = BrainModelSurface::HEMISPHERE_RIGHT;
         }
         else if (specFileIn.getStructure() == "left") {
            hemisphere = BrainModelSurface::HEMISPHERE_LEFT;
         }
         else if (specFileIn.getStructure() == "both") {
            hemisphere = BrainModelSurface::HEMISPHERE_BOTH;
         }
         setStructure(hemisphere);
*/
         setSpecies(loadedFilesSpecFile.getSpecies());
         setSubject(loadedFilesSpecFile.getSubject());
         stereotaxicSpace = loadedFilesSpecFile.getSpace();
         resetDataFiles(false, false);
         break;
      case SPEC_FILE_READ_MODE_APPEND:
         break;
   }
   
   const int numTopoFilesBeforeLoading = getNumberOfTopologyFiles();
   
   //
   // Note about reading topology files.  "readTopologyFile()" always places the newest topology
   // file at the beginning of its storage in "topologyFiles".  So, when we read the topology
   // files from the spec file, read them starting with the oldest unknown to the newest 
   // closed topology file (the spec file sorts each file type by date). 
   //
   //
   // Read the unknown topology files
   //
   for (int j = (specFileIn.unknownTopoFile.files.size() - 1); j >= 0; j--) {
      if (specFileIn.unknownTopoFile.files[j].selected) {
         if (updateFileReadProgressDialog(specFileIn.unknownTopoFile.files[j].filename, 
                                          progressFileCounter, progressDialog)) {
            return true;
         }
         
         try {
            readTopologyFile(specFileIn.unknownTopoFile.files[j].filename, TopologyFile::TOPOLOGY_TYPE_UNKNOWN, true, true);
         }
         catch (FileException& e) {
            errorMessages.push_back(e.whatQString());
         }
      }
   }
   
   //
   // Read the lobar cut topology files
   //
   for (int j = (specFileIn.lobarCutTopoFile.files.size() - 1); j >= 0; j--) {
      if (specFileIn.lobarCutTopoFile.files[j].selected) {
         if (updateFileReadProgressDialog(specFileIn.lobarCutTopoFile.files[j].filename, 
                                          progressFileCounter, progressDialog)) {
            return true;
         }
         
         try {
            readTopologyFile(specFileIn.lobarCutTopoFile.files[j].filename, TopologyFile::TOPOLOGY_TYPE_LOBAR_CUT, true, true);
         }
         catch (FileException& e) {
            errorMessages.push_back(e.whatQString());
         }
      }
   }
   
   //
   // Read the cut topology files
   //
   for (int j = (specFileIn.cutTopoFile.files.size() - 1); j >= 0; j--) {
      if (specFileIn.cutTopoFile.files[j].selected) {
         if (updateFileReadProgressDialog(specFileIn.cutTopoFile.files[j].filename, 
                                          progressFileCounter, progressDialog)) {
            return true;
         }
         
         try {
            readTopologyFile(specFileIn.cutTopoFile.files[j].filename, TopologyFile::TOPOLOGY_TYPE_CUT, true, true);
         }
         catch (FileException& e) {
            errorMessages.push_back(e.whatQString());
         }
      }
   }
   
   //
   // Read the open topology files
   //
   for (int j = (specFileIn.openTopoFile.files.size() - 1); j >= 0; j--) {
      if (specFileIn.openTopoFile.files[j].selected) {
         if (updateFileReadProgressDialog(specFileIn.openTopoFile.files[j].filename, 
                                          progressFileCounter, progressDialog)) {
            return true;
         }
         
         try {
            readTopologyFile(specFileIn.openTopoFile.files[j].filename, TopologyFile::TOPOLOGY_TYPE_OPEN, true, true);
         }
         catch (FileException& e) {
            errorMessages.push_back(e.whatQString());
         }
      }
   }
   
   //
   // Read the closed topology files
   //
   for (int j = (specFileIn.closedTopoFile.files.size() - 1); j >= 0; j--) {
      if (specFileIn.closedTopoFile.files[j].selected) {
         if (updateFileReadProgressDialog(specFileIn.closedTopoFile.files[j].filename, 
                                          progressFileCounter, progressDialog)) {
            return true;
         }
         
         try {
            readTopologyFile(specFileIn.closedTopoFile.files[j].filename, TopologyFile::TOPOLOGY_TYPE_CLOSED, true, true);
         }
         catch (FileException& e) {
            errorMessages.push_back(e.whatQString());
         }
      }
   }
   
   setSelectedTopologyFiles();
   
   //
   // Read in the raw coordinate files
   //
   if (readCoordinateFileGroup(specFileIn.rawCoordFile,
                    BrainModelSurface::SURFACE_TYPE_RAW,
                    errorMessages,
                    progressFileCounter,
                    progressDialog)) return true;

   //
   // Read in the fiducial coordinate files
   //
   if (readCoordinateFileGroup(specFileIn.fiducialCoordFile,
                    BrainModelSurface::SURFACE_TYPE_FIDUCIAL,
                    errorMessages,
                    progressFileCounter,
                    progressDialog)) return true;

   //
   // Read in the inflated coordinate files
   //
   if (readCoordinateFileGroup(specFileIn.inflatedCoordFile,
                    BrainModelSurface::SURFACE_TYPE_INFLATED,
                    errorMessages,
                    progressFileCounter,
                    progressDialog)) return true;

   //
   // Read in the very inflated coordinate files
   //
   if (readCoordinateFileGroup(specFileIn.veryInflatedCoordFile,
                    BrainModelSurface::SURFACE_TYPE_VERY_INFLATED,
                    errorMessages,
                    progressFileCounter,
                    progressDialog)) return true;
   
   //
   // Read in the spherical coordinate files
   //
   if (readCoordinateFileGroup(specFileIn.sphericalCoordFile,
                    BrainModelSurface::SURFACE_TYPE_SPHERICAL,
                    errorMessages,
                    progressFileCounter,
                    progressDialog)) return true;
   
   //
   // Read in the ellipsoid coordinate files
   //
   if (readCoordinateFileGroup(specFileIn.ellipsoidCoordFile,
                    BrainModelSurface::SURFACE_TYPE_ELLIPSOIDAL,
                    errorMessages,
                    progressFileCounter,
                    progressDialog)) return true;

   //
   // Read in the compressed medial wall coordinate files
   //
   if (readCoordinateFileGroup(specFileIn.compressedCoordFile,
                    BrainModelSurface::SURFACE_TYPE_COMPRESSED_MEDIAL_WALL,
                    errorMessages,
                    progressFileCounter,
                    progressDialog)) return true;

   //
   //
   // Read in the flat coordinate files
   //
   if (readCoordinateFileGroup(specFileIn.flatCoordFile,
                    BrainModelSurface::SURFACE_TYPE_FLAT,
                    errorMessages,
                    progressFileCounter,
                    progressDialog)) return true;

   //
   // Read in the lobar flat coordinate files
   //
   if (readCoordinateFileGroup(specFileIn.lobarFlatCoordFile,
                    BrainModelSurface::SURFACE_TYPE_FLAT_LOBAR,
                    errorMessages,
                    progressFileCounter,
                    progressDialog)) return true;

   //
   // Read in the hull coordinate files
   //
   if (readCoordinateFileGroup(specFileIn.hullCoordFile,
                    BrainModelSurface::SURFACE_TYPE_HULL,
                    errorMessages,
                    progressFileCounter,
                    progressDialog)) return true;

   //
   // Read in the unknown coordinate files
   //
   if (readCoordinateFileGroup(specFileIn.unknownCoordFile,
                    BrainModelSurface::SURFACE_TYPE_UNKNOWN,
                    errorMessages,
                    progressFileCounter,
                    progressDialog)) return true;
        
   //
   // Read in the raw coordinate files
   //
   if (readSurfaceFileGroup(specFileIn.rawSurfaceFile,
                    BrainModelSurface::SURFACE_TYPE_RAW,
                    errorMessages,
                    progressFileCounter,
                    progressDialog)) return true;

   //
   // Read in the fiducial coordinate files
   //
   if (readSurfaceFileGroup(specFileIn.fiducialSurfaceFile,
                    BrainModelSurface::SURFACE_TYPE_FIDUCIAL,
                    errorMessages,
                    progressFileCounter,
                    progressDialog)) return true;

   //
   // Read in the inflated coordinate files
   //
   if (readSurfaceFileGroup(specFileIn.inflatedSurfaceFile,
                    BrainModelSurface::SURFACE_TYPE_INFLATED,
                    errorMessages,
                    progressFileCounter,
                    progressDialog)) return true;

   //
   // Read in the very inflated coordinate files
   //
   if (readSurfaceFileGroup(specFileIn.veryInflatedSurfaceFile,
                    BrainModelSurface::SURFACE_TYPE_VERY_INFLATED,
                    errorMessages,
                    progressFileCounter,
                    progressDialog)) return true;
   
   //
   // Read in the spherical coordinate files
   //
   if (readSurfaceFileGroup(specFileIn.sphericalSurfaceFile,
                    BrainModelSurface::SURFACE_TYPE_SPHERICAL,
                    errorMessages,
                    progressFileCounter,
                    progressDialog)) return true;
   
   //
   // Read in the ellipsoid coordinate files
   //
   if (readSurfaceFileGroup(specFileIn.ellipsoidSurfaceFile,
                    BrainModelSurface::SURFACE_TYPE_ELLIPSOIDAL,
                    errorMessages,
                    progressFileCounter,
                    progressDialog)) return true;

   //
   // Read in the compressed medial wall coordinate files
   //
   if (readSurfaceFileGroup(specFileIn.compressedSurfaceFile,
                    BrainModelSurface::SURFACE_TYPE_COMPRESSED_MEDIAL_WALL,
                    errorMessages,
                    progressFileCounter,
                    progressDialog)) return true;

   //
   //
   // Read in the flat coordinate files
   //
   if (readSurfaceFileGroup(specFileIn.flatSurfaceFile,
                    BrainModelSurface::SURFACE_TYPE_FLAT,
                    errorMessages,
                    progressFileCounter,
                    progressDialog)) return true;

   //
   // Read in the lobar flat coordinate files
   //
   if (readSurfaceFileGroup(specFileIn.lobarFlatSurfaceFile,
                    BrainModelSurface::SURFACE_TYPE_FLAT_LOBAR,
                    errorMessages,
                    progressFileCounter,
                    progressDialog)) return true;

   //
   // Read in the hull coordinate files
   //
   if (readSurfaceFileGroup(specFileIn.hullSurfaceFile,
                    BrainModelSurface::SURFACE_TYPE_HULL,
                    errorMessages,
                    progressFileCounter,
                    progressDialog)) return true;

   //
   // Read in the unknown coordinate files
   //
   if (readSurfaceFileGroup(specFileIn.unknownSurfaceFile,
                    BrainModelSurface::SURFACE_TYPE_UNKNOWN,
                    errorMessages,
                    progressFileCounter,
                    progressDialog)) return true;

   //
   // Read in the area color file
   // 
   for (unsigned int i = 0; i < specFileIn.areaColorFile.files.size(); i++) {
      if (specFileIn.areaColorFile.files[i].selected) {
         if (updateFileReadProgressDialog(specFileIn.areaColorFile.files[i].filename, 
                                          progressFileCounter, progressDialog)) {
            return true;
         }
         try {
            readAreaColorFile(specFileIn.areaColorFile.files[i].filename, true, true);
         }
         catch (FileException& e) {
            errorMessages.push_back(e.whatQString());
         }
      }
   }

   //
   // Read in the anatomy volume files
   //
   for (unsigned int i = 0; i < specFileIn.volumeAnatomyFile.files.size(); i++) {
      if (specFileIn.volumeAnatomyFile.files[i].selected) {
         if (updateFileReadProgressDialog(specFileIn.volumeAnatomyFile.files[i].filename,
                                          progressFileCounter, progressDialog)) {
            return true;
         }
         try {
            readVolumeFile(specFileIn.volumeAnatomyFile.files[i].filename, VolumeFile::VOLUME_TYPE_ANATOMY, true, true);
         }
         catch (FileException& e) {
            errorMessages.push_back(e.whatQString());
         }
      }
   }
   
   //
   // Read in the functional volume files
   //
   for (unsigned int i = 0; i < specFileIn.volumeFunctionalFile.files.size(); i++) {
      if (specFileIn.volumeFunctionalFile.files[i].selected) {
         if (updateFileReadProgressDialog(specFileIn.volumeFunctionalFile.files[i].filename,
                                          progressFileCounter, progressDialog)) {
            return true;
         }
         try {
            readVolumeFile(specFileIn.volumeFunctionalFile.files[i].filename, VolumeFile::VOLUME_TYPE_FUNCTIONAL, true, true);
         }
         catch (FileException& e) {
            errorMessages.push_back(e.whatQString());
         }
      }
   }
   
   //
   // Read in the paint volume files
   //
   for (unsigned int i = 0; i < specFileIn.volumePaintFile.files.size(); i++) {
      if (specFileIn.volumePaintFile.files[i].selected) {
         if (updateFileReadProgressDialog(specFileIn.volumePaintFile.files[i].filename,
                                          progressFileCounter, progressDialog)) {
            return true;
         }
         try {
            readVolumeFile(specFileIn.volumePaintFile.files[i].filename, VolumeFile::VOLUME_TYPE_PAINT, true, true);
         }
         catch (FileException& e) {
            errorMessages.push_back(e.whatQString());
         }
      }
   }
   
   //
   // Read in the prob atlas volume files
   //
   for (unsigned int i = 0; i < specFileIn.volumeProbAtlasFile.files.size(); i++) {
      if (specFileIn.volumeProbAtlasFile.files[i].selected) {
         if (updateFileReadProgressDialog(specFileIn.volumeProbAtlasFile.files[i].filename,
                                          progressFileCounter, progressDialog)) {
            return true;
         }
         try {
            readVolumeFile(specFileIn.volumeProbAtlasFile.files[i].filename, VolumeFile::VOLUME_TYPE_PROB_ATLAS, true, true);
         }
         catch (FileException& e) {
            errorMessages.push_back(e.whatQString());
         }
      }
   }
   if (specFileIn.volumeProbAtlasFile.files.size() > 1) {
      synchronizeProbAtlasVolumeRegionNames();
   }
   
   //
   // Read in the rgb paint volume files
   //
   for (unsigned int i = 0; i < specFileIn.volumeRgbFile.files.size(); i++) {
      if (specFileIn.volumeRgbFile.files[i].selected) {
         if (updateFileReadProgressDialog(specFileIn.volumeRgbFile.files[i].filename,
                                          progressFileCounter, progressDialog)) {
            return true;
         }
         try {
            readVolumeFile(specFileIn.volumeRgbFile.files[i].filename, VolumeFile::VOLUME_TYPE_RGB, true, true);
         }
         catch (FileException& e) {
            errorMessages.push_back(e.whatQString());
         }
      }
   }
   
   //
   // Read in the segmentation volume files
   //
   for (unsigned int i = 0; i < specFileIn.volumeSegmentationFile.files.size(); i++) {
      if (specFileIn.volumeSegmentationFile.files[i].selected) {
         if (updateFileReadProgressDialog(specFileIn.volumeSegmentationFile.files[i].filename,
                                          progressFileCounter, progressDialog)) {
            return true;
         }
         try {
            readVolumeFile(specFileIn.volumeSegmentationFile.files[i].filename, VolumeFile::VOLUME_TYPE_SEGMENTATION, true, true);
         }
         catch (FileException& e) {
            errorMessages.push_back(e.whatQString());
         }
      }
   }
   
   //
   // Read in the vector volume files
   //
   for (unsigned int i = 0; i < specFileIn.volumeVectorFile.files.size(); i++) {
      if (specFileIn.volumeVectorFile.files[i].selected) {
         if (updateFileReadProgressDialog(specFileIn.volumeVectorFile.files[i].filename,
                                          progressFileCounter, progressDialog)) {
            return true;
         }
         try {
            readVolumeFile(specFileIn.volumeVectorFile.files[i].filename, VolumeFile::VOLUME_TYPE_VECTOR, true, true);
         }
         catch (FileException& e) {
            errorMessages.push_back(e.whatQString());
         }
      }
   }
   
   //
   // Read in the paint files
   // 
   for (unsigned int i = 0; i < specFileIn.paintFile.files.size(); i++) {
      if (specFileIn.paintFile.files[i].selected) {
         if (updateFileReadProgressDialog(specFileIn.paintFile.files[i].filename, 
                                          progressFileCounter, progressDialog)) {
            return true;
         }
         try {
            readPaintFile(specFileIn.paintFile.files[i].filename, true, true);
         }
         catch (FileException& e) {
            errorMessages.push_back(e.whatQString());
         }
      }
   }
   
   //
   // Read in the probabilistic atlas files
   // 
   for (unsigned int i = 0; i < specFileIn.atlasFile.files.size(); i++) {
      if (specFileIn.atlasFile.files[i].selected) {
         if (updateFileReadProgressDialog(specFileIn.atlasFile.files[i].filename, 
                                          progressFileCounter, progressDialog)) {
            return true;
         }
         try {
            readProbabilisticAtlasFile(specFileIn.atlasFile.files[i].filename, true, true);
         }
         catch (FileException& e) {
            errorMessages.push_back(e.whatQString());
         }
      }
   }
   
   //
   // Read the rgb paint files
   //
   for (unsigned int i = 0; i < specFileIn.rgbPaintFile.files.size(); i++) {
      if (specFileIn.rgbPaintFile.files[i].selected) {
         if (updateFileReadProgressDialog(specFileIn.rgbPaintFile.files[i].filename, 
                                          progressFileCounter, progressDialog)) {
            return true;
         }
         try {
            readRgbPaintFile(specFileIn.rgbPaintFile.files[i].filename, true, true);
         }
         catch (FileException& e) {
            errorMessages.push_back(e.whatQString());
         }
      }
   }

   //
   // Read the study collection files
   //
   for (unsigned int i = 0; i < specFileIn.studyCollectionFile.files.size(); i++) {
      if (specFileIn.studyCollectionFile.files[i].selected) {
         if (updateFileReadProgressDialog(specFileIn.studyCollectionFile.files[i].filename, 
                                          progressFileCounter, progressDialog)) {
            return true;
         }
         try {
            readStudyCollectionFile(specFileIn.studyCollectionFile.files[i].filename, true, true);
         }
         catch (FileException& e) {
            errorMessages.push_back(e.whatQString());
         }
      }
   }
   
   //
   // Read the study meta data files
   //
   for (unsigned int i = 0; i < specFileIn.studyMetaDataFile.files.size(); i++) {
      if (specFileIn.studyMetaDataFile.files[i].selected) {
         if (updateFileReadProgressDialog(specFileIn.studyMetaDataFile.files[i].filename, 
                                          progressFileCounter, progressDialog)) {
            return true;
         }
         try {
            readStudyMetaDataFile(specFileIn.studyMetaDataFile.files[i].filename, true, true);
         }
         catch (FileException& e) {
            errorMessages.push_back(e.whatQString());
         }
      }
   }
   
   //
   // Read the vocabulary files
   //
   for (unsigned int i = 0; i < specFileIn.vocabularyFile.files.size(); i++) {
      if (specFileIn.vocabularyFile.files[i].selected) {
         if (updateFileReadProgressDialog(specFileIn.vocabularyFile.files[i].filename, 
                                          progressFileCounter, progressDialog)) {
            return true;
         }
         try {
            readVocabularyFile(specFileIn.vocabularyFile.files[i].filename, true, true);
         }
         catch (FileException& e) {
            errorMessages.push_back(e.whatQString());
         }
      }
   }
   
   //
   // Read the wustl region files
   //
   for (unsigned int i = 0; i < specFileIn.wustlRegionFile.files.size(); i++) {
      if (specFileIn.wustlRegionFile.files[i].selected) {
         if (updateFileReadProgressDialog(specFileIn.wustlRegionFile.files[i].filename, 
                                          progressFileCounter, progressDialog)) {
            return true;
         }
         try {
            readWustlRegionFile(specFileIn.wustlRegionFile.files[i].filename, true, true);
         }
         catch (FileException& e) {
            errorMessages.push_back(e.whatQString());
         }
      }
   }
   
   //
   // Read the areal estimation files
   //
   for (unsigned int i = 0; i < specFileIn.arealEstimationFile.files.size(); i++) {
      if (specFileIn.arealEstimationFile.files[i].selected) {
         if (updateFileReadProgressDialog(specFileIn.arealEstimationFile.files[i].filename, 
                                          progressFileCounter, progressDialog)) {
            return true;
         }
         try {
            readArealEstimationFile(specFileIn.arealEstimationFile.files[i].filename, true, true);
         }
         catch (FileException& e) {
            errorMessages.push_back(e.whatQString());
         }
      }
   }
   
   //
   // Read the topography files
   //
   for (unsigned int i = 0; i < specFileIn.topographyFile.files.size(); i++) {
      if (specFileIn.topographyFile.files[i].selected) {
         if (updateFileReadProgressDialog(specFileIn.topographyFile.files[i].filename, 
                                          progressFileCounter, progressDialog)) {
            return true;
         }
         try {
            readTopographyFile(specFileIn.topographyFile.files[i].filename, true, true);
         }
         catch (FileException& e) {
            errorMessages.push_back(e.whatQString());
         }
      }
   }

   //
   // Read the geodesic files
   //
   for (unsigned int i = 0; i < specFileIn.geodesicDistanceFile.files.size(); i++) {
      if (specFileIn.geodesicDistanceFile.files[i].selected) {
         if (updateFileReadProgressDialog(specFileIn.geodesicDistanceFile.files[i].filename, 
                                          progressFileCounter, progressDialog)) {
            return true;
         }
         try {
            readGeodesicDistanceFile(specFileIn.geodesicDistanceFile.files[i].filename, true, true);
         }
         catch (FileException& e) {
            errorMessages.push_back(e.whatQString());
         }
      }
   }
   
   
   //
   // Read the lat/lon files
   //
   for (unsigned int i = 0; i < specFileIn.latLonFile.files.size(); i++) {
      if (specFileIn.latLonFile.files[i].selected) {
         if (updateFileReadProgressDialog(specFileIn.latLonFile.files[i].filename, 
                                          progressFileCounter, progressDialog)) {
            return true;
         }
         try {
            readLatLonFile(specFileIn.latLonFile.files[i].filename, true, true);
         }
         catch (FileException& e) {
            errorMessages.push_back(e.whatQString());
         }
      }
   }
   
   //
   // Read the params files
   //
   for (unsigned int i = 0; i < specFileIn.paramsFile.files.size(); i++) {
      if (specFileIn.paramsFile.files[i].selected) {
         if (updateFileReadProgressDialog(specFileIn.paramsFile.files[i].filename, 
                                          progressFileCounter, progressDialog)) {
            return true;
         }
         try {
            readParamsFile(specFileIn.paramsFile.files[i].filename, true, true);
         }
         catch (FileException& e) {
            errorMessages.push_back(e.whatQString());
         }
      }
   }
   
   //
   // Read the scene files
   //
   for (unsigned int i = 0; i < specFileIn.sceneFile.files.size(); i++) {
      if (specFileIn.sceneFile.files[i].selected) {
         if (updateFileReadProgressDialog(specFileIn.sceneFile.files[i].filename, 
                                          progressFileCounter, progressDialog)) {
            return true;
         }
         try {
            readSceneFile(specF