Commit 4df9ec0e82ddb0bc0314f26e7077958a11062aa8

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   Show diff stats
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<T> q){
333 332  
334   - stim::vec<double> temp( (double) q[0], (double) q[1], (double) q[2]);
  333 + stim::vec<double> 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<T> v(3); //v-direction vector of the segment
469 469 stim::vec<T> p(3); //- intermediate point to be added
470   - std::vector<T> p1(3); // p1 - starting point of an segment on the fiber,
471   - std::vector<T> p2(3); // p2 - ending point,
  470 + stim::vec<T> p1(3); // p1 - starting point of an segment on the fiber,
  471 + stim::vec<T> p2(3); // p2 - ending point,
472 472 double sum=0; //distance summation
473 473 std::vector<stim::vec<T> > fiberPositions = centerline();
474 474 std::vector<stim::vec<T> > 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 <list>
5 4 #include <stdlib.h>
  5 +#include <assert.h>
6 6 #include <sstream>
7 7 #include <fstream>
8 8 #include <algorithm>
... ... @@ -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<T>(){v[1] = -1; v[0] = -1;}
37   -
  36 + edge() : fiber<T>(){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<unsigned> 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<T> 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<T> 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<stim::vec<T> > points_afterResampling(){
  227 + std::vector<stim::vec<T> > pointsVector; // points in the resampled network
  228 + stim::fiber<T> FIBER; // initialize a fiber used in looping through all edges casting into fibers in the network
  229 + std::vector<stim::vec<T> > 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<T> metricList){
  251 + float sumMetricList = 0; // Initialize variable to calculate sum
  252 + for (unsigned int count=0; count<metricList.size(); count++) // for each element in the stim vector
  253 + { sumMetricList += metricList[count];} // running sum of values
  254 + return sumMetricList;
  255 + }
  256 +
  257 +
  258 + // distance between two points
  259 + double dist(stim::vec<T> p0, stim::vec<T> p1){
  260 + double sum = 0; // initialize variables
  261 + stim::vec<T> 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<T> 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<stim::vec<T> > 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<float> fiberMetric(networkTruth.edges()); // allocate space for accumulating fiber metric as each fiber is evaluated
  294 + stim::fiber<T> 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<T> > fiberPoints = FIBER.centerline(); // Get the points on the fiber
  300 + N = FIBER.n_pts(); // number of points on the fiber
  301 + stim::vec<float> 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<T> p1 = fiberPoints[j];stim::vec<T> 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
... ...