double dist_directional_swc_1_2(V3DLONG & nseg1, V3DLONG & nseg1big, double & sum1big, const NeuronTree *p1, const NeuronTree *p2) { if (!p1 || !p2) return -1; V3DLONG p1sz = p1->listNeuron.size(), p2sz = p2->listNeuron.size(); if (p1sz<2 || p2sz<2) return -1; NeuronSWC *tp1, *tp2; V3DLONG i, j; double sum1=0; nseg1=0; nseg1big=0; sum1big=0; QHash<int, int> h1 = generate_neuron_swc_hash(p1); //generate a hash lookup table from a neuron swc graph for (i=0;i<p1->listNeuron.size();i++) { //first find the two ends of a line seg tp1 = (NeuronSWC *)(&(p1->listNeuron.at(i))); if (tp1->pn < 0 || tp1->pn >= p1sz) continue; tp2 = (NeuronSWC *)(&(p1->listNeuron.at(h1.value(tp1->pn)))); //use hash table //qDebug() << "i="<< i << " pn="<<tp1->pn - 1; //now produce a series of points for the line seg double len=dist_L2(XYZ(tp1->x,tp1->y,tp1->z), XYZ(tp2->x,tp2->y,tp2->z)); int N = int(1+len+0.5); XYZ ptdiff; if (N<=1) { qDebug() << "detect one very short segment, len=" << len; ptdiff = XYZ(0,0,0); } else { double N1=1.0/(N-1); ptdiff = XYZ(N1,N1,N1) * XYZ(tp2->x-tp1->x, tp2->y-tp1->y, tp2->z-tp1->z); } qDebug() << "N="<<N << "len=" <<len << "xd="<<ptdiff.x << " yd=" << ptdiff.y << " zd=" << ptdiff.z << " "; for (j=0;j<N;j++) { XYZ curpt(tp1->x + ptdiff.x*j, tp1->y + ptdiff.y*j, tp1->z + ptdiff.z*j); double cur_d = dist_pt_to_swc(curpt, p2); sum1 += cur_d; nseg1++; if (cur_d>=2) { sum1big += cur_d; nseg1big++; } } } qDebug() << "end directional neuronal distance computing"; return sum1; }
double dist_pt_to_swc(const XYZ & pt, const NeuronTree * p_tree) { //first find all the edge end point distances if (!p_tree) return -1; V3DLONG p_tree_sz = p_tree->listNeuron.size(); NeuronSWC *tp1, *tp2; if (p_tree_sz<2) { tp1 = (NeuronSWC *)(&(p_tree->listNeuron.at(0))); return norm(pt - XYZ(tp1->x, tp1->y, tp1->z)); } QHash<int, int> h = generate_neuron_swc_hash(p_tree); //generate a hash lookup table from a neuron swc graph V3DLONG i; double min_dist; bool b_first=false; for (i=0;i<p_tree->listNeuron.size();i++) { //first find the two ends of a line seg tp1 = (NeuronSWC *)(&(p_tree->listNeuron.at(i))); if (tp1->pn < 0 || tp1->pn >= p_tree_sz) continue; tp2 = (NeuronSWC *)(&(p_tree->listNeuron.at(h.value(tp1->pn)))); //use hash table //now compute the distance between the pt and the current segment double cur_d = dist_pt_to_line_seg(pt, XYZ(tp1->x,tp1->y,tp1->z), XYZ(tp2->x,tp2->y,tp2->z)); //now find the min distance if (b_first==false) {min_dist = cur_d; b_first=true;} else min_dist = (min_dist>cur_d) ? cur_d : min_dist; } return min_dist; }
NeuronMorphoInfo neuron_morpho_features(const NeuronTree *p) //collect the morphological features of a neuron { NeuronMorphoInfo m; if (!p) return m; //create some reference names so that easier to write the code double & total_length = m.total_length; V3DLONG & n_node = m.n_node; V3DLONG & n_segment = m.n_segment; //091009 RZC V3DLONG & n_branch = m.n_branch; V3DLONG & n_tip = m.n_tip; double & bbox_xmin = m.bbox_xmin, bbox_xmax=m.bbox_xmax, bbox_ymin=m.bbox_ymin, bbox_ymax=m.bbox_ymax, bbox_zmin=m.bbox_zmin, bbox_zmax=m.bbox_zmax; double * moments = m.moments; // NeuronSWC *tp1, *tp2; V3DLONG i, j; QHash<int, int> h = generate_neuron_swc_hash(p); //generate a hash lookup table from a neuron swc graph n_node = h.size(); unsigned char *nchildren = new unsigned char [n_node]; //track the # of children each node has for (i=0;i<n_node;i++) nchildren[i]=0; total_length = 0; for (i=0, total_length=0.0;i<p->listNeuron.size();i++) { //first find the two ends of a line seg tp1 = (NeuronSWC *)(&(p->listNeuron.at(i))); if (tp1->pn < 0 || tp1->pn >= n_node) continue; tp2 = (NeuronSWC *)(&(p->listNeuron.at(h.value(tp1->pn)))); //use hash table nchildren[h.value(tp1->pn)]++; //update the parent node's children number //qDebug() << "i="<< i << " pn="<<tp1->pn - 1; //compute the length double len=dist_L2(XYZ(tp1->x,tp1->y,tp1->z), XYZ(tp2->x,tp2->y,tp2->z)); total_length += len; //compute the bbox if (i==0) { bbox_xmin = bbox_xmax = tp1->x; bbox_ymin = bbox_ymax = tp1->y; bbox_zmin = bbox_zmax = tp1->z; } else { if (bbox_xmin>tp1->x) bbox_xmin = tp1->x; if (bbox_xmax<tp1->x) bbox_xmax = tp1->x; if (bbox_ymin>tp1->y) bbox_ymin = tp1->y; if (bbox_ymax<tp1->y) bbox_ymax = tp1->y; if (bbox_zmin>tp1->z) bbox_zmin = tp1->z; if (bbox_zmax<tp1->z) bbox_zmax = tp1->z; } // //now produce a series of points for the line seg // int N = int(1+len+0.5); // XYZ ptdiff; // if (N<=1) // { // qDebug() << "detect one very short segment, len=" << len; // ptdiff = XYZ(0,0,0); // } // else // { // double N1=1.0/(N-1); // ptdiff = XYZ(N1,N1,N1) * XYZ(tp2->x-tp1->x, tp2->y-tp1->y, tp2->z-tp1->z); // } // qDebug() << "N="<<N << "len=" <<len << "xd="<<ptdiff.x << " yd=" << ptdiff.y << " zd=" << ptdiff.z << " "; // for (j=0;j<N;j++) // { // XYZ curpt(tp1->x + ptdiff.x*j, tp1->y + ptdiff.y*j, tp1->z + ptdiff.z*j); // double cur_d = dist_pt_to_swc(curpt, p2); // sum1 += cur_d; // nseg1++; // } } // for (i=0, n_branch=0;i<n_node;i++) //find the n_branches // if (nchildren[i]>1) n_branch++; if (nchildren) {delete nchildren; nchildren=0;} ////////////////////////////////////////////////////////// // 091009 RZC: count after splitting to simple segments ////////////////////////////////////////////////////////// vector <V_NeuronSWC> seg_vec = get_neuron_segments(p); n_segment = seg_vec.size(); //neuron_branch_tip_count(n_branch, n_tip, seg_vec); // 091212 RZC: count changed using link_map V_NeuronSWC v_neuron = join_V_NeuronSWC_vec(seg_vec); //V_NeuronSWC v_neuron = get_v_neuron_swc(p); neuron_branch_tip_count(n_branch, n_tip, v_neuron); //141006 CHB: above may cause error when there is overlapping point in the file, corrrected: vector<int> num_child (p->listNeuron.size(),0); for(int i=0; i<p->listNeuron.size(); i++){ V3DLONG pn=p->listNeuron.at(i).pn, pid=-1; if(p->hashNeuron.contains(pn)) pid=p->hashNeuron[pn]; else continue; num_child[pid]++; } n_branch=0; n_tip=0; for(int i=0; i<num_child.size(); i++){ if(p->listNeuron.at(i).pn<0) //skip root continue; if(num_child[i]==0) //tips n_tip++; if(num_child[i]>1) //branch points n_branch++; } return m; }