swc.h
5.33 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
#ifndef STIM_SWC_H
#define STIM_SWC_H
#include <vector>
#include <fstream>
#include <sstream>
#include <iostream>
//STIM includes
#include <stim/math/vec3.h>
#include <stim/parser/parser.h>
namespace stim {
namespace swc_tree {
template <typename T>
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<T> 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<int> 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<std::string> 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 <typename T>
class swc {
public:
std::vector< typename swc_tree::swc_node<T>> 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 << "STUN::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<T> 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<T> 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 << "STUN::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