Exemplo n.º 1
0
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);
    }
}
Exemplo n.º 2
0
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);
            }
        }
    }
}
Exemplo n.º 3
0
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++;
        }
    }
}
Exemplo n.º 4
0
/* 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;
}
Exemplo n.º 5
0
/* 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;
  }
}
Exemplo n.º 6
0
/**
 * @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;
	
}
Exemplo n.º 7
0
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);
}
Exemplo n.º 8
0
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));
}
Exemplo n.º 9
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;
}
Exemplo n.º 10
0
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);
}
Exemplo n.º 11
0
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;
}
Exemplo n.º 12
0
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);
}
Exemplo n.º 13
0
/* 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;
}
Exemplo n.º 14
0
		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;

		}
Exemplo n.º 15
0
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;
    }
}
Exemplo n.º 16
0
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;
    }
}
Exemplo n.º 17
0
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 << ")";
    }
}
Exemplo n.º 18
0
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 << ")";
    }
}
Exemplo n.º 19
0
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;
}
Exemplo n.º 20
0
		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;

		}