Exemple #1
0
        public void TestFillSigned16VoxelData()
        {
            var orientation = new DataSetOrientation(new Vector3D(1, 0, 0), new Vector3D(0, 1, 0), new Vector3D(0, 0, 1));

            TestVolume(VolumeFunction.Stars,
                       orientation.Initialize,
                       volume =>
            {
                Assert.AreEqual(16, volume.BitsPerVoxel, "BitsPerVoxel");
                Assert.AreEqual(false, volume.Signed, "Signed");
                Assert.AreEqual(65535, volume.MaximumVolumeValue, "MaximumVolumeValue");
                Assert.AreEqual(0, volume.MinimumVolumeValue, "MinimumVolumeValue");
                Assert.AreEqual(0, volume.PaddingValue, "PaddingValue");
                Assert.AreEqual(1, volume.RescaleSlope, "RescaleSlope");
                Assert.AreEqual(-32768, volume.RescaleIntercept, "RescaleIntercept");

                Assert.AreEqual(new Size3D(100, 100, 100), volume.ArrayDimensions, "ArrayDimensions");
                AssertAreEqual(new Vector3D(1, 0, 0), volume.VolumeOrientationPatientX, "VolumeOrientationPatientX");
                AssertAreEqual(new Vector3D(0, 1, 0), volume.VolumeOrientationPatientY, "VolumeOrientationPatientY");
                AssertAreEqual(new Vector3D(0, 0, 1), volume.VolumeOrientationPatientZ, "VolumeOrientationPatientZ");
                AssertAreEqual(new Vector3D(0, 0, 0), volume.VolumePositionPatient, "VolumePositionPatient");
                AssertAreEqual(new Vector3D(100, 100, 100), volume.VolumeSize, "VolumeSize");
                AssertAreEqual(new Vector3D(1, 1, 1), volume.VoxelSpacing, "VoxelSpacing");

                foreach (KnownSample sample in StarsKnownSamples)
                {
                    int actual = volume[(int)sample.Point.X, (int)sample.Point.Y, (int)sample.Point.Z];
                    Trace.WriteLine(string.Format("Sample {0} @{1}", actual, sample.Point));
                    Assert.AreEqual(sample.Value, actual, "Wrong colour sample @{0}", sample.Point);
                }
            },
                       signed: true);
        }
Exemple #2
0
        public void TestFillGantryTiltedVoxelData2()
        {
            const double angleDegrees = -30;
            const double angleRadians = angleDegrees * _degreesInRadians;
            const int    paddingRows  = 50;         // 50 padding rows because sin(-30)*(100 voxels deep) = 50 voxels high (just padding starts at bottom this time)

            DataSetOrientation orientation = DataSetOrientation.CreateGantryTiltedAboutX(angleDegrees);

            TestVolume(VolumeFunction.Stars,
                       orientation.Initialize,
                       volume =>
            {
                Assert.AreEqual(new Size3D(100, 100 + paddingRows, 100), volume.ArrayDimensions, "ArrayDimensions");
                AssertAreEqual(new Vector3D(1, 0, 0), volume.VolumeOrientationPatientX, "VolumeOrientationPatientX");
                AssertAreEqual(new Vector3D(0, (float)Math.Cos(angleRadians), -(float)Math.Sin(angleRadians)), volume.VolumeOrientationPatientY, "VolumeOrientationPatientY");
                AssertAreEqual(new Vector3D(0, (float)Math.Sin(angleRadians), (float)Math.Cos(angleRadians)), volume.VolumeOrientationPatientZ, "VolumeOrientationPatientZ");
                AssertAreEqual(new Vector3D(0, 0, 0), volume.VolumePositionPatient, "VolumePositionPatient");
                AssertAreEqual(new Vector3D(100, 100 + paddingRows, (float)(100 * Math.Cos(angleRadians))), volume.VolumeSize, "VolumeSize");
                AssertAreEqual(new Vector3D(1, 1, (float)Math.Cos(angleRadians)), volume.VoxelSpacing, "VoxelSpacing");

                foreach (KnownSample sample in StarsKnownSamples)
                {
                    Vector3D realPoint   = sample.Point;
                    Vector3D paddedPoint = realPoint + new Vector3D(0, (float)(-Math.Sin(angleRadians) * (realPoint.Z)), 0);

                    int actual = volume[(int)paddedPoint.X, (int)paddedPoint.Y, (int)paddedPoint.Z];
                    Trace.WriteLine(string.Format("Sample {0} @{1} ({2} before padding)", actual, paddedPoint, realPoint));
                    Assert.AreEqual(sample.Value, actual, "Wrong colour sample @{0} ({1} before padding)", paddedPoint, realPoint);
                }
            });
        }
Exemple #3
0
        public void TestFillObliqueCuboidVoxelData()
        {
            var halfRoot2   = (float)(1 / Math.Sqrt(2));
            var orientation = new DataSetOrientation(new Vector3D(0, 1, 0), new Vector3D(1, 0, 1), new Vector3D(-1, 0, 1));

            TestVolume(VolumeFunction.Stars,
                       orientation.Initialize,
                       volume =>
            {
                Assert.AreEqual(new Size3D(100, 100, 100), volume.ArrayDimensions, "ArrayDimensions");
                AssertAreEqual(new Vector3D(0, 1, 0), volume.VolumeOrientationPatientX, "VolumeOrientationPatientX");
                AssertAreEqual(new Vector3D(halfRoot2, 0, halfRoot2), volume.VolumeOrientationPatientY, "VolumeOrientationPatientY");
                AssertAreEqual(new Vector3D(halfRoot2, 0, -halfRoot2), volume.VolumeOrientationPatientZ, "VolumeOrientationPatientZ");                             // volume orientation is always a right-handed system
                AssertAreEqual(-99 * new Vector3D(halfRoot2, 0, -halfRoot2), volume.VolumePositionPatient, "VolumePositionPatient");                               // 0 is the the first frame, so the last (100th) frame is -99
                AssertAreEqual(new Vector3D(100, 100, 100), volume.VolumeSize, "VolumeSize");
                AssertAreEqual(new Vector3D(1, 1, 1), volume.VoxelSpacing, "VoxelSpacing");

                foreach (KnownSample sample in StarsKnownSamples)
                {
                    int actual = volume[(int)sample.Point.X, (int)sample.Point.Y, 100 - (int)sample.Point.Z];
                    Trace.WriteLine(string.Format("Sample {0} @{1}", actual, sample.Point));
                    Assert.AreEqual(sample.Value, actual, "Wrong colour sample @{0}", sample.Point);
                }
            });
        }
Exemple #4
0
        public void TestCouchTiltedSource()
        {
            {
                DataSetOrientation orientation = DataSetOrientation.CreateCouchTiltedAboutX(30);

                // it doesn't really matter what function we use
                TestVolume(VolumeFunction.Void, orientation.Initialize, null);
            }

            {
                DataSetOrientation orientation = DataSetOrientation.CreateCouchTiltedAboutX(-30);

                // it doesn't really matter what function we use
                TestVolume(VolumeFunction.Void, orientation.Initialize, null);
            }

            {
                DataSetOrientation orientation = DataSetOrientation.CreateCouchTiltedAboutY(30);

                // it doesn't really matter what function we use
                TestVolume(VolumeFunction.Void, orientation.Initialize, null);
            }

            {
                DataSetOrientation orientation = DataSetOrientation.CreateCouchTiltedAboutY(-30);

                // it doesn't really matter what function we use
                TestVolume(VolumeFunction.Void, orientation.Initialize, null);
            }
        }
Exemple #5
0
        public void TestSagittalSource()
        {
            DataSetOrientation orientation = DataSetOrientation.CreateSagittal(false);

            // it doesn't really matter what function we use
            TestVolume(VolumeFunction.Void, orientation.Initialize, null);
        }
Exemple #6
0
        public void TestGantryTiltedSource()
        {
            {
                string imageOrientationPatient = string.Format(@"{1:f9}\{1:f9}\{0:f9}\-{0:f9}\{0:f9}\0", Math.Cos(Math.PI / 4), Math.Pow(Math.Cos(Math.PI / 4), 2));
                try
                {
                    // it doesn't really matter what function we use
                    TestVolume(VolumeFunction.Void, sopDataSource => sopDataSource[DicomTags.ImageOrientationPatient].SetStringValue(imageOrientationPatient), null);
                    Assert.Fail("Expected an exception of type {0}", typeof(UnsupportedGantryTiltAxisException));
                }
                catch (UnsupportedGantryTiltAxisException) {}
            }

            {
                DataSetOrientation orientation = DataSetOrientation.CreateGantryTiltedAboutX(30);

                // it doesn't really matter what function we use
                TestVolume(VolumeFunction.Void, orientation.Initialize, null);
            }

            {
                DataSetOrientation orientation = DataSetOrientation.CreateGantryTiltedAboutX(-30);

                // it doesn't really matter what function we use
                TestVolume(VolumeFunction.Void, orientation.Initialize, null);
            }

            {
                DataSetOrientation orientation = DataSetOrientation.CreateGantryTiltedAboutY(30);

                try
                {
                    // it doesn't really matter what function we use
                    TestVolume(VolumeFunction.Void, orientation.Initialize, null);
                    Assert.Fail("Expected an exception of type {0}", typeof(UnsupportedGantryTiltAxisException));
                }
                catch (UnsupportedGantryTiltAxisException) {}
            }

            {
                DataSetOrientation orientation = DataSetOrientation.CreateGantryTiltedAboutY(-30);

                try
                {
                    // it doesn't really matter what function we use
                    TestVolume(VolumeFunction.Void, orientation.Initialize, null);
                    Assert.Fail("Expected an exception of type {0}", typeof(UnsupportedGantryTiltAxisException));
                }
                catch (UnsupportedGantryTiltAxisException) {}
            }
        }
Exemple #7
0
        public void TestFillObliqueParallelepipedVoxelData2()
        {
            // column orientation skewed by 30 degreees from normal
            const double skewAngle   = -30 * _degreesInRadians;
            const int    paddingRows = 50;          // 50 padding rows because sin(-30)*(100 voxels deep) = 50 voxels high (just padding starts at bottom this time)
            var          halfRoot2   = (float)(1 / Math.Sqrt(2));
            var          halfRoot3   = (float)Math.Sqrt(3) / 2;

            var row         = new Vector3D(0, 1, 0);
            var column      = new Vector3D(halfRoot2, 0, halfRoot2);
            var stack       = new Vector3D(halfRoot2 * halfRoot3 + halfRoot2 / 2, 0, -halfRoot2 * halfRoot3 + halfRoot2 / 2).Normalize();
            var orientation = new DataSetOrientation(row, column, stack);

            TestVolume(VolumeFunction.Stars,
                       orientation.Initialize,
                       volume =>
            {
                Assert.AreEqual(new Size3D(100, 100 + paddingRows, 100), volume.ArrayDimensions, "ArrayDimensions");
                AssertAreEqual(row, volume.VolumeOrientationPatientX, "VolumeOrientationPatientX");
                AssertAreEqual(column, volume.VolumeOrientationPatientY, "VolumeOrientationPatientY");
                AssertAreEqual((100 * stack - paddingRows * column).Normalize(), volume.VolumeOrientationPatientZ, "VolumeOrientationPatientZ");
                AssertAreEqual(new Vector3D(0, 0, 0), volume.VolumePositionPatient, "VolumePositionPatient");
                AssertAreEqual(new Vector3D(100, 100 + paddingRows, (float)(100 * Math.Cos(skewAngle))), volume.VolumeSize, "VolumeSize");
                AssertAreEqual(new Vector3D(1, 1, (float)Math.Cos(skewAngle)), volume.VoxelSpacing, "VoxelSpacing");

                foreach (KnownSample sample in StarsKnownSamples)
                {
                    Vector3D realPoint   = sample.Point;
                    Vector3D paddedPoint = realPoint + new Vector3D(0, (float)(-Math.Sin(skewAngle) * (realPoint.Z)), 0);

                    int actual = volume[(int)paddedPoint.X, (int)paddedPoint.Y, (int)paddedPoint.Z];
                    Trace.WriteLine(string.Format("Sample {0} @{1} ({2} before padding)", actual, paddedPoint, realPoint));
                    Assert.AreEqual(sample.Value, actual, "Wrong colour sample @{0} ({1} before padding)", paddedPoint, realPoint);
                }
            });
        }
Exemple #8
0
        public void TestObliqueSkewedSource()
        {
            {
                // perfectly rectangular cuboid, oblique source
                var row    = new Vector3D(1, 2, 3);
                var column = new Vector3D(7, 10, -9);
                var stack  = row.Cross(column);

                var orientation = new DataSetOrientation(row, column, stack);
                TestVolume(VolumeFunction.Void, orientation.Initialize, null);
            }

            {
                // based on a real breast tomo MLO source - perfectly valid, and oblique w.r.t normal gantry-oriented calculations
                var row    = new Vector3D(0, 1, 0);
                var column = new Vector3D(1, 0, 1);
                var stack  = new Vector3D(-100, 0, 100);

                var orientation = new DataSetOrientation(row, column, stack);
                TestVolume(VolumeFunction.Void, orientation.Initialize, null);
            }

            {
                // column orientation skewed by 30 degreees from normal
                const double skewAngle = 30 * _degreesInRadians;

                var row    = new Vector3D(1, 2, 3);
                var column = new Vector3D(7, 10, -9);
                var stack  = (float)Math.Cos(skewAngle) * row.Cross(column).Normalize() - (float)Math.Sin(skewAngle) * column.Normalize();

                var orientation = new DataSetOrientation(row, column, stack);
                TestVolume(VolumeFunction.Void, orientation.Initialize, null);
            }

            {
                // column orientation skewed by -30 degreees from normal
                const double skewAngle = -30 * _degreesInRadians;

                var row    = new Vector3D(1, 2, 3);
                var column = new Vector3D(7, 10, -9);
                var stack  = (float)Math.Cos(skewAngle) * row.Cross(column).Normalize() - (float)Math.Sin(skewAngle) * column.Normalize();

                var orientation = new DataSetOrientation(row, column, stack);
                TestVolume(VolumeFunction.Void, orientation.Initialize, null);
            }

            try
            {
                // row orientation skewed by 30 degreees from normal
                const double skewAngle = 30 * _degreesInRadians;

                var row    = new Vector3D(1, 2, 3);
                var column = new Vector3D(7, 10, -9);
                var stack  = (float)Math.Cos(skewAngle) * row.Cross(column).Normalize() - (float)Math.Sin(skewAngle) * row.Normalize();

                var orientation = new DataSetOrientation(row, column, stack);
                TestVolume(VolumeFunction.Void, orientation.Initialize, null);

                Assert.Fail("Expected an exception of type {0}", typeof(UnsupportedGantryTiltAxisException));
            }
            catch (UnsupportedGantryTiltAxisException) {}

            try
            {
                // row orientation skewed by -30 degreees from normal
                const double skewAngle = -30 * _degreesInRadians;

                var row    = new Vector3D(1, 2, 3);
                var column = new Vector3D(7, 10, -9);
                var stack  = (float)Math.Cos(skewAngle) * row.Cross(column).Normalize() - (float)Math.Sin(skewAngle) * row.Normalize();

                var orientation = new DataSetOrientation(row, column, stack);
                TestVolume(VolumeFunction.Void, orientation.Initialize, null);

                Assert.Fail("Expected an exception of type {0}", typeof(UnsupportedGantryTiltAxisException));
            }
            catch (UnsupportedGantryTiltAxisException) {}

            try
            {
                // column orientation skewed by -30 degreees from normal, then further row skewed by 20 degrees
                const double skewAngle1 = -30 * _degreesInRadians;
                const double skewAngle2 = 20 * _degreesInRadians;

                var row    = new Vector3D(1, 2, 3);
                var column = new Vector3D(7, 10, -9);
                var temp   = (float)Math.Cos(skewAngle1) * row.Cross(column).Normalize() - (float)Math.Sin(skewAngle1) * column.Normalize();
                var stack  = (float)Math.Cos(skewAngle2) * temp.Normalize() - (float)Math.Sin(skewAngle2) * row.Normalize();

                var orientation = new DataSetOrientation(row, column, stack);
                TestVolume(VolumeFunction.Void, orientation.Initialize, null);

                Assert.Fail("Expected an exception of type {0}", typeof(UnsupportedGantryTiltAxisException));
            }
            catch (UnsupportedGantryTiltAxisException) {}
        }
Exemple #9
0
        public void TestDifferentImageOrientationSource()
        {
            int n = 0;

            try
            {
                // it doesn't really matter what function we use
                TestVolume(VolumeFunction.Void, sopDataSource => sopDataSource[DicomTags.ImageOrientationPatient].SetStringValue(DataSetOrientation.CreateGantryTiltedAboutX(n++).ImageOrientationPatient), null);
                Assert.Fail("Expected an exception of type {0}", typeof(MultipleImageOrientationsException));
            }
            catch (MultipleImageOrientationsException) {}
        }
		public void TestFillObliqueParallelepipedVoxelData2()
		{
			// column orientation skewed by 30 degreees from normal
			const double skewAngle = -30*_degreesInRadians;
			const int paddingRows = 50; // 50 padding rows because sin(-30)*(100 voxels deep) = 50 voxels high (just padding starts at bottom this time)
			var halfRoot2 = (float) (1/Math.Sqrt(2));
			var halfRoot3 = (float) Math.Sqrt(3)/2;

			var row = new Vector3D(0, 1, 0);
			var column = new Vector3D(halfRoot2, 0, halfRoot2);
			var stack = new Vector3D(halfRoot2*halfRoot3 + halfRoot2/2, 0, -halfRoot2*halfRoot3 + halfRoot2/2).Normalize();
			var orientation = new DataSetOrientation(row, column, stack);

			TestVolume(VolumeFunction.Stars,
			           orientation.Initialize,
			           volume =>
			           	{
			           		Assert.AreEqual(new Size3D(100, 100 + paddingRows, 100), volume.ArrayDimensions, "ArrayDimensions");
			           		AssertAreEqual(row, volume.VolumeOrientationPatientX, "VolumeOrientationPatientX");
			           		AssertAreEqual(column, volume.VolumeOrientationPatientY, "VolumeOrientationPatientY");
			           		AssertAreEqual((100*stack - paddingRows*column).Normalize(), volume.VolumeOrientationPatientZ, "VolumeOrientationPatientZ");
			           		AssertAreEqual(new Vector3D(0, 0, 0), volume.VolumePositionPatient, "VolumePositionPatient");
			           		AssertAreEqual(new Vector3D(100, 100 + paddingRows, (float) (100*Math.Cos(skewAngle))), volume.VolumeSize, "VolumeSize");
			           		AssertAreEqual(new Vector3D(1, 1, (float) Math.Cos(skewAngle)), volume.VoxelSpacing, "VoxelSpacing");

			           		foreach (KnownSample sample in StarsKnownSamples)
			           		{
			           			Vector3D realPoint = sample.Point;
			           			Vector3D paddedPoint = realPoint + new Vector3D(0, (float) (-Math.Sin(skewAngle)*(realPoint.Z)), 0);

			           			int actual = volume[(int) paddedPoint.X, (int) paddedPoint.Y, (int) paddedPoint.Z];
			           			Trace.WriteLine(string.Format("Sample {0} @{1} ({2} before padding)", actual, paddedPoint, realPoint));
			           			Assert.AreEqual(sample.Value, actual, "Wrong colour sample @{0} ({1} before padding)", paddedPoint, realPoint);
			           		}
			           	});
		}
		public void TestFillObliqueCuboidVoxelData()
		{
			var halfRoot2 = (float) (1/Math.Sqrt(2));
			var orientation = new DataSetOrientation(new Vector3D(0, 1, 0), new Vector3D(1, 0, 1), new Vector3D(-1, 0, 1));

			TestVolume(VolumeFunction.Stars,
			           orientation.Initialize,
			           volume =>
			           	{
			           		Assert.AreEqual(new Size3D(100, 100, 100), volume.ArrayDimensions, "ArrayDimensions");
			           		AssertAreEqual(new Vector3D(0, 1, 0), volume.VolumeOrientationPatientX, "VolumeOrientationPatientX");
			           		AssertAreEqual(new Vector3D(halfRoot2, 0, halfRoot2), volume.VolumeOrientationPatientY, "VolumeOrientationPatientY");
			           		AssertAreEqual(new Vector3D(halfRoot2, 0, -halfRoot2), volume.VolumeOrientationPatientZ, "VolumeOrientationPatientZ"); // volume orientation is always a right-handed system
			           		AssertAreEqual(-99*new Vector3D(halfRoot2, 0, -halfRoot2), volume.VolumePositionPatient, "VolumePositionPatient"); // 0 is the the first frame, so the last (100th) frame is -99
			           		AssertAreEqual(new Vector3D(100, 100, 100), volume.VolumeSize, "VolumeSize");
			           		AssertAreEqual(new Vector3D(1, 1, 1), volume.VoxelSpacing, "VoxelSpacing");

			           		foreach (KnownSample sample in StarsKnownSamples)
			           		{
			           			int actual = volume[(int) sample.Point.X, (int) sample.Point.Y, 100 - (int) sample.Point.Z];
			           			Trace.WriteLine(string.Format("Sample {0} @{1}", actual, sample.Point));
			           			Assert.AreEqual(sample.Value, actual, "Wrong colour sample @{0}", sample.Point);
			           		}
			           	});
		}
		public void TestFillSigned16VoxelData()
		{
			var orientation = new DataSetOrientation(new Vector3D(1, 0, 0), new Vector3D(0, 1, 0), new Vector3D(0, 0, 1));

			TestVolume(VolumeFunction.Stars,
			           orientation.Initialize,
			           volume =>
			           	{
			           		Assert.AreEqual(16, volume.BitsPerVoxel, "BitsPerVoxel");
			           		Assert.AreEqual(false, volume.Signed, "Signed");
			           		Assert.AreEqual(65535, volume.MaximumVolumeValue, "MaximumVolumeValue");
			           		Assert.AreEqual(0, volume.MinimumVolumeValue, "MinimumVolumeValue");
			           		Assert.AreEqual(0, volume.PaddingValue, "PaddingValue");
			           		Assert.AreEqual(1, volume.RescaleSlope, "RescaleSlope");
			           		Assert.AreEqual(-32768, volume.RescaleIntercept, "RescaleIntercept");

			           		Assert.AreEqual(new Size3D(100, 100, 100), volume.ArrayDimensions, "ArrayDimensions");
			           		AssertAreEqual(new Vector3D(1, 0, 0), volume.VolumeOrientationPatientX, "VolumeOrientationPatientX");
			           		AssertAreEqual(new Vector3D(0, 1, 0), volume.VolumeOrientationPatientY, "VolumeOrientationPatientY");
			           		AssertAreEqual(new Vector3D(0, 0, 1), volume.VolumeOrientationPatientZ, "VolumeOrientationPatientZ");
			           		AssertAreEqual(new Vector3D(0, 0, 0), volume.VolumePositionPatient, "VolumePositionPatient");
			           		AssertAreEqual(new Vector3D(100, 100, 100), volume.VolumeSize, "VolumeSize");
			           		AssertAreEqual(new Vector3D(1, 1, 1), volume.VoxelSpacing, "VoxelSpacing");

			           		foreach (KnownSample sample in StarsKnownSamples)
			           		{
			           			int actual = volume[(int) sample.Point.X, (int) sample.Point.Y, (int) sample.Point.Z];
			           			Trace.WriteLine(string.Format("Sample {0} @{1}", actual, sample.Point));
			           			Assert.AreEqual(sample.Value, actual, "Wrong colour sample @{0}", sample.Point);
			           		}
			           	},
			           signed : true);
		}
		public void TestObliqueSkewedSource()
		{

			{
				// perfectly rectangular cuboid, oblique source
				var row = new Vector3D(1, 2, 3);
				var column = new Vector3D(7, 10, -9);
				var stack = row.Cross(column);

				var orientation = new DataSetOrientation(row, column, stack);
				TestVolume(VolumeFunction.Void, orientation.Initialize, null);
			}

			{
				// based on a real breast tomo MLO source - perfectly valid, and oblique w.r.t normal gantry-oriented calculations
				var row = new Vector3D(0, 1, 0);
				var column = new Vector3D(1, 0, 1);
				var stack = new Vector3D(-100, 0, 100);

				var orientation = new DataSetOrientation(row, column, stack);
				TestVolume(VolumeFunction.Void, orientation.Initialize, null);
			}

			{
				// column orientation skewed by 30 degreees from normal
				const double skewAngle = 30*_degreesInRadians;

				var row = new Vector3D(1, 2, 3);
				var column = new Vector3D(7, 10, -9);
				var stack = (float) Math.Cos(skewAngle)*row.Cross(column).Normalize() - (float) Math.Sin(skewAngle)*column.Normalize();

				var orientation = new DataSetOrientation(row, column, stack);
				TestVolume(VolumeFunction.Void, orientation.Initialize, null);
			}

			{
				// column orientation skewed by -30 degreees from normal
				const double skewAngle = -30*_degreesInRadians;

				var row = new Vector3D(1, 2, 3);
				var column = new Vector3D(7, 10, -9);
				var stack = (float) Math.Cos(skewAngle)*row.Cross(column).Normalize() - (float) Math.Sin(skewAngle)*column.Normalize();

				var orientation = new DataSetOrientation(row, column, stack);
				TestVolume(VolumeFunction.Void, orientation.Initialize, null);
			}

			try
			{
				// row orientation skewed by 30 degreees from normal
				const double skewAngle = 30*_degreesInRadians;

				var row = new Vector3D(1, 2, 3);
				var column = new Vector3D(7, 10, -9);
				var stack = (float) Math.Cos(skewAngle)*row.Cross(column).Normalize() - (float) Math.Sin(skewAngle)*row.Normalize();

				var orientation = new DataSetOrientation(row, column, stack);
				TestVolume(VolumeFunction.Void, orientation.Initialize, null);

				Assert.Fail("Expected an exception of type {0}", typeof (UnsupportedGantryTiltAxisException));
			}
			catch (UnsupportedGantryTiltAxisException) {}

			try
			{
				// row orientation skewed by -30 degreees from normal
				const double skewAngle = -30*_degreesInRadians;

				var row = new Vector3D(1, 2, 3);
				var column = new Vector3D(7, 10, -9);
				var stack = (float) Math.Cos(skewAngle)*row.Cross(column).Normalize() - (float) Math.Sin(skewAngle)*row.Normalize();

				var orientation = new DataSetOrientation(row, column, stack);
				TestVolume(VolumeFunction.Void, orientation.Initialize, null);

				Assert.Fail("Expected an exception of type {0}", typeof (UnsupportedGantryTiltAxisException));
			}
			catch (UnsupportedGantryTiltAxisException) {}

			try
			{
				// column orientation skewed by -30 degreees from normal, then further row skewed by 20 degrees
				const double skewAngle1 = -30*_degreesInRadians;
				const double skewAngle2 = 20*_degreesInRadians;

				var row = new Vector3D(1, 2, 3);
				var column = new Vector3D(7, 10, -9);
				var temp = (float) Math.Cos(skewAngle1)*row.Cross(column).Normalize() - (float) Math.Sin(skewAngle1)*column.Normalize();
				var stack = (float) Math.Cos(skewAngle2)*temp.Normalize() - (float) Math.Sin(skewAngle2)*row.Normalize();

				var orientation = new DataSetOrientation(row, column, stack);
				TestVolume(VolumeFunction.Void, orientation.Initialize, null);

				Assert.Fail("Expected an exception of type {0}", typeof (UnsupportedGantryTiltAxisException));
			}
			catch (UnsupportedGantryTiltAxisException) {}
		}