Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adding median3d and dezinger3d filters into tomopy.misc.corr #596

Merged
merged 24 commits into from Jan 11, 2023
Merged
Show file tree
Hide file tree
Changes from 11 commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
8828b6a
work on adding median/dezinger3d has started
dkazanc Dec 19, 2022
fac87c5
working version of the wrapper
dkazanc Jan 2, 2023
59446ee
added utils files
dkazanc Jan 2, 2023
b053d4d
completes implementation of median and dezinger 3d, tests added
dkazanc Jan 4, 2023
65f1779
reverting Packages
dkazanc Jan 4, 2023
01326ac
DOC: Add some text to docstrings
carterbox Jan 4, 2023
6ac0084
BLD: Use modern CMake to link OpenMP
carterbox Jan 5, 2023
464868d
BLD: Address compiler warning
carterbox Jan 5, 2023
2aa7271
STY: Format all new code with clang-format, yapf
carterbox Jan 5, 2023
c43b5eb
STY: Run clang-tidy on new code
carterbox Jan 5, 2023
77b4340
resolving suggestions
dkazanc Jan 5, 2023
26211e4
Use more concise conversion from size to half_filter width
carterbox Jan 5, 2023
b931cb4
REF: Use longlong for any linear index of volume
carterbox Jan 6, 2023
51566bb
adds 2D version of the filter, fixes suggestions and changes the test
dkazanc Jan 9, 2023
5a5ec1c
2D filtering has been removed
dkazanc Jan 10, 2023
03e9274
Require OpenMP_C
carterbox Jan 10, 2023
a7b12ff
BLD: Don't shadow OpenMP link with project flags
carterbox Jan 10, 2023
074c009
BLD: Move math.h public link to correct module
carterbox Jan 10, 2023
9c564b4
STY: Formatting and unused includes
carterbox Jan 10, 2023
bee4e18
REF: Remove some functions from public API
carterbox Jan 10, 2023
f3c0500
STY: Update docstrings for new python functions
carterbox Jan 10, 2023
f0b0506
BLD: Add openmp:experimental on Windows
carterbox Jan 10, 2023
8eedf30
BUG: Readd stdlib.h to includes
carterbox Jan 10, 2023
c4b321a
Merge branch 'master' into median
dkazanc Jan 11, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
68 changes: 68 additions & 0 deletions include/libtomo/median_filt3d.h
@@ -0,0 +1,68 @@
// Copyright (c) 2015, UChicago Argonne, LLC. All rights reserved.

// Copyright 2015. UChicago Argonne, LLC. This software was produced
// under U.S. Government contract DE-AC02-06CH11357 for Argonne National
// Laboratory (ANL), which is operated by UChicago Argonne, LLC for the
// U.S. Department of Energy. The U.S. Government has rights to use,
// reproduce, and distribute this software. NEITHER THE GOVERNMENT NOR
// UChicago Argonne, LLC MAKES ANY WARRANTY, EXPRESS OR IMPLIED, OR
// ASSUMES ANY LIABILITY FOR THE USE OF THIS SOFTWARE. If software is
// modified to produce derivative works, such modified software should
// be clearly marked, so as not to confuse it with the version available
// from ANL.

// Additionally, redistribution and use in source and binary forms, with
// or without modification, are permitted provided that the following
// conditions are met:

// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.

// * Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in
// the documentation and/or other materials provided with the
// distribution.

// * Neither the name of UChicago Argonne, LLC, Argonne National
// Laboratory, ANL, the U.S. Government, nor the names of its
// contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.

// THIS SOFTWARE IS PROVIDED BY UChicago Argonne, LLC AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL UChicago
// Argonne, LLC OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.

// C-module for median filtration and dezingering (3D and 2D case)
// Original author: Daniil Kazantsev, Diamond Light Source Ltd.

#pragma once

#ifdef WIN32
# define DLL __declspec(dllexport)
#else
# define DLL
#endif

DLL int
medianfilter_main_float(float* Input, float* Output, int radius, float mu_threshold,
int ncores, int dimX, int dimY, int dimZ);
DLL int
medianfilter_main_uint16(unsigned short* Input, unsigned short* Output, int radius,
float mu_threshold, int ncores, int dimX, int dimY, int dimZ);
DLL void
medfilt3D_float(float* Input, float* Output, int radius, int sizefilter_total,
float mu_threshold, long i, long j, long k, long index, long dimX,
long dimY, long dimZ);
DLL void
medfilt3D_uint16(unsigned short* Input, unsigned short* Output, int radius,
int sizefilter_total, float mu_threshold, long i, long j, long k,
long index, long dimX, long dimY, long dimZ);
21 changes: 18 additions & 3 deletions source/libtomo/misc/CMakeLists.txt
@@ -1,7 +1,22 @@
set(HEADERS "${tomopy_SOURCE_DIR}/include/libtomo/morph.h"
"${tomopy_SOURCE_DIR}/include/libtomo/remove_ring.h")
set(HEADERS
"${tomopy_SOURCE_DIR}/include/libtomo/morph.h"
"${tomopy_SOURCE_DIR}/include/libtomo/remove_ring.h"
"${tomopy_SOURCE_DIR}/include/libtomo/median_filt3d.h")

tomopy_add_library(tomo-misc SHARED morph.c remove_ring.c ${HEADERS})
tomopy_add_library(
tomo-misc
SHARED
morph.c
remove_ring.c
median_filt3d.c
utils.c
utils.h
${HEADERS})

find_package(OpenMP REQUIRED)
if(OpenMP_C_FOUND)
target_link_libraries(tomo-misc PUBLIC OpenMP::OpenMP_C)
endif()
carterbox marked this conversation as resolved.
Show resolved Hide resolved

target_include_directories(
tomo-misc
Expand Down
251 changes: 251 additions & 0 deletions source/libtomo/misc/median_filt3d.c
@@ -0,0 +1,251 @@
// Copyright (c) 2015, UChicago Argonne, LLC. All rights reserved.

// Copyright 2015. UChicago Argonne, LLC. This software was produced
// under U.S. Government contract DE-AC02-06CH11357 for Argonne National
// Laboratory (ANL), which is operated by UChicago Argonne, LLC for the
// U.S. Department of Energy. The U.S. Government has rights to use,
// reproduce, and distribute this software. NEITHER THE GOVERNMENT NOR
// UChicago Argonne, LLC MAKES ANY WARRANTY, EXPRESS OR IMPLIED, OR
// ASSUMES ANY LIABILITY FOR THE USE OF THIS SOFTWARE. If software is
// modified to produce derivative works, such modified software should
// be clearly marked, so as not to confuse it with the version available
// from ANL.

// Additionally, redistribution and use in source and binary forms, with
// or without modification, are permitted provided that the following
// conditions are met:

// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.

// * Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in
// the documentation and/or other materials provided with the
// distribution.

// * Neither the name of UChicago Argonne, LLC, Argonne National
// Laboratory, ANL, the U.S. Government, nor the names of its
// contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.

// THIS SOFTWARE IS PROVIDED BY UChicago Argonne, LLC AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL UChicago
// Argonne, LLC OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.

// C-module for median filtration and dezingering (3D and 2D cases)
// Original author: Daniil Kazantsev, Diamond Light Source Ltd.

#include "omp.h"
#include <math.h>
#include <memory.h>
#include <stdio.h>
#include <stdlib.h>

#include "libtomo/median_filt3d.h"
#include "utils.h"

DLL int
medianfilter_main_float(float* Input, float* Output, int radius, float mu_threshold,
int ncores, int dimX, int dimY, int dimZ)
{
int sizefilter_total;
int diameter;
long i;
long j;
long k;
long index;

diameter = (2 * radius + 1); /* diameter of the filter's kernel */
if(mu_threshold != 0.0)
{
copyIm(Input, Output, (long) (dimX), (long) (dimY), (long) (dimZ));
} /* copy input into output */

/* dealing here with a custom given number of cpu threads */
if(ncores > 0)
{
// Explicitly disable dynamic teams
omp_set_dynamic(0);
// Use a number of threads for all consecutive parallel regions
omp_set_num_threads(ncores);
}
/* 3D filtering */
sizefilter_total = (int) (powf(diameter, 3));
#pragma omp parallel for shared(Input, Output) private(i, j, k, index)
for(k = 0; k < dimZ; k++)
{
for(j = 0; j < dimY; j++)
{
for(i = 0; i < dimX; i++)
{
index = ((dimX * dimY) * k + j * dimX + i);
medfilt3D_float(Input, Output, radius, sizefilter_total, mu_threshold, i,
j, k, index, (long) (dimX), (long) (dimY), (long) (dimZ));
}
}
}
return 0;
}

DLL int
medianfilter_main_uint16(unsigned short* Input, unsigned short* Output, int radius,
float mu_threshold, int ncores, int dimX, int dimY, int dimZ)
{
int sizefilter_total;
int diameter;
long i;
long j;
long k;
long index;

diameter = (2 * radius + 1); /* diameter of the filter's kernel */
if(mu_threshold != 0.0)
{
copyIm_unshort(Input, Output, (long) (dimX), (long) (dimY), (long) (dimZ));
} /* copy input into output */

/* dealing here with a custom given number of cpu threads */
if(ncores > 0)
{
// Explicitly disable dynamic teams
omp_set_dynamic(0);
// Use a number of threads for all consecutive parallel regions
omp_set_num_threads(ncores);
}
/* 3D filtering */
sizefilter_total = (int) (powf(diameter, 3));
#pragma omp parallel for shared(Input, Output) private(i, j, k, index)
for(k = 0; k < dimZ; k++)
{
for(j = 0; j < dimY; j++)
{
for(i = 0; i < dimX; i++)
{
index = ((dimX * dimY) * k + j * dimX + i);
medfilt3D_uint16(Input, Output, radius, sizefilter_total, mu_threshold, i,
j, k, index, (long) (dimX), (long) (dimY),
(long) (dimZ));
}
}
}
return 0;
}

void
medfilt3D_float(float* Input, float* Output, int radius, int sizefilter_total,
float mu_threshold, long i, long j, long k, long index, long dimX,
long dimY, long dimZ)
{
float* ValVec;
long i_m;
long j_m;
long k_m;
long i1;
long j1;
long k1;
long counter;
int midval;
midval = (sizefilter_total / 2);
ValVec = (float*) calloc(sizefilter_total, sizeof(float));

/* filling the allocated vector with the neighbouring values */
counter = 0L;
for(i_m = -radius; i_m <= radius; i_m++)
{
i1 = i + i_m;
if((i1 < 0) || (i1 >= dimX))
i1 = i;
for(j_m = -radius; j_m <= radius; j_m++)
{
j1 = j + j_m;
if((j1 < 0) || (j1 >= dimY))
j1 = j;
for(k_m = -radius; k_m <= radius; k_m++)
{
k1 = k + k_m;
if((k1 < 0) || (k1 >= dimZ))
k1 = k;
ValVec[counter] = Input[(dimX * dimY) * k1 + j1 * dimX + i1];
counter++;
}
}
}
quicksort_float(ValVec, 0, sizefilter_total - 1); /* perform sorting */

if(mu_threshold == 0.0F)
{
/* perform median filtration */
Output[index] = ValVec[midval];
}
else
{
/* perform dezingering */
if(fabsf(Input[index] - ValVec[midval]) >= mu_threshold)
Output[index] = ValVec[midval];
}
free(ValVec);
}

void
medfilt3D_uint16(unsigned short* Input, unsigned short* Output, int radius,
int sizefilter_total, float mu_threshold, long i, long j, long k,
long index, long dimX, long dimY, long dimZ)
{
unsigned short* ValVec;
long i_m;
long j_m;
long k_m;
long i1;
long j1;
long k1;
long counter;
int midval;
midval = (sizefilter_total / 2);
ValVec = (unsigned short*) calloc(sizefilter_total, sizeof(unsigned short));

/* filling the allocated vector with the neighbouring values */
counter = 0L;
for(i_m = -radius; i_m <= radius; i_m++)
{
i1 = i + i_m;
if((i1 < 0) || (i1 >= dimX))
i1 = i;
for(j_m = -radius; j_m <= radius; j_m++)
{
j1 = j + j_m;
if((j1 < 0) || (j1 >= dimY))
j1 = j;
for(k_m = -radius; k_m <= radius; k_m++)
{
k1 = k + k_m;
if((k1 < 0) || (k1 >= dimZ))
k1 = k;
ValVec[counter] = Input[(dimX * dimY) * k1 + j1 * dimX + i1];
counter++;
}
}
}
quicksort_uint16(ValVec, 0, sizefilter_total - 1); /* perform sorting */

if(mu_threshold == 0.0F)
{
/* perform median filtration */
Output[index] = ValVec[midval];
}
else
{
/* perform dezingering */
if(abs(Input[index] - ValVec[midval]) >= mu_threshold)
Output[index] = ValVec[midval];
}
free(ValVec);
}