Skip to content

Commit b4a413c

Browse files
committed
New test file added
1 parent 4fbe07f commit b4a413c

File tree

5 files changed

+96
-43
lines changed

5 files changed

+96
-43
lines changed

src/algorithm/APRConverter.hpp

Lines changed: 5 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -104,15 +104,13 @@ bool APRConverter<ImageType>::get_apr_method(APR<ImageType> &aAPR, MeshData<T>&
104104

105105
//assuming uint16, the total memory cost shoudl be approximately (1 + 1 + 1/8 + 2/8 + 2/8) = 2 5/8 original image size in u16bit
106106
//storage of the particle cell tree for computing the pulling scheme
107-
MeshData<ImageType> image_temp; // global image variable useful for passing between methods, or re-using memory (should be the only full sized copy of the image)
108-
MeshData<ImageType> grad_temp; // should be a down-sampled image
109-
MeshData<float> local_scale_temp; // Used as down-sampled images for some averaging steps where it is useful to not lose precision, or get over-flow errors
110-
MeshData<float> local_scale_temp2;
111-
112107
allocation_timer.start_timer("init and copy image");
113-
image_temp.init(input_image);
108+
MeshData<ImageType> image_temp(input_image, false /* don't copy */); // global image variable useful for passing between methods, or re-using memory (should be the only full sized copy of the image)
109+
MeshData<ImageType> grad_temp; // should be a down-sampled image
114110
grad_temp.initDownsampled(input_image.y_num, input_image.x_num, input_image.z_num, 0);
111+
MeshData<float> local_scale_temp; // Used as down-sampled images for some averaging steps where it is useful to not lose precision, or get over-flow errors
115112
local_scale_temp.initDownsampled(input_image.y_num, input_image.x_num, input_image.z_num);
113+
MeshData<float> local_scale_temp2;
116114
local_scale_temp2.initDownsampled(input_image.y_num, input_image.x_num, input_image.z_num);
117115
allocation_timer.stop_timer();
118116

@@ -126,7 +124,7 @@ bool APRConverter<ImageType>::get_apr_method(APR<ImageType> &aAPR, MeshData<T>&
126124
//offset image by factor (this is required if there are zero areas in the background with uint16_t and uint8_t images, as the Bspline co-efficients otherwise may be negative!)
127125
// Warning both of these could result in over-flow (if your image is non zero, with a 'buffer' and has intensities up to uint16_t maximum value then set image_type = "", i.e. uncomment the following line)
128126
float bspline_offset = 0;
129-
if(std::is_same<uint16_t, ImageType>::value){
127+
if (std::is_same<uint16_t, ImageType>::value) {
130128
bspline_offset = 100;
131129
image_temp.copyFromMeshWithUnaryOp(input_image, [=](const auto &a) { return (a + bspline_offset); });
132130
} else if (std::is_same<uint8_t, ImageType>::value){
@@ -227,15 +225,10 @@ void APRConverter<ImageType>::get_local_particle_cell_set(MeshData<ImageType> &g
227225

228226
template<typename ImageType>
229227
void APRConverter<ImageType>::get_gradient(MeshData<ImageType> &image_temp, MeshData<ImageType> &grad_temp, MeshData<float> &local_scale_temp, MeshData<float> &local_scale_temp2, float bspline_offset) {
230-
//
231228
// Bevan Cheeseman 2018
232-
//
233229
// Calculate the gradient from the input image. (You could replace this method with your own)
234-
//
235230
// Input: full sized image.
236-
//
237231
// Output: down-sampled by 2 gradient magnitude (Note, the gradient is calculated at pixel level then maximum down sampled within the loops below)
238-
//
239232

240233
fine_grained_timer.verbose_flag = false;
241234

src/algorithm/ComputeGradient.hpp

Lines changed: 42 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@
66
#define PARTPLAY_GRADIENT_HPP
77

88
#include "src/data_structures/Mesh/MeshData.hpp"
9+
#include "src/io/TiffUtils.hpp"
10+
911
#ifdef HAVE_OPENMP
1012
#include "omp.h"
1113
#endif
@@ -720,7 +722,7 @@ void ComputeGradient::get_smooth_bspline_3D(MeshData<T>& input,APRParameters& pa
720722
}
721723

722724
template<typename T,typename S>
723-
void ComputeGradient::calc_bspline_fd_ds_mag(MeshData<T> &input, MeshData<S> &grad, const float hx, const float hy,const float hz){
725+
void ComputeGradient::calc_bspline_fd_ds_mag(MeshData<T> &input, MeshData<S> &grad, const float hx, const float hy,const float hz) {
724726
//
725727
// Bevan Cheeseman 2016
726728
//
@@ -733,52 +735,62 @@ void ComputeGradient::calc_bspline_fd_ds_mag(MeshData<T> &input, MeshData<S> &gr
733735
const size_t x_num_ds = grad.x_num;
734736
const size_t y_num_ds = grad.y_num;
735737

736-
const float a1 = -1.0/2.0;
737-
const float a3 = 1.0/2.0;
738-
739-
std::vector<S> temp(y_num,0);
738+
std::vector<S> temp(y_num, 0);
740739
const size_t xnumynum = x_num * y_num;
741740

741+
// 4 4
742+
// 2 1,3 ... 1 2 3 ...
743+
// 5 5
742744
#ifdef HAVE_OPENMP
743-
#pragma omp parallel for default(shared)firstprivate(temp)
745+
#pragma omp parallel for default(shared) firstprivate(temp)
744746
#endif
745-
for (size_t j = 0;j < z_num; ++j) {
746-
S *temp_vec_1 = input.mesh.begin() + j*x_num*y_num + 1*y_num;
747-
S *temp_vec_2 = input.mesh.begin() + j*x_num*y_num;
747+
for (size_t j = 0; j < z_num; ++j) {
748+
S *left = input.mesh.begin() + j * xnumynum + 1 * y_num;
749+
S *center = input.mesh.begin() + j * xnumynum;
748750

749751
//LHS boundary condition is accounted for wiht this initialization
750752
const size_t j_m = j > 0 ? j - 1 : 0;
751-
const size_t j_p = std::min(z_num-1, j+1);
752-
753-
for (size_t i = 0; i < x_num-1; ++i) {
754-
S *temp_vec_4 = input.mesh.begin() + j_m*xnumynum + i * y_num;
755-
S *temp_vec_5 = input.mesh.begin() + j_p*xnumynum + i * y_num;
756-
S *temp_vec_3 = input.mesh.begin() + j*x_num*y_num + (i+1)*y_num;
753+
const size_t j_p = std::min(z_num - 1, j + 1);
754+
float g[x_num][y_num];
755+
for (size_t i = 0; i < x_num - 1; ++i) {
756+
S *up = input.mesh.begin() + j_m * xnumynum + i * y_num;
757+
S *down = input.mesh.begin() + j_p * xnumynum + i * y_num;
758+
S *right = input.mesh.begin() + j * xnumynum + (i + 1) * y_num;
757759

758760
//compute the boundary values
759-
temp[0] = sqrt(pow((a1*temp_vec_1[0] + a3*temp_vec_3[0])/hx,2.0) + pow((a1*temp_vec_4[0] + a3*temp_vec_5[0])/hz,2.0));
760-
761+
temp[0] = sqrt(pow((right[0] - left[0]) / (2 * hx), 2.0) + pow((down[0] - up[0]) / (2 * hz), 2.0));
762+
g[0][i] = temp[0];
761763
//do the y gradient
762-
#ifdef HAVE_OPENMP
763-
#pragma omp simd
764-
#endif
765-
for (size_t k = 1; k < (y_num-1); ++k) {
766-
temp[k] = sqrt(pow((a1*temp_vec_4[k] + a3*temp_vec_5[k])/hz,2.0) + pow((a1*temp_vec_2[k-1] + a3*temp_vec_2[k+1])/hy,2.0) + pow((a1*temp_vec_1[k] + a3*temp_vec_3[k])/hx,2.0));
764+
#ifdef HAVE_OPENMP
765+
#pragma omp simd
766+
#endif
767+
for (size_t k = 1; k < y_num - 1; ++k) {
768+
temp[k] = sqrt(pow((right[k] - left[k]) / (2 * hx), 2.0) + pow((down[k] - up[k]) / (2 * hz), 2.0) +
769+
pow((center[k + 1] - center[k - 1]) / (2 * hy), 2.0));
770+
g[k][i] = temp[k];
767771
}
768772

769-
temp[y_num - 1] = sqrt(pow((a1*temp_vec_1[(y_num-1)] + a3*temp_vec_3[(y_num-1)])/hx,2.0) + pow((a1*temp_vec_4[(y_num-1)] + a3*temp_vec_5[(y_num-1)])/hz,2.0));
773+
temp[y_num - 1] = sqrt(pow((right[y_num - 1] - left[y_num - 1]) / (2 * hx), 2.0) +
774+
pow((down[y_num - 1] - up[y_num - 1]) / (2 * hz), 2.0));
775+
g[y_num - 1][i] = temp[y_num - 1];
770776

771-
int64_t j_2 = j/2;
772-
int64_t i_2 = i/2;
773-
774-
for (size_t k = 0; k < (y_num_ds); ++k) {
775-
size_t k_s = std::min(2*k+1, y_num-1);
777+
int64_t j_2 = j / 2;
778+
int64_t i_2 = i / 2;
779+
for (size_t k = 0; k < y_num_ds; ++k) {
780+
size_t k_s = std::min(2 * k + 1, y_num - 1);
776781
const size_t idx = j_2 * x_num_ds * y_num_ds + i_2 * y_num_ds + k;
777782
grad.mesh[idx] = std::max(temp[2 * k], std::max(temp[k_s], grad.mesh[idx]));
778783
}
779784

780-
std::swap(temp_vec_1, temp_vec_2);
781-
std::swap(temp_vec_2, temp_vec_3);
785+
// move left, center to current center, right (both +1 to right)
786+
std::swap(left, center);
787+
std::swap(center, right);
788+
}
789+
for (int y = 0; y < y_num; ++y) {
790+
for (int x = 0; x < x_num; ++x) {
791+
std::cout << g[y][x] << " ";
792+
}
793+
std::cout << "\n";
782794
}
783795
}
784796
}

src/data_structures/Mesh/MeshData.hpp

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -306,6 +306,33 @@ public :
306306
init(y_num_ds, x_num_ds, z_num_ds, aInitVal);
307307
}
308308

309+
/**
310+
* Initializes mesh with size of half of provided mesh dimensions (rounding up if not divisible by 2)
311+
* @param aMesh - mesh used to get dimensions
312+
*/
313+
template <typename U>
314+
void initDownsampled(const MeshData<U> &aMesh) {
315+
const int z_num_ds = ceil(1.0*aMesh.z_num/2.0);
316+
const int x_num_ds = ceil(1.0*aMesh.x_num/2.0);
317+
const int y_num_ds = ceil(1.0*aMesh.y_num/2.0);
318+
319+
init(y_num_ds, x_num_ds, z_num_ds);
320+
}
321+
322+
/**
323+
* Initializes mesh with size of half of provided mesh dimensions (rounding up if not divisible by 2) and initialize values
324+
* @param aMesh - mesh used to get dimensions
325+
* @param aInitVal
326+
*/
327+
template <typename U>
328+
void initDownsampled(const MeshData<U> &aMesh, T aInitVal) {
329+
const int z_num_ds = ceil(1.0*aMesh.z_num/2.0);
330+
const int x_num_ds = ceil(1.0*aMesh.x_num/2.0);
331+
const int y_num_ds = ceil(1.0*aMesh.y_num/2.0);
332+
333+
init(y_num_ds, x_num_ds, z_num_ds, aInitVal);
334+
}
335+
309336
/**
310337
* Swaps data of meshes this <-> aObj
311338
* @param aObj

test/CMakeLists.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
add_executable(testMeshData MeshDataTest.cpp)
22
add_executable(testTiff TiffTest.cpp)
33
add_executable(testAPR APRTest.cpp)
4+
add_executable(testComputeGradient ComputeGradientTest.cpp)
45

56
target_link_libraries(testMeshData ${GTEST_LIBRARIES} libapr)
67
target_link_libraries(testTiff ${GTEST_LIBRARIES} libapr)
78
target_link_libraries(testAPR ${GTEST_LIBRARIES} libapr)
9+
target_link_libraries(testComputeGradient ${GTEST_LIBRARIES} libapr)

test/MeshDataTest.cpp

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -170,7 +170,7 @@ namespace {
170170
}
171171
}
172172

173-
TEST_F(MeshDataTest, PreallocateTest) {
173+
TEST_F(MeshDataTest, InitDownsampledTest) {
174174
{
175175
MeshData<int> md;
176176
md.initDownsampled(3, 5, 7);
@@ -189,6 +189,25 @@ namespace {
189189
int size = 2 * 3 * 4;
190190
ASSERT_EQ(md.mesh.size(), size);
191191
}
192+
{
193+
MeshData<int> md;
194+
md.initDownsampled(MeshData<char>(4, 6, 8));
195+
ASSERT_EQ(md.y_num, 2);
196+
ASSERT_EQ(md.x_num, 3);
197+
ASSERT_EQ(md.z_num, 4);
198+
int size = 2 * 3 * 4;
199+
ASSERT_EQ(md.mesh.size(), size);
200+
}
201+
{
202+
MeshData<int> md;
203+
md.initDownsampled(MeshData<float>(3, 5, 7), 2);
204+
ASSERT_EQ(md.y_num, 2);
205+
ASSERT_EQ(md.x_num, 3);
206+
ASSERT_EQ(md.z_num, 4);
207+
int size = 2 * 3 * 4;
208+
ASSERT_EQ(md.mesh.size(), size);
209+
for (size_t i = 0; i < md.mesh.size(); ++i) ASSERT_EQ(md.mesh[i], 2);
210+
}
192211
}
193212

194213
TEST(MeshDataSimpleTest, UnaryOpTest) {

0 commit comments

Comments
 (0)