void CSCMatrix::add_from_csr(CSRMatrix *m) { free_data(); this->size = m->get_size(); this->nnz = m->get_nnz(); this->complex = m->is_complex(); // allocate data this->Ap = new int[this->size + 1]; this->Ai = new int[this->nnz]; if (is_complex()) this->Ax_cplx = new cplx[this->nnz]; else this->Ax = new double[this->nnz]; if (is_complex()) { csr_to_csc(this->size, this->nnz, m->get_Ap(), m->get_Ai(), m->get_Ax_cplx(), Ap, Ai, Ax_cplx); } else { csr_to_csc(this->size, this->nnz, m->get_Ap(), m->get_Ai(), m->get_Ax(), Ap, Ai, Ax); } }
void CooMatrix::print() { printf("\nCoo Matrix:\n"); if (is_complex()) { for(std::map<size_t, std::map<size_t, cplx> >::const_iterator it_row = A_cplx.begin(); it_row != A_cplx.end(); ++it_row) { for(std::map<size_t, cplx>::const_iterator it_col = it_row->second.begin(); it_col != it_row->second.end(); ++it_col) { printf("(%u, %u): (%g, %g)\n", (unsigned int)it_row->first, (unsigned int)it_col->first, ((cplx) it_col->second).real(), ((cplx) it_col->second).imag()); } } } else { for(std::map<size_t, std::map<size_t, double> >::const_iterator it_row = A.begin(); it_row != A.end(); ++it_row) { for(std::map<size_t, double>::const_iterator it_col = it_row->second.begin(); it_col != it_row->second.end(); ++it_col) { printf("(%u, %u): %g\n", (unsigned int)it_row->first, (unsigned int)it_col->first, it_col->second); } } } }
void CooMatrix::add_from_csc(CSCMatrix *m) { free_data(); this->complex = m->is_complex(); int *Ap = m->get_Ap(); int *Ai = m->get_Ai(); double *Ax = m->get_Ax(); cplx *Ax_cplx = m->get_Ax_cplx(); int count = 0; // loop through columns... for (int i = 1; i <= m->get_size(); i++) { for (int j = count; j < Ap[i]; j++) { if (is_complex()) add(Ai[count], i-1, Ax_cplx[count]); else add(Ai[count], i-1, Ax[count]); count++; } } }
/* This may be ultimately confused with nested types with 2 components called 'r' and 'i' and being floats, but in that case, the user most probably wanted to keep a complex type, so getting a complex instead of a nested type should not be a big issue (I hope!) :-/ F. Alted 2005-05-23 */ int is_complex(hid_t type_id) { hid_t class_id, base_type_id; hid_t class1, class2; char *colname1, *colname2; int result = 0; hsize_t nfields; class_id = H5Tget_class(type_id); if (class_id == H5T_COMPOUND) { nfields = H5Tget_nmembers(type_id); if (nfields == 2) { colname1 = H5Tget_member_name(type_id, 0); colname2 = H5Tget_member_name(type_id, 1); if ((strcmp(colname1, "r") == 0) && (strcmp(colname2, "i") == 0)) { class1 = H5Tget_member_class(type_id, 0); class2 = H5Tget_member_class(type_id, 1); if (class1 == H5T_FLOAT && class2 == H5T_FLOAT) result = 1; } free(colname1); free(colname2); } } /* Is an Array of Complex? */ else if (class_id == H5T_ARRAY) { /* Get the array base component */ base_type_id = H5Tget_super(type_id); /* Call is_complex again */ result = is_complex(base_type_id); H5Tclose(base_type_id); } return result; }
/* This is actually an extension of H5Tget_order to handle complex types */ herr_t get_order(hid_t type_id, char *byteorder) { H5T_order_t h5byteorder; /* hid_t class_id; class_id = H5Tget_class(type_id); */ if (is_complex(type_id)) { h5byteorder = get_complex_order(type_id); } else { h5byteorder = H5Tget_order(type_id); } if (h5byteorder == H5T_ORDER_LE) { strcpy(byteorder, "little"); return h5byteorder; } else if (h5byteorder == H5T_ORDER_BE ) { strcpy(byteorder, "big"); return h5byteorder; } else if (h5byteorder == H5T_ORDER_NONE ) { strcpy(byteorder, "irrelevant"); return h5byteorder; } else { /* This should never happen! */ fprintf(stderr, "Error: unsupported byteorder <%d>\n", h5byteorder); strcpy(byteorder, "unsupported"); return -1; } }
/** * @brief Eigenvalue decomposition * * Usage: * @code{.cpp} * Matrix<cxfl> m = rand<cxfl> (10,10), ev; * Matrix<float> lv, rv; * boost::tuple<Matrix<float>,Matrix<cxfl>,Matrix<float>> ler * ler = eig2 (m); * lv = boost::get<0>(ler) * ev = boost::get<1>(ler); * rv = boost::get<2>(ler) * @endcode * where m is the complex decomposed matrix, lv and rv are the left hand and right * hand side eigen vectors and ev is the eigenvalue vector. * * @see LAPACK driver xGEEV * * @param m Matrix for decomposition * @param jobvl Compute left vectors ('N'/'V') * @param jobvr Compute right vectors ('N'/'V') * @return Eigenvectors and values */ template <class T, class S> inline boost::tuple< Matrix<T>, Matrix<S>, Matrix<T> > eig2 (const Matrix<T>& m, char jobvl = 'N', char jobvr = 'N') { typedef typename LapackTraits<T>::RType T2; T t; boost::tuple< Matrix<T>, Matrix<S>, Matrix<T> > ret; assert (jobvl == 'N' || jobvl =='V'); assert (jobvr == 'N' || jobvr =='V'); assert (issquare(m)); int N = size(m, 0); int lda = N; int ldvl = (jobvl == 'V') ? N : 1; int ldvr = (jobvr == 'V') ? N : 1; int info = 0; int lwork = -1; // Appropriately resize the output boost::get<1>(ret) = Matrix<S>(N,1); if (jobvl == 'V') boost::get<0>(ret) = Matrix<T>(N,N); if (jobvr == 'V') boost::get<2>(ret) = Matrix<T>(N,N); Matrix<S>& ev = boost::get<1>(ret); Matrix<T> &lv = boost::get<0>(ret), &rv = boost::get<2>(ret); // Workspace for real numbers container<T2> rwork = (is_complex(t)) ? container<T2>(2*N) : container<T2>(1); // Workspace for complex numbers container<T> work = container<T>(1); // Need copy. Lapack destroys A on output. Matrix<T> a = m; // Work space query LapackTraits<T>::geev (jobvl, jobvr, N, &a[0], lda, &ev[0], &lv[0], ldvl, &rv[0], ldvr, &work[0], lwork, &rwork[0], info); // Initialize work space lwork = (int) TypeTraits<T>::Real (work[0]); work.resize(lwork); // Actual Eigenvalue computation LapackTraits<T>::geev (jobvl, jobvr, N, &a[0], lda, &ev[0], &lv[0], ldvl, &rv[0], ldvr, &work[0], lwork, &rwork[0], info); if (info > 0) { printf ("\nERROR - XGEEV: the QR algorithm failed to compute all the\n eigenvalues, and no eigenvectors have " \ "been computed;\n elements %d+1:N of ev contain eigenvalues which\n have converged.\n\n", info) ; } else if (info < 0) printf ("\nERROR - XGEEV: the %d-th argument had an illegal value.\n\n", -info); return ret; }
static Lisp_Object Lrealpart(Lisp_Object nil, Lisp_Object a) { CSL_IGNORE(nil); if (!is_number(a)) return aerror1("realpart", a); if (is_numbers(a) && is_complex(a)) return onevalue(real_part(a)); else return onevalue(a); }
static Lisp_Object Limagpart(Lisp_Object nil, Lisp_Object a) { CSL_IGNORE(nil); if (!is_number(a)) return aerror1("imagpart", a); if (is_numbers(a) && is_complex(a)) return onevalue(imag_part(a)); /* /* the 0.0 returned here ought to be the same type as a has */ else return onevalue(fixnum_of_int(0)); }
void CSCMatrix::add_from_dense(DenseMatrix *m) { free_data(); this->size = m->get_size(); this->nnz = m->get_nnz(); this->complex = m->is_complex(); // allocate data this->Ap = new int[this->size + 1]; this->Ai = new int[this->nnz]; if (is_complex()) this->Ax_cplx = new cplx[this->nnz]; else this->Ax = new double[this->nnz]; // get data int *row = new int[this->nnz]; int *col = new int[this->nnz]; if (is_complex()) { cplx *data = new cplx[this->nnz]; dense_to_coo(size, nnz, m->get_A_cplx(), row, col, data); coo_to_csc(this->size, this->nnz, row, col, data, Ap, Ai, Ax_cplx); if (data != NULL) delete[] data; } else { double *data = new double[this->nnz]; dense_to_coo(size, nnz, m->get_A(), row, col, data); print_vector("row", row, this->nnz); print_vector("col", col, this->nnz); print_vector("Ax", data, this->nnz); coo_to_csc(this->size, this->nnz, row, col, data, Ap, Ai, Ax); if (data != NULL) delete[] data; } // free data if (row != NULL) delete[] row; if (col != NULL) delete[] col; }
void CSCMatrix::print() { printf("\nCSC Matrix:\n"); printf("size: %i\n", this->size); printf("nzz: %i\n", this->nnz); print_vector("col_ptr", this->Ap, this->size+1); print_vector("row_ind", this->Ai, this->nnz); if (is_complex()) print_vector("data", this->Ax_cplx, this->nnz); else print_vector("data", this->Ax, this->nnz); }
void CSCMatrix::add_from_coo(CooMatrix *m) { free_data(); this->size = m->get_size(); this->nnz = m->get_nnz(); this->complex = m->is_complex(); // allocate data this->Ap = new int[this->size + 1]; this->Ai = new int[this->nnz]; if (is_complex()) this->Ax_cplx = new cplx[this->nnz]; else this->Ax = new double[this->nnz]; // get data int *row = new int[this->nnz]; int *col = new int[this->nnz]; if (is_complex()) { cplx *data = new cplx[this->nnz]; m->get_row_col_data(row, col, data); coo_to_csc(this->size, this->nnz, row, col, data, Ap, Ai, Ax_cplx); if (data != NULL) delete[] data; } else { double *data = new double[this->nnz]; m->get_row_col_data(row, col, data); coo_to_csc(this->size, this->nnz, row, col, data, Ap, Ai, Ax); if (data != NULL) delete[] data; } // free data if (row != NULL) delete[] row; if (col != NULL) delete[] col; }
static Lisp_Object Lconjugate(Lisp_Object nil, Lisp_Object a) { if (!is_number(a)) return aerror1("conjugate", a); if (is_numbers(a) && is_complex(a)) { Lisp_Object r = real_part(a), i = imag_part(a); push(r); i = negate(i); pop(r); errexit(); a = make_complex(r, i); errexit(); return onevalue(a); } else return onevalue(a); }
/* This only works for datatypes that are not Complex. However, these types should already been created with correct byteorder */ herr_t set_order(hid_t type_id, const char *byteorder) { herr_t status=0; if (! is_complex(type_id)) { if (strcmp(byteorder, "little") == 0) status = H5Tset_order(type_id, H5T_ORDER_LE); else if (strcmp(byteorder, "big") == 0) status = H5Tset_order(type_id, H5T_ORDER_BE); else if (strcmp(byteorder, "irrelevant") == 0) { /* Do nothing because 'irrelevant' doesn't require setting the byteorder explicitely */ /* status = H5Tset_order(type_id, H5T_ORDER_NONE ); */ } else { fprintf(stderr, "Error: unsupported byteorder <%s>\n", byteorder); status = -1; } } return status; }
template<class T> Matrix<T> Read (const std::string& uri) const { T t; DataSet dataset = m_file.openDataSet(uri); DataSpace space = dataset.getSpace(); std::vector<hsize_t> dims (space.getSimpleExtentNdims()); size_t ndim = space.getSimpleExtentDims(&dims[0], NULL); if (this->m_verb) { printf ("Reading dataset %s ... ", uri.c_str()); fflush(stdout); } if (is_complex(t)) { dims.pop_back(); --ndim; } std::vector<size_t> mdims (ndim,1); for (size_t i = 0; i < ndim; ++i) mdims[i] = dims[ndim-i-1]; PredType* type = HDF5Traits<T>::PType(); Matrix<T> M (mdims); dataset.read (&M[0], *type); if (this->m_verb) printf ("O(%s) done\n", DimsToCString(M)); space.close(); dataset.close(); return M; }
CSLbool onep(Lisp_Object a) { switch ((int)a & TAG_BITS) { case TAG_FIXNUM: return (a == fixnum_of_int(1)); case TAG_NUMBERS: /* #C(r i) must satisfy onep(r) and zerop(i) */ if (is_complex(a) && onep(real_part(a))) return zerop(imag_part(a)); else return NO; case TAG_SFLOAT: { Float_union w; w.f = (float)1.0; return (a == (w.i & ~(int32_t)0xf) + TAG_SFLOAT); } case TAG_BOXFLOAT: return (float_of_number(a) == 1.0); default: return NO; } }
CSLbool zerop(Lisp_Object a) { switch ((int)a & TAG_BITS) { case TAG_FIXNUM: return (a == fixnum_of_int(0)); case TAG_NUMBERS: /* #C(r i) must satisfy zerop is r and i both do */ if (is_complex(a) && zerop(real_part(a))) return zerop(imag_part(a)); else return NO; case TAG_SFLOAT: /* * The code here assumes that the the floating point number zero * is represented by a zero bit-pattern... see onep() for a more * cautious way of coding things. */ return ((a & 0x7ffffff8) == 0); /* Strip sign bit as well as tags */ case TAG_BOXFLOAT: return (float_of_number(a) == 0.0); default: return NO; } }
void PrinterFile::Implementation::print_entry (const Frame& frame, const Frame *const super, const symbol key, int indent, bool need_wrapper) { daisy_assert (frame.check (key)); Attribute::type type = frame.lookup (key); const bool do_wrap = (need_wrapper && is_complex (frame, super, key)); if (do_wrap) { out << "("; indent++; } if (frame.type_size (key) == Attribute::Singleton) { switch (type) { case Attribute::Number: out << frame.number (key); print_dimension (frame, key, frame.dimension (key)); break; case Attribute::Submodel: if (super && super->check (key)) print_alist (frame.submodel (key), &super->submodel (key), indent, false); else print_alist (frame.submodel (key), frame.default_frame (key).get (), indent, false); break; case Attribute::PLF: print_plf (frame.plf (key), indent); break; case Attribute::Boolean: print_bool (frame.flag (key)); break; case Attribute::String: print_symbol (frame.name (key)); break; case Attribute::Integer: out << frame.integer (key); break; case Attribute::Model: { const symbol component = frame.component (key); const Library& library = metalib.library (component); if (super && super->check (key)) print_object (frame.model (key), library, &super->model (key), indent); else print_object (frame.model (key), library, NULL, indent); } break; case Attribute::Scalar: case Attribute::Reference: case Attribute::Error: default: out << "<Unknown: " << Attribute::type_name (frame.lookup (key)) << ">"; } } else { switch (type) { case Attribute::Number: { const std::vector<double>& value = frame.number_sequence (key); for (unsigned int i = 0; i < value.size (); i++) { if (i > 0) out << " "; out << value[i]; } print_dimension (frame, key, frame.dimension (key)); } break; case Attribute::Submodel: { const FrameSubmodel& other = *frame.default_frame (key); const std::vector<boost::shared_ptr<const FrameSubmodel>/**/>& value = frame.submodel_sequence (key); for (unsigned int i = 0; i < value.size (); i++) { if (i > 0) out << "\n" << std::string (indent, ' '); out << "("; print_alist (*value[i], &other, indent + 1, false); out << ")"; } } break; case Attribute::PLF: { const std::vector<boost::shared_ptr<const PLF>/**/>& value = frame.plf_sequence (key); for (unsigned int i = 0; i < value.size (); i++) { if (i > 0) out << "\n" << std::string (indent, ' '); out << "("; print_plf (*value[i], indent + 1); out << ")"; } } break; case Attribute::Boolean: { const std::vector<bool>& value = frame.flag_sequence (key); for (unsigned int i = 0; i < value.size (); i++) { if (i > 0) out << " "; print_bool (value[i]); } } break; case Attribute::String: { const std::vector<symbol>& value = frame.name_sequence (key); for (unsigned int i = 0; i < value.size (); i++) { if (i > 0) out << " "; print_symbol (value[i]); } } break; case Attribute::Integer: { const std::vector<int>& value = frame.integer_sequence (key); for (unsigned int i = 0; i < value.size (); i++) { if (i > 0) out << " "; out << value[i]; } } break; case Attribute::Model: { const symbol component = frame.component (key); const Library& library = metalib.library (component); const std::vector<boost::shared_ptr<const FrameModel>/**/>& value = frame.model_sequence (key); // We really should check original value. const std::vector<boost::shared_ptr<const FrameModel>/**/>& super_value = (super && super->check (key)) ? super->model_sequence (key) : std::vector<boost::shared_ptr<const FrameModel>/**/> (); for (unsigned int i = 0; i < value.size (); i++) { const FrameModel& me = *value[i]; const FrameModel* other = super_value.size () > i ? super_value[i].get () : NULL; if (i > 0) out << "\n" << std::string (indent, ' '); if ((other && me.subset (metalib, *other)) || !is_complex_object (me, library)) print_object (me, library, other, indent); else { out << "("; print_object (me, library, other, indent + 1); out << ")"; } } } break; case Attribute::Scalar: case Attribute::Reference: case Attribute::Error: default: out << "<" << Attribute::type_name (frame.lookup (key)) << " sequence>"; } } if (do_wrap) { out << ")"; } }
void PrinterFile::Implementation::print_alist (const Frame& frame, const Frame *const super, int indent, bool skip) { // Always print ordered items. const std::vector<symbol>& order = frame.order (); bool complex_printing = false; for (unsigned int i = 0; i < order.size (); i++) { const symbol key = order[i]; if (!complex_printing && is_complex (frame, super, key)) complex_printing = true; if (!skip) skip = true; else if (complex_printing) out << "\n" << std::string (indent, ' '); else out << " "; if (frame.check (key)) { #if 0 // Design bug: We usually need to put parentheses around // ordered complex values. However, the parser doesn't // expect these for alist sequences, so we don't print them // either. if (frame.lookup (key) == Attribute::Submodel && frame.type_size (key) != Attribute::Singleton) print_entry (frame, super, key, indent, false); else #endif print_entry (frame, super, key, indent, true); } else if (!frame.is_optional (key)) out << "<missing " << key << ">"; } // Print unordered items. std::set<symbol> entries; frame.entries (entries); // Print new declarations. std::set<symbol> super_set; if (super) super->entries (super_set); for (std::set<symbol>::const_iterator i = entries.begin (); i != entries.end (); i++) { const symbol key = *i; // Skip already printed members. if (frame.order_index (key) >= 0) continue; // Declare new members. if (super_set.find (key) == super_set.end ()) { if (!skip) skip = true; else out << "\n" << std::string (indent, ' '); out << "(declare " << key << " "; const int size = frame.type_size (key); if (size == Attribute::Singleton) /* do nothing */; else if (size == Attribute::Variable) out << "[] "; else out << "[" << size << "] "; const Attribute::type type = frame.lookup (key); switch (type) { case Attribute::Boolean: case Attribute::String: case Attribute::Integer: out << Attribute::type_name (type); break; case Attribute::Number: out << Attribute::type_name (type) << " "; print_dimension (frame, key, frame.dimension (key)); break; case Attribute::Submodel: out << "fixed " << frame.submodel_name (key); break; case Attribute::Model: out << frame.component (key); break; case Attribute::PLF: case Attribute::Scalar: case Attribute::Reference: case Attribute::Error: default: out << "<Error>"; } out << "\n " << std::string (indent, ' '); print_symbol (frame.description (key)); out << ")"; } // Skip subset members. if (super && frame.subset (metalib, *super, key)) continue; if (!skip) skip = true; else out << "\n" << std::string (indent, ' '); // Now print it. out << "(" << key << " "; print_entry (frame, super, key, indent + key.name ().length () + 2, false); out << ")"; } }
int main(int argc, char **argv) { args::ArgumentParser parser("Generates masks in stages.\n" "Stage 1 - Otsu thresholding to generate binary mask\n" "Stage 2 - RATs (optional)\n" "Stage 3 - Hole filling (optional)\n" "http://github.com/spinicist/QUIT"); args::Positional<std::string> input_path(parser, "INPUT_FILE", "Input file"); args::HelpFlag help(parser, "HELP", "Show this help menu", {'h', "help"}); args::Flag verbose(parser, "VERBOSE", "Print more information", {'v', "verbose"}); args::ValueFlag<std::string> outarg( parser, "OUTPUT FILE", "Set output filename, default is input + _mask", {'o', "out"}); args::ValueFlag<int> volume( parser, "VOLUME", "Choose volume to mask in multi-volume file. Default 1, -1 selects last volume", {'v', "volume"}, 0); args::Flag is_complex(parser, "COMPLEX", "Input data is complex, take magnitude first", {'x', "complex"}); args::ValueFlag<float> lower_threshold( parser, "LOWER THRESHOLD", "Specify lower intensity threshold for 1st stage, otherwise Otsu's method is used", {'l', "lower"}, 0.); args::ValueFlag<float> upper_threshold( parser, "UPPER THRESHOLD", "Specify upper intensity threshold for 1st stage, otherwise Otsu's method is used", {'u', "upper"}, std::numeric_limits<float>::infinity()); args::ValueFlag<float> rats( parser, "RATS", "Perform the RATS step, argument is size threshold for connected component", {'r', "rats"}, 0.); args::ValueFlag<int> fillh_radius( parser, "FILL HOLES", "Fill holes in thresholded mask with radius N", {'F', "fillh"}, 0); QI::ParseArgs(parser, argc, argv, verbose); QI::SeriesF::Pointer vols = ITK_NULLPTR; if (is_complex) { vols = QI::ReadMagnitudeImage<QI::SeriesF>(QI::CheckPos(input_path), verbose); } else { vols = QI::ReadImage<QI::SeriesF>(QI::CheckPos(input_path), verbose); } std::string out_path; if (outarg.Get() == "") { out_path = QI::StripExt(input_path.Get()) + "_mask" + QI::OutExt(); } else { out_path = outarg.Get(); } // Extract one volume to process auto region = vols->GetLargestPossibleRegion(); if (static_cast<size_t>(std::abs(volume.Get())) < region.GetSize()[3]) { int volume_to_get = (region.GetSize()[3] + volume.Get()) % region.GetSize()[3]; QI::Log(verbose, "Masking volume {}...", volume_to_get); region.GetModifiableIndex()[3] = volume_to_get; } else { QI::Fail("Specified mask volume was invalid {} ", volume.Get()); } region.GetModifiableSize()[3] = 0; auto vol = itk::ExtractImageFilter<QI::SeriesF, QI::VolumeF>::New(); vol->SetExtractionRegion(region); vol->SetInput(vols); vol->SetDirectionCollapseToSubmatrix(); vol->Update(); QI::VolumeF::Pointer intensity_image = vol->GetOutput(); intensity_image->DisconnectPipeline(); /* * Stage 1 - Otsu or Threshold */ QI::VolumeI::Pointer mask_image = ITK_NULLPTR; if (lower_threshold || upper_threshold) { QI::Log(verbose, "Thresholding range: {}-{}", lower_threshold.Get(), upper_threshold.Get()); mask_image = QI::ThresholdMask(intensity_image, lower_threshold.Get(), upper_threshold.Get()); } else { QI::Log(verbose, "Generating Otsu mask"); mask_image = QI::OtsuMask(intensity_image); } /* * Stage 2 - RATS */ if (rats) { typedef itk::BinaryBallStructuringElement<int, 3> TBall; typedef itk::BinaryErodeImageFilter<QI::VolumeI, QI::VolumeI, TBall> TErode; typedef itk::BinaryDilateImageFilter<QI::VolumeI, QI::VolumeI, TBall> TDilate; float mask_volume = std::numeric_limits<float>::infinity(); float voxel_volume = QI::VoxelVolume(mask_image); QI::Log(verbose, "Voxel volume: {}", voxel_volume); int radius = 0; QI::VolumeI::Pointer mask_rats; while (mask_volume > rats.Get()) { radius++; TBall ball; TBall::SizeType radii; radii.Fill(radius); ball.SetRadius(radii); ball.CreateStructuringElement(); TErode::Pointer erode = TErode::New(); erode->SetInput(mask_image); erode->SetForegroundValue(1); erode->SetBackgroundValue(0); erode->SetKernel(ball); erode->Update(); std::vector<float> kept_sizes = QI::FindLabels(erode->GetOutput(), 0, 1, mask_rats); mask_volume = kept_sizes[0] * voxel_volume; auto dilate = TDilate::New(); dilate->SetKernel(ball); dilate->SetInput(mask_rats); dilate->SetForegroundValue(1); dilate->SetBackgroundValue(0); dilate->Update(); mask_rats = dilate->GetOutput(); mask_rats->DisconnectPipeline(); QI::Log(verbose, "Ran RATS iteration, radius = {} volume = {}", radius, mask_volume); } mask_image = mask_rats; } /* * Stage 3 - Hole Filling */ QI::VolumeI::Pointer finalMask = ITK_NULLPTR; if (fillh_radius) { QI::Log(verbose, "Filling holes"); auto fillHoles = itk::VotingBinaryIterativeHoleFillingImageFilter<QI::VolumeI>::New(); itk::VotingBinaryIterativeHoleFillingImageFilter<QI::VolumeI>::InputSizeType radius; radius.Fill(fillh_radius.Get()); fillHoles->SetInput(mask_image); fillHoles->SetRadius(radius); fillHoles->SetMajorityThreshold(2); // Corresponds to (rad^3-1)/2 + 2 threshold fillHoles->SetBackgroundValue(0); fillHoles->SetForegroundValue(1); fillHoles->SetMaximumNumberOfIterations(3); fillHoles->Update(); mask_image = fillHoles->GetOutput(); mask_image->DisconnectPipeline(); } QI::WriteImage(mask_image, out_path, verbose); QI::Log(verbose, "Finished."); return EXIT_SUCCESS; }
template<class T> bool Write (const Matrix<T>& M, const std::string& uri) { T t; Group group, *tmp; std::string path; boost::tokenizer<> tok(uri); std::vector<std::string> sv (Split (uri, "/")); std::string name = sv[sv.size() - 1]; sv.pop_back(); // data name not part of path if (sv.size() == 0) path = "/"; else for (size_t i = 0; i < sv.size(); i++) { if (sv[i].compare("")) path += "/"; path += sv[i]; } if (this->m_verb) printf ("Creating dataset %s at path (%s)\n", name.c_str(), path.c_str()); try { group = m_file.openGroup(path); if (this->m_verb) printf ("Group %s opened for writing\n", path.c_str()) ; } catch (const Exception& e) { for (size_t i = 0, depth = 0; i < sv.size(); i++) { if (sv[i].compare("")) { try { group = (depth) ? (*tmp).openGroup(sv[i]) : m_file.openGroup(sv[i]); } catch (const Exception& e) { group = (depth) ? (*tmp).createGroup(sv[i]) : m_file.createGroup(sv[i]); } tmp = &group; depth++; } } } // One more field for complex numbers size_t tmpdim = ndims(M); std::vector<hsize_t> dims (tmpdim); for (size_t i = 0; i < tmpdim; i++) dims[i] = M.Dim(tmpdim-1-i); if (is_complex(t)) { dims.push_back(2); tmpdim++; } DataSpace space (tmpdim, &dims[0]); PredType* type = HDF5Traits<T>::PType(); DataSet set = group.createDataSet(name, (*type), space); set.write (M.Ptr(), (*type)); set.close (); space.close (); return true; }