Commit 52cb8dfd2dc3f38bd35a6860afad2f86f4ec5f53
1 parent
1c3c8f1a
added function to resample a fiber in the network, adding resampled edges to the network
Showing
1 changed file
with
132 additions
and
88 deletions
Show diff stats
stim/visualization/network.h
... | ... | @@ -14,7 +14,6 @@ |
14 | 14 | #include <ANN/ANN.h> |
15 | 15 | #include <boost/tuple/tuple.hpp> |
16 | 16 | |
17 | -#define multfactor 2.51 | |
18 | 17 | |
19 | 18 | namespace stim{ |
20 | 19 | /** This is the a class that interfaces with gl_spider in order to store the currently |
... | ... | @@ -171,10 +170,13 @@ class network{ |
171 | 170 | edges_to_str() |
172 | 171 | { |
173 | 172 | std::ostringstream ss; |
173 | + std::cout<<"here"<<std::endl; | |
174 | 174 | // ss << "["; |
175 | 175 | for(int i = 0; i < edges.size()-1; i++) |
176 | 176 | { |
177 | + std::cout<<"here"<<i<<std::endl; | |
177 | 178 | ss << edges[i] << ";"; |
179 | + std::cout<<edges.size()-1<<std::endl; | |
178 | 180 | } |
179 | 181 | ss << edges[edges.size()-1]; |
180 | 182 | // ss << "]"; |
... | ... | @@ -187,6 +189,8 @@ class network{ |
187 | 189 | |
188 | 190 | std::vector<edge*> E; //list of pointers to edges. |
189 | 191 | std::vector<node> V; //list of nodes. |
192 | + std::vector< stim::vec<T> > allVerticesList; // all nodes before sampling | |
193 | + std::vector<stim::vec<T> > allVerticesAfterSampling ; //all vertices after sampling | |
190 | 194 | |
191 | 195 | ///Returns the number of edges in the network. |
192 | 196 | unsigned int |
... | ... | @@ -201,7 +205,11 @@ class network{ |
201 | 205 | { |
202 | 206 | return V.size(); |
203 | 207 | } |
204 | - | |
208 | + unsigned int | |
209 | + sizeAfterSamplingV() | |
210 | + { | |
211 | + return allVerticesAfterSampling.size(); | |
212 | + } | |
205 | 213 | /* //adds an edge from two std::vectors with positions and radii. |
206 | 214 | void |
207 | 215 | addEdge(std::vector< stim::vec<T> > pos, std::vector<stim::vec<T> > radii, int endId) |
... | ... | @@ -500,7 +508,7 @@ class network{ |
500 | 508 | totalEdges() |
501 | 509 | { |
502 | 510 | int totalEdgeVertices=0;int N=0; |
503 | - for (int i=0; i < sizeE(); i ++) | |
511 | + for (unsigned int i=0; i < sizeE(); i ++) | |
504 | 512 | {// FOR N points on the fiber N-1 edges are possible |
505 | 513 | N = E[i]->n_pts(); |
506 | 514 | totalEdgeVertices = totalEdgeVertices + N- 1; |
... | ... | @@ -512,46 +520,13 @@ class network{ |
512 | 520 | lengthOfNetwork() |
513 | 521 | { |
514 | 522 | float networkLength=0;float N=0; |
515 | - for (int i=0; i < sizeE(); i ++) | |
523 | + for (unsigned int i=0; i < sizeE(); i ++) | |
516 | 524 | { |
517 | 525 | N = E[i]->length(); |
518 | 526 | networkLength = networkLength + N; |
519 | 527 | } |
520 | 528 | return networkLength; |
521 | 529 | } |
522 | - /// get index of a node on a fiber | |
523 | - // by matching the node on fiber to already set vertices (both strings) | |
524 | - // used in obj file conversion | |
525 | - int | |
526 | - getIndexes(std::string* input, std::string searched, int sizeV) | |
527 | - { | |
528 | - int result = 0; | |
529 | - for (int i = 0; i < sizeV; i++) | |
530 | - { | |
531 | - if (input[i] == searched) | |
532 | - { | |
533 | - result = i + 1; | |
534 | - } | |
535 | - } | |
536 | - return result; | |
537 | - } | |
538 | - // strObj returns a string of fiber indices corresponding to vectors of positions in the fiber including intermediate nodes | |
539 | - std::string | |
540 | - strObj(std::string* strArray, int sizeV) | |
541 | - { | |
542 | - std::stringstream ss; | |
543 | - std::stringstream oss; | |
544 | - for(unsigned int i = 0; i < N; i++) | |
545 | - { | |
546 | - ss.str(std::string()); | |
547 | - for(unsigned int d = 0; d < 3; d++) | |
548 | - { | |
549 | - ss<<c[i][d]; | |
550 | - } | |
551 | - oss<<getIndexes(strArray, ss.str(), sizeV)<<" "; | |
552 | - } | |
553 | - return oss.str(); | |
554 | - } | |
555 | 530 | ///@param i: index of the required fiber. |
556 | 531 | ///Returns an std::vector with the centerline of the ith fiber in the edgelist. |
557 | 532 | std::vector< stim::vec<T> > |
... | ... | @@ -584,6 +559,7 @@ class network{ |
584 | 559 | objToNetwork(stim::obj<T> objInput) |
585 | 560 | { |
586 | 561 | stim::network<T> nwc; |
562 | + //network network2; | |
587 | 563 | // function to convert an obj file loaded using stim/visualization/obj.h |
588 | 564 | // to a 3D network class using network.h methods. |
589 | 565 | std::vector< stim::vec<T> > fiberPositions; //initialize positions on the fiber to be added to network |
... | ... | @@ -595,7 +571,8 @@ class network{ |
595 | 571 | // using addNode function for adding nodes |
596 | 572 | // and the line as an edge(belongs to fiber class) using addEdge function |
597 | 573 | std::vector<unsigned> vertexIndices(objInput.numV()); |
598 | - std::vector< stim::vec<T> > allVerticesList = objInput.getAllV(vertexIndices); | |
574 | + std::vector< stim::vec<T> > vertices = objInput.getAllV(vertexIndices); | |
575 | + nwc.addVertices(vertices); | |
599 | 576 | for (unsigned i =1; i< objInput.numL() + 1; i++) |
600 | 577 | { |
601 | 578 | // edges/fibers could be added to the network class |
... | ... | @@ -630,28 +607,33 @@ class network{ |
630 | 607 | { |
631 | 608 | fiberPositions1 = fiberPositions; |
632 | 609 | } |
633 | - std::vector<T> radii(numPointsOnFiber); // allocating radii to zero | |
634 | 610 | // then add edge |
635 | - // edge* a = new edge(fiberPositions1,radii); | |
636 | - //E.push_back(a); | |
637 | - nwc.addEdge(fiberPositions1, radii); | |
611 | + //edge* a = new edge(fiberPositions1,radii); | |
612 | + //std::cout<<"here"<<std::endl; | |
613 | + //E.push_back(a); | |
614 | + std::vector<stim::vec<T> > newPointList; | |
615 | + newPointList = Resample(fiberPositions1); | |
616 | + int numPointsOnnewFiber = newPointList.size(); | |
617 | + nwc.addVerticesAfterSamplimg(newPointList); | |
618 | + std::vector<T> radii(numPointsOnnewFiber); // allocating radii to zero | |
619 | + nwc.addEdge(newPointList, radii); | |
638 | 620 | // add nodes |
639 | 621 | stim::vec<T> v0(3);stim::vec<T> vN(3); |
640 | - int endId = numPointsOnFiber -1; | |
641 | - v0[0] = fiberPositions1[0][0];v0[1] = fiberPositions1[0][1];v0[2] = fiberPositions1[0][2]; | |
642 | - vN[0] = fiberPositions1[endId][0];vN[1] = fiberPositions1[endId][1];vN[2] = fiberPositions1[endId][2]; | |
622 | + int endId = numPointsOnnewFiber -1; | |
623 | + v0[0] = newPointList[0][0];v0[1] = newPointList[0][1];v0[2] = newPointList[0][2]; | |
624 | + vN[0] = newPointList[endId][0];vN[1] = newPointList[endId][1];vN[2] = newPointList[endId][2]; | |
643 | 625 | // VISITED INDEXES OF the nodes are set to true |
644 | - if(!validList[objInput.getIndex(allVerticesList, v0)]) | |
626 | + if(!validList[objInput.getIndex(vertices, v0)]) | |
645 | 627 | { |
646 | 628 | //V.push_back(node(v0)); |
647 | 629 | nwc.addNode(v0); |
648 | - validList[objInput.getIndex(allVerticesList, v0)] = true; | |
630 | + validList[objInput.getIndex(vertices, v0)] = true; | |
649 | 631 | } |
650 | - if(!validList[objInput.getIndex(allVerticesList, vN)]) | |
632 | + if(!validList[objInput.getIndex(vertices, vN)]) | |
651 | 633 | { |
652 | 634 | //V.push_back(node(vN)); |
653 | 635 | nwc.addNode(vN); |
654 | - validList[objInput.getIndex(allVerticesList, vN)] = true; | |
636 | + validList[objInput.getIndex(vertices, vN)] = true; | |
655 | 637 | } |
656 | 638 | } |
657 | 639 | return nwc; |
... | ... | @@ -672,6 +654,7 @@ class network{ |
672 | 654 | kdTree2 = generateKdTreeFromNetwork(network2); |
673 | 655 | std::cout<<"Test Network:network and kdtree generated"<<std::endl; |
674 | 656 | return boost::make_tuple(kdTree1, kdTree2, network1, network2); |
657 | + std::cout<<"out of this loop"<<std::endl; | |
675 | 658 | } |
676 | 659 | //distance between two points |
677 | 660 | double dist(std::vector<T> p0, std::vector<T> p1) |
... | ... | @@ -686,7 +669,7 @@ class network{ |
686 | 669 | double sum(stim::vec<T> metricList) |
687 | 670 | { |
688 | 671 | float sumMetricList = 0; |
689 | - for (int count=0; count<metricList.size(); count++) | |
672 | + for (unsigned int count=0; count<metricList.size(); count++) | |
690 | 673 | { sumMetricList += metricList[count];} |
691 | 674 | return sumMetricList; |
692 | 675 | } |
... | ... | @@ -694,21 +677,22 @@ class network{ |
694 | 677 | ANNkd_tree* |
695 | 678 | generateKdTreeFromNetwork(stim::network<T> network) //kd-tree stores all points in the fiber for fast searching |
696 | 679 | { |
680 | + std::cout<<"kd trees generated"<<std::endl; | |
697 | 681 | ANNkd_tree* kdt; |
698 | 682 | double **c; //centerline (array of double pointers) |
699 | 683 | float* r; // array of fiber radii |
700 | - unsigned int n_data = network.sizeV(); //set the number of points | |
684 | + unsigned int n_data = network.sizeAfterSamplingV(); //set the number of points | |
701 | 685 | c = (double**) malloc(sizeof(double*) * n_data); //allocate the array pointer |
702 | 686 | for(unsigned int i = 0; i < n_data; i++) //allocate space for each point |
703 | 687 | {c[i] = (double*) malloc(sizeof(double) * 3);} |
704 | 688 | r = (float*) malloc(sizeof(float) * n_data); //allocate space for the radii |
705 | - stim::vec<T> node; | |
706 | - for(int i = 0; i < n_data; i++) | |
689 | + //stim::vec<T> node; | |
690 | + for(unsigned int i = 0; i < n_data; i++) | |
707 | 691 | { |
708 | - node = network.V[i].getPosition(); | |
692 | + //node = network.V[i].getPosition(); | |
709 | 693 | //convert_to_double |
710 | 694 | for(unsigned int d = 0; d < 3; d++){ //for each dimension |
711 | - c[i][d] = double(node[d]); //copy the coordinate | |
695 | + c[i][d] = double(network.allVerticesAfterSampling[i][d]); //copy the coordinate | |
712 | 696 | } |
713 | 697 | r[i] = r[i]; //copy the radius |
714 | 698 | } |
... | ... | @@ -731,54 +715,38 @@ class network{ |
731 | 715 | { |
732 | 716 | V.push_back(nodes); |
733 | 717 | } |
734 | - ///exports the graph. | |
735 | 718 | void |
736 | - to_csv() | |
719 | + addVertices(std::vector< stim::vec<T> > vertices) | |
737 | 720 | { |
738 | - std::ofstream ofs; | |
739 | - ofs.open("Graph.csv", std::ofstream::out | std::ofstream::app); | |
740 | - for(int i = 0; i < V.size(); i++) | |
721 | + for (unsigned int i=0; i < vertices.size(); i ++) | |
741 | 722 | { |
742 | - ofs << V[i].edges_to_str() << "\n"; | |
723 | + allVerticesList.push_back(vertices[i]); | |
743 | 724 | } |
744 | - ofs.close(); | |
745 | 725 | } |
746 | - | |
747 | - ///exports the graph. | |
748 | 726 | void |
749 | - to_gdf() | |
727 | + addVerticesAfterSamplimg(std::vector< stim::vec<T> > vertices) | |
750 | 728 | { |
751 | - std::ofstream ofs; | |
752 | - ofs.open("Graph.gdf", std::ofstream::out | std::ofstream::app); | |
753 | - ofs << "nodedef>name VARCHAR\n"; | |
754 | - for(int i = 0; i < V.size(); i++) | |
729 | + for (unsigned int i=0; i < vertices.size(); i ++) | |
755 | 730 | { |
756 | - ofs << i << "\n"; | |
731 | + allVerticesAfterSampling.push_back(vertices[i]); | |
757 | 732 | } |
758 | - ofs << "edgedef>Nodes[1] VARCHAR, Nodes[2] VARCHAR, weight INT, length FLOAT, av_radius FLOAT \n"; | |
759 | - for(int i = 0; i < E.size(); i++) | |
760 | - { | |
761 | - ofs << E[i]->Nodes[1] << "," << E[i]->Nodes[2] << "," <<E[i]->n_pts() | |
762 | - << ","<< E[i]->length() << "," << E[i]->average_radius() << "\n"; | |
763 | - } | |
764 | - ofs.close(); | |
765 | 733 | } |
766 | 734 | // gaussian function |
767 | 735 | float gaussianFunction(float x, float std=25) |
768 | 736 | { |
769 | - float normalization = multfactor * std; | |
770 | - float evaluate = 1.0 - (exp(-x/(2*std*std))); | |
737 | + float evaluate = 1.0f - ((exp(-x/(2*std*std)))); | |
771 | 738 | return evaluate; |
772 | 739 | } |
740 | + // compares point on a network to a kd tree for two skeletons | |
773 | 741 | boost::tuple< float, float > |
774 | - compareSkeletons(boost::tuple< ANNkd_tree*, ANNkd_tree*, stim::network<int>, stim::network<int> > networkKdtree) | |
742 | + compareSkeletons(boost::tuple< ANNkd_tree*, ANNkd_tree*, stim::network<float>, stim::network<float> > networkKdtree) | |
775 | 743 | { |
776 | 744 | float gFPR, gFNR; |
777 | 745 | gFPR = CompareNetKD(networkKdtree.get<0>(), networkKdtree.get<3>()); |
778 | 746 | gFNR = CompareNetKD(networkKdtree.get<1>(), networkKdtree.get<2>()); |
779 | 747 | return boost::make_tuple(gFPR, gFNR); |
780 | 748 | } |
781 | - // gaussian distance of points on network to Kdtree | |
749 | + // gaussian distance of points on network to Kdtree | |
782 | 750 | float |
783 | 751 | CompareNetKD(ANNkd_tree* kdTreeGroundtruth, stim::network<T> networkTruth) |
784 | 752 | { |
... | ... | @@ -793,14 +761,14 @@ class network{ |
793 | 761 | float totalNetworkLength = networkTruth.lengthOfNetwork(); |
794 | 762 | stim::vec<float> fiberMetric(networkTruth.sizeE()); |
795 | 763 | //for each fiber |
796 | - for (unsigned i=0; i < networkTruth.sizeE(); i ++) | |
764 | + for (unsigned int i=0; i < networkTruth.sizeE(); i ++) | |
797 | 765 | { |
798 | 766 | std::vector<T> p1(3); std::vector<T> p2(3);//temporary variables to store point positions |
799 | 767 | fiberPoints = networkTruth.E[i]->centerline(); |
800 | 768 | N = networkTruth.E[i]->n_pts(); |
801 | 769 | stim::vec<float> segmentMetric(N-1); |
802 | 770 | // for each segment in the fiber |
803 | - for (unsigned j = 0; j < N - 1; j++) | |
771 | + for (unsigned int j = 0; j < N - 1; j++) | |
804 | 772 | { |
805 | 773 | ANNpoint queryPt1; queryPt1 = annAllocPt(3); |
806 | 774 | ANNpoint queryPt2; queryPt2 = annAllocPt(3); |
... | ... | @@ -814,14 +782,56 @@ class network{ |
814 | 782 | } |
815 | 783 | kdTreeGroundtruth->annkSearch( queryPt1, 1, nnIdx1, dists1, eps); // error bound |
816 | 784 | kdTreeGroundtruth->annkSearch( queryPt2, 1, nnIdx2, dists2, eps); // error bound |
817 | - float dist1 = gaussianFunction(dists1[0]);float dist2 = gaussianFunction(dists2[0]); | |
785 | + std::cout<<float(dists1[0])<<"dist1-----"<<float(dists2[0])<<"dist2---"<<std::endl; | |
786 | + float dist1 = gaussianFunction(float(dists1[0]));float dist2 = gaussianFunction(float(dists2[0])); | |
818 | 787 | segmentMetric[j] = (((dist1 + dist2) / 2) * dist(p1, p2)) ; |
819 | 788 | } |
820 | - fiberMetric[i] = sum(segmentMetric); | |
789 | + fiberMetric[i] = sum(segmentMetric)/; | |
821 | 790 | } |
822 | 791 | netmetsMetric = sum(fiberMetric)/totalNetworkLength ; |
823 | 792 | return netmetsMetric; |
824 | 793 | } |
794 | + //resample a fiber in the network | |
795 | + std::vector<stim::vec<T> > Resample(std::vector< stim::vec<T> > fiberPositions, float spacing=25.0) | |
796 | + { | |
797 | + std::vector<T> p1(3), p2(3), v(3); | |
798 | + stim::vec<T> p(3); | |
799 | + std::vector<stim::vec<T> > newPointList; | |
800 | + for(unsigned int f=0; f<fiberPositions.size()-1; f++) | |
801 | + { | |
802 | + T lengthSegment = dist(p1,p2); | |
803 | + for(int d=0; d<3;d++) | |
804 | + { | |
805 | + p1[d] = T(fiberPositions[f][d]); | |
806 | + p2[d] = T(fiberPositions[f + 1][d]); | |
807 | + }// for each dimension | |
808 | + if( lengthSegment >= spacing ) | |
809 | + { for (int dim=0; dim<3;dim++) //find the direction of travel | |
810 | + {v[dim] = p2[dim] - p1[dim];} | |
811 | + //set the step size to the voxel size | |
812 | + T step; | |
813 | + for(step=0.0; step<lengthSegment; step+=spacing) | |
814 | + { | |
815 | + for(int i=0; i<3;i++) | |
816 | + {p[i] = p1[i] + v[i]*(step/lengthSegment);} | |
817 | + newPointList.push_back(p); | |
818 | + } | |
819 | + } | |
820 | + else | |
821 | + newPointList = fiberPositions; | |
822 | + } | |
823 | + return newPointList; | |
824 | + } | |
825 | + // modulus of a vector | |
826 | + T | |
827 | + Length(std::vector<T> v) | |
828 | + { | |
829 | + T sum=0; | |
830 | + for (int i=0; i<v.size(); i++) | |
831 | + sum += v[i] * v[i]; | |
832 | + return sum; | |
833 | + } | |
834 | + // function to remove characters from a string | |
825 | 835 | void removeCharsFromString(std::string &str, char* charsToRemove ) { |
826 | 836 | for ( unsigned int i = 0; i < strlen(charsToRemove); ++i ) { |
827 | 837 | str.erase( remove(str.begin(), str.end(), charsToRemove[i]), str.end() ); |
... | ... | @@ -833,9 +843,9 @@ class network{ |
833 | 843 | { |
834 | 844 | std::ofstream ofs; |
835 | 845 | ofs.open("Graph.obj", std::ofstream::out | std::ofstream::app); |
836 | - int num = V.size(); | |
837 | - string *strArray = new string[num]; | |
838 | - for(int i = 0; i < allVerticesList.size(); i++) | |
846 | + int num = allVerticesList.size(); | |
847 | + std::string *strArray = new std::string[num]; | |
848 | + for(unsigned int i = 0; i < allVerticesList.size(); i++) | |
839 | 849 | { |
840 | 850 | std::string str; |
841 | 851 | str = allVerticesList[i].str(); |
... | ... | @@ -848,10 +858,44 @@ class network{ |
848 | 858 | { |
849 | 859 | std::string str; |
850 | 860 | str = E[i]->strObj(strArray, num); |
861 | + //removeCharsFromString(str,"0"); | |
851 | 862 | ofs << "l " << str << "\n"; |
852 | 863 | } |
853 | 864 | ofs.close(); |
854 | 865 | } |
866 | + ///exports the graph. | |
867 | + void | |
868 | + to_csv() | |
869 | + { | |
870 | + std::ofstream ofs; | |
871 | + ofs.open("Graph.csv", std::ofstream::out | std::ofstream::app); | |
872 | + std::cout<<"here"<<std::endl; | |
873 | + for(int i = 0; i < V.size(); i++) | |
874 | + { | |
875 | + std::cout<<"here"<<i<<std::endl; | |
876 | + ofs << V[i].edges_to_str() << "\n"; | |
877 | + } | |
878 | + ofs.close(); | |
879 | + } | |
880 | + ///exports the graph. | |
881 | + void | |
882 | + to_gdf() | |
883 | + { | |
884 | + std::ofstream ofs; | |
885 | + ofs.open("Graph.gdf", std::ofstream::out | std::ofstream::app); | |
886 | + ofs << "nodedef>name VARCHAR\n"; | |
887 | + for(int i = 0; i < V.size(); i++) | |
888 | + { | |
889 | + ofs << i << "\n"; | |
890 | + } | |
891 | + ofs << "edgedef>Nodes[1] VARCHAR, Nodes[2] VARCHAR, weight INT, length FLOAT, av_radius FLOAT \n"; | |
892 | + for(int i = 0; i < E.size(); i++) | |
893 | + { | |
894 | + ofs << E[i]->Nodes[1] << "," << E[i]->Nodes[2] << "," <<E[i]->n_pts() | |
895 | + << ","<< E[i]->length() << "," << E[i]->average_radius() << "\n"; | |
896 | + } | |
897 | + ofs.close(); | |
898 | + } | |
855 | 899 | |
856 | 900 | }; |
857 | 901 | }; | ... | ... |