#ifndef STIM_SWC_H #define STIM_SWC_H #include #include #include #include //STIM includes #include #include namespace stim { namespace swc_tree { template class swc_node { protected: enum neuronal_type { SWC_UNDEFINED, SWC_SOMA, SWC_AXON, SWC_DENDRITE, SWC_APICAL_DENDRITE, SWC_FORK_POINT, SWC_END_POINT, SWC_CUSTOM }; // eight types enum node_information { INTEGER_LABEL, NEURONAL_TYPE, X_COORDINATE, Y_COORDINATE, Z_COORDINATE, RADIUS, PARENT_LABEL }; public: int idx; // the index of current node start from 1(original index from the file) neuronal_type type; // the type of neuronal segmemt stim::vec3 point; // the point coordinates T radius; // the radius at current node int parent_idx; // parent idx of current node, -1 when it is origin(soma) int level; // tree level std::vector son_idx; // son idx of current node swc_node() { // default constructor idx = -1; // set to default -1 parent_idx = -1; // set to origin -1 level = -1; // set to default -1 type = SWC_UNDEFINED; // set to undefined type radius = 0; // set to 0 } void get_node(std::string line) { // get information from the node point we got // create a vector to store the information of one node point std::vector p = stim::parser::split(line, ' '); // for each information contained in the node point we got for (unsigned int i = 0; i < p.size(); i++) { std::stringstream ss(p[i]); // create a stringstream object for casting // store different information switch (i) { case INTEGER_LABEL: ss >> idx; // cast the stringstream to the correct numerical value break; case NEURONAL_TYPE: int tmp_type; ss >> tmp_type; // cast the stringstream to the correct numerical value type = (neuronal_type)tmp_type; break; case X_COORDINATE: T tmp_X; ss >> tmp_X; // cast the stringstream to the correct numerical value point[0] = tmp_X; // store the X_coordinate in vec3[0] break; case Y_COORDINATE: T tmp_Y; ss >> tmp_Y; // cast the stringstream to the correct numerical value point[1] = tmp_Y; // store the Y_coordinate in vec3[1] break; case Z_COORDINATE: T tmp_Z; ss >> tmp_Z; // cast the stringstream to the correct numerical value point[2] = tmp_Z; // store the Z_coordinate in vec3[2] break; case RADIUS: ss >> radius; // cast the stringstream to the correct numerical value break; case PARENT_LABEL: ss >> parent_idx; // cast the stringstream to the correct numerical value break; } } } }; } // end of namespace swc_tree template class swc { public: std::vector< typename swc_tree::swc_node> node; swc() {}; // default constructor // load the swc as tree nodes void load(std::string filename) { // load the file std::ifstream infile(filename.c_str()); // if the file is invalid, throw an error if (!infile) { std::cerr << "STIM::SWC Error loading file" << filename << std::endl; exit(-1); } std::string line; // skip comment while (getline(infile, line)) { if ('#' == line[0] || line.empty()) // if it is comment line or empty line continue; // keep read else break; } unsigned int l = 0; // number of nodes // get rid of the first/origin node swc_tree::swc_node new_node; new_node.get_node(line); l++; node.push_back(new_node); // push back the first node getline(infile, line); // get a new line // keep reading the following node point information as string while (!line.empty()) { // test for the last empty line l++; // still remaining node to be read swc_tree::swc_node next_node; next_node.get_node(line); node.push_back(next_node); getline(infile, line); // get a new line } } // read the head comment from swc file void read_comment(std::string filename) { // load the file std::ifstream infile(filename.c_str()); // if the file is invalid, throw an error if (!infile) { std::cerr << "STIM::SWC Error loading file" << filename << std::endl; exit(1); } std::string line; while (getline(infile, line)) { if ('#' == line[0] || line.empty()) { std::cout << line << std::endl; // print the comment line by line } else break; // break when reaches to node information } } // link those nodes to create a tree void create_tree() { unsigned n = node.size(); // get the total number of node point int cur_level = 0; // build the origin(soma) node[0].level = cur_level; // go through follow nodes for (unsigned i = 1; i < n; i++) { if (node[i].parent_idx != node[i - 1].parent_idx) cur_level = node[node[i].parent_idx - 1].level + 1; node[i].level = cur_level; int tmp_parent_idx = node[i].parent_idx - 1; // get the parent node loop idx of current node node[tmp_parent_idx].son_idx.push_back(i + 1); // son_idx stores the real idx = loop idx + 1 } } // return the number of point in swc unsigned int numL() { return node.size(); } }; } // end of namespace stim #endif