Authored by pranathivemuri
1 parent 3800c27f

### compare networks and give netmets metric function added in network class

Showing 2 changed files with 141 additions and 24 deletions
stim/biomodels/fiber.h

 ... ... @@ -193,7 +193,6 @@ public: 193 193 if(this == &rhs) return *this; //test for and handle self-assignment 194 194 195 195 copy(rhs); 196 - 197 196 } 198 197 199 198 /// Calculate the length of the fiber and return it. ... ... @@ -331,7 +330,7 @@ public: 331 330 /// @param q is the query point used to locate the nearest point on the fiber centerline 332 331 unsigned int nearest_idx(stim::vec q){ 333 332 334 - stim::vec temp( (double) q[0], (double) q[1], (double) q[2]); 333 + stim::vec temp((double) q[0], (double) q[1], (double) q[2]); 335 334 336 335 unsigned int idx = ann(temp); //determine the index of the nearest neighbor 337 336 ... ... @@ -449,6 +448,7 @@ public: 449 448 return N; 450 449 } 451 450 451 + 452 452 /// Bracket operator returns the element at index i 453 453 454 454 /// @param i is the index of the element to be returned as a stim::vec ... ... @@ -467,8 +467,8 @@ public: 467 467 468 468 std::vector v(3); //v-direction vector of the segment 469 469 stim::vec p(3); //- intermediate point to be added 470 - std::vector p1(3); // p1 - starting point of an segment on the fiber, 471 - std::vector p2(3); // p2 - ending point, 470 + stim::vec p1(3); // p1 - starting point of an segment on the fiber, 471 + stim::vec p2(3); // p2 - ending point, 472 472 double sum=0; //distance summation 473 473 std::vector > fiberPositions = centerline(); 474 474 std::vector > newPointList; // initialize list of new resampled points on the fiber ... ... @@ -476,14 +476,10 @@ public: 476 476 unsigned int N = fiberPositions.size(); // number of points on the fiber 477 477 for(unsigned int f=0; f< N-1; f++) 478 478 { 479 - for(unsigned int d = 0; d < 3; d++) 480 - { 481 - p1[d] = fiberPositions[f][d]; // starting point of the segment on the centerline 482 - p2[d] = fiberPositions[f + 1][d]; // ending point of the segment on the centerline 483 - v[d] = p2[d] - p1[d]; //direction vector 484 - sum +=v[d] * v[d]; //length of segment-distance between starting and ending point 485 - } 486 - //newPointList.push_back(fiberPositions[f]); //always push the starting point 479 + 480 + p1 = fiberPositions[f]; p2 = fiberPositions[f + 1]; v = p2 - p1; 481 + for(unsigned int d = 0; d < 3; d++){ 482 + sum +=v[d] * v[d];} //length of segment-distance between starting and ending point 487 483 488 484 T lengthSegment = sqrt(sum); //find Length of the segment as distance between the starting and ending points of the segment 489 485 ... ...
stim/biomodels/network.h

 1 1 #ifndef STIM_NETWORK_H 2 2 #define STIM_NETWORK_H 3 3 4 -#include 5 4 #include 5 +#include 6 6 #include 7 7 #include 8 8 #include ... ... @@ -33,8 +33,7 @@ class network{ 33 33 public: 34 34 unsigned v[2]; //unique id's designating the starting and ending 35 35 // default constructor 36 - edge() : fiber(){v[1] = -1; v[0] = -1;} 37 - 36 + edge() : fiber(){v[1] = -1; v[0] = -1;} 38 37 /// Constructor - creates an edge from a list of points by calling the stim::fiber constructor 39 38 40 39 ///@param p is an array of positions in space ... ... @@ -122,7 +121,7 @@ class network{ 122 121 123 122 std::vector id2vert; //this list stores the OBJ vertex ID associated with each network vertex 124 123 125 - unsigned i[2]; //temporary, IDs associated with the first and last points in an OBJ line 124 + unsigned i[2]; //temporary, IDs associated with the first and last points in an OBJ line 126 125 127 126 //for each line in the OBJ object 128 127 for(unsigned int l = 1; l <= O.numL(); l++){ ... ... @@ -145,10 +144,10 @@ class network{ 145 144 it = find(id2vert.begin(), id2vert.end(), i[0]); //look for the first node 146 145 it_idx = std::distance(id2vert.begin(), it); 147 146 if(it == id2vert.end()){ //if i[0] hasn't already been used 148 - vertex new_vertex = new_edge[0]; //create a new vertex, assign it a position 149 - new_vertex.e[0].push_back(E.size()); //add the current edge as outgoing 150 - new_edge.v[0] = V.size(); //add the new vertex to the edge 151 - V.push_back(new_vertex); //add the new vertex to the vertex list 147 + vertex new_vertex = new_edge[0]; //create a new vertex, assign it a position 148 + new_vertex.e[0].push_back(E.size()); //add the current edge as outgoing 149 + new_edge.v[0] = V.size(); //add the new vertex to the edge 150 + V.push_back(new_vertex); //add the new vertex to the vertex list 152 151 id2vert.push_back(i[0]); //add the ID to the ID->vertex conversion list 153 152 } 154 153 else{ //if the vertex already exists ... ... @@ -170,7 +169,7 @@ class network{ 170 169 new_edge.v[1] = it_idx; 171 170 } 172 171 173 - E.push_back(new_edge); //push the edge to the list 172 + E.push_back(new_edge); //push the edge to the list 174 173 175 174 } 176 175 } ... ... @@ -197,14 +196,136 @@ class network{ 197 196 stim::network n; //create a new network that will be an exact copy, with resampled fibers 198 197 n.V = V; //copy all vertices 199 198 200 - n.E.resize(E.size()); //allocate space for the edge list 199 + n.E.resize(edges()); //allocate space for the edge list 201 200 202 201 //copy all fibers, resampling them in the process 203 - for(unsigned e = 0; e < E.size(); e++){ //for each edge in the edge list 202 + for(unsigned e = 0; e < edges(); e++){ //for each edge in the edge list 204 203 n.E[e] = E[e].resample(spacing); //resample the edge and copy it to the new network 205 204 } 206 205 207 - return n; //return the resampled network 206 + return n; //return the resampled network 207 + } 208 + 209 + 210 + // this function gives sum of lengths of all the fibers in the network 211 + float lengthOfNetwork(){ 212 + stim::fiber FIBER; // initialize a fiber used in looping through all edges casting into fibers in the network 213 + float networkLength=0;float N=0; // initialize variables for finding total length of all the fibers 214 + // for each edge in the network 215 + for (unsigned int i=0; i < E.size(); i ++) 216 + { 217 + FIBER = get_fiber(i); // cast each edge to fiber 218 + N= FIBER.length(); // find length of the fiber 219 + networkLength = networkLength + N; // running sum of fiber lengths 220 + } 221 + return networkLength; 222 + } 223 + 224 + 225 + // list of all the points after resampling -- function used only on a resampled network 226 + std::vector > points_afterResampling(){ 227 + std::vector > pointsVector; // points in the resampled network 228 + stim::fiber FIBER; // initialize a fiber used in looping through all edges casting into fibers in the network 229 + std::vector > pointsFiber; // resampled points on each fiber of the network 230 + for(unsigned e = 0; e < E.size(); e++){ // for each edge in the edge list 231 + FIBER = get_fiber(e); // Cast edge to a fiber 232 + pointsFiber = FIBER.centerline(); // find points on the edge returns a stim vec 233 + for (unsigned v = 0; v < FIBER.n_pts(); v++){ // iterate one point at a time from the stim::vec 234 + pointsVector.push_back(pointsFiber[v]);} //add the points on centerline to the stim::vec points list 235 + } 236 + return pointsVector; 237 + } 238 + 239 + 240 + // total number of points on all fibers after resampling -- function used only on a resampled network 241 + unsigned int total_points(){ 242 + unsigned int n = points_afterResampling().size(); 243 + return n; 244 + } 245 + 246 + // gaussian function 247 + float gaussianFunction(float x, float std=25){ return exp(-x/(2*std*std));} // by default std = 25 248 + 249 + // sum of values in a stim vector 250 + float sum(stim::vec metricList){ 251 + float sumMetricList = 0; // Initialize variable to calculate sum 252 + for (unsigned int count=0; count p0, stim::vec p1){ 260 + double sum = 0; // initialize variables 261 + stim::vec v = p1 - p0;; // direction vector 262 + for(unsigned int d = 0; d < 3; d++){ // for each dimension 263 + sum += v[d] * v[d];} // running sum of modulus of direction vector 264 + return sqrt(sum); 265 + } 266 + 267 + 268 + /// This function compares two networks and returns a metric 269 + float compare(stim::network networkTruth, float sigma){ 270 + float metric = 0.0; // initialize metric to be returned after comparing the networks 271 + ANNkd_tree* kdt; // initialize a pointer to a kd tree 272 + double **c; // centerline (array of double pointers) - points on kdtree must be double 273 + unsigned int n_data = total_points(); // set the number of points 274 + c = (double**) malloc(sizeof(double*) * n_data); // allocate the array pointer 275 + for(unsigned int i = 0; i < n_data; i++) // allocate space for each point of 3 dimensions 276 + {c[i] = (double*) malloc(sizeof(double) * 3);} 277 + std::vector > pointsVector = points_afterResampling(); //get vertices in the network after resampling 278 + for(unsigned int i = 0; i < n_data; i++) // loop through all the vertices after resampling 279 + { 280 + for(unsigned int d = 0; d < 3; d++){ // for each dimension 281 + c[i][d] = double(pointsVector[i][d]); // copy the coordinate and convert_to_double 282 + } 283 + } 284 + ANNpointArray pts = (ANNpointArray)c; // create an array of data points of type double 285 + kdt = new ANNkd_tree(pts, n_data, 3); // build a KD tree using the annpointarray 286 + double eps = 0; // error bound 287 + ANNdistArray dists1;dists1 = new ANNdist[1]; // near neighbor distances 288 + ANNdistArray dists2; dists2 = new ANNdist[1]; // near neighbor distances 289 + ANNidxArray nnIdx1; nnIdx1 = new ANNidx[1]; // near neighbor indices // allocate near neigh indices 290 + ANNidxArray nnIdx2; nnIdx2 = new ANNidx[1]; // near neighbor indices // allocate near neigh indices 291 + int N; // number of points on the fiber in the second network 292 + float totalNetworkLength = networkTruth.lengthOfNetwork(); 293 + stim::vec fiberMetric(networkTruth.edges()); // allocate space for accumulating fiber metric as each fiber is evaluated 294 + stim::fiber FIBER; // Initialize a fiber will be used in calculating the metric 295 + //for each fiber in the second network, find nearest distance in the kd tree 296 + for (unsigned int i=0; i < networkTruth.edges(); i ++) // loop through all the edges/fibers in the network 297 + { 298 + FIBER = networkTruth.get_fiber(i); // Get the fiber corresponding to the index i 299 + std::vector< stim::vec > fiberPoints = FIBER.centerline(); // Get the points on the fiber 300 + N = FIBER.n_pts(); // number of points on the fiber 301 + stim::vec segmentMetric(N-1); // allocate space for a vec array that stores metric for each segmen in the fiber 302 + // for each segment in the fiber 303 + for (unsigned j = 0; j < N - 1; j++) 304 + { 305 + stim::vec p1 = fiberPoints[j];stim::vec p2 = fiberPoints[j+1]; // starting and ending points on the segments 306 + ANNpoint queryPt1; queryPt1 = annAllocPt(3); // allocate memory for query points 307 + ANNpoint queryPt2; queryPt2 = annAllocPt(3); 308 + 309 + //for each dimension of the points connecting segment 310 + for (unsigned d = 0; d < 3; d++){ 311 + queryPt1[d] = double(fiberPoints[j][d]); // starting point on segment in network whose closest distance on KD tree should be found 312 + queryPt2[d] = double(fiberPoints[j + 1][d]); // ending point on segment in network whose closest distance on KD tree should be found 313 + } 314 + kdt->annkSearch( queryPt1, 1, nnIdx1, dists1, eps); // search the nearest point in KD tree to query point(point on network), find the distance 315 + kdt->annkSearch( queryPt2, 1, nnIdx2, dists2, eps); // search the nearest point in KD tree to query point(point on network), find the distance 316 + // find the gaussian of the distance and subtract it from 1 to calculate the error 317 + float error1 = 1.0f - gaussianFunction(float(dists1[0]), sigma);float error2 = 1.0f - gaussianFunction(float(dists2[0]), sigma); 318 + // average the error and scale it with distance between the points 319 + segmentMetric[j] = ((error1 + error2) / 2) * dist(p1, p2) ; 320 + /*segmentDists[j] = dist(p1, p2); */ 321 + } 322 + fiberMetric[i] = sum(segmentMetric); 323 + /*distsList[i] = sum(segmentDists);*/ 324 + } 325 + /*assert (sum(distsList)==totalNetworkLength);*/ 326 + metric = sum(fiberMetric)/totalNetworkLength; //normalize the scaled error of all the points with total length of the network 327 + assert (0<=metric <=1); //assert metroc os always less than or equal to one and greater than or equal to zero 328 + return metric; 208 329 } 209 330 }; //end stim::network class 210 331 }; //end stim namespace ... ...