73 template <
typename KDATATYPE>
class TKernel {
295 template <
typename KDATATYPE2>
297 const KDATATYPE2 *
const xaxis,
const KDATATYPE2 *
const yaxis,
const KDATATYPE2 *
const zaxis,
298 const KDATATYPE2 *
const caxis,
const KDATATYPE2 *
const taxis,
const KDATATYPE2 *
const uaxis,
307 if (!xaxis || !yaxis || !zaxis || !caxis || !taxis || !uaxis){
314 KDATATYPE *valuematrix =
317 for (
MLint u=0; u<ext.
u; ++u){
318 for (
MLint t=0; t<ext.
t; ++t){
319 for (
MLint c=0; c<ext.
c; ++c){
320 for (
MLint z=0; z<ext.
z; ++z){
321 for (
MLint y=0; y<ext.
y; ++y){
322 for (
MLint x=0; x<ext.
x; ++x){
323 valuematrix[b++] =
static_cast<KDATATYPE
>(xaxis[x]*yaxis[y]*zaxis[z]*caxis[c]*taxis[t]*uaxis[u]);
372 static std::vector<KDATATYPE>
get1DGauss(
size_t numSamples,
bool normalize=
true);
498 KDATATYPE* _valueTab;
516 mutable bool _areSeparabilityInfosUpToDate;
536 mutable std::vector<ImageVector> _separableCoordTab;
552 template <
typename KDATATYPE>
561 template <
typename KDATATYPE>
571 template <
typename KDATATYPE>
580 template <
typename KDATATYPE>
592 _isSeparable = kern._isSeparable;
593 _areSeparabilityInfosUpToDate = kern._areSeparabilityInfosUpToDate;
594 _separableDimEntries = kern._separableDimEntries;
595 _separableOneDimExt = kern._separableOneDimExt;
596 _separableExt = kern._separableExt;
597 _separableNegExt = kern._separableNegExt;
598 _separablePosExt = kern._separablePosExt;
599 _separableCoordTab = kern._separableCoordTab;
609 template <
typename KDATATYPE>
623 template <
typename KDATATYPE>
643 template <
typename KDATATYPE>
655 template <
typename KDATATYPE>
664 template <
typename KDATATYPE>
669 for (
size_t i=0; i<_tabSize; i++){ v+=_valueTab[i]; }
677 template <
typename KDATATYPE>
681 KDATATYPE v = (_tabSize==0) ?
static_cast<KDATATYPE
>(0) : _valueTab[0];
682 for (
size_t i=1; i<_tabSize; i++){
if (_valueTab[i] < v){ v = _valueTab[i]; } }
690 template <
typename KDATATYPE>
694 KDATATYPE v = (_tabSize==0) ?
static_cast<KDATATYPE
>(1) : _valueTab[0];
695 for (
size_t i=1; i<_tabSize; i++){
if (_valueTab[i] > v){ v = _valueTab[i]; } }
704 template <
typename KDATATYPE>
708 for (
size_t i=0; i<_tabSize; i++){
710 if (!(_valueTab[i] > 0)){ v += _valueTab[i]; }
719 template <
typename KDATATYPE>
723 for (
size_t i=0; i<_tabSize; i++){
if (_valueTab[i] > 0){ v += _valueTab[i]; } }
731 template <
typename KDATATYPE>
740 for (
size_t i=0; i<_tabSize; i++){ _valueTab[i] = v; }
746 for (
size_t i=0; i<_tabSize; i++){ _valueTab[i] *= v; }
752 for (
size_t i=0; i<_tabSize; i++){ _valueTab[i] += v; }
758 for (
size_t i=0; i<_tabSize; i++){
if (!
MLValueIs0WOM(_valueTab[i])) {_valueTab[i] = v/_valueTab[i]; } }
764 for (
size_t i=0; i<_tabSize; i++){ _valueTab[i] = v-_valueTab[i]; }
770 for (
size_t i=0; i<_tabSize; i++){ _valueTab[i] *= _valueTab[i]; }
777 for (
size_t i=0; i<_tabSize; i++){
782 _valueTab[i] =
static_cast<KDATATYPE
>(
sqrt(
static_cast<double>(_valueTab[i])));
790 for (
size_t i=0; i<_tabSize; i++){
795 if ( (_valueTab[i] >
static_cast<KDATATYPE
>(0)) ||
MLValueIs0WOM(_valueTab[i]) ){
798 KDATATYPE buf =
static_cast<KDATATYPE
>(powl(_valueTab[i], v));
815 for (
size_t i=0; i<_tabSize; i++){
816 KDATATYPE val = _valueTab[i];
818 if (val > 0){ _valueTab[i] =
static_cast<KDATATYPE
>(
log(
static_cast<double>(val))*invBase); }
888 ML_PRINT_ERROR(
"TKernel<KDATATYPE>::manipulateKernelElements(mlKernModifier mode, KDATATYPE v)",
889 ML_PROGRAMMING_ERROR,
"NUM_KERN_MODIFYERS is an invalid parameter. Ignoring kernel manipulation.");
894 ML_PRINT_ERROR(
"TKernel<KDATATYPE>::manipulateKernelElements(mlKernModifier mode, KDATATYPE v)",
895 ML_BAD_PARAMETER,
"Invalid parameter passed. Ignoring kernel manipulation.");
912 template <
typename KDATATYPE>
917 return _separableExt;
930 template <
typename KDATATYPE>
935 return _separableNegExt;
945 template <
typename KDATATYPE>
950 return _separablePosExt;
961 template <
typename KDATATYPE>
970 template <
typename KDATATYPE>
979 template <
typename KDATATYPE>
988 template <
typename KDATATYPE>
997 template <
typename KDATATYPE>
1001 ext.
c-ext.
c/2-1, ext.
t-ext.
t/2-1, ext.
u-ext.
u/2-1);
1008 template <
typename KDATATYPE>
1012 for (
size_t c=0; c < _tabSize; c++){
1013 if (_coordTab[c] == pos){
1029 template <
typename KDATATYPE>
1036 _tabSize = numElems;
1042 _valueTab =
new KDATATYPE[_tabSize];
1045 for (
size_t c=0; c < _tabSize; c++){ _coordTab[c] = coords[c]; }
1050 memcpy(_valueTab, values, _tabSize*
sizeof(KDATATYPE));
1054 KDATATYPE v =
static_cast<KDATATYPE
>(1.0/
static_cast<KDATATYPE
>(_tabSize));
1055 for (
size_t d=0; d<_tabSize; d++){ _valueTab[d] = v; }
1096 template <
typename KDATATYPE>
1100 char strLine[256]=
"";
1103 if (fieldWidth > 128){ fieldWidth=128; }
1104 if (fieldWidth < 0){ fieldWidth=0; }
1114 snprintf(strLine, 255,
"(*,%lld,%lld,%lld,%lld,%lld):", y, z, c, t, u);
1119 while (strlen(strLine) < 16){ strcat(strLine,
" "); }
1134 strLine[0] = x==0 ?
' ' :
',';
1135 MLint w= x==0 ? fieldWidth : fieldWidth+1;
1136 for (
MLint i=1; i < w; i++){ strLine[i] =
' '; }
1146 snprintf(format, 63,
"%s%%%d.%dlf",
"%s",
static_cast<MLint32>(fieldWidth),
static_cast<MLint32>(precision));
1147 snprintf(strLine, 255, format, 0==x ?
"" :
",",
static_cast<MLdouble>(_valueTab[idx]));
1165 for (
size_t c=0; c < _tabSize; c++){
1167 KDATATYPE value = _valueTab[c];
1168 snprintf(strLine, 255,
"%s:%lf\n", coord.
print(
"(",
",",
")").c_str(),
static_cast<MLdouble>(value));
1214 template <
typename KDATATYPE>
1218 std::string errStr =
"";
1219 char *copy =
nullptr;
1225 if (kernString.length() < 15){
1232 std::string str = kernString;
1235 if (str[str.length()-1] !=
'\n'){ str +=
'\n'; }
1238 MLint lineNumber = 0;
1241 MLint x=0, y=0, z=0, c=0, t=0, u=0, num=0;
1243 num = sscanf(str.c_str(),
"(%lld,%lld,%lld,%lld,%lld,%lld):%lf", &x, &y, &z, &c, &t, &u, &fValue);
1244 KDATATYPE value =
static_cast<KDATATYPE
>(fValue);
1251 num = sscanf(str.c_str(),
"(*,%lld,%lld,%lld,%lld,%lld):", &y, &z, &c, &t, &u);
1254 const size_t cPos = str.find(
':');
1255 if (cPos != std::string::npos){
1257 str.erase(0, cPos+1);
1264 while (go && (str.length() != 0)){
1265 const char ch = str[0];
1273 else if (
'\n' == ch) {
1279 else if (
',' == ch) {
1288 char *stopPos=
nullptr;
1294 const MLdouble val = strtod(copy, &stopPos);
1297 if (stopPos != copy){
1303 str.erase(0, stopPos-copy);
1311 snprintf(err, 29,
" %lld", lineNumber);
1328 const size_t pos = str.find(
'\n');
1329 if (pos != std::string::npos){
1332 str.erase(0, pos+1);
1362 template <
typename KDATATYPE>
1369 size_t maxElems = ext.
compMul();
1374 for (
size_t c=0; c<maxElems; c++){
if (mask[c]){ _tabSize++; } }
1378 _tabSize = maxElems;
1384 _valueTab =
new KDATATYPE[_tabSize];
1385 if (!_coordTab || !_valueTab){
1388 "Cannot create kernel filter tables, so tables are reset. This will probably cause other errors.");
1391 if (_coordTab && _valueTab){
1395 memcpy(_valueTab, values, _tabSize*
sizeof(KDATATYPE));
1399 KDATATYPE v =
static_cast<KDATATYPE
>(1.0/
static_cast<KDATATYPE
>(_tabSize));
1400 for (
size_t d=0; d<_tabSize; d++){ _valueTab[d] = v; }
1406 for (
size_t e=0; e<maxElems; e++){
1407 if (!mask || (mask && mask[e])){
1413 if (idx !=_tabSize){
1415 "Internal error. Cannot create kernel filter tables. This will probably cause other errors.");
1435 template <
typename KDATATYPE>
1442 const size_t numRows = separableRows.size() > 6 ? 6 : separableRows.size();
1445 size_t numEntries = 0;
1446 for (
size_t e=0; e < numRows; ++e){ numEntries += separableRows[e].size(); }
1449 std::vector<KDATATYPE> valueTab; valueTab.reserve(numEntries);
1450 std::vector<ImageVector> coordTab; coordTab.reserve(numEntries);
1453 for (
size_t r=0; r < numRows; ++r){
1456 const std::vector<KDATATYPE> &row = separableRows[r];
1457 const size_t numRElements = row.size();
1465 for (
size_t re=0; re < numRElements; ++re){
1468 coordTab.push_back(entryCoord);
1469 valueTab.push_back(row[re]);
1488 template <
typename KDATATYPE>
1498 for (
MLint u=0; u < ext.
u; u++){
1499 for (
MLint t=0; t < ext.
t; t++){
1500 for (
MLint c=0; c < ext.
c; c++){
1501 for (
MLint z=0; z < ext.
z; z++){
1502 for (
MLint y=0; y < ext.
y; y++){
1503 for (
MLint x=0; x < ext.
x; x++){
1542 template <
typename KDATATYPE>
1584 template <
typename KDATATYPE>
1615 _coordTab =
nullptr;
1617 KDATATYPE *valueTab = _valueTab;
1618 _valueTab =
nullptr;
1620 size_t tabSize = _tabSize;
1626 for (
size_t e=0; e < tabSize; e++){
1637 if (
sqrt(px*px + py*py + pz*pz + pc*pc + pt*pt + pu*pu) <= 1){
1659 template <
typename KDATATYPE>
1667 _coordTab =
nullptr;
1669 KDATATYPE *valueTabBuf = _valueTab;
1670 _valueTab =
nullptr;
1672 size_t tabSizeBuf = _tabSize;
1679 if ((dimension<0) || (dimension>5)){
1684 for (
size_t e=0; e < tabSizeBuf; e++){
1691 for (
size_t e=0; e < tabSizeBuf; e++){
1693 mirVec = coordTabBuf[e];
1696 mirVec[dimensionSize_t] = maxP[dimensionSize_t] - coordTabBuf[e][dimensionSize_t];
1704 delete [] coordTabBuf;
1705 coordTabBuf =
nullptr;
1706 delete [] valueTabBuf;
1707 valueTabBuf =
nullptr;
1717 template <
typename KDATATYPE>
1725 if((k!=0) && (k!=n)){
1726 for (i=1; i<(n+1); i++){ v*=i; }
1727 for (i=1; i<(k+1); i++){ v/=i; }
1728 for (i=1; i<(n-k+1); i++){ v/=i; }
1741 template <
typename KDATATYPE>
1745 std::vector<KDATATYPE> v;
1747 if (numSamples > 0){
1748 v.reserve(numSamples);
1752 for (
size_t u=0; u<numSamples; ++u){
1755 KDATATYPE val =
static_cast<KDATATYPE
>(
binomialcoeff(numSamples-1, u));
1757 sum +=
static_cast<KDATATYPE
>(
mlAbs(val));
1761 if (normalize && (sum > 0)){
1762 for (
size_t u=0; u<numSamples; u++){ v[u] /= sum; }
1773 template <
typename KDATATYPE>
1783 std::vector<KDATATYPE> vx=
get1DGauss(ext.
x,
false);
1784 std::vector<KDATATYPE> vy=
get1DGauss(ext.
y,
false);
1785 std::vector<KDATATYPE> vz=
get1DGauss(ext.
z,
false);
1786 std::vector<KDATATYPE> vc=
get1DGauss(ext.
c,
false);
1787 std::vector<KDATATYPE> vt=
get1DGauss(ext.
t,
false);
1788 std::vector<KDATATYPE> vu=
get1DGauss(ext.
u,
false);
1792 setKernel(ext, &(vx[0]), &(vy[0]), &(vz[0]), &(vc[0]), &(vt[0]), &(vu[0]),
true);
1799 template <
typename KDATATYPE>
1808 _valueTab =
nullptr;
1809 _coordTab =
nullptr;
1812 _isSeparable =
false;
1813 _areSeparabilityInfosUpToDate =
false;
1814 _separableDimEntries.set(0);
1815 _separableOneDimExt.set(0);
1816 _separableExt.set(0);
1817 _separableNegExt.set(0);
1818 _separablePosExt.set(0);
1819 _separableCoordTab.clear();
1826 template <
typename KDATATYPE>
1833 _areSeparabilityInfosUpToDate =
false;
1835 delete [] _valueTab;
1837 _valueTab =
nullptr;
1838 delete [] _coordTab;
1839 _coordTab =
nullptr;
1849 template <
typename KDATATYPE>
1854 KDATATYPE *newValueTab =
nullptr;
1857 _areSeparabilityInfosUpToDate =
false;
1860 size_t newTabSize = _tabSize+1;
1863 newValueTab =
new KDATATYPE[_tabSize+1];
1866 if (!newCoordTab || !newValueTab){
1867 delete [] newCoordTab;
1868 newCoordTab =
nullptr;
1869 delete [] newValueTab;
1870 newValueTab =
nullptr;
1873 "Cannot create kernel tables. Returning with invalid "
1874 "reset tables. This will probably cause other errors.");
1880#if defined(__GNUC__)
1886#pragma GCC diagnostic push
1887#pragma GCC diagnostic ignored "-Wclass-memaccess"
1889 memcpy(newCoordTab, _coordTab, _tabSize *
sizeof(
ImageVector));
1890#if defined(__GNUC__)
1891#pragma GCC diagnostic pop
1893 memcpy(newValueTab, _valueTab, _tabSize *
sizeof(KDATATYPE));
1897 newCoordTab[_tabSize] = pos;
1898 newValueTab[_tabSize] = value;
1904 _tabSize = newTabSize;
1905 _coordTab = newCoordTab;
1906 _valueTab = newValueTab;
1919 template <
typename KDATATYPE>
1943 if (!_ext.allBiggerZero()){
1946 "Kernel has invalid extents now. Continuing anyway.");
1964 template <
typename KDATATYPE>
1968 if (_isSeparable != isSeparableVal){
1969 _isSeparable = isSeparableVal;
1978 template <
typename KDATATYPE>
1981 return _isSeparable;
1989 template <
typename KDATATYPE>
1993 return _separableDimEntries;
2003 template <
typename KDATATYPE>
2007 return _separableOneDimExt;
2018 template <
typename KDATATYPE>
2022 if (dim>5){ dim = 5; }
2028 case 1:
return static_cast<size_t>(_separableDimEntries.x);
2030 case 2:
return static_cast<size_t>(_separableDimEntries.x +
2031 _separableDimEntries.y);
2033 case 3:
return static_cast<size_t>(_separableDimEntries.x +
2034 _separableDimEntries.y +
2035 _separableDimEntries.z);
2037 case 4:
return static_cast<size_t>(_separableDimEntries.x +
2038 _separableDimEntries.y +
2039 _separableDimEntries.z +
2040 _separableDimEntries.c);
2042 case 5:
return static_cast<size_t>(_separableDimEntries.x +
2043 _separableDimEntries.y +
2044 _separableDimEntries.z +
2045 _separableDimEntries.c +
2046 _separableDimEntries.t);
2058 template <
typename KDATATYPE>
2062 return _separableCoordTab;
2068 template <
typename KDATATYPE>
2071 _areSeparabilityInfosUpToDate =
false;
2081 template <
typename KDATATYPE>
2085 if (_areSeparabilityInfosUpToDate){
return; }
2086 if (!_areSeparabilityInfosUpToDate){
2092 _separableDimEntries.set(0);
2093 _separableOneDimExt.set(0);
2094 _separableExt.set(0);
2095 _separableCoordTab.clear();
2098 while ((idx<_tabSize) && (_coordTab[idx].y < 6)){
2108 _separableDimEntries[entryY]++;
2113 if (entry.
x+1 > _separableOneDimExt[entryY]){ _separableOneDimExt[entryY] = entry.
x+1; }
2124 sepCoord[entryY] = entry.
x;
2125 _separableCoordTab.push_back(sepCoord);
2133 _separableExt = _separableOneDimExt;
2134 _separableExt.fillSmallerComps(1,1);
2142 for (
size_t e=0; e < idx; ++e){
2145 for (
size_t d=0; d < 6; ++d){
2147 if (coord[d] == -1){ coord[d] = negExt[d]; }
2157 _areSeparabilityInfosUpToDate =
true;
static void freeMemory(void *ptr)
static void * allocateMemory(MLuint numBytes, MLMemoryErrorHandling handleFailure)
static char * duplicateString(const char *str, MLMemoryErrorHandling handleFailure)
static MLEXPORT MLint coordToIndex(MLint x, MLint y, MLint z, MLint c, MLint t, MLint u, const ImageVector &size)
static MLEXPORT ImageVector indexToCoord(MLint index, const ImageVector &extent)
void set(const ComponentType v=0)
Sets all components to v or - if v is not specified - to 0.
virtual ~TKernel()
Destructor. Cleans up and removes instance of kernel.
void mirror(int dimension=-1)
std::string getKernel(bool asLines=false, MLint fieldWidth=0, MLint precision=10) const
const ImageVector & getPositiveExtent() const
See getNegativeExtent().
static ImageVector indexToCoord(MLint idx, const ImageVector &ext)
Converts an index into an array with extents ext to a coordinate.
static ImageVector calculateNegativeExtentFromExtent(const ImageVector &ext)
Calculate the negative extent of a kernel from a kernel extent.
static ImageVector calculatePositiveExtentFromExtent(const ImageVector &ext)
Calculate the positive extent of a kernel from a kernel extent.
void _invalidateSeparableInfos()
static MLldouble binomialcoeff(MLint n, MLint k)
void _init()
Initialization. Should be called only by constructors.
void fillUndefinedElements(KDATATYPE newVal=0)
Fill all undefined kernel elements with newVal.
static MLint coordToIndex(const ImageVector &p, const ImageVector &size)
Converts the coordinate into the kernel with extents size to an index.
void setPartialKernel(size_t numElems, ImageVector *const coords, KDATATYPE *const values=nullptr)
size_t getTabSize() const
Returns the current number of kernel elements.
ImageVector getSeparableDimEntries() const
KDATATYPE getMinValue() const
KDATATYPE getMaxValue() const
void setSeparable(bool isSeparableVal)
const TKernel & operator=(const TKernel &kern)
Assignment operator. Sets current instance to contents of kern.
void manipulateKernelElements(KernModifier mode, KDATATYPE v)
Modify all kernel element values with the value v.
TKernel()
Constructor. Builds an empty kernel.
static std::vector< KDATATYPE > get1DGauss(size_t numSamples, bool normalize=true)
std::string setKernel(const std::string &kernString)
void reset()
Reset kernel to construction state.
const ImageVector & getExtent() const
ImageVector getSeparableOneDimExtents() const
const std::vector< ImageVector > & getSeparableCoordTab() const
const KDATATYPE * getValueTab(size_t dim=0) const
MLint findIndex(const ImageVector &pos) const
KDATATYPE getValueTabSum() const
Return the sum of all kernel element values.
void setKernel(const ImageVector &ext, const KDATATYPE2 *const xaxis, const KDATATYPE2 *const yaxis, const KDATATYPE2 *const zaxis, const KDATATYPE2 *const caxis, const KDATATYPE2 *const taxis, const KDATATYPE2 *const uaxis, bool normalize)
static MLint coordToIndex(MLint x, MLint y, MLint z, MLint c, MLint t, MLint u, const ImageVector &size)
const ImageVector * getCoordTab(size_t dim=0) const
TKernel(const TKernel &kern)
Copy constructor. Builds a kernel with contents of kern.
void _addCoordinate(const ImageVector &pos, KDATATYPE value, bool update)
const ImageVector & getNegativeExtent() const
void _calculateRealKernelExt()
size_t getSeparableDimIndex(size_t dim=0) const
void setGauss(const ImageVector &ext)
Replaces the current kernel by a normalized gauss kernel.
KDATATYPE getNegativeValueSum() const
KDATATYPE getPositiveValueSum() const
void setKernel(const ImageVector &ext, const KDATATYPE *const values=nullptr, bool *const mask=nullptr)
void _validateSeparabilityInfos() const
void setSeparableKernel(const std::vector< typename std::vector< KDATATYPE > > &separableRows)
void resizeKernel(const ImageVector &ext, KDATATYPE newVal=0)
ComponentType c
Color component of the vector.
ComponentType t
Time component of the vector.
ComponentType u
Unit/Modality/User component of the vector.
ComponentType z
Z component of the vector.
ComponentType x
X component of the vector.
ComponentType y
Y component of the vector.
TVector< TVector6DBase< MLint > > compMax(const TVector< TVector6DBase< MLint > > &b) const
std::string print(const std::string &openStr="", const std::string &sepStr=" ", const std::string &termStr="", const MLint16 numDigits=-1) const
ComponentType compMul() const
Returns the product of all components. There is no check for integer overflow.
bool MLValueIs0WOM(MLint8 a)
bool MLValuesDifferWOM(MLint8 a, MLint8 b)
#define ML_CALCULATION_ERROR
#define ML_PROGRAMMING_ERROR
#define ML_PRINT_FATAL_ERROR(FUNC_NAME, REASON, HANDLING)
#define ML_PRINT_ERROR(FUNC_NAME, REASON, HANDLING)
Target mlrange_cast(Source arg)
Generic version of checked ML casts.
@ ML_FATAL_MEMORY_ERROR
On allocation failure, a fatal error print is done and NULL is returned.
TKernel< MLldouble > LDoubleKernel
Kernel type with MLldouble elements.
T mlAbs(T a)
Defines ML specific abs template since only type-dependent library functions exists.
MLdouble KernelDataType
Define the standard data type for kernel elements to be used in this library.
TKernel< MLfloat > FloatKernel
TKernel< KernelDataType > Kernel
Standard kernel type to be used in this kernel library.
TKernel< MLdouble > DoubleKernel
Kernel type with MLdouble elements.
TImageVector< MLint > ImageVector
Defines the standard ImageVector type that is used by the ML for indexing and coordinates.