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 ); } }