void
SegmentationVolumeReportTester::Test ( Tcl_Interp* iInterp ) {

  try {


    // Load our seg volume.
    string fnSegVolume = "test_data/testSegmentationVolumeReportData-Seg.mgz";
    VolumeCollection seg;
    seg.SetFileName( fnSegVolume );
    seg.LoadVolume();
    seg.SetLabel( "Seg" );

    // Load our intensity volume.
    string fnIntVolume = "test_data/testSegmentationVolumeReportData-Int.mgz";
    VolumeCollection vol;
    vol.SetFileName( fnIntVolume );
    vol.LoadVolume();
    vol.SetLabel( "Int" );


    // Load our LUT.
    string fnLUT = "test_data/TestLUT.txt";
    ScubaColorLUT lut;
    lut.UseFile( fnLUT );

    // Set up the report.
    SegmentationVolumeReport& report =
      SegmentationVolumeReport::GetReport();

    report.SetSegmentation( seg );
    if ( NULL == report.mSegVol ) {
      stringstream ssError;
      ssError << "Error on SetSegmentation, mSegVol was NULL";
      throw runtime_error( ssError.str() );
    }
    if ( report.mSegVol->GetID() != seg.GetID() ) {
      stringstream ssError;
      ssError << "Error on SetSegmentation, mSegVol was the wrong volume (should be ID " << seg.GetID() << " but was " << report.mSegVol->GetID();
      throw runtime_error( ssError.str() );
    }

    report.DontUseROI();
    if ( report.mbUseROI ) {
      stringstream ssError;
      ssError << "Error on DontUseROI, mbUseROI was true";
      throw runtime_error( ssError.str() );
    }


    report.SetColorLUT( lut );
    if ( NULL == report.mLUT ) {
      stringstream ssError;
      ssError << "Error on SetColorLUT, mROI was NULL";
      throw runtime_error( ssError.str() );
    }
    if ( report.mLUT->GetID() != lut.GetID() ) {
      stringstream ssError;
      ssError << "Error on SetColorLUT, id didn't match";
      throw runtime_error( ssError.str() );
    }

    // Add 1-5 but not 3.
    report.AddSegmentationStructure( 1 );
    report.AddSegmentationStructure( 2 );
    report.AddSegmentationStructure( 4 );
    report.AddSegmentationStructure( 5 );
    map<int,bool> structureMap;
    list<int>::iterator tStructure;
    for ( tStructure = report.mlStructures.begin();
          tStructure != report.mlStructures.end(); ++tStructure ) {
      int nStructure = *tStructure;
      if ( nStructure != 1 && nStructure != 2 &&
           nStructure != 4 && nStructure != 5 ) {
        stringstream ssError;
        ssError << "Error on AddSegmentationStructure, added an unknown structure " << nStructure;
        throw runtime_error( ssError.str() );
      }
      structureMap[nStructure] = true;
    }
    if ( !(structureMap[1] && structureMap[2] &&
           structureMap[4] && structureMap[5]) ) {
      stringstream ssError;
      ssError << "Error in AddSegmentationStructure, didn't add all structures";
      throw runtime_error( ssError.str() );
    }

    // Test handling of undefined structures.
    report.AddSegmentationStructure( 200 );

    // Add the intensity volume. Also add the seg vol as an additional
    // intensity volume.
    report.AddIntensityVolume( vol );
    report.AddIntensityVolume( seg );
    map<int,bool> volsLoadedMap;
    list<VolumeCollection*>::iterator tVolume;
    for ( tVolume = report.mlIntVols.begin();
          tVolume != report.mlIntVols.end(); ++tVolume ) {
      VolumeCollection* testVol = *tVolume;
      int volID = testVol->GetID();
      if ( volID != vol.GetID() && volID != seg.GetID() ) {
        stringstream ssError;
        ssError << "Error in AddIntensityVolume, added a volume with an unknown id " << volID;
        throw runtime_error( ssError.str() );
      }
      volsLoadedMap[volID] = true;
    }
    if ( !(volsLoadedMap[vol.GetID()] && volsLoadedMap[seg.GetID()]) ) {
      stringstream ssError;
      ssError << "Error in AddIntensityVolume, didn't add both volumes";
      throw runtime_error( ssError.str() );
    }

    report.MakeVolumeReport();


    for ( int nStructure = 1; nStructure <= 5; nStructure++ ) {

      // Check the number of voxels we got.
      float expectedSize;
      if ( nStructure == 3 ) {
        expectedSize = 0;
      } else {
        expectedSize = 25 * 25;
      }
      if ( report.mStructureToVolumeMap[nStructure] != expectedSize ) {
        stringstream ssError;
        ssError << "Error on report for seg " << nStructure
        << ": expectedSize was " << expectedSize << ", but got "
        << report.mStructureToVolumeMap[nStructure];
        throw runtime_error( ssError.str() );
      }

      // Check the intensity values (for the vol, should be 2x the
      // segmentation index, and for the seg, should be ==).
      float expectedIntensityAverage;
      if ( nStructure == 3 ) {
        expectedIntensityAverage = 0;
      } else {
        expectedIntensityAverage = nStructure * 2.0;
      }
      if ( report.mVolumeToIntensityAverageMap[&vol][nStructure] !=
           expectedIntensityAverage ) {
        stringstream ssError;
        ssError << "Error on report for seg " << nStructure
        << ": expectedIntensityAverage for intensity vol " << &vol
        << " was " << expectedIntensityAverage << ", but got "
        << report.mVolumeToIntensityAverageMap[&vol][nStructure];
        throw runtime_error( ssError.str() );
      }

      if ( nStructure == 3 ) {
        expectedIntensityAverage = 0;
      } else {
        expectedIntensityAverage = nStructure;
      }
      if ( report.mVolumeToIntensityAverageMap[&seg][nStructure] !=
           expectedIntensityAverage ) {
        stringstream ssError;
        ssError << "Error on report for seg " << nStructure
        << ": expectedIntensityAverage for seg vol " << &seg
        << " was " << expectedIntensityAverage << ", but got "
        << report.mVolumeToIntensityAverageMap[&seg][nStructure];
        throw runtime_error( ssError.str() );
      }
    }

    // Make the report.
    report.MakeVolumeReport( "/tmp/testReport.txt" );

    // Compare it with the correct one.
    int rDiff =
      system( "diff /tmp/testReport.txt testSegmentationVolumeReport-correct.txt" );
    if ( rDiff != 0 ) {
      throw runtime_error( "diff failed on testReport" );
    }

    // Make the report.
    report.MakeIntensityReport( "/tmp/testIntReport.txt" );

    // Compare it with the correct one.
    rDiff =
      system( "diff /tmp/testIntReport.txt testSegmentationVolumeReportIntReport-correct.txt" );
    if ( rDiff != 0 ) {
      throw runtime_error( "diff failed on testIntReport" );
    }

    // Test the tcl functions now. Just call them all and check the
    // results. Need to clear the report first.
    report.Clear();
    if ( NULL != report.mSegVol ||
         report.mlIntVols.size() != 0 ||
         report.mbUseROI ||
         NULL != report.mROIVol ||
         NULL != report.mROI ||
         NULL != report.mLUT ||
         report.mlStructures.size() != 0 ||
         !report.mbReportDirty ||
         report.mVolumeToIntensityAverageMap.size() != 0 ||
         report.mStructureToVolumeVoxelListMap.size() != 0 ) {
      stringstream ssError;
      ssError << "Error on Clear: not cleared";
      throw runtime_error( ssError.str() );
    }

    char sCommand[1024];
    int rTcl;

    sprintf( sCommand, "SetSegVolReportSegmentation %d", seg.GetID() );
    rTcl = Tcl_Eval( iInterp, sCommand );
    AssertTclOK( rTcl );

    if ( NULL == report.mSegVol ) {
      stringstream ssError;
      ssError << "Error on Tcl SetSegVolReportSegmentation, mSegVol was NULL";
      throw runtime_error( ssError.str() );
    }
    if ( report.mSegVol->GetID() != seg.GetID() ) {
      stringstream ssError;
      ssError << "Error on Tcl SetSegVolReportSegmentation, mSegVol was the wrong volume (should be ID " << seg.GetID() << " but was " << report.mSegVol->GetID();
      throw runtime_error( ssError.str() );
    }

    sprintf( sCommand, "AddSegVolReportIntensityVolume %d", vol.GetID() );
    rTcl = Tcl_Eval( iInterp, sCommand );
    AssertTclOK( rTcl );

    sprintf( sCommand, "AddSegVolReportIntensityVolume %d", seg.GetID() );
    rTcl = Tcl_Eval( iInterp, sCommand );
    AssertTclOK( rTcl );

    volsLoadedMap.clear();
    for ( tVolume = report.mlIntVols.begin();
          tVolume != report.mlIntVols.end(); ++tVolume ) {
      VolumeCollection* testVol = *tVolume;
      int volID = testVol->GetID();
      if ( volID != vol.GetID() && volID != seg.GetID() ) {
        stringstream ssError;
        ssError << "Error in Tcl AddSegVolReportIntensityVolume, added a volume with an unknown id " << volID;
        throw runtime_error( ssError.str() );
      }
      volsLoadedMap[volID] = true;
    }
    if ( !(volsLoadedMap[vol.GetID()] && volsLoadedMap[seg.GetID()]) ) {
      stringstream ssError;
      ssError << "Error in Tcl AddSegVolReportIntensityVolume, didn't add both volumes";
      throw runtime_error( ssError.str() );
    }

    sprintf( sCommand, "AddSegmentationToSegVolReport 1" );
    rTcl = Tcl_Eval( iInterp, sCommand );
    AssertTclOK( rTcl );
    sprintf( sCommand, "AddSegmentationToSegVolReport 2" );
    rTcl = Tcl_Eval( iInterp, sCommand );
    AssertTclOK( rTcl );
    sprintf( sCommand, "AddSegmentationToSegVolReport 4" );
    rTcl = Tcl_Eval( iInterp, sCommand );
    AssertTclOK( rTcl );
    sprintf( sCommand, "AddSegmentationToSegVolReport 5" );
    rTcl = Tcl_Eval( iInterp, sCommand );
    AssertTclOK( rTcl );
    structureMap.clear();
    for ( tStructure = report.mlStructures.begin();
          tStructure != report.mlStructures.end(); ++tStructure ) {
      int nStructure = *tStructure;
      if ( nStructure != 1 && nStructure != 2 &&
           nStructure != 4 && nStructure != 5 ) {
        stringstream ssError;
        ssError << "Error on Tcl AddSegmentationToSegVolReport, added an unknown structure " << nStructure;
        throw runtime_error( ssError.str() );
      }
      structureMap[nStructure] = true;
    }
    if ( !(structureMap[1] && structureMap[2] &&
           structureMap[4] && structureMap[5]) ) {
      stringstream ssError;
      ssError << "Error in Tcl AddSegmentationToSegVolReport, didn't add all structures";
      throw runtime_error( ssError.str() );
    }

    report.AddSegmentationStructure( 200 );

    sprintf( sCommand, "SetSegVolReportLUT %d", lut.GetID() );
    rTcl = Tcl_Eval( iInterp, sCommand );
    AssertTclOK( rTcl );
    if ( NULL == report.mLUT ) {
      stringstream ssError;
      ssError << "Error on Tcl SetSegVolReportLUT, mLUT was NULL";
      throw runtime_error( ssError.str() );
    }
    if ( report.mLUT->GetID() != lut.GetID() ) {
      stringstream ssError;
      ssError << "Error on Tcl SetSegVolReportLUT, id didn't match";
      throw runtime_error( ssError.str() );
    }

    sprintf( sCommand, "MakeSegVolReport /tmp/testReport2.txt" );
    rTcl = Tcl_Eval( iInterp, sCommand );
    AssertTclOK( rTcl );
    rDiff =
      system( "diff /tmp/testReport2.txt testSegmentationVolumeReport-correct.txt" );
    if ( rDiff != 0 ) {
      throw runtime_error( "diff failed on testReport in Tcl MakeSegVolReport" );
    }

    sprintf( sCommand, "MakeSegVolIntensityReport /tmp/testIntReport2.txt" );
    rTcl = Tcl_Eval( iInterp, sCommand );
    AssertTclOK( rTcl );
    rDiff =
      system( "diff /tmp/testIntReport2.txt testSegmentationVolumeReportIntReport-correct.txt" );
    if ( rDiff != 0 ) {
      throw runtime_error( "diff failed on testIntReport in Tcl MakeSegVolIntensityReport" );
    }

    sprintf( sCommand, "ClearSegVolReport" );
    rTcl = Tcl_Eval( iInterp, sCommand );
    AssertTclOK( rTcl );
    if ( NULL != report.mSegVol ||
         report.mlIntVols.size() != 0 ||
         report.mbUseROI ||
         NULL != report.mROIVol ||
         NULL != report.mROI ||
         NULL != report.mLUT ||
         report.mlStructures.size() != 0 ||
         !report.mbReportDirty ||
         report.mVolumeToIntensityAverageMap.size() != 0 ||
         report.mStructureToVolumeVoxelListMap.size() != 0 ) {
      stringstream ssError;
      ssError << "Error on Tcl ClearSegVolReport: not cleared";
      throw runtime_error( ssError.str() );
    }

  } catch ( exception& e ) {
    cerr << "failed with exception: " << e.what() << endl;
    exit( 1 );
  } catch (...) {
    cerr << "failed." << endl;
    exit( 1 );
  }
}
Пример #2
0
void
VolumeCollectionTester::Test ( Tcl_Interp* iInterp ) {

  stringstream ssError;

  try {

    string fnMRI = "test_data/bertT1.mgz";
    VolumeCollection* vol = new VolumeCollection();
    vol->SetFileName( fnMRI );
    MRI* mri = const_cast<MRI*>(vol->GetMRI());

    Assert( (vol->GetTypeDescription() == "Volume"),
            "GetTypeDescription didn't return Volume" );

    DataManager dataMgr = DataManager::GetManager();
    MRILoader mriLoader = dataMgr.GetMRILoader();
    Assert( 1 == mriLoader.CountLoaded(),
            "CountLoaded didn't return 1" );
    Assert( 1 == mriLoader.CountReferences(mri),
            "CountReferences didn't return 1" );

    char* fnMRIC = strdup( fnMRI.c_str() );
    MRI* mriComp = MRIread( fnMRIC );

    Assert( (MRImatch( mriComp, mri )), "MRImatch failed for load" );

    MRIfree( &mriComp );


    // Save it in /tmp, load it, and match it again.
    string fnSave( "/tmp/test.mgz" );
    vol->Save( fnSave );

    VolumeCollection* testVol = new VolumeCollection();
    testVol->SetFileName( fnSave );
    MRI* testMri = const_cast<MRI*>(testVol->GetMRI());
    Assert( (MRImatch( testMri, mri )), "MRImatch failed for load after save");



    // Make an ROI and make sure it's a volume ROI.
    try {
      int roiID = vol->NewROI();
      ScubaROIVolume* roi =
        dynamic_cast<ScubaROIVolume*>(&ScubaROI::FindByID( roiID ));
      roi = NULL;
    } catch (...) {
      throw( runtime_error("typecast failed for NewROI") );
    }


    // Try our conversions.
    Point3<float> world;
    Point3<float> data;
    Point3<int> index;
    world.Set( -50, 0, -80 );
    vol->RASToMRIIndex( world.xyz(), index.xyz() );
    {
      stringstream ssError;
      ssError << "RASToMRIIndex failed. world "
      << world << " index " << index;
      Assert( (index.x() == 178 && index.y() == 208 && index.z() == 128),
              ssError.str() );
    }

    // Set a transform that scales the volume up by 2x in the world.
    ScubaTransform dataTransform;
    dataTransform.SetMainTransform( 2, 0, 0, 0,
                                    0, 2, 0, 0,
                                    0, 0, 2, 0,
                                    0, 0, 0, 1 );
    vol->SetDataToWorldTransform( dataTransform.GetID() );

    world.Set( -50, 0, -80 );
    vol->RASToDataRAS( world.xyz(), data.xyz() );
    {
      stringstream ssError;
      ssError << "RASToDataRAS failed. world "
      << world << " data " << data;
      Assert( ((FEQUAL(data.x(),-25)) &&
               (FEQUAL(data.y(),0)) &&
               (FEQUAL(data.z(),-40))),
              ssError.str() );
    }

    vol->RASToMRIIndex( world.xyz(), index.xyz() );

    if ( index.x() != 153 || index.y() != 168 || index.z() != 128 ) {
      cerr << "RASToMRIIndex with data transform failed. world "
      << world << " index " << index << endl;
      throw( runtime_error( "failed" ) );
    }


    world.Set( -50, 0, -80 );
    VolumeLocation loc( vol->MakeVolumeLocationFromRAS( world.xyz() ) );
    if ( !vol->IsInBounds( loc ) ) {
      stringstream ssError;
      ssError << "IsInBounds failed. world " << world;
      throw( runtime_error( ssError.str() ) );
    }
    world.Set( -1000, 0, 0 );
    VolumeLocation loc2( vol->MakeVolumeLocationFromRAS( world.xyz() ) );
    if ( vol->IsInBounds( loc2 ) ) {
      stringstream ssError;
      ssError << "IsInBounds failed. world " << world;
      throw( runtime_error( ssError.str() ) );
    }


    dataTransform.SetMainTransform( 2, 0, 0, 0,
                                    0, 2, 0, 0,
                                    0, 0, 2, 0,
                                    0, 0, 0, 1 );
    vol->SetDataToWorldTransform( dataTransform.GetID() );
    world.Set( 0, -1000, -254 );
    VolumeLocation loc3( vol->MakeVolumeLocationFromRAS( world.xyz() ) );
    if ( vol->IsInBounds( loc3 ) ) {
      stringstream ssError;
      vol->RASToMRIIndex( world.xyz(), index.xyz() );
      ssError << "IsRASInMRIBounds failed. world " << world
      << " index " << index;
      throw( runtime_error( ssError.str() ) );
    }


    {
      // Create a new one from template.
      VolumeCollection* vol2 = new VolumeCollection();
      vol2->MakeUsingTemplate( vol->GetID(), -1 );
      Assert( (vol->mVoxelSize[0] == vol2->mVoxelSize[0] &&
	       vol->mVoxelSize[1] == vol2->mVoxelSize[1] &&
	       vol->mVoxelSize[2] == vol2->mVoxelSize[2]),
	      "NewUsingTemplate failed, vol2 didn't match vol's voxelsize" );
      Assert( (vol->GetDataType() == vol2->GetDataType()),
	    "NewUsingTemplate(-1) failed, vol2 didn't match vol's data type" );
      delete vol2;
    }
    
    {
      VolumeCollection* vol2 = new VolumeCollection();
      vol2->MakeUsingTemplate( vol->GetID(), MRI_FLOAT );
      Assert( (vol->mVoxelSize[0] == vol2->mVoxelSize[0] &&
	       vol->mVoxelSize[1] == vol2->mVoxelSize[1] &&
	       vol->mVoxelSize[2] == vol2->mVoxelSize[2]),
	      "NewUsingTemplate failed, vol2 didn't match vol's voxelsize" );
      Assert( (MRI_FLOAT == vol2->GetDataType()),
	      "NewUsingTemplate(float) failed, vol2 wasn't a float" );
      
      int idx[3] = { 0, 0, 0 };
      VolumeLocation loc( vol2->MakeVolumeLocationFromIndex( idx ) );
      vol2->SetMRIValue( loc, 0.6789 );
      float value = vol2->GetMRINearestValue(loc);

      stringstream ssError;
      ssError << "NewUsingTemplate(float) failed value comparison, "
	      << "was expecting 0.6789 but got " << value;
      Assert( (fabs(0.6789 - value) < 0.00001), ssError.str() );
      delete vol2;
    }

    {
      VolumeCollection* vol2 = NULL;
      try {
	vol2 = new VolumeCollection();
	vol2->MakeUsingTemplate( vol->GetID(), 10000 );
	throw runtime_error( "MakeUsingTemplate(10000) didn't throw an error");
      }
      catch(...) {}
      delete vol2;
    }

    dataTransform.SetMainTransform( 1, 0, 0, 0,
                                    0, 1, 0, 0,
                                    0, 0, 1, 0,
                                    0, 0, 0, 1 );
    vol->SetDataToWorldTransform( dataTransform.GetID() );

    // FindRASPointsInSquare
    {
      Point3<float> sqRAS[4], cRAS;
      sqRAS[0].Set( 0, -3, 71 );
      sqRAS[1].Set( 0, 1, 71 );
      sqRAS[2].Set( 0, 1, 67 );
      sqRAS[3].Set( 0, -3, 67 );
      cRAS.Set( 0, -1, 69 );
      list<Point3<float> > points;
      vol->FindRASPointsInSquare( cRAS.xyz(),
                                  sqRAS[0].xyz(), sqRAS[1].xyz(),
                                  sqRAS[2].xyz(), sqRAS[3].xyz(),
                                  0, points );
      list<Point3<float> >::iterator tPoint;
      for ( tPoint = points.begin(); tPoint != points.end(); ++tPoint ) {
        Point3<float> pRAS = *tPoint;

        stringstream ssMsg;
        ssMsg << "Failed: " << pRAS << " outside of square";

        Assert( ( pRAS[0] == 0 &&
                  (pRAS[1] >= -3 && pRAS[1] <= 1) &&
                  (pRAS[2] >= 67 && pRAS[2] <= 71) ),
                ssMsg.str() );
      }
    }


    // VoxelIntersectsSegment
    {
      Point3<int> idx;
      Point3<float> segIdxA, segIdxB;
      Point3<float> intIdx;

      idx.Set( 5, 5, 5 );

      float aSegments[6][3] = { {3, 5.5, 5.5}, {6, 5.5, 5.5},
                                {5.5, 3, 5.5}, {5.5, 6, 5.5},
                                {5.5, 5.5, 3}, {5.5, 5.5, 6} };
      for ( int nSegment = 0; nSegment < 6; nSegment += 2 ) {

        segIdxA.Set( aSegments[nSegment] );
        segIdxB.Set( aSegments[nSegment+1] );

        VectorOps::IntersectionResult rInt =
          vol->VoxelIntersectsSegment( idx, segIdxA, segIdxB, intIdx );

        if ( VectorOps::intersect != rInt ) {
          cerr << "Failed VoxelIntersectsSegment test: idx " << idx
          << ", seg " << segIdxA << ", " << segIdxB << endl
          << "\tDidn't intersect" << endl;
          throw runtime_error("failed");
        }
      }

      segIdxA.Set( 0, 5.5, 5.5 );
      segIdxB.Set( 4, 5.5, 5.5 );
      VectorOps::IntersectionResult rInt =
        vol->VoxelIntersectsSegment( idx, segIdxA, segIdxB, intIdx );

      if ( VectorOps::dontIntersect != rInt ) {
        cerr << "Failed VoxelIntersectsSegment test: idx " << idx
        << ", seg " << segIdxA << ", " << segIdxB << endl
        << "\tIntersected" << endl;
        throw runtime_error("failed");
      }
    }

    // FindRASPointsOnSegment
    {

    }


    // GetVoxelsWithValue
    {
      // This is a 5cubed volume whose values are set to the x
      // coordinate. So for x=3,y=0..4,z=0..4, value = 3.
      string fnVol = "test_data/testVolumeCollection-GetVoxelsWithValue.mgh";
      ifstream fVol( fnMRI.c_str(), ios::in );
      if ( !fVol ) {
        throw runtime_error("Couldn't find necessary test data.");
      }
      fVol.close();

      VolumeCollection* vol = new VolumeCollection();
      vol->SetFileName( fnVol );
      vol->LoadVolume();

      // Get the values 0-4 and make sure we got the right voxels.
      for ( int nStructure = 0; nStructure < 5; nStructure++ ) {

        list<VolumeLocation> lLocations;
        vol->GetVoxelsWithValue( nStructure, lLocations );

        Volume3<bool> bGot( 5, 5, 5, false );
        list<VolumeLocation>::iterator tLocation;
        for ( tLocation = lLocations.begin(); tLocation != lLocations.end();
              ++tLocation ) {

          VolumeLocation loc = *(tLocation);
          bGot.Set( loc.Index()[0], loc.Index()[1], loc.Index()[2], true );
        }

        for ( int nZ = 0; nZ < 5; nZ++ ) {
          for ( int nY = 0; nY < 5; nY++ ) {
            for ( int nX = 0; nX < 5; nX++ ) {
              if ( nX == nStructure && !bGot.Get( nX, nY, nZ ) ) {
                stringstream ssErr;
                ssErr << "Failed GetVoxelsWithValue test: "
                << " nStructure = " << nStructure
                << " index " << Point3<int>(nX,nY,nZ)
                << " - was supposed to get voxel but didn't";
                throw runtime_error(ssErr.str());
              }
              if ( nX != nStructure && bGot.Get( nX, nY, nZ ) ) {
                stringstream ssErr;
                ssErr << "Failed GetVoxelsWithValue test: "
                << " nStructure = " << nStructure
                << " index " << Point3<int>(nX,nY,nZ)
                << " - wasn't supposed to get voxel but did";
                throw runtime_error(ssErr.str());
              }
            }
          }
        }
      }

      delete vol;
    }

    // GetAverageValue
    {
      // We'll use the same volume as with GetVoxelsWithValue.
      string fnVol = "test_data/testVolumeCollection-GetVoxelsWithValue.mgh";
      ifstream fVol( fnMRI.c_str(), ios::in );
      if ( !fVol ) {
        throw runtime_error("Couldn't find necessary test data.");
      }
      fVol.close();

      VolumeCollection* vol = new VolumeCollection();
      vol->SetFileName( fnVol );
      vol->LoadVolume();

      // Get values of all voxels in plane x=3 and make sure it's 3.
      list<VolumeLocation> lVoxels;
      for ( int nZ = 0; nZ < 5; nZ++ ) {
        for ( int nY = 0; nY < 5; nY++ ) {
          int index[3] = { 3, nY, nZ };
          VolumeLocation loc( vol->MakeVolumeLocationFromIndex( index ) );
          lVoxels.push_back( loc );
        }
      }
      float average = vol->GetAverageValue( lVoxels );
      if ( average != 3.0 ) {
        stringstream ssErr;
        ssErr << "Failed GetAverageValue: Getting all voxels in x=3, "
        << "average should have been 3, but was " << average;
        throw runtime_error( ssErr.str() );
      }

      // Get values of 5 voxels, one from each x plane
      // (val=0,1,2,3,4), and make sure it's 2.
      lVoxels.clear();
      for ( int nX = 0; nX < 5; nX++ ) {
        int index[3] = { nX, 3, 3 };
        VolumeLocation loc( vol->MakeVolumeLocationFromIndex( index ) );
        lVoxels.push_back( loc );
      }
      average = vol->GetAverageValue( lVoxels );
      if ( average != 2.0 ) {
        stringstream ssErr;
        ssErr << "Failed GetAverageValue: Getting voxels in different planes, "
        << "average should have been 2, but was " << average;
        throw runtime_error( ssErr.str() );
      }

      // Make sure we get an error for no voxels.
      lVoxels.clear();
      bool bDidntThrow = false;
      try {
        average = vol->GetAverageValue( lVoxels );
        bDidntThrow = true;
      } catch ( exception& e ) {}
      if ( bDidntThrow ) {
        stringstream ssErr;
        ssErr << "Failed GetAverageValue: Didn't throw with empty list";
        throw runtime_error( ssErr.str() );
      }

      delete vol;
    }


    // Check the tcl commands.
    char sCommand[1024];
    int rTcl;

    int id = vol->GetID();
    string fnTest = "test-name";
    sprintf( sCommand, "SetVolumeCollectionFileName %d test-name", id );
    rTcl = Tcl_Eval( iInterp, sCommand );
    AssertTclOK( rTcl );
    Assert( (vol->mfnMRI == fnTest),
            "Setting file name via tcl didn't work" );

    vol->SetDataToWorldTransform( 0 );

    delete vol;
    delete testVol;
  } catch ( exception& e ) {
    cerr << "failed with exception: " << e.what() << endl;
    exit( 1 );
  } catch (...) {
    cerr << "failed." << endl;
    exit( 1 );
  }
}