diff --git a/Modules/Classification/CLLibSVM/src/svm.cpp b/Modules/Classification/CLLibSVM/src/svm.cpp index fd3c6ce94a..3324e37e38 100644 --- a/Modules/Classification/CLLibSVM/src/svm.cpp +++ b/Modules/Classification/CLLibSVM/src/svm.cpp @@ -1,3307 +1,3307 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ /*=================================================================== Copyright (c) 2000-2014 Chih-Chung Chang and Chih-Jen Lin All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. 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. 3. Neither name of copyright holders 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 THE COPYRIGHT HOLDERS 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 THE REGENTS 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. ===================================================================*/ #include #include #include #include #include #include #include #include #include #include #include "svm.h" int libsvm_version = LIBSVM_VERSION; typedef float Qfloat; typedef signed char schar; #ifndef min template static inline T min(T x,T y) { return (x static inline T max(T x,T y) { return (x>y)?x:y; } #endif template static inline void swap(T& x, T& y) { T t=x; x=y; y=t; } template static inline void clone(T*& dst, S* src, int n) { dst = new T[n]; memcpy((void *)dst,(void *)src,sizeof(T)*n); } static inline double powi(double base, int times) { double tmp = base, ret = 1.0; for(int t=times; t>0; t/=2) { if(t%2==1) ret*=tmp; tmp = tmp * tmp; } return ret; } #define INF HUGE_VAL #define TAU 1e-12 #define Malloc(type,n) (type *)malloc((n)*sizeof(type)) static void print_string_stdout(const char *s) { fputs(s,stdout); fflush(stdout); } static void (*svm_print_string) (const char *) = &print_string_stdout; #if 1 static void info(const char *fmt,...) { char buf[BUFSIZ]; va_list ap; va_start(ap,fmt); vsprintf(buf,fmt,ap); va_end(ap); (*svm_print_string)(buf); } #else static void info(const char *fmt,...) {} #endif // // Kernel Cache // // l is the number of total data items // size is the cache size limit in bytes // class Cache { public: Cache(int l,long int size); ~Cache(); // request data [0,len) // return some position p where [p,len) need to be filled // (p >= len if nothing needs to be filled) int get_data(const int index, Qfloat **data, int len); void swap_index(int i, int j); private: int l; long int size; struct head_t { head_t *prev, *next; // a circular list Qfloat *data; int len; // data[0,len) is cached in this entry }; head_t *head; head_t lru_head; void lru_delete(head_t *h); void lru_insert(head_t *h); }; Cache::Cache(int l_,long int size_):l(l_),size(size_) { head = (head_t *)calloc(l,sizeof(head_t)); // initialized to 0 size /= sizeof(Qfloat); size -= l * sizeof(head_t) / sizeof(Qfloat); size = max(size, 2 * (long int) l); // cache must be large enough for two columns lru_head.next = lru_head.prev = &lru_head; } Cache::~Cache() { for(head_t *h = lru_head.next; h != &lru_head; h=h->next) free(h->data); free(head); } void Cache::lru_delete(head_t *h) { // delete from current location h->prev->next = h->next; h->next->prev = h->prev; } void Cache::lru_insert(head_t *h) { // insert to last position h->next = &lru_head; h->prev = lru_head.prev; h->prev->next = h; h->next->prev = h; } int Cache::get_data(const int index, Qfloat **data, int len) { head_t *h = &head[index]; if(h->len) lru_delete(h); int more = len - h->len; if(more > 0) { // free old space while(size < more) { head_t *old = lru_head.next; lru_delete(old); free(old->data); size += old->len; old->data = 0; old->len = 0; } // allocate new space h->data = (Qfloat *)realloc(h->data,sizeof(Qfloat)*len); size -= more; swap(h->len,len); } lru_insert(h); *data = h->data; return len; } void Cache::swap_index(int i, int j) { if(i==j) return; if(head[i].len) lru_delete(&head[i]); if(head[j].len) lru_delete(&head[j]); swap(head[i].data,head[j].data); swap(head[i].len,head[j].len); if(head[i].len) lru_insert(&head[i]); if(head[j].len) lru_insert(&head[j]); if(i>j) swap(i,j); for(head_t *h = lru_head.next; h!=&lru_head; h=h->next) { if(h->len > i) { if(h->len > j) swap(h->data[i],h->data[j]); else { // give up lru_delete(h); free(h->data); size += h->len; h->data = 0; h->len = 0; } } } } // // Kernel evaluation // // the static method k_function is for doing single kernel evaluation // the constructor of Kernel prepares to calculate the l*l kernel matrix // the member function get_Q is for getting one column from the Q Matrix // class QMatrix { public: virtual Qfloat *get_Q(int column, int len) const = 0; virtual double *get_QD() const = 0; virtual void swap_index(int i, int j) const = 0; virtual ~QMatrix() {} }; class Kernel: public QMatrix { public: Kernel(int l, svm_node * const * x, const svm_parameter& param); - virtual ~Kernel(); + ~Kernel() override; static double k_function(const svm_node *x, const svm_node *y, const svm_parameter& param); - virtual Qfloat *get_Q(int column, int len) const = 0; - virtual double *get_QD() const = 0; - virtual void swap_index(int i, int j) const // no so const... + Qfloat *get_Q(int column, int len) const override = 0; + double *get_QD() const override = 0; + void swap_index(int i, int j) const override // no so const... { swap(x[i],x[j]); if(x_square) swap(x_square[i],x_square[j]); } protected: double (Kernel::*kernel_function)(int i, int j) const; private: const svm_node **x; double *x_square; // svm_parameter const int kernel_type; const int degree; const double gamma; const double coef0; static double dot(const svm_node *px, const svm_node *py); double kernel_linear(int i, int j) const { return dot(x[i],x[j]); } double kernel_poly(int i, int j) const { return powi(gamma*dot(x[i],x[j])+coef0,degree); } double kernel_rbf(int i, int j) const { return exp(-gamma*(x_square[i]+x_square[j]-2*dot(x[i],x[j]))); } double kernel_sigmoid(int i, int j) const { return tanh(gamma*dot(x[i],x[j])+coef0); } double kernel_precomputed(int i, int j) const { return x[i][(int)(x[j][0].value)].value; } }; Kernel::Kernel(int l, svm_node * const * x_, const svm_parameter& param) :kernel_type(param.kernel_type), degree(param.degree), gamma(param.gamma), coef0(param.coef0) { switch(kernel_type) { case LINEAR: kernel_function = &Kernel::kernel_linear; break; case POLY: kernel_function = &Kernel::kernel_poly; break; case RBF: kernel_function = &Kernel::kernel_rbf; break; case SIGMOID: kernel_function = &Kernel::kernel_sigmoid; break; case PRECOMPUTED: kernel_function = &Kernel::kernel_precomputed; break; } clone(x,x_,l); if(kernel_type == RBF) { x_square = new double[l]; for(int i=0;iindex != -1 && py->index != -1) { if(px->index == py->index) { sum += px->value * py->value; ++px; ++py; } else { if(px->index > py->index) ++py; else ++px; } } return sum; } double Kernel::k_function(const svm_node *x, const svm_node *y, const svm_parameter& param) { switch(param.kernel_type) { case LINEAR: return dot(x,y); case POLY: return powi(param.gamma*dot(x,y)+param.coef0,param.degree); case RBF: { double sum = 0; while(x->index != -1 && y->index !=-1) { if(x->index == y->index) { double d = x->value - y->value; sum += d*d; ++x; ++y; } else { if(x->index > y->index) { sum += y->value * y->value; ++y; } else { sum += x->value * x->value; ++x; } } } while(x->index != -1) { sum += x->value * x->value; ++x; } while(y->index != -1) { sum += y->value * y->value; ++y; } return exp(-param.gamma*sum); } case SIGMOID: return tanh(param.gamma*dot(x,y)+param.coef0); case PRECOMPUTED: //x: test (validation), y: SV return x[(int)(y->value)].value; default: return 0; // Unreachable } } // An SMO algorithm in Fan et al., JMLR 6(2005), p. 1889--1918 // Solves: // // min 0.5(\alpha^T Q \alpha) + p^T \alpha // // y^T \alpha = \delta // y_i = +1 or -1 // 0 <= alpha_i <= Cp for y_i = 1 // 0 <= alpha_i <= Cn for y_i = -1 // // Given: // // Q, p, y, Cp, Cn, and an initial feasible point \alpha // l is the size of vectors and matrices // eps is the stopping tolerance // // solution will be put in \alpha, objective value will be put in obj // class Solver { public: Solver() {}; virtual ~Solver() {}; struct SolutionInfo { double obj; double rho; double *upper_bound; double r; // for Solver_NU }; void Solve(int l, const QMatrix& Q, const double *p_, const schar *y_, double *alpha_, const double* C_, double eps, SolutionInfo* si, int shrinking); protected: int active_size; schar *y; double *G; // gradient of objective function enum { LOWER_BOUND, UPPER_BOUND, FREE }; char *alpha_status; // LOWER_BOUND, UPPER_BOUND, FREE double *alpha; const QMatrix *Q; const double *QD; double eps; double Cp,Cn; double *C; double *p; int *active_set; double *G_bar; // gradient, if we treat free variables as 0 int l; bool unshrink; // XXX double get_C(int i) { return C[i]; } void update_alpha_status(int i) { if(alpha[i] >= get_C(i)) alpha_status[i] = UPPER_BOUND; else if(alpha[i] <= 0) alpha_status[i] = LOWER_BOUND; else alpha_status[i] = FREE; } bool is_upper_bound(int i) { return alpha_status[i] == UPPER_BOUND; } bool is_lower_bound(int i) { return alpha_status[i] == LOWER_BOUND; } bool is_free(int i) { return alpha_status[i] == FREE; } void swap_index(int i, int j); void reconstruct_gradient(); virtual int select_working_set(int &i, int &j); virtual double calculate_rho(); virtual void do_shrinking(); private: bool be_shrunk(int i, double Gmax1, double Gmax2); }; void Solver::swap_index(int i, int j) { Q->swap_index(i,j); swap(y[i],y[j]); swap(G[i],G[j]); swap(alpha_status[i],alpha_status[j]); swap(alpha[i],alpha[j]); swap(p[i],p[j]); swap(active_set[i],active_set[j]); swap(G_bar[i],G_bar[j]); swap(C[i],C[j]); } void Solver::reconstruct_gradient() { // reconstruct inactive elements of G from G_bar and free variables if(active_size == l) return; int i,j; int nr_free = 0; for(j=active_size;j 2*active_size*(l-active_size)) { for(i=active_size;iget_Q(i,active_size); for(j=0;jget_Q(i,l); double alpha_i = alpha[i]; for(j=active_size;jl = l; this->Q = &Q; QD=Q.get_QD(); clone(p, p_,l); clone(y, y_,l); clone(alpha,alpha_,l); clone(C,C_,l); this->eps = eps; unshrink = false; // initialize alpha_status { alpha_status = new char[l]; for(int i=0;iINT_MAX/100 ? INT_MAX : 100*l); int counter = min(l,1000)+1; while(iter < max_iter) { // show progress and do shrinking if(--counter == 0) { counter = min(l,1000); if(shrinking) do_shrinking(); info("."); } int i,j; if(select_working_set(i,j)!=0) { // reconstruct the whole gradient reconstruct_gradient(); // reset active set size and check active_size = l; info("*"); if(select_working_set(i,j)!=0) break; else counter = 1; // do shrinking next iteration } ++iter; // update alpha[i] and alpha[j], handle bounds carefully const Qfloat *Q_i = Q.get_Q(i,active_size); const Qfloat *Q_j = Q.get_Q(j,active_size); double C_i = get_C(i); double C_j = get_C(j); double old_alpha_i = alpha[i]; double old_alpha_j = alpha[j]; if(y[i]!=y[j]) { double quad_coef = QD[i]+QD[j]+2*Q_i[j]; if (quad_coef <= 0) quad_coef = TAU; double delta = (-G[i]-G[j])/quad_coef; double diff = alpha[i] - alpha[j]; alpha[i] += delta; alpha[j] += delta; if(diff > 0) { if(alpha[j] < 0) { alpha[j] = 0; alpha[i] = diff; } } else { if(alpha[i] < 0) { alpha[i] = 0; alpha[j] = -diff; } } if(diff > C_i - C_j) { if(alpha[i] > C_i) { alpha[i] = C_i; alpha[j] = C_i - diff; } } else { if(alpha[j] > C_j) { alpha[j] = C_j; alpha[i] = C_j + diff; } } } else { double quad_coef = QD[i]+QD[j]-2*Q_i[j]; if (quad_coef <= 0) quad_coef = TAU; double delta = (G[i]-G[j])/quad_coef; double sum = alpha[i] + alpha[j]; alpha[i] -= delta; alpha[j] += delta; if(sum > C_i) { if(alpha[i] > C_i) { alpha[i] = C_i; alpha[j] = sum - C_i; } } else { if(alpha[j] < 0) { alpha[j] = 0; alpha[i] = sum; } } if(sum > C_j) { if(alpha[j] > C_j) { alpha[j] = C_j; alpha[i] = sum - C_j; } } else { if(alpha[i] < 0) { alpha[i] = 0; alpha[j] = sum; } } } // update G double delta_alpha_i = alpha[i] - old_alpha_i; double delta_alpha_j = alpha[j] - old_alpha_j; for(int k=0;k= max_iter) { if(active_size < l) { // reconstruct the whole gradient to calculate objective value reconstruct_gradient(); active_size = l; info("*"); } fprintf(stderr,"\nWARNING: reaching max number of iterations\n"); } // calculate rho si->rho = calculate_rho(); // calculate objective value { double v = 0; int i; for(i=0;iobj = v/2; } // put back the solution { for(int i=0;iupper_bound[i] = C[i]; info("\noptimization finished, #iter = %d\n",iter); delete[] p; delete[] y; delete[] C; delete[] alpha; delete[] alpha_status; delete[] active_set; delete[] G; delete[] G_bar; } // return 1 if already optimal, return 0 otherwise int Solver::select_working_set(int &out_i, int &out_j) { // return i,j such that // i: maximizes -y_i * grad(f)_i, i in I_up(\alpha) // j: minimizes the decrease of obj value // (if quadratic coefficeint <= 0, replace it with tau) // -y_j*grad(f)_j < -y_i*grad(f)_i, j in I_low(\alpha) double Gmax = -INF; double Gmax2 = -INF; int Gmax_idx = -1; int Gmin_idx = -1; double obj_diff_min = INF; for(int t=0;t= Gmax) { Gmax = -G[t]; Gmax_idx = t; } } else { if(!is_lower_bound(t)) if(G[t] >= Gmax) { Gmax = G[t]; Gmax_idx = t; } } int i = Gmax_idx; const Qfloat *Q_i = nullptr; if(i != -1) // nullptr Q_i not accessed: Gmax=-INF if i=-1 Q_i = Q->get_Q(i,active_size); for(int j=0;j= Gmax2) Gmax2 = G[j]; if (grad_diff > 0) { double obj_diff; double quad_coef = QD[i]+QD[j]-2.0*y[i]*Q_i[j]; if (quad_coef > 0) obj_diff = -(grad_diff*grad_diff)/quad_coef; else obj_diff = -(grad_diff*grad_diff)/TAU; if (obj_diff <= obj_diff_min) { Gmin_idx=j; obj_diff_min = obj_diff; } } } } else { if (!is_upper_bound(j)) { double grad_diff= Gmax-G[j]; if (-G[j] >= Gmax2) Gmax2 = -G[j]; if (grad_diff > 0) { double obj_diff; double quad_coef = QD[i]+QD[j]+2.0*y[i]*Q_i[j]; if (quad_coef > 0) obj_diff = -(grad_diff*grad_diff)/quad_coef; else obj_diff = -(grad_diff*grad_diff)/TAU; if (obj_diff <= obj_diff_min) { Gmin_idx=j; obj_diff_min = obj_diff; } } } } } if(Gmax+Gmax2 < eps) return 1; out_i = Gmax_idx; out_j = Gmin_idx; return 0; } bool Solver::be_shrunk(int i, double Gmax1, double Gmax2) { if(is_upper_bound(i)) { if(y[i]==+1) return(-G[i] > Gmax1); else return(-G[i] > Gmax2); } else if(is_lower_bound(i)) { if(y[i]==+1) return(G[i] > Gmax2); else return(G[i] > Gmax1); } else return(false); } void Solver::do_shrinking() { int i; double Gmax1 = -INF; // max { -y_i * grad(f)_i | i in I_up(\alpha) } double Gmax2 = -INF; // max { y_i * grad(f)_i | i in I_low(\alpha) } // find maximal violating pair first for(i=0;i= Gmax1) Gmax1 = -G[i]; } if(!is_lower_bound(i)) { if(G[i] >= Gmax2) Gmax2 = G[i]; } } else { if(!is_upper_bound(i)) { if(-G[i] >= Gmax2) Gmax2 = -G[i]; } if(!is_lower_bound(i)) { if(G[i] >= Gmax1) Gmax1 = G[i]; } } } if(unshrink == false && Gmax1 + Gmax2 <= eps*10) { unshrink = true; reconstruct_gradient(); active_size = l; info("*"); } for(i=0;i i) { if (!be_shrunk(active_size, Gmax1, Gmax2)) { swap_index(i,active_size); break; } active_size--; } } } double Solver::calculate_rho() { double r; int nr_free = 0; double ub = INF, lb = -INF, sum_free = 0; for(int i=0;i0) r = sum_free/nr_free; else r = (ub+lb)/2; return r; } // // Solver for nu-svm classification and regression // // additional constraint: e^T \alpha = constant // class Solver_NU: public Solver { public: Solver_NU() {} void Solve(int l, const QMatrix& Q, const double *p, const schar *y, double *alpha, double* C_, double eps, SolutionInfo* si, int shrinking) { this->si = si; Solver::Solve(l,Q,p,y,alpha,C_,eps,si,shrinking); } private: SolutionInfo *si; - int select_working_set(int &i, int &j); - double calculate_rho(); + int select_working_set(int &i, int &j) override; + double calculate_rho() override; bool be_shrunk(int i, double Gmax1, double Gmax2, double Gmax3, double Gmax4); - void do_shrinking(); + void do_shrinking() override; }; // return 1 if already optimal, return 0 otherwise int Solver_NU::select_working_set(int &out_i, int &out_j) { // return i,j such that y_i = y_j and // i: maximizes -y_i * grad(f)_i, i in I_up(\alpha) // j: minimizes the decrease of obj value // (if quadratic coefficeint <= 0, replace it with tau) // -y_j*grad(f)_j < -y_i*grad(f)_i, j in I_low(\alpha) double Gmaxp = -INF; double Gmaxp2 = -INF; int Gmaxp_idx = -1; double Gmaxn = -INF; double Gmaxn2 = -INF; int Gmaxn_idx = -1; int Gmin_idx = -1; double obj_diff_min = INF; for(int t=0;t= Gmaxp) { Gmaxp = -G[t]; Gmaxp_idx = t; } } else { if(!is_lower_bound(t)) if(G[t] >= Gmaxn) { Gmaxn = G[t]; Gmaxn_idx = t; } } int ip = Gmaxp_idx; int in = Gmaxn_idx; const Qfloat *Q_ip = nullptr; const Qfloat *Q_in = nullptr; if(ip != -1) // nullptr Q_ip not accessed: Gmaxp=-INF if ip=-1 Q_ip = Q->get_Q(ip,active_size); if(in != -1) Q_in = Q->get_Q(in,active_size); for(int j=0;j= Gmaxp2) Gmaxp2 = G[j]; if (grad_diff > 0) { double obj_diff; double quad_coef = QD[ip]+QD[j]-2*Q_ip[j]; if (quad_coef > 0) obj_diff = -(grad_diff*grad_diff)/quad_coef; else obj_diff = -(grad_diff*grad_diff)/TAU; if (obj_diff <= obj_diff_min) { Gmin_idx=j; obj_diff_min = obj_diff; } } } } else { if (!is_upper_bound(j)) { double grad_diff=Gmaxn-G[j]; if (-G[j] >= Gmaxn2) Gmaxn2 = -G[j]; if (grad_diff > 0) { double obj_diff; double quad_coef = QD[in]+QD[j]-2*Q_in[j]; if (quad_coef > 0) obj_diff = -(grad_diff*grad_diff)/quad_coef; else obj_diff = -(grad_diff*grad_diff)/TAU; if (obj_diff <= obj_diff_min) { Gmin_idx=j; obj_diff_min = obj_diff; } } } } } if(max(Gmaxp+Gmaxp2,Gmaxn+Gmaxn2) < eps) return 1; if (y[Gmin_idx] == +1) out_i = Gmaxp_idx; else out_i = Gmaxn_idx; out_j = Gmin_idx; return 0; } bool Solver_NU::be_shrunk(int i, double Gmax1, double Gmax2, double Gmax3, double Gmax4) { if(is_upper_bound(i)) { if(y[i]==+1) return(-G[i] > Gmax1); else return(-G[i] > Gmax4); } else if(is_lower_bound(i)) { if(y[i]==+1) return(G[i] > Gmax2); else return(G[i] > Gmax3); } else return(false); } void Solver_NU::do_shrinking() { double Gmax1 = -INF; // max { -y_i * grad(f)_i | y_i = +1, i in I_up(\alpha) } double Gmax2 = -INF; // max { y_i * grad(f)_i | y_i = +1, i in I_low(\alpha) } double Gmax3 = -INF; // max { -y_i * grad(f)_i | y_i = -1, i in I_up(\alpha) } double Gmax4 = -INF; // max { y_i * grad(f)_i | y_i = -1, i in I_low(\alpha) } // find maximal violating pair first int i; for(i=0;i Gmax1) Gmax1 = -G[i]; } else if(-G[i] > Gmax4) Gmax4 = -G[i]; } if(!is_lower_bound(i)) { if(y[i]==+1) { if(G[i] > Gmax2) Gmax2 = G[i]; } else if(G[i] > Gmax3) Gmax3 = G[i]; } } if(unshrink == false && max(Gmax1+Gmax2,Gmax3+Gmax4) <= eps*10) { unshrink = true; reconstruct_gradient(); active_size = l; } for(i=0;i i) { if (!be_shrunk(active_size, Gmax1, Gmax2, Gmax3, Gmax4)) { swap_index(i,active_size); break; } active_size--; } } } double Solver_NU::calculate_rho() { int nr_free1 = 0,nr_free2 = 0; double ub1 = INF, ub2 = INF; double lb1 = -INF, lb2 = -INF; double sum_free1 = 0, sum_free2 = 0; for(int i=0;i 0) r1 = sum_free1/nr_free1; else r1 = (ub1+lb1)/2; if(nr_free2 > 0) r2 = sum_free2/nr_free2; else r2 = (ub2+lb2)/2; si->r = (r1+r2)/2; return (r1-r2)/2; } // // Q matrices for various formulations // class SVC_Q: public Kernel { public: SVC_Q(const svm_problem& prob, const svm_parameter& param, const schar *y_) :Kernel(prob.l, prob.x, param) { clone(y,y_,prob.l); cache = new Cache(prob.l,(long int)(param.cache_size*(1<<20))); QD = new double[prob.l]; for(int i=0;i*kernel_function)(i,i); } - Qfloat *get_Q(int i, int len) const + Qfloat *get_Q(int i, int len) const override { Qfloat *data; int start, j; if((start = cache->get_data(i,&data,len)) < len) { for(j=start;j*kernel_function)(i,j)); } return data; } - double *get_QD() const + double *get_QD() const override { return QD; } - void swap_index(int i, int j) const + void swap_index(int i, int j) const override { cache->swap_index(i,j); Kernel::swap_index(i,j); swap(y[i],y[j]); swap(QD[i],QD[j]); } - ~SVC_Q() + ~SVC_Q() override { delete[] y; delete cache; delete[] QD; } private: schar *y; Cache *cache; double *QD; }; class ONE_CLASS_Q: public Kernel { public: ONE_CLASS_Q(const svm_problem& prob, const svm_parameter& param) :Kernel(prob.l, prob.x, param) { cache = new Cache(prob.l,(long int)(param.cache_size*(1<<20))); QD = new double[prob.l]; for(int i=0;i*kernel_function)(i,i); } - Qfloat *get_Q(int i, int len) const + Qfloat *get_Q(int i, int len) const override { Qfloat *data; int start, j; if((start = cache->get_data(i,&data,len)) < len) { for(j=start;j*kernel_function)(i,j); } return data; } - double *get_QD() const + double *get_QD() const override { return QD; } - void swap_index(int i, int j) const + void swap_index(int i, int j) const override { cache->swap_index(i,j); Kernel::swap_index(i,j); swap(QD[i],QD[j]); } - ~ONE_CLASS_Q() + ~ONE_CLASS_Q() override { delete cache; delete[] QD; } private: Cache *cache; double *QD; }; class SVR_Q: public Kernel { public: SVR_Q(const svm_problem& prob, const svm_parameter& param) :Kernel(prob.l, prob.x, param) { l = prob.l; cache = new Cache(l,(long int)(param.cache_size*(1<<20))); QD = new double[2*l]; sign = new schar[2*l]; index = new int[2*l]; for(int k=0;k*kernel_function)(k,k); QD[k+l] = QD[k]; } buffer[0] = new Qfloat[2*l]; buffer[1] = new Qfloat[2*l]; next_buffer = 0; } - void swap_index(int i, int j) const + void swap_index(int i, int j) const override { swap(sign[i],sign[j]); swap(index[i],index[j]); swap(QD[i],QD[j]); } - Qfloat *get_Q(int i, int len) const + Qfloat *get_Q(int i, int len) const override { Qfloat *data; int j, real_i = index[i]; if(cache->get_data(real_i,&data,l) < l) { for(j=0;j*kernel_function)(real_i,j); } // reorder and copy Qfloat *buf = buffer[next_buffer]; next_buffer = 1 - next_buffer; schar si = sign[i]; for(j=0;jl; double *minus_ones = new double[l]; schar *y = new schar[l]; double *C = new double[l]; int i; for(i=0;iy[i] > 0) { y[i] = +1; C[i] = prob->W[i]*Cp; } else { y[i] = -1; C[i] = prob->W[i]*Cn; } } Solver s; s.Solve(l, SVC_Q(*prob,*param,y), minus_ones, y, alpha, C, param->eps, si, param->shrinking); /* double sum_alpha=0; for(i=0;il)); */ for(i=0;il; double nu = param->nu; schar *y = new schar[l]; double *C = new double[l]; for(i=0;iy[i]>0) y[i] = +1; else y[i] = -1; C[i] = prob->W[i]; } double nu_l = 0; for(i=0;ieps, si, param->shrinking); double r = si->r; info("C = %f\n",1/r); for(i=0;iupper_bound[i] /= r; } si->rho /= r; si->obj /= (r*r); delete[] C; delete[] y; delete[] zeros; } static void solve_one_class( const svm_problem *prob, const svm_parameter *param, double *alpha, Solver::SolutionInfo* si) { int l = prob->l; double *zeros = new double[l]; schar *ones = new schar[l]; double *C = new double[l]; int i; double nu_l = 0; for(i=0;iW[i]; nu_l += C[i] * param->nu; } i = 0; while(nu_l > 0) { alpha[i] = min(C[i],nu_l); nu_l -= alpha[i]; ++i; } for(;ieps, si, param->shrinking); delete[] C; delete[] zeros; delete[] ones; } static void solve_epsilon_svr( const svm_problem *prob, const svm_parameter *param, double *alpha, Solver::SolutionInfo* si) { int l = prob->l; double *alpha2 = new double[2*l]; double *linear_term = new double[2*l]; double *C = new double[2*l]; schar *y = new schar[2*l]; int i; for(i=0;ip - prob->y[i]; y[i] = 1; C[i] = prob->W[i]*param->C; alpha2[i+l] = 0; linear_term[i+l] = param->p + prob->y[i]; y[i+l] = -1; C[i+l] = prob->W[i]*param->C; } Solver s; s.Solve(2*l, SVR_Q(*prob,*param), linear_term, y, alpha2, C, param->eps, si, param->shrinking); double sum_alpha = 0; for(i=0;iC*l)); delete[] alpha2; delete[] linear_term; delete[] C; delete[] y; } static void solve_nu_svr( const svm_problem *prob, const svm_parameter *param, double *alpha, Solver::SolutionInfo* si) { int l = prob->l; double *C = new double[2*l]; double *alpha2 = new double[2*l]; double *linear_term = new double[2*l]; schar *y = new schar[2*l]; int i; double sum = 0; for(i=0;iW[i]*param->C; sum += C[i] * param->nu; } sum /= 2; for(i=0;iy[i]; y[i] = 1; linear_term[i+l] = prob->y[i]; y[i+l] = -1; } Solver_NU s; s.Solve(2*l, SVR_Q(*prob,*param), linear_term, y, alpha2, C, param->eps, si, param->shrinking); info("epsilon = %f\n",-si->r); for(i=0;il); Solver::SolutionInfo si; switch(param->svm_type) { case C_SVC: si.upper_bound = Malloc(double,prob->l); solve_c_svc(prob,param,alpha,&si,Cp,Cn); break; case NU_SVC: si.upper_bound = Malloc(double,prob->l); solve_nu_svc(prob,param,alpha,&si); break; case ONE_CLASS: si.upper_bound = Malloc(double,prob->l); solve_one_class(prob,param,alpha,&si); break; case EPSILON_SVR: si.upper_bound = Malloc(double,2*prob->l); solve_epsilon_svr(prob,param,alpha,&si); break; case NU_SVR: si.upper_bound = Malloc(double,2*prob->l); solve_nu_svr(prob,param,alpha,&si); break; } info("obj = %f, rho = %f\n",si.obj,si.rho); // output SVs int nSV = 0; int nBSV = 0; for(int i=0;il;i++) { if(fabs(alpha[i]) > 0) { ++nSV; if(prob->y[i] > 0) { if(fabs(alpha[i]) >= si.upper_bound[i]) ++nBSV; } else { if(fabs(alpha[i]) >= si.upper_bound[i]) ++nBSV; } } } free(si.upper_bound); info("nSV = %d, nBSV = %d\n",nSV,nBSV); decision_function f; f.alpha = alpha; f.rho = si.rho; return f; } // Platt's binary SVM Probablistic Output: an improvement from Lin et al. static void sigmoid_train( int l, const double *dec_values, const double *labels, double& A, double& B) { double prior1=0, prior0 = 0; int i; for (i=0;i 0) prior1+=1; else prior0+=1; int max_iter=100; // Maximal number of iterations double min_step=1e-10; // Minimal step taken in line search double sigma=1e-12; // For numerically strict PD of Hessian double eps=1e-5; double hiTarget=(prior1+1.0)/(prior1+2.0); double loTarget=1/(prior0+2.0); double *t=Malloc(double,l); double fApB,p,q,h11,h22,h21,g1,g2,det,dA,dB,gd,stepsize; double newA,newB,newf,d1,d2; int iter; // Initial Point and Initial Fun Value A=0.0; B=log((prior0+1.0)/(prior1+1.0)); double fval = 0.0; for (i=0;i0) t[i]=hiTarget; else t[i]=loTarget; fApB = dec_values[i]*A+B; if (fApB>=0) fval += t[i]*fApB + log(1+exp(-fApB)); else fval += (t[i] - 1)*fApB +log(1+exp(fApB)); } for (iter=0;iter= 0) { p=exp(-fApB)/(1.0+exp(-fApB)); q=1.0/(1.0+exp(-fApB)); } else { p=1.0/(1.0+exp(fApB)); q=exp(fApB)/(1.0+exp(fApB)); } d2=p*q; h11+=dec_values[i]*dec_values[i]*d2; h22+=d2; h21+=dec_values[i]*d2; d1=t[i]-p; g1+=dec_values[i]*d1; g2+=d1; } // Stopping Criteria if (fabs(g1)= min_step) { newA = A + stepsize * dA; newB = B + stepsize * dB; // New function value newf = 0.0; for (i=0;i= 0) newf += t[i]*fApB + log(1+exp(-fApB)); else newf += (t[i] - 1)*fApB +log(1+exp(fApB)); } // Check sufficient decrease if (newf=max_iter) info("Reaching maximal iterations in two-class probability estimates\n"); free(t); } static double sigmoid_predict(double decision_value, double A, double B) { double fApB = decision_value*A+B; // 1-p used later; avoid catastrophic cancellation if (fApB >= 0) return exp(-fApB)/(1.0+exp(-fApB)); else return 1.0/(1+exp(fApB)) ; } // Method 2 from the multiclass_prob paper by Wu, Lin, and Weng static void multiclass_probability(int k, double **r, double *p) { int t,j; int iter = 0, max_iter=max(100,k); double **Q=Malloc(double *,k); double *Qp=Malloc(double,k); double pQp, eps=0.005/k; for (t=0;tmax_error) max_error=error; } if (max_error=max_iter) info("Exceeds max_iter in multiclass_prob\n"); for(t=0;tl); double *dec_values = Malloc(double,prob->l); // random shuffle for(i=0;il;i++) perm[i]=i; for(i=0;il;i++) { int j = i+rand()%(prob->l-i); swap(perm[i],perm[j]); } for(i=0;il/nr_fold; int end = (i+1)*prob->l/nr_fold; int j,k; struct svm_problem subprob; subprob.l = prob->l-(end-begin); subprob.x = Malloc(struct svm_node*,subprob.l); subprob.y = Malloc(double,subprob.l); subprob.W = Malloc(double,subprob.l); k=0; for(j=0;jx[perm[j]]; subprob.y[k] = prob->y[perm[j]]; subprob.W[k] = prob->W[perm[j]]; ++k; } for(j=end;jl;j++) { subprob.x[k] = prob->x[perm[j]]; subprob.y[k] = prob->y[perm[j]]; subprob.W[k] = prob->W[perm[j]]; ++k; } int p_count=0,n_count=0; for(j=0;j0) p_count++; else n_count++; if(p_count==0 && n_count==0) for(j=begin;j 0 && n_count == 0) for(j=begin;j 0) for(j=begin;jx[perm[j]],&(dec_values[perm[j]])); // ensure +1 -1 order; reason not using CV subroutine dec_values[perm[j]] *= submodel->label[0]; } svm_free_and_destroy_model(&submodel); svm_destroy_param(&subparam); } free(subprob.x); free(subprob.y); free(subprob.W); } sigmoid_train(prob->l,dec_values,prob->y,probA,probB); free(dec_values); free(perm); } // Return parameter of a Laplace distribution static double svm_svr_probability( const svm_problem *prob, const svm_parameter *param) { int i; int nr_fold = 5; double *ymv = Malloc(double,prob->l); double mae = 0; svm_parameter newparam = *param; newparam.probability = 0; svm_cross_validation(prob,&newparam,nr_fold,ymv); for(i=0;il;i++) { ymv[i]=prob->y[i]-ymv[i]; mae += fabs(ymv[i]); } mae /= prob->l; double std=sqrt(2*mae*mae); int count=0; mae=0; for(i=0;il;i++) if (fabs(ymv[i]) > 5*std) count=count+1; else mae+=fabs(ymv[i]); mae /= (prob->l-count); info("Prob. model for test data: target value = predicted value + z,\nz: Laplace distribution e^(-|z|/sigma)/(2sigma),sigma= %g\n",mae); free(ymv); return mae; } // label: label name, start: begin of each class, count: #data of classes, perm: indices to the original data // perm, length l, must be allocated before calling this subroutine static void svm_group_classes(const svm_problem *prob, int *nr_class_ret, int **label_ret, int **start_ret, int **count_ret, int *perm) { int l = prob->l; int max_nr_class = 16; int nr_class = 0; int *label = Malloc(int,max_nr_class); int *count = Malloc(int,max_nr_class); int *data_label = Malloc(int,l); int i; for(i=0;iy[i]; int j; for(j=0;j 0. // static void remove_zero_weight(svm_problem *newprob, const svm_problem *prob) { int i; int l = 0; for(i=0;il;i++) if(prob->W[i] > 0) l++; *newprob = *prob; newprob->l = l; newprob->x = Malloc(svm_node*,l); newprob->y = Malloc(double,l); newprob->W = Malloc(double,l); int j = 0; for(i=0;il;i++) if(prob->W[i] > 0) { newprob->x[j] = prob->x[i]; newprob->y[j] = prob->y[i]; newprob->W[j] = prob->W[i]; j++; } } // // Interface functions // svm_model *svm_train(const svm_problem *prob, const svm_parameter *param) { svm_problem newprob; remove_zero_weight(&newprob, prob); prob = &newprob; svm_model *model = Malloc(svm_model,1); model->param = *param; model->free_sv = 0; // XXX if(param->svm_type == ONE_CLASS || param->svm_type == EPSILON_SVR || param->svm_type == NU_SVR) { // regression or one-class-svm model->nr_class = 2; model->label = nullptr; model->nSV = nullptr; model->probA = nullptr; model->probB = nullptr; model->sv_coef = Malloc(double *,1); if(param->probability && (param->svm_type == EPSILON_SVR || param->svm_type == NU_SVR)) { model->probA = Malloc(double,1); model->probA[0] = svm_svr_probability(prob,param); } decision_function f = svm_train_one(prob,param,0,0); model->rho = Malloc(double,1); model->rho[0] = f.rho; int nSV = 0; int i; for(i=0;il;i++) if(fabs(f.alpha[i]) > 0) ++nSV; model->l = nSV; model->SV = Malloc(svm_node *,nSV); model->sv_coef[0] = Malloc(double,nSV); model->sv_indices = Malloc(int,nSV); int j = 0; for(i=0;il;i++) if(fabs(f.alpha[i]) > 0) { model->SV[j] = prob->x[i]; model->sv_coef[0][j] = f.alpha[i]; model->sv_indices[j] = i+1; ++j; } free(f.alpha); } else { // classification int l = prob->l; int nr_class; int *label = nullptr; int *start = nullptr; int *count = nullptr; int *perm = Malloc(int,l); // group training data of the same class svm_group_classes(prob,&nr_class,&label,&start,&count,perm); if(nr_class == 1) info("WARNING: training data in only one class. See README for details.\n"); svm_node **x = Malloc(svm_node *,l); double *W; W = Malloc(double,l); int i; for(i=0;ix[perm[i]]; W[i] = prob->W[perm[i]]; } // calculate weighted C double *weighted_C = Malloc(double, nr_class); for(i=0;iC; for(i=0;inr_weight;i++) { int j; for(j=0;jweight_label[i] == label[j]) break; if(j == nr_class) fprintf(stderr,"WARNING: class label %d specified in weight is not found\n", param->weight_label[i]); else weighted_C[j] *= param->weight[i]; } // train k*(k-1)/2 models bool *nonzero = Malloc(bool,l); for(i=0;iprobability) { probA=Malloc(double,nr_class*(nr_class-1)/2); probB=Malloc(double,nr_class*(nr_class-1)/2); } int p = 0; for(i=0;iprobability) svm_binary_svc_probability(&sub_prob,param,weighted_C[i],weighted_C[j],probA[p],probB[p]); f[p] = svm_train_one(&sub_prob,param,weighted_C[i],weighted_C[j]); for(k=0;k 0) nonzero[si+k] = true; for(k=0;k 0) nonzero[sj+k] = true; free(sub_prob.x); free(sub_prob.y); free(sub_prob.W); ++p; } // build output model->nr_class = nr_class; model->label = Malloc(int,nr_class); for(i=0;ilabel[i] = label[i]; model->rho = Malloc(double,nr_class*(nr_class-1)/2); for(i=0;irho[i] = f[i].rho; if(param->probability) { model->probA = Malloc(double,nr_class*(nr_class-1)/2); model->probB = Malloc(double,nr_class*(nr_class-1)/2); for(i=0;iprobA[i] = probA[i]; model->probB[i] = probB[i]; } } else { model->probA=nullptr; model->probB=nullptr; } int total_sv = 0; int *nz_count = Malloc(int,nr_class); model->nSV = Malloc(int,nr_class); for(i=0;inSV[i] = nSV; nz_count[i] = nSV; } info("Total nSV = %d\n",total_sv); model->l = total_sv; model->SV = Malloc(svm_node *,total_sv); model->sv_indices = Malloc(int,total_sv); p = 0; for(i=0;iSV[p] = x[i]; model->sv_indices[p++] = perm[i] + 1; } int *nz_start = Malloc(int,nr_class); nz_start[0] = 0; for(i=1;isv_coef = Malloc(double *,nr_class-1); for(i=0;isv_coef[i] = Malloc(double,total_sv); p = 0; for(i=0;isv_coef[j-1][q++] = f[p].alpha[k]; q = nz_start[j]; for(k=0;ksv_coef[i][q++] = f[p].alpha[ci+k]; ++p; } free(label); free(probA); free(probB); free(count); free(perm); free(start); free(W); free(x); free(weighted_C); free(nonzero); for(i=0;il; int *perm = Malloc(int,l); int nr_class; if (nr_fold > l) { nr_fold = l; fprintf(stderr,"WARNING: # folds > # data. Will use # folds = # data instead (i.e., leave-one-out cross validation)\n"); } fold_start = Malloc(int,nr_fold+1); // stratified cv may not give leave-one-out rate // Each class to l folds -> some folds may have zero elements if((param->svm_type == C_SVC || param->svm_type == NU_SVC) && nr_fold < l) { int *start = nullptr; int *label = nullptr; int *count = nullptr; svm_group_classes(prob,&nr_class,&label,&start,&count,perm); // random shuffle and then data grouped by fold using the array perm int *fold_count = Malloc(int,nr_fold); int c; int *index = Malloc(int,l); for(i=0;ix[perm[j]]; subprob.y[k] = prob->y[perm[j]]; subprob.W[k] = prob->W[perm[j]]; ++k; } for(j=end;jx[perm[j]]; subprob.y[k] = prob->y[perm[j]]; subprob.W[k] = prob->W[perm[j]]; ++k; } struct svm_model *submodel = svm_train(&subprob,param); if(param->probability && (param->svm_type == C_SVC || param->svm_type == NU_SVC)) { double *prob_estimates=Malloc(double,svm_get_nr_class(submodel)); for(j=begin;jx[perm[j]],prob_estimates); free(prob_estimates); } else for(j=begin;jx[perm[j]]); svm_free_and_destroy_model(&submodel); free(subprob.x); free(subprob.y); free(subprob.W); } free(fold_start); free(perm); } int svm_get_svm_type(const svm_model *model) { return model->param.svm_type; } int svm_get_nr_class(const svm_model *model) { return model->nr_class; } void svm_get_labels(const svm_model *model, int* label) { if (model->label != nullptr) for(int i=0;inr_class;i++) label[i] = model->label[i]; } void svm_get_sv_indices(const svm_model *model, int* indices) { if (model->sv_indices != nullptr) for(int i=0;il;i++) indices[i] = model->sv_indices[i]; } int svm_get_nr_sv(const svm_model *model) { return model->l; } double svm_get_svr_probability(const svm_model *model) { if ((model->param.svm_type == EPSILON_SVR || model->param.svm_type == NU_SVR) && model->probA!=nullptr) return model->probA[0]; else { fprintf(stderr,"Model doesn't contain information for SVR probability inference\n"); return 0; } } double svm_predict_values(const svm_model *model, const svm_node *x, double* dec_values) { int i; if(model->param.svm_type == ONE_CLASS || model->param.svm_type == EPSILON_SVR || model->param.svm_type == NU_SVR) { double *sv_coef = model->sv_coef[0]; double sum = 0; for(i=0;il;i++) sum += sv_coef[i] * Kernel::k_function(x,model->SV[i],model->param); sum -= model->rho[0]; *dec_values = sum; if(model->param.svm_type == ONE_CLASS) return (sum>0)?1:-1; else return sum; } else { int nr_class = model->nr_class; int l = model->l; double *kvalue = Malloc(double,l); for(i=0;iSV[i],model->param); int *start = Malloc(int,nr_class); start[0] = 0; for(i=1;inSV[i-1]; int *vote = Malloc(int,nr_class); for(i=0;inSV[i]; int cj = model->nSV[j]; int k; double *coef1 = model->sv_coef[j-1]; double *coef2 = model->sv_coef[i]; for(k=0;krho[p]; dec_values[p] = sum; if(dec_values[p] > 0) ++vote[i]; else ++vote[j]; p++; } int vote_max_idx = 0; for(i=1;i vote[vote_max_idx]) vote_max_idx = i; free(kvalue); free(start); free(vote); return model->label[vote_max_idx]; } } double svm_predict(const svm_model *model, const svm_node *x) { int nr_class = model->nr_class; double *dec_values; if(model->param.svm_type == ONE_CLASS || model->param.svm_type == EPSILON_SVR || model->param.svm_type == NU_SVR) dec_values = Malloc(double, 1); else dec_values = Malloc(double, nr_class*(nr_class-1)/2); double pred_result = svm_predict_values(model, x, dec_values); free(dec_values); return pred_result; } double svm_predict_probability( const svm_model *model, const svm_node *x, double *prob_estimates) { if ((model->param.svm_type == C_SVC || model->param.svm_type == NU_SVC) && model->probA!=nullptr && model->probB!=nullptr) { int i; int nr_class = model->nr_class; double *dec_values = Malloc(double, nr_class*(nr_class-1)/2); svm_predict_values(model, x, dec_values); double min_prob=1e-7; double **pairwise_prob=Malloc(double *,nr_class); for(i=0;iprobA[k],model->probB[k]),min_prob),1-min_prob); pairwise_prob[j][i]=1-pairwise_prob[i][j]; k++; } multiclass_probability(nr_class,pairwise_prob,prob_estimates); int prob_max_idx = 0; for(i=1;i prob_estimates[prob_max_idx]) prob_max_idx = i; for(i=0;ilabel[prob_max_idx]; } else return svm_predict(model, x); } static const char *svm_type_table[] = { "c_svc","nu_svc","one_class","epsilon_svr","nu_svr",nullptr }; static const char *kernel_type_table[]= { "linear","polynomial","rbf","sigmoid","precomputed",nullptr }; int svm_save_model(const char *model_file_name, const svm_model *model) { FILE *fp = fopen(model_file_name,"w"); if(fp==nullptr) return -1; mitk::LocaleSwitch localeSwitch("C"); const svm_parameter& param = model->param; fprintf(fp,"svm_type %s\n", svm_type_table[param.svm_type]); fprintf(fp,"kernel_type %s\n", kernel_type_table[param.kernel_type]); if(param.kernel_type == POLY) fprintf(fp,"degree %d\n", param.degree); if(param.kernel_type == POLY || param.kernel_type == RBF || param.kernel_type == SIGMOID) fprintf(fp,"gamma %g\n", param.gamma); if(param.kernel_type == POLY || param.kernel_type == SIGMOID) fprintf(fp,"coef0 %g\n", param.coef0); int nr_class = model->nr_class; int l = model->l; fprintf(fp, "nr_class %d\n", nr_class); fprintf(fp, "total_sv %d\n",l); { fprintf(fp, "rho"); for(int i=0;irho[i]); fprintf(fp, "\n"); } if(model->label) { fprintf(fp, "label"); for(int i=0;ilabel[i]); fprintf(fp, "\n"); } if(model->probA) // regression has probA only { fprintf(fp, "probA"); for(int i=0;iprobA[i]); fprintf(fp, "\n"); } if(model->probB) { fprintf(fp, "probB"); for(int i=0;iprobB[i]); fprintf(fp, "\n"); } if(model->nSV) { fprintf(fp, "nr_sv"); for(int i=0;inSV[i]); fprintf(fp, "\n"); } fprintf(fp, "SV\n"); const double * const *sv_coef = model->sv_coef; const svm_node * const *SV = model->SV; for(int i=0;ivalue)); else while(p->index != -1) { fprintf(fp,"%d:%.8g ",p->index,p->value); p++; } fprintf(fp, "\n"); } if (ferror(fp) != 0 || fclose(fp) != 0) return -1; else return 0; } static char *line = nullptr; static int max_line_len; static char* readline(FILE *input) { int len; if(fgets(line,max_line_len,input) == nullptr) return nullptr; while(strrchr(line,'\n') == nullptr) { max_line_len *= 2; line = (char *) realloc(line,max_line_len); len = (int) strlen(line); if(fgets(line+len,max_line_len-len,input) == nullptr) break; } return line; } // // FSCANF helps to handle fscanf failures. // Its do-while block avoids the ambiguity when // if (...) // FSCANF(); // is used // #define FSCANF(_stream, _format, _var) do{ if (fscanf(_stream, _format, _var) != 1) return false; }while(0) bool read_model_header(FILE *fp, svm_model* model) { svm_parameter& param = model->param; char cmd[81]; while(1) { FSCANF(fp,"%80s",cmd); if(strcmp(cmd,"svm_type")==0) { FSCANF(fp,"%80s",cmd); int i; for(i=0;svm_type_table[i];i++) { if(strcmp(svm_type_table[i],cmd)==0) { param.svm_type=i; break; } } if(svm_type_table[i] == nullptr) { fprintf(stderr,"unknown svm type.\n"); return false; } } else if(strcmp(cmd,"kernel_type")==0) { FSCANF(fp,"%80s",cmd); int i; for(i=0;kernel_type_table[i];i++) { if(strcmp(kernel_type_table[i],cmd)==0) { param.kernel_type=i; break; } } if(kernel_type_table[i] == nullptr) { fprintf(stderr,"unknown kernel function.\n"); return false; } } else if(strcmp(cmd,"degree")==0) FSCANF(fp,"%d",¶m.degree); else if(strcmp(cmd,"gamma")==0) FSCANF(fp,"%lf",¶m.gamma); else if(strcmp(cmd,"coef0")==0) FSCANF(fp,"%lf",¶m.coef0); else if(strcmp(cmd,"nr_class")==0) FSCANF(fp,"%d",&model->nr_class); else if(strcmp(cmd,"total_sv")==0) FSCANF(fp,"%d",&model->l); else if(strcmp(cmd,"rho")==0) { int n = model->nr_class * (model->nr_class-1)/2; model->rho = Malloc(double,n); for(int i=0;irho[i]); } else if(strcmp(cmd,"label")==0) { int n = model->nr_class; model->label = Malloc(int,n); for(int i=0;ilabel[i]); } else if(strcmp(cmd,"probA")==0) { int n = model->nr_class * (model->nr_class-1)/2; model->probA = Malloc(double,n); for(int i=0;iprobA[i]); } else if(strcmp(cmd,"probB")==0) { int n = model->nr_class * (model->nr_class-1)/2; model->probB = Malloc(double,n); for(int i=0;iprobB[i]); } else if(strcmp(cmd,"nr_sv")==0) { int n = model->nr_class; model->nSV = Malloc(int,n); for(int i=0;inSV[i]); } else if(strcmp(cmd,"SV")==0) { while(1) { int c = getc(fp); if(c==EOF || c=='\n') break; } break; } else { fprintf(stderr,"unknown text in model file: [%s]\n",cmd); return false; } } return true; } svm_model *svm_load_model(const char *model_file_name) { FILE *fp = fopen(model_file_name,"rb"); if(fp==nullptr) return nullptr; mitk::LocaleSwitch localeSwitch("C"); // read parameters svm_model *model = Malloc(svm_model,1); model->rho = nullptr; model->probA = nullptr; model->probB = nullptr; model->sv_indices = nullptr; model->label = nullptr; model->nSV = nullptr; // read header if (!read_model_header(fp, model)) { fprintf(stderr, "ERROR: fscanf failed to read model\n"); free(model->rho); free(model->label); free(model->nSV); free(model); return nullptr; } // read sv_coef and SV int elements = 0; long pos = ftell(fp); max_line_len = 1024; line = Malloc(char,max_line_len); char *p,*endptr,*idx,*val; while(readline(fp)!=nullptr) { p = strtok(line,":"); while(1) { p = strtok(nullptr,":"); if(p == nullptr) break; ++elements; } } elements += model->l; fseek(fp,pos,SEEK_SET); int m = model->nr_class - 1; int l = model->l; model->sv_coef = Malloc(double *,m); int i; for(i=0;isv_coef[i] = Malloc(double,l); model->SV = Malloc(svm_node*,l); svm_node *x_space = nullptr; if(l>0) x_space = Malloc(svm_node,elements); int j=0; for(i=0;iSV[i] = &x_space[j]; p = strtok(line, " \t"); model->sv_coef[0][i] = strtod(p,&endptr); for(int k=1;ksv_coef[k][i] = strtod(p,&endptr); } while(1) { idx = strtok(nullptr, ":"); val = strtok(nullptr, " \t"); if(val == nullptr) break; x_space[j].index = (int) strtol(idx,&endptr,10); x_space[j].value = strtod(val,&endptr); ++j; } x_space[j++].index = -1; } free(line); if (ferror(fp) != 0 || fclose(fp) != 0) return nullptr; model->free_sv = 1; // XXX return model; } void svm_free_model_content(svm_model* model_ptr) { if(model_ptr->free_sv && model_ptr->l > 0 && model_ptr->SV != nullptr) free((void *)(model_ptr->SV[0])); if(model_ptr->sv_coef) { for(int i=0;inr_class-1;i++) free(model_ptr->sv_coef[i]); } free(model_ptr->SV); model_ptr->SV = nullptr; free(model_ptr->sv_coef); model_ptr->sv_coef = nullptr; free(model_ptr->rho); model_ptr->rho = nullptr; free(model_ptr->label); model_ptr->label= nullptr; free(model_ptr->probA); model_ptr->probA = nullptr; free(model_ptr->probB); model_ptr->probB= nullptr; free(model_ptr->sv_indices); model_ptr->sv_indices = nullptr; free(model_ptr->nSV); model_ptr->nSV = nullptr; } void svm_free_and_destroy_model(svm_model** model_ptr_ptr) { if(model_ptr_ptr != nullptr && *model_ptr_ptr != nullptr) { svm_free_model_content(*model_ptr_ptr); free(*model_ptr_ptr); *model_ptr_ptr = nullptr; } } void svm_destroy_param(svm_parameter* param) { free(param->weight_label); free(param->weight); } const char *svm_check_parameter(const svm_problem *prob, const svm_parameter *param) { // svm_type int svm_type = param->svm_type; if(svm_type != C_SVC && svm_type != NU_SVC && svm_type != ONE_CLASS && svm_type != EPSILON_SVR && svm_type != NU_SVR) return "unknown svm type"; // kernel_type, degree int kernel_type = param->kernel_type; if(kernel_type != LINEAR && kernel_type != POLY && kernel_type != RBF && kernel_type != SIGMOID && kernel_type != PRECOMPUTED) return "unknown kernel type"; if(param->gamma < 0) return "gamma < 0"; if(param->degree < 0) return "degree of polynomial kernel < 0"; // cache_size,eps,C,nu,p,shrinking if(param->cache_size <= 0) return "cache_size <= 0"; if(param->eps <= 0) return "eps <= 0"; if(svm_type == C_SVC || svm_type == EPSILON_SVR || svm_type == NU_SVR) if(param->C <= 0) return "C <= 0"; if(svm_type == NU_SVC || svm_type == ONE_CLASS || svm_type == NU_SVR) if(param->nu <= 0 || param->nu > 1) return "nu <= 0 or nu > 1"; if(svm_type == EPSILON_SVR) if(param->p < 0) return "p < 0"; if(param->shrinking != 0 && param->shrinking != 1) return "shrinking != 0 and shrinking != 1"; if(param->probability != 0 && param->probability != 1) return "probability != 0 and probability != 1"; if(param->probability == 1 && svm_type == ONE_CLASS) return "one-class SVM probability output not supported yet"; // check whether nu-svc is feasible if(svm_type == NU_SVC) { int l = prob->l; int max_nr_class = 16; int nr_class = 0; int *label = Malloc(int,max_nr_class); double *count = Malloc(double,max_nr_class); int i; for(i=0;iy[i]; int j; for(j=0;jW[i]; break; } if(j == nr_class) { if(nr_class == max_nr_class) { max_nr_class *= 2; label = (int *)realloc(label,max_nr_class*sizeof(int)); count = (double *)realloc(count,max_nr_class*sizeof(double)); } label[nr_class] = this_label; count[nr_class] = prob->W[i]; ++nr_class; } } for(i=0;inu*(n1+n2)/2 > min(n1,n2)) { free(label); free(count); return "specified nu is infeasible"; } } } free(label); free(count); } return nullptr; } int svm_check_probability_model(const svm_model *model) { return ((model->param.svm_type == C_SVC || model->param.svm_type == NU_SVC) && model->probA!=nullptr && model->probB!=nullptr) || ((model->param.svm_type == EPSILON_SVR || model->param.svm_type == NU_SVR) && model->probA!=nullptr); } void svm_set_print_string_function(void (*print_func)(const char *)) { if(print_func == nullptr) svm_print_string = &print_string_stdout; else svm_print_string = print_func; } diff --git a/Modules/Classification/CLUtilities/test/mitkGlobalFeaturesTest.cpp b/Modules/Classification/CLUtilities/test/mitkGlobalFeaturesTest.cpp index 0eed3e55e6..3aea5886b3 100644 --- a/Modules/Classification/CLUtilities/test/mitkGlobalFeaturesTest.cpp +++ b/Modules/Classification/CLUtilities/test/mitkGlobalFeaturesTest.cpp @@ -1,317 +1,317 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include #include #include "mitkIOUtil.h" #include #include #include #include #include #include template static mitk::Image::Pointer GenerateMaskImage(unsigned int dimX, unsigned int dimY, unsigned int dimZ, float spacingX = 1, float spacingY = 1, float spacingZ = 1) { typedef itk::Image< TPixelType, 3 > ImageType; typename ImageType::RegionType imageRegion; imageRegion.SetSize(0, dimX); imageRegion.SetSize(1, dimY); imageRegion.SetSize(2, dimZ); typename ImageType::SpacingType spacing; spacing[0] = spacingX; spacing[1] = spacingY; spacing[2] = spacingZ; mitk::Point3D origin; origin.Fill(0.0); itk::Matrix directionMatrix; directionMatrix.SetIdentity(); typename ImageType::Pointer image = ImageType::New(); image->SetSpacing( spacing ); image->SetOrigin( origin ); image->SetDirection( directionMatrix ); image->SetLargestPossibleRegion( imageRegion ); image->SetBufferedRegion( imageRegion ); image->SetRequestedRegion( imageRegion ); image->Allocate(); image->FillBuffer(1); mitk::Image::Pointer mitkImage = mitk::Image::New(); mitkImage->InitializeByItk( image.GetPointer() ); mitkImage->SetVolume( image->GetBufferPointer() ); return mitkImage; } template static mitk::Image::Pointer GenerateGradientWithDimXImage(unsigned int dimX, unsigned int dimY, unsigned int dimZ, float spacingX = 1, float spacingY = 1, float spacingZ = 1) { typedef itk::Image< TPixelType, 3 > ImageType; typename ImageType::RegionType imageRegion; imageRegion.SetSize(0, dimX); imageRegion.SetSize(1, dimY); imageRegion.SetSize(2, dimZ); typename ImageType::SpacingType spacing; spacing[0] = spacingX; spacing[1] = spacingY; spacing[2] = spacingZ; mitk::Point3D origin; origin.Fill(0.0); itk::Matrix directionMatrix; directionMatrix.SetIdentity(); typename ImageType::Pointer image = ImageType::New(); image->SetSpacing( spacing ); image->SetOrigin( origin ); image->SetDirection( directionMatrix ); image->SetLargestPossibleRegion( imageRegion ); image->SetBufferedRegion( imageRegion ); image->SetRequestedRegion( imageRegion ); image->Allocate(); image->FillBuffer(0.0); typedef itk::ImageRegionIterator IteratorOutputType; IteratorOutputType it(image, imageRegion); it.GoToBegin(); TPixelType val = 0; while(!it.IsAtEnd()) { it.Set(val % dimX); val++; ++it; } mitk::Image::Pointer mitkImage = mitk::Image::New(); mitkImage->InitializeByItk( image.GetPointer() ); mitkImage->SetVolume( image->GetBufferPointer() ); return mitkImage; } class mitkGlobalFeaturesTestSuite : public mitk::TestFixture { CPPUNIT_TEST_SUITE(mitkGlobalFeaturesTestSuite ); MITK_TEST(FirstOrder_SinglePoint); MITK_TEST(FirstOrder_QubicArea); //MITK_TEST(RunLenght_QubicArea); MITK_TEST(Coocurrence_QubicArea); //MITK_TEST(TestFirstOrderStatistic); // MITK_TEST(TestThreadedDecisionForest); CPPUNIT_TEST_SUITE_END(); private: typedef itk::Image ImageType; typedef itk::Image MaskType; mitk::Image::Pointer m_Image,m_Mask,m_Mask1; ImageType::Pointer m_ItkImage; MaskType::Pointer m_ItkMask,m_ItkMask1; mitk::Image::Pointer m_GradientImage, m_GradientMask; public: - void setUp(void) + void setUp(void) override { // Load Image Data m_Image = dynamic_cast(mitk::IOUtil::Load(GetTestDataFilePath("Pic3D.nrrd"))[0].GetPointer()); mitk::CastToItkImage(m_Image,m_ItkImage); // Create a single mask with only one pixel within the regions mitk::Image::Pointer mask1 = dynamic_cast(mitk::IOUtil::Load(GetTestDataFilePath("Pic3D.nrrd"))[0].GetPointer()); mitk::CastToItkImage(mask1,m_ItkMask); m_ItkMask->FillBuffer(0); MaskType::IndexType index; index[0]=88;index[1]=81;index[2]=13; m_ItkMask->SetPixel(index, 1); MITK_INFO << "Pixel Value: "<GetPixel(index); mitk::CastToMitkImage(m_ItkMask, m_Mask); // Create a mask with a covered region mitk::Image::Pointer lmask1 = dynamic_cast(mitk::IOUtil::Load(GetTestDataFilePath("Pic3D.nrrd"))[0].GetPointer()); mitk::CastToItkImage(lmask1,m_ItkMask1); m_ItkMask1->FillBuffer(0); int range=2; for (int x = 88-range;x < 88+range+1;++x) { for (int y=81-range;y<81+range+1;++y) { for (int z=13-range;z<13+range+1;++z) { index[0] = x; index[1] = y; index[2] = z; //MITK_INFO << "Pixel: " <GetPixel(index); m_ItkMask1->SetPixel(index, 1); } } } mitk::CastToMitkImage(m_ItkMask1, m_Mask1); m_GradientImage=GenerateGradientWithDimXImage(5,5,5); m_GradientMask = GenerateMaskImage(5,5,5); } void FirstOrder_SinglePoint() { mitk::GIFFirstOrderStatistics::Pointer calculator = mitk::GIFFirstOrderStatistics::New(); calculator->SetHistogramSize(4096); calculator->SetUseCtRange(true); auto features = calculator->CalculateFeatures(m_Image, m_Mask); std::map results; for (auto iter=features.begin(); iter!=features.end();++iter) { results[(*iter).first]=(*iter).second; MITK_INFO << (*iter).first << " : " << (*iter).second; } CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE("The range of a single pixel should be 0",0.0, results["FirstOrder Range"], 0); CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE("The uniformity of a single pixel should be 1",1.0, results["FirstOrder Uniformity"], 0); CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE("The entropy of a single pixel should be 0",0.0, results["FirstOrder Entropy"], 0); CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE("The Root-Means-Square of a single pixel with (-352) should be 352",352.0, results["FirstOrder RMS"], 0.01); CPPUNIT_ASSERT_EQUAL_MESSAGE("The Kurtosis of a single pixel should be undefined",results["FirstOrder Kurtosis"]==results["FirstOrder Kurtosis"], false); CPPUNIT_ASSERT_EQUAL_MESSAGE("The Skewness of a single pixel should be undefined",results["FirstOrder Skewness"]==results["FirstOrder Skewness"], false); CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE("The Mean absolute deviation of a single pixel with (-352) should be 0",0, results["FirstOrder Mean absolute deviation"], 0.0); CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE("The Covered image intensity range of a single pixel with (-352) should be 0",0, results["FirstOrder Covered Image Intensity Range"], 0.0); CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE("The Minimum of a single pixel with (-352) should be -352",-352, results["FirstOrder Minimum"], 0.0); CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE("The Maximum of a single pixel with (-352) should be -352",-352, results["FirstOrder Maximum"], 0.0); CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE("The Mean of a single pixel with (-352) should be -352",-352, results["FirstOrder Mean"], 0.0); CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE("The Variance (corrected) of a single pixel with (-352) should be 0",0, results["FirstOrder Variance"], 0.0); CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE("The Sum of a single pixel with (-352) should be -352",-352, results["FirstOrder Sum"], 0.0); CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE("The Median of a single pixel with (-352) should be -352",-352, results["FirstOrder Median"], 0.0); CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE("The Standard deviation (corrected) of a single pixel with (-352) should be -352",0, results["FirstOrder Standard deviation"], 0.0); CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE("The number of voxels of a single pixel should be 1",1, results["FirstOrder No. of Voxel"], 0.0); CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE("The Energy of a single pixel should be 352*352",352*352, results["FirstOrder Energy"], 0.0); // MITK_ASSERT_EQUAL(results["FirstOrder Range"]==0.0,true,"The range of a single pixel should be 0"); } void FirstOrder_QubicArea() { mitk::GIFFirstOrderStatistics::Pointer calculator = mitk::GIFFirstOrderStatistics::New(); calculator->SetHistogramSize(4096); calculator->SetUseCtRange(true); auto features = calculator->CalculateFeatures(m_Image, m_Mask1); std::map results; for (auto iter=features.begin(); iter!=features.end();++iter) { results[(*iter).first]=(*iter).second; MITK_INFO << (*iter).first << " : " << (*iter).second; } CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE("The range should be 981",981, results["FirstOrder Range"], 0); CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE("The Root-Means-Square of a single pixel with (-352) should be 352",402.895778, results["FirstOrder RMS"], 0.01); CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE("The Minimum of a single pixel with (-352) should be -352",-937, results["FirstOrder Minimum"], 0.0); CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE("The Maximum of a single pixel with (-352) should be -352",44, results["FirstOrder Maximum"], 0.0); CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE("The Mean of a single pixel with (-352) should be -352",-304.448, results["FirstOrder Mean"], 0.0); CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE("The Sum of a single pixel with (-352) should be -352",-38056, results["FirstOrder Sum"], 0.0); CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE("The Median of a single pixel with (-352) should be -352",-202, results["FirstOrder Median"], 0.0); CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE("The number of voxels of a single pixel should be 1",125, results["FirstOrder No. of Voxel"], 0.0); CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE("The Standard deviation (corrected) of a single pixel with (-352) should be -352",264.949066, results["FirstOrder Standard deviation"], 0.000001); CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE("The Energy of a single pixel should be 352*352",20290626, results["FirstOrder Energy"], 0.0); CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE("The uniformity of a single pixel should be 1",0.0088960, results["FirstOrder Uniformity"], 0.0000001); CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE("The entropy of a single pixel should be 0",-6.853784285, results["FirstOrder Entropy"], 0.000000005); CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE("The Variance (corrected) of a single pixel with (-352) should be 0",70198.0074, results["FirstOrder Variance"], 0.0001); CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE("The Kurtosis of a single pixel should be 0",2.63480121, results["FirstOrder Kurtosis"], 0.0001); CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE("The Skewness of a single pixel should be 0",-0.91817318, results["FirstOrder Skewness"], 0.00001); CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE("The Mean absolute deviation of a single pixel with (-352) should be 0",219.348608, results["FirstOrder Mean absolute deviation"], 0.000001); CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE("The Covered image intensity range of a single pixel with (-352) should be 0",0.41149329, results["FirstOrder Covered Image Intensity Range"], 0.000001); } void RunLenght_QubicArea() { mitk::GIFGrayLevelRunLength::Pointer calculator = mitk::GIFGrayLevelRunLength::New(); //calculator->SetHistogramSize(4096); calculator->SetUseCtRange(true); calculator->SetRange(981); auto features = calculator->CalculateFeatures(m_Image, m_Mask1); std::map results; for (auto iter=features.begin(); iter!=features.end();++iter) { results[(*iter).first]=(*iter).second; MITK_INFO << (*iter).first << " : " << (*iter).second; } } void Coocurrence_QubicArea() { /* * Expected Matrix: (Direction 0,0,1) * |------------------------| * | 20 | 0 | 0 | 0 | 0 | * |------------------------| * | 0 | 20 | 0 | 0 | 0 | * |------------------------| * | 0 | 0 | 20 | 0 | 0 | * |------------------------| * | 0 | 0 | 0 | 20 | 0 | * |------------------------| * | 0 | 0 | 0 | 0 | 20 | * |------------------------| * Expected Matrix: (Direction (1,0,0),(0,1,0)) * |------------------------| * | 20 | 0 | 0 | 0 | 0 | * |------------------------| * | 20 | 0 | 0 | 0 | 0 | * |------------------------| * | 20 | 0 | 0 | 0 | 0 | * |------------------------| * | 20 | 0 | 0 | 0 | 0 | * |------------------------| * | 20 | 0 | 0 | 0 | 0 | * |------------------------| */ mitk::GIFCooccurenceMatrix::Pointer calculator = mitk::GIFCooccurenceMatrix::New(); //calculator->SetHistogramSize(4096); //calculator->SetUseCtRange(true); //calculator->SetRange(981); calculator->SetDirection(1); auto features = calculator->CalculateFeatures(m_GradientImage, m_GradientMask); std::map results; for (auto iter=features.begin(); iter!=features.end();++iter) { results[(*iter).first]=(*iter).second; MITK_INFO << (*iter).first << " : " << (*iter).second; } CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE("The mean energy value should be 0.2",0.2, results["co-occ. (1) Energy Means"], mitk::eps); CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE("The mean entropy value should be 0.2",2.321928, results["co-occ. (1) Entropy Means"], 0.000001); CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE("The mean contrast value should be 0.0",0, results["co-occ. (1) Contrast Means"], mitk::eps); CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE("The mean dissimilarity value should be 0.0",0, results["co-occ. (1) Dissimilarity Means"], mitk::eps); CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE("The mean homogenity1 value should be 1.0",1, results["co-occ. (1) Homogeneity1 Means"], mitk::eps); CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE("The mean InverseDifferenceMoment value should be 1.0",1, results["co-occ. (1) InverseDifferenceMoment Means"], mitk::eps); } }; MITK_TEST_SUITE_REGISTRATION(mitkGlobalFeatures) \ No newline at end of file diff --git a/Modules/Core/src/IO/mitkIOUtil.cpp b/Modules/Core/src/IO/mitkIOUtil.cpp index 3f4a0429f4..bf9dac59ad 100644 --- a/Modules/Core/src/IO/mitkIOUtil.cpp +++ b/Modules/Core/src/IO/mitkIOUtil.cpp @@ -1,1062 +1,1062 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "mitkIOUtil.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include // ITK #include // VTK #include #include #include #include #include static std::string GetLastErrorStr() { #ifdef US_PLATFORM_POSIX return std::string(strerror(errno)); #else // Retrieve the system error message for the last-error code LPVOID lpMsgBuf; DWORD dw = GetLastError(); FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, nullptr, dw, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR)&lpMsgBuf, 0, nullptr); std::string errMsg((LPCTSTR)lpMsgBuf); LocalFree(lpMsgBuf); return errMsg; #endif } #ifdef US_PLATFORM_WINDOWS #include #include // make the posix flags point to the obsolte bsd types on windows #define S_IRUSR S_IREAD #define S_IWUSR S_IWRITE #else #include #include #include #endif #include #include static const char validLetters[] = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"; // A cross-platform version of the mkstemps function static int mkstemps_compat(char *tmpl, int suffixlen) { static unsigned long long value = 0; int savedErrno = errno; // Lower bound on the number of temporary files to attempt to generate. #define ATTEMPTS_MIN (62 * 62 * 62) /* The number of times to attempt to generate a temporary file. To conform to POSIX, this must be no smaller than TMP_MAX. */ #if ATTEMPTS_MIN < TMP_MAX const unsigned int attempts = TMP_MAX; #else const unsigned int attempts = ATTEMPTS_MIN; #endif const int len = strlen(tmpl); if ((len - suffixlen) < 6 || strncmp(&tmpl[len - 6 - suffixlen], "XXXXXX", 6)) { errno = EINVAL; return -1; } /* This is where the Xs start. */ char *XXXXXX = &tmpl[len - 6 - suffixlen]; /* Get some more or less random data. */ #ifdef US_PLATFORM_WINDOWS { SYSTEMTIME stNow; FILETIME ftNow; // get system time GetSystemTime(&stNow); stNow.wMilliseconds = 500; if (!SystemTimeToFileTime(&stNow, &ftNow)) { errno = -1; return -1; } unsigned long long randomTimeBits = ((static_cast(ftNow.dwHighDateTime) << 32) | static_cast(ftNow.dwLowDateTime)); value = randomTimeBits ^ static_cast(GetCurrentThreadId()); } #else { struct timeval tv; gettimeofday(&tv, nullptr); unsigned long long randomTimeBits = ((static_cast(tv.tv_usec) << 32) | static_cast(tv.tv_sec)); value = randomTimeBits ^ static_cast(getpid()); } #endif for (unsigned int count = 0; count < attempts; value += 7777, ++count) { unsigned long long v = value; /* Fill in the random bits. */ XXXXXX[0] = validLetters[v % 62]; v /= 62; XXXXXX[1] = validLetters[v % 62]; v /= 62; XXXXXX[2] = validLetters[v % 62]; v /= 62; XXXXXX[3] = validLetters[v % 62]; v /= 62; XXXXXX[4] = validLetters[v % 62]; v /= 62; XXXXXX[5] = validLetters[v % 62]; int fd = open(tmpl, O_RDWR | O_CREAT | O_EXCL, S_IRUSR | S_IWUSR); if (fd >= 0) { errno = savedErrno; return fd; } else if (errno != EEXIST) { return -1; } } /* We got out of the loop because we ran out of combinations to try. */ errno = EEXIST; return -1; } // A cross-platform version of the POSIX mkdtemp function static char *mkdtemps_compat(char *tmpl, int suffixlen) { static unsigned long long value = 0; int savedErrno = errno; // Lower bound on the number of temporary dirs to attempt to generate. #define ATTEMPTS_MIN (62 * 62 * 62) /* The number of times to attempt to generate a temporary dir. To conform to POSIX, this must be no smaller than TMP_MAX. */ #if ATTEMPTS_MIN < TMP_MAX const unsigned int attempts = TMP_MAX; #else const unsigned int attempts = ATTEMPTS_MIN; #endif const int len = strlen(tmpl); if ((len - suffixlen) < 6 || strncmp(&tmpl[len - 6 - suffixlen], "XXXXXX", 6)) { errno = EINVAL; return nullptr; } /* This is where the Xs start. */ char *XXXXXX = &tmpl[len - 6 - suffixlen]; /* Get some more or less random data. */ #ifdef US_PLATFORM_WINDOWS { SYSTEMTIME stNow; FILETIME ftNow; // get system time GetSystemTime(&stNow); stNow.wMilliseconds = 500; if (!SystemTimeToFileTime(&stNow, &ftNow)) { errno = -1; return nullptr; } unsigned long long randomTimeBits = ((static_cast(ftNow.dwHighDateTime) << 32) | static_cast(ftNow.dwLowDateTime)); value = randomTimeBits ^ static_cast(GetCurrentThreadId()); } #else { struct timeval tv; gettimeofday(&tv, nullptr); unsigned long long randomTimeBits = ((static_cast(tv.tv_usec) << 32) | static_cast(tv.tv_sec)); value = randomTimeBits ^ static_cast(getpid()); } #endif unsigned int count = 0; for (; count < attempts; value += 7777, ++count) { unsigned long long v = value; /* Fill in the random bits. */ XXXXXX[0] = validLetters[v % 62]; v /= 62; XXXXXX[1] = validLetters[v % 62]; v /= 62; XXXXXX[2] = validLetters[v % 62]; v /= 62; XXXXXX[3] = validLetters[v % 62]; v /= 62; XXXXXX[4] = validLetters[v % 62]; v /= 62; XXXXXX[5] = validLetters[v % 62]; #ifdef US_PLATFORM_WINDOWS int fd = _mkdir(tmpl); //, _S_IREAD | _S_IWRITE | _S_IEXEC); #else int fd = mkdir(tmpl, S_IRUSR | S_IWUSR | S_IXUSR); #endif if (fd >= 0) { errno = savedErrno; return tmpl; } else if (errno != EEXIST) { return nullptr; } } /* We got out of the loop because we ran out of combinations to try. */ errno = EEXIST; return nullptr; } //#endif //************************************************************** // mitk::IOUtil method definitions namespace mitk { struct IOUtil::Impl { struct FixedReaderOptionsFunctor : public ReaderOptionsFunctorBase { FixedReaderOptionsFunctor(const IFileReader::Options &options) : m_Options(options) {} - virtual bool operator()(LoadInfo &loadInfo) const override + bool operator()(LoadInfo &loadInfo) const override { IFileReader *reader = loadInfo.m_ReaderSelector.GetSelected().GetReader(); if (reader) { reader->SetOptions(m_Options); } return false; } private: const IFileReader::Options &m_Options; }; struct FixedWriterOptionsFunctor : public WriterOptionsFunctorBase { FixedWriterOptionsFunctor(const IFileReader::Options &options) : m_Options(options) {} - virtual bool operator()(SaveInfo &saveInfo) const override + bool operator()(SaveInfo &saveInfo) const override { IFileWriter *writer = saveInfo.m_WriterSelector.GetSelected().GetWriter(); if (writer) { writer->SetOptions(m_Options); } return false; } private: const IFileWriter::Options &m_Options; }; static BaseData::Pointer LoadBaseDataFromFile(const std::string &path, const ReaderOptionsFunctorBase* optionsCallback = nullptr); static void SetDefaultDataNodeProperties(mitk::DataNode *node, const std::string &filePath = std::string()); }; BaseData::Pointer IOUtil::Impl::LoadBaseDataFromFile(const std::string &path, const ReaderOptionsFunctorBase *optionsCallback) { std::vector baseDataList = Load(path, optionsCallback); // The Load(path) call above should throw an exception if nothing could be loaded assert(!baseDataList.empty()); return baseDataList.front(); } #ifdef US_PLATFORM_WINDOWS std::string IOUtil::GetProgramPath() { char path[512]; std::size_t index = std::string(path, GetModuleFileName(nullptr, path, 512)).find_last_of('\\'); return std::string(path, index); } #elif defined(US_PLATFORM_APPLE) #include std::string IOUtil::GetProgramPath() { char path[512]; uint32_t size = sizeof(path); if (_NSGetExecutablePath(path, &size) == 0) { std::size_t index = std::string(path).find_last_of('/'); std::string strPath = std::string(path, index); // const char* execPath = strPath.c_str(); // mitk::StandardFileLocations::GetInstance()->AddDirectoryForSearch(execPath,false); return strPath; } return std::string(); } #else #include #include #include std::string IOUtil::GetProgramPath() { std::stringstream ss; ss << "/proc/" << getpid() << "/exe"; char proc[512] = {0}; ssize_t ch = readlink(ss.str().c_str(), proc, 512); if (ch == -1) return std::string(); std::size_t index = std::string(proc).find_last_of('/'); return std::string(proc, index); } #endif char IOUtil::GetDirectorySeparator() { #ifdef US_PLATFORM_WINDOWS return '\\'; #else return '/'; #endif } std::string IOUtil::GetTempPath() { static std::string result; if (result.empty()) { #ifdef US_PLATFORM_WINDOWS char tempPathTestBuffer[1]; DWORD bufferLength = ::GetTempPath(1, tempPathTestBuffer); if (bufferLength == 0) { mitkThrow() << GetLastErrorStr(); } std::vector tempPath(bufferLength); bufferLength = ::GetTempPath(bufferLength, &tempPath[0]); if (bufferLength == 0) { mitkThrow() << GetLastErrorStr(); } result.assign(tempPath.begin(), tempPath.begin() + static_cast(bufferLength)); #else result = "/tmp/"; #endif } return result; } std::string IOUtil::CreateTemporaryFile(const std::string &templateName, std::string path) { ofstream tmpOutputStream; std::string returnValue = CreateTemporaryFile(tmpOutputStream, templateName, path); tmpOutputStream.close(); return returnValue; } std::string IOUtil::CreateTemporaryFile(std::ofstream &f, const std::string &templateName, std::string path) { return CreateTemporaryFile(f, std::ios_base::out | std::ios_base::trunc, templateName, path); } std::string IOUtil::CreateTemporaryFile(std::ofstream &f, std::ios_base::openmode mode, const std::string &templateName, std::string path) { if (path.empty()) { path = GetTempPath(); } path += templateName; std::vector dst_path(path.begin(), path.end()); dst_path.push_back('\0'); std::size_t lastX = path.find_last_of('X'); std::size_t firstX = path.find_last_not_of('X', lastX); int firstNonX = firstX == std::string::npos ? -1 : firstX - 1; while (lastX != std::string::npos && (lastX - firstNonX) < 6) { lastX = path.find_last_of('X', firstX); firstX = path.find_last_not_of('X', lastX); firstNonX = firstX == std::string::npos ? -1 : firstX - 1; } std::size_t suffixlen = lastX == std::string::npos ? path.size() : path.size() - lastX - 1; int fd = mkstemps_compat(&dst_path[0], suffixlen); if (fd != -1) { path.assign(dst_path.begin(), dst_path.end() - 1); f.open(path.c_str(), mode | std::ios_base::out | std::ios_base::trunc); close(fd); } else { mitkThrow() << "Creating temporary file " << &dst_path[0] << " failed: " << GetLastErrorStr(); } return path; } std::string IOUtil::CreateTemporaryDirectory(const std::string &templateName, std::string path) { if (path.empty()) { path = GetTempPath(); } path += GetDirectorySeparator() + templateName; std::vector dst_path(path.begin(), path.end()); dst_path.push_back('\0'); std::size_t lastX = path.find_last_of('X'); std::size_t firstX = path.find_last_not_of('X', lastX); int firstNonX = firstX == std::string::npos ? -1 : firstX - 1; while (lastX != std::string::npos && (lastX - firstNonX) < 6) { lastX = path.find_last_of('X', firstX); firstX = path.find_last_not_of('X', lastX); firstNonX = firstX == std::string::npos ? -1 : firstX - 1; } std::size_t suffixlen = lastX == std::string::npos ? path.size() : path.size() - lastX - 1; if (mkdtemps_compat(&dst_path[0], suffixlen) == nullptr) { mitkThrow() << "Creating temporary directory " << &dst_path[0] << " failed: " << GetLastErrorStr(); } path.assign(dst_path.begin(), dst_path.end() - 1); return path; } DataStorage::SetOfObjects::Pointer IOUtil::Load(const std::string &path, DataStorage &storage, const ReaderOptionsFunctorBase *optionsCallback) { std::vector paths; paths.push_back(path); return Load(paths, storage, optionsCallback); } DataStorage::SetOfObjects::Pointer IOUtil::Load(const std::string &path, const IFileReader::Options &options, DataStorage &storage) { std::vector loadInfos; loadInfos.push_back(LoadInfo(path)); DataStorage::SetOfObjects::Pointer nodeResult = DataStorage::SetOfObjects::New(); Impl::FixedReaderOptionsFunctor optionsCallback(options); std::string errMsg = Load(loadInfos, nodeResult, &storage, &optionsCallback); if (!errMsg.empty()) { mitkThrow() << errMsg; } return nodeResult; } std::vector IOUtil::Load(const std::string &path, const ReaderOptionsFunctorBase *optionsCallback) { std::vector paths; paths.push_back(path); return Load(paths, optionsCallback); } std::vector IOUtil::Load(const std::string &path, const IFileReader::Options &options) { std::vector loadInfos; loadInfos.push_back(LoadInfo(path)); Impl::FixedReaderOptionsFunctor optionsCallback(options); std::string errMsg = Load(loadInfos, nullptr, nullptr, &optionsCallback); if (!errMsg.empty()) { mitkThrow() << errMsg; } return loadInfos.front().m_Output; } DataStorage::SetOfObjects::Pointer IOUtil::Load(const std::vector &paths, DataStorage &storage, const ReaderOptionsFunctorBase *optionsCallback) { DataStorage::SetOfObjects::Pointer nodeResult = DataStorage::SetOfObjects::New(); std::vector loadInfos; for (auto loadInfo : paths) { loadInfos.push_back(loadInfo); } std::string errMsg = Load(loadInfos, nodeResult, &storage, optionsCallback); if (!errMsg.empty()) { mitkThrow() << errMsg; } return nodeResult; } std::vector IOUtil::Load(const std::vector &paths, const ReaderOptionsFunctorBase *optionsCallback) { std::vector result; std::vector loadInfos; for (auto loadInfo : paths) { loadInfos.push_back(loadInfo); } std::string errMsg = Load(loadInfos, nullptr, nullptr, optionsCallback); if (!errMsg.empty()) { mitkThrow() << errMsg; } for (std::vector::const_iterator iter = loadInfos.begin(), iterEnd = loadInfos.end(); iter != iterEnd; ++iter) { result.insert(result.end(), iter->m_Output.begin(), iter->m_Output.end()); } return result; } Image::Pointer IOUtil::LoadImage(const std::string &path, const ReaderOptionsFunctorBase *optionsCallback) { BaseData::Pointer baseData = Impl::LoadBaseDataFromFile(path, optionsCallback); mitk::Image::Pointer image = dynamic_cast(baseData.GetPointer()); if (image.IsNull()) { mitkThrow() << path << " is not a mitk::Image but a " << baseData->GetNameOfClass(); } return image; } Surface::Pointer IOUtil::LoadSurface(const std::string &path, const ReaderOptionsFunctorBase *optionsCallback) { BaseData::Pointer baseData = Impl::LoadBaseDataFromFile(path, optionsCallback); mitk::Surface::Pointer surface = dynamic_cast(baseData.GetPointer()); if (surface.IsNull()) { mitkThrow() << path << " is not a mitk::Surface but a " << baseData->GetNameOfClass(); } return surface; } PointSet::Pointer IOUtil::LoadPointSet(const std::string &path, const ReaderOptionsFunctorBase *optionsCallback) { BaseData::Pointer baseData = Impl::LoadBaseDataFromFile(path, optionsCallback); mitk::PointSet::Pointer pointset = dynamic_cast(baseData.GetPointer()); if (pointset.IsNull()) { mitkThrow() << path << " is not a mitk::PointSet but a " << baseData->GetNameOfClass(); } return pointset; } std::string IOUtil::Load(std::vector &loadInfos, DataStorage::SetOfObjects *nodeResult, DataStorage *ds, const ReaderOptionsFunctorBase *optionsCallback) { if (loadInfos.empty()) { return "No input files given"; } int filesToRead = loadInfos.size(); mitk::ProgressBar::GetInstance()->AddStepsToDo(2 * filesToRead); std::string errMsg; std::map usedReaderItems; std::vector< std::string > read_files; for (auto &loadInfo : loadInfos) { if(std::find(read_files.begin(), read_files.end(), loadInfo.m_Path) != read_files.end()) continue; std::vector readers = loadInfo.m_ReaderSelector.Get(); if (readers.empty()) { if (!itksys::SystemTools::FileExists(loadInfo.m_Path.c_str())) { errMsg += "File '" + loadInfo.m_Path + "' does not exist\n"; } else { errMsg += "No reader available for '" + loadInfo.m_Path + "'\n"; } continue; } bool callOptionsCallback = readers.size() > 1 || !readers.front().GetReader()->GetOptions().empty(); // check if we already used a reader which should be re-used std::vector currMimeTypes = loadInfo.m_ReaderSelector.GetMimeTypes(); std::string selectedMimeType; for (std::vector::const_iterator mimeTypeIter = currMimeTypes.begin(), mimeTypeIterEnd = currMimeTypes.end(); mimeTypeIter != mimeTypeIterEnd; ++mimeTypeIter) { std::map::const_iterator oldSelectedItemIter = usedReaderItems.find(mimeTypeIter->GetName()); if (oldSelectedItemIter != usedReaderItems.end()) { // we found an already used item for a mime-type which is contained // in the current reader set, check all current readers if there service // id equals the old reader for (std::vector::const_iterator currReaderItem = readers.begin(), currReaderItemEnd = readers.end(); currReaderItem != currReaderItemEnd; ++currReaderItem) { if (currReaderItem->GetMimeType().GetName() == mimeTypeIter->GetName() && currReaderItem->GetServiceId() == oldSelectedItemIter->second.GetServiceId() && currReaderItem->GetConfidenceLevel() >= oldSelectedItemIter->second.GetConfidenceLevel()) { // okay, we used the same reader already, re-use its options selectedMimeType = mimeTypeIter->GetName(); callOptionsCallback = false; loadInfo.m_ReaderSelector.Select(oldSelectedItemIter->second.GetServiceId()); loadInfo.m_ReaderSelector.GetSelected().GetReader()->SetOptions( oldSelectedItemIter->second.GetReader()->GetOptions()); break; } } if (!selectedMimeType.empty()) break; } } if (callOptionsCallback && optionsCallback) { callOptionsCallback = (*optionsCallback)(loadInfo); if (!callOptionsCallback && !loadInfo.m_Cancel) { usedReaderItems.erase(selectedMimeType); FileReaderSelector::Item selectedItem = loadInfo.m_ReaderSelector.GetSelected(); usedReaderItems.insert(std::make_pair(selectedItem.GetMimeType().GetName(), selectedItem)); } } if (loadInfo.m_Cancel) { errMsg += "Reading operation(s) cancelled."; break; } IFileReader *reader = loadInfo.m_ReaderSelector.GetSelected().GetReader(); if (reader == nullptr) { errMsg += "Unexpected nullptr reader."; break; } // Do the actual reading try { DataStorage::SetOfObjects::Pointer nodes; if (ds != nullptr) { nodes = reader->Read(*ds); std::vector< std::string > new_files = reader->GetReadFiles(); read_files.insert( read_files.end(), new_files.begin(), new_files.end() ); } else { nodes = DataStorage::SetOfObjects::New(); std::vector baseData = reader->Read(); for (std::vector::iterator iter = baseData.begin(); iter != baseData.end(); ++iter) { if (iter->IsNotNull()) { mitk::DataNode::Pointer node = mitk::DataNode::New(); node->SetData(*iter); nodes->InsertElement(nodes->Size(), node); } } std::vector< std::string > new_files = reader->GetReadFiles(); read_files.insert( read_files.end(), new_files.begin(), new_files.end() ); } for (DataStorage::SetOfObjects::ConstIterator nodeIter = nodes->Begin(), nodeIterEnd = nodes->End(); nodeIter != nodeIterEnd; ++nodeIter) { const mitk::DataNode::Pointer &node = nodeIter->Value(); mitk::BaseData::Pointer data = node->GetData(); if (data.IsNull()) { continue; } mitk::StringProperty::Pointer pathProp = mitk::StringProperty::New(loadInfo.m_Path); data->SetProperty("path", pathProp); loadInfo.m_Output.push_back(data); if (nodeResult) { nodeResult->push_back(nodeIter->Value()); } } if (loadInfo.m_Output.empty() || (nodeResult && nodeResult->Size() == 0)) { errMsg += "Unknown read error occurred reading " + loadInfo.m_Path; } } catch (const std::exception &e) { errMsg += "Exception occured when reading file " + loadInfo.m_Path + ":\n" + e.what() + "\n\n"; } mitk::ProgressBar::GetInstance()->Progress(2); --filesToRead; } if (!errMsg.empty()) { MITK_ERROR << errMsg; } mitk::ProgressBar::GetInstance()->Progress(2 * filesToRead); return errMsg; } std::vector IOUtil::Load(const us::ModuleResource &usResource, std::ios_base::openmode mode) { us::ModuleResourceStream resStream(usResource, mode); mitk::CoreServicePointer mimeTypeProvider(mitk::CoreServices::GetMimeTypeProvider()); std::vector mimetypes = mimeTypeProvider->GetMimeTypesForFile(usResource.GetResourcePath()); std::vector data; if (mimetypes.empty()) { mitkThrow() << "No mimetype for resource stream: " << usResource.GetResourcePath(); return data; } mitk::FileReaderRegistry fileReaderRegistry; std::vector> refs = fileReaderRegistry.GetReferences(mimetypes[0]); if (refs.empty()) { mitkThrow() << "No reader available for resource stream: " << usResource.GetResourcePath(); return data; } mitk::IFileReader *reader = fileReaderRegistry.GetReader(refs[0]); reader->SetInput(usResource.GetResourcePath(), &resStream); data = reader->Read(); return data; } void IOUtil::Save(const BaseData *data, const std::string &path) { Save(data, path, IFileWriter::Options()); } void IOUtil::Save(const BaseData *data, const std::string &path, const IFileWriter::Options &options) { Save(data, std::string(), path, options); } void IOUtil::Save(const BaseData *data, const std::string &mimeType, const std::string &path, bool addExtension) { Save(data, mimeType, path, IFileWriter::Options(), addExtension); } void IOUtil::Save(const BaseData *data, const std::string &mimeType, const std::string &path, const IFileWriter::Options &options, bool addExtension) { if ((data == nullptr) || (data->IsEmpty())) mitkThrow() << "BaseData cannotbe null or empty for save methods in IOUtil.h."; std::string errMsg; if (options.empty()) { errMsg = Save(data, mimeType, path, nullptr, addExtension); } else { Impl::FixedWriterOptionsFunctor optionsCallback(options); errMsg = Save(data, mimeType, path, &optionsCallback, addExtension); } if (!errMsg.empty()) { mitkThrow() << errMsg; } } void IOUtil::Save(std::vector &saveInfos) { std::string errMsg = Save(saveInfos, nullptr); if (!errMsg.empty()) { mitkThrow() << errMsg; } } std::string IOUtil::Save(const BaseData *data, const std::string &mimeTypeName, const std::string &path, WriterOptionsFunctorBase *optionsCallback, bool addExtension) { if (path.empty()) { return "No output filename given"; } mitk::CoreServicePointer mimeTypeProvider(mitk::CoreServices::GetMimeTypeProvider()); MimeType mimeType = mimeTypeProvider->GetMimeTypeForName(mimeTypeName); SaveInfo saveInfo(data, mimeType, path); std::string ext = itksys::SystemTools::GetFilenameExtension(path); if (saveInfo.m_WriterSelector.IsEmpty()) { return std::string("No suitable writer found for the current data of type ") + data->GetNameOfClass() + (mimeType.IsValid() ? (std::string(" and mime-type ") + mimeType.GetName()) : std::string()) + (ext.empty() ? std::string() : (std::string(" with extension ") + ext)); } // Add an extension if not already specified if (ext.empty() && addExtension) { saveInfo.m_MimeType.GetExtensions().empty() ? std::string() : "." + saveInfo.m_MimeType.GetExtensions().front(); } std::vector infos; infos.push_back(saveInfo); return Save(infos, optionsCallback); } std::string IOUtil::Save(std::vector &saveInfos, WriterOptionsFunctorBase *optionsCallback) { if (saveInfos.empty()) { return "No data for saving available"; } int filesToWrite = saveInfos.size(); mitk::ProgressBar::GetInstance()->AddStepsToDo(2 * filesToWrite); std::string errMsg; std::set usedSaveInfos; for (auto &saveInfo : saveInfos) { const std::string baseDataType = saveInfo.m_BaseData->GetNameOfClass(); std::vector writers = saveInfo.m_WriterSelector.Get(); // Error out if no compatible Writer was found if (writers.empty()) { errMsg += std::string("No writer available for ") + baseDataType + " data.\n"; continue; } bool callOptionsCallback = writers.size() > 1 || !writers[0].GetWriter()->GetOptions().empty(); // check if we already used a writer for this base data type // which should be re-used std::set::const_iterator oldSaveInfoIter = usedSaveInfos.find(saveInfo); if (oldSaveInfoIter != usedSaveInfos.end()) { // we previously saved a base data object of the same data with the same mime-type, // check if the same writer is contained in the current writer set and if the // confidence level matches FileWriterSelector::Item oldSelectedItem = oldSaveInfoIter->m_WriterSelector.Get(oldSaveInfoIter->m_WriterSelector.GetSelectedId()); for (std::vector::const_iterator currWriterItem = writers.begin(), currWriterItemEnd = writers.end(); currWriterItem != currWriterItemEnd; ++currWriterItem) { if (currWriterItem->GetServiceId() == oldSelectedItem.GetServiceId() && currWriterItem->GetConfidenceLevel() >= oldSelectedItem.GetConfidenceLevel()) { // okay, we used the same writer already, re-use its options callOptionsCallback = false; saveInfo.m_WriterSelector.Select(oldSaveInfoIter->m_WriterSelector.GetSelectedId()); saveInfo.m_WriterSelector.GetSelected().GetWriter()->SetOptions(oldSelectedItem.GetWriter()->GetOptions()); break; } } } if (callOptionsCallback && optionsCallback) { callOptionsCallback = (*optionsCallback)(saveInfo); if (!callOptionsCallback && !saveInfo.m_Cancel) { usedSaveInfos.erase(saveInfo); usedSaveInfos.insert(saveInfo); } } if (saveInfo.m_Cancel) { errMsg += "Writing operation(s) cancelled."; break; } IFileWriter *writer = saveInfo.m_WriterSelector.GetSelected().GetWriter(); if (writer == nullptr) { errMsg += "Unexpected nullptr writer."; break; } // Do the actual writing try { writer->SetOutputLocation(saveInfo.m_Path); writer->Write(); } catch (const std::exception &e) { errMsg += std::string("Exception occurred when writing to ") + saveInfo.m_Path + ":\n" + e.what() + "\n"; } mitk::ProgressBar::GetInstance()->Progress(2); --filesToWrite; } if (!errMsg.empty()) { MITK_ERROR << errMsg; } mitk::ProgressBar::GetInstance()->Progress(2 * filesToWrite); return errMsg; } // This method can be removed after the deprecated LoadDataNode() method was removed void IOUtil::Impl::SetDefaultDataNodeProperties(DataNode *node, const std::string &filePath) { // path mitk::StringProperty::Pointer pathProp = mitk::StringProperty::New(itksys::SystemTools::GetFilenamePath(filePath)); node->SetProperty(StringProperty::PATH, pathProp); // name already defined? mitk::StringProperty::Pointer nameProp = dynamic_cast(node->GetProperty("name")); if (nameProp.IsNull() || (strcmp(nameProp->GetValue(), "No Name!") == 0)) { // name already defined in BaseData mitk::StringProperty::Pointer baseDataNameProp = dynamic_cast(node->GetData()->GetProperty("name").GetPointer()); if (baseDataNameProp.IsNull() || (strcmp(baseDataNameProp->GetValue(), "No Name!") == 0)) { // name neither defined in node, nor in BaseData -> name = filename nameProp = mitk::StringProperty::New(itksys::SystemTools::GetFilenameWithoutExtension(filePath)); node->SetProperty("name", nameProp); } else { // name defined in BaseData! nameProp = mitk::StringProperty::New(baseDataNameProp->GetValue()); node->SetProperty("name", nameProp); } } // visibility if (!node->GetProperty("visible")) { node->SetVisibility(true); } } IOUtil::SaveInfo::SaveInfo(const BaseData *baseData, const MimeType &mimeType, const std::string &path) : m_BaseData(baseData), m_WriterSelector(baseData, mimeType.GetName(), path), m_MimeType(mimeType.IsValid() ? mimeType // use the original mime-type : (m_WriterSelector.IsEmpty() ? mimeType // no writer found, use the original invalid mime-type : m_WriterSelector.GetDefault().GetMimeType() // use the found default mime-type )), m_Path(path), m_Cancel(false) { } bool IOUtil::SaveInfo::operator<(const IOUtil::SaveInfo &other) const { int r = strcmp(m_BaseData->GetNameOfClass(), other.m_BaseData->GetNameOfClass()); if (r == 0) { return m_WriterSelector.GetSelected().GetMimeType() < other.m_WriterSelector.GetSelected().GetMimeType(); } return r < 0; } IOUtil::LoadInfo::LoadInfo(const std::string &path) : m_Path(path), m_ReaderSelector(path), m_Cancel(false) {} } diff --git a/Modules/Core/src/mitkCoreActivator.cpp b/Modules/Core/src/mitkCoreActivator.cpp index 785e45b8e9..9c4f779b06 100644 --- a/Modules/Core/src/mitkCoreActivator.cpp +++ b/Modules/Core/src/mitkCoreActivator.cpp @@ -1,324 +1,324 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "mitkCoreActivator.h" // File IO #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "mitkDicomSeriesReaderService.h" #include "mitkLegacyFileWriterService.h" #include #include #include // Micro Services #include #include #include #include #include #include #include #include #include #include // ITK "injects" static initialization code for IO factories // via the itkImageIOFactoryRegisterManager.h header (which // is generated in the application library build directory). // To ensure that the code is called *before* the CppMicroServices // static initialization code (which triggers the Activator::Start // method), we include the ITK header here. #include void HandleMicroServicesMessages(us::MsgType type, const char *msg) { switch (type) { case us::DebugMsg: MITK_DEBUG << msg; break; case us::InfoMsg: MITK_INFO << msg; break; case us::WarningMsg: MITK_WARN << msg; break; case us::ErrorMsg: MITK_ERROR << msg; break; } } void AddMitkAutoLoadPaths(const std::string &programPath) { us::ModuleSettings::AddAutoLoadPath(programPath); #ifdef __APPLE__ // Walk up three directories since that is where the .dylib files are located // for build trees. std::string additionalPath = programPath; bool addPath = true; for (int i = 0; i < 3; ++i) { std::size_t index = additionalPath.find_last_of('/'); if (index != std::string::npos) { additionalPath = additionalPath.substr(0, index); } else { addPath = false; break; } } if (addPath) { us::ModuleSettings::AddAutoLoadPath(additionalPath); } #endif } class FixedNiftiImageIO : public itk::NiftiImageIO { public: /** Standard class typedefs. */ typedef FixedNiftiImageIO Self; typedef itk::NiftiImageIO Superclass; typedef itk::SmartPointer Pointer; /** Method for creation through the object factory. */ itkNewMacro(Self) /** Run-time type information (and related methods). */ itkTypeMacro(FixedNiftiImageIO, Superclass) - virtual bool SupportsDimension(unsigned long dim) override + bool SupportsDimension(unsigned long dim) override { return dim > 1 && dim < 5; } }; void MitkCoreActivator::Load(us::ModuleContext *context) { // Handle messages from CppMicroServices us::installMsgHandler(HandleMicroServicesMessages); this->m_Context = context; // Add the current application directory to the auto-load paths. // This is useful for third-party executables. std::string programPath = mitk::IOUtil::GetProgramPath(); if (programPath.empty()) { MITK_WARN << "Could not get the program path."; } else { AddMitkAutoLoadPaths(programPath); } // m_RenderingManager = mitk::RenderingManager::New(); // context->RegisterService(renderingManager.GetPointer()); m_PlanePositionManager.reset(new mitk::PlanePositionManagerService); context->RegisterService(m_PlanePositionManager.get()); m_PropertyAliases.reset(new mitk::PropertyAliases); context->RegisterService(m_PropertyAliases.get()); m_PropertyDescriptions.reset(new mitk::PropertyDescriptions); context->RegisterService(m_PropertyDescriptions.get()); m_PropertyExtensions.reset(new mitk::PropertyExtensions); context->RegisterService(m_PropertyExtensions.get()); m_PropertyFilters.reset(new mitk::PropertyFilters); context->RegisterService(m_PropertyFilters.get()); m_PropertyPersistence.reset(new mitk::PropertyPersistence); context->RegisterService(m_PropertyPersistence.get()); m_MimeTypeProvider.reset(new mitk::MimeTypeProvider); m_MimeTypeProvider->Start(); m_MimeTypeProviderReg = context->RegisterService(m_MimeTypeProvider.get()); this->RegisterDefaultMimeTypes(); this->RegisterItkReaderWriter(); this->RegisterVtkReaderWriter(); // Add custom Reader / Writer Services m_FileReaders.push_back(new mitk::PointSetReaderService()); m_FileWriters.push_back(new mitk::PointSetWriterService()); m_FileReaders.push_back(new mitk::GeometryDataReaderService()); m_FileWriters.push_back(new mitk::GeometryDataWriterService()); m_FileReaders.push_back(new mitk::DicomSeriesReaderService()); m_FileReaders.push_back(new mitk::RawImageFileReaderService()); /* There IS an option to exchange ALL vtkTexture instances against vtkNeverTranslucentTextureFactory. This code is left here as a reminder, just in case we might need to do that some time. vtkNeverTranslucentTextureFactory* textureFactory = vtkNeverTranslucentTextureFactory::New(); vtkObjectFactory::RegisterFactory( textureFactory ); textureFactory->Delete(); */ this->RegisterLegacyWriter(); } void MitkCoreActivator::Unload(us::ModuleContext *) { for (auto &elem : m_FileReaders) { delete elem; } for (auto &elem : m_FileWriters) { delete elem; } for (auto &elem : m_FileIOs) { delete elem; } for (auto &elem : m_LegacyWriters) { delete elem; } // The mitk::ModuleContext* argument of the Unload() method // will always be 0 for the Mitk library. It makes no sense // to use it at this stage anyway, since all libraries which // know about the module system have already been unloaded. // we need to close the internal service tracker of the // MimeTypeProvider class here. Otherwise it // would hold on to the ModuleContext longer than it is // actually valid. m_MimeTypeProviderReg.Unregister(); m_MimeTypeProvider->Stop(); for (std::vector::const_iterator mimeTypeIter = m_DefaultMimeTypes.begin(), iterEnd = m_DefaultMimeTypes.end(); mimeTypeIter != iterEnd; ++mimeTypeIter) { delete *mimeTypeIter; } } void MitkCoreActivator::RegisterDefaultMimeTypes() { // Register some default mime-types std::vector mimeTypes = mitk::IOMimeTypes::Get(); for (std::vector::const_iterator mimeTypeIter = mimeTypes.begin(), iterEnd = mimeTypes.end(); mimeTypeIter != iterEnd; ++mimeTypeIter) { m_DefaultMimeTypes.push_back(*mimeTypeIter); m_Context->RegisterService(m_DefaultMimeTypes.back()); } } void MitkCoreActivator::RegisterItkReaderWriter() { std::list allobjects = itk::ObjectFactoryBase::CreateAllInstance("itkImageIOBase"); for (auto &allobject : allobjects) { itk::ImageIOBase *io = dynamic_cast(allobject.GetPointer()); // NiftiImageIO does not provide a correct "SupportsDimension()" methods // and the supported read/write extensions are not ordered correctly if (dynamic_cast(io)) continue; // Use a custom mime-type for GDCMImageIO below if (dynamic_cast(allobject.GetPointer())) { // MITK provides its own DICOM reader (which internally uses GDCMImageIO). continue; } if (io) { m_FileIOs.push_back(new mitk::ItkImageIO(io)); } else { MITK_WARN << "Error ImageIO factory did not return an ImageIOBase: " << (allobject)->GetNameOfClass(); } } FixedNiftiImageIO::Pointer itkNiftiIO = FixedNiftiImageIO::New(); mitk::ItkImageIO *niftiIO = new mitk::ItkImageIO(mitk::IOMimeTypes::NIFTI_MIMETYPE(), itkNiftiIO.GetPointer(), 0); m_FileIOs.push_back(niftiIO); } void MitkCoreActivator::RegisterVtkReaderWriter() { m_FileIOs.push_back(new mitk::SurfaceVtkXmlIO()); m_FileIOs.push_back(new mitk::SurfaceStlIO()); m_FileIOs.push_back(new mitk::SurfaceVtkLegacyIO()); m_FileIOs.push_back(new mitk::ImageVtkXmlIO()); m_FileIOs.push_back(new mitk::ImageVtkLegacyIO()); } void MitkCoreActivator::RegisterLegacyWriter() { std::list allobjects = itk::ObjectFactoryBase::CreateAllInstance("IOWriter"); for (std::list::iterator i = allobjects.begin(); i != allobjects.end(); ++i) { mitk::FileWriter::Pointer io = dynamic_cast(i->GetPointer()); if (io) { std::string description = std::string("Legacy ") + io->GetNameOfClass() + " Writer"; mitk::IFileWriter *writer = new mitk::LegacyFileWriterService(io, description); m_LegacyWriters.push_back(writer); } else { MITK_ERROR << "Error IOWriter override is not of type mitk::FileWriter: " << (*i)->GetNameOfClass() << std::endl; } } } US_EXPORT_MODULE_ACTIVATOR(MitkCoreActivator) // Call CppMicroservices initialization code at the end of the file. // This especially ensures that VTK object factories have already // been registered (VTK initialization code is injected by implicitly // include VTK header files at the top of this file). US_INITIALIZE_MODULE diff --git a/Modules/Core/test/mitkBaseGeometryTest.cpp b/Modules/Core/test/mitkBaseGeometryTest.cpp index 106d31e1db..8614323d42 100644 --- a/Modules/Core/test/mitkBaseGeometryTest.cpp +++ b/Modules/Core/test/mitkBaseGeometryTest.cpp @@ -1,1347 +1,1347 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "mitkTestingMacros.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include class vtkMatrix4x4; class vtkMatrixToLinearTransform; class vtkLinearTransform; typedef itk::BoundingBox BoundingBox; typedef itk::BoundingBox BoundingBoxType; typedef BoundingBoxType::BoundsArrayType BoundsArrayType; typedef BoundingBoxType::Pointer BoundingBoxPointer; // Dummy instance of abstract base class class DummyTestClass : public mitk::BaseGeometry { public: DummyTestClass(){}; DummyTestClass(const DummyTestClass &other) : BaseGeometry(other){}; - ~DummyTestClass(){}; + ~DummyTestClass() override{}; mitkClassMacro(DummyTestClass, mitk::BaseGeometry); itkNewMacro(Self); mitkNewMacro1Param(Self, const Self &); itk::LightObject::Pointer InternalClone() const override { Self::Pointer newGeometry = new Self(*this); newGeometry->UnRegister(); return newGeometry.GetPointer(); } protected: - virtual void PrintSelf(std::ostream & /*os*/, itk::Indent /*indent*/) const override{}; + void PrintSelf(std::ostream & /*os*/, itk::Indent /*indent*/) const override{}; //##Documentation //## @brief Pre- and Post-functions are empty in BaseGeometry //## //## These virtual functions allow for a different beahiour in subclasses. //## Do implement them in every subclass of BaseGeometry. If not needed, use {}. //## If this class is inherited from a subclass of BaseGeometry, call {Superclass::Pre...();};, example: // SlicedGeometry3D class - virtual void PreSetSpacing(const mitk::Vector3D &/*aSpacing*/) override{}; + void PreSetSpacing(const mitk::Vector3D &/*aSpacing*/) override{}; }; class mitkBaseGeometryTestSuite : public mitk::TestFixture { // List of Tests CPPUNIT_TEST_SUITE(mitkBaseGeometryTestSuite); // Constructor MITK_TEST(TestConstructors); MITK_TEST(TestInitialize); // Set MITK_TEST(TestSetOrigin); MITK_TEST(TestSetBounds); MITK_TEST(TestSetFloatBounds); MITK_TEST(TestSetFloatBoundsDouble); MITK_TEST(TestSetFrameOfReferenceID); MITK_TEST(TestSetIndexToWorldTransform); MITK_TEST(TestSetIndexToWorldTransformWithoutChangingSpacing); MITK_TEST(TestSetIndexToWorldTransform_WithPointerToSameTransform); MITK_TEST(TestSetSpacing); MITK_TEST(TestTransferItkToVtkTransform); MITK_TEST(TestSetIndexToWorldTransformByVtkMatrix); MITK_TEST(TestSetIdentity); MITK_TEST(TestSetImageGeometry); // Equal MITK_TEST(Equal_CloneAndOriginal_ReturnsTrue); MITK_TEST(Equal_DifferentOrigin_ReturnsFalse); MITK_TEST(Equal_DifferentIndexToWorldTransform_ReturnsFalse); MITK_TEST(Equal_DifferentSpacing_ReturnsFalse); MITK_TEST(Equal_InputIsNull_ReturnsFalse); MITK_TEST(Equal_DifferentBoundingBox_ReturnsFalse); MITK_TEST(Equal_Transforms_MinorDifferences_And_Eps); // other Functions MITK_TEST(TestComposeTransform); MITK_TEST(TestComposeVtkMatrix); MITK_TEST(TestTranslate); MITK_TEST(TestIndexToWorld); MITK_TEST(TestExecuteOperation); MITK_TEST(TestCalculateBoundingBoxRelToTransform); // MITK_TEST(TestSetTimeBounds); MITK_TEST(TestIs2DConvertable); MITK_TEST(TestGetCornerPoint); MITK_TEST(TestExtentInMM); MITK_TEST(TestGetAxisVector); MITK_TEST(TestGetCenter); MITK_TEST(TestGetDiagonalLength); MITK_TEST(TestGetExtent); MITK_TEST(TestIsInside); MITK_TEST(TestGetMatrixColumn); CPPUNIT_TEST_SUITE_END(); // Used Variables private: mitk::Point3D aPoint; float aFloatSpacing[3]; mitk::Vector3D aSpacing; mitk::AffineTransform3D::Pointer aTransform; BoundingBoxPointer aBoundingBox; mitk::AffineTransform3D::MatrixType aMatrix; mitk::Point3D anotherPoint; mitk::Vector3D anotherSpacing; BoundingBoxPointer anotherBoundingBox; BoundingBoxPointer aThirdBoundingBox; mitk::AffineTransform3D::Pointer anotherTransform; mitk::AffineTransform3D::Pointer aThirdTransform; mitk::AffineTransform3D::MatrixType anotherMatrix; mitk::AffineTransform3D::MatrixType aThirdMatrix; DummyTestClass::Pointer aDummyGeometry; DummyTestClass::Pointer anotherDummyGeometry; public: // Set up for variables void setUp() override { mitk::FillVector3D(aFloatSpacing, 1, 1, 1); mitk::FillVector3D(aSpacing, 1, 1, 1); mitk::FillVector3D(aPoint, 0, 0, 0); // Transform aTransform = mitk::AffineTransform3D::New(); aTransform->SetIdentity(); aMatrix.SetIdentity(); anotherTransform = mitk::AffineTransform3D::New(); anotherMatrix.SetIdentity(); anotherMatrix(1, 1) = 2; anotherTransform->SetMatrix(anotherMatrix); aThirdTransform = mitk::AffineTransform3D::New(); aThirdMatrix.SetIdentity(); aThirdMatrix(1, 1) = 7; aThirdTransform->SetMatrix(aThirdMatrix); // Bounding Box float bounds[6] = {0, 1, 0, 1, 0, 1}; mitk::BoundingBox::BoundsArrayType b; const float *input = bounds; int j = 0; for (mitk::BoundingBox::BoundsArrayType::Iterator it = b.Begin(); j < 6; ++j) *it++ = (mitk::ScalarType)*input++; aBoundingBox = BoundingBoxType::New(); BoundingBoxType::PointsContainer::Pointer pointscontainer = BoundingBoxType::PointsContainer::New(); BoundingBoxType::PointType p; BoundingBoxType::PointIdentifier pointid; for (pointid = 0; pointid < 2; ++pointid) { unsigned int i; for (i = 0; i < 3; ++i) { p[i] = bounds[2 * i + pointid]; } pointscontainer->InsertElement(pointid, p); } aBoundingBox->SetPoints(pointscontainer); aBoundingBox->ComputeBoundingBox(); anotherBoundingBox = BoundingBoxType::New(); p[0] = 11; p[1] = 12; p[2] = 13; pointscontainer->InsertElement(1, p); anotherBoundingBox->SetPoints(pointscontainer); anotherBoundingBox->ComputeBoundingBox(); aThirdBoundingBox = BoundingBoxType::New(); p[0] = 22; p[1] = 23; p[2] = 24; pointscontainer->InsertElement(1, p); aThirdBoundingBox->SetPoints(pointscontainer); aThirdBoundingBox->ComputeBoundingBox(); mitk::FillVector3D(anotherPoint, 2, 3, 4); mitk::FillVector3D(anotherSpacing, 5, 6.5, 7); aDummyGeometry = DummyTestClass::New(); aDummyGeometry->Initialize(); anotherDummyGeometry = aDummyGeometry->Clone(); } void tearDown() override { aDummyGeometry = nullptr; anotherDummyGeometry = nullptr; } // Test functions void TestSetOrigin() { DummyTestClass::Pointer dummy = DummyTestClass::New(); dummy->SetOrigin(anotherPoint); CPPUNIT_ASSERT(mitk::Equal(anotherPoint, dummy->GetOrigin())); // undo changes, new and changed object need to be the same! dummy->SetOrigin(aPoint); DummyTestClass::Pointer newDummy = DummyTestClass::New(); MITK_ASSERT_EQUAL(dummy, newDummy, "TestSetOrigin"); } void TestSetImageGeometry() { DummyTestClass::Pointer dummy = DummyTestClass::New(); dummy->SetImageGeometry(true); CPPUNIT_ASSERT(dummy->GetImageGeometry()); // undo changes, new and changed object need to be the same! dummy->SetImageGeometry(false); CPPUNIT_ASSERT(dummy->GetImageGeometry() == false); DummyTestClass::Pointer newDummy = DummyTestClass::New(); MITK_ASSERT_EQUAL(dummy, newDummy, "TestSetImageGeometry"); } void TestSetFloatBounds() { float bounds[6] = {0, 11, 0, 12, 0, 13}; DummyTestClass::Pointer dummy = DummyTestClass::New(); dummy->SetFloatBounds(bounds); MITK_ASSERT_EQUAL(BoundingBox::ConstPointer(dummy->GetBoundingBox()), anotherBoundingBox, "BoundingBox equality"); // Wrong bounds, test needs to fail bounds[1] = 7; dummy->SetFloatBounds(bounds); MITK_ASSERT_NOT_EQUAL( BoundingBox::ConstPointer(dummy->GetBoundingBox()), anotherBoundingBox, "BoundingBox not equal"); // undo changes, new and changed object need to be the same! float originalBounds[6] = {0, 1, 0, 1, 0, 1}; dummy->SetFloatBounds(originalBounds); DummyTestClass::Pointer newDummy = DummyTestClass::New(); MITK_ASSERT_EQUAL(dummy, newDummy, "Undo and equal"); } void TestSetBounds() { DummyTestClass::Pointer dummy = DummyTestClass::New(); dummy->SetBounds(anotherBoundingBox->GetBounds()); MITK_ASSERT_EQUAL(BoundingBox::ConstPointer(dummy->GetBoundingBox()), anotherBoundingBox, "Setting bounds"); // Test needs to fail now dummy->SetBounds(aThirdBoundingBox->GetBounds()); MITK_ASSERT_NOT_EQUAL( BoundingBox::ConstPointer(dummy->GetBoundingBox()), anotherBoundingBox, "Setting unequal bounds"); // undo changes, new and changed object need to be the same! dummy->SetBounds(aBoundingBox->GetBounds()); DummyTestClass::Pointer newDummy = DummyTestClass::New(); MITK_ASSERT_EQUAL(dummy, newDummy, "Undo set bounds"); } void TestSetFloatBoundsDouble() { double bounds[6] = {0, 11, 0, 12, 0, 13}; DummyTestClass::Pointer dummy = DummyTestClass::New(); dummy->SetFloatBounds(bounds); MITK_ASSERT_EQUAL(BoundingBox::ConstPointer(dummy->GetBoundingBox()), anotherBoundingBox, "Float bounds"); // Test needs to fail now bounds[3] = 7; dummy->SetFloatBounds(bounds); MITK_ASSERT_NOT_EQUAL( BoundingBox::ConstPointer(dummy->GetBoundingBox()), anotherBoundingBox, "Float bounds unequal"); // undo changes, new and changed object need to be the same! double originalBounds[6] = {0, 1, 0, 1, 0, 1}; dummy->SetFloatBounds(originalBounds); DummyTestClass::Pointer newDummy = DummyTestClass::New(); MITK_ASSERT_EQUAL(dummy, newDummy, "Undo set float bounds"); } void TestSetFrameOfReferenceID() { DummyTestClass::Pointer dummy = DummyTestClass::New(); dummy->SetFrameOfReferenceID(5); CPPUNIT_ASSERT(dummy->GetFrameOfReferenceID() == 5); // undo changes, new and changed object need to be the same! dummy->SetFrameOfReferenceID(0); DummyTestClass::Pointer newDummy = DummyTestClass::New(); MITK_ASSERT_EQUAL(dummy, newDummy, "Undo set frame of reference"); } void TestSetIndexToWorldTransform() { DummyTestClass::Pointer dummy = DummyTestClass::New(); dummy->SetIndexToWorldTransform(anotherTransform); MITK_ASSERT_EQUAL(anotherTransform, mitk::AffineTransform3D::Pointer(dummy->GetIndexToWorldTransform()), "Compare IndexToWorldTransform 1"); // Test needs to fail now dummy->SetIndexToWorldTransform(aThirdTransform); MITK_ASSERT_NOT_EQUAL(anotherTransform, mitk::AffineTransform3D::Pointer(dummy->GetIndexToWorldTransform()), "Compare IndexToWorldTransform 2"); // undo changes, new and changed object need to be the same! dummy->SetIndexToWorldTransform(aTransform); DummyTestClass::Pointer newDummy = DummyTestClass::New(); MITK_ASSERT_EQUAL(dummy, newDummy, "Compare IndexToWorldTransform 3"); } void TestSetIndexToWorldTransformWithoutChangingSpacing() { DummyTestClass::Pointer dummy = DummyTestClass::New(); dummy->SetIndexToWorldTransformWithoutChangingSpacing(anotherTransform); CPPUNIT_ASSERT(mitk::Equal(aSpacing, dummy->GetSpacing(), mitk::eps, true)); // calculate a new version of anotherTransform, so that the spacing should be the same as the original spacing of // aTransform. mitk::AffineTransform3D::MatrixType::InternalMatrixType vnlmatrix; vnlmatrix = anotherTransform->GetMatrix().GetVnlMatrix(); mitk::VnlVector col; col = vnlmatrix.get_column(0); col.normalize(); col *= aSpacing[0]; vnlmatrix.set_column(0, col); col = vnlmatrix.get_column(1); col.normalize(); col *= aSpacing[1]; vnlmatrix.set_column(1, col); col = vnlmatrix.get_column(2); col.normalize(); col *= aSpacing[2]; vnlmatrix.set_column(2, col); mitk::Matrix3D matrix; matrix = vnlmatrix; anotherTransform->SetMatrix(matrix); CPPUNIT_ASSERT(mitk::Equal(anotherTransform, dummy->GetIndexToWorldTransform(), mitk::eps, true)); } void TestSetIndexToWorldTransform_WithPointerToSameTransform() { DummyTestClass::Pointer dummy = DummyTestClass::New(); dummy->SetOrigin(anotherPoint); dummy->SetIndexToWorldTransform(anotherTransform); dummy->SetSpacing(anotherSpacing); mitk::AffineTransform3D::Pointer testTransfrom = dummy->GetIndexToWorldTransform(); mitk::Vector3D modifiedPoint = anotherPoint.GetVectorFromOrigin() * 2.; testTransfrom->SetOffset(modifiedPoint); dummy->SetIndexToWorldTransform(testTransfrom); CPPUNIT_ASSERT(mitk::Equal(modifiedPoint, dummy->GetOrigin().GetVectorFromOrigin())); } void TestSetIndexToWorldTransformByVtkMatrix() { vtkMatrix4x4 *vtkmatrix; vtkmatrix = vtkMatrix4x4::New(); vtkmatrix->Identity(); vtkmatrix->SetElement(1, 1, 2); DummyTestClass::Pointer dummy = DummyTestClass::New(); dummy->SetIndexToWorldTransformByVtkMatrix(vtkmatrix); MITK_ASSERT_EQUAL(anotherTransform, mitk::AffineTransform3D::Pointer(dummy->GetIndexToWorldTransform()), "Compare IndexToWorldTransformByVtkMatrix 1"); // test needs to fail now vtkmatrix->SetElement(1, 1, 7); dummy->SetIndexToWorldTransformByVtkMatrix(vtkmatrix); MITK_ASSERT_NOT_EQUAL(anotherTransform, mitk::AffineTransform3D::Pointer(dummy->GetIndexToWorldTransform()), "Compare IndexToWorldTransformByVtkMatrix 2"); // undo changes, new and changed object need to be the same! vtkmatrix->SetElement(1, 1, 1); dummy->SetIndexToWorldTransformByVtkMatrix(vtkmatrix); vtkmatrix->Delete(); DummyTestClass::Pointer newDummy = DummyTestClass::New(); MITK_ASSERT_EQUAL(dummy, newDummy, "Compare IndexToWorldTransformByVtkMatrix 3"); } void TestSetIdentity() { DummyTestClass::Pointer dummy = DummyTestClass::New(); // Change IndextoWorldTransform and Origin dummy->SetIndexToWorldTransform(anotherTransform); dummy->SetOrigin(anotherPoint); // Set Identity should reset ITWT and Origin dummy->SetIdentity(); MITK_ASSERT_EQUAL( aTransform, mitk::AffineTransform3D::Pointer(dummy->GetIndexToWorldTransform()), "Test set identity 1"); CPPUNIT_ASSERT(mitk::Equal(aPoint, dummy->GetOrigin())); CPPUNIT_ASSERT(mitk::Equal(aSpacing, dummy->GetSpacing())); // new and changed object need to be the same! DummyTestClass::Pointer newDummy = DummyTestClass::New(); MITK_ASSERT_EQUAL(dummy, newDummy, "Test set identity 2"); } void TestSetSpacing() { DummyTestClass::Pointer dummy = DummyTestClass::New(); dummy->SetSpacing(anotherSpacing); CPPUNIT_ASSERT(mitk::Equal(anotherSpacing, dummy->GetSpacing())); // undo changes, new and changed object need to be the same! dummy->SetSpacing(aSpacing); DummyTestClass::Pointer newDummy = DummyTestClass::New(); MITK_ASSERT_EQUAL(dummy, newDummy, "Dummy spacing"); } void TestTransferItkToVtkTransform() { DummyTestClass::Pointer dummy = DummyTestClass::New(); dummy->SetIndexToWorldTransform(anotherTransform); // calls TransferItkToVtkTransform mitk::AffineTransform3D::Pointer dummyTransform = dummy->GetIndexToWorldTransform(); CPPUNIT_ASSERT(mitk::MatrixEqualElementWise(anotherMatrix, dummyTransform->GetMatrix())); } void TestConstructors() { // test standard constructor DummyTestClass::Pointer dummy1 = DummyTestClass::New(); bool test = dummy1->IsValid(); CPPUNIT_ASSERT(test == true); CPPUNIT_ASSERT(dummy1->GetFrameOfReferenceID() == 0); CPPUNIT_ASSERT(dummy1->GetIndexToWorldTransformLastModified() == 0); CPPUNIT_ASSERT(mitk::Equal(dummy1->GetSpacing(), aSpacing)); CPPUNIT_ASSERT(mitk::Equal(dummy1->GetOrigin(), aPoint)); CPPUNIT_ASSERT(dummy1->GetImageGeometry() == false); MITK_ASSERT_EQUAL( mitk::AffineTransform3D::Pointer(dummy1->GetIndexToWorldTransform()), aTransform, "Contructor test 1"); MITK_ASSERT_EQUAL( mitk::BaseGeometry::BoundingBoxType::ConstPointer(dummy1->GetBoundingBox()), aBoundingBox, "Constructor test 2"); DummyTestClass::Pointer dummy2 = DummyTestClass::New(); dummy2->SetOrigin(anotherPoint); float bounds[6] = {0, 11, 0, 12, 0, 13}; dummy2->SetFloatBounds(bounds); dummy2->SetIndexToWorldTransform(anotherTransform); dummy2->SetSpacing(anotherSpacing); DummyTestClass::Pointer dummy3 = DummyTestClass::New(*dummy2); MITK_ASSERT_EQUAL(dummy3, dummy2, "Dummy contructor"); } // Equal Tests void Equal_CloneAndOriginal_ReturnsTrue() { MITK_ASSERT_EQUAL(aDummyGeometry, anotherDummyGeometry, "Clone test"); } void Equal_DifferentOrigin_ReturnsFalse() { anotherDummyGeometry->SetOrigin(anotherPoint); MITK_ASSERT_NOT_EQUAL(aDummyGeometry, anotherDummyGeometry, "Different origin test"); } void Equal_DifferentIndexToWorldTransform_ReturnsFalse() { anotherDummyGeometry->SetIndexToWorldTransform(anotherTransform); MITK_ASSERT_NOT_EQUAL(aDummyGeometry, anotherDummyGeometry, "Different index to world"); } void Equal_DifferentSpacing_ReturnsFalse() { anotherDummyGeometry->SetSpacing(anotherSpacing); MITK_ASSERT_NOT_EQUAL(aDummyGeometry, anotherDummyGeometry, "Different spacing"); } void Equal_InputIsNull_ReturnsFalse() { DummyTestClass::Pointer geometryNull = nullptr; CPPUNIT_ASSERT_THROW(MITK_ASSERT_EQUAL(geometryNull, anotherDummyGeometry, "Input is null"), mitk::Exception); } void Equal_DifferentBoundingBox_ReturnsFalse() { // create different bounds to make the comparison false mitk::ScalarType bounds[] = {0.0, 0.0, 0.0, 0.0, 0.0, 0.0}; anotherDummyGeometry->SetBounds(bounds); MITK_ASSERT_NOT_EQUAL(aDummyGeometry, anotherDummyGeometry, "Different bounding box"); } void Equal_Transforms_MinorDifferences_And_Eps() { // Verifies that the eps parameter is evaluated properly // when comparing two mitk::BaseGeometry::TransformTypes aMatrix.SetIdentity(); anotherMatrix.SetIdentity(); aMatrix(0, 1) = 0.0002; aTransform->SetMatrix(aMatrix); anotherMatrix(0, 1) = 0.0002; anotherTransform->SetMatrix(anotherMatrix); anotherTransform->SetMatrix(aMatrix); CPPUNIT_ASSERT_MESSAGE("Exact same transforms are mitk::Equal() for eps=mitk::eps", mitk::Equal(aTransform, anotherTransform, mitk::eps, true)); CPPUNIT_ASSERT_MESSAGE("Exact same transforms are mitk::Equal() for eps=vnl_math::eps", mitk::Equal(aTransform, anotherTransform, vnl_math::eps, true)); anotherMatrix(0, 1) = 0.0002 + mitk::eps; anotherTransform->SetMatrix(anotherMatrix); CPPUNIT_ASSERT_MESSAGE("Transforms of diff mitk::eps are !mitk::Equal() for eps=vnl_math::eps", !mitk::Equal(aTransform, anotherTransform, vnl_math::eps, true)); CPPUNIT_ASSERT_MESSAGE("Transforms of diff mitk::eps are !mitk::Equal() for eps=mitk::eps-1%", !mitk::Equal(aTransform, anotherTransform, mitk::eps * 0.99, true)); CPPUNIT_ASSERT_MESSAGE("Transforms of diff mitk::eps _are_ mitk::Equal() for eps=mitk::eps+1%", mitk::Equal(aTransform, anotherTransform, mitk::eps * 1.01, true)); } void TestComposeTransform() { // Create Transformations to set and compare mitk::AffineTransform3D::Pointer transform1; transform1 = mitk::AffineTransform3D::New(); mitk::AffineTransform3D::MatrixType matrix1; matrix1.SetIdentity(); matrix1(1, 1) = 2; transform1->SetMatrix(matrix1); // Spacing = 2 mitk::AffineTransform3D::Pointer transform2; transform2 = mitk::AffineTransform3D::New(); mitk::AffineTransform3D::MatrixType matrix2; matrix2.SetIdentity(); matrix2(1, 1) = 2; transform2->SetMatrix(matrix2); // Spacing = 2 mitk::AffineTransform3D::Pointer transform3; transform3 = mitk::AffineTransform3D::New(); mitk::AffineTransform3D::MatrixType matrix3; matrix3.SetIdentity(); matrix3(1, 1) = 4; transform3->SetMatrix(matrix3); // Spacing = 4 mitk::AffineTransform3D::Pointer transform4; transform4 = mitk::AffineTransform3D::New(); mitk::AffineTransform3D::MatrixType matrix4; matrix4.SetIdentity(); matrix4(1, 1) = 0.25; transform4->SetMatrix(matrix4); // Spacing = 0.25 // Vector to compare spacing mitk::Vector3D expectedSpacing; expectedSpacing.Fill(1.0); expectedSpacing[1] = 4; DummyTestClass::Pointer dummy = DummyTestClass::New(); dummy->SetIndexToWorldTransform(transform1); // Spacing = 2 dummy->Compose(transform2); // Spacing = 4 CPPUNIT_ASSERT(mitk::Equal(dummy->GetSpacing(), expectedSpacing)); MITK_ASSERT_EQUAL( transform3, mitk::AffineTransform3D::Pointer(dummy->GetIndexToWorldTransform()), "Compose transform 2"); // 4=4 // undo changes, new and changed object need to be the same! dummy->Compose(transform4); // Spacing = 1 DummyTestClass::Pointer newDummy = DummyTestClass::New(); MITK_ASSERT_EQUAL(dummy, newDummy, "Compose transform 3"); // 1=1 } void TestComposeVtkMatrix() { // Create Transformations to set and compare mitk::AffineTransform3D::Pointer transform1; transform1 = mitk::AffineTransform3D::New(); mitk::AffineTransform3D::MatrixType matrix1; matrix1.SetIdentity(); matrix1(1, 1) = 2; transform1->SetMatrix(matrix1); // Spacing = 2 vtkMatrix4x4 *vtkmatrix2; vtkmatrix2 = vtkMatrix4x4::New(); vtkmatrix2->Identity(); vtkmatrix2->SetElement(1, 1, 2); // Spacing = 2 mitk::AffineTransform3D::Pointer transform3; transform3 = mitk::AffineTransform3D::New(); mitk::AffineTransform3D::MatrixType matrix3; matrix3.SetIdentity(); matrix3(1, 1) = 4; transform3->SetMatrix(matrix3); // Spacing = 4 vtkMatrix4x4 *vtkmatrix4; vtkmatrix4 = vtkMatrix4x4::New(); vtkmatrix4->Identity(); vtkmatrix4->SetElement(1, 1, 0.25); // Spacing = 0.25 // Vector to compare spacing mitk::Vector3D expectedSpacing; expectedSpacing.Fill(1.0); expectedSpacing[1] = 4; DummyTestClass::Pointer dummy = DummyTestClass::New(); dummy->SetIndexToWorldTransform(transform1); // Spacing = 2 dummy->Compose(vtkmatrix2); // Spacing = 4 vtkmatrix2->Delete(); MITK_ASSERT_EQUAL( transform3, mitk::AffineTransform3D::Pointer(dummy->GetIndexToWorldTransform()), "Compose vtk matrix"); // 4=4 CPPUNIT_ASSERT(mitk::Equal(dummy->GetSpacing(), expectedSpacing)); // undo changes, new and changed object need to be the same! dummy->Compose(vtkmatrix4); // Spacing = 1 vtkmatrix4->Delete(); DummyTestClass::Pointer newDummy = DummyTestClass::New(); MITK_ASSERT_EQUAL(dummy, newDummy, "Compose vtk"); // 1=1 } void TestTranslate() { DummyTestClass::Pointer dummy = DummyTestClass::New(); dummy->SetOrigin(anotherPoint); CPPUNIT_ASSERT(mitk::Equal(anotherPoint, dummy->GetOrigin())); // use some random values for translation mitk::Vector3D translationVector; translationVector.SetElement(0, 17.5f); translationVector.SetElement(1, -32.3f); translationVector.SetElement(2, 4.0f); // compute ground truth mitk::Point3D tmpResult = anotherPoint + translationVector; dummy->Translate(translationVector); CPPUNIT_ASSERT(mitk::Equal(dummy->GetOrigin(), tmpResult)); // undo changes translationVector *= -1; dummy->Translate(translationVector); CPPUNIT_ASSERT(mitk::Equal(dummy->GetOrigin(), anotherPoint)); // undo changes, new and changed object need to be the same! translationVector.SetElement(0, -1 * anotherPoint[0]); translationVector.SetElement(1, -1 * anotherPoint[1]); translationVector.SetElement(2, -1 * anotherPoint[2]); dummy->Translate(translationVector); DummyTestClass::Pointer newDummy = DummyTestClass::New(); MITK_ASSERT_EQUAL(dummy, newDummy, "Translate test"); } // a part of the test requires axis-parallel coordinates int testIndexAndWorldConsistency(DummyTestClass::Pointer dummyGeometry) { // Testing consistency of index and world coordinate systems mitk::Point3D origin = dummyGeometry->GetOrigin(); mitk::Point3D dummyPoint; // Testing index->world->index conversion consistency dummyGeometry->WorldToIndex(origin, dummyPoint); dummyGeometry->IndexToWorld(dummyPoint, dummyPoint); CPPUNIT_ASSERT(mitk::EqualArray(dummyPoint, origin, 3, mitk::eps, true)); // Testing WorldToIndex(origin, mitk::Point3D)==(0,0,0) mitk::Point3D globalOrigin; mitk::FillVector3D(globalOrigin, 0, 0, 0); mitk::Point3D originContinuousIndex; dummyGeometry->WorldToIndex(origin, originContinuousIndex); CPPUNIT_ASSERT(mitk::EqualArray(originContinuousIndex, globalOrigin, 3, mitk::eps, true)); // Testing WorldToIndex(origin, itk::Index)==(0,0,0) itk::Index<3> itkindex; dummyGeometry->WorldToIndex(origin, itkindex); itk::Index<3> globalOriginIndex; mitk::vtk2itk(globalOrigin, globalOriginIndex); CPPUNIT_ASSERT(mitk::EqualArray(itkindex, globalOriginIndex, 3, mitk::eps, true)); // Testing WorldToIndex(origin-0.5*spacing, itk::Index)==(0,0,0) mitk::Vector3D halfSpacingStep = dummyGeometry->GetSpacing() * 0.5; mitk::Matrix3D rotation; mitk::Point3D originOffCenter = origin - halfSpacingStep; dummyGeometry->WorldToIndex(originOffCenter, itkindex); CPPUNIT_ASSERT(mitk::EqualArray(itkindex, globalOriginIndex, 3, mitk::eps, true)); // Testing WorldToIndex(origin+0.5*spacing-eps, itk::Index)==(0,0,0) originOffCenter = origin + halfSpacingStep; originOffCenter -= 0.0001; dummyGeometry->WorldToIndex(originOffCenter, itkindex); CPPUNIT_ASSERT(mitk::EqualArray(itkindex, globalOriginIndex, 3, mitk::eps, true)); // Testing WorldToIndex(origin+0.5*spacing, itk::Index)==(1,1,1)"); originOffCenter = origin + halfSpacingStep; itk::Index<3> global111; mitk::FillVector3D(global111, 1, 1, 1); dummyGeometry->WorldToIndex(originOffCenter, itkindex); CPPUNIT_ASSERT(mitk::EqualArray(itkindex, global111, 3, mitk::eps, true)); // Testing WorldToIndex(GetCenter())==BoundingBox.GetCenter mitk::Point3D center = dummyGeometry->GetCenter(); mitk::Point3D centerContIndex; dummyGeometry->WorldToIndex(center, centerContIndex); mitk::BoundingBox::ConstPointer boundingBox = dummyGeometry->GetBoundingBox(); mitk::BoundingBox::PointType centerBounds = boundingBox->GetCenter(); CPPUNIT_ASSERT(mitk::Equal(centerContIndex, centerBounds)); // Testing GetCenter()==IndexToWorld(BoundingBox.GetCenter) center = dummyGeometry->GetCenter(); mitk::Point3D centerBoundsInWorldCoords; dummyGeometry->IndexToWorld(centerBounds, centerBoundsInWorldCoords); CPPUNIT_ASSERT(mitk::Equal(center, centerBoundsInWorldCoords)); // Test using random point, // Testing consistency of index and world coordinate systems mitk::Point3D point; mitk::FillVector3D(point, 3.5, -2, 4.6); // Testing index->world->index conversion consistency dummyGeometry->WorldToIndex(point, dummyPoint); dummyGeometry->IndexToWorld(dummyPoint, dummyPoint); CPPUNIT_ASSERT(mitk::EqualArray(dummyPoint, point, 3, mitk::eps, true)); return EXIT_SUCCESS; } int testIndexAndWorldConsistencyForVectors(DummyTestClass::Pointer dummyGeometry) { // Testing consistency of index and world coordinate systems for vectors mitk::Vector3D xAxisMM = dummyGeometry->GetAxisVector(0); mitk::Vector3D xAxisContinuousIndex; mitk::Point3D p, pIndex, origin; origin = dummyGeometry->GetOrigin(); p[0] = xAxisMM[0] + origin[0]; p[1] = xAxisMM[1] + origin[1]; p[2] = xAxisMM[2] + origin[2]; dummyGeometry->WorldToIndex(p, pIndex); dummyGeometry->WorldToIndex(xAxisMM, xAxisContinuousIndex); CPPUNIT_ASSERT(mitk::Equal(xAxisContinuousIndex[0], pIndex[0])); CPPUNIT_ASSERT(mitk::Equal(xAxisContinuousIndex[1], pIndex[1])); CPPUNIT_ASSERT(mitk::Equal(xAxisContinuousIndex[2], pIndex[2])); dummyGeometry->IndexToWorld(xAxisContinuousIndex, xAxisContinuousIndex); dummyGeometry->IndexToWorld(pIndex, p); CPPUNIT_ASSERT(xAxisContinuousIndex == xAxisMM); CPPUNIT_ASSERT(mitk::Equal(xAxisContinuousIndex[0], p[0] - origin[0])); CPPUNIT_ASSERT(mitk::Equal(xAxisContinuousIndex[1], p[1] - origin[1])); CPPUNIT_ASSERT(mitk::Equal(xAxisContinuousIndex[2], p[2] - origin[2])); // Test consictency for random vector mitk::Vector3D vector; mitk::FillVector3D(vector, 2.5, -3.2, 8.1); mitk::Vector3D vectorContinuousIndex; p[0] = vector[0] + origin[0]; p[1] = vector[1] + origin[1]; p[2] = vector[2] + origin[2]; dummyGeometry->WorldToIndex(p, pIndex); dummyGeometry->WorldToIndex(vector, vectorContinuousIndex); CPPUNIT_ASSERT(mitk::Equal(vectorContinuousIndex[0], pIndex[0])); CPPUNIT_ASSERT(mitk::Equal(vectorContinuousIndex[1], pIndex[1])); CPPUNIT_ASSERT(mitk::Equal(vectorContinuousIndex[2], pIndex[2])); dummyGeometry->IndexToWorld(vectorContinuousIndex, vectorContinuousIndex); dummyGeometry->IndexToWorld(pIndex, p); CPPUNIT_ASSERT(vectorContinuousIndex == vector); CPPUNIT_ASSERT(mitk::Equal(vectorContinuousIndex[0], p[0] - origin[0])); CPPUNIT_ASSERT(mitk::Equal(vectorContinuousIndex[1], p[1] - origin[1])); CPPUNIT_ASSERT(mitk::Equal(vectorContinuousIndex[2], p[2] - origin[2])); return EXIT_SUCCESS; } int testIndexAndWorldConsistencyForIndex(DummyTestClass::Pointer dummyGeometry) { // Testing consistency of index and world coordinate systems // creating testing data itk::Index<4> itkIndex4, itkIndex4b; itk::Index<3> itkIndex3, itkIndex3b; itk::Index<2> itkIndex2, itkIndex2b; itk::Index<3> mitkIndex, mitkIndexb; itkIndex4[0] = itkIndex4[1] = itkIndex4[2] = itkIndex4[3] = 4; itkIndex3[0] = itkIndex3[1] = itkIndex3[2] = 6; itkIndex2[0] = itkIndex2[1] = 2; mitkIndex[0] = mitkIndex[1] = mitkIndex[2] = 13; // check for constistency mitk::Point3D point; dummyGeometry->IndexToWorld(itkIndex2, point); dummyGeometry->WorldToIndex(point, itkIndex2b); CPPUNIT_ASSERT(((itkIndex2b[0] == itkIndex2[0]) && (itkIndex2b[1] == itkIndex2[1]))); // Testing itk::index<2> for IndexToWorld/WorldToIndex consistency dummyGeometry->IndexToWorld(itkIndex3, point); dummyGeometry->WorldToIndex(point, itkIndex3b); CPPUNIT_ASSERT( ((itkIndex3b[0] == itkIndex3[0]) && (itkIndex3b[1] == itkIndex3[1]) && (itkIndex3b[2] == itkIndex3[2]))); // Testing itk::index<3> for IndexToWorld/WorldToIndex consistency dummyGeometry->IndexToWorld(itkIndex4, point); dummyGeometry->WorldToIndex(point, itkIndex4b); CPPUNIT_ASSERT(((itkIndex4b[0] == itkIndex4[0]) && (itkIndex4b[1] == itkIndex4[1]) && (itkIndex4b[2] == itkIndex4[2]) && (itkIndex4b[3] == 0))); // Testing itk::index<3> for IndexToWorld/WorldToIndex consistency dummyGeometry->IndexToWorld(mitkIndex, point); dummyGeometry->WorldToIndex(point, mitkIndexb); CPPUNIT_ASSERT( ((mitkIndexb[0] == mitkIndex[0]) && (mitkIndexb[1] == mitkIndex[1]) && (mitkIndexb[2] == mitkIndex[2]))); // Testing mitk::Index for IndexToWorld/WorldToIndex consistency return EXIT_SUCCESS; } void TestIndexToWorld() { DummyTestClass::Pointer dummy = DummyTestClass::New(); testIndexAndWorldConsistency(dummy); testIndexAndWorldConsistencyForVectors(dummy); testIndexAndWorldConsistencyForIndex(dummy); // Geometry must not have changed DummyTestClass::Pointer newDummy = DummyTestClass::New(); MITK_ASSERT_EQUAL(dummy, newDummy, "Dummy index to world"); // Test with other geometries dummy->SetOrigin(anotherPoint); testIndexAndWorldConsistency(dummy); testIndexAndWorldConsistencyForVectors(dummy); testIndexAndWorldConsistencyForIndex(dummy); dummy->SetIndexToWorldTransform(anotherTransform); testIndexAndWorldConsistency(dummy); testIndexAndWorldConsistencyForVectors(dummy); testIndexAndWorldConsistencyForIndex(dummy); dummy->SetOrigin(anotherPoint); testIndexAndWorldConsistency(dummy); testIndexAndWorldConsistencyForVectors(dummy); testIndexAndWorldConsistencyForIndex(dummy); dummy->SetSpacing(anotherSpacing); testIndexAndWorldConsistency(dummy); testIndexAndWorldConsistencyForVectors(dummy); testIndexAndWorldConsistencyForIndex(dummy); } void TestExecuteOperation() { DummyTestClass::Pointer dummy = DummyTestClass::New(); // Do same Operations with new Dummy and compare DummyTestClass::Pointer newDummy = DummyTestClass::New(); // Test operation Nothing auto opN = new mitk::Operation(mitk::OpNOTHING); dummy->ExecuteOperation(opN); MITK_ASSERT_EQUAL(dummy, newDummy, "Dummy execute operation 1"); // Test operation Move auto opP = new mitk::PointOperation(mitk::OpMOVE, anotherPoint); dummy->ExecuteOperation(opP); CPPUNIT_ASSERT(mitk::Equal(anotherPoint, dummy->GetOrigin())); newDummy->SetOrigin(anotherPoint); MITK_ASSERT_EQUAL(dummy, newDummy, "Dummy execute operation 2"); // Test operation Scale, Scale sets spacing to scale+1 mitk::Point3D spacing; spacing[0] = anotherSpacing[0] - 1.; spacing[1] = anotherSpacing[1] - 1.; spacing[2] = anotherSpacing[2] - 1.; auto opS = new mitk::ScaleOperation(mitk::OpSCALE, spacing, anotherPoint); dummy->ExecuteOperation(opS); CPPUNIT_ASSERT(mitk::Equal(anotherSpacing, dummy->GetSpacing())); newDummy->SetSpacing(anotherSpacing); MITK_ASSERT_EQUAL(dummy, newDummy, "Dummy execute operation 3"); // change Geometry to test more cases dummy->SetIndexToWorldTransform(anotherTransform); dummy->SetSpacing(anotherSpacing); // Testing a rotation of the geometry double angle = 35.0; mitk::Vector3D rotationVector; mitk::FillVector3D(rotationVector, 1, 0, 0); mitk::Point3D center = dummy->GetCenter(); auto opR = new mitk::RotationOperation(mitk::OpROTATE, center, rotationVector, angle); dummy->ExecuteOperation(opR); mitk::Matrix3D rotation; mitk::GetRotation(dummy, rotation); mitk::Vector3D voxelStep = rotation * anotherSpacing; mitk::Vector3D voxelStepIndex; dummy->WorldToIndex(voxelStep, voxelStepIndex); mitk::Vector3D expectedVoxelStepIndex; expectedVoxelStepIndex.Fill(1); CPPUNIT_ASSERT(mitk::Equal(voxelStepIndex, expectedVoxelStepIndex)); delete opR; delete opN; delete opS; delete opP; } void TestCalculateBoundingBoxRelToTransform() { DummyTestClass::Pointer dummy = DummyTestClass::New(); dummy->SetExtentInMM(0, 15); dummy->SetExtentInMM(1, 20); dummy->SetExtentInMM(2, 8); mitk::BoundingBox::Pointer dummyBoundingBox = dummy->CalculateBoundingBoxRelativeToTransform(anotherTransform); mitk::BoundingBox::PointsContainer::Pointer pointscontainer = mitk::BoundingBox::PointsContainer::New(); mitk::BoundingBox::PointIdentifier pointid = 0; unsigned char i; mitk::AffineTransform3D::Pointer inverse = mitk::AffineTransform3D::New(); anotherTransform->GetInverse(inverse); for (i = 0; i < 8; ++i) pointscontainer->InsertElement(pointid++, inverse->TransformPoint(dummy->GetCornerPoint(i))); mitk::BoundingBox::Pointer result = mitk::BoundingBox::New(); result->SetPoints(pointscontainer); result->ComputeBoundingBox(); MITK_ASSERT_EQUAL(result, dummyBoundingBox, "BBox rel to transform"); // dummy still needs to be unchanged, except for extend DummyTestClass::Pointer newDummy = DummyTestClass::New(); newDummy->SetExtentInMM(0, 15); newDummy->SetExtentInMM(1, 20); newDummy->SetExtentInMM(2, 8); MITK_ASSERT_EQUAL(dummy, newDummy, "Dummy BBox"); } // void TestSetTimeBounds(){ // mitk::TimeBounds timeBounds; // timeBounds[0] = 1; // timeBounds[1] = 9; // DummyTestClass::Pointer dummy = DummyTestClass::New(); // dummy->SetTimeBounds(timeBounds); // mitk::TimeBounds timeBounds2 = dummy->GetTimeBounds(); // CPPUNIT_ASSERT(timeBounds[0]==timeBounds2[0]); // CPPUNIT_ASSERT(timeBounds[1]==timeBounds2[1]); // //undo changes, new and changed object need to be the same! // timeBounds[0]=mitk::ScalarTypeNumericTraits::NonpositiveMin(); // timeBounds[1]=mitk::ScalarTypeNumericTraits::max(); // DummyTestClass::Pointer newDummy = DummyTestClass::New(); // CPPUNIT_ASSERT(mitk::Equal(dummy,newDummy,mitk::eps,true)); //} void TestIs2DConvertable() { DummyTestClass::Pointer dummy = DummyTestClass::New(); // new initialized geometry is 2D convertable CPPUNIT_ASSERT(dummy->Is2DConvertable()); // Wrong Spacing needs to fail dummy->SetSpacing(anotherSpacing); CPPUNIT_ASSERT(dummy->Is2DConvertable() == false); // undo dummy->SetSpacing(aSpacing); CPPUNIT_ASSERT(dummy->Is2DConvertable()); // Wrong Origin needs to fail dummy->SetOrigin(anotherPoint); CPPUNIT_ASSERT(dummy->Is2DConvertable() == false); // undo dummy->SetOrigin(aPoint); CPPUNIT_ASSERT(dummy->Is2DConvertable()); // third dimension must not be transformed mitk::AffineTransform3D::Pointer dummyTransform = mitk::AffineTransform3D::New(); mitk::AffineTransform3D::MatrixType dummyMatrix; dummyMatrix.SetIdentity(); dummyTransform->SetMatrix(dummyMatrix); dummy->SetIndexToWorldTransform(dummyTransform); // identity matrix is 2DConvertable CPPUNIT_ASSERT(dummy->Is2DConvertable()); dummyMatrix(0, 2) = 3; dummyTransform->SetMatrix(dummyMatrix); CPPUNIT_ASSERT(dummy->Is2DConvertable() == false); dummyMatrix.SetIdentity(); dummyMatrix(1, 2) = 0.4; dummyTransform->SetMatrix(dummyMatrix); CPPUNIT_ASSERT(dummy->Is2DConvertable() == false); dummyMatrix.SetIdentity(); dummyMatrix(2, 2) = 3; dummyTransform->SetMatrix(dummyMatrix); CPPUNIT_ASSERT(dummy->Is2DConvertable() == false); dummyMatrix.SetIdentity(); dummyMatrix(2, 1) = 3; dummyTransform->SetMatrix(dummyMatrix); CPPUNIT_ASSERT(dummy->Is2DConvertable() == false); dummyMatrix.SetIdentity(); dummyMatrix(2, 0) = 3; dummyTransform->SetMatrix(dummyMatrix); CPPUNIT_ASSERT(dummy->Is2DConvertable() == false); // undo changes, new and changed object need to be the same! dummyMatrix.SetIdentity(); dummyTransform->SetMatrix(dummyMatrix); DummyTestClass::Pointer newDummy = DummyTestClass::New(); MITK_ASSERT_EQUAL(dummy, newDummy, "Is 2D convertable"); } void TestGetCornerPoint() { DummyTestClass::Pointer dummy = DummyTestClass::New(); dummy->SetIndexToWorldTransform(anotherTransform); double bounds[6] = {0, 11, 0, 12, 0, 13}; dummy->SetFloatBounds(bounds); mitk::Point3D corner, refCorner; // Corner 0 mitk::FillVector3D(refCorner, bounds[0], bounds[2], bounds[4]); refCorner = anotherTransform->TransformPoint(refCorner); corner = dummy->GetCornerPoint(0); CPPUNIT_ASSERT(mitk::Equal(refCorner, corner)); corner = dummy->GetCornerPoint(true, true, true); CPPUNIT_ASSERT(mitk::Equal(refCorner, corner)); // Corner 1 mitk::FillVector3D(refCorner, bounds[0], bounds[2], bounds[5]); refCorner = anotherTransform->TransformPoint(refCorner); corner = dummy->GetCornerPoint(1); CPPUNIT_ASSERT(mitk::Equal(refCorner, corner)); corner = dummy->GetCornerPoint(true, true, false); CPPUNIT_ASSERT(mitk::Equal(refCorner, corner)); // Corner 2 mitk::FillVector3D(refCorner, bounds[0], bounds[3], bounds[4]); refCorner = anotherTransform->TransformPoint(refCorner); corner = dummy->GetCornerPoint(2); CPPUNIT_ASSERT(mitk::Equal(refCorner, corner)); corner = dummy->GetCornerPoint(true, false, true); CPPUNIT_ASSERT(mitk::Equal(refCorner, corner)); // Corner 3 mitk::FillVector3D(refCorner, bounds[0], bounds[3], bounds[5]); refCorner = anotherTransform->TransformPoint(refCorner); corner = dummy->GetCornerPoint(3); CPPUNIT_ASSERT(mitk::Equal(refCorner, corner)); corner = dummy->GetCornerPoint(true, false, false); CPPUNIT_ASSERT(mitk::Equal(refCorner, corner)); // Corner 4 mitk::FillVector3D(refCorner, bounds[1], bounds[2], bounds[4]); refCorner = anotherTransform->TransformPoint(refCorner); corner = dummy->GetCornerPoint(4); CPPUNIT_ASSERT(mitk::Equal(refCorner, corner)); corner = dummy->GetCornerPoint(false, true, true); CPPUNIT_ASSERT(mitk::Equal(refCorner, corner)); // Corner 5 mitk::FillVector3D(refCorner, bounds[1], bounds[2], bounds[5]); refCorner = anotherTransform->TransformPoint(refCorner); corner = dummy->GetCornerPoint(5); CPPUNIT_ASSERT(mitk::Equal(refCorner, corner)); corner = dummy->GetCornerPoint(false, true, false); CPPUNIT_ASSERT(mitk::Equal(refCorner, corner)); // Corner 6 mitk::FillVector3D(refCorner, bounds[1], bounds[3], bounds[4]); refCorner = anotherTransform->TransformPoint(refCorner); corner = dummy->GetCornerPoint(6); CPPUNIT_ASSERT(mitk::Equal(refCorner, corner)); corner = dummy->GetCornerPoint(false, false, true); CPPUNIT_ASSERT(mitk::Equal(refCorner, corner)); // Corner 7 mitk::FillVector3D(refCorner, bounds[1], bounds[3], bounds[5]); refCorner = anotherTransform->TransformPoint(refCorner); corner = dummy->GetCornerPoint(7); CPPUNIT_ASSERT(mitk::Equal(refCorner, corner)); corner = dummy->GetCornerPoint(false, false, false); CPPUNIT_ASSERT(mitk::Equal(refCorner, corner)); // Wrong Corner needs to fail CPPUNIT_ASSERT_THROW(dummy->GetCornerPoint(20), itk::ExceptionObject); // dummy geometry must not have changed! DummyTestClass::Pointer newDummy = DummyTestClass::New(); newDummy->SetIndexToWorldTransform(anotherTransform); newDummy->SetFloatBounds(bounds); MITK_ASSERT_EQUAL(dummy, newDummy, "Corner point"); } void TestExtentInMM() { DummyTestClass::Pointer dummy = DummyTestClass::New(); dummy->SetExtentInMM(0, 50); CPPUNIT_ASSERT(mitk::Equal(50., dummy->GetExtentInMM(0))); // Vnl Matrix has changed. The next line only works because the spacing is 1! CPPUNIT_ASSERT( mitk::Equal(50., dummy->GetIndexToWorldTransform()->GetMatrix().GetVnlMatrix().get_column(0).magnitude())); // Smaller extent than original dummy->SetExtentInMM(0, 5); CPPUNIT_ASSERT(mitk::Equal(5., dummy->GetExtentInMM(0))); CPPUNIT_ASSERT( mitk::Equal(5., dummy->GetIndexToWorldTransform()->GetMatrix().GetVnlMatrix().get_column(0).magnitude())); dummy->SetExtentInMM(1, 4); CPPUNIT_ASSERT(mitk::Equal(4., dummy->GetExtentInMM(1))); CPPUNIT_ASSERT( mitk::Equal(4., dummy->GetIndexToWorldTransform()->GetMatrix().GetVnlMatrix().get_column(1).magnitude())); dummy->SetExtentInMM(2, 2.5); CPPUNIT_ASSERT(mitk::Equal(2.5, dummy->GetExtentInMM(2))); CPPUNIT_ASSERT( mitk::Equal(2.5, dummy->GetIndexToWorldTransform()->GetMatrix().GetVnlMatrix().get_column(2).magnitude())); } void TestGetAxisVector() { DummyTestClass::Pointer dummy = DummyTestClass::New(); dummy->SetIndexToWorldTransform(anotherTransform); double bounds[6] = {0, 11, 0, 12, 0, 13}; dummy->SetFloatBounds(bounds); mitk::Vector3D vector; mitk::FillVector3D(vector, bounds[1], 0, 0); dummy->IndexToWorld(vector, vector); CPPUNIT_ASSERT(mitk::Equal(dummy->GetAxisVector(0), vector)); mitk::FillVector3D(vector, 0, bounds[3], 0); dummy->IndexToWorld(vector, vector); CPPUNIT_ASSERT(mitk::Equal(dummy->GetAxisVector(1), vector)); mitk::FillVector3D(vector, 0, 0, bounds[5]); dummy->IndexToWorld(vector, vector); CPPUNIT_ASSERT(mitk::Equal(dummy->GetAxisVector(2), vector)); } void TestGetCenter() { DummyTestClass::Pointer dummy = DummyTestClass::New(); dummy->SetIndexToWorldTransform(anotherTransform); double bounds[6] = {0, 11, 2, 12, 1, 13}; dummy->SetFloatBounds(bounds); mitk::Point3D refCenter; for (int i = 0; i < 3; i++) refCenter.SetElement(i, (bounds[2 * i] + bounds[2 * i + 1]) / 2.0); dummy->IndexToWorld(refCenter, refCenter); CPPUNIT_ASSERT(mitk::Equal(dummy->GetCenter(), refCenter)); } void TestGetDiagonalLength() { DummyTestClass::Pointer dummy = DummyTestClass::New(); double bounds[6] = {1, 3, 5, 8, 7.5, 11.5}; dummy->SetFloatBounds(bounds); // 3-1=2, 8-5=3, 11.5-7.5=4; 2^2+3^2+4^2 = 29 double expectedLength = sqrt(29.); CPPUNIT_ASSERT(mitk::Equal(expectedLength, dummy->GetDiagonalLength(), mitk::eps, true)); CPPUNIT_ASSERT(mitk::Equal(29., dummy->GetDiagonalLength2(), mitk::eps, true)); // dummy must not have changed DummyTestClass::Pointer newDummy = DummyTestClass::New(); newDummy->SetFloatBounds(bounds); MITK_ASSERT_EQUAL(dummy, newDummy, "Diagonal length"); } void TestGetExtent() { DummyTestClass::Pointer dummy = DummyTestClass::New(); double bounds[6] = {1, 3, 5, 8, 7.5, 11.5}; dummy->SetFloatBounds(bounds); CPPUNIT_ASSERT(mitk::Equal(2., dummy->GetExtent(0))); CPPUNIT_ASSERT(mitk::Equal(3., dummy->GetExtent(1))); CPPUNIT_ASSERT(mitk::Equal(4., dummy->GetExtent(2))); // dummy must not have changed DummyTestClass::Pointer newDummy = DummyTestClass::New(); newDummy->SetFloatBounds(bounds); MITK_ASSERT_EQUAL(dummy, newDummy, "Extend"); } void TestIsInside() { DummyTestClass::Pointer dummy = DummyTestClass::New(); double bounds[6] = {1, 3, 5, 8, 7.5, 11.5}; dummy->SetFloatBounds(bounds); mitk::Point3D insidePoint; mitk::Point3D outsidePoint; mitk::FillVector3D(insidePoint, 2, 6, 7.6); mitk::FillVector3D(outsidePoint, 0, 9, 8.2); CPPUNIT_ASSERT(dummy->IsIndexInside(insidePoint)); CPPUNIT_ASSERT(false == dummy->IsIndexInside(outsidePoint)); dummy->IndexToWorld(insidePoint, insidePoint); dummy->IndexToWorld(outsidePoint, outsidePoint); CPPUNIT_ASSERT(dummy->IsInside(insidePoint)); CPPUNIT_ASSERT(false == dummy->IsInside(outsidePoint)); // dummy must not have changed DummyTestClass::Pointer newDummy = DummyTestClass::New(); newDummy->SetFloatBounds(bounds); MITK_ASSERT_EQUAL(dummy, newDummy, "Is inside"); } void TestInitialize() { // test standard constructor DummyTestClass::Pointer dummy1 = DummyTestClass::New(); DummyTestClass::Pointer dummy2 = DummyTestClass::New(); dummy2->SetOrigin(anotherPoint); dummy2->SetBounds(anotherBoundingBox->GetBounds()); // mitk::TimeBounds timeBounds; // timeBounds[0] = 1; // timeBounds[1] = 9; // dummy2->SetTimeBounds(timeBounds); dummy2->SetIndexToWorldTransform(anotherTransform); dummy2->SetSpacing(anotherSpacing); dummy1->InitializeGeometry(dummy2); MITK_ASSERT_EQUAL(dummy1, dummy2, "Initialize 1"); dummy1->Initialize(); DummyTestClass::Pointer dummy3 = DummyTestClass::New(); MITK_ASSERT_EQUAL(dummy3, dummy1, "Initialize 2"); } void TestGetMatrixColumn() { DummyTestClass::Pointer dummy = DummyTestClass::New(); dummy->SetIndexToWorldTransform(anotherTransform); mitk::Vector3D testVector, refVector; testVector.SetVnlVector(dummy->GetMatrixColumn(0)); mitk::FillVector3D(refVector, 1, 0, 0); CPPUNIT_ASSERT(testVector == refVector); testVector.SetVnlVector(dummy->GetMatrixColumn(1)); mitk::FillVector3D(refVector, 0, 2, 0); CPPUNIT_ASSERT(testVector == refVector); testVector.SetVnlVector(dummy->GetMatrixColumn(2)); mitk::FillVector3D(refVector, 0, 0, 1); CPPUNIT_ASSERT(testVector == refVector); // dummy must not have changed DummyTestClass::Pointer newDummy = DummyTestClass::New(); newDummy->SetIndexToWorldTransform(anotherTransform); MITK_ASSERT_EQUAL(dummy, newDummy, "GetMatrixColumn"); } /* void (){ DummyTestClass::Pointer dummy = DummyTestClass::New(); CPPUNIT_ASSERT(); //undo changes, new and changed object need to be the same! DummyTestClass::Pointer newDummy = DummyTestClass::New(); CPPUNIT_ASSERT(mitk::Equal(dummy,newDummy,mitk::eps,true)); } */ }; // end class mitkBaseGeometryTestSuite MITK_TEST_SUITE_REGISTRATION(mitkBaseGeometry) diff --git a/Modules/Core/test/mitkFileReaderRegistryTest.cpp b/Modules/Core/test/mitkFileReaderRegistryTest.cpp index dc29617155..f54b7d5809 100644 --- a/Modules/Core/test/mitkFileReaderRegistryTest.cpp +++ b/Modules/Core/test/mitkFileReaderRegistryTest.cpp @@ -1,216 +1,216 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "mitkAbstractFileReader.h" #include "mitkFileReaderRegistry.h" #include "mitkIFileReader.h" #include "mitkTestingMacros.h" #include #include #include class DummyReader : public mitk::AbstractFileReader { public: DummyReader(const DummyReader &other) : mitk::AbstractFileReader(other) {} DummyReader(const std::string &mimeTypeName, const std::string &extension, int priority) : mitk::AbstractFileReader() { mitk::CustomMimeType mimeType(mimeTypeName); mimeType.AddExtension(extension); mimeType.SetComment("This is a dummy description"); this->SetMimeType(mimeType); this->SetRanking(priority); m_ServiceReg = this->RegisterService(); } - ~DummyReader() + ~DummyReader() override { if (m_ServiceReg) m_ServiceReg.Unregister(); } using mitk::AbstractFileReader::Read; - virtual std::vector> Read() override + std::vector> Read() override { std::vector result; return result; } private: DummyReader *Clone() const override { return new DummyReader(*this); } us::ServiceRegistration m_ServiceReg; }; // End of internal dummy reader class DummyReader2 : public mitk::AbstractFileReader { public: DummyReader2(const DummyReader2 &other) : mitk::AbstractFileReader(other) {} DummyReader2(const std::string &mimeTypeName, const std::string &extension, int priority) : mitk::AbstractFileReader() { mitk::CustomMimeType mimeType(mimeTypeName); mimeType.AddExtension(extension); mimeType.SetComment("This is a second dummy description"); this->SetMimeType(mimeType); this->SetRanking(priority); m_ServiceReg = this->RegisterService(); } - ~DummyReader2() + ~DummyReader2() override { if (m_ServiceReg) m_ServiceReg.Unregister(); } using mitk::AbstractFileReader::Read; - virtual std::vector> Read() override + std::vector> Read() override { std::vector result; return result; } private: DummyReader2 *Clone() const override { return new DummyReader2(*this); } us::ServiceRegistration m_ServiceReg; }; // End of internal dummy reader 2 /** * TODO */ int mitkFileReaderRegistryTest(int /*argc*/, char * /*argv*/ []) { // always start with this! MITK_TEST_BEGIN("FileReaderRegistry"); // mitk::FileReaderRegistry::Pointer frm = mitk::FileReaderRegistry::New(); // MITK_TEST_CONDITION_REQUIRED(argc == 2,"Testing FileReaderRegistry instantiation"); // DummyReader testDR("application/dummy", "test",1); // DummyReader otherDR("application/dummy2", "other",1); // MITK_TEST_CONDITION_REQUIRED(!testDR.CanRead("/this/is/a/folder/file.tes"),"Negative test of default CanRead() // implementation"); // mitk::FileReaderRegistry* readerRegistry = new mitk::FileReaderRegistry; // mitk::IFileReader* returned = readerRegistry->GetReader("bla.test"); // MITK_TEST_CONDITION_REQUIRED(returned && &static_cast(testDR) != returned,"Testing correct // retrieval of FileReader 1/2"); // returned = readerRegistry->GetReader("other"); // MITK_TEST_CONDITION_REQUIRED(returned && &static_cast(otherDR) != returned,"Testing correct // retrieval of FileReader 2/2"); // DummyReader mediocreTestDR("application/dummy", "test", 20); // DummyReader prettyFlyTestDR("application/dummy", "test", 50); // DummyReader2 awesomeTestDR("application/dummy", "test", 100); // returned = readerRegistry->GetReader("test"); // MITK_TEST_CONDITION_REQUIRED(dynamic_cast(returned), "Testing correct priorized retrieval of // FileReader: Best reader"); // Now to give those readers some options, then we will try again // mitk::IFileReader::OptionList options; // options.push_back(std::make_pair("isANiceGuy", true)); // mediocreTestDR.SetOptions(options); // options.clear(); // options.push_back(std::make_pair("canFly", true)); // prettyFlyTestDR.SetOptions(options); // options.push_back(std::make_pair("isAwesome", true)); // awesomeTestDR.SetOptions(options); //note: awesomeReader canFly and isAwesome // // Reset Options, use to define what we want the reader to do // options.clear(); // mitk::IFileReader::OptionNames optionsFilter; // optionsFilter.push_back("canFly"); // returned = readerRegistry->GetReader("test", optionsFilter); // MITK_TEST_CONDITION_REQUIRED(returned && &static_cast(awesomeTestDR) != returned, "Testing // correct retrieval of FileReader with Options: Best reader with options"); // optionsFilter.push_back("isAwesome"); // returned = readerRegistry->GetReader("test", optionsFilter); // MITK_TEST_CONDITION_REQUIRED(returned && &static_cast(awesomeTestDR) != returned, "Testing // correct retrieval of FileReader with multiple Options: Best reader with options"); // optionsFilter.clear(); // optionsFilter.push_back("isANiceGuy"); // returned = readerRegistry->GetReader("test", optionsFilter); // MITK_TEST_CONDITION_REQUIRED(returned && &static_cast(mediocreTestDR) != returned, "Testing // correct retrieval of specific FileReader with Options: Low priority reader with specific option"); // optionsFilter.push_back("canFly"); // returned = readerRegistry->GetReader("test", optionsFilter); // MITK_TEST_CONDITION_REQUIRED(returned == nullptr, "Testing correct return of 0 value when no matching reader was // found"); // // Onward to test the retrieval of multiple readers // std::vector< mitk::IFileReader* > returnedList; // returnedList = readerRegistry->GetReaders("test", optionsFilter); // MITK_TEST_CONDITION_REQUIRED(returnedList.empty(), "Testing correct return of zero readers when no matching reader // was found, asking for all compatibles"); // optionsFilter.clear(); // optionsFilter.push_back("canFly"); // returnedList = readerRegistry->GetReaders("test", optionsFilter); // MITK_TEST_CONDITION_REQUIRED(returnedList.size() == 2, "Testing correct return of two readers when two matching // reader was found, asking for all compatibles"); // MITK_TEST_CONDITION_REQUIRED(dynamic_cast(returnedList.front()), "Testing correct priorization of // returned Readers with options 1/2"); // optionsFilter.clear(); // optionsFilter.push_back("isAwesome"); // returnedList = readerRegistry->GetReaders("test", optionsFilter); // MITK_TEST_CONDITION_REQUIRED(returnedList.size() == 1, "Testing correct return of one readers when one matching // reader was found, asking for all compatibles"); // MITK_TEST_CONDITION_REQUIRED(dynamic_cast(returnedList.front()), "Testing correctness of result // from former query"); // And now to verify a working read chain for a mps file: // mitk::PointSetReader::Pointer psr = mitk::PointSetReader::New(); // std::vector basedata; // basedata = mitk::FileReaderRegistry::Read("F://Build//MITK-Data//pointSet.mps"); // MITK_TEST_CONDITION_REQUIRED(basedata.size() > 0, "Testing correct read of PointSet"); // Testing templated call to ReaderRegistry // mitk::PointSet::Pointer pointset = mitk::FileReaderRegistry::Read< mitk::PointSet // >("F://Build//MITK-Data//pointSet.mps"); // MITK_TEST_CONDITION_REQUIRED(pointset.IsNotNull(), "Testing templated call of Read()"); // And now for something completely different... (Debug) // mitk::LegacyFileReaderService::Pointer lfr = mitk::LegacyFileReaderService::New(".nrrd", "Nearly Raw Raster Data"); // returned = mitk::FileReaderRegistry::GetReader(".nrrd"); // MITK_TEST_CONDITION_REQUIRED(lfr == returned, "Testing correct retrieval of specific FileReader with Options: Low // priority reader with specific option"); // std::vector image = // mitk::FileReaderRegistry::Read("F://Build//MITK-Data//Pic2DplusT.nrrd"); // MITK_TEST_CONDITION_REQUIRED(image.size() > 0, "Testing whether image was returned or not"); // mitk::Image::Pointer image2 = dynamic_cast (image.front().GetPointer()); // MITK_TEST_CONDITION_REQUIRED(image2.IsNotNull(), "Testing if BaseData is an image"); // Delete this here because it will call the PrototypeServiceFactory::Unget() method // of the dummy readers. // delete readerRegistry; // always end with this! MITK_TEST_END(); } diff --git a/Modules/Core/test/mitkLevelWindowManagerCppUnitTest.cpp b/Modules/Core/test/mitkLevelWindowManagerCppUnitTest.cpp index 3c025ff466..8b44acc49f 100644 --- a/Modules/Core/test/mitkLevelWindowManagerCppUnitTest.cpp +++ b/Modules/Core/test/mitkLevelWindowManagerCppUnitTest.cpp @@ -1,154 +1,154 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "mitkTestingMacros.h" #include #include "mitkLevelWindowManager.h" #include "mitkStandaloneDataStorage.h" #include #include #include #include #include class mitkLevelWindowManagerCppUnitTestSuite : public mitk::TestFixture { CPPUNIT_TEST_SUITE(mitkLevelWindowManagerCppUnitTestSuite); MITK_TEST(TestMultiComponentRescaling); CPPUNIT_TEST_SUITE_END(); private: mitk::Image::Pointer m_mitkMultiComponentImage; mitk::Image::Pointer m_mitkImageComponent1; mitk::Image::Pointer m_mitkImageComponent2; public: - void setUp() + void setUp() override { typedef itk::Image ImageType; typedef itk::ImageRegionIterator ImageIteratorType; typedef itk::ImageDuplicator DuplicatorType; typedef itk::ComposeImageFilter CompositeFilterType; // generate two images with one component ImageType::Pointer imageComponent1 = itk::Image::New(); ImageType::IndexType start; start.Fill(0); ImageType::SizeType size; size.Fill(5); ImageType::RegionType region; region.SetSize(size); region.SetIndex(start); imageComponent1->SetRegions(region); imageComponent1->Allocate(); DuplicatorType::Pointer duplicator = DuplicatorType::New(); duplicator->SetInputImage(imageComponent1); duplicator->Update(); ImageType::Pointer imageComponent2 = duplicator->GetOutput(); // give them differing data ImageIteratorType iterator1(imageComponent1, imageComponent1->GetLargestPossibleRegion()); iterator1.GoToBegin(); int i = 0; while (!iterator1.IsAtEnd()) { iterator1.Set((double)i); ++iterator1; ++i; } ImageIteratorType iterator2(imageComponent2, imageComponent2->GetLargestPossibleRegion()); iterator2.GoToBegin(); i = 2000; while (!iterator2.IsAtEnd()) { iterator2.Set((double)i); ++iterator2; ++i; } // copy into single VectorImage CompositeFilterType::Pointer compositeFilter = CompositeFilterType::New(); compositeFilter->SetInput(0, imageComponent1); compositeFilter->SetInput(1, imageComponent2); compositeFilter->Update(); itk::VectorImage::Pointer multiComponentImage = compositeFilter->GetOutput(); // cast images to mitk mitk::CastToMitkImage(multiComponentImage, m_mitkMultiComponentImage); mitk::CastToMitkImage(imageComponent1, m_mitkImageComponent1); mitk::CastToMitkImage(imageComponent2, m_mitkImageComponent2); } static mitk::LevelWindow getLevelWindowForImage(mitk::Image *image, unsigned component) { mitk::LevelWindowManager::Pointer manager; manager = mitk::LevelWindowManager::New(); mitk::StandaloneDataStorage::Pointer ds = mitk::StandaloneDataStorage::New(); try { manager->SetDataStorage(ds); } catch (std::exception &e) { MITK_ERROR << "Exception: " << e.what(); } mitk::DataNode::Pointer node = mitk::DataNode::New(); node->SetData(image); ds->Add(node); node->SetBoolProperty("selected", true); node->SetIntProperty("Image.Displayed Component", component); mitk::LevelWindow levelWindow; node->GetLevelWindow(levelWindow); return levelWindow; // node is an image node because of predicates } void TestMultiComponentRescaling() { // compute level windows for the three images mitk::LevelWindow imageComponent1LevelWindow = getLevelWindowForImage(m_mitkImageComponent1, 0); mitk::LevelWindow imageComponent2LevelWindow = getLevelWindowForImage(m_mitkImageComponent2, 0); // calculate level window for second component in multi-component image mitk::LevelWindow multiComponentImageLevelWindow = getLevelWindowForImage(m_mitkMultiComponentImage, 1); // compare level window boundaries. the multicomponent image level window // should match the second image, since the second component was selected CPPUNIT_ASSERT_EQUAL_MESSAGE("default lower bounds equal", imageComponent2LevelWindow.GetDefaultLowerBound(), multiComponentImageLevelWindow.GetDefaultLowerBound()); CPPUNIT_ASSERT_EQUAL_MESSAGE("default upper bounds equal", imageComponent2LevelWindow.GetDefaultUpperBound(), multiComponentImageLevelWindow.GetDefaultUpperBound()); CPPUNIT_ASSERT_EQUAL_MESSAGE( "range equal", imageComponent2LevelWindow.GetRange(), multiComponentImageLevelWindow.GetRange()); CPPUNIT_ASSERT(imageComponent1LevelWindow.GetDefaultLowerBound() != multiComponentImageLevelWindow.GetDefaultLowerBound()); CPPUNIT_ASSERT(imageComponent1LevelWindow.GetDefaultUpperBound() != multiComponentImageLevelWindow.GetDefaultUpperBound()); } }; MITK_TEST_SUITE_REGISTRATION(mitkLevelWindowManagerCppUnit) diff --git a/Modules/Core/test/mitkPropertyExtensionsTest.cpp b/Modules/Core/test/mitkPropertyExtensionsTest.cpp index 7f8ae68997..00aeb9d58d 100644 --- a/Modules/Core/test/mitkPropertyExtensionsTest.cpp +++ b/Modules/Core/test/mitkPropertyExtensionsTest.cpp @@ -1,67 +1,67 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include #include #include #include class TestPropertyExtension : public mitk::PropertyExtension { public: mitkClassMacro(TestPropertyExtension, mitk::PropertyExtension); mitkNewMacro1Param(Self, const std::string &); std::string GetName() const { return m_Name; } private: explicit TestPropertyExtension(const std::string &name) : m_Name(name) {} - ~TestPropertyExtension() {} + ~TestPropertyExtension() override {} std::string m_Name; }; int mitkPropertyExtensionsTest(int, char *[]) { MITK_TEST_BEGIN("mitkPropertyExtensionsTest"); mitk::IPropertyExtensions *propertyExtensions = mitk::CoreServices::GetPropertyExtensions(); MITK_TEST_CONDITION_REQUIRED(propertyExtensions != nullptr, "Get property extensions service"); propertyExtensions->AddExtension("propertyName1", TestPropertyExtension::New("extension1a").GetPointer()); propertyExtensions->AddExtension("propertyName1", TestPropertyExtension::New("extension1b").GetPointer()); TestPropertyExtension::Pointer extension1 = dynamic_cast(propertyExtensions->GetExtension("propertyName1").GetPointer()); MITK_TEST_CONDITION(extension1.IsNotNull() && extension1->GetName() == "extension1a", "Get extension of \"propertyName1\""); propertyExtensions->AddExtension("propertyName1", TestPropertyExtension::New("extension1b").GetPointer(), "", true); extension1 = dynamic_cast(propertyExtensions->GetExtension("propertyName1").GetPointer()); MITK_TEST_CONDITION(extension1.IsNotNull() && extension1->GetName() == "extension1b", "Get overwritten extension of \"propertyName1\""); propertyExtensions->AddExtension( "propertyName1", TestPropertyExtension::New("extension1c").GetPointer(), "className"); TestPropertyExtension::Pointer extension2 = dynamic_cast(propertyExtensions->GetExtension("propertyName1", "className").GetPointer()); extension1 = dynamic_cast(propertyExtensions->GetExtension("propertyName1").GetPointer()); MITK_TEST_CONDITION(extension1.IsNotNull() && extension1->GetName() == "extension1b" && extension2.IsNotNull() && extension2->GetName() == "extension1c", "Get extension of \"propertyName1\" restricted to \"className\""); MITK_TEST_END(); } diff --git a/Modules/Core/test/mitkVerboseLimitedLinearUndoTest.cpp b/Modules/Core/test/mitkVerboseLimitedLinearUndoTest.cpp index 2cb181029c..c223b1f5d7 100644 --- a/Modules/Core/test/mitkVerboseLimitedLinearUndoTest.cpp +++ b/Modules/Core/test/mitkVerboseLimitedLinearUndoTest.cpp @@ -1,136 +1,136 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "mitkInteractionConst.h" #include "mitkOperation.h" #include "mitkUndoController.h" #include "mitkVerboseLimitedLinearUndo.h" #include "mitkTestingMacros.h" #include int g_GlobalCounter = 0; namespace mitk { /** * @brief Class to check that the destructor of object Operation is called and memory freed **/ class TestOperation : public Operation { public: TestOperation(OperationType operationType) : Operation(operationType) { g_GlobalCounter++; }; - virtual ~TestOperation() { g_GlobalCounter--; }; + ~TestOperation() override { g_GlobalCounter--; }; }; } // namespace /** * @brief Test of the LimitedLinearUndo object * * This test was motivated by bug 3248 which had to check memory leakage * while using mitkOperations within the UndoMechanism. * OperationObjects are added to the UndoController and stored within * two lists (m_UndoList and m_RedoList) inside LimitedLinearUndo and * derived from this VerboseLimitedLinearUndo. When using Undo during * runtime operations are moved from UndoList to RedoList. In case of * a new interaction, causing new operations to be stored in the UndoList * the RedoList needs to be cleared. For this, the operations and all * connected objects need to be deleted and memory to be freed. * And this what this test checks! * * argc and argv are the command line parameters which were passed to * the ADD_TEST command in the CMakeLists.txt file. For the automatic * tests, argv is either empty for the simple tests or contains the filename * of a test image for the image tests (see CMakeLists.txt). */ int mitkVerboseLimitedLinearUndoTest(int /* argc */, char * /*argv*/ []) { // always start with this! MITK_TEST_BEGIN("VerboseLimitedLinearUndo") // an UndoController for the management auto myUndoController = new mitk::UndoController(); // set model, even if it is verboseLimitedLinearUndo by default; this already is tested by UndoControllerTest! myUndoController->SwitchUndoModel(mitk::UndoController::VERBOSE_LIMITEDLINEARUNDO); for (int i = 0; i < 2; i++) { auto doOp = new mitk::TestOperation(mitk::OpTEST); auto undoOp = new mitk::TestOperation(mitk::OpTEST); mitk::OperationEvent *operationEvent = new mitk::OperationEvent(nullptr, doOp, undoOp, "Test"); myUndoController->SetOperationEvent(operationEvent); // increase the ID to separate the operationEvents from each other. Otherwise they would be undone all together at // once. mitk::OperationEvent::IncCurrObjectEventId(); } // now 2 * 2 operation should have been instanciated MITK_TEST_CONDITION_REQUIRED(g_GlobalCounter == 4, "checking initialization of mitkOperation"); // undo one operation; 1 operationEvent element in undo list, 1 in Redo list myUndoController->Undo(); // sending two new OperationEvents: RedoList should be deleted and memory of operations freed for (int i = 0; i < 2; i++) { auto doOp = new mitk::TestOperation(mitk::OpTEST); auto undoOp = new mitk::TestOperation(mitk::OpTEST); mitk::OperationEvent *operationEvent = new mitk::OperationEvent(nullptr, doOp, undoOp, "Test"); myUndoController->SetOperationEvent(operationEvent); // increase the ID to separate the operationEvents from each other. Otherwise they would be undone all together at // once. mitk::OperationEvent::IncCurrObjectEventId(); } // 2 operations should have been deleted, 4 should have been added MITK_TEST_CONDITION_REQUIRED(g_GlobalCounter == 6, "checking adding of operations"); // two operations to RedoList myUndoController->Undo(); myUndoController->ClearRedoList(); // one operationEvent containing 2 operations should have been deleted MITK_TEST_CONDITION_REQUIRED(g_GlobalCounter == 4, "checking deleting RedoList"); // clear all myUndoController->Clear(); MITK_TEST_CONDITION_REQUIRED(g_GlobalCounter == 0, "checking deleting all operations in UndoModel"); // sending two new OperationEvents for (int i = 0; i < 2; i++) { auto doOp = new mitk::TestOperation(mitk::OpTEST); auto undoOp = new mitk::TestOperation(mitk::OpTEST); mitk::OperationEvent *operationEvent = new mitk::OperationEvent(nullptr, doOp, undoOp, "Test"); myUndoController->SetOperationEvent(operationEvent); // increase the ID to separate the operationEvents from each other. Otherwise they would be undone all together at // once. mitk::OperationEvent::IncCurrObjectEventId(); } MITK_TEST_CONDITION_REQUIRED(g_GlobalCounter == 4, "checking added operations in UndoModel"); delete myUndoController; // after deleting UndoController g_GlobalCounter will still be 4 because m_CurrentUndoModel inside myUndoModel is a // static singleton MITK_TEST_CONDITION_REQUIRED(g_GlobalCounter == 4, "checking singleton UndoModel"); // always end with this! MITK_TEST_END() // operations will be deleted after terminating the application } diff --git a/Modules/CppMicroServices/core/doc/snippets/uServices-registration/main.cpp b/Modules/CppMicroServices/core/doc/snippets/uServices-registration/main.cpp index d3ba6e4446..1997969ebe 100644 --- a/Modules/CppMicroServices/core/doc/snippets/uServices-registration/main.cpp +++ b/Modules/CppMicroServices/core/doc/snippets/uServices-registration/main.cpp @@ -1,115 +1,115 @@ #include #include #include #include US_USE_NAMESPACE struct InterfaceA { virtual ~InterfaceA() {} }; struct InterfaceB { virtual ~InterfaceB() {} }; struct InterfaceC { virtual ~InterfaceC() {} }; //! [1-1] class MyService : public InterfaceA {}; //! [1-1] //! [2-1] class MyService2 : public InterfaceA, public InterfaceB {}; //! [2-1] class MyActivator : public ModuleActivator { public: void Load(ModuleContext* context) override { Register1(context); Register2(context); RegisterFactory1(context); RegisterFactory2(context); } void Register1(ModuleContext* context) { //! [1-2] MyService* myService = new MyService; context->RegisterService(myService); //! [1-2] } void Register2(ModuleContext* context) { //! [2-2] MyService2* myService = new MyService2; context->RegisterService(myService); //! [2-2] } void RegisterFactory1(ModuleContext* context) { //! [f1] class MyServiceFactory : public ServiceFactory { - virtual InterfaceMap GetService(Module* /*module*/, const ServiceRegistrationBase& /*registration*/) override + InterfaceMap GetService(Module* /*module*/, const ServiceRegistrationBase& /*registration*/) override { MyService* myService = new MyService; return MakeInterfaceMap(myService); } - virtual void UngetService(Module* /*module*/, const ServiceRegistrationBase& /*registration*/, + void UngetService(Module* /*module*/, const ServiceRegistrationBase& /*registration*/, const InterfaceMap& service) override { delete ExtractInterface(service); } }; MyServiceFactory* myServiceFactory = new MyServiceFactory; context->RegisterService(myServiceFactory); //! [f1] } void RegisterFactory2(ModuleContext* context) { //! [f2] class MyServiceFactory : public ServiceFactory { - virtual InterfaceMap GetService(Module* /*module*/, const ServiceRegistrationBase& /*registration*/) override + InterfaceMap GetService(Module* /*module*/, const ServiceRegistrationBase& /*registration*/) override { MyService2* myService = new MyService2; return MakeInterfaceMap(myService); } - virtual void UngetService(Module* /*module*/, const ServiceRegistrationBase& /*registration*/, + void UngetService(Module* /*module*/, const ServiceRegistrationBase& /*registration*/, const InterfaceMap& service) override { delete ExtractInterface(service); } }; MyServiceFactory* myServiceFactory = new MyServiceFactory; context->RegisterService(static_cast(myServiceFactory)); //! [f2] // In the RegisterService call above, we could remove the static_cast because local types // are not considered in template argument type deduction and hence the compiler choose // the correct RegisterService(ServiceFactory*) overload. However, local types are // usually the exception and using a non-local type for the service factory would make the // compiler choose RegisterService(Impl*) instead, unless we use the static_cast. } void Unload(ModuleContext* /*context*/) override { /* cleanup */ } }; US_EXPORT_MODULE_ACTIVATOR(MyActivator) int main(int /*argc*/, char* /*argv*/[]) { MyActivator ma; return 0; } diff --git a/Modules/CppMicroServices/core/doc/snippets/uServices-servicetracker/main.cpp b/Modules/CppMicroServices/core/doc/snippets/uServices-servicetracker/main.cpp index db66194a84..0ab4f49d98 100644 --- a/Modules/CppMicroServices/core/doc/snippets/uServices-servicetracker/main.cpp +++ b/Modules/CppMicroServices/core/doc/snippets/uServices-servicetracker/main.cpp @@ -1,113 +1,113 @@ #include #include US_USE_NAMESPACE struct IFooService {}; ///! [tt] struct MyTrackedClass { /* ... */ }; //! [tt] //! [ttt] struct MyTrackedClassTraits : public TrackedTypeTraitsBase { static bool IsValid(const TrackedType&) { // Dummy implementation return true; } static void Dispose(TrackedType&) {} static TrackedType DefaultValue() { return TrackedType(); } }; //! [ttt] //! [customizer] struct MyTrackingCustomizer : public ServiceTrackerCustomizer { - virtual MyTrackedClass AddingService(const ServiceReferenceType&) override + MyTrackedClass AddingService(const ServiceReferenceType&) override { return MyTrackedClass(); } - virtual void ModifiedService(const ServiceReferenceType&, MyTrackedClass) override + void ModifiedService(const ServiceReferenceType&, MyTrackedClass) override { } - virtual void RemovedService(const ServiceReferenceType&, MyTrackedClass) override + void RemovedService(const ServiceReferenceType&, MyTrackedClass) override { } }; //! [customizer] struct MyTrackingPointerCustomizer : public ServiceTrackerCustomizer { - virtual MyTrackedClass* AddingService(const ServiceReferenceType&) override + MyTrackedClass* AddingService(const ServiceReferenceType&) override { return new MyTrackedClass(); } - virtual void ModifiedService(const ServiceReferenceType&, MyTrackedClass*) override + void ModifiedService(const ServiceReferenceType&, MyTrackedClass*) override { } - virtual void RemovedService(const ServiceReferenceType&, MyTrackedClass*) override + void RemovedService(const ServiceReferenceType&, MyTrackedClass*) override { } }; // For compilation test purposes only struct MyTrackingCustomizerVoid : public ServiceTrackerCustomizer { - virtual MyTrackedClass AddingService(const ServiceReferenceType&) override + MyTrackedClass AddingService(const ServiceReferenceType&) override { return MyTrackedClass(); } - virtual void ModifiedService(const ServiceReferenceType&, MyTrackedClass) override + void ModifiedService(const ServiceReferenceType&, MyTrackedClass) override { } - virtual void RemovedService(const ServiceReferenceType&, MyTrackedClass) override + void RemovedService(const ServiceReferenceType&, MyTrackedClass) override { } }; int main(int /*argc*/, char* /*argv*/[]) { { //! [tracker] MyTrackingCustomizer myCustomizer; ServiceTracker tracker(GetModuleContext(), &myCustomizer); //! [tracker] } { //! [tracker2] MyTrackingPointerCustomizer myCustomizer; ServiceTracker > tracker(GetModuleContext(), &myCustomizer); //! [tracker2] } // For compilation test purposes only MyTrackingCustomizerVoid myCustomizer2; try { ServiceTracker tracker2(GetModuleContext(), &myCustomizer2); ServiceTracker > tracker3(GetModuleContext()); } catch (const us::ServiceException&) {} return 0; } #include US_INITIALIZE_MODULE diff --git a/Modules/CppMicroServices/core/src/service/usServiceListenerEntry.cpp b/Modules/CppMicroServices/core/src/service/usServiceListenerEntry.cpp index 0792525266..aa72db5d84 100644 --- a/Modules/CppMicroServices/core/src/service/usServiceListenerEntry.cpp +++ b/Modules/CppMicroServices/core/src/service/usServiceListenerEntry.cpp @@ -1,148 +1,148 @@ /*============================================================================= Library: CppMicroServices Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. =============================================================================*/ #include "usServiceListenerEntry_p.h" #include "usServiceListenerHook_p.h" #include US_BEGIN_NAMESPACE class ServiceListenerEntryData : public ServiceListenerHook::ListenerInfoData { public: ServiceListenerEntryData(ModuleContext* mc, const ServiceListenerEntry::ServiceListener& l, void* data, const std::string& filter) : ServiceListenerHook::ListenerInfoData(mc, l, data, filter) , ldap() , hashValue(0) { if (!filter.empty()) { ldap = LDAPExpr(filter); } } - ~ServiceListenerEntryData() + ~ServiceListenerEntryData() override { } LDAPExpr ldap; /** * The elements of "simple" filters are cached, for easy lookup. * * The grammar for simple filters is as follows: * *
    * Simple = '(' attr '=' value ')'
    *        | '(' '|' Simple+ ')'
    * 
* where attr is one of Constants#OBJECTCLASS, * Constants#SERVICE_ID or Constants#SERVICE_PID, and * value must not contain a wildcard character. *

* The index of the vector determines which key the cache is for * (see ServiceListenerState#hashedKeys). For each key, there is * a vector pointing out the values which are accepted by this * ServiceListenerEntry's filter. This cache is maintained to make * it easy to remove this service listener. */ LDAPExpr::LocalCache local_cache; std::size_t hashValue; private: // purposely not implemented ServiceListenerEntryData(const ServiceListenerEntryData&); ServiceListenerEntryData& operator=(const ServiceListenerEntryData&); }; ServiceListenerEntry::ServiceListenerEntry(const ServiceListenerEntry& other) : ServiceListenerHook::ListenerInfo(other) { } ServiceListenerEntry::ServiceListenerEntry(const ServiceListenerHook::ListenerInfo& info) : ServiceListenerHook::ListenerInfo(info) { assert(info.d); } ServiceListenerEntry::~ServiceListenerEntry() { } ServiceListenerEntry& ServiceListenerEntry::operator=(const ServiceListenerEntry& other) { d = other.d; return *this; } void ServiceListenerEntry::SetRemoved(bool removed) const { d->bRemoved = removed; } ServiceListenerEntry::ServiceListenerEntry(ModuleContext* mc, const ServiceListener& l, void* data, const std::string& filter) : ServiceListenerHook::ListenerInfo(new ServiceListenerEntryData(mc, l, data, filter)) { } const LDAPExpr& ServiceListenerEntry::GetLDAPExpr() const { return static_cast(d.Data())->ldap; } LDAPExpr::LocalCache& ServiceListenerEntry::GetLocalCache() const { return static_cast(d.Data())->local_cache; } void ServiceListenerEntry::CallDelegate(const ServiceEvent& event) const { d->listener(event); } bool ServiceListenerEntry::operator==(const ServiceListenerEntry& other) const { return ((d->mc == nullptr || other.d->mc == nullptr) || d->mc == other.d->mc) && (d->data == other.d->data) && ServiceListenerCompare()(d->listener, other.d->listener); } std::size_t ServiceListenerEntry::Hash() const { using namespace US_HASH_FUNCTION_NAMESPACE; if (static_cast(d.Data())->hashValue == 0) { static_cast(d.Data())->hashValue = ((US_HASH_FUNCTION(ModuleContext*, d->mc) ^ (US_HASH_FUNCTION(void*, d->data) << 1)) >> 1) ^ (US_HASH_FUNCTION(US_SERVICE_LISTENER_FUNCTOR, d->listener) << 1); } return static_cast(d.Data())->hashValue; } US_END_NAMESPACE diff --git a/Modules/CppMicroServices/core/test/modules/libA/usTestModuleA.cpp b/Modules/CppMicroServices/core/test/modules/libA/usTestModuleA.cpp index 8ef066de4c..9f6210573c 100644 --- a/Modules/CppMicroServices/core/test/modules/libA/usTestModuleA.cpp +++ b/Modules/CppMicroServices/core/test/modules/libA/usTestModuleA.cpp @@ -1,77 +1,77 @@ /*============================================================================= Library: CppMicroServices Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. =============================================================================*/ #include "usTestModuleAService.h" #include #include #include US_BEGIN_NAMESPACE struct TestModuleA : public TestModuleAService { TestModuleA(ModuleContext* mc) { US_INFO << "Registering TestModuleAService"; sr = mc->RegisterService(this); } void Unregister() { if (sr) { sr.Unregister(); sr = 0; } } private: ServiceRegistration sr; }; class TestModuleAActivator : public ModuleActivator { public: TestModuleAActivator() : s(0) {} - ~TestModuleAActivator() { delete s; } + ~TestModuleAActivator() override { delete s; } void Load(ModuleContext* context) override { s = new TestModuleA(context); } void Unload(ModuleContext*) override { } private: TestModuleA* s; }; US_END_NAMESPACE US_EXPORT_MODULE_ACTIVATOR(US_PREPEND_NAMESPACE(TestModuleAActivator)) diff --git a/Modules/CppMicroServices/core/test/modules/libA2/usTestModuleA2.cpp b/Modules/CppMicroServices/core/test/modules/libA2/usTestModuleA2.cpp index a8b1088361..405db6024a 100644 --- a/Modules/CppMicroServices/core/test/modules/libA2/usTestModuleA2.cpp +++ b/Modules/CppMicroServices/core/test/modules/libA2/usTestModuleA2.cpp @@ -1,76 +1,76 @@ /*============================================================================= Library: CppMicroServices Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. =============================================================================*/ #include "usTestModuleA2Service.h" #include #include US_BEGIN_NAMESPACE struct TestModuleA2 : public TestModuleA2Service { TestModuleA2(ModuleContext* mc) { US_INFO << "Registering TestModuleA2Service"; sr = mc->RegisterService(this); } void Unregister() { if (sr) { sr.Unregister(); } } private: ServiceRegistration sr; }; class TestModuleA2Activator : public ModuleActivator { public: TestModuleA2Activator() : s(0) {} - ~TestModuleA2Activator() { delete s; } + ~TestModuleA2Activator() override { delete s; } void Load(ModuleContext* context) override { s = new TestModuleA2(context); } void Unload(ModuleContext* /*context*/) override { s->Unregister(); } private: TestModuleA2* s; }; US_END_NAMESPACE US_EXPORT_MODULE_ACTIVATOR(US_PREPEND_NAMESPACE(TestModuleA2Activator)) diff --git a/Modules/CppMicroServices/core/test/modules/libBWithStatic/usTestModuleB.cpp b/Modules/CppMicroServices/core/test/modules/libBWithStatic/usTestModuleB.cpp index c1f571ec40..9ed3fddf50 100644 --- a/Modules/CppMicroServices/core/test/modules/libBWithStatic/usTestModuleB.cpp +++ b/Modules/CppMicroServices/core/test/modules/libBWithStatic/usTestModuleB.cpp @@ -1,66 +1,66 @@ /*============================================================================= Library: CppMicroServices Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. =============================================================================*/ #include "usTestModuleBService.h" #include #include #include US_BEGIN_NAMESPACE struct TestModuleB : public TestModuleBService { TestModuleB(ModuleContext* mc) { US_INFO << "Registering TestModuleBService"; mc->RegisterService(this); } }; class TestModuleBActivator : public ModuleActivator { public: TestModuleBActivator() : s(0) {} - ~TestModuleBActivator() { delete s; } + ~TestModuleBActivator() override { delete s; } void Load(ModuleContext* context) override { s = new TestModuleB(context); } void Unload(ModuleContext*) override { } private: TestModuleB* s; }; US_END_NAMESPACE US_EXPORT_MODULE_ACTIVATOR(US_PREPEND_NAMESPACE(TestModuleBActivator)) US_IMPORT_MODULE(TestModuleImportedByB) diff --git a/Modules/CppMicroServices/core/test/modules/libBWithStatic/usTestModuleImportedByB.cpp b/Modules/CppMicroServices/core/test/modules/libBWithStatic/usTestModuleImportedByB.cpp index 0e67a4a3fb..5e003d537a 100644 --- a/Modules/CppMicroServices/core/test/modules/libBWithStatic/usTestModuleImportedByB.cpp +++ b/Modules/CppMicroServices/core/test/modules/libBWithStatic/usTestModuleImportedByB.cpp @@ -1,64 +1,64 @@ /*============================================================================= Library: CppMicroServices Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. =============================================================================*/ #include "usTestModuleBService.h" #include #include US_BEGIN_NAMESPACE struct TestModuleImportedByB : public TestModuleBService { TestModuleImportedByB(ModuleContext* mc) { US_INFO << "Registering TestModuleImportedByB"; mc->RegisterService(this); } }; class TestModuleImportedByBActivator : public ModuleActivator { public: TestModuleImportedByBActivator() : s(0) {} - ~TestModuleImportedByBActivator() { delete s; } + ~TestModuleImportedByBActivator() override { delete s; } void Load(ModuleContext* context) override { s = new TestModuleImportedByB(context); } void Unload(ModuleContext*) override { } private: TestModuleImportedByB* s; }; US_END_NAMESPACE US_EXPORT_MODULE_ACTIVATOR(US_PREPEND_NAMESPACE(TestModuleImportedByBActivator)) diff --git a/Modules/CppMicroServices/core/test/modules/libS/usTestModuleS.cpp b/Modules/CppMicroServices/core/test/modules/libS/usTestModuleS.cpp index e8fae0a999..98972f40c9 100644 --- a/Modules/CppMicroServices/core/test/modules/libS/usTestModuleS.cpp +++ b/Modules/CppMicroServices/core/test/modules/libS/usTestModuleS.cpp @@ -1,142 +1,142 @@ /*============================================================================= Library: CppMicroServices Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. =============================================================================*/ #include "../../usServiceControlInterface.h" #include "usTestModuleSService0.h" #include "usTestModuleSService1.h" #include "usTestModuleSService2.h" #include "usTestModuleSService3.h" #include #include #include US_BEGIN_NAMESPACE class TestModuleS : public ServiceControlInterface, public TestModuleSService0, public TestModuleSService1, public TestModuleSService2, public TestModuleSService3 { public: TestModuleS(ModuleContext* mc) : mc(mc) { for(int i = 0; i <= 3; ++i) { servregs.push_back(ServiceRegistrationU()); } sreg = mc->RegisterService(this); sciReg = mc->RegisterService(this); } virtual const char* GetNameOfClass() const { return "TestModuleS"; } void ServiceControl(int offset, const std::string& operation, int ranking) override { if (0 <= offset && offset <= 3) { if (operation == "register") { if (!servregs[offset]) { std::stringstream servicename; servicename << SERVICE << offset; InterfaceMap ifm; ifm.insert(std::make_pair(servicename.str(), static_cast(this))); ServiceProperties props; props.insert(std::make_pair(ServiceConstants::SERVICE_RANKING(), Any(ranking))); servregs[offset] = mc->RegisterService(ifm, props); } } if (operation == "unregister") { if (servregs[offset]) { ServiceRegistrationU sr1 = servregs[offset]; sr1.Unregister(); servregs[offset] = 0; } } } } void Unregister() { if (sreg) { sreg.Unregister(); } if (sciReg) { sciReg.Unregister(); } } private: static const std::string SERVICE; // = "us::TestModuleSService" ModuleContext* mc; std::vector servregs; ServiceRegistration sreg; ServiceRegistration sciReg; }; const std::string TestModuleS::SERVICE = "us::TestModuleSService"; class TestModuleSActivator : public ModuleActivator { public: TestModuleSActivator() : s(0) {} - ~TestModuleSActivator() { delete s; } + ~TestModuleSActivator() override { delete s; } void Load(ModuleContext* context) override { s = new TestModuleS(context); } void Unload(ModuleContext* /*context*/) override { #ifndef US_BUILD_SHARED_LIBS s->Unregister(); #endif } private: TestModuleS* s; }; US_END_NAMESPACE US_EXPORT_MODULE_ACTIVATOR(US_PREPEND_NAMESPACE(TestModuleSActivator)) diff --git a/Modules/CppMicroServices/core/test/modules/libSL1/usActivatorSL1.cpp b/Modules/CppMicroServices/core/test/modules/libSL1/usActivatorSL1.cpp index 96f23afd6e..4bb29185b0 100644 --- a/Modules/CppMicroServices/core/test/modules/libSL1/usActivatorSL1.cpp +++ b/Modules/CppMicroServices/core/test/modules/libSL1/usActivatorSL1.cpp @@ -1,106 +1,106 @@ /*============================================================================= Library: CppMicroServices Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. =============================================================================*/ #include #include #include #include #include "usFooService.h" US_BEGIN_NAMESPACE class ActivatorSL1 : public ModuleActivator, public ModulePropsInterface, public ServiceTrackerCustomizer { public: ActivatorSL1() : tracker(0), context(0) { } - ~ActivatorSL1() + ~ActivatorSL1() override { delete tracker; } void Load(ModuleContext* context) override { this->context = context; InterfaceMap im = MakeInterfaceMap(this); im.insert(std::make_pair(std::string("ActivatorSL1"), this)); sr = context->RegisterService(im); delete tracker; tracker = new FooTracker(context, this); tracker->Open(); } void Unload(ModuleContext* /*context*/) override { tracker->Close(); } const Properties& GetProperties() const override { return props; } FooService* AddingService(const ServiceReferenceType& reference) override { props["serviceAdded"] = true; FooService* fooService = context->GetService(reference); fooService->foo(); return fooService; } void ModifiedService(const ServiceReferenceType& /*reference*/, FooService* /*service*/) override {} void RemovedService(const ServiceReferenceType& /*reference*/, FooService* /*service*/) override { props["serviceRemoved"] = true; } private: ModulePropsInterface::Properties props; ServiceRegistrationU sr; typedef ServiceTracker FooTracker; FooTracker* tracker; ModuleContext* context; }; // ActivatorSL1 US_END_NAMESPACE US_EXPORT_MODULE_ACTIVATOR(US_PREPEND_NAMESPACE(ActivatorSL1)) diff --git a/Modules/CppMicroServices/core/test/modules/libSL3/usActivatorSL3.cpp b/Modules/CppMicroServices/core/test/modules/libSL3/usActivatorSL3.cpp index a6b609d322..95212637f2 100644 --- a/Modules/CppMicroServices/core/test/modules/libSL3/usActivatorSL3.cpp +++ b/Modules/CppMicroServices/core/test/modules/libSL3/usActivatorSL3.cpp @@ -1,99 +1,99 @@ /*============================================================================= Library: CppMicroServices Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. =============================================================================*/ #include #include #include #include #include US_BEGIN_NAMESPACE class ActivatorSL3 : public ModuleActivator, public ModulePropsInterface, public ServiceTrackerCustomizer { public: ActivatorSL3() : tracker(0), context(0) {} - ~ActivatorSL3() + ~ActivatorSL3() override { delete tracker; } void Load(ModuleContext* context) override { this->context = context; InterfaceMap im = MakeInterfaceMap(this); im.insert(std::make_pair(std::string("ActivatorSL3"), this)); sr = context->RegisterService(im); delete tracker; tracker = new FooTracker(context, this); tracker->Open(); } void Unload(ModuleContext* /*context*/) override { tracker->Close(); } const ModulePropsInterface::Properties& GetProperties() const override { return props; } FooService* AddingService(const ServiceReferenceType& reference) override { props["serviceAdded"] = true; US_INFO << "SL3: Adding reference =" << reference; FooService* fooService = context->GetService(reference); fooService->foo(); return fooService; } void ModifiedService(const ServiceReferenceType& /*reference*/, FooService* /*service*/) override { } void RemovedService(const ServiceReferenceType& reference, FooService* /*service*/) override { props["serviceRemoved"] = true; US_INFO << "SL3: Removing reference =" << reference; } private: typedef ServiceTracker FooTracker; FooTracker* tracker; ModuleContext* context; ServiceRegistrationU sr; ModulePropsInterface::Properties props; }; US_END_NAMESPACE US_EXPORT_MODULE_ACTIVATOR(US_PREPEND_NAMESPACE(ActivatorSL3)) diff --git a/Modules/CppMicroServices/core/test/modules/libSL4/usActivatorSL4.cpp b/Modules/CppMicroServices/core/test/modules/libSL4/usActivatorSL4.cpp index fdfd4a3061..5f86992e51 100644 --- a/Modules/CppMicroServices/core/test/modules/libSL4/usActivatorSL4.cpp +++ b/Modules/CppMicroServices/core/test/modules/libSL4/usActivatorSL4.cpp @@ -1,64 +1,64 @@ /*============================================================================= Library: CppMicroServices Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. =============================================================================*/ #include #include #include #include US_BEGIN_NAMESPACE class ActivatorSL4 : public ModuleActivator, public FooService { public: - ~ActivatorSL4() + ~ActivatorSL4() override { } void foo() override { US_INFO << "TestModuleSL4: Doing foo"; } void Load(ModuleContext* context) override { sr = context->RegisterService(this); US_INFO << "TestModuleSL4: Registered " << sr; } void Unload(ModuleContext* /*context*/) override { } private: ServiceRegistration sr; }; US_END_NAMESPACE US_EXPORT_MODULE_ACTIVATOR(US_PREPEND_NAMESPACE(ActivatorSL4)) diff --git a/Modules/CppMicroServices/core/test/usServiceTemplateTest.cpp b/Modules/CppMicroServices/core/test/usServiceTemplateTest.cpp index 73ae3e6f6d..a483821862 100644 --- a/Modules/CppMicroServices/core/test/usServiceTemplateTest.cpp +++ b/Modules/CppMicroServices/core/test/usServiceTemplateTest.cpp @@ -1,208 +1,208 @@ /*============================================================================= Library: CppMicroServices Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. =============================================================================*/ #include #include #include #include #include "usTestingMacros.h" struct Interface1 {}; struct Interface2 {}; struct Interface3 {}; struct MyService1 : public Interface1 {}; struct MyService2 : public Interface1, public Interface2 {}; struct MyService3 : public Interface1, public Interface2, public Interface3 {}; struct MyFactory1 : public us::ServiceFactory { std::map m_idToServiceMap; - virtual us::InterfaceMap GetService(us::Module* module, const us::ServiceRegistrationBase& /*registration*/) override + us::InterfaceMap GetService(us::Module* module, const us::ServiceRegistrationBase& /*registration*/) override { MyService1* s = new MyService1; m_idToServiceMap.insert(std::make_pair(module->GetModuleId(), s)); return us::MakeInterfaceMap(s); } - virtual void UngetService(us::Module* module, const us::ServiceRegistrationBase& /*registration*/, + void UngetService(us::Module* module, const us::ServiceRegistrationBase& /*registration*/, const us::InterfaceMap& service) override { std::map::iterator iter = m_idToServiceMap.find(module->GetModuleId()); if (iter != m_idToServiceMap.end()) { US_TEST_CONDITION(static_cast(iter->second) == us::ExtractInterface(service), "Compare service pointer") delete iter->second; m_idToServiceMap.erase(iter); } } }; struct MyFactory2 : public us::ServiceFactory { std::map m_idToServiceMap; - virtual us::InterfaceMap GetService(us::Module* module, const us::ServiceRegistrationBase& /*registration*/) override + us::InterfaceMap GetService(us::Module* module, const us::ServiceRegistrationBase& /*registration*/) override { MyService2* s = new MyService2; m_idToServiceMap.insert(std::make_pair(module->GetModuleId(), s)); return us::MakeInterfaceMap(s); } - virtual void UngetService(us::Module* module, const us::ServiceRegistrationBase& /*registration*/, + void UngetService(us::Module* module, const us::ServiceRegistrationBase& /*registration*/, const us::InterfaceMap& service) override { std::map::iterator iter = m_idToServiceMap.find(module->GetModuleId()); if (iter != m_idToServiceMap.end()) { US_TEST_CONDITION(static_cast(iter->second) == us::ExtractInterface(service), "Compare service pointer") delete iter->second; m_idToServiceMap.erase(iter); } } }; struct MyFactory3 : public us::ServiceFactory { std::map m_idToServiceMap; - virtual us::InterfaceMap GetService(us::Module* module, const us::ServiceRegistrationBase& /*registration*/) override + us::InterfaceMap GetService(us::Module* module, const us::ServiceRegistrationBase& /*registration*/) override { MyService3* s = new MyService3; m_idToServiceMap.insert(std::make_pair(module->GetModuleId(), s)); return us::MakeInterfaceMap(s); } - virtual void UngetService(us::Module* module, const us::ServiceRegistrationBase& /*registration*/, + void UngetService(us::Module* module, const us::ServiceRegistrationBase& /*registration*/, const us::InterfaceMap& service) override { std::map::iterator iter = m_idToServiceMap.find(module->GetModuleId()); if (iter != m_idToServiceMap.end()) { US_TEST_CONDITION(static_cast(iter->second) == us::ExtractInterface(service), "Compare service pointer") delete iter->second; m_idToServiceMap.erase(iter); } } }; US_USE_NAMESPACE int usServiceTemplateTest(int /*argc*/, char* /*argv*/[]) { US_TEST_BEGIN("ServiceTemplateTest"); ModuleContext* mc = GetModuleContext(); // Register compile tests MyService1 s1; MyService2 s2; MyService3 s3; us::ServiceRegistration sr1 = mc->RegisterService(&s1); us::ServiceRegistration sr2 = mc->RegisterService(&s2); us::ServiceRegistration sr3 = mc->RegisterService(&s3); MyFactory1 f1; us::ServiceRegistration sfr1 = mc->RegisterService(&f1); MyFactory2 f2; us::ServiceRegistration sfr2 = mc->RegisterService(static_cast(&f2)); MyFactory3 f3; us::ServiceRegistration sfr3 = mc->RegisterService(static_cast(&f3)); #ifdef US_BUILD_SHARED_LIBS US_TEST_CONDITION(mc->GetModule()->GetRegisteredServices().size() == 6, "# of reg services") #endif std::vector > s1refs = mc->GetServiceReferences(); US_TEST_CONDITION(s1refs.size() == 6, "# of interface1 regs") std::vector > s2refs = mc->GetServiceReferences(); US_TEST_CONDITION(s2refs.size() == 4, "# of interface2 regs") std::vector > s3refs = mc->GetServiceReferences(); US_TEST_CONDITION(s3refs.size() == 2, "# of interface3 regs") Interface1* i1 = mc->GetService(sr1.GetReference()); US_TEST_CONDITION(i1 == static_cast(&s1), "interface1 ptr") i1 = nullptr; US_TEST_CONDITION(mc->UngetService(sr1.GetReference()), "unget interface1 ptr") i1 = mc->GetService(sfr1.GetReference()); US_TEST_CONDITION(i1 == static_cast(f1.m_idToServiceMap[mc->GetModule()->GetModuleId()]), "interface1 factory ptr") i1 = nullptr; US_TEST_CONDITION(mc->UngetService(sfr1.GetReference()), "unget interface1 factory ptr") i1 = mc->GetService(sr2.GetReference(InterfaceType())); US_TEST_CONDITION(i1 == static_cast(&s2), "interface1 ptr") i1 = nullptr; US_TEST_CONDITION(mc->UngetService(sr2.GetReference(InterfaceType())), "unget interface1 ptr") i1 = mc->GetService(sfr2.GetReference(InterfaceType())); US_TEST_CONDITION(i1 == static_cast(f2.m_idToServiceMap[mc->GetModule()->GetModuleId()]), "interface1 factory ptr") i1 = nullptr; US_TEST_CONDITION(mc->UngetService(sfr2.GetReference(InterfaceType())), "unget interface1 factory ptr") Interface2* i2 = mc->GetService(sr2.GetReference(InterfaceType())); US_TEST_CONDITION(i2 == static_cast(&s2), "interface2 ptr") i2 = nullptr; US_TEST_CONDITION(mc->UngetService(sr2.GetReference(InterfaceType())), "unget interface2 ptr") i2 = mc->GetService(sfr2.GetReference(InterfaceType())); US_TEST_CONDITION(i2 == static_cast(f2.m_idToServiceMap[mc->GetModule()->GetModuleId()]), "interface2 factory ptr") i2 = nullptr; US_TEST_CONDITION(mc->UngetService(sfr2.GetReference(InterfaceType())), "unget interface2 factory ptr") i1 = mc->GetService(sr3.GetReference(InterfaceType())); US_TEST_CONDITION(i1 == static_cast(&s3), "interface1 ptr") i1 = nullptr; US_TEST_CONDITION(mc->UngetService(sr3.GetReference(InterfaceType())), "unget interface1 ptr") i1 = mc->GetService(sfr3.GetReference(InterfaceType())); US_TEST_CONDITION(i1 == static_cast(f3.m_idToServiceMap[mc->GetModule()->GetModuleId()]), "interface1 factory ptr") i1 = nullptr; US_TEST_CONDITION(mc->UngetService(sfr3.GetReference(InterfaceType())), "unget interface1 factory ptr") i2 = mc->GetService(sr3.GetReference(InterfaceType())); US_TEST_CONDITION(i2 == static_cast(&s3), "interface2 ptr") i2 = nullptr; US_TEST_CONDITION(mc->UngetService(sr3.GetReference(InterfaceType())), "unget interface2 ptr") i2 = mc->GetService(sfr3.GetReference(InterfaceType())); US_TEST_CONDITION(i2 == static_cast(f3.m_idToServiceMap[mc->GetModule()->GetModuleId()]), "interface2 factory ptr") i2 = nullptr; US_TEST_CONDITION(mc->UngetService(sfr3.GetReference(InterfaceType())), "unget interface2 factory ptr") Interface3* i3 = mc->GetService(sr3.GetReference(InterfaceType())); US_TEST_CONDITION(i3 == static_cast(&s3), "interface3 ptr") i3 = nullptr; US_TEST_CONDITION(mc->UngetService(sr3.GetReference(InterfaceType())), "unget interface3 ptr") i3 = mc->GetService(sfr3.GetReference(InterfaceType())); US_TEST_CONDITION(i3 == static_cast(f3.m_idToServiceMap[mc->GetModule()->GetModuleId()]), "interface3 factory ptr") i3 = nullptr; US_TEST_CONDITION(mc->UngetService(sfr3.GetReference(InterfaceType())), "unget interface3 factory ptr") sr1.Unregister(); sr2.Unregister(); sr3.Unregister(); US_TEST_END() } diff --git a/Modules/CppMicroServices/core/test/usServiceTrackerTest.cpp b/Modules/CppMicroServices/core/test/usServiceTrackerTest.cpp index 0e70dafbad..ca689cda42 100644 --- a/Modules/CppMicroServices/core/test/usServiceTrackerTest.cpp +++ b/Modules/CppMicroServices/core/test/usServiceTrackerTest.cpp @@ -1,287 +1,287 @@ /*============================================================================= Library: CppMicroServices Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. =============================================================================*/ #include #include #include #include #include #include #include #include #include "usServiceControlInterface.h" #include US_USE_NAMESPACE bool CheckConvertibility(const std::vector& refs, std::vector::const_iterator idBegin, std::vector::const_iterator idEnd) { std::vector ids; ids.assign(idBegin, idEnd); for (std::vector::const_iterator sri = refs.begin(); sri != refs.end(); ++sri) { for (std::vector::iterator idIter = ids.begin(); idIter != ids.end(); ++idIter) { if (sri->IsConvertibleTo(*idIter)) { ids.erase(idIter); break; } } } return ids.empty(); } struct MyInterfaceOne { virtual ~MyInterfaceOne() {} }; struct MyInterfaceTwo { virtual ~MyInterfaceTwo() {} }; class MyCustomizer : public us::ServiceTrackerCustomizer { public: MyCustomizer(us::ModuleContext* context) : m_context(context) {} - virtual MyInterfaceOne* AddingService(const ServiceReferenceType& reference) override + MyInterfaceOne* AddingService(const ServiceReferenceType& reference) override { US_TEST_CONDITION_REQUIRED(reference, "AddingService() valid reference") return m_context->GetService(reference); } - virtual void ModifiedService(const ServiceReferenceType& reference, MyInterfaceOne* service) override + void ModifiedService(const ServiceReferenceType& reference, MyInterfaceOne* service) override { US_TEST_CONDITION(reference, "ModifiedService() valid reference") US_TEST_CONDITION(service, "ModifiedService() valid service") } - virtual void RemovedService(const ServiceReferenceType& reference, MyInterfaceOne* service) override + void RemovedService(const ServiceReferenceType& reference, MyInterfaceOne* service) override { US_TEST_CONDITION(reference, "RemovedService() valid reference") US_TEST_CONDITION(service, "RemovedService() valid service") } private: us::ModuleContext* m_context; }; void TestFilterString() { us::ModuleContext* context = us::GetModuleContext(); MyCustomizer customizer(context); us::LDAPFilter filter("(" + us::ServiceConstants::SERVICE_ID() + ">=0)"); us::ServiceTracker tracker(context, filter, &customizer); tracker.Open(); struct MyServiceOne : public MyInterfaceOne {}; struct MyServiceTwo : public MyInterfaceTwo {}; MyServiceOne serviceOne; MyServiceTwo serviceTwo; ServiceRegistration reg1 = context->RegisterService(&serviceOne); ServiceRegistration reg2 = context->RegisterService(&serviceTwo); US_TEST_CONDITION(tracker.GetServiceReferences().size() == 1, "tracking count") reg1.Unregister(); reg2.Unregister(); } void TestServiceTracker() { #ifdef US_PLATFORM_WINDOWS const std::string LIB_PATH = US_RUNTIME_OUTPUT_DIRECTORY; #else const std::string LIB_PATH = US_LIBRARY_OUTPUT_DIRECTORY; #endif ModuleContext* mc = GetModuleContext(); SharedLibrary libS(LIB_PATH, "TestModuleS"); #ifdef US_BUILD_SHARED_LIBS // Start the test target to get a service published. try { libS.Load(); } catch (const std::exception& e) { US_TEST_FAILED_MSG( << "Failed to load module, got exception: " << e.what() ); } #endif // 1. Create a ServiceTracker with ServiceTrackerCustomizer == null std::string s1("us::TestModuleSService"); ServiceReferenceU servref = mc->GetServiceReference(s1 + "0"); US_TEST_CONDITION_REQUIRED(servref != 0, "Test if registered service of id us::TestModuleSService0"); ServiceReference servCtrlRef = mc->GetServiceReference(); US_TEST_CONDITION_REQUIRED(servCtrlRef != 0, "Test if constrol service was registered"); ServiceControlInterface* serviceController = mc->GetService(servCtrlRef); US_TEST_CONDITION_REQUIRED(serviceController != 0, "Test valid service controller"); std::unique_ptr> st1(new ServiceTracker(mc, servref)); // 2. Check the size method with an unopened service tracker US_TEST_CONDITION_REQUIRED(st1->Size() == 0, "Test if size == 0"); // 3. Open the service tracker and see what it finds, // expect to find one instance of the implementation, // "org.cppmicroservices.TestModuleSService0" st1->Open(); std::vector sa2 = st1->GetServiceReferences(); US_TEST_CONDITION_REQUIRED(sa2.size() == 1, "Checking ServiceTracker size"); US_TEST_CONDITION_REQUIRED(s1 + "0" == sa2[0].GetInterfaceId(), "Checking service implementation name"); // 5. Close this service tracker st1->Close(); // 6. Check the size method, now when the servicetracker is closed US_TEST_CONDITION_REQUIRED(st1->Size() == 0, "Checking ServiceTracker size"); // 7. Check if we still track anything , we should get null sa2 = st1->GetServiceReferences(); US_TEST_CONDITION_REQUIRED(sa2.empty(), "Checking ServiceTracker size"); // 8. A new Servicetracker, this time with a filter for the object std::string fs = std::string("(") + ServiceConstants::OBJECTCLASS() + "=" + s1 + "*" + ")"; LDAPFilter f1(fs); st1.reset(new ServiceTracker(mc, f1)); // add a service serviceController->ServiceControl(1, "register", 7); // 9. Open the service tracker and see what it finds, // expect to find two instances of references to // "org.cppmicroservices.TestModuleSService*" // i.e. they refer to the same piece of code std::vector ids; ids.push_back((s1 + "0")); ids.push_back((s1 + "1")); ids.push_back((s1 + "2")); ids.push_back((s1 + "3")); st1->Open(); sa2 = st1->GetServiceReferences(); US_TEST_CONDITION_REQUIRED(sa2.size() == 2, "Checking service reference count"); US_TEST_CONDITION_REQUIRED(CheckConvertibility(sa2, ids.begin(), ids.begin()+2), "Check for expected interface id [0]"); US_TEST_CONDITION_REQUIRED(sa2[1].IsConvertibleTo(s1 + "1"), "Check for expected interface id [1]"); // 10. Get libTestModuleS to register one more service and see if it appears serviceController->ServiceControl(2, "register", 1); sa2 = st1->GetServiceReferences(); US_TEST_CONDITION_REQUIRED(sa2.size() == 3, "Checking service reference count"); US_TEST_CONDITION_REQUIRED(CheckConvertibility(sa2, ids.begin(), ids.begin()+3), "Check for expected interface id [2]"); // 11. Get libTestModuleS to register one more service and see if it appears serviceController->ServiceControl(3, "register", 2); sa2 = st1->GetServiceReferences(); US_TEST_CONDITION_REQUIRED(sa2.size() == 4, "Checking service reference count"); US_TEST_CONDITION_REQUIRED(CheckConvertibility(sa2, ids.begin(), ids.end()), "Check for expected interface id [3]"); // 12. Get libTestModuleS to unregister one service and see if it disappears serviceController->ServiceControl(3, "unregister", 0); sa2 = st1->GetServiceReferences(); US_TEST_CONDITION_REQUIRED(sa2.size() == 3, "Checking service reference count"); // 13. Get the highest ranking service reference, it should have ranking 7 ServiceReferenceU h1 = st1->GetServiceReference(); int rank = any_cast(h1.GetProperty(ServiceConstants::SERVICE_RANKING())); US_TEST_CONDITION_REQUIRED(rank == 7, "Check service rank"); // 14. Get the service of the highest ranked service reference InterfaceMap o1 = st1->GetService(h1); US_TEST_CONDITION_REQUIRED(!o1.empty(), "Check for non-null service"); // 14a Get the highest ranked service, directly this time InterfaceMap o3 = st1->GetService(); US_TEST_CONDITION_REQUIRED(!o3.empty(), "Check for non-null service"); US_TEST_CONDITION_REQUIRED(o1 == o3, "Check for equal service instances"); // 15. Now release the tracking of that service and then try to get it // from the servicetracker, which should yield a null object serviceController->ServiceControl(1, "unregister", 7); InterfaceMap o2 = st1->GetService(h1); US_TEST_CONDITION_REQUIRED(o2.empty(), "Checkt that service is null"); // 16. Get all service objects this tracker tracks, it should be 2 std::vector ts1 = st1->GetServices(); US_TEST_CONDITION_REQUIRED(ts1.size() == 2, "Check service count"); // 17. Test the remove method. // First register another service, then remove it being tracked serviceController->ServiceControl(1, "register", 7); h1 = st1->GetServiceReference(); std::vector sa3 = st1->GetServiceReferences(); US_TEST_CONDITION_REQUIRED(sa3.size() == 3, "Check service reference count"); US_TEST_CONDITION_REQUIRED(CheckConvertibility(sa3, ids.begin(), ids.begin()+3), "Check for expected interface id [0]"); st1->Remove(h1); // remove tracking on one servref sa2 = st1->GetServiceReferences(); US_TEST_CONDITION_REQUIRED(sa2.size() == 2, "Check service reference count"); // 18. Test the addingService method,add a service reference // 19. Test the removedService method, remove a service reference // 20. Test the waitForService method InterfaceMap o9 = st1->WaitForService(50); US_TEST_CONDITION_REQUIRED(!o9.empty(), "Checking WaitForService method"); } int usServiceTrackerTest(int /*argc*/, char* /*argv*/[]) { US_TEST_BEGIN("ServiceTrackerTest") TestFilterString(); TestServiceTracker(); US_TEST_END() } diff --git a/Modules/IOExt/Internal/mitkUnstructuredGridVtkWriterFactory.cpp b/Modules/IOExt/Internal/mitkUnstructuredGridVtkWriterFactory.cpp index ee6496267e..b38afce2c4 100644 --- a/Modules/IOExt/Internal/mitkUnstructuredGridVtkWriterFactory.cpp +++ b/Modules/IOExt/Internal/mitkUnstructuredGridVtkWriterFactory.cpp @@ -1,82 +1,82 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "mitkUnstructuredGridVtkWriterFactory.h" #include "itkCreateObjectFunction.h" #include "itkVersion.h" #include "mitkUnstructuredGridVtkWriter.h" #include #include #include namespace mitk { template class CreateUnstructuredGridWriter : public itk::CreateObjectFunctionBase { public: /** Standard class typedefs. */ typedef CreateUnstructuredGridWriter Self; typedef itk::SmartPointer Pointer; /** Methods from itk:LightObject. */ itkFactorylessNewMacro(Self); LightObject::Pointer CreateObject() override { typename T::Pointer p = T::New(); p->Register(); return p.GetPointer(); } protected: CreateUnstructuredGridWriter() {} - ~CreateUnstructuredGridWriter() {} + ~CreateUnstructuredGridWriter() override {} private: CreateUnstructuredGridWriter(const Self &); // purposely not implemented void operator=(const Self &); // purposely not implemented }; UnstructuredGridVtkWriterFactory::UnstructuredGridVtkWriterFactory() { this->RegisterOverride( "IOWriter", "UnstructuredGridVtkWriter", "VTK Legacy Unstructured Grid Writer", 1, mitk::CreateUnstructuredGridWriter>::New()); this->RegisterOverride( "IOWriter", "UnstructuredGridVtkWriter", "VTK XML UnstructuredGrid Writer", 1, mitk::CreateUnstructuredGridWriter>::New()); this->RegisterOverride( "IOWriter", "UnstructuredGridVtkWriter", "VTK Parallel XML UnstructuredGrid Writer", 1, mitk::CreateUnstructuredGridWriter>::New()); } UnstructuredGridVtkWriterFactory::~UnstructuredGridVtkWriterFactory() {} const char *UnstructuredGridVtkWriterFactory::GetITKSourceVersion() const { return ITK_SOURCE_VERSION; } const char *UnstructuredGridVtkWriterFactory::GetDescription() const { return "UnstructuredGridVtkWriterFactory"; } } // end namespace mitk diff --git a/Modules/LegacyIO/mitkImageWriterFactory.cpp b/Modules/LegacyIO/mitkImageWriterFactory.cpp index 183695cf10..6097cb6fc1 100644 --- a/Modules/LegacyIO/mitkImageWriterFactory.cpp +++ b/Modules/LegacyIO/mitkImageWriterFactory.cpp @@ -1,60 +1,60 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "mitkImageWriterFactory.h" #include "itkCreateObjectFunction.h" #include "itkVersion.h" #include "mitkImageWriter.h" namespace mitk { template class CreateImageWriter : public itk::CreateObjectFunctionBase { public: /** Standard class typedefs. */ typedef CreateImageWriter Self; typedef itk::SmartPointer Pointer; /** Methods from itk:LightObject. */ itkFactorylessNewMacro(Self); LightObject::Pointer CreateObject() override { typename T::Pointer p = T::New(); p->Register(); return p.GetPointer(); } protected: CreateImageWriter() {} - ~CreateImageWriter() {} + ~CreateImageWriter() override {} private: CreateImageWriter(const Self &); // purposely not implemented void operator=(const Self &); // purposely not implemented }; ImageWriterFactory::ImageWriterFactory() { this->RegisterOverride( "IOWriter", "ImageWriter", "Image Writer", 1, mitk::CreateImageWriter::New()); } ImageWriterFactory::~ImageWriterFactory() {} const char *ImageWriterFactory::GetITKSourceVersion() const { return ITK_SOURCE_VERSION; } const char *ImageWriterFactory::GetDescription() const { return "ImageWriterFactory"; } } // end namespace mitk diff --git a/Modules/LegacyIO/mitkPointSetWriterFactory.cpp b/Modules/LegacyIO/mitkPointSetWriterFactory.cpp index 544700f325..7f98f72d95 100644 --- a/Modules/LegacyIO/mitkPointSetWriterFactory.cpp +++ b/Modules/LegacyIO/mitkPointSetWriterFactory.cpp @@ -1,60 +1,60 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "mitkPointSetWriterFactory.h" #include "itkCreateObjectFunction.h" #include "itkVersion.h" #include "mitkPointSetWriter.h" namespace mitk { template class CreatePointSetWriter : public itk::CreateObjectFunctionBase { public: /** Standard class typedefs. */ typedef CreatePointSetWriter Self; typedef itk::SmartPointer Pointer; /** Methods from itk:LightObject. */ itkFactorylessNewMacro(Self); LightObject::Pointer CreateObject() override { typename T::Pointer p = T::New(); p->Register(); return p.GetPointer(); } protected: CreatePointSetWriter() {} - ~CreatePointSetWriter() {} + ~CreatePointSetWriter() override {} private: CreatePointSetWriter(const Self &); // purposely not implemented void operator=(const Self &); // purposely not implemented }; PointSetWriterFactory::PointSetWriterFactory() { this->RegisterOverride( "IOWriter", "PointSetWriter", "Point-Set Writer", 1, mitk::CreatePointSetWriter::New()); } PointSetWriterFactory::~PointSetWriterFactory() {} const char *PointSetWriterFactory::GetITKSourceVersion() const { return ITK_SOURCE_VERSION; } const char *PointSetWriterFactory::GetDescription() const { return "PointSetWriterFactory"; } } // end namespace mitk diff --git a/Modules/LegacyIO/mitkSurfaceVtkWriterFactory.cpp b/Modules/LegacyIO/mitkSurfaceVtkWriterFactory.cpp index 7fbd296f0d..b16f7ed086 100644 --- a/Modules/LegacyIO/mitkSurfaceVtkWriterFactory.cpp +++ b/Modules/LegacyIO/mitkSurfaceVtkWriterFactory.cpp @@ -1,64 +1,64 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "mitkSurfaceVtkWriterFactory.h" #include "itkCreateObjectFunction.h" #include "itkVersion.h" #include #include namespace mitk { template class CreateSurfaceWriter : public itk::CreateObjectFunctionBase { public: /** Standard class typedefs. */ typedef CreateSurfaceWriter Self; typedef itk::SmartPointer Pointer; /** Methods from itk:LightObject. */ itkFactorylessNewMacro(Self); LightObject::Pointer CreateObject() override { typename T::Pointer p = T::New(); p->Register(); return p.GetPointer(); } protected: CreateSurfaceWriter() {} - ~CreateSurfaceWriter() {} + ~CreateSurfaceWriter() override {} private: CreateSurfaceWriter(const Self &); // purposely not implemented void operator=(const Self &); // purposely not implemented }; SurfaceVtkWriterFactory::SurfaceVtkWriterFactory() { this->RegisterOverride("IOWriter", "SurfaceVtkWriter", "Surface Vtk Writer", 1, mitk::CreateSurfaceWriter>::New()); } SurfaceVtkWriterFactory::~SurfaceVtkWriterFactory() {} const char *SurfaceVtkWriterFactory::GetITKSourceVersion() const { return ITK_SOURCE_VERSION; } const char *SurfaceVtkWriterFactory::GetDescription() const { return "SurfaceVtkWriterFactory"; } } // end namespace mitk diff --git a/Modules/Persistence/Testing/mitkPersistenceTest.cpp b/Modules/Persistence/Testing/mitkPersistenceTest.cpp index 8af0fbe4bb..ce71861a71 100644 --- a/Modules/Persistence/Testing/mitkPersistenceTest.cpp +++ b/Modules/Persistence/Testing/mitkPersistenceTest.cpp @@ -1,191 +1,191 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include #include #include #include #include #include #include #include #include #include #include struct PersistenceTestClass { PersistenceTestClass() : id(""), param1(1), param2(2), param3(false) {} std::string id; int param1; double param2; bool param3; PERSISTENCE_CREATE3(PersistenceTestClass, id, param1, param2, param3) }; struct TestPropertyListReplacedObserver : public mitk::PropertyListReplacedObserver { TestPropertyListReplacedObserver() : counter(0) {} - virtual void BeforePropertyListReplaced(const std::string &id, mitk::PropertyList *) override + void BeforePropertyListReplaced(const std::string &id, mitk::PropertyList *) override { if (id == m_Id) ++counter; } - virtual void AfterPropertyListReplaced(const std::string &id, mitk::PropertyList *) override + void AfterPropertyListReplaced(const std::string &id, mitk::PropertyList *) override { if (id == m_Id) ++counter; } int counter; std::string m_Id; }; class mitkPersistenceTestSuite : public mitk::TestFixture { CPPUNIT_TEST_SUITE(mitkPersistenceTestSuite); MITK_TEST(PersistenceTest); CPPUNIT_TEST_SUITE_END(); private: // private test members that are initialized by setUp() std::string testClassId; int param1; double param2; bool param3; public: void setUp() override { testClassId = "testClass"; param1 = 100; param2 = 201.56; param3 = true; } void PersistenceTest() { // dummy load of SceneIO, otherwise PersistenceService won't be available mitk::PersistenceService::LoadModule(); PERSISTENCE_GET_SERVICE_MACRO CPPUNIT_ASSERT_MESSAGE("Testing availability of the PersistenceService.", persistenceService != nullptr); // Initialize testable parameter values std::string defaultPersistenceFile = persistenceService->GetDefaultPersistenceFile(); PersistenceTestClass autoLoadTestClass; autoLoadTestClass.id = testClassId; if (itksys::SystemTools::FileExists(defaultPersistenceFile.c_str(), true) && persistenceService->GetAutoLoadAndSave()) { /// Test auto load/save of the PersistenceService. itksys::SystemTools::RemoveFile(defaultPersistenceFile.c_str()); autoLoadTestClass.FromPropertyList(); testParams(autoLoadTestClass, "autoLoadTestClass"); } std::string testTempFile = mitk::IOUtil::CreateTemporaryFile("XXXXXX.mitk"); std::string testXmlTempFile = mitk::IOUtil::CreateTemporaryFile("PersistenceTestFileXXXXXX.xml"); MITK_INFO << "Testing standard write to scene file/xml file."; PersistenceTestClass testClass; testClass.id = testClassId; testClass.param1 = param1; testClass.param2 = param2; testClass.param3 = param3; CPPUNIT_ASSERT_MESSAGE("Testing to save a scene file", testClass.Save(testTempFile)); CPPUNIT_ASSERT_MESSAGE("testing to save an xml file", testClass.Save(testXmlTempFile)); CPPUNIT_ASSERT_MESSAGE("Testing read from scene file: persistenceService->RemovePropertyList(testClassId)", persistenceService->RemovePropertyList(testClassId)); PersistenceTestClass testClass2; testClass2.id = testClassId; CPPUNIT_ASSERT_MESSAGE("Testing read from scene file: testClass2.Load(testTempFile.path())", testClass2.Load(testTempFile)); testParams(testClass2, "testClass2"); CPPUNIT_ASSERT_MESSAGE("Testing read from xml file: persistenceService->RemovePropertyList(testClassId)", persistenceService->RemovePropertyList(testClassId)); PersistenceTestClass testClass3; testClass3.id = testClassId; CPPUNIT_ASSERT_MESSAGE("Testing read from xml file: testClass3.Load(testXmlTempFile.path())", testClass3.Load(testXmlTempFile)); testParams(testClass3, "testClass3"); CPPUNIT_ASSERT_MESSAGE( "Testing appendChanges functionality with scene load/write: persistenceService->RemovePropertyList(testClassId)", persistenceService->RemovePropertyList(testClassId)); CPPUNIT_ASSERT_MESSAGE( "Testing appendChanges functionality with scene load/write: persistenceService->Save(testTempFile.path())", persistenceService->Save(testTempFile, true)); CPPUNIT_ASSERT_MESSAGE( "Testing appendChanges functionality with scene load/write: persistenceService->Load(testTempFile.path())", persistenceService->Load(testTempFile)); PersistenceTestClass testClass4; testClass4.id = testClassId; testClass4.FromPropertyList(); testParams(testClass4, "testClass4"); CPPUNIT_ASSERT_MESSAGE( "Testing appendChanges functionality with xml load/write: persistenceService->RemovePropertyList(testClassId)", persistenceService->RemovePropertyList(testClassId)); CPPUNIT_ASSERT_MESSAGE( "Testing appendChanges functionality with xml load/write: persistenceService->Save(testXmlTempFile.path())", persistenceService->Save(testXmlTempFile, true)); CPPUNIT_ASSERT_MESSAGE( "Testing appendChanges functionality with xml load/write: persistenceService->Load(testXmlTempFile.path())", persistenceService->Load(testXmlTempFile)); PersistenceTestClass testClass5; testClass5.id = testClassId; testClass5.FromPropertyList(); testParams(testClass5, "testClass5"); // Test Observer Functionality TestPropertyListReplacedObserver testObserver; testObserver.m_Id = testClassId; persistenceService->AddPropertyListReplacedObserver(&testObserver); persistenceService->Load(testTempFile); CPPUNIT_ASSERT_MESSAGE( "Testing observer functionality: testObserver.counter == 2, testObserver.counter is " + std::to_string(testObserver.counter), testObserver.counter == 2); autoLoadTestClass.param1 = param1; autoLoadTestClass.param2 = param2; autoLoadTestClass.param3 = param3; autoLoadTestClass.ToPropertyList(); } /** * Helper Method that compares the returned class to its base values */ void testParams(const PersistenceTestClass &testClass, const std::string &) { CPPUNIT_ASSERT_MESSAGE("Parameter of TestClass not equal to reference value: testClass.id", testClass.id == testClassId); CPPUNIT_ASSERT_MESSAGE("Parameter of TestClass not equal to reference value: testClass.param1", testClass.param1 == param1); CPPUNIT_ASSERT_MESSAGE("Parameter of TestClass not equal to reference value: testClass.param2", testClass.param2 == param2); CPPUNIT_ASSERT_MESSAGE("Parameter of TestClass not equal to reference value: testClass.param3", testClass.param3 == param3); } }; MITK_TEST_SUITE_REGISTRATION(mitkPersistence) diff --git a/Modules/PhotoacousticsLib/test/mitkMCThreadHandlerTest.cpp b/Modules/PhotoacousticsLib/test/mitkMCThreadHandlerTest.cpp index 83ae8b69c7..1607acc6cd 100644 --- a/Modules/PhotoacousticsLib/test/mitkMCThreadHandlerTest.cpp +++ b/Modules/PhotoacousticsLib/test/mitkMCThreadHandlerTest.cpp @@ -1,124 +1,124 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include #include #include // us #include #include #include #include #include #include #include class mitkMCThreadHandlerTestSuite : public mitk::TestFixture { CPPUNIT_TEST_SUITE(mitkMCThreadHandlerTestSuite); MITK_TEST(testConstructorBehavior); MITK_TEST(testCorrectNumberOfPhotons); MITK_TEST(testCorrectNumberOfPhotonsWithUnevenPackageSize); MITK_TEST(testCorrectNumberOfPhotonsWithTooLargePackageSize); MITK_TEST(testCorrectTimeMeasure); CPPUNIT_TEST_SUITE_END(); private: mitk::pa::MonteCarloThreadHandler::Pointer m_MonteCarloThreadHandler; long m_NumberOrTime = 500; public: - void setUp() + void setUp() override { } void testConstructorBehavior() { auto threadHandler1 = mitk::pa::MonteCarloThreadHandler::New(m_NumberOrTime, true, true); auto threadHandler2 = mitk::pa::MonteCarloThreadHandler::New(m_NumberOrTime, true); CPPUNIT_ASSERT(mitk::pa::Equal(threadHandler1, threadHandler2, 1e-6, true)); } void testCorrectTimeMeasure() { for (int i = 0; i < 10; i++) { m_MonteCarloThreadHandler = mitk::pa::MonteCarloThreadHandler::New(m_NumberOrTime, true, false); auto timeBefore = std::chrono::duration_cast(std::chrono::high_resolution_clock::now().time_since_epoch()).count(); long nextWorkPackage = 0; while ((nextWorkPackage = m_MonteCarloThreadHandler->GetNextWorkPackage()) > 0) {//Do nothing } auto timeAfter = std::chrono::duration_cast(std::chrono::high_resolution_clock::now().time_since_epoch()).count(); //Assert that the time error is less than 10% in a 500ms sample size //This test might not be stable when on different machines. - CPPUNIT_ASSERT(abs((timeAfter - timeBefore) - m_NumberOrTime) <= 50); + CPPUNIT_ASSERT(std::abs((timeAfter - timeBefore) - m_NumberOrTime) <= 50); } } void testCorrectNumberOfPhotons() { m_MonteCarloThreadHandler = mitk::pa::MonteCarloThreadHandler::New(m_NumberOrTime, false, false); m_MonteCarloThreadHandler->SetPackageSize(100); long numberOfPhotonsSimulated = 0; long nextWorkPackage = 0; while ((nextWorkPackage = m_MonteCarloThreadHandler->GetNextWorkPackage()) > 0) { numberOfPhotonsSimulated += nextWorkPackage; } CPPUNIT_ASSERT(numberOfPhotonsSimulated == m_NumberOrTime); } void testCorrectNumberOfPhotonsWithUnevenPackageSize() { m_MonteCarloThreadHandler = mitk::pa::MonteCarloThreadHandler::New(m_NumberOrTime, false, false); m_MonteCarloThreadHandler->SetPackageSize(77); long numberOfPhotonsSimulated = 0; long nextWorkPackage = 0; while ((nextWorkPackage = m_MonteCarloThreadHandler->GetNextWorkPackage()) > 0) { numberOfPhotonsSimulated += nextWorkPackage; } CPPUNIT_ASSERT(numberOfPhotonsSimulated == m_NumberOrTime); } void testCorrectNumberOfPhotonsWithTooLargePackageSize() { m_MonteCarloThreadHandler = mitk::pa::MonteCarloThreadHandler::New(m_NumberOrTime, false, false); m_MonteCarloThreadHandler->SetPackageSize(10000); long numberOfPhotonsSimulated = 0; long nextWorkPackage = 0; while ((nextWorkPackage = m_MonteCarloThreadHandler->GetNextWorkPackage()) > 0) { numberOfPhotonsSimulated += nextWorkPackage; } CPPUNIT_ASSERT(numberOfPhotonsSimulated == m_NumberOrTime); } - void tearDown() + void tearDown() override { m_MonteCarloThreadHandler = nullptr; } }; MITK_TEST_SUITE_REGISTRATION(mitkMCThreadHandler) diff --git a/Modules/PhotoacousticsLib/test/mitkMcxyzXmlTest.cpp b/Modules/PhotoacousticsLib/test/mitkMcxyzXmlTest.cpp index 7a559b0979..441b0e755e 100644 --- a/Modules/PhotoacousticsLib/test/mitkMcxyzXmlTest.cpp +++ b/Modules/PhotoacousticsLib/test/mitkMcxyzXmlTest.cpp @@ -1,242 +1,242 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include #include #include // us #include #include #include #include #include #include #include #include class mitkMcxyzXmlTestSuite : public mitk::TestFixture { CPPUNIT_TEST_SUITE(mitkMcxyzXmlTestSuite); MITK_TEST(TestCreatePointSourceProbe); MITK_TEST(TestCreateCircleSourceProbe); MITK_TEST(TestCreateRectangleSourceProbe); MITK_TEST(TestCreateTwoPointSourcesProbe); MITK_TEST(TestCreateAllSourcesProbe); MITK_TEST(TestValuesAreInBoundsUniformRectangle); MITK_TEST(TestValuesAreInBoundsGaussianRectangle); CPPUNIT_TEST_SUITE_END(); private: mitk::pa::LightSource::Pointer m_LightSource; mitk::pa::Probe::Pointer m_Probe; std::string m_XmlProbePointSource; std::string m_XmlProbeCircleSource; std::string m_XmlProbeRectangleSource; std::string m_XmlProbeTwoPointSources; std::string m_XmlProbeAllSources; public: - void setUp() + void setUp() override { m_LightSource = mitk::pa::LightSource::New(); LoadXmlFile("pointsource.xml", &m_XmlProbePointSource); LoadXmlFile("circlesource.xml", &m_XmlProbeCircleSource); LoadXmlFile("rectanglesource.xml", &m_XmlProbeRectangleSource); LoadXmlFile("twopointsources.xml", &m_XmlProbeTwoPointSources); LoadXmlFile("allsources.xml", &m_XmlProbeAllSources); } void LoadXmlFile(std::string filename, std::string* lines) { us::ModuleResource pointSourceXml = us::GetModuleContext()->GetModule()->GetResource(filename); std::string line; if (pointSourceXml.IsValid() && pointSourceXml.IsFile()) { us::ModuleResourceStream stream(pointSourceXml); stream.std::istream::imbue(std::locale("C")); while (std::getline(stream, line)) { *lines = *lines + line + " "; } } else { MITK_ERROR << "Xml file was not valid"; } } void TestCreatePointSourceProbe() { m_Probe = mitk::pa::Probe::New(m_XmlProbePointSource.c_str(), true); CPPUNIT_ASSERT(true == m_Probe->IsValid()); } void TestCreateCircleSourceProbe() { m_Probe = mitk::pa::Probe::New(m_XmlProbeCircleSource.c_str(), true); CPPUNIT_ASSERT(true == m_Probe->IsValid()); } void TestCreateRectangleSourceProbe() { m_Probe = mitk::pa::Probe::New(m_XmlProbeRectangleSource.c_str(), true); CPPUNIT_ASSERT(true == m_Probe->IsValid()); } void TestCreateTwoPointSourcesProbe() { m_Probe = mitk::pa::Probe::New(m_XmlProbeTwoPointSources.c_str(), true); CPPUNIT_ASSERT(true == m_Probe->IsValid()); } void TestCreateAllSourcesProbe() { m_Probe = mitk::pa::Probe::New(m_XmlProbeAllSources.c_str(), true); CPPUNIT_ASSERT(true == m_Probe->IsValid()); } void TestValuesAreInBoundsUniformRectangle() { int MAXIMUM = 2; int MINIMUM = -2; int ANGLE_MAXIMUM = 1; int ANGLE_MINIMUM = -1; m_LightSource->SetAngleXMode(mitk::pa::LightSource::DistributionMode::UNIFORM); m_LightSource->SetAngleYMode(mitk::pa::LightSource::DistributionMode::UNIFORM); m_LightSource->SetAngleXMaximum(ANGLE_MAXIMUM); m_LightSource->SetAngleXMinimum(ANGLE_MINIMUM); m_LightSource->SetAngleYMaximum(ANGLE_MAXIMUM); m_LightSource->SetAngleYMinimum(ANGLE_MINIMUM); m_LightSource->SetSpawnLocationX(MINIMUM); m_LightSource->SetSpawnLocationXLength(2 * MAXIMUM); m_LightSource->SetSpawnLocationY(MINIMUM); m_LightSource->SetSpawnLocationYLength(2 * MAXIMUM); m_LightSource->SetSpawnLocationZ(MINIMUM); m_LightSource->SetSpawnLocationZLength(2 * MAXIMUM); m_LightSource->SetSpawnLocationRadius(MAXIMUM); m_LightSource->SetVerbose(false); m_LightSource->SetSpawnType(mitk::pa::LightSource::SpawnType::RECTANGLE); std::mt19937 rng; rng.seed(std::chrono::duration_cast(std::chrono::high_resolution_clock:: now().time_since_epoch()).count()); std::uniform_real_distribution<> realDist(0, 1); for (int i = 0, length = 10000; i < length; i++) { auto result = m_LightSource->GetNextPhoton(realDist(rng), realDist(rng), realDist(rng), realDist(rng), realDist(rng), realDist(rng), realDist(rng)); CPPUNIT_ASSERT(result.xAngle >= ANGLE_MINIMUM); CPPUNIT_ASSERT(result.xAngle <= ANGLE_MAXIMUM); CPPUNIT_ASSERT(result.yAngle >= ANGLE_MINIMUM); CPPUNIT_ASSERT(result.yAngle <= ANGLE_MAXIMUM); CPPUNIT_ASSERT(result.zAngle >= 0); CPPUNIT_ASSERT(result.zAngle <= ANGLE_MAXIMUM); CPPUNIT_ASSERT(result.xPosition >= MINIMUM); CPPUNIT_ASSERT(result.xPosition <= MAXIMUM); CPPUNIT_ASSERT(result.yPosition >= MINIMUM); CPPUNIT_ASSERT(result.yPosition <= MAXIMUM); CPPUNIT_ASSERT(result.zPosition >= MINIMUM); CPPUNIT_ASSERT(result.zPosition <= MAXIMUM); } } void TestValuesAreInBoundsGaussianRectangle() { int MAXIMUM = 2; int MINIMUM = -2; int ANGLE_MAXIMUM = 1; int ANGLE_MINIMUM = -1; m_LightSource->SetAngleXMode(mitk::pa::LightSource::DistributionMode::GAUSSIAN); m_LightSource->SetAngleYMode(mitk::pa::LightSource::DistributionMode::GAUSSIAN); m_LightSource->SetAngleXMaximum(ANGLE_MAXIMUM); m_LightSource->SetAngleXMinimum(ANGLE_MINIMUM); m_LightSource->SetAngleYMaximum(ANGLE_MAXIMUM); m_LightSource->SetAngleYMinimum(ANGLE_MINIMUM); m_LightSource->SetSpawnLocationX(MINIMUM); m_LightSource->SetSpawnLocationXLength(2 * MAXIMUM); m_LightSource->SetSpawnLocationY(MINIMUM); m_LightSource->SetSpawnLocationYLength(2 * MAXIMUM); m_LightSource->SetSpawnLocationZ(MINIMUM); m_LightSource->SetSpawnLocationZLength(2 * MAXIMUM); m_LightSource->SetSpawnLocationRadius(MAXIMUM); m_LightSource->SetVerbose(false); m_LightSource->SetSpawnType(mitk::pa::LightSource::SpawnType::RECTANGLE); std::mt19937 rng; rng.seed(std::chrono::duration_cast(std::chrono::high_resolution_clock:: now().time_since_epoch()).count()); std::uniform_real_distribution<> realDist(0, 1); for (int i = 0, length = 10000; i < length; i++) { auto result = m_LightSource->GetNextPhoton(realDist(rng), realDist(rng), realDist(rng), realDist(rng), realDist(rng), realDist(rng), realDist(rng)); CPPUNIT_ASSERT(result.xAngle >= ANGLE_MINIMUM); CPPUNIT_ASSERT(result.xAngle <= ANGLE_MAXIMUM); CPPUNIT_ASSERT(result.yAngle >= ANGLE_MINIMUM); CPPUNIT_ASSERT(result.yAngle <= ANGLE_MAXIMUM); CPPUNIT_ASSERT(result.zAngle >= 0); CPPUNIT_ASSERT(result.zAngle <= ANGLE_MAXIMUM); CPPUNIT_ASSERT(result.xPosition >= MINIMUM); CPPUNIT_ASSERT(result.xPosition <= MAXIMUM); CPPUNIT_ASSERT(result.yPosition >= MINIMUM); CPPUNIT_ASSERT(result.yPosition <= MAXIMUM); CPPUNIT_ASSERT(result.zPosition >= MINIMUM); CPPUNIT_ASSERT(result.zPosition <= MAXIMUM); } } - void tearDown() + void tearDown() override { m_XmlProbePointSource = ""; m_XmlProbeCircleSource = ""; m_XmlProbeRectangleSource = ""; m_XmlProbeTwoPointSources = ""; m_XmlProbeAllSources = ""; m_Probe = nullptr; } }; MITK_TEST_SUITE_REGISTRATION(mitkMcxyzXml) diff --git a/Modules/PhotoacousticsLib/test/mitkPhotoacoustic3dVolumeTest.cpp b/Modules/PhotoacousticsLib/test/mitkPhotoacoustic3dVolumeTest.cpp index f83ad44e06..fb4a1f5a36 100644 --- a/Modules/PhotoacousticsLib/test/mitkPhotoacoustic3dVolumeTest.cpp +++ b/Modules/PhotoacousticsLib/test/mitkPhotoacoustic3dVolumeTest.cpp @@ -1,224 +1,224 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include #include #include "mitkPAVolume.h" #include #include class mitkPhotoacoustic3dVolumeTestSuite : public mitk::TestFixture { CPPUNIT_TEST_SUITE(mitkPhotoacoustic3dVolumeTestSuite); MITK_TEST(TestCorrectGetDataAndSetDataBehavior); MITK_TEST(TestCallingConstructorWithNullParameter); MITK_TEST(TestCallingConstructorWithCorrectParameters); MITK_TEST(TestModifyImage); MITK_TEST(TestModifyComplexImage); MITK_TEST(TestConvertToMitkImage); MITK_TEST(TestDeepCopy); MITK_TEST(TestCatchException); CPPUNIT_TEST_SUITE_END(); private: mitk::pa::Volume::Pointer m_Photoacoustic3dVolume; public: - void setUp() + void setUp() override { } void TestCallingConstructorWithNullParameter() { bool exceptionEncountered = false; try { m_Photoacoustic3dVolume = mitk::pa::Volume::New(nullptr, 3, 3, 3); } catch (...) { exceptionEncountered = true; } CPPUNIT_ASSERT(exceptionEncountered); } void TestCallingConstructorWithCorrectParameters() { double* data = new double[1]; data[0] = 3; m_Photoacoustic3dVolume = mitk::pa::Volume::New(data, 1, 1, 1); CPPUNIT_ASSERT(m_Photoacoustic3dVolume->GetData(0, 0, 0) == 3); CPPUNIT_ASSERT(m_Photoacoustic3dVolume->GetXDim() == 1); CPPUNIT_ASSERT(m_Photoacoustic3dVolume->GetYDim() == 1); CPPUNIT_ASSERT(m_Photoacoustic3dVolume->GetZDim() == 1); } void TestModifyImage() { double* data = new double[1]; data[0] = 3; m_Photoacoustic3dVolume = mitk::pa::Volume::New(data, 1, 1, 1); CPPUNIT_ASSERT_MESSAGE(std::to_string(m_Photoacoustic3dVolume->GetData(0, 0, 0)), m_Photoacoustic3dVolume->GetData(0, 0, 0) == 3); m_Photoacoustic3dVolume->SetData(17, 0, 0, 0); CPPUNIT_ASSERT(m_Photoacoustic3dVolume->GetData(0, 0, 0) == 17); } void TestModifyComplexImage() { unsigned int xDim = 4; unsigned int yDim = 7; unsigned int zDim = 12; unsigned int length = xDim * yDim * zDim; double* data = new double[length]; for (unsigned int i = 0; i < length; i++) data[i] = 5; m_Photoacoustic3dVolume = mitk::pa::Volume::New(data, xDim, yDim, zDim); for (unsigned int z = 0; z < zDim; z++) for (unsigned int y = 0; y < yDim; y++) for (unsigned int x = 0; x < xDim; x++) { CPPUNIT_ASSERT(m_Photoacoustic3dVolume->GetData(x, y, z) == 5); m_Photoacoustic3dVolume->SetData((x + y)*(z + 1), x, y, z); CPPUNIT_ASSERT(abs(m_Photoacoustic3dVolume->GetData(x, y, z) - (x + y)*(z + 1)) < mitk::eps); } } void TestCorrectGetDataAndSetDataBehavior() { unsigned int xDim = 40; unsigned int yDim = 7; unsigned int zDim = 12; unsigned int length = xDim * yDim * zDim; double* data = new double[length]; for (unsigned int i = 0; i < length; i++) data[i] = 0; m_Photoacoustic3dVolume = mitk::pa::Volume::New(data, xDim, yDim, zDim); for (unsigned int z = 0; z < zDim; z++) for (unsigned int y = 0; y < yDim; y++) for (unsigned int x = 0; x < xDim; x++) { int index = z*xDim*yDim + x*yDim + y; m_Photoacoustic3dVolume->SetData(index, x, y, z); CPPUNIT_ASSERT_MESSAGE(std::to_string(index), m_Photoacoustic3dVolume->GetData(x, y, z) == index); } } void TestConvertToMitkImage() { double* data = new double[6]; data[0] = 3; data[1] = 3; data[2] = 3; data[3] = 3; data[4] = 3; data[5] = 3; m_Photoacoustic3dVolume = mitk::pa::Volume::New(data, 1, 2, 3); CPPUNIT_ASSERT(m_Photoacoustic3dVolume->GetData(0, 0, 0) == 3); CPPUNIT_ASSERT(m_Photoacoustic3dVolume->GetData(0, 0, 1) == 3); CPPUNIT_ASSERT(m_Photoacoustic3dVolume->GetData(0, 0, 2) == 3); CPPUNIT_ASSERT(m_Photoacoustic3dVolume->GetData(0, 1, 0) == 3); CPPUNIT_ASSERT(m_Photoacoustic3dVolume->GetData(0, 1, 1) == 3); CPPUNIT_ASSERT(m_Photoacoustic3dVolume->GetData(0, 1, 2) == 3); m_Photoacoustic3dVolume->SetData(17, 0, 0, 0); m_Photoacoustic3dVolume->SetData(17, 0, 1, 0); m_Photoacoustic3dVolume->SetData(17, 0, 1, 2); CPPUNIT_ASSERT(m_Photoacoustic3dVolume->GetData(0, 0, 0) == 17); CPPUNIT_ASSERT(m_Photoacoustic3dVolume->GetData(0, 0, 1) == 3); CPPUNIT_ASSERT(m_Photoacoustic3dVolume->GetData(0, 0, 2) == 3); CPPUNIT_ASSERT(m_Photoacoustic3dVolume->GetData(0, 1, 0) == 17); CPPUNIT_ASSERT(m_Photoacoustic3dVolume->GetData(0, 1, 1) == 3); CPPUNIT_ASSERT(m_Photoacoustic3dVolume->GetData(0, 1, 2) == 17); mitk::Image::Pointer mitkImage = m_Photoacoustic3dVolume->AsMitkImage(); CPPUNIT_ASSERT(mitkImage->GetDimensions()[0] == 2); CPPUNIT_ASSERT(mitkImage->GetDimensions()[1] == 1); CPPUNIT_ASSERT(mitkImage->GetDimensions()[2] == 3); mitk::ImageReadAccessor readAccess(mitkImage, mitkImage->GetVolumeData()); double* copyData = (double*)readAccess.GetData(); CPPUNIT_ASSERT_MESSAGE(std::to_string(copyData[0]), copyData[0] == 17); CPPUNIT_ASSERT_MESSAGE(std::to_string(copyData[1]), copyData[1] == 17); CPPUNIT_ASSERT_MESSAGE(std::to_string(copyData[2]), copyData[2] == 3); CPPUNIT_ASSERT_MESSAGE(std::to_string(copyData[3]), copyData[3] == 3); CPPUNIT_ASSERT_MESSAGE(std::to_string(copyData[4]), copyData[4] == 3); CPPUNIT_ASSERT_MESSAGE(std::to_string(copyData[5]), copyData[5] == 17); } void TestDeepCopy() { double* data = new double[1]; data[0] = 3; m_Photoacoustic3dVolume = mitk::pa::Volume::New(data, 1, 1, 1); mitk::pa::Volume::Pointer copiedVolume = m_Photoacoustic3dVolume->DeepCopy(); CPPUNIT_ASSERT(m_Photoacoustic3dVolume->GetXDim() == copiedVolume->GetXDim()); CPPUNIT_ASSERT(m_Photoacoustic3dVolume->GetYDim() == copiedVolume->GetYDim()); CPPUNIT_ASSERT(m_Photoacoustic3dVolume->GetZDim() == copiedVolume->GetZDim()); CPPUNIT_ASSERT(m_Photoacoustic3dVolume->GetData(0, 0, 0) == 3); CPPUNIT_ASSERT(copiedVolume->GetData(0, 0, 0) == 3); m_Photoacoustic3dVolume->SetData(17, 0, 0, 0); CPPUNIT_ASSERT(m_Photoacoustic3dVolume->GetData(0, 0, 0) == 17); CPPUNIT_ASSERT(copiedVolume->GetData(0, 0, 0) == 3); } void AssertIndexException(unsigned int x, unsigned int y, unsigned int z) { bool exceptionCaught = false; try { double thisIsIrrelevant = m_Photoacoustic3dVolume->GetData(x, y, z); thisIsIrrelevant += 1; } catch (...) { exceptionCaught = true; if (exceptionCaught) exceptionCaught = true; } #ifdef _DEBUG CPPUNIT_ASSERT(exceptionCaught); #endif } void TestCatchException() { double* data = new double[1]; data[0] = 3; m_Photoacoustic3dVolume = mitk::pa::Volume::New(data, 1, 1, 1); AssertIndexException(1, 0, 0); AssertIndexException(0, 1, 0); AssertIndexException(0, 0, 1); AssertIndexException(18, 1, 222); } - void tearDown() + void tearDown() override { m_Photoacoustic3dVolume = nullptr; } }; MITK_TEST_SUITE_REGISTRATION(mitkPhotoacoustic3dVolume) diff --git a/Modules/PhotoacousticsLib/test/mitkPhotoacousticComposedVolumeTest.cpp b/Modules/PhotoacousticsLib/test/mitkPhotoacousticComposedVolumeTest.cpp index 6d954bba08..48a981ad11 100644 --- a/Modules/PhotoacousticsLib/test/mitkPhotoacousticComposedVolumeTest.cpp +++ b/Modules/PhotoacousticsLib/test/mitkPhotoacousticComposedVolumeTest.cpp @@ -1,148 +1,148 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include #include #include "mitkPAComposedVolume.h" #include "mitkIOUtil.h" #include "mitkImageReadAccessor.h" #include class mitkPhotoacousticComposedVolumeTestSuite : public mitk::TestFixture { CPPUNIT_TEST_SUITE(mitkPhotoacousticComposedVolumeTestSuite); MITK_TEST(TestCreateAndDestructComposedVolume); MITK_TEST(TestAccessInvalidFluenceComponent); MITK_TEST(TestAccessInvalidFluenceComponentIndex); MITK_TEST(TestAddMultiplePairs); MITK_TEST(TestSortFunctionality); MITK_TEST(TestAccessInvalidFluenceComponentForYOffset); CPPUNIT_TEST_SUITE_END(); private: mitk::pa::ComposedVolume::Pointer m_ComposedVolume; mitk::pa::TissueGeneratorParameters::Pointer m_DefaultParameters; mitk::pa::InSilicoTissueVolume::Pointer m_InSilicoTissueVolume; public: - void setUp() + void setUp() override { m_DefaultParameters = mitk::pa::TissueGeneratorParameters::New(); m_DefaultParameters->SetXDim(5); m_DefaultParameters->SetYDim(5); m_DefaultParameters->SetZDim(5); m_InSilicoTissueVolume = mitk::pa::InSilicoTissueVolume::New(m_DefaultParameters); m_ComposedVolume = mitk::pa::ComposedVolume::New(m_InSilicoTissueVolume); } mitk::pa::FluenceYOffsetPair::Pointer createFluenceYOffsetPair(double value, double yOffset) { double* data = new double[125]; for (int i = 0; i < 125; ++i) data[i] = value; mitk::pa::Volume::Pointer volume = mitk::pa::Volume::New(data, 5, 5, 5); return mitk::pa::FluenceYOffsetPair::New(volume, yOffset); } void TestCreateAndDestructComposedVolume() { CPPUNIT_ASSERT(m_ComposedVolume->GetNumberOfFluenceComponents() == 0); } void TestAccessInvalidFluenceComponent() { bool caughtException = false; try { m_ComposedVolume->GetFluenceValue(0, 0, 0, 0); } catch (mitk::Exception e) { caughtException = true; } CPPUNIT_ASSERT(caughtException); } void TestAddMultiplePairs() { m_ComposedVolume->AddSlice(createFluenceYOffsetPair(0, 0)); CPPUNIT_ASSERT(m_ComposedVolume->GetNumberOfFluenceComponents() == 1); m_ComposedVolume->AddSlice(createFluenceYOffsetPair(1, 1)); CPPUNIT_ASSERT(m_ComposedVolume->GetNumberOfFluenceComponents() == 2); } void TestSortFunctionality() { m_ComposedVolume->AddSlice(createFluenceYOffsetPair(2, 2)); m_ComposedVolume->AddSlice(createFluenceYOffsetPair(-1, -1)); m_ComposedVolume->AddSlice(createFluenceYOffsetPair(1, 1)); m_ComposedVolume->AddSlice(createFluenceYOffsetPair(0, 0)); m_ComposedVolume->AddSlice(createFluenceYOffsetPair(-2, -2)); CPPUNIT_ASSERT(m_ComposedVolume->GetFluenceValue(0, 0, 2, 0) == 2); CPPUNIT_ASSERT(m_ComposedVolume->GetFluenceValue(1, 0, 2, 0) == -1); CPPUNIT_ASSERT(m_ComposedVolume->GetFluenceValue(2, 0, 2, 0) == 1); CPPUNIT_ASSERT(m_ComposedVolume->GetFluenceValue(3, 0, 2, 0) == 0); CPPUNIT_ASSERT(m_ComposedVolume->GetFluenceValue(4, 0, 2, 0) == -2); m_ComposedVolume->Sort(); CPPUNIT_ASSERT(m_ComposedVolume->GetFluenceValue(0, 0, 2, 0) == -2); CPPUNIT_ASSERT(m_ComposedVolume->GetFluenceValue(1, 0, 2, 0) == -1); CPPUNIT_ASSERT(m_ComposedVolume->GetFluenceValue(2, 0, 2, 0) == 0); CPPUNIT_ASSERT(m_ComposedVolume->GetFluenceValue(3, 0, 2, 0) == 1); CPPUNIT_ASSERT(m_ComposedVolume->GetFluenceValue(4, 0, 2, 0) == 2); } void TestAccessInvalidFluenceComponentIndex() { #ifdef _DEBUG m_ComposedVolume->AddSlice(createFluenceYOffsetPair(0, 0)); bool caughtException = false; try { double unusedValue = m_ComposedVolume->GetFluenceValue(0, 1, 2, 300); unusedValue = 0; } catch (mitk::Exception e) { caughtException = true; } CPPUNIT_ASSERT(caughtException); #endif } void TestAccessInvalidFluenceComponentForYOffset() { bool caughtException = false; try { m_ComposedVolume->GetYOffsetForFluenceComponentInPixels(0); } catch (mitk::Exception e) { caughtException = true; } CPPUNIT_ASSERT(caughtException); } - void tearDown() + void tearDown() override { m_ComposedVolume = nullptr; } }; MITK_TEST_SUITE_REGISTRATION(mitkPhotoacousticComposedVolume) diff --git a/Modules/PhotoacousticsLib/test/mitkPhotoacousticIOTest.cpp b/Modules/PhotoacousticsLib/test/mitkPhotoacousticIOTest.cpp index 37d662697f..893b68f581 100644 --- a/Modules/PhotoacousticsLib/test/mitkPhotoacousticIOTest.cpp +++ b/Modules/PhotoacousticsLib/test/mitkPhotoacousticIOTest.cpp @@ -1,187 +1,187 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include #include #include #include #include #include #include #include #include class mitkPhotoacousticIOTestSuite : public mitk::TestFixture { CPPUNIT_TEST_SUITE(mitkPhotoacousticIOTestSuite); MITK_TEST(testLoadInSilicoTissueNrrdFile); MITK_TEST(testLoad3DVolumeNrrdFile); MITK_TEST(testLoad3DVolumeNrrdFileWithBlur); MITK_TEST(testGetNumberOfNrrdFilesInTestDir); MITK_TEST(testGetChildFoldersFromFolder); MITK_TEST(testLoadFCMs); CPPUNIT_TEST_SUITE_END(); private: const std::string TEST_FOLDER_PATH = "testFiles/"; const std::string TEST_IN_SILICO_VOLUME_PATH = "testInSilicoVolume"; const std::string TEST_3D_Volume_PATH = "test3DVolume"; const std::string TEST_FILE_ENDING = ".nrrd"; const std::string TEST_QUALIFIED_FOLDER_PATH = TEST_FOLDER_PATH + TEST_IN_SILICO_VOLUME_PATH + "/"; const std::string FOLDER_FOLDER = "folder/"; const std::string FCM_PATH = TEST_FOLDER_PATH + "fcms/"; const int NUMBER_OF_NRRD_FILES_IN_TEST_DIR = 2; mitk::pa::TissueGeneratorParameters::Pointer m_VolumeProperties; mitk::pa::InSilicoTissueVolume::Pointer m_TestInSilicoVolume; mitk::pa::Volume::Pointer m_Test3DVolume; public: - void setUp() + void setUp() override { m_VolumeProperties = createTestVolumeParameters(); m_TestInSilicoVolume = mitk::pa::InSilicoTissueVolume::New(m_VolumeProperties); m_Test3DVolume = createTest3DVolume(5); itk::FileTools::CreateDirectory(TEST_FOLDER_PATH); itk::FileTools::CreateDirectory(TEST_QUALIFIED_FOLDER_PATH); itk::FileTools::CreateDirectory(TEST_FOLDER_PATH + FOLDER_FOLDER + FOLDER_FOLDER); itk::FileTools::CreateDirectory(FCM_PATH); CPPUNIT_ASSERT(itksys::SystemTools::FileIsDirectory(TEST_FOLDER_PATH)); CPPUNIT_ASSERT(itksys::SystemTools::FileIsDirectory(TEST_QUALIFIED_FOLDER_PATH)); CPPUNIT_ASSERT(itksys::SystemTools::FileIsDirectory(TEST_FOLDER_PATH + FOLDER_FOLDER + FOLDER_FOLDER)); CPPUNIT_ASSERT(itksys::SystemTools::FileIsDirectory(FCM_PATH)); mitk::IOUtil::Save(m_TestInSilicoVolume->ConvertToMitkImage(), TEST_FOLDER_PATH + TEST_IN_SILICO_VOLUME_PATH + TEST_FILE_ENDING); mitk::IOUtil::Save(m_Test3DVolume->AsMitkImage(), TEST_FOLDER_PATH + TEST_3D_Volume_PATH + TEST_FILE_ENDING); auto yo0 = createTest3DVolume(1)->AsMitkImage(); auto yo1 = createTest3DVolume(2)->AsMitkImage(); yo0->GetPropertyList()->SetStringProperty("y-offset", "0"); yo1->GetPropertyList()->SetStringProperty("y-offset", "1"); mitk::CoreServices::GetPropertyPersistence()->AddInfo(mitk::PropertyPersistenceInfo::New("y-offset")); mitk::IOUtil::Save(yo0, TEST_QUALIFIED_FOLDER_PATH + TEST_IN_SILICO_VOLUME_PATH + "_yo0" + TEST_FILE_ENDING); mitk::IOUtil::Save(yo1, TEST_QUALIFIED_FOLDER_PATH + TEST_IN_SILICO_VOLUME_PATH + "_yo1" + TEST_FILE_ENDING); } mitk::pa::Volume::Pointer createTest3DVolume(double value) { unsigned int xDim = 10; unsigned int yDim = 10; unsigned int zDim = 10; unsigned int length = xDim * yDim * zDim; double* data = new double[length]; for (unsigned int i = 0; i < length; i++) data[i] = value; return mitk::pa::Volume::New(data, xDim, yDim, zDim); } mitk::pa::TissueGeneratorParameters::Pointer createTestVolumeParameters() { auto returnParameters = mitk::pa::TissueGeneratorParameters::New(); returnParameters->SetXDim(10); returnParameters->SetYDim(10); returnParameters->SetZDim(10); returnParameters->SetBackgroundAbsorption(0); returnParameters->SetBackgroundScattering(0); returnParameters->SetBackgroundAnisotropy(0); return returnParameters; } void assertEqual(mitk::pa::Volume::Pointer first, mitk::pa::Volume::Pointer second) { CPPUNIT_ASSERT(first->GetXDim() == second->GetXDim()); CPPUNIT_ASSERT(first->GetYDim() == second->GetYDim()); CPPUNIT_ASSERT(first->GetZDim() == second->GetZDim()); for (unsigned int x = 0; x < first->GetXDim(); ++x) for (unsigned int y = 0; y < first->GetYDim(); ++y) for (unsigned int z = 0; z < first->GetZDim(); ++z) { std::string message = "Expected " + std::to_string(first->GetData(x, y, z)) + " but was " + std::to_string(second->GetData(x, y, z)); CPPUNIT_ASSERT_MESSAGE(message, abs(first->GetData(x, y, z) - second->GetData(x, y, z)) < 1e-6); } } void testLoadInSilicoTissueNrrdFile() { auto loadedVolume = mitk::pa::IOUtil::LoadInSilicoTissueVolumeFromNrrdFile(TEST_FOLDER_PATH + TEST_IN_SILICO_VOLUME_PATH + TEST_FILE_ENDING); CPPUNIT_ASSERT(loadedVolume->GetTDim() == m_TestInSilicoVolume->GetTDim()); assertEqual(m_TestInSilicoVolume->GetAbsorptionVolume(), loadedVolume->GetAbsorptionVolume()); assertEqual(m_TestInSilicoVolume->GetScatteringVolume(), loadedVolume->GetScatteringVolume()); assertEqual(m_TestInSilicoVolume->GetAnisotropyVolume(), loadedVolume->GetAnisotropyVolume()); } void testLoad3DVolumeNrrdFile() { auto loadedVolume = mitk::pa::IOUtil::LoadNrrd(TEST_FOLDER_PATH + TEST_3D_Volume_PATH + TEST_FILE_ENDING); assertEqual(loadedVolume, m_Test3DVolume); } void testLoad3DVolumeNrrdFileWithBlur() { auto loadedVolume = mitk::pa::IOUtil::LoadNrrd(TEST_FOLDER_PATH + TEST_3D_Volume_PATH + TEST_FILE_ENDING, 1); assertEqual(loadedVolume, m_Test3DVolume); } void testGetNumberOfNrrdFilesInTestDir() { int numberOfFiles = mitk::pa::IOUtil::GetNumberOfNrrdFilesInDirectory(TEST_FOLDER_PATH); CPPUNIT_ASSERT(numberOfFiles == NUMBER_OF_NRRD_FILES_IN_TEST_DIR); } void testGetChildFoldersFromFolder() { std::vector childFolders = mitk::pa::IOUtil::GetAllChildfoldersFromFolder(TEST_FOLDER_PATH); CPPUNIT_ASSERT(childFolders.size() == 1); CPPUNIT_ASSERT(childFolders[0] == TEST_FOLDER_PATH); childFolders = mitk::pa::IOUtil::GetAllChildfoldersFromFolder(TEST_FOLDER_PATH + FOLDER_FOLDER); MITK_INFO << "ChildFolders: " << childFolders.size(); CPPUNIT_ASSERT(childFolders.size() == 1); CPPUNIT_ASSERT(childFolders[0] == TEST_FOLDER_PATH + FOLDER_FOLDER + "/folder"); } void testLoadFCMs() { auto fcm1 = createTest3DVolume(1); auto fcm2 = createTest3DVolume(2); auto fcm3 = createTest3DVolume(3); auto fcm4 = createTest3DVolume(4); mitk::IOUtil::Save(fcm1->AsMitkImage(), FCM_PATH + "fcm1_p0,0,0FluenceContributionMap.nrrd"); mitk::IOUtil::Save(fcm2->AsMitkImage(), FCM_PATH + "fcm1_p0,0,1FluenceContributionMap.nrrd"); mitk::IOUtil::Save(fcm3->AsMitkImage(), FCM_PATH + "fcm1_p1,0,0FluenceContributionMap.nrrd"); mitk::IOUtil::Save(fcm4->AsMitkImage(), FCM_PATH + "fcm1_p1,0,1FluenceContributionMap.nrrd"); int prog = 0; auto map = mitk::pa::IOUtil::LoadFluenceContributionMaps(FCM_PATH, 0, &prog); assertEqual(fcm1, map[mitk::pa::IOUtil::Position{ 0,0 }]); assertEqual(fcm2, map[mitk::pa::IOUtil::Position{ 0,1 }]); assertEqual(fcm3, map[mitk::pa::IOUtil::Position{ 1,0 }]); assertEqual(fcm4, map[mitk::pa::IOUtil::Position{ 1,1 }]); } - void tearDown() + void tearDown() override { //CPPUNIT_ASSERT_MESSAGE("Resource leak of test files onto hard drive..", itksys::SystemTools::RemoveADirectory(TEST_FOLDER_PATH) == true); } }; MITK_TEST_SUITE_REGISTRATION(mitkPhotoacousticIO) diff --git a/Modules/PhotoacousticsLib/test/mitkPhotoacousticNoiseGeneratorTest.cpp b/Modules/PhotoacousticsLib/test/mitkPhotoacousticNoiseGeneratorTest.cpp index 4661aabd0f..53c4fe5ba2 100644 --- a/Modules/PhotoacousticsLib/test/mitkPhotoacousticNoiseGeneratorTest.cpp +++ b/Modules/PhotoacousticsLib/test/mitkPhotoacousticNoiseGeneratorTest.cpp @@ -1,71 +1,71 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include #include #include #include "mitkPAVolume.h" #include "mitkPANoiseGenerator.h" class mitkPhotoacousticNoiseGeneratorTestSuite : public mitk::TestFixture { CPPUNIT_TEST_SUITE(mitkPhotoacousticNoiseGeneratorTestSuite); MITK_TEST(testNoiseGenerator); CPPUNIT_TEST_SUITE_END(); private: public: mitk::pa::Volume::Pointer m_Volume; - void setUp() + void setUp() override { } void testNoiseGenerator() { int size = 1000 * 100 * 100; double* volume = new double[size]; for (int i = 0; i < size; i++) { volume[i] = 1; } m_Volume = mitk::pa::Volume::New(volume, 1000, 100, 100); mitk::pa::NoiseGenerator::ApplyNoiseModel(m_Volume, 0.75, 0.1); int negativecounter = 0; for (int i = 0; i < size; i++) { if (m_Volume->GetData()[i] <= 0) { negativecounter++; } } CPPUNIT_ASSERT_EQUAL_MESSAGE("More than one negative: " + std::to_string(negativecounter) + " (" + std::to_string((((double)negativecounter) / size) * 100) + "%)", negativecounter, 0); } - void tearDown() + void tearDown() override { } }; MITK_TEST_SUITE_REGISTRATION(mitkPhotoacousticNoiseGenerator) diff --git a/Modules/PhotoacousticsLib/test/mitkPhotoacousticTissueGeneratorTest.cpp b/Modules/PhotoacousticsLib/test/mitkPhotoacousticTissueGeneratorTest.cpp index 6a1f07d09f..8199cdc0bf 100644 --- a/Modules/PhotoacousticsLib/test/mitkPhotoacousticTissueGeneratorTest.cpp +++ b/Modules/PhotoacousticsLib/test/mitkPhotoacousticTissueGeneratorTest.cpp @@ -1,83 +1,83 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include #include #include "mitkPATissueGenerator.h" class mitkPhotoacousticTissueGeneratorTestSuite : public mitk::TestFixture { CPPUNIT_TEST_SUITE(mitkPhotoacousticTissueGeneratorTestSuite); MITK_TEST(testCallWithEmptyParameters); MITK_TEST(testCallWithWorkingParameters); CPPUNIT_TEST_SUITE_END(); private: public: - void setUp() + void setUp() override { } mitk::pa::TissueGeneratorParameters::Pointer createRandomTestVolumeParameters() { auto returnParameters = mitk::pa::TissueGeneratorParameters::New(); returnParameters->SetXDim(rand() % 50 + 1); returnParameters->SetYDim(rand() % 50 + 1); returnParameters->SetZDim(rand() % 50 + 1); returnParameters->SetBackgroundAbsorption(rand() % 100 / 10.0); returnParameters->SetBackgroundScattering(rand() % 100 / 10.0); returnParameters->SetBackgroundAnisotropy(rand() % 100 / 10.0); int min = rand() % 10; returnParameters->SetMinNumberOfVessels(min); returnParameters->SetMaxNumberOfVessels(min + (rand() % 10)); returnParameters->SetCalculateNewVesselPositionCallback( &mitk::pa::VesselMeanderStrategy::CalculateRandomlyDivergingPosition); returnParameters->SetMinVesselZOrigin(rand() % 3 + 1); returnParameters->SetMaxVesselZOrigin(rand() % 3 + 1); int minRad = rand() % 100; returnParameters->SetMinVesselRadiusInMillimeters(minRad); returnParameters->SetMaxVesselRadiusInMillimeters(minRad + (rand() % 100)); returnParameters->SetVoxelSpacingInCentimeters(1); return returnParameters; } void testCallWithEmptyParameters() { auto parameters = mitk::pa::TissueGeneratorParameters::New(); auto volume = mitk::pa::InSilicoTissueGenerator::GenerateInSilicoData(parameters); CPPUNIT_ASSERT(volume.IsNotNull()); } void testCallWithWorkingParameters() { for (int i = 0; i < 20; i++) { auto parameters = createRandomTestVolumeParameters(); auto volume = mitk::pa::InSilicoTissueGenerator::GenerateInSilicoData(parameters); CPPUNIT_ASSERT(volume.IsNotNull()); } } - void tearDown() + void tearDown() override { } }; MITK_TEST_SUITE_REGISTRATION(mitkPhotoacousticTissueGenerator) diff --git a/Modules/PhotoacousticsLib/test/mitkPhotoacousticVectorTest.cpp b/Modules/PhotoacousticsLib/test/mitkPhotoacousticVectorTest.cpp index 4cbe2b9f1b..68844272af 100644 --- a/Modules/PhotoacousticsLib/test/mitkPhotoacousticVectorTest.cpp +++ b/Modules/PhotoacousticsLib/test/mitkPhotoacousticVectorTest.cpp @@ -1,260 +1,260 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include #include #define _USE_MATH_DEFINES #include #include "mitkPAVector.h" class mitkPhotoacousticVectorTestSuite : public mitk::TestFixture { CPPUNIT_TEST_SUITE(mitkPhotoacousticVectorTestSuite); MITK_TEST(TestNormalizeVector); MITK_TEST(TestRotateVectorZeroDegrees); MITK_TEST(TestRotatedVectorPositiveDegrees); MITK_TEST(TestRotateVectorZeroDegrees); MITK_TEST(TestScaleVector); MITK_TEST(TestCloneVector); CPPUNIT_TEST_SUITE_END(); private: mitk::pa::Vector::Pointer m_TestVector; mitk::pa::Vector::Pointer m_TestReturnVector; const double DIF_VAL = 0.001; const double TWO_PI = 6.283185; public: - void setUp() + void setUp() override { m_TestVector = mitk::pa::Vector::New(); m_TestReturnVector = mitk::pa::Vector::New(); } void TestNormalizeVector() { std::stringstream output; int a = 2; int b = 3; int c = 4; m_TestVector->SetElement(0, a); m_TestVector->SetElement(1, b); m_TestVector->SetElement(2, c); output << "The vectorlength should be"; output << sqrt(a*a + b*b + c*c); CPPUNIT_ASSERT_EQUAL_MESSAGE(output.str(), sqrt(a*a + b*b + c*c), m_TestVector->GetNorm()); output.flush(); m_TestVector->Normalize(); CPPUNIT_ASSERT_EQUAL_MESSAGE("The vectorlength should be 1.", true, m_TestVector->GetNorm() - 1 < DIF_VAL); } void TestRotateVectorZeroDegrees() { int a = 1; int b = 2; int c = 3; double length; m_TestVector->SetElement(0, a); m_TestVector->SetElement(1, b); m_TestVector->SetElement(2, c); length = m_TestVector->GetNorm(); m_TestVector->Rotate(0, 0); CPPUNIT_ASSERT_EQUAL_MESSAGE("The vector length should be equal", length, m_TestVector->GetNorm()); CPPUNIT_ASSERT_MESSAGE("The vector value at index0 should be 1.0", m_TestVector->GetElement(0) - 1 < DIF_VAL); CPPUNIT_ASSERT_MESSAGE("The vector value at index1 should be 2.0", m_TestVector->GetElement(1) - 2 < DIF_VAL); CPPUNIT_ASSERT_MESSAGE("The vector value at index2 should be 3.0", m_TestVector->GetElement(2) - 3 < DIF_VAL); } void TestRotatedVectorPositiveDegrees() { MITK_INFO << atan2(0, 0); for (int r = 0; r < 10; r++) { for (double phi = 0.1; phi < 3; phi += 0.1) { for (double theta = 0.1; theta < 3; theta += 0.1) { double rotateTheta = 0.1; double rotatePhi = 0.1; m_TestVector->SetElement(0, r * sin(theta) * cos(phi)); m_TestVector->SetElement(1, r * sin(theta) * sin(phi)); m_TestVector->SetElement(2, r * cos(theta)); m_TestVector->Rotate(rotateTheta, rotatePhi); double newTheta = fmod(theta + rotateTheta, TWO_PI); double newPhi = fmod(phi + rotatePhi, TWO_PI); double expectedX = r * sin(newTheta) * cos(newPhi); double expectedY = r * sin(newTheta) * sin(newPhi); double expectedZ = r * cos(newTheta); CPPUNIT_ASSERT_MESSAGE("The vector value at index0 should be " + std::to_string(expectedX) + " but was " + std::to_string(m_TestVector->GetElement(0)) + " at r=" + std::to_string(r) + " phi=" + std::to_string(phi) + " theta=" + std::to_string(theta), m_TestVector->GetElement(0) - expectedX < DIF_VAL); CPPUNIT_ASSERT_MESSAGE("The vector value at index1 should be " + std::to_string(expectedY) + " but was " + std::to_string(m_TestVector->GetElement(0)) + " at r=" + std::to_string(r) + " phi=" + std::to_string(phi) + " theta=" + std::to_string(theta), m_TestVector->GetElement(1) - expectedY < DIF_VAL); CPPUNIT_ASSERT_MESSAGE("The vector value at index2 should be " + std::to_string(expectedZ) + " but was " + std::to_string(m_TestVector->GetElement(0)) + " at r=" + std::to_string(r) + " phi=" + std::to_string(phi) + " theta=" + std::to_string(theta), m_TestVector->GetElement(2) - expectedZ < DIF_VAL); } } } } void TestRotatedVectorNegativeDegrees() { for (int r = 0; r < 10; r++) { for (double phi = -0.1; phi > -3; phi -= 0.1) { for (double theta = -0.1; theta > -3; theta -= 0.1) { double rotateTheta = -0.1; double rotatePhi = -0.1; m_TestVector->SetElement(0, r * sin(theta) * cos(phi)); m_TestVector->SetElement(1, r * sin(theta) * sin(phi)); m_TestVector->SetElement(2, r * cos(theta)); m_TestVector->Rotate(rotateTheta, rotatePhi); double newTheta = fmod(theta + rotateTheta, TWO_PI); double newPhi = fmod(phi + rotatePhi, TWO_PI); double expectedX = r * sin(newTheta) * cos(newPhi); double expectedY = r * sin(newTheta) * sin(newPhi); double expectedZ = r * cos(newTheta); CPPUNIT_ASSERT_MESSAGE("The vector value at index0 should be " + std::to_string(expectedX) + " but was " + std::to_string(m_TestVector->GetElement(0)) + " at r=" + std::to_string(r) + " phi=" + std::to_string(phi) + " theta=" + std::to_string(theta), m_TestVector->GetElement(0) - expectedX < DIF_VAL); CPPUNIT_ASSERT_MESSAGE("The vector value at index1 should be " + std::to_string(expectedY) + " but was " + std::to_string(m_TestVector->GetElement(0)) + " at r=" + std::to_string(r) + " phi=" + std::to_string(phi) + " theta=" + std::to_string(theta), m_TestVector->GetElement(1) - expectedY < DIF_VAL); CPPUNIT_ASSERT_MESSAGE("The vector value at index2 should be " + std::to_string(expectedZ) + " but was " + std::to_string(m_TestVector->GetElement(0)) + " at r=" + std::to_string(r) + " phi=" + std::to_string(phi) + " theta=" + std::to_string(theta), m_TestVector->GetElement(2) - expectedZ < DIF_VAL); } } } } void TestScaleVector() { double a = 1.0; double b = 2.0; double c = 3.0; for (double testFactor = -2.0; testFactor <= 2.0; testFactor += 0.3) { double potElement0Fctr; double potElement1Fctr; double potElement2Fctr; std::stringstream output; m_TestVector->SetElement(0, a); m_TestVector->SetElement(1, b); m_TestVector->SetElement(2, c); potElement0Fctr = (m_TestVector->GetElement(0)*testFactor)*(m_TestVector->GetElement(0)*testFactor); potElement1Fctr = (m_TestVector->GetElement(1)*testFactor)*(m_TestVector->GetElement(1)*testFactor); potElement2Fctr = (m_TestVector->GetElement(2)*testFactor)*(m_TestVector->GetElement(2)*testFactor); m_TestVector->Scale(testFactor); CPPUNIT_ASSERT_EQUAL_MESSAGE("The vector length should not be equal", sqrt(potElement0Fctr + potElement1Fctr + potElement2Fctr), m_TestVector->GetNorm()); output << "The vector value at index0 should be"; output << a*testFactor; CPPUNIT_ASSERT_EQUAL_MESSAGE(output.str(), a*testFactor, m_TestVector->GetElement(0)); output.flush(); output << "The vector value at index1 should be"; output << b*testFactor; CPPUNIT_ASSERT_EQUAL_MESSAGE(output.str(), b*testFactor, m_TestVector->GetElement(1)); output.flush(); output << "The vector value at index2 should be"; output << c*testFactor; CPPUNIT_ASSERT_EQUAL_MESSAGE(output.str(), c*testFactor, m_TestVector->GetElement(2)); output.flush(); } } void TestCloneVector() { int a = 1; int b = 2; int c = 3; m_TestVector->SetElement(0, a); m_TestVector->SetElement(1, b); m_TestVector->SetElement(2, c); m_TestReturnVector = m_TestVector->Clone(); CPPUNIT_ASSERT_EQUAL_MESSAGE("The vector length should be equal", (m_TestVector->GetNorm()), m_TestReturnVector->GetNorm()); CPPUNIT_ASSERT_EQUAL_MESSAGE("The vector value at index0 should be equal", m_TestVector->GetElement(0), m_TestReturnVector->GetElement(0)); CPPUNIT_ASSERT_EQUAL_MESSAGE("The vector value at index1 should be equal", m_TestVector->GetElement(1), m_TestReturnVector->GetElement(1)); CPPUNIT_ASSERT_EQUAL_MESSAGE("The vector value at index2 should be equal", m_TestVector->GetElement(2), m_TestReturnVector->GetElement(2)); m_TestReturnVector->Rotate(M_PI / 4, M_PI / 4); CPPUNIT_ASSERT_EQUAL_MESSAGE("The vector value at index0 should be not equal", true, m_TestVector->GetElement(0) != m_TestReturnVector->GetElement(0)); CPPUNIT_ASSERT_EQUAL_MESSAGE("The vector value at index0 should be not equal", true, m_TestVector->GetElement(1) != m_TestReturnVector->GetElement(1)); CPPUNIT_ASSERT_EQUAL_MESSAGE("The vector value at index0 should be not equal", true, m_TestVector->GetElement(2) != m_TestReturnVector->GetElement(2)); for (double testFactor = -2.0; testFactor <= 2.0; testFactor += 0.3) { m_TestReturnVector->Scale(testFactor); CPPUNIT_ASSERT_EQUAL_MESSAGE("The vector value at index0 should be not equal", true, m_TestVector->GetElement(0) != m_TestReturnVector->GetElement(0)); CPPUNIT_ASSERT_EQUAL_MESSAGE("The vector value at index0 should be not equal", true, m_TestVector->GetElement(1) != m_TestReturnVector->GetElement(1)); CPPUNIT_ASSERT_EQUAL_MESSAGE("The vector value at index0 should be not equal", true, m_TestVector->GetElement(2) != m_TestReturnVector->GetElement(2)); } } - void tearDown() + void tearDown() override { m_TestVector = nullptr; m_TestReturnVector = nullptr; } }; MITK_TEST_SUITE_REGISTRATION(mitkPhotoacousticVector) diff --git a/Modules/PhotoacousticsLib/test/mitkPhotoacousticVesselMeanderStrategyTest.cpp b/Modules/PhotoacousticsLib/test/mitkPhotoacousticVesselMeanderStrategyTest.cpp index ee7d551e9b..82c29f332a 100644 --- a/Modules/PhotoacousticsLib/test/mitkPhotoacousticVesselMeanderStrategyTest.cpp +++ b/Modules/PhotoacousticsLib/test/mitkPhotoacousticVesselMeanderStrategyTest.cpp @@ -1,114 +1,114 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include #include #include #include "mitkPAInSilicoTissueVolume.h" #include "mitkPATissueGenerator.h" #include "mitkPAVesselMeanderStrategy.h" class mitkPhotoacousticVesselMeanderStrategyTestSuite : public mitk::TestFixture { CPPUNIT_TEST_SUITE(mitkPhotoacousticVesselMeanderStrategyTestSuite); MITK_TEST(TestCalculateNewPositionInStraightLine); CPPUNIT_TEST_SUITE_END(); private: mitk::pa::VesselMeanderStrategy::Pointer m_TestVector; mitk::pa::Vector::Pointer m_TestPostion; mitk::pa::Vector::Pointer m_TestDirection; public: - void setUp() + void setUp() override { m_TestVector = mitk::pa::VesselMeanderStrategy::New(); m_TestPostion = mitk::pa::Vector::New(); m_TestDirection = mitk::pa::Vector::New(); } void TestCalculateNewPositionInStraightLine() { std::stringstream output; int a = 0; int b = 1; int c = 2; int d = 3; int e = 4; int f = 5; for (int i = -2; i <= 2; i++) { if (i == 0) { i++; } for (int j = -2; j <= 2; j++) { if (j == 0) { j++; } m_TestPostion->SetElement(0, a*i); m_TestPostion->SetElement(1, b*i); m_TestPostion->SetElement(2, c*i); m_TestDirection->SetElement(0, d*j); m_TestDirection->SetElement(1, e*j); m_TestDirection->SetElement(2, f*j); m_TestVector->CalculateNewPositionInStraightLine(m_TestPostion, m_TestDirection, 0, nullptr); MITK_INFO << "m_TestPosition Element(0) =" << m_TestPostion->GetElement(0); MITK_INFO << "Data0 =" << (a*i) + (d*j); MITK_INFO << "m_TestPosition Element(1) =" << m_TestPostion->GetElement(1); MITK_INFO << "Data1 =" << (b*i) + (e*j); MITK_INFO << "m_TestPosition Element(2) =" << m_TestPostion->GetElement(2); MITK_INFO << "Data2 =" << (c*i) + (f*j); output << "Element0 from m_TestPosition should be "; output << a*i + d*j; CPPUNIT_ASSERT_EQUAL_MESSAGE(output.str(), true, a*i + d*j == m_TestPostion->GetElement(0)); output.flush(); output << "Element1 from m_TestPosition should be "; output << b*i + e*j; CPPUNIT_ASSERT_EQUAL_MESSAGE(output.str(), true, b*i + e*j == m_TestPostion->GetElement(1)); output.flush(); output << "Element2 from m_TestPosition should be "; output << c*i + f*j; CPPUNIT_ASSERT_EQUAL_MESSAGE(output.str(), true, c*i + f*j == m_TestPostion->GetElement(2)); output.flush(); } } } - void tearDown() + void tearDown() override { m_TestVector = nullptr; m_TestPostion = nullptr; m_TestDirection = nullptr; } }; MITK_TEST_SUITE_REGISTRATION(mitkPhotoacousticVesselMeanderStrategy) diff --git a/Modules/PhotoacousticsLib/test/mitkPhotoacousticVesselTest.cpp b/Modules/PhotoacousticsLib/test/mitkPhotoacousticVesselTest.cpp index b319b94bb3..7485f03122 100644 --- a/Modules/PhotoacousticsLib/test/mitkPhotoacousticVesselTest.cpp +++ b/Modules/PhotoacousticsLib/test/mitkPhotoacousticVesselTest.cpp @@ -1,169 +1,169 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include #include #include #include "mitkPAInSilicoTissueVolume.h" #include "mitkPAVector.h" #include "mitkPAVessel.h" #include "mitkIOUtil.h" class mitkPhotoacousticVesselTestSuite : public mitk::TestFixture { CPPUNIT_TEST_SUITE(mitkPhotoacousticVesselTestSuite); MITK_TEST(testEmptyInitializationProperties); MITK_TEST(testWalkInStraightLine); MITK_TEST(testBifurcate); CPPUNIT_TEST_SUITE_END(); private: mitk::pa::Vessel::Pointer m_TestVessel; mitk::pa::Vessel::CalculateNewVesselPositionCallback m_StraightLine; mitk::pa::Vessel::CalculateNewVesselPositionCallback m_Diverging; mitk::pa::InSilicoTissueVolume::Pointer m_TestInSilicoVolume; mitk::pa::TissueGeneratorParameters::Pointer m_TestVolumeParameters; public: - void setUp() + void setUp() override { auto params = mitk::pa::VesselProperties::New(); m_TestVessel = mitk::pa::Vessel::New(params); m_StraightLine = &mitk::pa::VesselMeanderStrategy::CalculateNewPositionInStraightLine; m_Diverging = &mitk::pa::VesselMeanderStrategy::CalculateRandomlyDivergingPosition; m_TestVolumeParameters = createTestVolumeParameters(); m_TestInSilicoVolume = mitk::pa::InSilicoTissueVolume::New(m_TestVolumeParameters); } mitk::pa::TissueGeneratorParameters::Pointer createTestVolumeParameters() { auto returnParameters = mitk::pa::TissueGeneratorParameters::New(); returnParameters->SetXDim(10); returnParameters->SetYDim(10); returnParameters->SetZDim(10); returnParameters->SetBackgroundAbsorption(0); returnParameters->SetBackgroundScattering(0); returnParameters->SetBackgroundAnisotropy(0); return returnParameters; } void testEmptyInitializationProperties() { CPPUNIT_ASSERT(m_TestVessel->CanBifurcate() == false); CPPUNIT_ASSERT(m_TestVessel->IsFinished() == true); } void testWalkInStraightLine() { auto testPosition = mitk::pa::Vector::New(); testPosition->SetElement(0, 0); testPosition->SetElement(1, 4); testPosition->SetElement(2, 4); auto testDirection = mitk::pa::Vector::New(); testDirection->SetElement(0, 1); testDirection->SetElement(1, 0); testDirection->SetElement(2, 0); auto params = mitk::pa::VesselProperties::New(); params->SetRadiusInVoxel(1); params->SetBifurcationFrequency(100); params->SetAbsorptionCoefficient(10); params->SetScatteringCoefficient(10); params->SetAnisotopyCoefficient(10); params->SetPositionVector(testPosition); params->SetDirectionVector(testDirection); m_TestVessel = mitk::pa::Vessel::New(params); CPPUNIT_ASSERT(m_TestVessel->CanBifurcate() == false); CPPUNIT_ASSERT(m_TestVessel->IsFinished() == false); CPPUNIT_ASSERT(abs(m_TestInSilicoVolume->GetAbsorptionVolume()->GetData(0, 4, 4)) <= mitk::eps); m_TestVessel->ExpandVessel(m_TestInSilicoVolume, m_StraightLine, 0, nullptr); CPPUNIT_ASSERT(abs(m_TestInSilicoVolume->GetAbsorptionVolume()->GetData(0, 4, 4) - 10) <= mitk::eps); CPPUNIT_ASSERT(abs(m_TestInSilicoVolume->GetAbsorptionVolume()->GetData(0, 5, 4) - 10) <= mitk::eps); CPPUNIT_ASSERT(abs(m_TestInSilicoVolume->GetAbsorptionVolume()->GetData(0, 6, 4)) <= mitk::eps); CPPUNIT_ASSERT(abs(m_TestInSilicoVolume->GetAbsorptionVolume()->GetData(0, 4, 4) - 10) <= mitk::eps); CPPUNIT_ASSERT(abs(m_TestInSilicoVolume->GetAbsorptionVolume()->GetData(0, 4, 5) - 10) <= mitk::eps); CPPUNIT_ASSERT(abs(m_TestInSilicoVolume->GetAbsorptionVolume()->GetData(0, 4, 6)) <= mitk::eps); CPPUNIT_ASSERT(abs(m_TestInSilicoVolume->GetAbsorptionVolume()->GetData(0, 4, 4) - 10) <= mitk::eps); CPPUNIT_ASSERT(abs(m_TestInSilicoVolume->GetAbsorptionVolume()->GetData(1, 4, 4) - 10) <= mitk::eps); CPPUNIT_ASSERT(abs(m_TestInSilicoVolume->GetAbsorptionVolume()->GetData(2, 4, 4)) <= mitk::eps); m_TestVessel->ExpandVessel(m_TestInSilicoVolume, m_StraightLine, 0, nullptr); CPPUNIT_ASSERT(abs(m_TestInSilicoVolume->GetAbsorptionVolume()->GetData(1, 4, 4) - 10) <= mitk::eps); CPPUNIT_ASSERT(abs(m_TestInSilicoVolume->GetAbsorptionVolume()->GetData(1, 5, 4) - 10) <= mitk::eps); CPPUNIT_ASSERT(abs(m_TestInSilicoVolume->GetAbsorptionVolume()->GetData(1, 6, 4)) <= mitk::eps); CPPUNIT_ASSERT(abs(m_TestInSilicoVolume->GetAbsorptionVolume()->GetData(1, 4, 4) - 10) <= mitk::eps); CPPUNIT_ASSERT(abs(m_TestInSilicoVolume->GetAbsorptionVolume()->GetData(1, 4, 5) - 10) <= mitk::eps); CPPUNIT_ASSERT(abs(m_TestInSilicoVolume->GetAbsorptionVolume()->GetData(1, 4, 6)) <= mitk::eps); CPPUNIT_ASSERT(abs(m_TestInSilicoVolume->GetAbsorptionVolume()->GetData(1, 4, 4) - 10) <= mitk::eps); CPPUNIT_ASSERT(abs(m_TestInSilicoVolume->GetAbsorptionVolume()->GetData(2, 4, 4) - 10) <= mitk::eps); CPPUNIT_ASSERT(abs(m_TestInSilicoVolume->GetAbsorptionVolume()->GetData(3, 4, 4)) <= mitk::eps); } void testBifurcate() { auto testPosition = mitk::pa::Vector::New(); testPosition->SetElement(0, 0); testPosition->SetElement(1, 4); testPosition->SetElement(2, 4); auto testDirection = mitk::pa::Vector::New(); testDirection->SetElement(0, 1); testDirection->SetElement(1, 0); testDirection->SetElement(2, 0); auto params = mitk::pa::VesselProperties::New(); params->SetRadiusInVoxel(1); params->SetBifurcationFrequency(1); params->SetAbsorptionCoefficient(10); params->SetScatteringCoefficient(10); params->SetAnisotopyCoefficient(10); params->SetPositionVector(testPosition); params->SetDirectionVector(testDirection); m_TestVessel = mitk::pa::Vessel::New(params); CPPUNIT_ASSERT(m_TestVessel->CanBifurcate() == false); CPPUNIT_ASSERT(m_TestVessel->IsFinished() == false); CPPUNIT_ASSERT(abs(m_TestInSilicoVolume->GetAbsorptionVolume()->GetData(0, 4, 4)) <= mitk::eps); m_TestVessel->ExpandVessel(m_TestInSilicoVolume, m_StraightLine, 0, nullptr); m_TestVessel->ExpandVessel(m_TestInSilicoVolume, m_StraightLine, 0, nullptr); CPPUNIT_ASSERT(m_TestVessel->CanBifurcate() == true); std::mt19937 rng; auto bifurcationVessel = m_TestVessel->Bifurcate(&rng); CPPUNIT_ASSERT(m_TestVessel->CanBifurcate() == false); CPPUNIT_ASSERT(bifurcationVessel->CanBifurcate() == false); } - void tearDown() + void tearDown() override { } }; MITK_TEST_SUITE_REGISTRATION(mitkPhotoacousticVessel) diff --git a/Modules/PhotoacousticsLib/test/mitkPhotoacousticVesselTreeTest.cpp b/Modules/PhotoacousticsLib/test/mitkPhotoacousticVesselTreeTest.cpp index 96884e36b7..a78d6a7bb9 100644 --- a/Modules/PhotoacousticsLib/test/mitkPhotoacousticVesselTreeTest.cpp +++ b/Modules/PhotoacousticsLib/test/mitkPhotoacousticVesselTreeTest.cpp @@ -1,106 +1,106 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include #include #include #include "mitkPAVesselTree.h" #include "mitkPAInSilicoTissueVolume.h" using namespace mitk::pa; class mitkPhotoacousticVesselTreeTestSuite : public mitk::TestFixture { CPPUNIT_TEST_SUITE(mitkPhotoacousticVesselTreeTestSuite); MITK_TEST(testVesselTreeInitialBehavior); MITK_TEST(testCallStepMethod); CPPUNIT_TEST_SUITE_END(); private: public: VesselTree::Pointer m_Tree; VesselProperties::Pointer m_VesselProperties; Vessel::CalculateNewVesselPositionCallback m_StraightLine; InSilicoTissueVolume::Pointer m_TestInSilicoVolume; - void setUp() + void setUp() override { m_VesselProperties = VesselProperties::New(); m_Tree = VesselTree::New(m_VesselProperties); m_StraightLine = &VesselMeanderStrategy::CalculateNewPositionInStraightLine; m_TestInSilicoVolume = InSilicoTissueVolume::New(createTestVolumeParameters()); } TissueGeneratorParameters::Pointer createTestVolumeParameters() { auto returnParameters = TissueGeneratorParameters::New(); returnParameters->SetXDim(10); returnParameters->SetYDim(10); returnParameters->SetZDim(10); returnParameters->SetBackgroundAbsorption(0); returnParameters->SetBackgroundScattering(0); returnParameters->SetBackgroundAnisotropy(0); return returnParameters; } void testVesselTreeInitialBehavior() { CPPUNIT_ASSERT(m_Tree->IsFinished() == true); } void testCallStepMethod() { //really bad test atm.. The only thing that is tested is that the method can be called without a crash. //But hey - it is something :P m_VesselProperties->SetRadiusInVoxel(2); std::mt19937 rng; rng.seed(1); m_Tree = VesselTree::New(m_VesselProperties); m_Tree->Step(m_TestInSilicoVolume, m_StraightLine, 0, &rng); rng.seed(1); auto secondTree = VesselTree::New(m_VesselProperties); secondTree->Step(m_TestInSilicoVolume, m_StraightLine, 0, &rng); CPPUNIT_ASSERT(Equal(m_Tree, secondTree, 1e-6, true)); secondTree->Step(m_TestInSilicoVolume, m_StraightLine, 0, &rng); CPPUNIT_ASSERT(!Equal(m_Tree, secondTree, 1e-6, true)); int i = 0; for (; i < 1000; i++) { secondTree->Step(m_TestInSilicoVolume, m_StraightLine, 0, &rng); if (secondTree->IsFinished()) break; } CPPUNIT_ASSERT(i < 999); } - void tearDown() + void tearDown() override { } }; MITK_TEST_SUITE_REGISTRATION(mitkPhotoacousticVesselTree) diff --git a/Modules/PhotoacousticsLib/test/mitkPhotoacousticVolumeTest.cpp b/Modules/PhotoacousticsLib/test/mitkPhotoacousticVolumeTest.cpp index be8b31aa35..5383b4a461 100644 --- a/Modules/PhotoacousticsLib/test/mitkPhotoacousticVolumeTest.cpp +++ b/Modules/PhotoacousticsLib/test/mitkPhotoacousticVolumeTest.cpp @@ -1,347 +1,347 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include #include #include #include "mitkPAInSilicoTissueVolume.h" #include "mitkPATissueGeneratorParameters.h" class mitkPhotoacousticVolumeTestSuite : public mitk::TestFixture { CPPUNIT_TEST_SUITE(mitkPhotoacousticVolumeTestSuite); MITK_TEST(TestInitializedTissueContainsOnlyZeros); MITK_TEST(TestConvertedMitkImageContainsOnlyZerosOrAir); MITK_TEST(TestTissueVolumeContainsCorrectAbsorptionNumber); MITK_TEST(TestTissueVolumeContainsCorrectScatteringNumber); MITK_TEST(TestTissueVolumeContainsCorrectAnisotropyNumber); MITK_TEST(testSecondConstructor); MITK_TEST(testCompleteAirVoxelInclusion); MITK_TEST(testHalfAirVoxelInclusion); MITK_TEST(testCompleteAirAndSkinVoxelInclusion); MITK_TEST(testRandomizeCoefficients); CPPUNIT_TEST_SUITE_END(); private: mitk::pa::InSilicoTissueVolume::Pointer m_PhotoacousticVolume; mitk::pa::TissueGeneratorParameters::Pointer m_TissueGeneratorParameters; public: - void setUp() + void setUp() override { m_TissueGeneratorParameters = mitk::pa::TissueGeneratorParameters::New(); m_PhotoacousticVolume = mitk::pa::InSilicoTissueVolume::New(m_TissueGeneratorParameters); } void TestInitializedTissueContainsOnlyZeros() { int dims = 30; m_TissueGeneratorParameters->SetXDim(dims); m_TissueGeneratorParameters->SetYDim(dims); m_TissueGeneratorParameters->SetZDim(dims); m_TissueGeneratorParameters->SetAirThicknessInMillimeters(0); m_TissueGeneratorParameters->SetBackgroundAbsorption(0); m_PhotoacousticVolume = mitk::pa::InSilicoTissueVolume::New(m_TissueGeneratorParameters); for (int x = 0; x < dims; x++) { for (int y = 0; y < dims; y++) { for (int z = 0; z < dims; z++) { CPPUNIT_ASSERT_EQUAL_MESSAGE("Every field should be initialized with 0.", abs(m_PhotoacousticVolume->GetAbsorptionVolume()->GetData(x, y, z)) < mitk::eps, true); } } } } void TestConvertedMitkImageContainsOnlyZerosOrAir() { int dims = 30; m_TissueGeneratorParameters->SetXDim(dims); m_TissueGeneratorParameters->SetYDim(dims); m_TissueGeneratorParameters->SetZDim(dims); m_PhotoacousticVolume = mitk::pa::InSilicoTissueVolume::New(m_TissueGeneratorParameters); mitk::Image::Pointer testImage = m_PhotoacousticVolume->ConvertToMitkImage(); mitk::ImageReadAccessor imgMemAcc(testImage); double* imagePointer = (double*)imgMemAcc.GetData(); for (int index = 0; index < dims*dims*dims; index++, imagePointer++) { CPPUNIT_ASSERT_EQUAL_MESSAGE("Every voxel in image should be 0.1 or 0.0001.", true, abs(*imagePointer - 0.1) <= mitk::eps || abs(*imagePointer - 0.0001) <= mitk::eps); } } void TestTissueVolumeContainsCorrectAbsorptionNumber() { int dims = 2; m_TissueGeneratorParameters->SetXDim(dims); m_TissueGeneratorParameters->SetYDim(dims); m_TissueGeneratorParameters->SetZDim(dims); m_PhotoacousticVolume = mitk::pa::InSilicoTissueVolume::New(m_TissueGeneratorParameters); m_PhotoacousticVolume->SetVolumeValues(0, 0, 0, 0, 0, 0); m_PhotoacousticVolume->SetVolumeValues(0, 0, 1, 1, 0, 0); m_PhotoacousticVolume->SetVolumeValues(0, 1, 0, 2, 0, 0); m_PhotoacousticVolume->SetVolumeValues(0, 1, 1, 3, 0, 0); m_PhotoacousticVolume->SetVolumeValues(1, 0, 0, 4, 0, 0); m_PhotoacousticVolume->SetVolumeValues(1, 0, 1, 5, 0, 0); m_PhotoacousticVolume->SetVolumeValues(1, 1, 0, 6, 0, 0); m_PhotoacousticVolume->SetVolumeValues(1, 1, 1, 7, 0, 0); CPPUNIT_ASSERT_EQUAL_MESSAGE("Should be correct value", 0.0, m_PhotoacousticVolume->GetAbsorptionVolume()->GetData(0, 0, 0)); CPPUNIT_ASSERT_EQUAL_MESSAGE("Should be correct value", 1.0, m_PhotoacousticVolume->GetAbsorptionVolume()->GetData(0, 0, 1)); CPPUNIT_ASSERT_EQUAL_MESSAGE("Should be correct value", 2.0, m_PhotoacousticVolume->GetAbsorptionVolume()->GetData(0, 1, 0)); CPPUNIT_ASSERT_EQUAL_MESSAGE("Should be correct value", 3.0, m_PhotoacousticVolume->GetAbsorptionVolume()->GetData(0, 1, 1)); CPPUNIT_ASSERT_EQUAL_MESSAGE("Should be correct value", 4.0, m_PhotoacousticVolume->GetAbsorptionVolume()->GetData(1, 0, 0)); CPPUNIT_ASSERT_EQUAL_MESSAGE("Should be correct value", 5.0, m_PhotoacousticVolume->GetAbsorptionVolume()->GetData(1, 0, 1)); CPPUNIT_ASSERT_EQUAL_MESSAGE("Should be correct value", 6.0, m_PhotoacousticVolume->GetAbsorptionVolume()->GetData(1, 1, 0)); CPPUNIT_ASSERT_EQUAL_MESSAGE("Should be correct value", 7.0, m_PhotoacousticVolume->GetAbsorptionVolume()->GetData(1, 1, 1)); } void TestTissueVolumeContainsCorrectScatteringNumber() { int dims = 2; m_TissueGeneratorParameters->SetXDim(dims); m_TissueGeneratorParameters->SetYDim(dims); m_TissueGeneratorParameters->SetZDim(dims); m_PhotoacousticVolume = mitk::pa::InSilicoTissueVolume::New(m_TissueGeneratorParameters); m_PhotoacousticVolume->SetVolumeValues(0, 0, 0, 0, 0, 0); m_PhotoacousticVolume->SetVolumeValues(0, 0, 1, 0, 1, 0); m_PhotoacousticVolume->SetVolumeValues(0, 1, 0, 0, 2, 0); m_PhotoacousticVolume->SetVolumeValues(0, 1, 1, 0, 3, 0); m_PhotoacousticVolume->SetVolumeValues(1, 0, 0, 0, 4, 0); m_PhotoacousticVolume->SetVolumeValues(1, 0, 1, 0, 5, 0); m_PhotoacousticVolume->SetVolumeValues(1, 1, 0, 0, 6, 0); m_PhotoacousticVolume->SetVolumeValues(1, 1, 1, 0, 7, 0); CPPUNIT_ASSERT_EQUAL_MESSAGE("Should be correct value", 0.0, m_PhotoacousticVolume->GetScatteringVolume()->GetData(0, 0, 0)); CPPUNIT_ASSERT_EQUAL_MESSAGE("Should be correct value", 1.0, m_PhotoacousticVolume->GetScatteringVolume()->GetData(0, 0, 1)); CPPUNIT_ASSERT_EQUAL_MESSAGE("Should be correct value", 2.0, m_PhotoacousticVolume->GetScatteringVolume()->GetData(0, 1, 0)); CPPUNIT_ASSERT_EQUAL_MESSAGE("Should be correct value", 3.0, m_PhotoacousticVolume->GetScatteringVolume()->GetData(0, 1, 1)); CPPUNIT_ASSERT_EQUAL_MESSAGE("Should be correct value", 4.0, m_PhotoacousticVolume->GetScatteringVolume()->GetData(1, 0, 0)); CPPUNIT_ASSERT_EQUAL_MESSAGE("Should be correct value", 5.0, m_PhotoacousticVolume->GetScatteringVolume()->GetData(1, 0, 1)); CPPUNIT_ASSERT_EQUAL_MESSAGE("Should be correct value", 6.0, m_PhotoacousticVolume->GetScatteringVolume()->GetData(1, 1, 0)); CPPUNIT_ASSERT_EQUAL_MESSAGE("Should be correct value", 7.0, m_PhotoacousticVolume->GetScatteringVolume()->GetData(1, 1, 1)); } void TestTissueVolumeContainsCorrectAnisotropyNumber() { int dims = 2; m_TissueGeneratorParameters->SetXDim(dims); m_TissueGeneratorParameters->SetYDim(dims); m_TissueGeneratorParameters->SetZDim(dims); m_PhotoacousticVolume = mitk::pa::InSilicoTissueVolume::New(m_TissueGeneratorParameters); m_PhotoacousticVolume->SetVolumeValues(0, 0, 0, 0, 0, 0); m_PhotoacousticVolume->SetVolumeValues(0, 0, 1, 0, 0, 1); m_PhotoacousticVolume->SetVolumeValues(0, 1, 0, 0, 0, 2); m_PhotoacousticVolume->SetVolumeValues(0, 1, 1, 0, 0, 3); m_PhotoacousticVolume->SetVolumeValues(1, 0, 0, 0, 0, 4); m_PhotoacousticVolume->SetVolumeValues(1, 0, 1, 0, 0, 5); m_PhotoacousticVolume->SetVolumeValues(1, 1, 0, 0, 0, 6); m_PhotoacousticVolume->SetVolumeValues(1, 1, 1, 0, 0, 7); CPPUNIT_ASSERT_EQUAL_MESSAGE("Should be correct value", 0.0, m_PhotoacousticVolume->GetAnisotropyVolume()->GetData(0, 0, 0)); CPPUNIT_ASSERT_EQUAL_MESSAGE("Should be correct value", 1.0, m_PhotoacousticVolume->GetAnisotropyVolume()->GetData(0, 0, 1)); CPPUNIT_ASSERT_EQUAL_MESSAGE("Should be correct value", 2.0, m_PhotoacousticVolume->GetAnisotropyVolume()->GetData(0, 1, 0)); CPPUNIT_ASSERT_EQUAL_MESSAGE("Should be correct value", 3.0, m_PhotoacousticVolume->GetAnisotropyVolume()->GetData(0, 1, 1)); CPPUNIT_ASSERT_EQUAL_MESSAGE("Should be correct value", 4.0, m_PhotoacousticVolume->GetAnisotropyVolume()->GetData(1, 0, 0)); CPPUNIT_ASSERT_EQUAL_MESSAGE("Should be correct value", 5.0, m_PhotoacousticVolume->GetAnisotropyVolume()->GetData(1, 0, 1)); CPPUNIT_ASSERT_EQUAL_MESSAGE("Should be correct value", 6.0, m_PhotoacousticVolume->GetAnisotropyVolume()->GetData(1, 1, 0)); CPPUNIT_ASSERT_EQUAL_MESSAGE("Should be correct value", 7.0, m_PhotoacousticVolume->GetAnisotropyVolume()->GetData(1, 1, 1)); } mitk::pa::Volume::Pointer createTestVolume(double value) { double* data = new double[27]; for (int i = 0; i < 27; ++i) data[i] = value; return mitk::pa::Volume::New(data, 3, 3, 3); } void assertEqual(mitk::pa::Volume::Pointer first, mitk::pa::Volume::Pointer second) { CPPUNIT_ASSERT(first->GetXDim() == second->GetXDim()); CPPUNIT_ASSERT(first->GetYDim() == second->GetYDim()); CPPUNIT_ASSERT(first->GetZDim() == second->GetZDim()); for (unsigned int x = 0; x < first->GetXDim(); ++x) for (unsigned int y = 0; y < first->GetYDim(); ++y) for (unsigned int z = 0; z < first->GetZDim(); ++z) CPPUNIT_ASSERT(abs(first->GetData(x, y, z) - second->GetData(x, y, z)) < mitk::eps); } void testSecondConstructor() { mitk::pa::Volume::Pointer absorption = createTestVolume(1); mitk::pa::Volume::Pointer scattering = createTestVolume(2); mitk::pa::Volume::Pointer anisotropy = createTestVolume(3); mitk::pa::Volume::Pointer segmentation = createTestVolume(4); mitk::PropertyList::Pointer properties = mitk::PropertyList::New(); m_PhotoacousticVolume = mitk::pa::InSilicoTissueVolume::New(absorption, scattering, anisotropy, segmentation, m_TissueGeneratorParameters, properties); assertEqual(m_PhotoacousticVolume->GetAbsorptionVolume(), absorption); assertEqual(m_PhotoacousticVolume->GetScatteringVolume(), scattering); assertEqual(m_PhotoacousticVolume->GetAnisotropyVolume(), anisotropy); assertEqual(m_PhotoacousticVolume->GetSegmentationVolume(), segmentation); } void testCompleteAirVoxelInclusion() { mitk::pa::Volume::Pointer absorption = createTestVolume(1); mitk::pa::Volume::Pointer scattering = createTestVolume(2); mitk::pa::Volume::Pointer anisotropy = createTestVolume(3); mitk::pa::Volume::Pointer segmentation = createTestVolume(4); mitk::PropertyList::Pointer properties = mitk::PropertyList::New(); m_TissueGeneratorParameters->SetXDim(3); m_TissueGeneratorParameters->SetYDim(3); m_TissueGeneratorParameters->SetZDim(3); m_TissueGeneratorParameters->SetAirThicknessInMillimeters(10); m_TissueGeneratorParameters->SetSkinThicknessInMillimeters(0); m_TissueGeneratorParameters->SetAirAbsorption(2); m_TissueGeneratorParameters->SetAirScattering(4); m_TissueGeneratorParameters->SetAirAnisotropy(6); m_PhotoacousticVolume = mitk::pa::InSilicoTissueVolume::New(absorption, scattering, anisotropy, segmentation, m_TissueGeneratorParameters, properties); m_PhotoacousticVolume->FinalizeVolume(); CPPUNIT_ASSERT(abs(m_PhotoacousticVolume->GetAbsorptionVolume()->GetData(0, 0, 0) - 2) < mitk::eps); CPPUNIT_ASSERT(abs(m_PhotoacousticVolume->GetAbsorptionVolume()->GetData(1, 1, 1) - 1) < mitk::eps); CPPUNIT_ASSERT(abs(m_PhotoacousticVolume->GetAbsorptionVolume()->GetData(1, 1, 2) - 1) < mitk::eps); CPPUNIT_ASSERT(abs(m_PhotoacousticVolume->GetScatteringVolume()->GetData(0, 0, 0) - 4) < mitk::eps); CPPUNIT_ASSERT(abs(m_PhotoacousticVolume->GetScatteringVolume()->GetData(1, 1, 1) - 2) < mitk::eps); CPPUNIT_ASSERT(abs(m_PhotoacousticVolume->GetScatteringVolume()->GetData(1, 1, 2) - 2) < mitk::eps); CPPUNIT_ASSERT(abs(m_PhotoacousticVolume->GetAnisotropyVolume()->GetData(0, 0, 0) - 6) < mitk::eps); CPPUNIT_ASSERT(abs(m_PhotoacousticVolume->GetAnisotropyVolume()->GetData(1, 1, 1) - 3) < mitk::eps); CPPUNIT_ASSERT(abs(m_PhotoacousticVolume->GetAnisotropyVolume()->GetData(1, 1, 2) - 3) < mitk::eps); } void testRandomizeCoefficients() { mitk::pa::Volume::Pointer absorption = createTestVolume(1); mitk::pa::Volume::Pointer scattering = createTestVolume(1); mitk::pa::Volume::Pointer anisotropy = createTestVolume(1); mitk::pa::Volume::Pointer segmentation = createTestVolume(4); mitk::PropertyList::Pointer properties = mitk::PropertyList::New(); m_TissueGeneratorParameters->SetXDim(3); m_TissueGeneratorParameters->SetYDim(3); m_TissueGeneratorParameters->SetZDim(3); m_TissueGeneratorParameters->SetRandomizePhysicalProperties(true); m_TissueGeneratorParameters->SetRandomizePhysicalPropertiesPercentage(1); m_TissueGeneratorParameters->SetRngSeed(17); m_TissueGeneratorParameters->SetUseRngSeed(true); m_PhotoacousticVolume = mitk::pa::InSilicoTissueVolume::New(absorption, scattering, anisotropy, segmentation, m_TissueGeneratorParameters, properties); m_PhotoacousticVolume->FinalizeVolume(); CPPUNIT_ASSERT(abs(m_PhotoacousticVolume->GetAbsorptionVolume()->GetData(0, 0, 0) - 1) < 0.1); CPPUNIT_ASSERT(abs(m_PhotoacousticVolume->GetAbsorptionVolume()->GetData(1, 1, 1) - 1) < 0.1); CPPUNIT_ASSERT(abs(m_PhotoacousticVolume->GetAbsorptionVolume()->GetData(1, 1, 2) - 1) < 0.1); CPPUNIT_ASSERT(abs(m_PhotoacousticVolume->GetScatteringVolume()->GetData(0, 0, 0) - 1) < 0.1); CPPUNIT_ASSERT(abs(m_PhotoacousticVolume->GetScatteringVolume()->GetData(1, 1, 1) - 1) < 0.1); CPPUNIT_ASSERT(abs(m_PhotoacousticVolume->GetScatteringVolume()->GetData(1, 1, 2) - 1) < 0.1); CPPUNIT_ASSERT(abs(m_PhotoacousticVolume->GetAnisotropyVolume()->GetData(0, 0, 0) - 1) < 0.1); CPPUNIT_ASSERT(abs(m_PhotoacousticVolume->GetAnisotropyVolume()->GetData(1, 1, 1) - 1) < 0.1); CPPUNIT_ASSERT(abs(m_PhotoacousticVolume->GetAnisotropyVolume()->GetData(1, 1, 2) - 1) < 0.1); } void testCompleteAirAndSkinVoxelInclusion() { mitk::pa::Volume::Pointer absorption = createTestVolume(1); mitk::pa::Volume::Pointer scattering = createTestVolume(2); mitk::pa::Volume::Pointer anisotropy = createTestVolume(3); mitk::pa::Volume::Pointer segmentation = createTestVolume(4); mitk::PropertyList::Pointer properties = mitk::PropertyList::New(); m_TissueGeneratorParameters->SetXDim(3); m_TissueGeneratorParameters->SetYDim(3); m_TissueGeneratorParameters->SetZDim(3); m_TissueGeneratorParameters->SetAirThicknessInMillimeters(10); m_TissueGeneratorParameters->SetSkinThicknessInMillimeters(10); m_TissueGeneratorParameters->SetAirAbsorption(2); m_TissueGeneratorParameters->SetAirScattering(4); m_TissueGeneratorParameters->SetAirAnisotropy(6); m_TissueGeneratorParameters->SetSkinAbsorption(4); m_TissueGeneratorParameters->SetSkinScattering(8); m_TissueGeneratorParameters->SetSkinAnisotropy(12); m_PhotoacousticVolume = mitk::pa::InSilicoTissueVolume::New(absorption, scattering, anisotropy, segmentation, m_TissueGeneratorParameters, properties); m_PhotoacousticVolume->FinalizeVolume(); CPPUNIT_ASSERT(abs(m_PhotoacousticVolume->GetAbsorptionVolume()->GetData(0, 0, 0) - 2) < mitk::eps); CPPUNIT_ASSERT(abs(m_PhotoacousticVolume->GetAbsorptionVolume()->GetData(1, 1, 1) - 4) < mitk::eps); CPPUNIT_ASSERT(abs(m_PhotoacousticVolume->GetAbsorptionVolume()->GetData(1, 1, 2) - 1) < mitk::eps); CPPUNIT_ASSERT(abs(m_PhotoacousticVolume->GetScatteringVolume()->GetData(0, 0, 0) - 4) < mitk::eps); CPPUNIT_ASSERT(abs(m_PhotoacousticVolume->GetScatteringVolume()->GetData(1, 1, 1) - 8) < mitk::eps); CPPUNIT_ASSERT(abs(m_PhotoacousticVolume->GetScatteringVolume()->GetData(1, 1, 2) - 2) < mitk::eps); CPPUNIT_ASSERT(abs(m_PhotoacousticVolume->GetAnisotropyVolume()->GetData(0, 0, 0) - 6) < mitk::eps); CPPUNIT_ASSERT(abs(m_PhotoacousticVolume->GetAnisotropyVolume()->GetData(1, 1, 1) - 12) < mitk::eps); CPPUNIT_ASSERT(abs(m_PhotoacousticVolume->GetAnisotropyVolume()->GetData(1, 1, 2) - 3) < mitk::eps); } void testHalfAirVoxelInclusion() { mitk::pa::Volume::Pointer absorption = createTestVolume(1); mitk::pa::Volume::Pointer scattering = createTestVolume(2); mitk::pa::Volume::Pointer anisotropy = createTestVolume(3); mitk::pa::Volume::Pointer segmentation = createTestVolume(4); mitk::PropertyList::Pointer properties = mitk::PropertyList::New(); m_TissueGeneratorParameters->SetXDim(3); m_TissueGeneratorParameters->SetYDim(3); m_TissueGeneratorParameters->SetZDim(3); m_TissueGeneratorParameters->SetAirThicknessInMillimeters(15); m_TissueGeneratorParameters->SetSkinThicknessInMillimeters(0); m_TissueGeneratorParameters->SetAirAbsorption(2); m_TissueGeneratorParameters->SetAirScattering(4); m_TissueGeneratorParameters->SetAirAnisotropy(6); m_PhotoacousticVolume = mitk::pa::InSilicoTissueVolume::New(absorption, scattering, anisotropy, segmentation, m_TissueGeneratorParameters, properties); m_PhotoacousticVolume->FinalizeVolume(); CPPUNIT_ASSERT(abs(m_PhotoacousticVolume->GetAbsorptionVolume()->GetData(0, 0, 0) - 2) < mitk::eps); CPPUNIT_ASSERT(abs(m_PhotoacousticVolume->GetAbsorptionVolume()->GetData(1, 1, 1) - 1.5) < mitk::eps); CPPUNIT_ASSERT(abs(m_PhotoacousticVolume->GetAbsorptionVolume()->GetData(1, 1, 2) - 1) < mitk::eps); CPPUNIT_ASSERT(abs(m_PhotoacousticVolume->GetScatteringVolume()->GetData(0, 0, 0) - 4) < mitk::eps); CPPUNIT_ASSERT(abs(m_PhotoacousticVolume->GetScatteringVolume()->GetData(1, 1, 1) - 3) < mitk::eps); CPPUNIT_ASSERT(abs(m_PhotoacousticVolume->GetScatteringVolume()->GetData(1, 1, 2) - 2) < mitk::eps); CPPUNIT_ASSERT(abs(m_PhotoacousticVolume->GetAnisotropyVolume()->GetData(0, 0, 0) - 6) < mitk::eps); CPPUNIT_ASSERT(abs(m_PhotoacousticVolume->GetAnisotropyVolume()->GetData(1, 1, 1) - 4.5) < mitk::eps); CPPUNIT_ASSERT(abs(m_PhotoacousticVolume->GetAnisotropyVolume()->GetData(1, 1, 2) - 3) < mitk::eps); } - void tearDown() + void tearDown() override { m_PhotoacousticVolume = nullptr; } }; MITK_TEST_SUITE_REGISTRATION(mitkPhotoacousticVolume) diff --git a/Modules/PhotoacousticsLib/test/mitkPropertyCalculatorTest.cpp b/Modules/PhotoacousticsLib/test/mitkPropertyCalculatorTest.cpp index e2148bb387..3064f6f835 100644 --- a/Modules/PhotoacousticsLib/test/mitkPropertyCalculatorTest.cpp +++ b/Modules/PhotoacousticsLib/test/mitkPropertyCalculatorTest.cpp @@ -1,79 +1,79 @@ ///*=================================================================== //The Medical Imaging Interaction Toolkit (MITK) //Copyright (c) German Cancer Research Center, //Division of Medical and Biological Informatics. //All rights reserved. //This software is distributed WITHOUT ANY WARRANTY; without //even the implied warranty of MERCHANTABILITY or FITNESS FOR //A PARTICULAR PURPOSE. //See LICENSE.txt or http://www.mitk.org for details. //===================================================================*/ #include #include #include class mitkPropertyCalculatorTestSuite : public mitk::TestFixture { CPPUNIT_TEST_SUITE(mitkPropertyCalculatorTestSuite); MITK_TEST(testOutputIsNotEmpty); CPPUNIT_TEST_SUITE_END(); private: mitk::pa::PropertyCalculator::Pointer m_PropertyCalculator; public: - void setUp() + void setUp() override { m_PropertyCalculator = mitk::pa::PropertyCalculator::New(); } void assertProperties(mitk::pa::PropertyCalculator::Properties properties, std::string type, int wavelength, int oxygenation) { CPPUNIT_ASSERT_MESSAGE("anisotropy " + std::to_string(properties.g) + " not bigger than 0 at type " + type + " wv: " + std::to_string(wavelength) + " ox: " + std::to_string(oxygenation), properties.g > 0); CPPUNIT_ASSERT_MESSAGE("absorption " + std::to_string(properties.mua) + " not bigger than 0 at type " + type + " wv: " + std::to_string(wavelength) + " ox: " + std::to_string(oxygenation), properties.mua > 0); CPPUNIT_ASSERT_MESSAGE("scattering " + std::to_string(properties.mus) + " not bigger than 0 at type " + type + " wv: " + std::to_string(wavelength) + " ox: " + std::to_string(oxygenation), properties.mus > 0); } void testOutputIsNotEmpty() { for (double oxygenation = 0; oxygenation <= 1; oxygenation += 0.05) { for (int wavelength = 700; wavelength <= 900; wavelength += 5) { auto properties = m_PropertyCalculator->CalculatePropertyForSpecificWavelength( mitk::pa::PropertyCalculator::TissueType::AIR, wavelength, oxygenation); assertProperties(properties, "AIR", wavelength, oxygenation); properties = m_PropertyCalculator->CalculatePropertyForSpecificWavelength( mitk::pa::PropertyCalculator::TissueType::BLOOD, wavelength, oxygenation); assertProperties(properties, "BLOOD", wavelength, oxygenation); properties = m_PropertyCalculator->CalculatePropertyForSpecificWavelength( mitk::pa::PropertyCalculator::TissueType::EPIDERMIS, wavelength, oxygenation); assertProperties(properties, "EPIDERMIS", wavelength, oxygenation); properties = m_PropertyCalculator->CalculatePropertyForSpecificWavelength( mitk::pa::PropertyCalculator::TissueType::FAT, wavelength, oxygenation); assertProperties(properties, "FAT", wavelength, oxygenation); properties = m_PropertyCalculator->CalculatePropertyForSpecificWavelength( mitk::pa::PropertyCalculator::TissueType::STANDARD_TISSUE, wavelength, oxygenation); assertProperties(properties, "STANDARD_TISSUE", wavelength, oxygenation); } } } - void tearDown() + void tearDown() override { m_PropertyCalculator = nullptr; } }; MITK_TEST_SUITE_REGISTRATION(mitkPropertyCalculator) diff --git a/Modules/PhotoacousticsLib/test/mitkSimulationBatchGeneratorTest.cpp b/Modules/PhotoacousticsLib/test/mitkSimulationBatchGeneratorTest.cpp index 305057568e..04d2995f72 100644 --- a/Modules/PhotoacousticsLib/test/mitkSimulationBatchGeneratorTest.cpp +++ b/Modules/PhotoacousticsLib/test/mitkSimulationBatchGeneratorTest.cpp @@ -1,90 +1,90 @@ ///*=================================================================== //The Medical Imaging Interaction Toolkit (MITK) //Copyright (c) German Cancer Research Center, //Division of Medical and Biological Informatics. //All rights reserved. //This software is distributed WITHOUT ANY WARRANTY; without //even the implied warranty of MERCHANTABILITY or FITNESS FOR //A PARTICULAR PURPOSE. //See LICENSE.txt or http://www.mitk.org for details. //===================================================================*/ #include #include #include #include #include class mitkSimulationBatchGeneratorTestSuite : public mitk::TestFixture { CPPUNIT_TEST_SUITE(mitkSimulationBatchGeneratorTestSuite); MITK_TEST(testGenerateBatchFileString); MITK_TEST(testGenerateBatchFileAndSaveFile); CPPUNIT_TEST_SUITE_END(); private: const std::string TEST_FOLDER_PATH = "testFiles/"; mitk::pa::SimulationBatchGeneratorParameters::Pointer m_Parameters; mitk::pa::Volume::Pointer m_Test3DVolume; public: - void setUp() + void setUp() override { m_Parameters = mitk::pa::SimulationBatchGeneratorParameters::New(); m_Parameters->SetBinaryPath("binary"); m_Parameters->SetNrrdFilePath(TEST_FOLDER_PATH); m_Parameters->SetNumberOfPhotons(100); m_Parameters->SetTissueName("tissueName"); m_Parameters->SetVolumeIndex(0); m_Parameters->SetYOffsetLowerThresholdInCentimeters(-1); m_Parameters->SetYOffsetUpperThresholdInCentimeters(1); m_Parameters->SetYOffsetStepInCentimeters(0.5); m_Test3DVolume = createTest3DVolume(5); itk::FileTools::CreateDirectory(TEST_FOLDER_PATH); CPPUNIT_ASSERT(itksys::SystemTools::FileIsDirectory(TEST_FOLDER_PATH)); } mitk::pa::Volume::Pointer createTest3DVolume(double value) { unsigned int xDim = 10; unsigned int yDim = 10; unsigned int zDim = 10; unsigned int length = xDim * yDim * zDim; double* data = new double[length]; for (unsigned int i = 0; i < length; i++) data[i] = value; return mitk::pa::Volume::New(data, xDim, yDim, zDim); } void testGenerateBatchFileString() { std::string batchGenerationString = mitk::pa::SimulationBatchGenerator::CreateBatchSimulationString(m_Parameters); CPPUNIT_ASSERT(!batchGenerationString.empty()); } void testGenerateBatchFileAndSaveFile() { mitk::pa::SimulationBatchGenerator::WriteBatchFileAndSaveTissueVolume(m_Parameters, m_Test3DVolume->AsMitkImage()); CPPUNIT_ASSERT(itksys::SystemTools::FileExists(TEST_FOLDER_PATH + m_Parameters->GetTissueName() + "000.nrrd")); CPPUNIT_ASSERT(itksys::SystemTools::FileExists(TEST_FOLDER_PATH + "simulate_all.sh") || itksys::SystemTools::FileExists(TEST_FOLDER_PATH + "simulate_all.bat")); CPPUNIT_ASSERT(itksys::SystemTools::FileExists(TEST_FOLDER_PATH + m_Parameters->GetTissueName() + "000") && itksys::SystemTools::FileIsDirectory(TEST_FOLDER_PATH + m_Parameters->GetTissueName() + "000")); } - void tearDown() + void tearDown() override { m_Parameters = nullptr; CPPUNIT_ASSERT_MESSAGE("Resource leak of test files onto hard drive..", itksys::SystemTools::RemoveADirectory(TEST_FOLDER_PATH) == true); } }; MITK_TEST_SUITE_REGISTRATION(mitkSimulationBatchGenerator) diff --git a/Modules/PhotoacousticsLib/test/mitkSlicedVolumeGeneratorTest.cpp b/Modules/PhotoacousticsLib/test/mitkSlicedVolumeGeneratorTest.cpp index 812ce231e8..ba84befbd2 100644 --- a/Modules/PhotoacousticsLib/test/mitkSlicedVolumeGeneratorTest.cpp +++ b/Modules/PhotoacousticsLib/test/mitkSlicedVolumeGeneratorTest.cpp @@ -1,187 +1,187 @@ ///*=================================================================== //The Medical Imaging Interaction Toolkit (MITK) //Copyright (c) German Cancer Research Center, //Division of Medical and Biological Informatics. //All rights reserved. //This software is distributed WITHOUT ANY WARRANTY; without //even the implied warranty of MERCHANTABILITY or FITNESS FOR //A PARTICULAR PURPOSE. //See LICENSE.txt or http://www.mitk.org for details. //===================================================================*/ #include #include #include class mitkSlicedVolumeGeneratorTestSuite : public mitk::TestFixture { CPPUNIT_TEST_SUITE(mitkSlicedVolumeGeneratorTestSuite); MITK_TEST(testConstructorDestructor); MITK_TEST(testGetSlicedFluenceVolume); MITK_TEST(testGetSlicedFluenceVolumeInverse); MITK_TEST(testGetSlicedFluenceVolumeWithPrecorrection); MITK_TEST(testGetSlicedFluenceVolumeWithPrecorrectionInverse); MITK_TEST(testGetSlicedSignalVolume); MITK_TEST(testGetSlicedAbsorptionVolume); CPPUNIT_TEST_SUITE_END(); private: mitk::pa::ComposedVolume::Pointer m_ComposedVolume; mitk::pa::TissueGeneratorParameters::Pointer m_DefaultParameters; mitk::pa::InSilicoTissueVolume::Pointer m_InSilicoTissueVolume; mitk::pa::SlicedVolumeGenerator::Pointer m_SlicedVolumeGenerator; mitk::pa::Volume::Pointer m_PrecorrectionVolume; public: - void setUp() + void setUp() override { m_SlicedVolumeGenerator = nullptr; m_DefaultParameters = mitk::pa::TissueGeneratorParameters::New(); m_DefaultParameters->SetXDim(3); m_DefaultParameters->SetYDim(3); m_DefaultParameters->SetZDim(3); m_InSilicoTissueVolume = mitk::pa::InSilicoTissueVolume::New(m_DefaultParameters); m_ComposedVolume = mitk::pa::ComposedVolume::New(m_InSilicoTissueVolume); m_ComposedVolume->AddSlice(CreateValidationPair(-1, 1)); m_ComposedVolume->AddSlice(CreateValidationPair(0, 3)); m_ComposedVolume->AddSlice(CreateValidationPair(1, 6)); m_PrecorrectionVolume = CreatePrecorrectionVolume(); } mitk::pa::Volume::Pointer CreatePrecorrectionVolume() { double* data = new double[27]; for (int i = 0; i < 27; ++i) data[i] = 0.5; return mitk::pa::Volume::New(data, 3, 3, 3); } void FillYSliceWith(mitk::pa::Volume::Pointer fluenceVolume, double ySlice, double value) { for (unsigned int x = 0; x < fluenceVolume->GetXDim(); ++x) for (unsigned int z = 0; z < fluenceVolume->GetZDim(); ++z) { fluenceVolume->SetData(value, x, ySlice, z); } } mitk::pa::FluenceYOffsetPair::Pointer CreateValidationPair(double yOffset, int start) { double* data = new double[27]; mitk::pa::Volume::Pointer fluenceVolume = mitk::pa::Volume::New(data, 3, 3, 3); FillYSliceWith(fluenceVolume, 0, start + 0); FillYSliceWith(fluenceVolume, 1, start + 1); FillYSliceWith(fluenceVolume, 2, start + 2); return mitk::pa::FluenceYOffsetPair::New(fluenceVolume, yOffset); } void AssertYSliceValue(mitk::pa::Volume::Pointer fluenceVolume, double ySlice, double value) { for (unsigned int x = 0; x < fluenceVolume->GetXDim(); ++x) for (unsigned int z = 0; z < fluenceVolume->GetZDim(); ++z) { std::string msg = "Expected: " + std::to_string(value) + " actual: " + std::to_string(fluenceVolume->GetData(x, ySlice, z)); CPPUNIT_ASSERT_MESSAGE(msg, abs(fluenceVolume->GetData(x, ySlice, z) - value) < mitk::eps); } } void testConstructorDestructor() { m_SlicedVolumeGenerator = mitk::pa::SlicedVolumeGenerator::New(0, false, nullptr, false); CPPUNIT_ASSERT(m_SlicedVolumeGenerator.IsNotNull()); } void testGetSlicedFluenceVolume() { m_SlicedVolumeGenerator = mitk::pa::SlicedVolumeGenerator::New(1, false, nullptr, false); mitk::pa::Volume::Pointer slicedFluence = m_SlicedVolumeGenerator->GetSlicedFluenceImageFromComposedVolume(m_ComposedVolume); CPPUNIT_ASSERT(slicedFluence->GetXDim() == 3); CPPUNIT_ASSERT(slicedFluence->GetYDim() == 3); CPPUNIT_ASSERT(slicedFluence->GetZDim() == 3); AssertYSliceValue(slicedFluence, 0, 1); AssertYSliceValue(slicedFluence, 1, 4); AssertYSliceValue(slicedFluence, 2, 8); } void testGetSlicedFluenceVolumeInverse() { m_SlicedVolumeGenerator = mitk::pa::SlicedVolumeGenerator::New(1, false, nullptr, true); mitk::pa::Volume::Pointer slicedFluence = m_SlicedVolumeGenerator->GetSlicedFluenceImageFromComposedVolume(m_ComposedVolume); CPPUNIT_ASSERT(slicedFluence->GetXDim() == 3); CPPUNIT_ASSERT(slicedFluence->GetYDim() == 3); CPPUNIT_ASSERT(slicedFluence->GetZDim() == 3); AssertYSliceValue(slicedFluence, 0, 1); AssertYSliceValue(slicedFluence, 1, 1.0 / 4.0); AssertYSliceValue(slicedFluence, 2, 1.0 / 8.0); } void testGetSlicedFluenceVolumeWithPrecorrection() { m_SlicedVolumeGenerator = mitk::pa::SlicedVolumeGenerator::New(1, true, m_PrecorrectionVolume, false); mitk::pa::Volume::Pointer slicedFluence = m_SlicedVolumeGenerator->GetSlicedFluenceImageFromComposedVolume(m_ComposedVolume); CPPUNIT_ASSERT(slicedFluence->GetXDim() == 3); CPPUNIT_ASSERT(slicedFluence->GetYDim() == 3); CPPUNIT_ASSERT(slicedFluence->GetZDim() == 3); AssertYSliceValue(slicedFluence, 0, 2); AssertYSliceValue(slicedFluence, 1, 8); AssertYSliceValue(slicedFluence, 2, 16); } void testGetSlicedFluenceVolumeWithPrecorrectionInverse() { m_SlicedVolumeGenerator = mitk::pa::SlicedVolumeGenerator::New(1, true, m_PrecorrectionVolume, true); mitk::pa::Volume::Pointer slicedFluence = m_SlicedVolumeGenerator->GetSlicedFluenceImageFromComposedVolume(m_ComposedVolume); CPPUNIT_ASSERT(slicedFluence->GetXDim() == 3); CPPUNIT_ASSERT(slicedFluence->GetYDim() == 3); CPPUNIT_ASSERT(slicedFluence->GetZDim() == 3); AssertYSliceValue(slicedFluence, 0, 1.0 / 2); AssertYSliceValue(slicedFluence, 1, 1.0 / 8); AssertYSliceValue(slicedFluence, 2, 1.0 / 16); } void testGetSlicedSignalVolume() { m_SlicedVolumeGenerator = mitk::pa::SlicedVolumeGenerator::New(1, false, nullptr, false); mitk::pa::Volume::Pointer slicedFluence = m_SlicedVolumeGenerator->GetSlicedSignalImageFromComposedVolume(m_ComposedVolume); CPPUNIT_ASSERT(slicedFluence->GetXDim() == 3); CPPUNIT_ASSERT(slicedFluence->GetYDim() == 3); CPPUNIT_ASSERT(slicedFluence->GetZDim() == 3); AssertYSliceValue(slicedFluence, 0, 1 * m_DefaultParameters->GetBackgroundAbsorption()); AssertYSliceValue(slicedFluence, 1, 4 * m_DefaultParameters->GetBackgroundAbsorption()); AssertYSliceValue(slicedFluence, 2, 8 * m_DefaultParameters->GetBackgroundAbsorption()); } void testGetSlicedAbsorptionVolume() { m_SlicedVolumeGenerator = mitk::pa::SlicedVolumeGenerator::New(1, false, nullptr, false); mitk::pa::Volume::Pointer slicedFluence = m_SlicedVolumeGenerator->GetSlicedGroundTruthImageFromComposedVolume(m_ComposedVolume); CPPUNIT_ASSERT(slicedFluence->GetXDim() == 3); CPPUNIT_ASSERT(slicedFluence->GetYDim() == 3); CPPUNIT_ASSERT(slicedFluence->GetZDim() == 3); AssertYSliceValue(slicedFluence, 0, m_DefaultParameters->GetBackgroundAbsorption()); AssertYSliceValue(slicedFluence, 1, m_DefaultParameters->GetBackgroundAbsorption()); AssertYSliceValue(slicedFluence, 2, m_DefaultParameters->GetBackgroundAbsorption()); } - void tearDown() + void tearDown() override { m_SlicedVolumeGenerator = nullptr; } }; MITK_TEST_SUITE_REGISTRATION(mitkSlicedVolumeGenerator) diff --git a/Modules/PlanarFigure/src/IO/mitkPlanarFigureWriterFactory.cpp b/Modules/PlanarFigure/src/IO/mitkPlanarFigureWriterFactory.cpp index 2249249aef..bd86a80e1b 100644 --- a/Modules/PlanarFigure/src/IO/mitkPlanarFigureWriterFactory.cpp +++ b/Modules/PlanarFigure/src/IO/mitkPlanarFigureWriterFactory.cpp @@ -1,81 +1,81 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "mitkPlanarFigureWriterFactory.h" #include "itkCreateObjectFunction.h" #include "itkVersion.h" #include namespace mitk { template class CreatePlanarFigureWriter : public itk::CreateObjectFunctionBase { public: /** Standard class typedefs. */ typedef CreatePlanarFigureWriter Self; typedef itk::SmartPointer Pointer; /** Methods from itk:LightObject. */ itkFactorylessNewMacro(Self) LightObject::Pointer CreateObject() override { typename T::Pointer p = T::New(); p->Register(); return p.GetPointer(); } protected: CreatePlanarFigureWriter() {} - ~CreatePlanarFigureWriter() {} + ~CreatePlanarFigureWriter() override {} private: CreatePlanarFigureWriter(const Self &); // purposely not implemented void operator=(const Self &); // purposely not implemented }; PlanarFigureWriterFactory::PlanarFigureWriterFactory() { this->RegisterOverride("IOWriter", "PlanarFigureWriter", "PlanarFigure xml Writer", 1, mitk::CreatePlanarFigureWriter::New()); } PlanarFigureWriterFactory::~PlanarFigureWriterFactory() {} itk::ObjectFactoryBase::Pointer PlanarFigureWriterFactory::GetInstance() { static itk::ObjectFactoryBase::Pointer factory(mitk::PlanarFigureWriterFactory::New().GetPointer()); return factory; } void PlanarFigureWriterFactory::RegisterOneFactory(void) { if (GetInstance()->GetReferenceCount() == 1) { ObjectFactoryBase::RegisterFactory(GetInstance().GetPointer()); } } void PlanarFigureWriterFactory::UnRegisterOneFactory(void) { ObjectFactoryBase::UnRegisterFactory(GetInstance().GetPointer()); } const char *PlanarFigureWriterFactory::GetITKSourceVersion() const { return ITK_SOURCE_VERSION; } const char *PlanarFigureWriterFactory::GetDescription() const { return "PlanarFigureWriterFactory"; } } // end namespace mitk diff --git a/Modules/SceneSerializationBase/src/mitkAnnotationPropertySerializer.cpp b/Modules/SceneSerializationBase/src/mitkAnnotationPropertySerializer.cpp index 29b6479d2d..627ead4125 100644 --- a/Modules/SceneSerializationBase/src/mitkAnnotationPropertySerializer.cpp +++ b/Modules/SceneSerializationBase/src/mitkAnnotationPropertySerializer.cpp @@ -1,85 +1,85 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #ifndef mitkAnnotationPropertySerializer_h_included #define mitkAnnotationPropertySerializer_h_included #include "mitkBasePropertySerializer.h" #include "mitkAnnotationProperty.h" #include "mitkStringsToNumbers.h" namespace mitk { class AnnotationPropertySerializer : public BasePropertySerializer { public: mitkClassMacro(AnnotationPropertySerializer, BasePropertySerializer); itkFactorylessNewMacro(Self) itkCloneMacro(Self) - virtual TiXmlElement *Serialize() override + TiXmlElement *Serialize() override { if (const AnnotationProperty *prop = dynamic_cast(m_Property.GetPointer())) { auto element = new TiXmlElement("annotation"); element->SetAttribute("label", prop->GetLabel()); Point3D point = prop->GetPosition(); element->SetAttribute("x", boost::lexical_cast(point[0])); element->SetAttribute("y", boost::lexical_cast(point[1])); element->SetAttribute("z", boost::lexical_cast(point[2])); return element; } else return nullptr; } - virtual BaseProperty::Pointer Deserialize(TiXmlElement *element) override + BaseProperty::Pointer Deserialize(TiXmlElement *element) override { if (!element) return nullptr; const char *label(element->Attribute("label")); std::string p_string[3]; if (element->QueryStringAttribute("x", &p_string[0]) != TIXML_SUCCESS) return nullptr; if (element->QueryStringAttribute("y", &p_string[1]) != TIXML_SUCCESS) return nullptr; if (element->QueryStringAttribute("z", &p_string[2]) != TIXML_SUCCESS) return nullptr; Point3D p; try { StringsToNumbers(3, p_string, p); } catch (boost::bad_lexical_cast &e) { MITK_ERROR << "Could not parse string as number: " << e.what(); return nullptr; } return AnnotationProperty::New(label, p).GetPointer(); } protected: AnnotationPropertySerializer() {} - virtual ~AnnotationPropertySerializer() {} + ~AnnotationPropertySerializer() override {} }; } // namespace // important to put this into the GLOBAL namespace (because it starts with 'namespace mitk') MITK_REGISTER_SERIALIZER(AnnotationPropertySerializer); #endif diff --git a/Modules/SceneSerializationBase/src/mitkBoolLookupTablePropertySerializer.cpp b/Modules/SceneSerializationBase/src/mitkBoolLookupTablePropertySerializer.cpp index 6ef64fd9b2..dfe221c1a1 100644 --- a/Modules/SceneSerializationBase/src/mitkBoolLookupTablePropertySerializer.cpp +++ b/Modules/SceneSerializationBase/src/mitkBoolLookupTablePropertySerializer.cpp @@ -1,82 +1,82 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #ifndef mitkBoolLookupTablePropertySerializer_h_included #define mitkBoolLookupTablePropertySerializer_h_included #include "mitkBasePropertySerializer.h" #include "mitkProperties.h" namespace mitk { class BoolLookupTablePropertySerializer : public BasePropertySerializer { public: mitkClassMacro(BoolLookupTablePropertySerializer, BasePropertySerializer); itkFactorylessNewMacro(Self) itkCloneMacro(Self) - virtual TiXmlElement *Serialize() override + TiXmlElement *Serialize() override { const BoolLookupTableProperty *prop = dynamic_cast(m_Property.GetPointer()); if (prop == nullptr) return nullptr; BoolLookupTable lut = prop->GetValue(); // if (lut.IsNull()) // return nullptr; // really? const BoolLookupTable::LookupTableType &map = lut.GetLookupTable(); auto element = new TiXmlElement("BoolLookupTable"); for (auto it = map.begin(); it != map.end(); ++it) { auto tableEntry = new TiXmlElement("LUTValue"); tableEntry->SetAttribute("id", it->first); if (it->second == true) tableEntry->SetAttribute("value", "true"); else tableEntry->SetAttribute("value", "false"); element->LinkEndChild(tableEntry); } return element; } - virtual BaseProperty::Pointer Deserialize(TiXmlElement *element) override + BaseProperty::Pointer Deserialize(TiXmlElement *element) override { if (!element) return nullptr; BoolLookupTable lut; for (TiXmlElement *child = element->FirstChildElement("LUTValue"); child != nullptr; child = child->NextSiblingElement("LUTValue")) { int xmlID; if (child->QueryIntAttribute("id", &xmlID) == TIXML_WRONG_TYPE) return nullptr; // TODO: can we do a better error handling? BoolLookupTable::IdentifierType id = static_cast(xmlID); BoolLookupTable::ValueType val = std::string(child->Attribute("value")) == std::string("true"); lut.SetTableValue(id, val); } return BoolLookupTableProperty::New(lut).GetPointer(); } protected: BoolLookupTablePropertySerializer() {} - virtual ~BoolLookupTablePropertySerializer() {} + ~BoolLookupTablePropertySerializer() override {} }; } // namespace // important to put this into the GLOBAL namespace (because it starts with 'namespace mitk') MITK_REGISTER_SERIALIZER(BoolLookupTablePropertySerializer); #endif diff --git a/Modules/SceneSerializationBase/src/mitkBoolPropertySerializer.cpp b/Modules/SceneSerializationBase/src/mitkBoolPropertySerializer.cpp index c365a5c219..b31050632f 100644 --- a/Modules/SceneSerializationBase/src/mitkBoolPropertySerializer.cpp +++ b/Modules/SceneSerializationBase/src/mitkBoolPropertySerializer.cpp @@ -1,68 +1,68 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #ifndef mitkBoolPropertySerializer_h_included #define mitkBoolPropertySerializer_h_included #include "mitkBasePropertySerializer.h" #include "mitkProperties.h" namespace mitk { class BoolPropertySerializer : public BasePropertySerializer { public: mitkClassMacro(BoolPropertySerializer, BasePropertySerializer); itkFactorylessNewMacro(Self) itkCloneMacro(Self) - virtual TiXmlElement *Serialize() override + TiXmlElement *Serialize() override { if (const BoolProperty *prop = dynamic_cast(m_Property.GetPointer())) { auto element = new TiXmlElement("bool"); if (prop->GetValue() == true) { element->SetAttribute("value", "true"); } else { element->SetAttribute("value", "false"); } return element; } else return nullptr; } - virtual BaseProperty::Pointer Deserialize(TiXmlElement *element) override + BaseProperty::Pointer Deserialize(TiXmlElement *element) override { if (!element) return nullptr; return BoolProperty::New(std::string(element->Attribute("value")) == "true").GetPointer(); } protected: BoolPropertySerializer() {} - virtual ~BoolPropertySerializer() {} + ~BoolPropertySerializer() override {} }; } // namespace // important to put this into the GLOBAL namespace (because it starts with 'namespace mitk') MITK_REGISTER_SERIALIZER(BoolPropertySerializer); #endif diff --git a/Modules/SceneSerializationBase/src/mitkClippingPropertySerializer.cpp b/Modules/SceneSerializationBase/src/mitkClippingPropertySerializer.cpp index 0387f15e86..ef3d09ae29 100644 --- a/Modules/SceneSerializationBase/src/mitkClippingPropertySerializer.cpp +++ b/Modules/SceneSerializationBase/src/mitkClippingPropertySerializer.cpp @@ -1,127 +1,127 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #ifndef mitkClippingPropertySerializer_h_included #define mitkClippingPropertySerializer_h_included #include "mitkBasePropertySerializer.h" #include "mitkClippingProperty.h" #include "mitkNumericTypes.h" #include #include "mitkStringsToNumbers.h" namespace mitk { class ClippingPropertySerializer : public BasePropertySerializer { public: mitkClassMacro(ClippingPropertySerializer, BasePropertySerializer); itkFactorylessNewMacro(Self) itkCloneMacro(Self) - virtual TiXmlElement *Serialize() override + TiXmlElement *Serialize() override { if (const ClippingProperty *prop = dynamic_cast(m_Property.GetPointer())) { LocaleSwitch localeSwitch("C"); auto element = new TiXmlElement("clipping"); if (prop->GetClippingEnabled()) element->SetAttribute("enabled", "true"); else element->SetAttribute("enabled", "false"); auto originElement = new TiXmlElement("origin"); const Point3D origin = prop->GetOrigin(); originElement->SetAttribute("x", boost::lexical_cast(origin[0])); originElement->SetAttribute("y", boost::lexical_cast(origin[1])); originElement->SetAttribute("z", boost::lexical_cast(origin[2])); element->LinkEndChild(originElement); auto normalElement = new TiXmlElement("normal"); const Vector3D normal = prop->GetNormal(); normalElement->SetAttribute("x", boost::lexical_cast(normal[0])); normalElement->SetAttribute("y", boost::lexical_cast(normal[1])); normalElement->SetAttribute("z", boost::lexical_cast(normal[2])); element->LinkEndChild(normalElement); return element; } else return nullptr; } - virtual BaseProperty::Pointer Deserialize(TiXmlElement *element) override + BaseProperty::Pointer Deserialize(TiXmlElement *element) override { if (!element) return nullptr; LocaleSwitch localeSwitch("C"); bool enabled = std::string(element->Attribute("enabled")) == "true"; TiXmlElement *originElement = element->FirstChildElement("origin"); if (originElement == nullptr) return nullptr; std::string origin_string[3]; if (originElement->QueryStringAttribute("x", &origin_string[0]) != TIXML_SUCCESS) return nullptr; if (originElement->QueryStringAttribute("y", &origin_string[1]) != TIXML_SUCCESS) return nullptr; if (originElement->QueryStringAttribute("z", &origin_string[2]) != TIXML_SUCCESS) return nullptr; Point3D origin; try { StringsToNumbers(3, origin_string, origin); } catch (boost::bad_lexical_cast &e) { MITK_ERROR << "Could not parse string as number: " << e.what(); return nullptr; } TiXmlElement *normalElement = element->FirstChildElement("normal"); if (normalElement == nullptr) return nullptr; std::string normal_string[3]; if (normalElement->QueryStringAttribute("x", &normal_string[0]) != TIXML_SUCCESS) return nullptr; if (normalElement->QueryStringAttribute("y", &normal_string[1]) != TIXML_SUCCESS) return nullptr; if (normalElement->QueryStringAttribute("z", &normal_string[2]) != TIXML_SUCCESS) return nullptr; Vector3D normal; try { StringsToNumbers(3, normal_string, normal); } catch (boost::bad_lexical_cast &e) { MITK_ERROR << "Could not parse string as number: " << e.what(); return nullptr; } ClippingProperty::Pointer cp = ClippingProperty::New(origin, normal); cp->SetClippingEnabled(enabled); return cp.GetPointer(); } protected: ClippingPropertySerializer() {} - virtual ~ClippingPropertySerializer() {} + ~ClippingPropertySerializer() override {} }; } // namespace // important to put this into the GLOBAL namespace (because it starts with 'namespace mitk') MITK_REGISTER_SERIALIZER(ClippingPropertySerializer); #endif diff --git a/Modules/SceneSerializationBase/src/mitkColorPropertySerializer.cpp b/Modules/SceneSerializationBase/src/mitkColorPropertySerializer.cpp index 9402f02f0f..b0f704fd66 100644 --- a/Modules/SceneSerializationBase/src/mitkColorPropertySerializer.cpp +++ b/Modules/SceneSerializationBase/src/mitkColorPropertySerializer.cpp @@ -1,88 +1,88 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #ifndef mitkColorPropertySerializer_h_included #define mitkColorPropertySerializer_h_included #include "mitkBasePropertySerializer.h" #include "mitkColorProperty.h" #include "mitkStringsToNumbers.h" #include namespace mitk { class ColorPropertySerializer : public BasePropertySerializer { public: mitkClassMacro(ColorPropertySerializer, BasePropertySerializer); itkFactorylessNewMacro(Self) itkCloneMacro(Self) - virtual TiXmlElement *Serialize() override + TiXmlElement *Serialize() override { if (const ColorProperty *prop = dynamic_cast(m_Property.GetPointer())) { LocaleSwitch localeSwitch("C"); auto element = new TiXmlElement("color"); Color color = prop->GetValue(); element->SetAttribute("r", boost::lexical_cast(color[0])); element->SetAttribute("g", boost::lexical_cast(color[1])); element->SetAttribute("b", boost::lexical_cast(color[2])); return element; } else return nullptr; } - virtual BaseProperty::Pointer Deserialize(TiXmlElement *element) override + BaseProperty::Pointer Deserialize(TiXmlElement *element) override { if (!element) return nullptr; LocaleSwitch localeSwitch("C"); std::string c_string[3]; if (element->QueryStringAttribute("r", &c_string[0]) != TIXML_SUCCESS) return nullptr; if (element->QueryStringAttribute("g", &c_string[1]) != TIXML_SUCCESS) return nullptr; if (element->QueryStringAttribute("b", &c_string[2]) != TIXML_SUCCESS) return nullptr; Color c; try { StringsToNumbers(3, c_string, c); } catch (boost::bad_lexical_cast &e) { MITK_ERROR << "Could not parse string as number: " << e.what(); return nullptr; } return ColorProperty::New(c).GetPointer(); } protected: ColorPropertySerializer() {} - virtual ~ColorPropertySerializer() {} + ~ColorPropertySerializer() override {} }; } // namespace // important to put this into the GLOBAL namespace (because it starts with 'namespace mitk') MITK_REGISTER_SERIALIZER(ColorPropertySerializer); #endif diff --git a/Modules/SceneSerializationBase/src/mitkDoublePropertySerializer.cpp b/Modules/SceneSerializationBase/src/mitkDoublePropertySerializer.cpp index fe47938bc0..87fe4909fd 100644 --- a/Modules/SceneSerializationBase/src/mitkDoublePropertySerializer.cpp +++ b/Modules/SceneSerializationBase/src/mitkDoublePropertySerializer.cpp @@ -1,87 +1,87 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #ifndef mitkDoublePropertySerializer_h_included #define mitkDoublePropertySerializer_h_included #include "mitkBasePropertySerializer.h" #include "mitkProperties.h" #include #include #include namespace mitk { class DoublePropertySerializer : public BasePropertySerializer { public: mitkClassMacro(DoublePropertySerializer, BasePropertySerializer); itkFactorylessNewMacro(Self) itkCloneMacro(Self) - virtual TiXmlElement *Serialize() override + TiXmlElement *Serialize() override { if (const DoubleProperty *prop = dynamic_cast(m_Property.GetPointer())) { LocaleSwitch localeSwitch("C"); auto element = new TiXmlElement("double"); element->SetAttribute("value", boost::lexical_cast(prop->GetValue())); return element; } else return nullptr; } - virtual BaseProperty::Pointer Deserialize(TiXmlElement *element) override + BaseProperty::Pointer Deserialize(TiXmlElement *element) override { if (!element) return nullptr; LocaleSwitch localeSwitch("C"); std::string d; if (element->QueryStringAttribute("value", &d) == TIXML_SUCCESS) { try { return DoubleProperty::New(boost::lexical_cast(d)).GetPointer(); } catch (boost::bad_lexical_cast &e) { MITK_ERROR << "Could not parse string as number: " << e.what(); return nullptr; } } else { return nullptr; } } protected: DoublePropertySerializer() {} - virtual ~DoublePropertySerializer() {} + ~DoublePropertySerializer() override {} }; } // namespace // important to put this into the GLOBAL namespace (because it starts with 'namespace mitk') MITK_REGISTER_SERIALIZER(DoublePropertySerializer); #endif diff --git a/Modules/SceneSerializationBase/src/mitkFloatLookupTablePropertySerializer.cpp b/Modules/SceneSerializationBase/src/mitkFloatLookupTablePropertySerializer.cpp index c60518346f..56e1657a10 100644 --- a/Modules/SceneSerializationBase/src/mitkFloatLookupTablePropertySerializer.cpp +++ b/Modules/SceneSerializationBase/src/mitkFloatLookupTablePropertySerializer.cpp @@ -1,95 +1,95 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #ifndef mitkFloatLookupTablePropertySerializer_h_included #define mitkFloatLookupTablePropertySerializer_h_included #include "mitkBasePropertySerializer.h" #include "mitkProperties.h" #include #include namespace mitk { class FloatLookupTablePropertySerializer : public BasePropertySerializer { public: mitkClassMacro(FloatLookupTablePropertySerializer, BasePropertySerializer); itkFactorylessNewMacro(Self) itkCloneMacro(Self) - virtual TiXmlElement *Serialize() override + TiXmlElement *Serialize() override { const FloatLookupTableProperty *prop = dynamic_cast(m_Property.GetPointer()); if (prop == nullptr) return nullptr; LocaleSwitch localeSwitch("C"); FloatLookupTable lut = prop->GetValue(); // if (lut.IsNull()) // return nullptr; // really? const FloatLookupTable::LookupTableType &map = lut.GetLookupTable(); auto element = new TiXmlElement("FloatLookupTableTable"); for (auto it = map.begin(); it != map.end(); ++it) { auto tableEntry = new TiXmlElement("LUTValue"); tableEntry->SetAttribute("id", it->first); tableEntry->SetAttribute("value", boost::lexical_cast(it->second)); element->LinkEndChild(tableEntry); } return element; } - virtual BaseProperty::Pointer Deserialize(TiXmlElement *element) override + BaseProperty::Pointer Deserialize(TiXmlElement *element) override { if (!element) return nullptr; LocaleSwitch localeSwitch("C"); FloatLookupTable lut; for (TiXmlElement *child = element->FirstChildElement("LUTValue"); child != nullptr; child = child->NextSiblingElement("LUTValue")) { int tempID; if (child->QueryIntAttribute("id", &tempID) != TIXML_SUCCESS) return nullptr; FloatLookupTable::IdentifierType id = static_cast(tempID); std::string value_string; if (child->QueryStringAttribute("value", &value_string) != TIXML_SUCCESS) return nullptr; try { lut.SetTableValue(id, boost::lexical_cast(value_string)); } catch (boost::bad_lexical_cast &e) { MITK_ERROR << "Could not parse string as number: " << e.what(); return nullptr; } } return FloatLookupTableProperty::New(lut).GetPointer(); } protected: FloatLookupTablePropertySerializer() {} - virtual ~FloatLookupTablePropertySerializer() {} + ~FloatLookupTablePropertySerializer() override {} }; } // namespace // important to put this into the GLOBAL namespace (because it starts with 'namespace mitk') MITK_REGISTER_SERIALIZER(FloatLookupTablePropertySerializer); #endif diff --git a/Modules/SceneSerializationBase/src/mitkFloatPropertySerializer.cpp b/Modules/SceneSerializationBase/src/mitkFloatPropertySerializer.cpp index 2fc93f9a55..f18e7f8cc2 100644 --- a/Modules/SceneSerializationBase/src/mitkFloatPropertySerializer.cpp +++ b/Modules/SceneSerializationBase/src/mitkFloatPropertySerializer.cpp @@ -1,84 +1,84 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #ifndef mitkFloatPropertySerializer_h_included #define mitkFloatPropertySerializer_h_included #include "mitkBasePropertySerializer.h" #include "mitkProperties.h" #include "mitkStringsToNumbers.h" #include namespace mitk { class FloatPropertySerializer : public BasePropertySerializer { public: mitkClassMacro(FloatPropertySerializer, BasePropertySerializer); itkFactorylessNewMacro(Self) itkCloneMacro(Self) - virtual TiXmlElement *Serialize() override + TiXmlElement *Serialize() override { if (const FloatProperty *prop = dynamic_cast(m_Property.GetPointer())) { LocaleSwitch localeSwitch("C"); auto element = new TiXmlElement("float"); element->SetAttribute("value", boost::lexical_cast(prop->GetValue())); return element; } else return nullptr; } - virtual BaseProperty::Pointer Deserialize(TiXmlElement *element) override + BaseProperty::Pointer Deserialize(TiXmlElement *element) override { if (!element) return nullptr; LocaleSwitch localeSwitch("C"); std::string f_string; if (element->QueryStringAttribute("value", &f_string) == TIXML_SUCCESS) { try { return FloatProperty::New(boost::lexical_cast(f_string)).GetPointer(); } catch (boost::bad_lexical_cast &e) { MITK_ERROR << "Could not parse string as number: " << e.what(); return nullptr; } } else { return nullptr; } } protected: FloatPropertySerializer() {} - virtual ~FloatPropertySerializer() {} + ~FloatPropertySerializer() override {} }; } // namespace // important to put this into the GLOBAL namespace (because it starts with 'namespace mitk') MITK_REGISTER_SERIALIZER(FloatPropertySerializer); #endif diff --git a/Modules/SceneSerializationBase/src/mitkGroupTagPropertySerializer.cpp b/Modules/SceneSerializationBase/src/mitkGroupTagPropertySerializer.cpp index 0ff8ba74d5..b751c1d187 100644 --- a/Modules/SceneSerializationBase/src/mitkGroupTagPropertySerializer.cpp +++ b/Modules/SceneSerializationBase/src/mitkGroupTagPropertySerializer.cpp @@ -1,60 +1,60 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #ifndef mitkGroupTagPropertySerializer_h_included #define mitkGroupTagPropertySerializer_h_included #include "mitkBasePropertySerializer.h" #include "mitkGroupTagProperty.h" namespace mitk { class GroupTagPropertySerializer : public BasePropertySerializer { public: mitkClassMacro(GroupTagPropertySerializer, BasePropertySerializer); itkFactorylessNewMacro(Self) itkCloneMacro(Self) - virtual TiXmlElement *Serialize() override + TiXmlElement *Serialize() override { if (dynamic_cast(m_Property.GetPointer()) != nullptr) { auto element = new TiXmlElement("GroupTag"); return element; } else return nullptr; } - virtual BaseProperty::Pointer Deserialize(TiXmlElement *) override + BaseProperty::Pointer Deserialize(TiXmlElement *) override { // if (!element) // return nullptr; return GroupTagProperty::New().GetPointer(); } protected: GroupTagPropertySerializer() {} - virtual ~GroupTagPropertySerializer() {} + ~GroupTagPropertySerializer() override {} }; } // namespace // important to put this into the GLOBAL namespace (because it starts with 'namespace mitk') MITK_REGISTER_SERIALIZER(GroupTagPropertySerializer); #endif diff --git a/Modules/SceneSerializationBase/src/mitkIntLookupTablePropertySerializer.cpp b/Modules/SceneSerializationBase/src/mitkIntLookupTablePropertySerializer.cpp index a153ee8355..b71a66e2c3 100644 --- a/Modules/SceneSerializationBase/src/mitkIntLookupTablePropertySerializer.cpp +++ b/Modules/SceneSerializationBase/src/mitkIntLookupTablePropertySerializer.cpp @@ -1,81 +1,81 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #ifndef mitkIntLookupTablePropertySerializer_h_included #define mitkIntLookupTablePropertySerializer_h_included #include "mitkBasePropertySerializer.h" #include "mitkProperties.h" namespace mitk { class IntLookupTablePropertySerializer : public BasePropertySerializer { public: mitkClassMacro(IntLookupTablePropertySerializer, BasePropertySerializer); itkFactorylessNewMacro(Self) itkCloneMacro(Self) - virtual TiXmlElement *Serialize() override + TiXmlElement *Serialize() override { const IntLookupTableProperty *prop = dynamic_cast(m_Property.GetPointer()); if (prop == nullptr) return nullptr; IntLookupTable lut = prop->GetValue(); // if (lut.IsNull()) // return nullptr; // really? const IntLookupTable::LookupTableType &map = lut.GetLookupTable(); auto element = new TiXmlElement("IntLookupTableTable"); for (auto it = map.begin(); it != map.end(); ++it) { auto tableEntry = new TiXmlElement("LUTValue"); tableEntry->SetAttribute("id", it->first); tableEntry->SetAttribute("value", it->second); element->LinkEndChild(tableEntry); } return element; } - virtual BaseProperty::Pointer Deserialize(TiXmlElement *element) override + BaseProperty::Pointer Deserialize(TiXmlElement *element) override { if (!element) return nullptr; IntLookupTable lut; for (TiXmlElement *child = element->FirstChildElement("LUTValue"); child != nullptr; child = child->NextSiblingElement("LUTValue")) { int temp; if (child->QueryIntAttribute("id", &temp) == TIXML_WRONG_TYPE) return nullptr; // TODO: can we do a better error handling? IntLookupTable::IdentifierType id = static_cast(temp); if (child->QueryIntAttribute("value", &temp) == TIXML_WRONG_TYPE) return nullptr; // TODO: can we do a better error handling? IntLookupTable::ValueType val = static_cast(temp); lut.SetTableValue(id, val); } return IntLookupTableProperty::New(lut).GetPointer(); } protected: IntLookupTablePropertySerializer() {} - virtual ~IntLookupTablePropertySerializer() {} + ~IntLookupTablePropertySerializer() override {} }; } // namespace // important to put this into the GLOBAL namespace (because it starts with 'namespace mitk') MITK_REGISTER_SERIALIZER(IntLookupTablePropertySerializer); #endif diff --git a/Modules/SceneSerializationBase/src/mitkIntPropertySerializer.cpp b/Modules/SceneSerializationBase/src/mitkIntPropertySerializer.cpp index 496b4f5d1b..92d6de1815 100644 --- a/Modules/SceneSerializationBase/src/mitkIntPropertySerializer.cpp +++ b/Modules/SceneSerializationBase/src/mitkIntPropertySerializer.cpp @@ -1,70 +1,70 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #ifndef mitkIntPropertySerializer_h_included #define mitkIntPropertySerializer_h_included #include "mitkBasePropertySerializer.h" #include "mitkProperties.h" namespace mitk { class IntPropertySerializer : public BasePropertySerializer { public: mitkClassMacro(IntPropertySerializer, BasePropertySerializer); itkFactorylessNewMacro(Self) itkCloneMacro(Self) - virtual TiXmlElement *Serialize() override + TiXmlElement *Serialize() override { if (const IntProperty *prop = dynamic_cast(m_Property.GetPointer())) { auto element = new TiXmlElement("int"); element->SetAttribute("value", prop->GetValue()); return element; } else return nullptr; } - virtual BaseProperty::Pointer Deserialize(TiXmlElement *element) override + BaseProperty::Pointer Deserialize(TiXmlElement *element) override { if (!element) return nullptr; int integer; if (element->QueryIntAttribute("value", &integer) == TIXML_SUCCESS) { return IntProperty::New(integer).GetPointer(); } else { return nullptr; } } protected: IntPropertySerializer() {} - virtual ~IntPropertySerializer() {} + ~IntPropertySerializer() override {} }; } // namespace // important to put this into the GLOBAL namespace (because it starts with 'namespace mitk') MITK_REGISTER_SERIALIZER(IntPropertySerializer); #endif diff --git a/Modules/SceneSerializationBase/src/mitkLevelWindowPropertySerializer.cpp b/Modules/SceneSerializationBase/src/mitkLevelWindowPropertySerializer.cpp index 9264326361..455dbc0097 100644 --- a/Modules/SceneSerializationBase/src/mitkLevelWindowPropertySerializer.cpp +++ b/Modules/SceneSerializationBase/src/mitkLevelWindowPropertySerializer.cpp @@ -1,139 +1,139 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #ifndef mitkLevelWindowPropertySerializer_h_included #define mitkLevelWindowPropertySerializer_h_included #include "mitkBasePropertySerializer.h" #include "mitkLevelWindowProperty.h" #include #include namespace mitk { class LevelWindowPropertySerializer : public BasePropertySerializer { public: mitkClassMacro(LevelWindowPropertySerializer, BasePropertySerializer); itkFactorylessNewMacro(Self) itkCloneMacro(Self) - virtual TiXmlElement *Serialize() override + TiXmlElement *Serialize() override { if (const LevelWindowProperty *prop = dynamic_cast(m_Property.GetPointer())) { LocaleSwitch localeSwitch("C"); auto element = new TiXmlElement("LevelWindow"); LevelWindow lw = prop->GetLevelWindow(); std::string boolString("false"); if (lw.IsFixed() == true) boolString = "true"; element->SetAttribute("fixed", boolString.c_str()); std::string boolStringFltImage("false"); if (lw.IsFloatingValues() == true) boolStringFltImage = "true"; element->SetAttribute("isFloatingImage", boolStringFltImage.c_str()); auto child = new TiXmlElement("CurrentSettings"); element->LinkEndChild(child); child->SetAttribute("level", boost::lexical_cast(lw.GetLevel())); child->SetAttribute("window", boost::lexical_cast(lw.GetWindow())); child = new TiXmlElement("DefaultSettings"); element->LinkEndChild(child); child->SetAttribute("level", boost::lexical_cast(lw.GetDefaultLevel())); child->SetAttribute("window", boost::lexical_cast(lw.GetDefaultWindow())); child = new TiXmlElement("CurrentRange"); element->LinkEndChild(child); child->SetAttribute("min", boost::lexical_cast(lw.GetRangeMin())); child->SetAttribute("max", boost::lexical_cast(lw.GetRangeMax())); return element; } else return nullptr; } - virtual BaseProperty::Pointer Deserialize(TiXmlElement *element) override + BaseProperty::Pointer Deserialize(TiXmlElement *element) override { if (!element) return nullptr; LocaleSwitch localeSwitch("C"); bool isFixed(false); if (element->Attribute("fixed")) isFixed = std::string(element->Attribute("fixed")) == "true"; bool isFloatingImage(false); if (element->Attribute("isFloatingImage")) isFloatingImage = std::string(element->Attribute("isFloatingImage")) == "true"; std::string level_string; std::string window_string; TiXmlElement *child = element->FirstChildElement("CurrentSettings"); if (child->QueryStringAttribute("level", &level_string) != TIXML_SUCCESS) return nullptr; if (child->QueryStringAttribute("window", &window_string) != TIXML_SUCCESS) return nullptr; std::string defaultLevel_string; std::string defaultWindow_string; child = element->FirstChildElement("DefaultSettings"); if (child->QueryStringAttribute("level", &defaultLevel_string) != TIXML_SUCCESS) return nullptr; if (child->QueryStringAttribute("window", &defaultWindow_string) != TIXML_SUCCESS) return nullptr; std::string minRange_string; std::string maxRange_string; child = element->FirstChildElement("CurrentRange"); if (child->QueryStringAttribute("min", &minRange_string) != TIXML_SUCCESS) return nullptr; if (child->QueryStringAttribute("max", &maxRange_string) != TIXML_SUCCESS) return nullptr; LevelWindow lw; try { lw.SetRangeMinMax(boost::lexical_cast(minRange_string), boost::lexical_cast(maxRange_string)); lw.SetDefaultLevelWindow(boost::lexical_cast(defaultLevel_string), boost::lexical_cast(defaultWindow_string)); lw.SetLevelWindow(boost::lexical_cast(level_string), boost::lexical_cast(window_string)); lw.SetFixed(isFixed); lw.SetFloatingValues(isFloatingImage); } catch (boost::bad_lexical_cast &e) { MITK_ERROR << "Could not parse string as number: " << e.what(); return nullptr; } return LevelWindowProperty::New(lw).GetPointer(); } protected: LevelWindowPropertySerializer() {} - virtual ~LevelWindowPropertySerializer() {} + ~LevelWindowPropertySerializer() override {} }; } // namespace // important to put this into the GLOBAL namespace (because it starts with 'namespace mitk') MITK_REGISTER_SERIALIZER(LevelWindowPropertySerializer); #endif diff --git a/Modules/SceneSerializationBase/src/mitkPoint3dPropertySerializer.cpp b/Modules/SceneSerializationBase/src/mitkPoint3dPropertySerializer.cpp index c63cabf9eb..37f8e416ca 100644 --- a/Modules/SceneSerializationBase/src/mitkPoint3dPropertySerializer.cpp +++ b/Modules/SceneSerializationBase/src/mitkPoint3dPropertySerializer.cpp @@ -1,87 +1,87 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #ifndef mitkPoint3dPropertySerializer_h_included #define mitkPoint3dPropertySerializer_h_included #include "mitkBasePropertySerializer.h" #include "mitkProperties.h" #include "mitkStringsToNumbers.h" #include namespace mitk { class Point3dPropertySerializer : public BasePropertySerializer { public: mitkClassMacro(Point3dPropertySerializer, BasePropertySerializer); itkFactorylessNewMacro(Self) itkCloneMacro(Self) - virtual TiXmlElement *Serialize() override + TiXmlElement *Serialize() override { if (const Point3dProperty *prop = dynamic_cast(m_Property.GetPointer())) { LocaleSwitch localeSwitch("C"); auto element = new TiXmlElement("point"); Point3D point = prop->GetValue(); element->SetAttribute("x", boost::lexical_cast(point[0])); element->SetAttribute("y", boost::lexical_cast(point[1])); element->SetAttribute("z", boost::lexical_cast(point[2])); return element; } else return nullptr; } - virtual BaseProperty::Pointer Deserialize(TiXmlElement *element) override + BaseProperty::Pointer Deserialize(TiXmlElement *element) override { if (!element) return nullptr; LocaleSwitch localeSwitch("C"); std::string v_str[3]; if (element->QueryStringAttribute("x", &v_str[0]) != TIXML_SUCCESS) return nullptr; if (element->QueryStringAttribute("y", &v_str[1]) != TIXML_SUCCESS) return nullptr; if (element->QueryStringAttribute("z", &v_str[2]) != TIXML_SUCCESS) return nullptr; Point3D v; try { StringsToNumbers(3, v_str, v); } catch (boost::bad_lexical_cast &e) { MITK_ERROR << "Could not parse string as number: " << e.what(); return nullptr; } return Point3dProperty::New(v).GetPointer(); } protected: Point3dPropertySerializer() {} - virtual ~Point3dPropertySerializer() {} + ~Point3dPropertySerializer() override {} }; } // namespace // important to put this into the GLOBAL namespace (because it starts with 'namespace mitk') MITK_REGISTER_SERIALIZER(Point3dPropertySerializer); #endif diff --git a/Modules/SceneSerializationBase/src/mitkPoint3iPropertySerializer.cpp b/Modules/SceneSerializationBase/src/mitkPoint3iPropertySerializer.cpp index 01dc5637b4..5f46adb171 100644 --- a/Modules/SceneSerializationBase/src/mitkPoint3iPropertySerializer.cpp +++ b/Modules/SceneSerializationBase/src/mitkPoint3iPropertySerializer.cpp @@ -1,68 +1,68 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #ifndef mitkPoint3iPropertySerializer_h_included #define mitkPoint3iPropertySerializer_h_included #include "mitkBasePropertySerializer.h" #include "mitkProperties.h" namespace mitk { class Point3iPropertySerializer : public BasePropertySerializer { public: mitkClassMacro(Point3iPropertySerializer, BasePropertySerializer); itkFactorylessNewMacro(Self) itkCloneMacro(Self) - virtual TiXmlElement *Serialize() override + TiXmlElement *Serialize() override { if (const Point3iProperty *prop = dynamic_cast(m_Property.GetPointer())) { auto element = new TiXmlElement("point"); Point3I point = prop->GetValue(); element->SetAttribute("x", point[0]); element->SetAttribute("y", point[1]); element->SetAttribute("z", point[2]); return element; } else return nullptr; } - virtual BaseProperty::Pointer Deserialize(TiXmlElement *element) override + BaseProperty::Pointer Deserialize(TiXmlElement *element) override { if (!element) return nullptr; Point3I v; if (element->QueryIntAttribute("x", &v[0]) != TIXML_SUCCESS) return nullptr; if (element->QueryIntAttribute("y", &v[1]) != TIXML_SUCCESS) return nullptr; if (element->QueryIntAttribute("z", &v[2]) != TIXML_SUCCESS) return nullptr; return Point3iProperty::New(v).GetPointer(); } protected: Point3iPropertySerializer() {} - virtual ~Point3iPropertySerializer() {} + ~Point3iPropertySerializer() override {} }; } // namespace // important to put this into the GLOBAL namespace (because it starts with 'namespace mitk') MITK_REGISTER_SERIALIZER(Point3iPropertySerializer); #endif diff --git a/Modules/SceneSerializationBase/src/mitkPoint4dPropertySerializer.cpp b/Modules/SceneSerializationBase/src/mitkPoint4dPropertySerializer.cpp index a6d86bd1cd..2d44ab0a2d 100644 --- a/Modules/SceneSerializationBase/src/mitkPoint4dPropertySerializer.cpp +++ b/Modules/SceneSerializationBase/src/mitkPoint4dPropertySerializer.cpp @@ -1,90 +1,90 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #ifndef mitkPoint4dPropertySerializer_h_included #define mitkPoint4dPropertySerializer_h_included #include "mitkBasePropertySerializer.h" #include "mitkProperties.h" #include "mitkStringsToNumbers.h" #include namespace mitk { class Point4dPropertySerializer : public BasePropertySerializer { public: mitkClassMacro(Point4dPropertySerializer, BasePropertySerializer); itkFactorylessNewMacro(Self) itkCloneMacro(Self) - virtual TiXmlElement *Serialize() override + TiXmlElement *Serialize() override { if (const Point4dProperty *prop = dynamic_cast(m_Property.GetPointer())) { LocaleSwitch localeSwitch("C"); auto element = new TiXmlElement("point"); Point4D point = prop->GetValue(); element->SetAttribute("x", boost::lexical_cast(point[0])); element->SetAttribute("y", boost::lexical_cast(point[1])); element->SetAttribute("z", boost::lexical_cast(point[2])); element->SetAttribute("t", boost::lexical_cast(point[3])); return element; } else return nullptr; } - virtual BaseProperty::Pointer Deserialize(TiXmlElement *element) override + BaseProperty::Pointer Deserialize(TiXmlElement *element) override { if (!element) return nullptr; LocaleSwitch localeSwitch("C"); std::string v_str[4]; if (element->QueryStringAttribute("x", &v_str[0]) != TIXML_SUCCESS) return nullptr; if (element->QueryStringAttribute("y", &v_str[1]) != TIXML_SUCCESS) return nullptr; if (element->QueryStringAttribute("z", &v_str[2]) != TIXML_SUCCESS) return nullptr; if (element->QueryStringAttribute("t", &v_str[3]) != TIXML_SUCCESS) return nullptr; Point4D v; try { StringsToNumbers(4, v_str, v); } catch (boost::bad_lexical_cast &e) { MITK_ERROR << "Could not parse string as number: " << e.what(); return nullptr; } return Point4dProperty::New(v).GetPointer(); } protected: Point4dPropertySerializer() {} - virtual ~Point4dPropertySerializer() {} + ~Point4dPropertySerializer() override {} }; } // namespace // important to put this into the GLOBAL namespace (because it starts with 'namespace mitk') MITK_REGISTER_SERIALIZER(Point4dPropertySerializer); #endif diff --git a/Modules/SceneSerializationBase/src/mitkStringLookupTablePropertySerializer.cpp b/Modules/SceneSerializationBase/src/mitkStringLookupTablePropertySerializer.cpp index 3af77ccab0..558aa1bd72 100644 --- a/Modules/SceneSerializationBase/src/mitkStringLookupTablePropertySerializer.cpp +++ b/Modules/SceneSerializationBase/src/mitkStringLookupTablePropertySerializer.cpp @@ -1,82 +1,82 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #ifndef mitkStringLookupTablePropertySerializer_h_included #define mitkStringLookupTablePropertySerializer_h_included #include "mitkBasePropertySerializer.h" #include "mitkProperties.h" namespace mitk { class StringLookupTablePropertySerializer : public BasePropertySerializer { public: mitkClassMacro(StringLookupTablePropertySerializer, BasePropertySerializer); itkFactorylessNewMacro(Self) itkCloneMacro(Self) - virtual TiXmlElement *Serialize() override + TiXmlElement *Serialize() override { const StringLookupTableProperty *prop = dynamic_cast(m_Property.GetPointer()); if (prop == nullptr) return nullptr; StringLookupTable lut = prop->GetValue(); // if (lut.IsNull()) // return nullptr; // really? const StringLookupTable::LookupTableType &map = lut.GetLookupTable(); auto element = new TiXmlElement("StringLookupTable"); for (auto it = map.begin(); it != map.end(); ++it) { auto tableEntry = new TiXmlElement("LUTValue"); tableEntry->SetAttribute("id", it->first); tableEntry->SetAttribute("value", it->second); element->LinkEndChild(tableEntry); } return element; } - virtual BaseProperty::Pointer Deserialize(TiXmlElement *element) override + BaseProperty::Pointer Deserialize(TiXmlElement *element) override { if (!element) return nullptr; StringLookupTable lut; for (TiXmlElement *child = element->FirstChildElement("LUTValue"); child != nullptr; child = child->NextSiblingElement("LUTValue")) { int temp; if (child->QueryIntAttribute("id", &temp) == TIXML_WRONG_TYPE) return nullptr; // TODO: can we do a better error handling? StringLookupTable::IdentifierType id = static_cast(temp); if (child->Attribute("value") == nullptr) return nullptr; // TODO: can we do a better error handling? StringLookupTable::ValueType val = child->Attribute("value"); lut.SetTableValue(id, val); } return StringLookupTableProperty::New(lut).GetPointer(); } protected: StringLookupTablePropertySerializer() {} - virtual ~StringLookupTablePropertySerializer() {} + ~StringLookupTablePropertySerializer() override {} }; } // namespace // important to put this into the GLOBAL namespace (because it starts with 'namespace mitk') MITK_REGISTER_SERIALIZER(StringLookupTablePropertySerializer); #endif diff --git a/Modules/SceneSerializationBase/src/mitkStringPropertySerializer.cpp b/Modules/SceneSerializationBase/src/mitkStringPropertySerializer.cpp index 0bb42c2d1f..c32b99c6ba 100644 --- a/Modules/SceneSerializationBase/src/mitkStringPropertySerializer.cpp +++ b/Modules/SceneSerializationBase/src/mitkStringPropertySerializer.cpp @@ -1,62 +1,62 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #ifndef mitkStringPropertySerializer_h_included #define mitkStringPropertySerializer_h_included #include "mitkBasePropertySerializer.h" #include "mitkStringProperty.h" namespace mitk { class StringPropertySerializer : public BasePropertySerializer { public: mitkClassMacro(StringPropertySerializer, BasePropertySerializer); itkFactorylessNewMacro(Self) itkCloneMacro(Self) - virtual TiXmlElement *Serialize() override + TiXmlElement *Serialize() override { if (const StringProperty *prop = dynamic_cast(m_Property.GetPointer())) { auto element = new TiXmlElement("string"); element->SetAttribute("value", prop->GetValue()); return element; } else return nullptr; } - virtual BaseProperty::Pointer Deserialize(TiXmlElement *element) override + BaseProperty::Pointer Deserialize(TiXmlElement *element) override { if (!element) return nullptr; const char *s(element->Attribute("value")); return StringProperty::New(std::string(s ? s : "")).GetPointer(); } protected: StringPropertySerializer() {} - virtual ~StringPropertySerializer() {} + ~StringPropertySerializer() override {} }; } // namespace // important to put this into the GLOBAL namespace (because it starts with 'namespace mitk') MITK_REGISTER_SERIALIZER(StringPropertySerializer); #endif diff --git a/Modules/SceneSerializationBase/src/mitkTemporoSpatialStringPropertySerializer.cpp b/Modules/SceneSerializationBase/src/mitkTemporoSpatialStringPropertySerializer.cpp index e30db4802f..77725e1533 100644 --- a/Modules/SceneSerializationBase/src/mitkTemporoSpatialStringPropertySerializer.cpp +++ b/Modules/SceneSerializationBase/src/mitkTemporoSpatialStringPropertySerializer.cpp @@ -1,66 +1,66 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #ifndef mitkTemporoSpatialStringPropertySerializer_h_included #define mitkTemporoSpatialStringPropertySerializer_h_included #include "mitkBasePropertySerializer.h" #include "mitkTemporoSpatialStringProperty.h" namespace mitk { class TemporoSpatialStringPropertySerializer : public BasePropertySerializer { public: mitkClassMacro(TemporoSpatialStringPropertySerializer, BasePropertySerializer); itkFactorylessNewMacro(Self) itkCloneMacro(Self) - virtual TiXmlElement *Serialize() override + TiXmlElement *Serialize() override { if (const TemporoSpatialStringProperty *prop = dynamic_cast(m_Property.GetPointer())) { auto element = new TiXmlElement("temporo_spatial_string"); std::string content = PropertyPersistenceSerialization::serializeTemporoSpatialStringPropertyToJSON(prop); TiXmlText text(content.c_str()); element->InsertEndChild(text); return element; } else return nullptr; } - virtual BaseProperty::Pointer Deserialize(TiXmlElement *element) override + BaseProperty::Pointer Deserialize(TiXmlElement *element) override { if (!element) return nullptr; const char *s(element->GetText()); std::string content = s ? s : ""; return PropertyPersistenceDeserialization::deserializeJSONToTemporoSpatialStringProperty(content); } protected: TemporoSpatialStringPropertySerializer() {} - virtual ~TemporoSpatialStringPropertySerializer() {} + ~TemporoSpatialStringPropertySerializer() override {} }; } // namespace // important to put this into the GLOBAL namespace (because it starts with 'namespace mitk') MITK_REGISTER_SERIALIZER(TemporoSpatialStringPropertySerializer); #endif diff --git a/Modules/SceneSerializationBase/src/mitkUIntPropertySerializer.cpp b/Modules/SceneSerializationBase/src/mitkUIntPropertySerializer.cpp index 3f35e7d68d..2ee23a38df 100644 --- a/Modules/SceneSerializationBase/src/mitkUIntPropertySerializer.cpp +++ b/Modules/SceneSerializationBase/src/mitkUIntPropertySerializer.cpp @@ -1,70 +1,70 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #ifndef mitkUIntPropertySerializer_h_included #define mitkUIntPropertySerializer_h_included #include "mitkBasePropertySerializer.h" #include "mitkProperties.h" namespace mitk { class UIntPropertySerializer : public BasePropertySerializer { public: mitkClassMacro(UIntPropertySerializer, BasePropertySerializer); itkFactorylessNewMacro(Self) itkCloneMacro(Self) - virtual TiXmlElement *Serialize() override + TiXmlElement *Serialize() override { if (const UIntProperty *prop = dynamic_cast(m_Property.GetPointer())) { auto element = new TiXmlElement("unsigned"); element->SetAttribute("value", static_cast(prop->GetValue())); return element; } else return nullptr; } - virtual BaseProperty::Pointer Deserialize(TiXmlElement *element) override + BaseProperty::Pointer Deserialize(TiXmlElement *element) override { if (!element) return nullptr; unsigned int integer; if (element->QueryUnsignedAttribute("value", &integer) == TIXML_SUCCESS) { return UIntProperty::New(integer).GetPointer(); } else { return nullptr; } } protected: UIntPropertySerializer() {} - virtual ~UIntPropertySerializer() {} + ~UIntPropertySerializer() override {} }; } // namespace // important to put this into the GLOBAL namespace (because it starts with 'namespace mitk') MITK_REGISTER_SERIALIZER(UIntPropertySerializer); #endif diff --git a/Modules/SceneSerializationBase/src/mitkUShortPropertySerializer.cpp b/Modules/SceneSerializationBase/src/mitkUShortPropertySerializer.cpp index 68a8b7c4ac..1e4bacfc2d 100644 --- a/Modules/SceneSerializationBase/src/mitkUShortPropertySerializer.cpp +++ b/Modules/SceneSerializationBase/src/mitkUShortPropertySerializer.cpp @@ -1,70 +1,70 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #ifndef mitkUShortPropertySerializer_h_included #define mitkUShortPropertySerializer_h_included #include "mitkBasePropertySerializer.h" #include "mitkProperties.h" namespace mitk { class UShortPropertySerializer : public BasePropertySerializer { public: mitkClassMacro(UShortPropertySerializer, BasePropertySerializer); itkFactorylessNewMacro(Self) itkCloneMacro(Self) - virtual TiXmlElement *Serialize() override + TiXmlElement *Serialize() override { if (const UShortProperty *prop = dynamic_cast(m_Property.GetPointer())) { auto element = new TiXmlElement("unsigned"); element->SetAttribute("value", static_cast(prop->GetValue())); return element; } else return nullptr; } - virtual BaseProperty::Pointer Deserialize(TiXmlElement *element) override + BaseProperty::Pointer Deserialize(TiXmlElement *element) override { if (!element) return nullptr; unsigned int value; if (element->QueryUnsignedAttribute("value", &value) == TIXML_SUCCESS) { return UShortProperty::New(static_cast(value)).GetPointer(); } else { return nullptr; } } protected: UShortPropertySerializer() {} - virtual ~UShortPropertySerializer() {} + ~UShortPropertySerializer() override {} }; } // namespace // important to put this into the GLOBAL namespace (because it starts with 'namespace mitk') MITK_REGISTER_SERIALIZER(UShortPropertySerializer); #endif diff --git a/Modules/SceneSerializationBase/src/mitkVector3DPropertySerializer.cpp b/Modules/SceneSerializationBase/src/mitkVector3DPropertySerializer.cpp index 9b1befcd1e..9c146236a3 100644 --- a/Modules/SceneSerializationBase/src/mitkVector3DPropertySerializer.cpp +++ b/Modules/SceneSerializationBase/src/mitkVector3DPropertySerializer.cpp @@ -1,88 +1,88 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #ifndef mitkVector3DPropertySerializer_h_included #define mitkVector3DPropertySerializer_h_included #include "mitkBasePropertySerializer.h" #include "mitkProperties.h" #include "mitkStringsToNumbers.h" #include namespace mitk { class Vector3DPropertySerializer : public BasePropertySerializer { public: mitkClassMacro(Vector3DPropertySerializer, BasePropertySerializer); itkFactorylessNewMacro(Self) itkCloneMacro(Self) - virtual TiXmlElement *Serialize() override + TiXmlElement *Serialize() override { if (const Vector3DProperty *prop = dynamic_cast(m_Property.GetPointer())) { LocaleSwitch localeSwitch("C"); auto element = new TiXmlElement("vector"); Vector3D point = prop->GetValue(); element->SetAttribute("x", boost::lexical_cast(point[0])); element->SetAttribute("y", boost::lexical_cast(point[1])); element->SetAttribute("z", boost::lexical_cast(point[2])); return element; } else return nullptr; } - virtual BaseProperty::Pointer Deserialize(TiXmlElement *element) override + BaseProperty::Pointer Deserialize(TiXmlElement *element) override { if (!element) return nullptr; LocaleSwitch localeSwitch("C"); std::string v_str[3]; if (element->QueryStringAttribute("x", &v_str[0]) != TIXML_SUCCESS) return nullptr; if (element->QueryStringAttribute("y", &v_str[1]) != TIXML_SUCCESS) return nullptr; if (element->QueryStringAttribute("z", &v_str[2]) != TIXML_SUCCESS) return nullptr; Vector3D v; try { StringsToNumbers(3, v_str, v); } catch (boost::bad_lexical_cast &e) { MITK_ERROR << "Could not parse string '" << v_str << "'as number: " << e.what(); return nullptr; } return Vector3DProperty::New(v).GetPointer(); } protected: Vector3DPropertySerializer() {} - virtual ~Vector3DPropertySerializer() {} + ~Vector3DPropertySerializer() override {} }; } // namespace // important to put this into the GLOBAL namespace (because it starts with 'namespace mitk') MITK_REGISTER_SERIALIZER(Vector3DPropertySerializer); #endif diff --git a/Modules/Segmentation/Testing/mitkFeatureBasedEdgeDetectionFilterTest.cpp b/Modules/Segmentation/Testing/mitkFeatureBasedEdgeDetectionFilterTest.cpp index cce740eb02..3994af96e7 100644 --- a/Modules/Segmentation/Testing/mitkFeatureBasedEdgeDetectionFilterTest.cpp +++ b/Modules/Segmentation/Testing/mitkFeatureBasedEdgeDetectionFilterTest.cpp @@ -1,71 +1,71 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "mitkTestingMacros.h" #include #include #include class mitkFeatureBasedEdgeDetectionFilterTestSuite : public mitk::TestFixture { CPPUNIT_TEST_SUITE(mitkFeatureBasedEdgeDetectionFilterTestSuite); MITK_TEST(testFeatureBasedEdgeDetectionFilterInitialization); MITK_TEST(testInput); MITK_TEST(testUnstructuredGridGeneration); CPPUNIT_TEST_SUITE_END(); private: /** Members used inside the different test methods. All members are initialized via setUp().*/ mitk::Image::Pointer m_Pic3D; mitk::Image::Pointer m_Segmentation; public: /** * @brief Setup Always call this method before each Test-case to ensure correct and new intialization of the used * members for a new test case. (If the members are not used in a test, the method does not need to be called). */ - void setUp() + void setUp() override { m_Pic3D = dynamic_cast(mitk::IOUtil::Load(GetTestDataFilePath("Pic3D.nrrd"))[0].GetPointer()); m_Segmentation = dynamic_cast(mitk::IOUtil::Load(GetTestDataFilePath("PlaneSuggestion/pic3D_segmentation.nrrd"))[0].GetPointer()); } void testFeatureBasedEdgeDetectionFilterInitialization() { mitk::FeatureBasedEdgeDetectionFilter::Pointer testFilter = mitk::FeatureBasedEdgeDetectionFilter::New(); CPPUNIT_ASSERT_MESSAGE("Testing instantiation of test object", testFilter.IsNotNull()); } void testInput() { mitk::FeatureBasedEdgeDetectionFilter::Pointer testFilter = mitk::FeatureBasedEdgeDetectionFilter::New(); testFilter->SetInput(m_Pic3D); CPPUNIT_ASSERT_MESSAGE("Testing set / get input!", testFilter->GetInput() == m_Pic3D); } void testUnstructuredGridGeneration() { mitk::FeatureBasedEdgeDetectionFilter::Pointer testFilter = mitk::FeatureBasedEdgeDetectionFilter::New(); testFilter->SetInput(m_Pic3D); testFilter->SetSegmentationMask(m_Segmentation); testFilter->Update(); CPPUNIT_ASSERT_MESSAGE("Testing surface generation!", testFilter->GetOutput()->GetVtkUnstructuredGrid() != nullptr); } }; MITK_TEST_SUITE_REGISTRATION(mitkFeatureBasedEdgeDetectionFilter) diff --git a/Modules/SurfaceInterpolation/Testing/mitkImageToPointCloudFilterTest.cpp b/Modules/SurfaceInterpolation/Testing/mitkImageToPointCloudFilterTest.cpp index 296d3e4df7..0124bc6e72 100644 --- a/Modules/SurfaceInterpolation/Testing/mitkImageToPointCloudFilterTest.cpp +++ b/Modules/SurfaceInterpolation/Testing/mitkImageToPointCloudFilterTest.cpp @@ -1,82 +1,82 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "mitkTestingMacros.h" #include #include #include class mitkImageToPointCloudFilterTestSuite : public mitk::TestFixture { CPPUNIT_TEST_SUITE(mitkImageToPointCloudFilterTestSuite); MITK_TEST(testImageToPointCloudFilterInitialization); MITK_TEST(testInput); MITK_TEST(testUnstructuredGridGeneration); MITK_TEST(testThreshold); CPPUNIT_TEST_SUITE_END(); private: /** Members used inside the different test methods. All members are initialized via setUp().*/ mitk::Image::Pointer m_BallImage; public: /** * @brief Setup Always call this method before each Test-case to ensure correct and new intialization of the used * members for a new test case. (If the members are not used in a test, the method does not need to be called). */ - void setUp() { m_BallImage = dynamic_cast(mitk::IOUtil::Load(GetTestDataFilePath("BallBinary30x30x30.nrrd"))[0].GetPointer()); } + void setUp() override { m_BallImage = dynamic_cast(mitk::IOUtil::Load(GetTestDataFilePath("BallBinary30x30x30.nrrd"))[0].GetPointer()); } void testImageToPointCloudFilterInitialization() { mitk::ImageToUnstructuredGridFilter::Pointer testFilter = mitk::ImageToUnstructuredGridFilter::New(); CPPUNIT_ASSERT_MESSAGE("Testing instantiation of test object", testFilter.IsNotNull()); } void testInput() { mitk::ImageToPointCloudFilter::Pointer testFilter = mitk::ImageToPointCloudFilter::New(); testFilter->SetInput(m_BallImage); CPPUNIT_ASSERT_MESSAGE("Testing set / get input!", testFilter->GetInput() == m_BallImage); } void testUnstructuredGridGeneration() { mitk::ImageToPointCloudFilter::Pointer testFilter = mitk::ImageToPointCloudFilter::New(); testFilter->SetInput(m_BallImage); testFilter->Update(); CPPUNIT_ASSERT_MESSAGE("Testing UnstructuredGrid generation!", testFilter->GetOutput() != nullptr); } void testThreshold() { mitk::ImageToPointCloudFilter::Pointer testFilter1 = mitk::ImageToPointCloudFilter::New(); testFilter1->SetInput(m_BallImage); testFilter1->Update(); int numberOfPoints1 = testFilter1->GetNumberOfExtractedPoints(); mitk::ImageToPointCloudFilter::Pointer testFilter2 = mitk::ImageToPointCloudFilter::New(); testFilter2->SetInput(m_BallImage); testFilter2->SetMethod(mitk::ImageToPointCloudFilter::LAPLACIAN_STD_DEV3); testFilter2->Update(); int numberOfPoints2 = testFilter2->GetNumberOfExtractedPoints(); CPPUNIT_ASSERT_MESSAGE("Testing Threshold", numberOfPoints1 > numberOfPoints2); } }; MITK_TEST_SUITE_REGISTRATION(mitkImageToPointCloudFilter)