package edu.stanford.rsl.conrad.cuda;
import java.util.Random;
import org.junit.Test;
import edu.stanford.rsl.conrad.filtering.multiprojection.anisotropic.AnisotropicFilterFunction;
import edu.stanford.rsl.conrad.utils.Configuration;
import edu.stanford.rsl.conrad.volume3d.ParallelVolumeOperator;
import edu.stanford.rsl.conrad.volume3d.Volume3D;
import edu.stanford.rsl.conrad.volume3d.VolumeOperator;
public class CUDAVolumeTest {
protected int [] size = {130, 152, 124};
protected float [] dim = {1f, 1f, 1f};
protected CUDAVolumeOperator cuop = new CUDAVolumeOperator();
protected VolumeOperator op = new ParallelVolumeOperator();
protected void assertVolumeEquality(Volume3D one, Volume3D two){
op.subtractVolume(one, two);
op.abs(one);
double maxAbsoluteError = op.max(one);
System.out.println("Max Error: " + maxAbsoluteError);
org.junit.Assert.assertTrue(maxAbsoluteError < 0.00001);
}
protected void assertWeakVolumeEquality(Volume3D one, Volume3D two){
op.subtractVolume(one, two);
op.abs(one);
double maxAbsoluteError = op.mean(one);
System.out.println("Mean Error: " + maxAbsoluteError);
org.junit.Assert.assertTrue(maxAbsoluteError < 0.001);
}
protected void assertVolumeDifference(Volume3D one, Volume3D two){
op.subtractVolume(one, two);
op.abs(one);
double maxAbsoluteError = op.max(one);
org.junit.Assert.assertFalse(maxAbsoluteError < 0.000001);
}
public CUDAVolume3D createCUDACopy (Volume3D vol){
CUDAVolume3D cudaVol = (CUDAVolume3D) cuop.createVolume(size, dim, 1);
float [][][] temp = cudaVol.data;
cudaVol.data = vol.data;
cudaVol.updateOnDevice();
cudaVol.data = temp;
return cudaVol;
}
@Test
public void testMax(){
Configuration.loadConfiguration();
Volume3D one = createRandomVolume();
cuop.initCUDA();
CUDAVolume3D cudaVol = createCUDACopy(one);
float cpu = op.max(one);
float gpu = cuop.max(cudaVol);
cudaVol.fetch();
org.junit.Assert.assertTrue(cpu == gpu);
cudaVol.destroy();
one.destroy();
}
@Test
public void testMin(){
Configuration.loadConfiguration();
Volume3D one = createRandomVolume();
cuop.initCUDA();
CUDAVolume3D cudaVol = createCUDACopy(one);
float cpu = op.min(one);
float gpu = cuop.min(cudaVol);
cudaVol.fetch();
org.junit.Assert.assertTrue(cpu == gpu);
cudaVol.destroy();
one.destroy();
}
@Test
public void testMean(){
Configuration.loadConfiguration();
Volume3D one = createRandomVolume();
cuop.initCUDA();
CUDAVolume3D cudaVol = createCUDACopy(one);
float cpu = op.mean(one);
float gpu = cuop.mean(cudaVol);
cudaVol.fetch();
//System.out.println(cpu + " " + gpu);
org.junit.Assert.assertTrue(Math.abs(cpu - gpu) < 0.00001);
cudaVol.destroy();
one.destroy();
}
@Test
public void testAbs(){
Configuration.loadConfiguration();
Volume3D one = createRandomVolume();
cuop.initCUDA();
CUDAVolume3D cudaVol = createCUDACopy(one);
op.abs(one);
cuop.abs(cudaVol);
cudaVol.fetch();
assertVolumeEquality(one, cudaVol);
cudaVol.destroy();
one.destroy();
}
@Test
public void testAddScalar(){
Configuration.loadConfiguration();
Volume3D one = createRandomVolume();
cuop.initCUDA();
CUDAVolume3D cudaVol = createCUDACopy(one);
op.addScalar(one, 1.0f, 0.0f);
cuop.addScalar(cudaVol, 1.0f, 0.0f);
cudaVol.fetch();
assertVolumeEquality(one, cudaVol);
cudaVol.destroy();
one.destroy();
}
@Test
public void testAddVolume(){
Configuration.loadConfiguration();
Volume3D one = createRandomVolume();
Volume3D two = createRandomVolume();
cuop.initCUDA();
CUDAVolume3D cudaVol = createCUDACopy(one);
CUDAVolume3D cudaVol2 = createCUDACopy(two);
op.addVolume(one, two);
cuop.addVolume(cudaVol, cudaVol2);
cudaVol.fetch();
assertVolumeEquality(one, cudaVol);
cudaVol.destroy();
cudaVol2.destroy();
one.destroy();
two.destroy();
}
@Test
public void testAddVolumeWeight(){
Configuration.loadConfiguration();
Volume3D one = createRandomVolume();
Volume3D two = createRandomVolume();
cuop.initCUDA();
CUDAVolume3D cudaVol = createCUDACopy(one);
CUDAVolume3D cudaVol2 = createCUDACopy(two);
op.addVolume(one, two, 2.0);
cuop.addVolume(cudaVol, cudaVol2, 2.0);
cudaVol.fetch();
assertVolumeEquality(one, cudaVol);
cudaVol.destroy();
cudaVol2.destroy();
one.destroy();
two.destroy();
}
@Test
public void testCreateHighPassFilter(){
Configuration.loadConfiguration();
Volume3D one = op.createHighPassFilter(3, size, dim, 2, 1.5f);
cuop.initCUDA();
CUDAVolume3D cudaVol = (CUDAVolume3D) cuop.createHighPassFilter(3, size, dim, 2, 1.5f);
cudaVol.fetch();
assertVolumeEquality(one, cudaVol);
cudaVol.destroy();
one.destroy();
}
@Test
public void testCreateLowPassFilter(){
Configuration.loadConfiguration();
Volume3D one = op.createLowPassFilter(3, size, dim, 1.5f);
cuop.initCUDA();
CUDAVolume3D cudaVol = (CUDAVolume3D) cuop.createLowPassFilter(3, size, dim, 1.5f);
cudaVol.fetch();
assertVolumeEquality(one, cudaVol);
cudaVol.destroy();
one.destroy();
}
@Test
public void testCreateVolume(){
Configuration.loadConfiguration();
Volume3D vol = op.createVolume(size , dim, 1);
CUDAVolume3D cudaVol = (CUDAVolume3D) cuop.createVolume(size, dim, 1);
cudaVol.fetch();
assertVolumeEquality(vol, cudaVol);
cudaVol.destroy();
vol.destroy();
}
@Test
public void testDivideByVolume(){
Configuration.loadConfiguration();
Volume3D one = createRandomVolume();
Volume3D two = createRandomVolume();
op.multiplyScalar(one, 1000, 0);
op.addScalar(two, 10, 0);
cuop.initCUDA();
CUDAVolume3D cudaVol = createCUDACopy(one);
CUDAVolume3D cudaVol2 = createCUDACopy(two);
op.divideByVolume(one, two);
cuop.divideByVolume(cudaVol, cudaVol2);
cudaVol.fetch();
assertWeakVolumeEquality(one, cudaVol);
cudaVol.destroy();
cudaVol2.destroy();
one.destroy();
two.destroy();
}
@Test
public void testDivideScalar(){
Configuration.loadConfiguration();
Volume3D one = createRandomVolume();
cuop.initCUDA();
CUDAVolume3D cudaVol = createCUDACopy(one);
op.divideScalar(one, 3.0f, 0.0f);
cuop.divideScalar(cudaVol, 3.0f, 0.0f);
cudaVol.fetch();
assertVolumeEquality(one, cudaVol);
cudaVol.destroy();
one.destroy();
}
@Test
public void testFFTShift(){
Configuration.loadConfiguration();
Volume3D one = createRandomVolume();
cuop.initCUDA();
CUDAVolume3D cudaVol = createCUDACopy(one);
op.fftShift(one);
cuop.fftShift(cudaVol);
cudaVol.fetch();
assertVolumeEquality(one, cudaVol);
cudaVol.destroy();
one.destroy();
}
@Test
public void testfilt_cos2_quad(){
Configuration.loadConfiguration();
cuop.initCUDA();
float [] [] dirs = new float [6][3];
AnisotropicFilterFunction.filt_get_filt_dirs(3, dirs);
Volume3D one = op.createDirectionalWeights(3, size, dim, dirs[0], 1, VolumeOperator.FILTER_TYPE.QUADRATIC);
CUDAVolume3D cudaVol = (CUDAVolume3D) cuop.createDirectionalWeights(3, size, dim, dirs[0], 1, VolumeOperator.FILTER_TYPE.QUADRATIC);
cudaVol.fetch();
assertVolumeEquality(one, cudaVol);
cudaVol.destroy();
one.destroy();
}
@Test
public void testfilt_cos2r(){
Configuration.loadConfiguration();
cuop.initCUDA();
float [] [] dirs = new float [6][3];
AnisotropicFilterFunction.filt_get_filt_dirs(3, dirs);
Volume3D one = op.createExponentialDirectionalHighPassFilter(3, size, dim, dirs[0], 1, 2.0f, 1.5f, VolumeOperator.FILTER_TYPE.NORMAL);
CUDAVolume3D cudaVol = (CUDAVolume3D) cuop.createExponentialDirectionalHighPassFilter(3, size, dim, dirs[0], 1, 2.0f, 1.5f, VolumeOperator.FILTER_TYPE.NORMAL);
cudaVol.fetch();
assertVolumeEquality(one, cudaVol);
cudaVol.destroy();
one.destroy();
}
@Test
public void testfilt_cos2r_quad(){
Configuration.loadConfiguration();
cuop.initCUDA();
float [] [] dirs = new float [6][3];
AnisotropicFilterFunction.filt_get_filt_dirs(3, dirs);
Volume3D one = op.createExponentialDirectionalHighPassFilter(3, size, dim, dirs[0], 1, 2.0f, 1.5f, VolumeOperator.FILTER_TYPE.QUADRATIC);
CUDAVolume3D cudaVol = (CUDAVolume3D) cuop.createExponentialDirectionalHighPassFilter(3, size, dim, dirs[0], 1, 2.0f, 1.5f, VolumeOperator.FILTER_TYPE.QUADRATIC);
cudaVol.fetch();
assertVolumeEquality(one, cudaVol);
cudaVol.destroy();
one.destroy();
}
@Test
public void testfilt_gauss(){
Configuration.loadConfiguration();
cuop.initCUDA();
Volume3D one = op.createGaussLowPassFilter(3, size, dim, 2);
CUDAVolume3D cudaVol = (CUDAVolume3D) cuop.createGaussLowPassFilter(3, size, dim, 2);
cudaVol.fetch();
assertVolumeEquality(one, cudaVol);
cudaVol.destroy();
one.destroy();
}
@Test
public void testfilt_solve_max_eigenValue(){
Configuration.loadConfiguration();
cuop.initCUDA();
int [] size = {30, 30, 30};
this.size = size;
float [] [] dirs = new float [6][3];
AnisotropicFilterFunction.filt_get_filt_dirs(3, dirs);
Volume3D a11 = op.createExponentialDirectionalHighPassFilter(3, size, dim, dirs[0], 1, 2.0f, 1.5f, VolumeOperator.FILTER_TYPE.QUADRATIC);
Volume3D a12 = op.createExponentialDirectionalHighPassFilter(3, size, dim, dirs[1], 1, 2.0f, 1.5f, VolumeOperator.FILTER_TYPE.QUADRATIC);
Volume3D a13 = op.createExponentialDirectionalHighPassFilter(3, size, dim, dirs[2], 1, 2.0f, 1.5f, VolumeOperator.FILTER_TYPE.QUADRATIC);
Volume3D a22 = op.createExponentialDirectionalHighPassFilter(3, size, dim, dirs[3], 1, 2.0f, 1.5f, VolumeOperator.FILTER_TYPE.QUADRATIC);
Volume3D a23 = op.createExponentialDirectionalHighPassFilter(3, size, dim, dirs[4], 1, 2.0f, 1.5f, VolumeOperator.FILTER_TYPE.QUADRATIC);
Volume3D a33 = op.createExponentialDirectionalHighPassFilter(3, size, dim, dirs[5], 1, 2.0f, 1.5f, VolumeOperator.FILTER_TYPE.QUADRATIC);
op.real(a11);
op.real(a12);
op.real(a13);
op.real(a22);
op.real(a23);
op.real(a33);
Volume3D [][] st = new Volume3D[3][3];
st[0][0] = a11;
st[0][1] = a12;
st[0][2] = a13;
st[1][0] = a12;
st[1][1] = a22;
st[1][2] = a23;
st[2][0] = a13;
st[2][1] = a23;
st[2][2] = a33;
CUDAVolume3D ca11 = (CUDAVolume3D) cuop.createExponentialDirectionalHighPassFilter(3, size, dim, dirs[0], 1, 2.0f, 1.5f, VolumeOperator.FILTER_TYPE.QUADRATIC);
CUDAVolume3D ca12 = (CUDAVolume3D) cuop.createExponentialDirectionalHighPassFilter(3, size, dim, dirs[1], 1, 2.0f, 1.5f, VolumeOperator.FILTER_TYPE.QUADRATIC);
CUDAVolume3D ca13 = (CUDAVolume3D) cuop.createExponentialDirectionalHighPassFilter(3, size, dim, dirs[2], 1, 2.0f, 1.5f, VolumeOperator.FILTER_TYPE.QUADRATIC);
CUDAVolume3D ca22 = (CUDAVolume3D) cuop.createExponentialDirectionalHighPassFilter(3, size, dim, dirs[3], 1, 2.0f, 1.5f, VolumeOperator.FILTER_TYPE.QUADRATIC);
CUDAVolume3D ca23 = (CUDAVolume3D) cuop.createExponentialDirectionalHighPassFilter(3, size, dim, dirs[4], 1, 2.0f, 1.5f, VolumeOperator.FILTER_TYPE.QUADRATIC);
CUDAVolume3D ca33 = (CUDAVolume3D) cuop.createExponentialDirectionalHighPassFilter(3, size, dim, dirs[5], 1, 2.0f, 1.5f, VolumeOperator.FILTER_TYPE.QUADRATIC);
cuop.real(ca11);
cuop.real(ca12);
cuop.real(ca13);
cuop.real(ca22);
cuop.real(ca23);
cuop.real(ca33);
CUDAVolume3D [][] cst = new CUDAVolume3D[3][3];
cst[0][0] = ca11;
cst[0][1] = ca12;
cst[0][2] = ca13;
cst[1][1] = ca22;
cst[1][2] = ca23;
cst[2][2] = ca33;
//new ImageJ();
Volume3D one = op.solveMaximumEigenvalue(st);
//one.getImagePlus("CPU Result").show();
CUDAVolume3D cudaVol = (CUDAVolume3D) cuop.solveMaximumEigenvalue(cst);
cudaVol.fetch();
//cudaVol.getImagePlus("CUDA Result").show();
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
assertWeakVolumeEquality(one, cudaVol);
a11.destroy();
a12.destroy();
a13.destroy();
a22.destroy();
a23.destroy();
a33.destroy();
ca11.destroy();
ca12.destroy();
ca13.destroy();
ca22.destroy();
ca23.destroy();
ca33.destroy();
cudaVol.destroy();
one.destroy();
}
public Volume3D createRandomVolume(){
Volume3D vol = op.createVolume(size , dim, 1);
Random rand = new Random();
for (int i = 0; i < size[0]; i++)
for (int j = 0; j < size[1]; j++)
for (int k = 0; k < size[2]; k++) {
vol.data[i][j][k] = (rand.nextFloat() - 0.5f)*2;
}
return vol;
}
@Test
public void testRandomVolume(){
Volume3D one = createRandomVolume();
Volume3D two = createRandomVolume();
assertVolumeDifference(one, two);
}
}
/*
* Copyright (C) 2010-2014 - Andreas Maier
* CONRAD is developed as an Open Source project under the GNU General Public License (GPL).
*/