text:
//  Copyright (c) 2006-2009, Bernhard Reiter
//
//  Distributed under the Boost Software License, Version 1.0.
//  (See accompanying file LICENSE_1_0.txt or copy at
//  http://www.boost.org/LICENSE_1_0.txt)

/**
 * @file nary_cursor.hpp
 * Nary cursor implementation
 */

#ifndef BOOST_TREE_DETAIL_NARY_CURSOR_HPP
#define BOOST_TREE_DETAIL_NARY_CURSOR_HPP

#include <boost/tree/cursor.hpp>
#include <boost/tree/cursor_adaptor.hpp>
#include <boost/tree/detail/nary_node.hpp>

#include <boost/mpl/eval_if.hpp>
#include <boost/mpl/identity.hpp>
#include <boost/type_traits/is_const.hpp>
#include <boost/type_traits/add_const.hpp>
#include <boost/type_traits/add_pointer.hpp>

namespace boost {
namespace tree {
namespace detail {

using boost::iterator_core_access;
using boost::tree::cursor_core_access;

template <class Node>
class ascending_nary_cursor
 : public cursor_adaptor<ascending_nary_cursor<Node>
      , typename mpl::eval_if<
                        is_const<Node>
                      , add_const<typename Node::node_base>
                      , mpl::identity<typename Node::node_base>
                    >::type*
      , typename mpl::eval_if<
                    is_const<Node>
                  , add_const<typename Node::value_type>
                  , mpl::identity<typename Node::value_type>
                >::type
      , random_access_traversal_tag
      , ascending_vertical_traversal_tag
    > {

private:
    struct enabler {};

    typedef Node node_type;
    typedef node_type* node_pointer;

    typedef typename mpl::eval_if<
                        is_const<Node>
                      , add_const<typename Node::node_base>
                      , mpl::identity<typename Node::node_base>
                    >::type node_base_type;

public:
    typedef typename mpl::eval_if<
                        is_const<Node>
                       , add_const<typename Node::value_type>
                       , mpl::identity<typename Node::value_type>
                    >::type value_type;

    // Container-specific:
    typedef typename ascending_nary_cursor::cursor_adaptor_::size_type size_type;

    // Cursor-specific
    typedef ascending_nary_cursor<node_type> cursor;
    typedef ascending_nary_cursor<node_type const> const_cursor;
    typedef std::size_t subtree_size_type;

    // Container-specific:
    typedef cursor iterator;
    typedef const_cursor const_iterator;

    template <class OtherValue>
    struct rebind {
        typedef ascending_nary_cursor<OtherValue> other;
    };

    ascending_nary_cursor()
      : ascending_nary_cursor::cursor_adaptor_(0), m_pos(0) {}

    explicit ascending_nary_cursor(node_base_type* p, size_type pos)
    : ascending_nary_cursor::cursor_adaptor_(p), m_pos(pos) {}

    template <class OtherNode>
    ascending_nary_cursor(
        ascending_nary_cursor<OtherNode> const& other
      , typename boost::enable_if<
            boost::is_convertible<typename OtherNode::value_type*, value_type*>
          , enabler
        >::type = enabler()
    )
    : ascending_nary_cursor::cursor_adaptor_(other.base()), m_pos(other.m_pos) {}

private:
    size_type m_pos;

    friend class iterator_core_access;
    friend class cursor_core_access;

    friend class access_detach;

    value_type& dereference() const
    {
        return **static_cast<node_type*>(this->base_reference()->m_children[m_pos]);
    }

    bool equal(cursor const& other) const
    {
        return (this->base_reference() == other.base_reference()) && (this->m_pos == other.m_pos);
    }

    void increment()
    {
        ++m_pos;
        // this->base_reference() += sizeof(node_type);
    }

    void decrement()
    {
        --m_pos;
        //this->base_reference() -= sizeof(node_type);
    }

    void advance(typename ascending_nary_cursor::cursor_facade_::difference_type n)
    {
        m_pos += n;
        //this->base_reference() += n * sizeof(node_type);
    }

    typename ascending_nary_cursor::cursor_facade_::difference_type
    distance_to(ascending_nary_cursor z) const //FIXME: convertible to instead of ascending_nary_cursor
    {
        return (z.m_pos - this->m_pos);
        //return (z.base_reference() - this->base_reference()) / sizeof(node_type);
    }

    // Container specific
    bool empty_() const
    {
        return //this->base_reference()->m_children[m_pos] == node_type::nil() ||
        this->base_reference()->m_children[m_pos] == 0; //->is_leaf()
        //return this->base_reference()->get_index();
    }

    size_type size_() const
    {
        return this->base_reference()->m_children.size();
    }

    size_type max_size_() const
    {
        return this->base_reference()->m_children.max_size();
    }

    size_type idx() const
    {
        return m_pos;
        //return
    }

    void left()
    {
        this->base_reference() =
            static_cast<node_base_type*>(this->base_reference()->m_children[m_pos]);
        m_pos  = 0;
        //this->base_reference() = this->base_reference()->operator[0];
    }

    void right()
    {
        size_type new_pos = this->base_reference()->m_children.size()-1;
        this->base_reference() =
            static_cast<node_base_type*>(this->base_reference()->m_children[m_pos]);
        m_pos  = new_pos;
        //this->base_reference() = this->base_reference()->operator[0];
    }

    // Cursor stuff
    void up()
    {
        m_pos  = this->base_reference()->get_index();
        this->base_reference() = static_cast<node_base_type*>(this->base_reference()->parent());
        //this->base_reference() = this->base_reference()->parent();
    }

//protected:
public:
    bool is_on_top() const
    {
        node_base_type* parent_begin_node =
            static_cast<node_base_type*>(
            static_cast<node_base_type*>(this->base_reference()->parent())
            ->m_children[this->base_reference()->get_index()]);
        return (!m_pos && (this->base_reference() != parent_begin_node));
        // (*this != this->parent().begin())
    }

    node_base_type* const& parent_node() const
    {
        return this->base_reference();
    }

    node_base_type*& parent_node()
    {
        return this->base_reference();
    }

    typename node_base_type::descending_node_base* const& child_node() const
    {
        return this->base_reference()->m_children[m_pos];
    }

    typename node_base_type::descending_node_base*& child_node()
    {
        return this->base_reference()->m_children[m_pos];
    }

//    /**
//     * Detaches the node this cursor points to and returns a pointer to it;
//     * this cursor will be set to its inorder successor afterwards (?)
//     */
//    node_pointer detach()
//    {
//        return static_cast<node_pointer>(m_node->detach(m_pos));
//    }
//
//    node_pointer detach(cursor y)
//    {
//        return static_cast<node_pointer>(m_node->detach(m_pos, y.m_pos, y.m_node));
//    }

};

} // namespace detail

template <class Node>
typename detail::ascending_nary_cursor<Node>::size_type
index(detail::ascending_nary_cursor<Node> const& cur)
{
    return cur.index();
}

} // namespace tree
} // namespace boost

#endif // BOOST_TREE_DETAIL_NARY_CURSOR_HPP

max_stars_repo_name: grafikrobot/tree

max_issues_repo_name: grafikrobot/tree

max_forks_repo_name: grafikrobot/tree


text:
/**
 * Copyright (c) 2017 Melown Technologies SE
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 * *  Redistributions of source code must retain the above copyright notice,
 *    this list of conditions and the following disclaimer.
 *
 * *  Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * 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 COPYRIGHT HOLDER 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.
 */
/* pointcloud.cpp */

#include "pointcloud.hpp"

#include <dbglog/dbglog.hpp>
#include <boost/foreach.hpp>
#include <fstream>

namespace geometry {

void PointCloud::push_back( const math::Point3 & x ) {

    updateExtents( x );
    std::vector<math::Point3>::push_back( x );
}

PointCloud::iterator PointCloud::insert( iterator position,
    const math::Point3 & x ) {

    updateExtents( x );
    return std::vector<math::Point3>::insert( position, x );
}

void PointCloud::insert( iterator position, size_type n,
    const math::Point3 & x ) {

    updateExtents( x );
    std::vector<math::Point3>::insert( position, n, x );
}

void PointCloud::clear() {
    extents_ = math::Extents3();
}

void PointCloud::dump( const std::string & path ) {

    std::fstream f;

    f.exceptions( std::ios::badbit | std::ios::failbit );

    try {

        f.open( path, std::ios_base::out | std::ios_base::trunc );

        for ( const_iterator it = begin(); it < end(); ++it ) {
            f << (*it)(0) << "\t" << (*it)(1) << "\t" << (*it)(2) << "\n";
        }

    } catch ( std::ios_base::failure & e ) {

        LOG( err2 ) << "Failed to write to '" << path
                    << "', error: " << e.what();
        throw;
    }
}

void PointCloud::load( const std::string & path ) {

    std::ifstream f;
    f.exceptions( std::ios::badbit );

    try {

        f.open( path );
        clear();

        double x, y, z;
        while (f >> x >> y >> z) {
            push_back( math::Point3(x, y, z) );
        }

    } catch ( std::ios_base::failure & e ) {

        LOG( err2 ) << "Failed to read '" << path
                    << "', error: " << e.what();
        throw;
    }
}

void PointCloud::updateExtents( const math::Point3 & x ) {
    if ( empty() ) {
        extents_ = math::Extents3(x, x);
        return;
    }

    update(extents_, x);
}

double PointCloud::samplingDelta( float bulkThreshold ) const {

    ThreeDistance * distArray = new ThreeDistance[ size() ];

    // sanity
    assert( ! empty() );

    // obtain array of closest neighbour distances
    double maxDist = ublas::norm_2( extents_.ur - extents_.ll );
    for ( unsigned int i = 0; i < size(); i++ )
        distArray[i] = ThreeDistance( maxDist );

    for ( unsigned int i = 0; i < size(); i++ )
        for ( unsigned int j = 0; j < i; j++ ) {

            distArray[i].update( at( i ) - at( j ) );
            distArray[j].update( at( i ) - at( j ) );
       }

    // sort array
    std::sort( distArray, distArray + size() );

    // return delta
    double retval =  distArray[ int( floor( bulkThreshold * ( size() - 1 ) ) ) ].value();
    delete[] distArray;
    return retval;
}

/* PointCloud::ThreeDistance */

void PointCloud::ThreeDistance::update( const math::Point3 diff ) {

    double dist = ublas::norm_2( diff );

    if ( dist < 1E-15 ) return;

    int code = ( fabs( diff[0] ) > fabs( diff[1] ) ) << 0
    | ( fabs( diff[1] ) > fabs( diff[2] ) ) << 1
    | ( fabs( diff[2] ) > fabs( diff[0] ) ) << 2;

    if ( code == 0 || code == 1 || code == 3 ) {

        if ( dist < distX ) distX = dist;
    }

    if ( code == 2 || code == 6 ) {

        if ( dist < distY ) distY = dist;
    }

    if ( code == 4 || code == 5 ) {

        if ( dist < distZ ) distZ = dist;
    }

}

double PointCloud::ThreeDistance::value() const {

    double dists[3];
    dists[0] = distX; dists[1] = distY; dists[2] = distZ;
    std::sort( dists, dists + 3 );
    return dists[ 1 ];
}

} // namespace geometry

ext: cpp

max_issues_repo_name: HanochZhu/vts-browser-unity-plugin

max_forks_repo_name: HanochZhu/vts-browser-unity-plugin


text:
// All content Copyright (C) 2018 Genomics plc
#ifndef WECALL_MAP_HPP
#define WECALL_MAP_HPP

#include <iomanip>

#include <boost/program_options.hpp>
#include <boost/asio/io_service.hpp>
#include <boost/bind.hpp>
#include <boost/thread/thread.hpp>
#include <boost/algorithm/string.hpp>
#include <boost/filesystem/path.hpp>
#include <boost/lambda/bind.hpp>
#include <boost/lambda/construct.hpp>

#include "caller/jobReduce.hpp"
#include "common.hpp"
#include "caller/job.hpp"
#include "version/version.hpp"
#include "weCallBase.hpp"

namespace wecall
{
using namespace boost::program_options;
using namespace io;

class weCallMapAndReduce : public weCallBase
{
public:
    weCallMapAndReduce();
    int processJob( int argc, char * argv[] );

private:
    void initOptions();

private:
    options_description m_configOpts;
    options_description m_cmdLineOpts;
};
}

#endif

ext: hpp

max_stars_repo_name: dylex/wecall

max_issues_repo_name: dylex/wecall

max_forks_repo_name: dylex/wecall


text:
#include <ros/ros.h>
#include <tf/transform_broadcaster.h>
#include <nav_msgs/Odometry.h>
#include <sensor_msgs/JointState.h>
#include <iostream>
#include <iomanip>
#include <boost/asio.hpp>
#include <boost/bind.hpp>
#include <math.h>

using namespace std;
using namespace boost::asio;

double x = 0.0;
double y = 0.0;
double th = 0.0;
double vx = 0.0;
double vy = 0.0;
double vth = 0.0;
unsigned char startByte = 0xff;
unsigned char endByte = 0xfe;

static ros::Time current_time;
static ros::Time last_time;
geometry_msgs::Quaternion odom_quat;

unsigned char recv_buffer[8];
unsigned char recv_buffer_temp[1];
float Data_vx;
float Data_vth;

int HerdWore_vx;
int HerdWore_vth;

bool isStart = false;
int recv_buf_num = 0;

int main(int argc, char** argv){
    ros::init(argc, argv, "odometry_publisher");
    ros::NodeHandle nh_private("~");
    ros::NodeHandle nh;

    static std::string Base_Port = "";
    if(!nh_private.getParam("Base_Port", Base_Port)){
        Base_Port = "/dev/ttyUSB1";
    }

    ros::Publisher odom_pub = nh.advertise<nav_msgs::Odometry>("odom", 50);
    tf::TransformBroadcaster odom_broadcaster;

    io_service iosev;
    serial_port sp(iosev);
    sp.open(Base_Port);
    sp.set_option(serial_port::baud_rate(9600));
    sp.set_option(serial_port::flow_control(serial_port::flow_control::none));
    sp.set_option(serial_port::parity(serial_port::parity::none));
    sp.set_option(serial_port::stop_bits(serial_port::stop_bits::one));
    sp.set_option(serial_port::character_size(8));

    current_time = ros::Time::now();
    last_time = ros::Time::now();

    while(ros::ok()){

        read(sp, buffer(recv_buffer_temp));

        if(isStart == false)
        {
            if(recv_buffer_temp[0] == startByte)
            {
                isStart = true;
                recv_buf_num = 0;
            }
            continue;
        }
        else
        {
            if (recv_buf_num < 8)
            {
                recv_buffer[recv_buf_num] = recv_buffer_temp[0];
                recv_buf_num ++;
                continue;

            }else if (recv_buffer_temp[0] != endByte)
            {
                recv_buf_num = 0;
                if(recv_buffer_temp[0] != startByte)
                    isStart = false;
                continue;

            }else{
                isStart = false;
                recv_buf_num = 0;

                current_time = ros::Time::now();

                HerdWore_vx = (recv_buffer[3] << 24 | recv_buffer[2] << 16 | recv_buffer[1] << 8 | recv_buffer[0]);
                HerdWore_vth = (recv_buffer[7] << 24 | recv_buffer[6] << 16 | recv_buffer[5] << 8 | recv_buffer[4]);
                Data_vx = *((float *)&HerdWore_vx);
                Data_vth = *((float *)&HerdWore_vth);
                vx = (double)Data_vx;
                vth = (double)Data_vth;

                ROS_INFO("Encores linear is %f", vx);
                ROS_INFO("Encores angular is %f\n ", vth);

                if(vx <= -10.0 || vx >= 10.0)
                    vx = 0.0;
                if(vth <= -10.0 || vth >= 10.0)
                    vth = 0.0;

                //compute odometry in a typical way given the velocities of the robot
                double dt = (current_time - last_time).toSec();
                double delta_x = (vx * cos(th) - vy * sin(th)) * dt;
                double delta_y = (vx * sin(th) + vy * cos(th)) * dt;
                double delta_th = vth * dt;
                x += delta_x;
                y += delta_y;
                th += delta_th;
            }
        }

        //since all odometry is 6DOF we'll need a quaternion created from yaw
        geometry_msgs::Quaternion odom_quat = tf::createQuaternionMsgFromYaw(th);

        //first, we'll publish the transform over tf
        geometry_msgs::TransformStamped odom_trans;
        odom_trans.header.stamp = current_time;
        odom_trans.header.frame_id = "odom";
        odom_trans.child_frame_id = "base_link";

        odom_trans.transform.translation.x = x;
        odom_trans.transform.translation.y = y;
        odom_trans.transform.translation.z = 0.0;
        odom_trans.transform.rotation = odom_quat;

        //send the transform
        odom_broadcaster.sendTransform(odom_trans);

        //next, we'll publish the odometry message over ROS
        nav_msgs::Odometry odom;
        odom.header.stamp = current_time;
        odom.header.frame_id = "odom";

        //set the position
        odom.pose.pose.position.x = x;
        odom.pose.pose.position.y = y;
        odom.pose.pose.position.z = 0.0;
        odom.pose.pose.orientation = odom_quat;

        //set the velocity
        odom.child_frame_id = "base_link";
        odom.twist.twist.linear.x = vx;
        odom.twist.twist.linear.y = vy;
        odom.twist.twist.angular.z = vth;

        //publish the message
        odom_pub.publish(odom);
        last_time = current_time;
    }
    iosev.run();
}


text:
/*
 * @Description: IMU integration activity
 * @Author: Ge Yao
 * @Date: 2020-11-10 14:25:03
 */
#ifndef IMU_INTEGRATION_ACTIVITY_HPP_
#define IMU_INTEGRATION_ACTIVITY_HPP_

// common:
#include <ros/ros.h>

#include <Eigen/Dense>
#include <Eigen/Core>

// config:
#include "imu_integration/config/config.hpp"

// subscribers:
#include "imu_integration/subscriber/imu_subscriber.hpp"
#include "imu_integration/subscriber/odom_subscriber.hpp"

#include <nav_msgs/Odometry.h>

namespace imu_integration {

namespace estimator {

class Activity {
  public:
    Activity(void);
    void Init(void);
    bool Run(void);
  private:
    // workflow:
    bool ReadData(void);
    bool HasData(void);
    bool UpdatePose(void);
    bool PublishPose(void);

    // utils:
    /**
     * @brief  get unbiased angular velocity in body frame
     * @param  angular_vel, angular velocity measurement
     * @return unbiased angular velocity in body frame
     */
    Eigen::Vector3d GetUnbiasedAngularVel(const Eigen::Vector3d &angular_vel);
    /**
     * @brief  get unbiased linear acceleration in navigation frame
     * @param  linear_acc, linear acceleration measurement
     * @param  R, corresponding orientation of measurement
     * @return unbiased linear acceleration in navigation frame
     */
    Eigen::Vector3d GetUnbiasedLinearAcc(
        const Eigen::Vector3d &linear_acc,
        const Eigen::Matrix3d &R
    );
    /**
     * @brief  get angular delta
     * @param  index_curr, current imu measurement buffer index
     * @param  index_prev, previous imu measurement buffer index
     * @param  angular_delta, angular delta output
     * @return true if success false otherwise
     */
    bool GetAngularDelta(
        const size_t index_curr, const size_t index_prev,
        Eigen::Vector3d &angular_delta
    );
    /**
     * @brief  get velocity delta
     * @param  index_curr, current imu measurement buffer index
     * @param  index_prev, previous imu measurement buffer index
     * @param  R_curr, corresponding orientation of current imu measurement
     * @param  R_prev, corresponding orientation of previous imu measurement
     * @param  velocity_delta, velocity delta output
     * @return true if success false otherwise
     */
    bool GetVelocityDelta(
        const size_t index_curr, const size_t index_prev,
        const Eigen::Matrix3d &R_curr, const Eigen::Matrix3d &R_prev,
        double &delta_t, Eigen::Vector3d &velocity_delta
    );
    /**
     * @brief  update orientation with effective rotation angular_delta
     * @param  angular_delta, effective rotation
     * @param  R_curr, current orientation
     * @param  R_prev, previous orientation
     * @return void
     */
    void UpdateOrientation(
        const Eigen::Vector3d &angular_delta,
        Eigen::Matrix3d &R_curr, Eigen::Matrix3d &R_prev
    );
    /**
     * @brief  update orientation with effective velocity change velocity_delta
     * @param  velocity_delta, effective velocity change
     * @return void
     */
    void UpdatePosition(const double &delta_t, const Eigen::Vector3d &velocity_delta);

  private:
    // node handler:
    ros::NodeHandle private_nh_;

    // subscriber:
    std::shared_ptr<IMUSubscriber> imu_sub_ptr_;
    std::shared_ptr<OdomSubscriber> odom_ground_truth_sub_ptr;
    ros::Publisher odom_estimation_pub_;

    // data buffer:
    std::deque<IMUData> imu_data_buff_;
    std::deque<OdomData> odom_data_buff_;

    // config:
    bool initialized_ = false;

    IMUConfig imu_config_;
    OdomConfig odom_config_;

    // a. gravity constant:
    Eigen::Vector3d G_;
    // b. angular velocity:
    Eigen::Vector3d angular_vel_bias_;
    // c. linear acceleration:
    Eigen::Vector3d linear_acc_bias_;

    // IMU pose estimation:
    Eigen::Matrix4d pose_ = Eigen::Matrix4d::Identity();
    Eigen::Vector3d vel_ = Eigen::Vector3d::Zero();

    nav_msgs::Odometry message_odom_;
};

} // namespace estimator

} // namespace imu_integration

#endif


text:
#include <iostream>
#include <fstream>
#include <iterator>
#include <cmath>
#include <unordered_map>

#include <boost/algorithm/string.hpp>

#include <qdir.h>
#include <qfile.h>
#include <qdebug.h>

#include "SegPipe_Controller.h"

using namespace std;

SegPipe_Controller::SegPipe_Controller(QString inputPath, QString outputPath) : inputCaseRootPath(inputPath), outputRootPath(outputPath)
{
	this->caseList.clear();
	QDir inputDir(inputCaseRootPath);
	inputDir.setFilter(QDir::Dirs | QDir::NoDotAndDotDot);
	this->caseList = inputDir.entryList();

	if (caseList.empty()) // No directories found.
	{
		inputDir.setFilter(QDir::Files | QDir::NoDotAndDotDot);
		this->caseList = inputDir.entryList();

		int swcFileCount = 0;
		int tifFileCount = 0;
		for (QStringList::iterator caseCheckIt = this->caseList.begin(); caseCheckIt != this->caseList.end(); ++caseCheckIt)
		{
			if ((*caseCheckIt).contains(".swc")) ++swcFileCount;
			else if ((*caseCheckIt).contains(".tif")) ++tifFileCount;
		}

		if (swcFileCount == this->caseList.size())
		{
			this->inputSWCRootPath = inputPath;
			this->inputCaseRootPath = "";
		}
		else if (tifFileCount == this->caseList.size())
		{
			this->inputSWCRootPath = "";
			this->inputCaseRootPath = inputPath;
		}
	}
	else
	{
		for (QStringList::iterator caseIt = this->caseList.begin(); caseIt != this->caseList.end(); ++caseIt)
		{
			QString caseFullPath = this->inputCaseRootPath + "/" + *caseIt;
			QString outputCaseFullPath = this->outputRootPath + "/" + *caseIt;
			QDir caseFolder(caseFullPath);
			caseFolder.setFilter(QDir::Files | QDir::NoDotAndDotDot);
			QStringList caseSlices = caseFolder.entryList();
			if (caseSlices.empty()) cout << "case " << (*caseIt).toStdString() << " is empty. Skip." << endl;

			for (QStringList::iterator sliceIt = caseSlices.begin(); sliceIt != caseSlices.end(); ++sliceIt)
			{
				QString sliceFullPath = caseFullPath + "/" + *sliceIt;
				inputMultiCasesSliceFullPaths.insert(pair<string, string>((*caseIt).toStdString(), sliceFullPath.toStdString()));

				QString outputSliceFullPath = outputCaseFullPath + "/" + *sliceIt;
				outputMultiCasesSliceFullPaths.insert(pair<string, string>((*caseIt).toStdString(), outputSliceFullPath.toStdString()));
			}
		}
	}

	this->myImgManagerPtr = new ImgManager;
	this->myImgManagerPtr->inputCaseRootPath = this->inputCaseRootPath;
	this->myImgManagerPtr->caseList = this->caseList;
	this->myImgManagerPtr->inputMultiCasesSliceFullPaths = this->inputMultiCasesSliceFullPaths;

	this->myImgAnalyzerPtr = new ImgAnalyzer;

	this->myNeuronUtilPtr = new NeuronStructUtil;

	this->myNeuronStructExpPtr = new NeuronStructExplorer;
}

void SegPipe_Controller::singleTaskDispatcher(deque<task> taskList)
{
	// Use this method to dispatch image cases. The idea is to deliver 'subject package' to other methods.
	// The subject package should be a data struct that contains information and/or instruction of how the images should be handled.
	// To be implemented.

	for (deque<task>::iterator it = taskList.begin(); it != taskList.end(); ++it)
	{
		switch (*it)
		{
			case downsample2D:
				break;
			case threshold2D:
				break;
			case bkgThreshold2D:
				break;
			case gammaCorrect2D:
				break;
		}
	}
}

void SegPipe_Controller::sliceDownSample2D(int downFactor, string method)
{
	for (QStringList::iterator caseIt = this->caseList.begin(); caseIt != this->caseList.end(); ++caseIt)
	{
		QString caseFullPathQ = this->inputCaseRootPath + "/" + *caseIt;
		qDebug() << "INPUT DIRECTORY: " << caseFullPathQ;
		QDir caseDir(caseFullPathQ);
		caseDir.setFilter(QDir::Files | QDir::NoDotAndDotDot);
		QStringList sliceList = caseDir.entryList();
		QString saveCaseFullNameQ = this->outputRootPath + "/" + *caseIt;
		qDebug() << "OUTPUT DIRECTORY: " << saveCaseFullNameQ;
		if (!QDir(saveCaseFullNameQ).exists()) QDir().mkpath(saveCaseFullNameQ);

		for (QStringList::iterator sliceIt = sliceList.begin(); sliceIt != sliceList.end(); ++sliceIt)
		{
			QString sliceFullNameQ = caseFullPathQ + "/" + *sliceIt;
			string sliceFullName = sliceFullNameQ.toStdString();
			const char* sliceFullNameC = sliceFullName.c_str();
			Image4DSimple* slicePtr = new Image4DSimple;
			slicePtr->loadImage(sliceFullNameC);
			int dims[3];
			dims[0] = int(slicePtr->getXDim());
			dims[1] = int(slicePtr->getYDim());
			dims[2] = 1;
			long int totalbyteSlice = slicePtr->getTotalBytes();
			unsigned char* slice1D = new unsigned char[totalbyteSlice];
			memcpy(slice1D, slicePtr->getRawData(), totalbyteSlice);

			long newLength = (dims[0] / downFactor) * (dims[1] / downFactor);
			unsigned char* dnSampledSlice = new unsigned char[newLength];
			if (!method.compare("")) ImgProcessor::imgDownSample2D(slice1D, dnSampledSlice, dims, downFactor);
			else if (!method.compare("max")) ImgProcessor::imgDownSample2DMax(slice1D, dnSampledSlice, dims, downFactor);

			V3DLONG Dims[4];
			Dims[0] = dims[0] / downFactor;
			Dims[1] = dims[1] / downFactor;
			Dims[2] = 1;
			Dims[3] = 1;

			string saveFullName = this->outputRootPath.toStdString() + "/" + (*caseIt).toStdString() + "/" + (*sliceIt).toStdString();
			const char* saveFullNameC = saveFullName.c_str();
			ImgManager::saveimage_wrapper(saveFullNameC, dnSampledSlice, Dims, 1);

			slicePtr->~Image4DSimple();
			operator delete(slicePtr);

			if (slice1D) { delete[] slice1D; slice1D = 0; }
			if (dnSampledSlice) { delete[] dnSampledSlice; dnSampledSlice = 0; }
		}
	}
}

void SegPipe_Controller::sliceThre(float threPercentile)
{
	for (QStringList::iterator caseIt = this->caseList.begin(); caseIt != this->caseList.end(); ++caseIt)
	{
		QString saveCaseFullNameQ = this->outputRootPath + "/" + *caseIt;
		if (!QDir(saveCaseFullNameQ).exists()) QDir().mkpath(saveCaseFullNameQ);
		else
		{
			cerr << "This folder already exists. Skip case: " << (*caseIt).toStdString() << endl;
			continue;
		}
		string saveFullPathRoot = saveCaseFullNameQ.toStdString();

		pair<multimap<string, string>::iterator, multimap<string, string>::iterator> range;
		range = this->inputMultiCasesSliceFullPaths.equal_range((*caseIt).toStdString());
		QString caseFullPathQ = this->inputCaseRootPath + "/" + *caseIt;

		myImgManagerPtr->imgDatabase.clear();
		myImgManagerPtr->inputMultiCasesSliceFullPaths = this->inputMultiCasesSliceFullPaths;
		myImgManagerPtr->imgEntry((*caseIt).toStdString(), ImgManager::slices);
		qDebug() << *caseIt;

		for (map<string, myImg1DPtr>::iterator sliceIt = myImgManagerPtr->imgDatabase.begin()->second.slicePtrs.begin();
			sliceIt != myImgManagerPtr->imgDatabase.begin()->second.slicePtrs.end(); ++sliceIt)
		{
			unsigned char* threSlice = new unsigned char[myImgManagerPtr->imgDatabase.begin()->second.dims[0] * myImgManagerPtr->imgDatabase.begin()->second.dims[1]];
			map<int, size_t> histMap = ImgProcessor::histQuickList(sliceIt->second.get(), myImgManagerPtr->imgDatabase.begin()->second.dims);
			int topBracket = 0;
			float pixCount = histMap[0];
			for (int bracketI = 1; bracketI < 255; ++bracketI)
			{
				pixCount = pixCount + float(histMap[bracketI]);
				if (pixCount / float(myImgManagerPtr->imgDatabase.begin()->second.dims[0] * myImgManagerPtr->imgDatabase.begin()->second.dims[1]) >= threPercentile)
				{
					topBracket = bracketI;
					break;
				}
			}
			ImgProcessor::simpleThresh(sliceIt->second.get(), threSlice, myImgManagerPtr->imgDatabase.begin()->second.dims, topBracket);

			V3DLONG Dims[4];
			Dims[0] = myImgManagerPtr->imgDatabase.begin()->second.dims[0];
			Dims[1] = myImgManagerPtr->imgDatabase.begin()->second.dims[1];
			Dims[2] = 1;
			Dims[3] = 1;
			string sliceSaveFullName = saveFullPathRoot + "/" + sliceIt->first;
			const char* sliceSaveFullNameC = sliceSaveFullName.c_str();
			ImgManager::saveimage_wrapper(sliceSaveFullNameC, threSlice, Dims, 1);

			if (threSlice) { delete[] threSlice; threSlice = 0; }
		}
	}
}

void SegPipe_Controller::threshold3D(float threPercentile)
{
	for (QStringList::iterator caseIt = this->caseList.begin(); caseIt != this->caseList.end(); ++caseIt)
	{
		QString saveCaseFullNameQ = this->outputRootPath + "/" + *caseIt;
		if (!QDir(saveCaseFullNameQ).exists()) QDir().mkpath(saveCaseFullNameQ);
		else
		{
			cerr << "This folder already exists. Skip case: " << (*caseIt).toStdString() << endl;
			continue;
		}
		string saveFullPathRoot = saveCaseFullNameQ.toStdString();

		pair<multimap<string, string>::iterator, multimap<string, string>::iterator> range;
		range = this->inputMultiCasesSliceFullPaths.equal_range((*caseIt).toStdString());
		QString caseFullPathQ = this->inputCaseRootPath + "/" + *caseIt;

		myImgManagerPtr->imgDatabase.clear();
		myImgManagerPtr->inputMultiCasesSliceFullPaths = this->inputMultiCasesSliceFullPaths;
		myImgManagerPtr->imgEntry((*caseIt).toStdString(), ImgManager::slices);
		int zSliceNum = myImgManagerPtr->imgDatabase.begin()->second.slicePtrs.size();
		size_t totalPixel = size_t(zSliceNum) * size_t(myImgManagerPtr->imgDatabase.begin()->second.dims[0]) * size_t(myImgManagerPtr->imgDatabase.begin()->second.dims[1]);
		cout << "total pixel num: " << totalPixel << endl;

		map<int, map<int, size_t>> histMapAllSlice;
		int sliceCount = 0;
		cout << "processing slice: ";
		for (map<string, myImg1DPtr>::iterator sliceIt = myImgManagerPtr->imgDatabase.begin()->second.slicePtrs.begin();
			sliceIt != myImgManagerPtr->imgDatabase.begin()->second.slicePtrs.end(); ++sliceIt)
		{
			map<int, size_t> histMap = ImgProcessor::histQuickList(sliceIt->second.get(), myImgManagerPtr->imgDatabase.begin()->second.dims);
			histMapAllSlice.insert(pair<int, map<int, size_t>>(sliceCount, histMap));
			++sliceCount;
			cout << sliceCount << " ";
		}
		cout << endl;

		float currPercentile = 0;
		int threshedPixelCount = 0;
		int currThre = 256;
		while (currPercentile < (1 - threPercentile))
		{
			--currThre;
			cout << "current threshold: " << currThre;
			for (map<int, map<int, size_t>>::iterator sliceHistIt = histMapAllSlice.begin(); sliceHistIt != histMapAllSlice.end(); ++sliceHistIt)
			{
				if (sliceHistIt->second.find(currThre) != sliceHistIt->second.end()) threshedPixelCount = threshedPixelCount + sliceHistIt->second[currThre];
			}

			currPercentile = float(threshedPixelCount) / float(totalPixel);
			cout << " thresholded pixel number: " << threshedPixelCount << " " << currPercentile << endl;
		}

		for (map<string, myImg1DPtr>::iterator sliceIt = myImgManagerPtr->imgDatabase.begin()->second.slicePtrs.begin();
			sliceIt != myImgManagerPtr->imgDatabase.begin()->second.slicePtrs.end(); ++sliceIt)
		{
			unsigned char* slice1DPtr = new unsigned char[myImgManagerPtr->imgDatabase.begin()->second.dims[0] * myImgManagerPtr->imgDatabase.begin()->second.dims[1]];
			ImgProcessor::simpleThresh(sliceIt->second.get(), slice1DPtr, myImgManagerPtr->imgDatabase.begin()->second.dims, currThre);

			V3DLONG Dims[4];
			Dims[0] = myImgManagerPtr->imgDatabase.begin()->second.dims[0];
			Dims[1] = myImgManagerPtr->imgDatabase.begin()->second.dims[1];
			Dims[2] = 1;
			Dims[3] = 1;
			string sliceSaveFullName = saveFullPathRoot + "/" + sliceIt->first;
			const char* sliceSaveFullNameC = sliceSaveFullName.c_str();
			ImgManager::saveimage_wrapper(sliceSaveFullNameC, slice1DPtr, Dims, 1);

			delete[] slice1DPtr;
		}
	}
}

void SegPipe_Controller::sliceBkgThre()
{
	for (QStringList::iterator caseIt = this->caseList.begin(); caseIt != this->caseList.end(); ++caseIt)
	{
		QString saveCaseFullNameQ = this->outputRootPath + "/" + *caseIt;
		if (!QDir(saveCaseFullNameQ).exists()) QDir().mkpath(saveCaseFullNameQ);
		else
		{
			cerr << "This folder already exists. Skip case: " << (*caseIt).toStdString() << endl << endl;
			continue;
		}
		string saveFullPathRoot = saveCaseFullNameQ.toStdString();

		pair<multimap<string, string>::iterator, multimap<string, string>::iterator> range;
		range = this->inputMultiCasesSliceFullPaths.equal_range((*caseIt).toStdString());
		QString caseFullPathQ = this->inputCaseRootPath + "/" + *caseIt;

		myImgManagerPtr->imgDatabase.clear();
		myImgManagerPtr->inputMultiCasesSliceFullPaths = this->inputMultiCasesSliceFullPaths;
		myImgManagerPtr->imgEntry((*caseIt).toStdString(), ImgManager::slices);
		for (map<string, myImg1DPtr>::iterator sliceIt = myImgManagerPtr->imgDatabase.begin()->second.slicePtrs.begin();
			sliceIt != myImgManagerPtr->imgDatabase.begin()->second.slicePtrs.end(); ++sliceIt)
		{
			unsigned char* threSlice = new unsigned char[myImgManagerPtr->imgDatabase.begin()->second.dims[0] * myImgManagerPtr->imgDatabase.begin()->second.dims[1]];
			map<int, size_t> histMap = ImgProcessor::histQuickList(sliceIt->second.get(), myImgManagerPtr->imgDatabase.begin()->second.dims);
			int thre = 0;
			int previousI = 0;
			for (map<int, size_t>::iterator it = histMap.begin(); it != histMap.end(); ++it)
			{
				if (it->first - previousI > 1)
				{
					thre = it->first;
					break;
				}
				previousI = it->first;
			}
			cout << "  slice " << sliceIt->first << " cut off threshold: " << thre << endl;
			ImgProcessor::simpleThresh(sliceIt->second.get(), threSlice, myImgManagerPtr->imgDatabase.begin()->second.dims, thre);

			V3DLONG Dims[4];
			Dims[0] = myImgManagerPtr->imgDatabase.begin()->second.dims[0];
			Dims[1] = myImgManagerPtr->imgDatabase.begin()->second.dims[1];
			Dims[2] = 1;
			Dims[3] = 1;
			string sliceSaveFullName = saveFullPathRoot + "/" + sliceIt->first;
			const char* sliceSaveFullNameC = sliceSaveFullName.c_str();
			ImgManager::saveimage_wrapper(sliceSaveFullNameC, threSlice, Dims, 1);

			if (threSlice) { delete[] threSlice; threSlice = 0; }
		}
	}
}

void SegPipe_Controller::makeMIPimgs()
{
	myImgManagerPtr->imgDatabase.clear();
	myImgManagerPtr->inputMultiCasesSliceFullPaths = this->inputMultiCasesSliceFullPaths;
	for (QStringList::iterator caseIt = this->caseList.begin(); caseIt != this->caseList.end(); ++caseIt)
	{
		pair<multimap<string, string>::iterator, multimap<string, string>::iterator> range;
		range = this->inputMultiCasesSliceFullPaths.equal_range((*caseIt).toStdString());
		QString caseFullPathQ = this->inputCaseRootPath + "/" + *caseIt;

		myImgManagerPtr->imgEntry((*caseIt).toStdString(), ImgManager::slices);

		unsigned char* MIPptr = new unsigned char[myImgManagerPtr->imgDatabase.begin()->second.dims[0] * myImgManagerPtr->imgDatabase.begin()->second.dims[1]];
		for (size_t j = 0; j < myImgManagerPtr->imgDatabase.begin()->second.dims[1]; ++j)
			for (size_t i = 0; i < myImgManagerPtr->imgDatabase.begin()->second.dims[0]; ++i) MIPptr[myImgManagerPtr->imgDatabase.begin()->second.dims[0] * j + i] = 0;
		for (map<string, myImg1DPtr>::iterator sliceIt = myImgManagerPtr->imgDatabase.begin()->second.slicePtrs.begin();
			sliceIt != myImgManagerPtr->imgDatabase.begin()->second.slicePtrs.end(); ++sliceIt)
		{
			if (sliceIt->first.find("_") != string::npos) continue;
			else ImgProcessor::imgMax(sliceIt->second.get(), MIPptr, MIPptr, myImgManagerPtr->imgDatabase.begin()->second.dims);
		}

		V3DLONG Dims[4];
		Dims[0] = myImgManagerPtr->imgDatabase.begin()->second.dims[0];
		Dims[1] = myImgManagerPtr->imgDatabase.begin()->second.dims[1];
		Dims[2] = 1;
		Dims[3] = 1;
		string sliceSaveFullName = (this->outputRootPath).toStdString() + "/" + (*caseIt).toStdString() + ".tif";
		const char* sliceSaveFullNameC = sliceSaveFullName.c_str();
		ImgManager::saveimage_wrapper(sliceSaveFullNameC, MIPptr, Dims, 1);

		delete[] MIPptr;
		myImgManagerPtr->imgDatabase.clear();
	}
}

void SegPipe_Controller::makeDescentSkeletons()
{
	for (QStringList::iterator caseIt = this->caseList.begin(); caseIt != this->caseList.end(); ++caseIt)
	{
		QStringList inputNameParse = (*caseIt).split(".");
		QString caseNum = *inputNameParse.begin();

		qDebug() << this->outputRootPath << " " << this->outputRootPath2 << endl;
		QString saveCaseFullNameQ = this->outputRootPath + "/" + caseNum;
		if (!QDir(saveCaseFullNameQ).exists()) QDir().mkpath(saveCaseFullNameQ);
		else
		{
			cerr << "This folder already exists. Skip case: " << (*caseIt).toStdString() << endl << endl;
			continue;
		}
		string saveFullPathRoot = saveCaseFullNameQ.toStdString();

		QString saveSkeFullNameQ = this->outputRootPath2 + "/" + caseNum;
		if (!QDir(saveSkeFullNameQ).exists()) QDir().mkpath(saveSkeFullNameQ);
		else
		{
			cerr << "This folder already exists. Skip case: " << (*caseIt).toStdString() << endl << endl;
			continue;
		}
		string saveSkeFullPathRoot = saveSkeFullNameQ.toStdString();

		QString inputFileFullPath = this->inputCaseRootPath + "/" + *caseIt;
		myImgManagerPtr->inputSingleCaseFullPath = inputFileFullPath.toStdString();
		myImgManagerPtr->imgEntry((*caseIt).toStdString(), ImgManager::singleCase);

		map<int, size_t> histMap = ImgProcessor::histQuickList(myImgManagerPtr->imgDatabase.begin()->second.slicePtrs.begin()->second.get(), myImgManagerPtr->imgDatabase.begin()->second.dims);
		histMap.erase(histMap.begin());
		for (map<int, size_t>::iterator histIt = histMap.begin(); histIt != histMap.end(); ++histIt)
		{
			unsigned char* newThreSlice1D = new unsigned char[myImgManagerPtr->imgDatabase.begin()->second.dims[0] * myImgManagerPtr->imgDatabase.begin()->second.dims[1]];
			ImgProcessor::simpleThresh(myImgManagerPtr->imgDatabase.begin()->second.slicePtrs.begin()->second.get(), newThreSlice1D, myImgManagerPtr->imgDatabase.begin()->second.dims, histIt->first);
			V3DLONG Dims[4];
			Dims[0] = myImgManagerPtr->imgDatabase.begin()->second.dims[0];
			Dims[1] = myImgManagerPtr->imgDatabase.begin()->second.dims[1];
			Dims[2] = 1;
			Dims[3] = 1;
			string threshold = to_string(histIt->first);
			string newSliceName = saveFullPathRoot + "/" + caseNum.toStdString() + "_" + threshold + ".tif";
			const char* newSliceNameC = newSliceName.c_str();
			ImgManager::saveimage_wrapper(newSliceNameC, newThreSlice1D, Dims, 1);

			unsigned char* newThreSliceSke1D = new unsigned char[myImgManagerPtr->imgDatabase.begin()->second.dims[0] * myImgManagerPtr->imgDatabase.begin()->second.dims[1]];
			ImgProcessor::skeleton2D(newThreSlice1D, newThreSliceSke1D, myImgManagerPtr->imgDatabase.begin()->second.dims);
			string newSkeletonSliceName = saveSkeFullPathRoot + "/" + caseNum.toStdString() + "_" + threshold + "skeleton.tif";
			const char* newSkeletonSliceNameC = newSkeletonSliceName.c_str();
			ImgManager::saveimage_wrapper(newSkeletonSliceNameC, newThreSliceSke1D, Dims, 1);

			delete[] newThreSlice1D;
			delete[] newThreSliceSke1D;
		}

		myImgManagerPtr->imgDatabase.clear();
	}
}

void SegPipe_Controller::getSomaBlendedImgs()
{
	myImgManagerPtr->imgDatabase.clear();
	myImgManagerPtr->inputMultiCasesSliceFullPaths = this->inputMultiCasesSliceFullPaths;
	for (QStringList::iterator caseIt = this->caseList.begin(); caseIt != this->caseList.end(); ++caseIt)
	{
		pair<multimap<string, string>::iterator, multimap<string, string>::iterator> range;
		range = this->inputMultiCasesSliceFullPaths.equal_range((*caseIt).toStdString());
		QString caseFullPathQ = this->inputCaseRootPath + "/" + *caseIt;

		myImgManagerPtr->imgEntry((*caseIt).toStdString(), ImgManager::slices);

		string sliceName;
		string threshold;
		for (map<string, myImg1DPtr>::reverse_iterator sliceIt = myImgManagerPtr->imgDatabase.begin()->second.slicePtrs.rbegin();
			sliceIt != myImgManagerPtr->imgDatabase.begin()->second.slicePtrs.rend(); ++sliceIt)
		{
			for (size_t i = 0; i < myImgManagerPtr->imgDatabase.begin()->second.dims[0] * myImgManagerPtr->imgDatabase.begin()->second.dims[1]; ++i)
				if (sliceIt->second.get()[i] > 0)
				{
					sliceName = sliceIt->first;
					vector<string> sliceItParse;
					boost::split(sliceItParse, sliceName, boost::is_any_of("_"));
					vector<string> threParse;
					boost::split(threParse, sliceItParse.back(), boost::is_any_of("skeleton"));
					threshold = threParse.front();
					goto HIGHEST_THRESHOLD;
				}
		}

	HIGHEST_THRESHOLD:
		QString mipFullNameQ = this->inputCaseRootPath2 + "/" + *caseIt + ".tif";
		QString mipAlias = *caseIt + "_mip";
		string mipFullName = mipFullNameQ.toStdString();
		myImgManagerPtr->inputSingleCaseFullPath = mipFullName;
		myImgManagerPtr->imgEntry(mipAlias.toStdString(), ImgManager::singleCase);

		unsigned char* blendingPtr = new unsigned char[myImgManagerPtr->imgDatabase.begin()->second.dims[0] * myImgManagerPtr->imgDatabase.begin()->second.dims[1] * 2];
		vector<unsigned char*> blending;
		blending.push_back(myImgManagerPtr->imgDatabase.at((*caseIt).toStdString()).slicePtrs.at(sliceName).get());
		blending.push_back(myImgManagerPtr->imgDatabase.at(mipAlias.toStdString()).slicePtrs.begin()->second.get());
		ImgManager::imgsBlend(blending, blendingPtr, myImgManagerPtr->imgDatabase.begin()->second.dims);

		V3DLONG Dims[4];
		Dims[0] = myImgManagerPtr->imgDatabase.begin()->second.dims[0];
		Dims[1] = myImgManagerPtr->imgDatabase.begin()->second.dims[1];
		Dims[2] = 1;
		Dims[3] = 2;
		string saveFullName = this->outputRootPath.toStdString() + "/" + (*caseIt).toStdString() + "_" + threshold + ".tif";
		const char* saveFullNameC = saveFullName.c_str();
		ImgManager::saveimage_wrapper(saveFullNameC, blendingPtr, Dims, 1);

		myImgManagerPtr->imgDatabase.clear();
		delete[] blendingPtr;
	}
}

void SegPipe_Controller::skeletonThreFiltered()
{
	myImgManagerPtr->inputMultiCasesSliceFullPaths = this->inputMultiCasesSliceFullPaths;
	for (QStringList::iterator caseIt = this->caseList.begin(); caseIt != this->caseList.end(); ++caseIt)
	{
		pair<multimap<string, string>::iterator, multimap<string, string>::iterator> range;
		range = this->inputMultiCasesSliceFullPaths.equal_range((*caseIt).toStdString());
		QString caseFullPathQ = this->inputCaseRootPath + "/" + *caseIt;

		myImgManagerPtr->imgEntry((*caseIt).toStdString(), ImgManager::slices);

		V3DLONG Dims[4];
		Dims[0] = myImgManagerPtr->imgDatabase.begin()->second.dims[0];
		Dims[1] = myImgManagerPtr->imgDatabase.begin()->second.dims[1];
		Dims[2] = 1;
		Dims[3] = 1;

		for (map<string, myImg1DPtr>::iterator sliceIt = myImgManagerPtr->imgDatabase.at((*caseIt).toStdString()).slicePtrs.begin();
			sliceIt != myImgManagerPtr->imgDatabase.at((*caseIt).toStdString()).slicePtrs.end(); ++sliceIt)
		{
			vector<string> sliceNameParse;
			boost::split(sliceNameParse, sliceIt->first, boost::is_any_of("_"));
			vector<string> threParse;
			boost::split(threParse, sliceNameParse.back(), boost::is_any_of(".tif"));
			int threshold = stoi(threParse.front());
			unsigned char* threStep1D = new unsigned char[myImgManagerPtr->imgDatabase.begin()->second.dims[0] * myImgManagerPtr->imgDatabase.begin()->second.dims[1]];
			ImgProcessor::simpleThresh_reverse(sliceIt->second.get(), threStep1D, myImgManagerPtr->imgDatabase.begin()->second.dims, threshold);
			string saveThreFullName = this->outputRootPath.toStdString() + "/" + (*caseIt).toStdString() + "/" + threParse.front() + ".tif";
			const char* saveThreFullNameC = saveThreFullName.c_str();
			ImgManager::saveimage_wrapper(saveThreFullNameC, threStep1D, Dims, 1);
			cout << saveThreFullName << endl;

			unsigned char* skeletonThreStep1D = new unsigned char[myImgManagerPtr->imgDatabase.begin()->second.dims[0] * myImgManagerPtr->imgDatabase.begin()->second.dims[1]];
			string sliceName = (*caseIt).toStdString() + "_" + threParse.front() + "skeleton.tif";
			myImgManagerPtr->inputSingleCaseFullPath = (this->inputCaseRootPath2 + "/" + *caseIt).toStdString() + "/" + sliceName;
			myImgManagerPtr->imgEntry(threParse.front(), ImgManager::singleCase);
			ImgProcessor::imgDotMultiply(myImgManagerPtr->imgDatabase.at(threParse.front()).slicePtrs.begin()->second.get(), threStep1D, skeletonThreStep1D, myImgManagerPtr->imgDatabase.begin()->second.dims);
			string saveSkeFullName = this->outputRootPath2.toStdString() + "/" + (*caseIt).toStdString() + "/" + threParse.front() + ".tif";
			const char* saveSkeFullNameC = saveSkeFullName.c_str();
			ImgManager::saveimage_wrapper(saveSkeFullNameC, skeletonThreStep1D, Dims, 1);
			cout << saveSkeFullName << endl << endl;

			delete[] threStep1D;
			delete[] skeletonThreStep1D;
		}

		myImgManagerPtr->imgDatabase.clear();
	}
}

void SegPipe_Controller::sliceGammaCorrect()
{
	for (QStringList::iterator caseIt = this->caseList.begin(); caseIt != this->caseList.end(); ++caseIt)
	{
		QString saveCaseFullNameQ = this->outputRootPath + "/" + *caseIt;
		qDebug() << saveCaseFullNameQ;
		if (!QDir(saveCaseFullNameQ).exists()) QDir().mkpath(saveCaseFullNameQ);
		else
		{
			cerr << "This folder already exists. Skip case: " << (*caseIt).toStdString() << endl << endl;
			continue;
		}
		string saveFullPathRoot = saveCaseFullNameQ.toStdString();

		pair<multimap<string, string>::iterator, multimap<string, string>::iterator> range;
		range = this->inputMultiCasesSliceFullPaths.equal_range((*caseIt).toStdString());
		QString caseFullPathQ = this->inputCaseRootPath + "/" + *caseIt;

		for (multimap<string, string>::iterator sliceIt = range.first; sliceIt != range.second; ++sliceIt)
		{
			const char* inputFullPathC = (sliceIt->second).c_str();
			Image4DSimple* slicePtr = new Image4DSimple;
			slicePtr->loadImage(inputFullPathC);
			int dims[3];
			dims[0] = int(slicePtr->getXDim());
			dims[1] = int(slicePtr->getYDim());
			dims[2] = 1;
			long int totalbyteSlice = slicePtr->getTotalBytes();
			unsigned char* slice1D = new unsigned char[totalbyteSlice];
			memcpy(slice1D, slicePtr->getRawData(), totalbyteSlice);
			unsigned char* gammaSlice = new unsigned char[dims[0] * dims[1]];
			map<int, size_t> histMap = ImgProcessor::histQuickList(slice1D, dims);
			int gammaStart = 0;
			for (int histI = 1; histI < histMap.size(); ++histI)
			{
				if (histMap[histI] <= histMap[histI - 1] && histMap[histI] <= histMap[histI + 1])
				{
					gammaStart = histI;
					break;
				}
			}
			ImgProcessor::gammaCorrect_eqSeriesFactor(slice1D, gammaSlice, dims, gammaStart);

			V3DLONG Dims[4];
			Dims[0] = dims[0];
			Dims[1] = dims[1];
			Dims[2] = 1;
			Dims[3] = 1;

			string fileName = sliceIt->second.substr(sliceIt->second.length() - 9, 9);
			string sliceSaveFullName = saveFullPathRoot + "/" + fileName;
			const char* sliceSaveFullNameC = sliceSaveFullName.c_str();
			ImgManager::saveimage_wrapper(sliceSaveFullNameC, gammaSlice, Dims, 1);

			slicePtr->~Image4DSimple();
			operator delete(slicePtr);
			if (slice1D) { delete[] slice1D; slice1D = 0; }
			if (gammaSlice) { delete[] gammaSlice; gammaSlice = 0; }
		}
	}
}

void SegPipe_Controller::sliceReversedGammaCorrect()
{
	for (QStringList::iterator caseIt = this->caseList.begin(); caseIt != this->caseList.end(); ++caseIt)
	{
		QString saveCaseFullNameQ = this->outputRootPath + "/gamma/" + *caseIt;
		if (!QDir(saveCaseFullNameQ).exists()) QDir().mkpath(saveCaseFullNameQ);
		string saveFullPathRoot = saveCaseFullNameQ.toStdString();

		pair<multimap<string, string>::iterator, multimap<string, string>::iterator> range;
		range = this->inputMultiCasesSliceFullPaths.equal_range((*caseIt).toStdString());
		QString caseFullPathQ = this->inputCaseRootPath + "/" + *caseIt;

		for (multimap<string, string>::iterator sliceIt = range.first; sliceIt != range.second; ++sliceIt)
		{
			const char* inputFullPathC = (sliceIt->second).c_str();
			Image4DSimple* slicePtr = new Image4DSimple;
			slicePtr->loadImage(inputFullPathC);
			int dims[3];
			dims[0] = int(slicePtr->getXDim());
			dims[1] = int(slicePtr->getYDim());
			dims[2] = 1;
			long int totalbyteSlice = slicePtr->getTotalBytes();
			unsigned char* slice1D = new unsigned char[totalbyteSlice];
			memcpy(slice1D, slicePtr->getRawData(), totalbyteSlice);
			unsigned char* gammaSlice = new unsigned char[dims[0] * dims[1]];
			map<int, size_t> histMap = ImgProcessor::histQuickList(slice1D, dims);
			int histMin = 100000;
			for (int histI = 1; histI < histMap.size(); ++histI)
			{
				if (histMap[histI] <= histMin)
				{
					histMin = histI;
					break;
				}
			}
			ImgProcessor::reversed_gammaCorrect_eqSeriesFactor(slice1D, gammaSlice, dims, histMin);

			V3DLONG Dims[4];
			Dims[0] = dims[0];
			Dims[1] = dims[1];
			Dims[2] = 1;
			Dims[3] = 1;

			string fileName = sliceIt->second.substr(sliceIt->second.length() - 9, 9);
			string sliceSaveFullName = saveFullPathRoot + "/" + fileName;
			const char* sliceSaveFullNameC = sliceSaveFullName.c_str();
			ImgManager::saveimage_wrapper(sliceSaveFullNameC, gammaSlice, Dims, 1);

			slicePtr->~Image4DSimple();
			operator delete(slicePtr);
			if (slice1D) { delete[] slice1D; slice1D = 0; }
			if (gammaSlice) { delete[] gammaSlice; gammaSlice = 0; }
		}
	}
}

void SegPipe_Controller::histQuickList()
{
	for (QStringList::iterator caseIt = this->caseList.begin(); caseIt != this->caseList.end(); ++caseIt)
	{
		pair<multimap<string, string>::iterator, multimap<string, string>::iterator> range;
		range = this->inputMultiCasesSliceFullPaths.equal_range((*caseIt).toStdString());
		QString caseFullPathQ = this->inputCaseRootPath + "/" + *caseIt;

		int sliceCount = 0;
		for (multimap<string, string>::iterator sliceIt = range.first; sliceIt != range.second; ++sliceIt)
		{
			++sliceCount;
			const char* inputFullPathC = (sliceIt->second).c_str();
			Image4DSimple* slicePtr = new Image4DSimple;
			slicePtr->loadImage(inputFullPathC);
			int dims[3];
			dims[0] = int(slicePtr->getXDim());
			dims[1] = int(slicePtr->getYDim());
			dims[2] = 1;
			long int totalbyteSlice = slicePtr->getTotalBytes();
			unsigned char* slice1D = new unsigned char[totalbyteSlice];
			memcpy(slice1D, slicePtr->getRawData(), totalbyteSlice);
			map<int, size_t> histMap = ImgProcessor::histQuickList(slice1D, dims);
			cout << "slice No: " << sliceCount << endl;
			for (map<int, size_t>::iterator it = histMap.begin(); it != histMap.end(); ++it) cout << it->first << " " << it->second << endl;
			cout << endl;

			slicePtr->~Image4DSimple();
			operator delete(slicePtr);
			if (slice1D) { delete[] slice1D; slice1D = 0; }
		}
	}
}

void SegPipe_Controller::findSomaMass(int somaSizeThre)
{
	for (QStringList::iterator caseIt = this->caseList.begin(); caseIt != this->caseList.end(); ++caseIt)
	{
		QString saveCaseFullNameQ = this->outputRootPath + "/" + *caseIt;
		if (!QDir(saveCaseFullNameQ).exists()) QDir().mkpath(saveCaseFullNameQ);
		else
		{
			cerr << "This folder already exists. Skip case: " << (*caseIt).toStdString() << endl;
			continue;
		}
		string saveFullPathRoot = saveCaseFullNameQ.toStdString();

		pair<multimap<string, string>::iterator, multimap<string, string>::iterator> range;
		range = this->inputMultiCasesSliceFullPaths.equal_range((*caseIt).toStdString());
		QString caseFullPathQ = this->inputCaseRootPath + "/" + *caseIt;

		myImgManagerPtr->imgDatabase.clear();
		myImgManagerPtr->inputMultiCasesSliceFullPaths = this->inputMultiCasesSliceFullPaths;
		myImgManagerPtr->imgEntry((*caseIt).toStdString(), ImgManager::slices);

		map<int, map<int, size_t>> histMapAllSlice;
		int sliceCount = 0;
		cout << "processing slice: ";
		for (map<string, myImg1DPtr>::iterator sliceIt = myImgManagerPtr->imgDatabase.begin()->second.slicePtrs.begin();
			sliceIt != myImgManagerPtr->imgDatabase.begin()->second.slicePtrs.end(); ++sliceIt)
		{
			map<int, size_t> histMap = ImgProcessor::histQuickList(sliceIt->second.get(), myImgManagerPtr->imgDatabase.begin()->second.dims);
			histMapAllSlice.insert(pair<int, map<int, size_t>>(sliceCount, histMap));
			++sliceCount;
			cout << sliceCount << " ";
		}
		cout << endl;

		int pixelCount = 0;
		int currThre = 256;
		while (pixelCount <= somaSizeThre)
		{
			--currThre;
			cout << "current threshold: " << currThre;
			for (map<int, map<int, size_t>>::iterator sliceHistIt = histMapAllSlice.begin(); sliceHistIt != histMapAllSlice.end(); ++sliceHistIt)
			{
				if (sliceHistIt->second.find(currThre) != sliceHistIt->second.end()) pixelCount = pixelCount + sliceHistIt->second[currThre];
			}
			cout << " thresholded pixel number: " << pixelCount << endl;
		}

		for (map<string, myImg1DPtr>::iterator sliceIt = myImgManagerPtr->imgDatabase.begin()->second.slicePtrs.begin();
			sliceIt != myImgManagerPtr->imgDatabase.begin()->second.slicePtrs.end(); ++sliceIt)
		{
			unsigned char* slice1DPtr = new unsigned char[myImgManagerPtr->imgDatabase.begin()->second.dims[0] * myImgManagerPtr->imgDatabase.begin()->second.dims[1]];
			ImgProcessor::simpleThresh(sliceIt->second.get(), slice1DPtr, myImgManagerPtr->imgDatabase.begin()->second.dims, currThre);

			V3DLONG Dims[4];
			Dims[0] = myImgManagerPtr->imgDatabase.begin()->second.dims[0];
			Dims[1] = myImgManagerPtr->imgDatabase.begin()->second.dims[1];
			Dims[2] = 1;
			Dims[3] = 1;
			string sliceSaveFullName = saveFullPathRoot + "/" + sliceIt->first;
			const char* sliceSaveFullNameC = sliceSaveFullName.c_str();
			ImgManager::saveimage_wrapper(sliceSaveFullNameC, slice1DPtr, Dims, 1);

			delete[] slice1DPtr;
		}
	}
}

void SegPipe_Controller::findSignalBlobs2D()
{
	myImgManagerPtr->inputMultiCasesSliceFullPaths = this->inputMultiCasesSliceFullPaths;
	for (QStringList::iterator caseIt = this->caseList.begin(); caseIt != this->caseList.end(); ++caseIt)
	{
		cout << "Processing case " << (*caseIt).toStdString() << ":" << endl;
		pair<multimap<string, string>::iterator, multimap<string, string>::iterator> range;
		range = this->inputMultiCasesSliceFullPaths.equal_range((*caseIt).toStdString());
		QString caseFullPathQ = this->inputCaseRootPath + "/" + *caseIt;
		vector<unsigned char**> slice2DVector;

		QString swcSaveFullNameQ = this->outputRootPath + "/" + *caseIt + ".swc";
		QFile swcFileCheck(swcSaveFullNameQ);
		if (swcFileCheck.exists())
		{
			cerr << "This case is complete. Skip " << (*caseIt).toStdString() << endl;
			continue;
		}

		myImgManagerPtr->imgDatabase.clear();
		myImgManagerPtr->imgEntry((*caseIt).toStdString(), ImgManager::slices);
		int dims[3];
		dims[0] = myImgManagerPtr->imgDatabase[(*caseIt).toStdString()].dims[0];
		dims[1] = myImgManagerPtr->imgDatabase[(*caseIt).toStdString()].dims[1];
		dims[2] = myImgManagerPtr->imgDatabase[(*caseIt).toStdString()].dims[2];
		unsigned char* MIP1Dptr = new unsigned char[dims[0] * dims[1]];
		for (int i = 0; i < dims[0] * dims[1]; ++i) MIP1Dptr[i] = 0;

		for (map<string, myImg1DPtr>::iterator sliceIt = myImgManagerPtr->imgDatabase[(*caseIt).toStdString()].slicePtrs.begin();
			sliceIt != myImgManagerPtr->imgDatabase[(*caseIt).toStdString()].slicePtrs.end(); ++sliceIt)
		{
			ImgProcessor::imgMax(sliceIt->second.get(), MIP1Dptr, MIP1Dptr, dims);

			unsigned char** slice2DPtr = new unsigned char*[dims[1]];
			for (int j = 0; j < dims[1]; ++j)
			{
				slice2DPtr[j] = new unsigned char[dims[0]];
				for (int i = 0; i < dims[0]; ++i) slice2DPtr[j][i] = sliceIt->second.get()[dims[0] * j + i];
			}
			slice2DVector.push_back(slice2DPtr);
		}
		cout << "slice preparation done." << endl;

		this->signalBlobs.clear();
		ImgAnalyzer* myAnalyzer = new ImgAnalyzer;
		this->signalBlobs = myImgAnalyzerPtr->findSignalBlobs_2Dcombine(slice2DVector, dims, MIP1Dptr);

		// ----------- Releasing memory ------------
		delete[] MIP1Dptr;
		MIP1Dptr = nullptr;
		for (vector<unsigned char**>::iterator slice2DPtrIt = slice2DVector.begin(); slice2DPtrIt != slice2DVector.end(); ++slice2DPtrIt)
		{
			for (int yi = 0; yi < dims[1]; ++yi)
			{
				delete[] (*slice2DPtrIt)[yi];
				(*slice2DPtrIt)[yi] = nullptr;
			}
			delete[] *slice2DPtrIt;
			*slice2DPtrIt = nullptr;
		}
		slice2DVector.clear();
		// ------- END of [Releasing memory] -------

		QList<NeuronSWC> allSigs;
		for (vector<connectedComponent>::iterator connIt = this->signalBlobs.begin(); connIt != this->signalBlobs.end(); ++connIt)
		{
			for (map<int, set<vector<int>>>::iterator sliceSizeIt = connIt->coordSets.begin(); sliceSizeIt != connIt->coordSets.end(); ++sliceSizeIt)
			{
				for (set<vector<int>>::iterator nodeIt = sliceSizeIt->second.begin(); nodeIt != sliceSizeIt->second.end(); ++nodeIt)
				{
					NeuronSWC sig;
					V3DLONG blobID = connIt->islandNum;
					sig.n = blobID;
					sig.x = nodeIt->at(1);
					sig.y = nodeIt->at(0);
					sig.z = sliceSizeIt->first;
					sig.type = 2;
					sig.parent = -1;
					allSigs.push_back(sig);
				}
			}
		}
		NeuronTree sigTree;
		sigTree.listNeuron = allSigs;
		writeSWC_file(swcSaveFullNameQ, sigTree);
		allSigs.clear();
	}
}

void SegPipe_Controller::swc2DsignalBlobsCenter()
{
	for (QStringList::iterator caseIt = this->caseList.begin(); caseIt != this->caseList.end(); ++caseIt)
	{
		QString swcFileFullPathQ = this->inputSWCRootPath + "/" + *caseIt;
		QFile swcFileCheck(swcFileFullPathQ);
		if (!swcFileCheck.exists())
		{
			cerr << "This case hasn't been generated. Skip " << (*caseIt).toStdString() << endl;
			continue;
		}
		NeuronTree currTree = readSWC_file(swcFileFullPathQ);
		vector<connectedComponent> signalBlobs2D = myNeuronUtilPtr->swc2signal2DBlobs(currTree);
		//cout << signalBlobs2D.size() << endl;

		this->centers.clear();
		for (vector<connectedComponent>::iterator it = signalBlobs2D.begin(); it != signalBlobs2D.end(); ++it)
		{
			if (it->size <= 3) continue;
			ImgAnalyzer::ChebyshevCenter_connComp(*it);
			NeuronSWC centerNode;
			centerNode.n = it->islandNum;
			centerNode.x = it->ChebyshevCenter[0];
			centerNode.y = it->ChebyshevCenter[1];
			centerNode.z = it->ChebyshevCenter[2];
			centerNode.type = 2;
			centerNode.parent = -1;
			this->centers.push_back(centerNode);
		}

		NeuronTree centerTree;
		centerTree.listNeuron = this->centers;
		QString swcSaveFullNameQ = this->outputRootPath + "/" + *caseIt;
		writeSWC_file(swcSaveFullNameQ, centerTree);
	}
}

void SegPipe_Controller::swcSignalBlob3Dcenter()
{
	for (QStringList::iterator caseIt = this->caseList.begin(); caseIt != this->caseList.end(); ++caseIt)
	{
		QString swcFileFullPathQ = this->inputSWCRootPath + "/" + *caseIt;
		QFile swcFileCheck(swcFileFullPathQ);
		if (!swcFileCheck.exists())
		{
			cerr << "This case hasn't been generated. Skip " << (*caseIt).toStdString() << endl;
			continue;
		}
		NeuronTree currTree = readSWC_file(swcFileFullPathQ);
		vector<connectedComponent> signalBlobs3D = myNeuronUtilPtr->swc2signal3DBlobs(currTree);

		this->centers.clear();
		for (vector<connectedComponent>::iterator it = signalBlobs3D.begin(); it != signalBlobs3D.end(); ++it)
		{
			if (it->size <= 3) continue;

			ImgAnalyzer::ChebyshevCenter_connComp(*it);
			NeuronSWC centerNode;
			centerNode.n = it->islandNum;
			centerNode.x = it->ChebyshevCenter[0];
			centerNode.y = it->ChebyshevCenter[1];
			centerNode.z = it->ChebyshevCenter[2];
			centerNode.type = 2;
			centerNode.parent = -1;
			this->centers.push_back(centerNode);
		}

		NeuronTree centerTree;
		centerTree.listNeuron = this->centers;
		QString swcSaveFullNameQ = this->outputRootPath + "/" + *caseIt;
		writeSWC_file(swcSaveFullNameQ, centerTree);
	}
}

void SegPipe_Controller::getChebyshevCenters(QString caseNum)
{
	this->centers.clear();
	for (vector<connectedComponent>::iterator it = this->signalBlobs.begin(); it != this->signalBlobs.end(); ++it)
	{
		ImgAnalyzer::ChebyshevCenter_connComp(*it);

		NeuronSWC centerNode;
		centerNode.x = it->ChebyshevCenter[1];
		centerNode.y = it->ChebyshevCenter[0];
		centerNode.z = it->ChebyshevCenter[2];
		centerNode.type = 2;
		centerNode.parent = -1;
		this->centers.push_back(centerNode);
	}

	NeuronTree centerTree;
	centerTree.listNeuron = this->centers;
	QString swcSaveFullNameQ = this->outputRootPath + "/centers/" + caseNum + ".swc";
	writeSWC_file(swcSaveFullNameQ, centerTree);

}

void SegPipe_Controller::getSomaCandidates(float distThre)
{
	for (QStringList::iterator caseIt = this->caseList.begin(); caseIt != this->caseList.end(); ++caseIt)
	{
		QString swcFileFullPathQ = this->inputSWCRootPath + "/" + *caseIt;
		QFile swcFileCheck(swcFileFullPathQ);
		if (!swcFileCheck.exists())
		{
			cerr << "This case hasn't been generated. Skip " << (*caseIt).toStdString() << endl;
			continue;
		}
		NeuronTree currTree = readSWC_file(swcFileFullPathQ);

		vector<connectedComponent> somaCandidateList;
		if (distThre == 30) somaCandidateList = NeuronStructUtil::swc2clusters_distance(currTree);
		else somaCandidateList = NeuronStructUtil::swc2clusters_distance(currTree, distThre);
		NeuronTree somaOutput;
		int nodeNum = 1;
		for (vector<connectedComponent>::iterator connCompIt = somaCandidateList.begin(); connCompIt != somaCandidateList.end(); ++connCompIt)
		{
			ImgAnalyzer::ChebyshevCenter_connComp(*connCompIt);

			NeuronSWC somaNode;
			somaNode.n = nodeNum;
			somaNode.x = connCompIt->ChebyshevCenter[0];
			somaNode.y = connCompIt->ChebyshevCenter[1];
			somaNode.z = connCompIt->ChebyshevCenter[2];
			somaNode.type = 1;
			somaNode.parent = -1;
			somaOutput.listNeuron.push_back(somaNode);

			++nodeNum;
		}
		QString swcSaveFullNameQ = this->outputRootPath + "/" + *caseIt;
		writeSWC_file(swcSaveFullNameQ, somaOutput);
	}
}

void SegPipe_Controller::somaDendriteMask()
{
	myImgManagerPtr->imgDatabase.clear();
	myImgManagerPtr->inputCaseRootPath = this->inputCaseRootPath;
	for (QStringList::iterator caseIt = this->caseList.begin(); caseIt != this->caseList.end(); ++caseIt)
	{
		QStringList nameSplit = (*caseIt).split(".");
		string caseName = nameSplit.at(0).toStdString();
		myImgManagerPtr->inputSingleCaseFullPath = this->inputCaseRootPath.toStdString() + "/" + (*caseIt).toStdString();
		myImgManagerPtr->imgEntry(caseName, ImgManager::singleCase);
		QString swcFileFullPathQ = this->inputSWCRootPath + "/" + QString::fromStdString(caseName) + ".swc";
		NeuronTree currTree = readSWC_file(swcFileFullPathQ);

		int xCoord, yCoord;
		float zCoord = 0;
		for (QList<NeuronSWC>::iterator it = currTree.listNeuron.begin(); it != currTree.listNeuron.end(); ++it)
		{
			if (it->z > zCoord)
			{
				xCoord = int(it->x);
				yCoord = int(it->y);
				zCoord = int(it->z);
			}
		}

		set<vector<int>> whitePixSet = myImgAnalyzerPtr->somaDendrite_radialDetect2D(myImgManagerPtr->imgDatabase.begin()->second.slicePtrs.begin()->second.get(),
			xCoord, yCoord, myImgManagerPtr->imgDatabase.begin()->second.dims);

		unsigned char* dendriteDetect2D = new unsigned char[myImgManagerPtr->imgDatabase.begin()->second.dims[0] * myImgManagerPtr->imgDatabase.begin()->second.dims[1]];
		for (size_t i = 0; i < myImgManagerPtr->imgDatabase.begin()->second.dims[0] * myImgManagerPtr->imgDatabase.begin()->second.dims[1]; ++i)
			dendriteDetect2D[i] = 0;

		for (set<vector<int>>::iterator coordIt = whitePixSet.begin(); coordIt != whitePixSet.end(); ++coordIt)
		{
			size_t index = size_t((coordIt->at(1) - 1) * myImgManagerPtr->imgDatabase.begin()->second.dims[0]) + size_t(coordIt->at(0));
			dendriteDetect2D[index] = 255;
		}

		V3DLONG saveDims[4];
		saveDims[0] = myImgManagerPtr->imgDatabase.begin()->second.dims[0];
		saveDims[1] = myImgManagerPtr->imgDatabase.begin()->second.dims[1];
		saveDims[2] = 1;
		saveDims[3] = 1;
		QString saveFileNameQ = this->outputRootPath + "/" + *caseIt;
		string saveFileName = saveFileNameQ.toStdString();
		const char* saveFileNameC = saveFileName.c_str();
		ImgManager::saveimage_wrapper(saveFileNameC, dendriteDetect2D, saveDims, 1);

		delete[] dendriteDetect2D;
		myImgManagerPtr->imgDatabase.clear();
	}
}

void SegPipe_Controller::swcMapBack()
{
	QString scaledSWC_saveRootQ = this->outputSWCRootPath;

	myImgManagerPtr->inputMultiCasesSliceFullPaths = this->inputMultiCasesSliceFullPaths;
	for (QStringList::iterator caseIt = this->caseList.begin(); caseIt != this->caseList.end(); ++caseIt)
	{
		cout << "Processing case " << (*caseIt).toStdString() << ":" << endl;

		myImgManagerPtr->imgDatabase.clear();
		myImgManagerPtr->imgEntry((*caseIt).toStdString(), ImgManager::slices);

		QString currInputSWCFile = this->refSWCRootPath + "/" + *caseIt + ".swc";
		NeuronTree currCaseTree = readSWC_file(currInputSWCFile);

		vector<int> offSets = ImgManager::retreiveSWCcropDnParam_imgBased(myImgManagerPtr->imgDatabase[(*caseIt).toStdString()], currCaseTree.listNeuron, 4, 4, 2);
		QString targetedTreeFullNameQ = this->inputSWCRootPath + "/" + *caseIt + ".swc";
		NeuronTree targetedTree = readSWC_file(targetedTreeFullNameQ);
		NeuronTree registeredTree;
		registeredTree.listNeuron.clear();
		for (QList<NeuronSWC>::iterator nodeIt = targetedTree.listNeuron.begin(); nodeIt != targetedTree.listNeuron.end(); ++nodeIt)
		{
			NeuronSWC newNode = *nodeIt;
			newNode.x = (nodeIt->x + offSets.at(0)) * 4;
			newNode.y = (nodeIt->y + offSets.at(1)) * 4;
			newNode.z = (nodeIt->z + offSets.at(2)) * 2;
			registeredTree.listNeuron.push_back(newNode);
		}
		QString newTreeName = scaledSWC_saveRootQ + *caseIt + ".swc";
		writeSWC_file(newTreeName, registeredTree);
	}
}

void SegPipe_Controller::swc_imgCrop()
{
	QString scaledSWC_saveRootQ = this->outputSWCRootPath;

	myImgManagerPtr->inputMultiCasesSliceFullPaths = this->inputMultiCasesSliceFullPaths;
	for (QStringList::iterator caseIt = this->caseList.begin(); caseIt != this->caseList.end(); ++caseIt)
	{
		cout << "Processing case " << (*caseIt).toStdString() << ":" << endl;
		QString saveCaseFullNameQ = this->outputRootPath + "/" + *caseIt;
		if (!QDir(saveCaseFullNameQ).exists()) QDir().mkpath(saveCaseFullNameQ);
		else
		{
			cerr << "This case is done. Skip " << (*caseIt).toStdString() << endl;
			continue;
		}
		string saveCaseFullPathRoot = saveCaseFullNameQ.toStdString();
		myImgManagerPtr->imgDatabase.clear();
		myImgManagerPtr->imgEntry((*caseIt).toStdString(), ImgManager::slices);

		pair<multimap<string, string>::iterator, multimap<string, string>::iterator> range;
		range = this->inputMultiCasesSliceFullPaths.equal_range((*caseIt).toStdString());
		QString caseFullPathQ = this->inputCaseRootPath + "/" + *caseIt;

		QString currInputSWCFile = this->refSWCRootPath + "/" + *caseIt + ".swc";
		NeuronTree currCaseTree = readSWC_file(currInputSWCFile);
		int xlb = 10000, xhb = 0, ylb = 10000, yhb = 0;
		for (QList<NeuronSWC>::iterator nodeIt = currCaseTree.listNeuron.begin(); nodeIt != currCaseTree.listNeuron.end(); ++nodeIt)
		{
			int thisNodeX = int(round(nodeIt->x / 4));
			int thisNodeY = int(round(nodeIt->y / 4));
			if (thisNodeX < xlb) xlb = thisNodeX;
			if (thisNodeX > xhb) xhb = thisNodeX;
			if (thisNodeY < ylb) ylb = thisNodeY;
			if (thisNodeY > yhb) yhb = thisNodeY;
		}
		xlb -= 10; xhb += 10; ylb -= 10; yhb += 10;
		if (xlb <= 0) xlb = 1;
		if (xhb >= myImgManagerPtr->imgDatabase[(*caseIt).toStdString()].dims[0]) xhb = myImgManagerPtr->imgDatabase[(*caseIt).toStdString()].dims[0];
		if (ylb <= 0) ylb = 1;
		if (yhb >= myImgManagerPtr->imgDatabase[(*caseIt).toStdString()].dims[1]) yhb = myImgManagerPtr->imgDatabase[(*caseIt).toStdString()].dims[1];
		int newDims[3];
		newDims[0] = xhb - xlb + 1;
		newDims[1] = yhb - ylb + 1;
		newDims[2] = 1;
		cout << "boundries: " << xlb << " " << xhb << " " << ylb << " " << yhb << endl;

		if (!this->outputSWCRootPath.isEmpty())
		{
			NeuronTree newTree;
			for (QList<NeuronSWC>::iterator nodeIt = currCaseTree.listNeuron.begin(); nodeIt != currCaseTree.listNeuron.end(); ++nodeIt)
			{
				NeuronSWC newNode = *nodeIt;
				newNode.x = (nodeIt->x / 4) - xlb;
				newNode.y = (nodeIt->y / 4) - ylb;
				newNode.z = (nodeIt->z / 2);
				newTree.listNeuron.push_back(newNode);
			}
			QString newTreeName = scaledSWC_saveRootQ + *caseIt + ".swc";
			writeSWC_file(newTreeName, newTree);
		}

		V3DLONG saveDims[4];
		saveDims[0] = newDims[0];
		saveDims[1] = newDims[1];
		saveDims[2] = 1;
		saveDims[3] = 1;

		QString saveImgCasePathQ = this->outputRootPath + "/" + *caseIt + "/";
		if (!QDir(saveImgCasePathQ).exists()) QDir().mkpath(saveImgCasePathQ);
		for (map<string, myImg1DPtr>::iterator sliceIt = myImgManagerPtr->imgDatabase[(*caseIt).toStdString()].slicePtrs.begin();
			sliceIt != myImgManagerPtr->imgDatabase[(*caseIt).toStdString()].slicePtrs.end(); ++sliceIt)
		{
			unsigned char* croppedSlice = new unsigned char[newDims[0] * newDims[1]];
			ImgProcessor::cropImg2D(sliceIt->second.get(), croppedSlice, xlb, xhb, ylb, yhb, myImgManagerPtr->imgDatabase[(*caseIt).toStdString()].dims);

			QString saveFileNameQ = saveImgCasePathQ + QString::fromStdString(sliceIt->first);
			string saveFileName = saveFileNameQ.toStdString();
			const char* saveFileNameC = saveFileName.c_str();
			ImgManager::saveimage_wrapper(saveFileNameC, croppedSlice, saveDims, 1);

			if (croppedSlice) { delete[] croppedSlice; croppedSlice = 0; }
		}
	}
}

void SegPipe_Controller::getMST()
{
	for (QStringList::iterator caseIt = this->caseList.begin(); caseIt != this->caseList.end(); ++caseIt)
	{
		QString swcFileFullPathQ = this->inputSWCRootPath + "/" + *caseIt;
		QFile swcFileCheck(swcFileFullPathQ);
		if (!swcFileCheck.exists())
		{
			cerr << "This case hasn't been generated. Skip " << (*caseIt).toStdString() << endl;
			continue;
		}
		NeuronTree currTree = readSWC_file(swcFileFullPathQ);
		NeuronTree MSTtree = myNeuronStructExpPtr->SWC2MSTtree(currTree);

		QString outputSWCFullPath = this->outputRootPath + "/" + *caseIt;
		writeSWC_file(outputSWCFullPath, MSTtree);
	}
}

void SegPipe_Controller::getMST_2Dslices()
{
	for (QStringList::iterator caseIt = this->caseList.begin(); caseIt != this->caseList.end(); ++caseIt)
	{
		QString swcFileFullPathQ = this->inputSWCRootPath + "/" + *caseIt;
		QFile swcFileCheck(swcFileFullPathQ);
		if (!swcFileCheck.exists())
		{
			cerr << "This case hasn't been generated. Skip " << (*caseIt).toStdString() << endl;
			continue;
		}

		QStringList caseParse = (*caseIt).split(".");
		QString caseNum = caseParse[0];
		QString outputSWCcasePath = this->outputRootPath + "/" + caseNum;
		if (!QDir(outputSWCcasePath).exists()) QDir().mkpath(outputSWCcasePath);
		else
		{
			cerr << "This case is done. Skip " << caseNum.toStdString() << endl;
			continue;
		}

		NeuronTree currTree = readSWC_file(swcFileFullPathQ);
		float zMax = 0;
		for (QList<NeuronSWC>::iterator zIt = currTree.listNeuron.begin(); zIt != currTree.listNeuron.end(); ++zIt)
			if (zIt->z > zMax) zMax = zIt->z;

		vector<connectedComponent> blob2D = myNeuronUtilPtr->swc2signal2DBlobs(currTree);
		vector<NeuronTree> MSTsliceTrees;
		NeuronTree thisSliceTree;
		for (int i = 0; i <= int(zMax); ++i)
		{
			thisSliceTree.listNeuron.clear();
			for (vector<connectedComponent>::iterator blobIt = blob2D.begin(); blobIt != blob2D.end(); ++blobIt)
			{
				if (blobIt->coordSets.begin()->first == i)
				{
					NeuronSWC centerSWC;
					centerSWC.n = blobIt->islandNum;
					centerSWC.type = 2;
					centerSWC.x = blobIt->ChebyshevCenter[0];
					centerSWC.y = blobIt->ChebyshevCenter[1];
					centerSWC.z = blobIt->ChebyshevCenter[2];
					centerSWC.parent = -1;
					thisSliceTree.listNeuron.push_back(centerSWC);
				}
			}
			if (thisSliceTree.listNeuron.isEmpty()) continue;

			NeuronTree thisSliceMSTtree = myNeuronStructExpPtr->SWC2MSTtree(thisSliceTree);
			NeuronTree outputTree = NeuronStructExplorer::MSTtreeCut(thisSliceMSTtree, 15);
			MSTsliceTrees.push_back(outputTree);
		}

		for (vector<NeuronTree>::iterator treeIt = MSTsliceTrees.begin(); treeIt != MSTsliceTrees.end(); ++treeIt)
		{
			QString sliceMSTtreeSaveName = outputSWCcasePath + "/" + QString::number((int(treeIt - MSTsliceTrees.begin()))) + ".swc";
			writeSWC_file(sliceMSTtreeSaveName, *treeIt);
		}
	}
}

void SegPipe_Controller::cutMST()
{
	for (QStringList::iterator caseIt = this->caseList.begin(); caseIt != this->caseList.end(); ++caseIt)
	{
		QString swcFileFullPathQ = this->inputSWCRootPath + "/" + *caseIt;
		QFile swcFileCheck(swcFileFullPathQ);
		if (!swcFileCheck.exists())
		{
			cerr << "This case hasn't been generated. Skip " << (*caseIt).toStdString() << endl;
			continue;
		}
		NeuronTree currTree = readSWC_file(swcFileFullPathQ);
		NeuronTree outputTree = NeuronStructExplorer::MSTtreeCut(currTree, 50);

		QString outputSWCFullPath = this->outputRootPath + "/" + *caseIt;
		writeSWC_file(outputSWCFullPath, outputTree);
	}
}

void SegPipe_Controller::MSTtrim()
{
	for (QStringList::iterator caseIt = this->caseList.begin(); caseIt != this->caseList.end(); ++caseIt)
	{
		QString swcFileFullPathQ = this->inputSWCRootPath + "/" + *caseIt;
		QFile swcFileCheck(swcFileFullPathQ);
		if (!swcFileCheck.exists())
		{
			cerr << "This case hasn't been generated. Skip " << (*caseIt).toStdString() << endl;
			continue;
		}
		NeuronTree inputTree = readSWC_file(swcFileFullPathQ);
		profiledTree currTree(inputTree);
		/*vector<segUnit> segs = myNeuronStructExpPtr->MSTtreeTrim(currTree.segs);
		NeuronTree outputTree;
		for (vector<segUnit>::iterator it = segs.begin(); it != segs.end(); ++it)
		{
			for (QList<NeuronSWC>::iterator nodeIt = it->nodes.begin(); nodeIt != it->nodes.end(); ++nodeIt)
				outputTree.listNeuron.push_back(*nodeIt);
		}

		QString outputSWCFullPath = this->outputRootPath + "/" + *caseIt;
		writeSWC_file(outputSWCFullPath, outputTree);*/
	}
}

void SegPipe_Controller::breakMSTbranch()
{
	for (QStringList::iterator caseIt = this->caseList.begin(); caseIt != this->caseList.end(); ++caseIt)
	{
		QString swcFileFullPathQ = this->inputSWCRootPath + "/" + *caseIt;
		QFile swcFileCheck(swcFileFullPathQ);
		if (!swcFileCheck.exists())
		{
			cerr << "This case hasn't been generated. Skip " << (*caseIt).toStdString() << endl;
			continue;
		}
		NeuronTree currTree = readSWC_file(swcFileFullPathQ);
		myNeuronStructExpPtr->treeEntry(currTree, "currTree");
		NeuronTree outputTree = myNeuronStructExpPtr->MSTbranchBreak(myNeuronStructExpPtr->treeDataBase["currTree"], 20, false);

		QString outputSWCFullPath = this->outputRootPath + "/" + *caseIt;
		writeSWC_file(outputSWCFullPath, outputTree);

		myNeuronStructExpPtr->treeDataBase.clear();
	}
}

void SegPipe_Controller::getTiledMST()
{
	float xyLength = 40;
	map<string, QList<NeuronSWC>> tiledSWCmap;
	for (QStringList::iterator caseIt = this->caseList.begin(); caseIt != this->caseList.end(); ++caseIt)
	{
		tiledSWCmap.clear();
		QString swcFullPath = this->inputSWCRootPath + "/" + *caseIt;
		NeuronTree inputTree = readSWC_file(swcFullPath);
		QList<NeuronSWC> tileSWCList;
		tileSWCList.clear();
		for (QList<NeuronSWC>::iterator it = inputTree.listNeuron.begin(); it != inputTree.listNeuron.end(); ++it)
		{
			int tileXlabel = int(floor(it->x / 500));
			int tileYlabel = int(floor(it->y / 500));
			int tileZlabel = int(floor(it->z / (125 / zRATIO)));
			string swcTileKey = to_string(tileXlabel) + "_" + to_string(tileYlabel) + "_" + to_string(tileZlabel);
			tiledSWCmap.insert(pair<string, QList<NeuronSWC>>(swcTileKey, tileSWCList));
			tiledSWCmap[swcTileKey].push_back(*it);
		}
		cout << "tiledSWCmap size = " << tiledSWCmap.size() << endl;

		NeuronTree assembledTree;
		for (map<string, QList<NeuronSWC>>::iterator it = tiledSWCmap.begin(); it != tiledSWCmap.end(); ++it)
		{
			NeuronTree tileTree;
			tileTree.listNeuron = it->second;
			NeuronTree tileMSTtree = myNeuronStructExpPtr->SWC2MSTtree(tileTree);

			int currnodeNum = assembledTree.listNeuron.size();
			for (QList<NeuronSWC>::iterator nodeIt = tileMSTtree.listNeuron.begin(); nodeIt != tileMSTtree.listNeuron.end(); ++nodeIt)
			{
				nodeIt->n = nodeIt->n + currnodeNum;
				if (nodeIt->parent != -1)
				{
					nodeIt->parent = nodeIt->parent + currnodeNum;
					//cout << "  " << nodeIt->parent << " " << currnodeNum << endl;
				}

				//cout << nodeIt->n << " " << nodeIt->parent << endl;
				assembledTree.listNeuron.push_back(*nodeIt);
			}
		}

		QString outputSWCPath = this->outputRootPath + "/" + *caseIt;
		writeSWC_file(outputSWCPath, assembledTree);
	}
}

void SegPipe_Controller::swcRegister()
{
	for (QStringList::iterator caseIt = this->caseList.begin(); caseIt != this->caseList.end(); ++caseIt)
	{
		QString swcFullPath = this->inputSWCRootPath + "/" + *caseIt;
		NeuronTree inputTree = readSWC_file(swcFullPath);
		QString refSWCPath = this->refSWCRootPath + "/" + *caseIt;
		QFile refCheck(refSWCPath);
		if (!refCheck.exists())
		{
			cerr << "No refSWC for this case. Skip  " << (*caseIt).toStdString() << endl;
			continue;
		}
		NeuronTree refTree = readSWC_file(refSWCPath);

		NeuronTree regTree = NeuronStructUtil::swcRegister(inputTree, refTree);
		QString outputSWCPath = this->outputRootPath + "/" + *caseIt;
		writeSWC_file(outputSWCPath, regTree);
	}
}

void SegPipe_Controller::swcScale(float xScale, float yScale, float zScale)
{
	for (QStringList::iterator caseIt = this->caseList.begin(); caseIt != this->caseList.end(); ++caseIt)
	{
		QString swcFullPath = this->inputSWCRootPath + "/" + *caseIt;
		NeuronTree inputTree = readSWC_file(swcFullPath);

		NeuronTree scaledTree = NeuronStructUtil::swcScale(inputTree, xScale, yScale, zScale);
		QString outputSWCPath = this->outputRootPath + "/" + *caseIt;
		writeSWC_file(outputSWCPath, scaledTree);
	}
}

void SegPipe_Controller::correctSWC()
{
	QString scaledSWC_saveRootQ = this->outputSWCRootPath;

	for (QStringList::iterator caseIt = this->caseList.begin(); caseIt != this->caseList.end(); ++caseIt)
	{
		pair<multimap<string, string>::iterator, multimap<string, string>::iterator> range;
		range = this->inputMultiCasesSliceFullPaths.equal_range((*caseIt).toStdString());
		string inputSliceFullPath = range.first->second;
		myImgManagerPtr->inputSingleCaseFullPath = inputSliceFullPath;
		myImgManagerPtr->imgEntry((*caseIt).toStdString(), ImgManager::singleCase);

		QString currInputSWCFile = this->refSWCRootPath + "/" + *caseIt + ".swc";
		NeuronTree currCaseTree = readSWC_file(currInputSWCFile);
		int xlb = 10000, xhb = 0, ylb = 10000, yhb = 0;
		for (QList<NeuronSWC>::iterator nodeIt = currCaseTree.listNeuron.begin(); nodeIt != currCaseTree.listNeuron.end(); ++nodeIt)
		{
			int thisNodeX = int(round(nodeIt->x / 4));
			int thisNodeY = int(round(nodeIt->y / 4));
			if (thisNodeX < xlb) xlb = thisNodeX;
			if (thisNodeX > xhb) xhb = thisNodeX;
			if (thisNodeY < ylb) ylb = thisNodeY;
			if (thisNodeY > yhb) yhb = thisNodeY;
		}
		xlb -= 10; xhb += 10; ylb -= 10; yhb += 10;
		if (xlb <= 0) xlb = 1;
		if (xhb >= myImgManagerPtr->imgDatabase[(*caseIt).toStdString()].dims[0]) xhb = myImgManagerPtr->imgDatabase[(*caseIt).toStdString()].dims[0];
		if (ylb <= 0) ylb = 1;
		if (yhb >= myImgManagerPtr->imgDatabase[(*caseIt).toStdString()].dims[1]) yhb = myImgManagerPtr->imgDatabase[(*caseIt).toStdString()].dims[1];
		int newDims[3];
		newDims[0] = xhb - xlb + 1;
		newDims[1] = yhb - ylb + 1;
		newDims[2] = 1;
		cout << "boundries: " << xlb << " " << xhb << " " << ylb << " " << yhb << endl;

		NeuronTree correctedTree = this->swcBackTrack(4, 4, 2, xlb, ylb, 0, currCaseTree);
		QString outputSWCPath = this->outputRootPath + "/" + *caseIt + ".swc";
		writeSWC_file(outputSWCPath, correctedTree);

		myImgManagerPtr->inputSingleCaseFullPath.clear();
	}
}

void SegPipe_Controller::nodeIdentify()
{
	for (QStringList::iterator caseIt = this->caseList.begin(); caseIt != this->caseList.end(); ++caseIt)
	{
		QString swcFullPath = this->inputSWCRootPath + "/" + *caseIt;
		NeuronTree inputTree = readSWC_file(swcFullPath);

		QString refSWCfullPath = this->refSWCRootPath + "/" + *caseIt;
		NeuronTree refTree = readSWC_file(refSWCfullPath);

		NeuronTree diffTree = NeuronStructUtil::swcIdentityCompare(inputTree, refTree, 20);
		QString outputSWCPath = this->outputRootPath + "/" + *caseIt;
		writeSWC_file(outputSWCPath, diffTree);
	}
}

void SegPipe_Controller::cleanUpzFor2Dcentroids()
{
	for (QStringList::iterator caseIt = this->caseList.begin(); caseIt != this->caseList.end(); ++caseIt)
	{
		QString swcFullPath = this->inputSWCRootPath + "/" + *caseIt;
		NeuronTree inputTree = readSWC_file(swcFullPath);

		NeuronTree cleanedZtree = NeuronStructUtil::swcZclenUP(inputTree);
		QString outputSWCPath = this->outputRootPath + "/" + *caseIt;
		writeSWC_file(outputSWCPath, cleanedZtree);
	}
}

void SegPipe_Controller::swcSeparate(QString outputRoot2)
{
	for (QStringList::iterator caseIt = this->caseList.begin(); caseIt != this->caseList.end(); ++caseIt)
	{
		QString swcFullPath = this->inputSWCRootPath + "/" + *caseIt;
		NeuronTree inputTree = readSWC_file(swcFullPath);

		NeuronTree sigTree;
		NeuronTree noiseTree;

		for (QList<NeuronSWC>::iterator it = inputTree.listNeuron.begin(); it != inputTree.listNeuron.end(); ++it)
		{
			NeuronSWC thisNode = *it;
			if (it->type == 2) sigTree.listNeuron.push_back(thisNode);
			else if (it->type == 3) noiseTree.listNeuron.push_back(thisNode);
		}

		QString outputSWCPath = this->outputRootPath + "/" + *caseIt;
		QString outputSWCPath2 = outputRoot2 + "/" + *caseIt;
		writeSWC_file(outputSWCPath, sigTree);
		writeSWC_file(outputSWCPath2, noiseTree);
	}
}

void SegPipe_Controller::swcTypeSeparate(int type)
{
	for (QStringList::iterator caseIt = this->caseList.begin(); caseIt != this->caseList.end(); ++caseIt)
	{
		QString swcFullPath = this->inputSWCRootPath + "/" + *caseIt;
		NeuronTree inputTree = readSWC_file(swcFullPath);

		map<int, QList<NeuronSWC>> nodeTypeMap = NeuronStructUtil::swcSplitByType(inputTree);
		NeuronTree signalTree;
		signalTree.listNeuron = nodeTypeMap.at(type);

		QString outputSWCPath = this->outputRootPath + "/" + *caseIt;
		writeSWC_file(outputSWCPath, signalTree);
	}
}

void SegPipe_Controller::swcSubtraction(int type)
{
	for (QStringList::iterator caseIt = this->caseList.begin(); caseIt != this->caseList.end(); ++caseIt)
	{
		QString swcFullPath = this->inputSWCRootPath + "/" + *caseIt;
		NeuronTree inputTree = readSWC_file(swcFullPath);
		QString refSwcFullPath = this->inputSWCRootPath2 + "/" + *caseIt;
		NeuronTree refTree = readSWC_file(refSwcFullPath);
		qDebug() << swcFullPath << " " << refSwcFullPath;

		NeuronTree outputTree = NeuronStructUtil::swcSubtraction(inputTree, refTree, type);

		QString outputSWCPath = this->outputRootPath + "/" + *caseIt;
		writeSWC_file(outputSWCPath, outputTree);
	}
}

void SegPipe_Controller::swcUpSample()
{
	for (QStringList::iterator caseIt = this->caseList.begin(); caseIt != this->caseList.end(); ++caseIt)
	{
		QString swcFullPath = this->inputSWCRootPath + "/" + *caseIt;
		NeuronTree inputTree = readSWC_file(swcFullPath);
		profiledTree inputProfiledTree(inputTree);
		profiledTree outputProfiledTree;
		NeuronStructExplorer::treeUpSample(inputProfiledTree, outputProfiledTree, 5);

		QString outputSWCPath = this->outputRootPath + "/" + *caseIt;
		writeSWC_file(outputSWCPath, outputProfiledTree.tree);
	}
}

void SegPipe_Controller::segElongation()
{
	for (QStringList::iterator caseIt = this->caseList.begin(); caseIt != this->caseList.end(); ++caseIt)
	{
		QString swcFullPath = this->inputSWCRootPath + "/" + *caseIt;
		NeuronTree inputTree = readSWC_file(swcFullPath);
		string treeName = (*caseIt).toStdString();
		treeName = treeName.substr(0, treeName.length() - 3);

		myNeuronStructExpPtr->treeEntry(inputTree, treeName, 50); // for axon, treeTileLength = 80;
		profiledTree elongatedTree = myNeuronStructExpPtr->itered_segElongate(myNeuronStructExpPtr->treeDataBase.begin()->second, 0.40); // for axon, angle threshold = 0.30;
		QString outputSWCPath = this->outputRootPath + "/" + *caseIt;
		writeSWC_file(outputSWCPath, elongatedTree.tree);

		myNeuronStructExpPtr->treeDataBase.clear();
	}
}

void SegPipe_Controller::segTerminalize()
{
	for (QStringList::iterator caseIt = this->caseList.begin(); caseIt != this->caseList.end(); ++caseIt)
	{
		QString swcFullPath = this->inputSWCRootPath + "/" + *caseIt;
		NeuronTree inputTree = readSWC_file(swcFullPath);
		string treeName = (*caseIt).toStdString();
		treeName = treeName.substr(0, treeName.length() - 3);

		myNeuronStructExpPtr->treeEntry(inputTree, treeName);
		NeuronTree outputTree = NeuronStructExplorer::segTerminalize(myNeuronStructExpPtr->treeDataBase.begin()->second);
		QString outputSWCPath = this->outputRootPath + "/" + *caseIt;
		writeSWC_file(outputSWCPath, outputTree);

		myNeuronStructExpPtr->treeDataBase.clear();
	}
}

void SegPipe_Controller::dotRemove()
{
	for (QStringList::iterator caseIt = this->caseList.begin(); caseIt != this->caseList.end(); ++caseIt)
	{
		QString swcFullPath = this->inputSWCRootPath + "/" + *caseIt;
		NeuronTree inputTree = readSWC_file(swcFullPath);
		string treeName = (*caseIt).toStdString();
		treeName = treeName.substr(0, treeName.length() - 3);

		myNeuronStructExpPtr->treeEntry(inputTree, treeName);
		NeuronTree outputTree = NeuronStructExplorer::singleDotRemove(myNeuronStructExpPtr->treeDataBase.begin()->second, 2);
		QString outputSWCPath = this->outputRootPath + "/" + *caseIt;
		writeSWC_file(outputSWCPath, outputTree);

		myNeuronStructExpPtr->treeDataBase.clear();
	}
}

void SegPipe_Controller::longConnCut()
{
	for (QStringList::iterator caseIt = this->caseList.begin(); caseIt != this->caseList.end(); ++caseIt)
	{
		QString swcFullPath = this->inputSWCRootPath + "/" + *caseIt;
		NeuronTree inputTree = readSWC_file(swcFullPath);
		string treeName = (*caseIt).toStdString();
		treeName = treeName.substr(0, treeName.length() - 3);

		myNeuronStructExpPtr->treeEntry(inputTree, treeName);
		NeuronTree outputTree = NeuronStructExplorer::longConnCut(myNeuronStructExpPtr->treeDataBase.begin()->second, 50); // for axon, it was set to be 100
		QString outputSWCPath = this->outputRootPath + "/" + *caseIt;
		writeSWC_file(outputSWCPath, outputTree);

		myNeuronStructExpPtr->treeDataBase.clear();
	}
}

void SegPipe_Controller::treeUnion()
{
	for (QStringList::iterator caseIt = this->caseList.begin(); caseIt != this->caseList.end(); ++caseIt)
	{
		QString swcFullPath = this->inputSWCRootPath + "/" + *caseIt;
		NeuronTree MST2ndTree = readSWC_file(swcFullPath);
		profiledTree profiledMST2ndTree(MST2ndTree);

		QString refSWCfullPath = this->refSWCRootPath + "/" + *caseIt;
		NeuronTree baseTree = readSWC_file(refSWCfullPath);
		profiledTree profiledBaseTree(baseTree);

		profiledTree outputProfiledTree = myNeuronStructExpPtr->treeUnion_MSTbased(profiledMST2ndTree, profiledBaseTree);
		NeuronTree outputTree = outputProfiledTree.tree;
		QString outputSWCPath = this->outputRootPath + "/" + *caseIt;
		writeSWC_file(outputSWCPath, outputTree);
	}
}

void SegPipe_Controller::treeWithinDist()
{
	string dist2D = "dist2D.txt";
	string dist3D = "dist3D.txt";
	string outputName = outputRootPath.toStdString() + "/" + dist3D;
	ofstream outputFile(outputName.c_str());
	outputFile << "case num\t" << "mean\t" << "std\t" << "median" << endl;
	for (QStringList::iterator caseIt = this->caseList.begin(); caseIt != this->caseList.end(); ++caseIt)
	{
		QString swcFullPath = this->inputSWCRootPath + "/" + *caseIt;
		NeuronTree inputTree = readSWC_file(swcFullPath);
		string treeName = (*caseIt).toStdString();
		treeName = treeName.substr(0, treeName.length() - 3);

		map<string, float> swcWithinStats = NeuronStructUtil::selfNodeDist(inputTree.listNeuron);
		outputFile << (*caseIt).toStdString() << "\t" << swcWithinStats["mean"] << "\t" << swcWithinStats["std"] << "\t" << swcWithinStats["median"] << endl;
	}
	outputFile.close();
}


text:
#include <boost/python.hpp>
#include "EvolutionIndirect.h"

class EvolutionIndirect_python : public EvolutionIndirect {
public:
  EvolutionIndirect_python(std::string experiment_name,
                      std::string type_experiment)
     : EvolutionIndirect(experiment_name, type_experiment)
  {}

//  double runExperiment()
//  {
//    EvolutionIndirect::runExperiment(0, nullptr);
//  }

};

BOOST_PYTHON_MODULE (lsystem_python)
{
  boost::python::class_< EvolutionIndirect_python, boost::noncopyable >(
          "EvolutionIndirect",
          boost::python::init< std::string,
                               std::string >())
      .def("setupEvolution",
           &EvolutionIndirect_python::setupEvolution)
      .def("runExperiment_evolve1",
           &EvolutionIndirect_python::runExperiment_evolve1)
      .def("runExperiment_evolve2",
           &EvolutionIndirect_python::runExperiment_evolve2)
      .def("saveLocomotionFitness",
           &EvolutionIndirect_python::saveLocomotionFitness)
      .def("runExperiment_learn1",
           &EvolutionIndirect_python::runExperiment_learn1)
      .def("runExperiment_learn2",
           &EvolutionIndirect_python::runExperiment_learn2)
      .def("writesEvolutionState",
           &EvolutionIndirect_python::writesEvolutionState)
      ;
}

max_stars_repo_name: karinemiras/l-system

max_issues_repo_name: karinemiras/l-system

max_forks_repo_name: karinemiras/l-system


text:
#ifndef SGM_RP_HANSER96_HH_
#define SGM_RP_HANSER96_HH_

#include <boost/graph/adjacency_list.hpp>

#include "sgm/RingPerception.hh"

#include <limits>
#include <set>

namespace sgm {

	 /*! @brief Ring enumeration ala Hanser et al.
	  *
	  * Implementation of the exhaustive ring perception algorithm by
	  * Hanser et al. (1996)
	  *
	  *   A New Algorithm for Exhaustive Ring Perception in a Molecular Graph
	  *   T. Hanser, P. Jauffret, and G. Kaufmann
	  *   J. Chem. Inf. Comput. Sci., 1996, 36, 1146-1152
	  *
	  * @author Martin Mann - 2010 - http://www.bioinf.uni-freiburg.de/~mmann/
	  *
	  */
	class RP_Hanser96 : public RingPerception {
	public:

		typedef std::set< std::pair<size_t,size_t> > BondSet;

		  //! construction
		RP_Hanser96();

		  //! destruction
		virtual ~RP_Hanser96();

		  /*!
		   * Finds ALL rings within the given graph and reports each found
		   * ring to the assigned reporter. The enumeration can be restricted
		   * to rings up to a given ring size, ie. number of nodes per ring.
		   *
		   * @param graph the graph to be analyzed
		   * @param reporter the RingReporter to report all found rings to
		   * @param maxRingSize the maximal size of rings to report
		   * @return the number of all rings within the gaph
		   */
		size_t
		findRings( const Graph_Interface & graph,
					RingReporter & reporter,
					const size_t maxRingSize = std::numeric_limits<size_t>::max());

		  /*!
		   * Identifies all bonds participating in rings and stores the
		   * according vertex index pairs in the provided container.
		   *
		   * @param graph the graph to search for ring bonds
		   * @param ringBonds OUT : the container to fill with the ring bonds.
		   *   NOTE: the container is cleared at the beginning of the call.
		   * @param maxRingSize the maximal size of rings to consider
		   *
		   * @return the number of ring bonds within the graph
		   */
		size_t
		findRingBonds( const Graph_Interface & graph
					, BondSet & ringBonds
					, const size_t maxRingSize = std::numeric_limits<size_t>::max() );

	protected:

		  //! information on the current ring part
		struct RingInfo {
		public:
			RingReporter::RingNodes nodes;
			RingReporter::RingList path;
		};

		  //! The properties available for the nodes of the P-graph
		typedef	boost::property<	boost::vertex_index_t, size_t >
						Graph_NodeProperties;

		  //! The properties available for the edges of the P-graph
		typedef	boost::property<	boost::edge_name_t, RingInfo >
						Graph_EdgeProperties;

		  //! the P-graph type that is used to detect all rings
		typedef boost::adjacency_list<
							boost::multisetS,      			// store edges
							boost::vecS,       				// store vertices
							boost::undirectedS,				// is an undirected graph
							Graph_NodeProperties,  			// index information
							Graph_EdgeProperties   			// ring information
						>
							P_Graph;

	protected:

		  //! the P-graph to be compressed during the ring perception
		P_Graph pGraph;

		  //! the index access for pGraph
		boost::property_map<P_Graph, boost::vertex_index_t>::type pGraphIndex;
		  //! the edge label access for pGraph, i.e. the according RingList
		boost::property_map<P_Graph, boost::edge_name_t>::type pGraphPath;

		  //! the degree of each node in pGraph
		std::vector<size_t> pGraphDegree;
		  //! the nodes to be removed during the ring perception from pGraph
		std::vector<size_t> toRemove;

	protected:

		  /*!
		   * Initializes the pGraph member with the given graph. If direct loops
		   * are found, these are directly reported and counted.
		   *
		   * @param graph the graph to be encoded in the pGraph member
		   * @param reporter the RingReporter to report all rings to
		   * @return the number of rings found
		   */
		size_t
		initializeP_Graph( const Graph_Interface & graph
							, RingReporter& reporter);

		  /*!
		   * Virtually removes the vertex nextToRemove from the pGraph and
		   * reports all found rings to the given reporter.
		   * The removal is only virtual, since the node remains within the
		   * pGraph but all adjacent edges are removed, i.e. it is not
		   * accessible anymore in later iterations. This is to ease the
		   * maintenance of the temporary data structures.
		   *
		   * @param nextToRemove the index of the vertex to be removed
		   * @param graph the graph searched (needed for ring report)
		   * @param reporter the RingReporter to report all rings to
		   * @param maxRingSize the maximal ring size to consider
		   * @return the number of rings found
		   */
		size_t
		remove_vertex( const size_t nextToRemove
						, const Graph_Interface& graph
						, RingReporter& reporter
						, const size_t maxRingSize);

		struct degree_sort {
			const std::vector<size_t> & degree;
			degree_sort( const std::vector<size_t> & degree_ )
			 : degree(degree_)
			{}
			bool operator()(const size_t& i1, const size_t& i2 ) const {
				return degree[i1] > degree[i2];
			}
		};

		/**
		 * Stores the bond information for loops.
		 */
		class LoopBondReporter : public RingReporter {

		protected:

			BondSet & bondSet;

		public:
			  //! construction
			LoopBondReporter( BondSet & bondSet );
			  //! destruction
			virtual ~LoopBondReporter();

			  /*!
			   * Is called to report a ring.
			   * @param graph the graph that contains the ring
			   * @param ringList the ring to report
			   */
			virtual
			void
			reportRing( const Graph_Interface& graph, const RingList & ringList );

		};

	};

} // namespace sgm

#endif /* SGM_RP_HANSER96_HH_ */

ext: hh

max_stars_repo_name: michaelapeterka/GGL

max_issues_repo_name: michaelapeterka/GGL

max_forks_repo_name: michaelapeterka/GGL