Esempio n. 1
0
Swc_Tree_Node *Find_Closest_Leaf_Point(Swc_Tree *tree, double *pos, double *dist_xy, double *dist_z){

	double tn_pos[3];
	double dxy, dz;
	Swc_Tree_Iterator_Start(tree, 2, FALSE);

	Swc_Tree_Node *tn = NULL;
	Swc_Tree_Node *close_tn = NULL;

	double mindist = -1.0;
	while ((tn = Swc_Tree_Next(tree)) != NULL) {
		if (Swc_Tree_Node_Is_Regular(tn) &&  Swc_Tree_Node_Is_Leaf(tn)) {
			Swc_Tree_Node_Pos(tn, tn_pos);
			if (mindist < 0) {
				close_tn = tn;
				mindist = Geo3d_Dist_Sqr(pos[0], pos[1], pos[2], tn_pos[0], tn_pos[1], tn_pos[2]);
				dxy = sqrt((pos[0]-tn_pos[0])*(pos[0]-tn_pos[0])+(pos[1]-tn_pos[1])*(pos[1]-tn_pos[1]));
				dz = fabs(pos[2] - tn_pos[2]);
			}else {
				double d = Geo3d_Dist_Sqr(pos[0], pos[1], pos[2],  tn_pos[0], tn_pos[1], tn_pos[2]);
				if (d < mindist) {
					mindist = d;
					close_tn = tn;
					dxy = sqrt((pos[0]-tn_pos[0])*(pos[0]-tn_pos[0])+(pos[1]-tn_pos[1])*(pos[1]-tn_pos[1]));
					dz = fabs(pos[2] - tn_pos[2]);
				}
			}
		}
	}

	*dist_xy = dxy;
	*dist_z = dz;
	return close_tn;
}
Esempio n. 2
0
double Puncta_Tree_Distance(double x, double y, double z, double r, Swc_Tree* tree, double pixelperumxy, double pixelperumz,
                            BOOL bmask,
                            double maskextendbyum, Swc_Tree_Node** refNode)
{
  double min_dist = DBL_MAX;
  double zscale = pixelperumxy/pixelperumz;
  Swc_Tree_Iterator_Start(tree, SWC_TREE_ITERATOR_DEPTH_FIRST, FALSE);
  Swc_Tree_Node *tn;
  while ((tn = Swc_Tree_Next(tree)) != NULL) {
    if (!Swc_Tree_Node_Is_Virtual(tn) && !Swc_Tree_Node_Is_Root(tn) && tn->node.type != 1) {
      double dist = sqrt((tn->node.x-x)*(tn->node.x-x) + (tn->node.y-y)*(tn->node.y-y) + (tn->node.z-z)*(tn->node.z-z))-tn->node.d;
      if (dist > 1000) {
        continue;
      }
      dist = Point_Frustum_Cone_Distance(x, y, z, &(tn->node), &(tn->parent->node), zscale);
      if (bmask) {
        double maskextendxy = maskextendbyum*pixelperumxy;
        if (dist < maskextendxy + r && dist < min_dist) {   //in mask area
          min_dist = dist;
          if (refNode)
            *refNode = tn;
        }
      } else {
        if (dist < min_dist) {
          min_dist = dist;
          if (refNode)
            *refNode = tn;
        }
      }
    }
  }
  return min_dist;
}
Esempio n. 3
0
double Point_Tree_Distance(double x, double y, double z, Swc_Tree* tree, double zScale, Swc_Tree_Node** refNode)
{
  double min_dist = DBL_MAX;
  Swc_Tree_Iterator_Start(tree, SWC_TREE_ITERATOR_DEPTH_FIRST, FALSE);
  Swc_Tree_Node *tn;
  while ((tn = Swc_Tree_Next(tree)) != NULL) {
    if (!Swc_Tree_Node_Is_Virtual(tn) && !Swc_Tree_Node_Is_Root(tn)) {
      double dist = Point_Frustum_Cone_Distance(x, y, z, &(tn->node), &(tn->parent->node), zScale);
      if (dist < min_dist) {
        min_dist = dist;
        if (refNode)
          *refNode = tn;
      }
    }
  }
  return min_dist;
}
Esempio n. 4
0
void ZSwcSignalFitter::fitSignal(
    Swc_Tree *tree, const ZStack *stack, int channel)
{
  Swc_Tree_Iterator_Start(tree, SWC_TREE_ITERATOR_DEPTH_FIRST, false);
  Swc_Tree_Node *tmptn = NULL;
  while ((tmptn = Swc_Tree_Next(tree)) != NULL) {
    if (!SwcTreeNode::isRoot(tmptn)) {
      ZPoint oldCenter = SwcTreeNode::center(tmptn);
      double oldBend = SwcTreeNode::maxBendingEnergy(tmptn);
      fitSignal(tmptn, stack, channel);
      double newBend = SwcTreeNode::maxBendingEnergy(tmptn);
      if (newBend > 1.0) {
        if (newBend - oldBend > 0.5) {
          SwcTreeNode::setPos(tmptn, oldCenter);
        }
      }
    }
  }
}
Esempio n. 5
0
/* Calculate positions of key nodes in the dendrogram of <tree>, which is a
 * reduced tree. */
static void swc_tree_dendrogram_position(Swc_Tree *tree, int max_vx, int max_vy,
					 double *x, double *y, double *dm,
					 double *xscale)
{
  int count = Swc_Tree_Iterator_Start(tree, 1, TRUE) + 1;
  
  /* alloc <decided> */
  uint8 *decided = u8array_calloc(count);
  
  /* alloc <isleaf> */
  uint8 *isleaf = u8array_calloc(count);

  /* the left-top corner of the bounding box is <margin> */
  double margin = 10.0;
  x[1] = 0.0;
  x[2] = 0.0;
  
  Swc_Tree_Node *root = tree->root;
  
  Swc_Tree_Node *node = root;
  int leaf_count = 0;
  double xmax = x[1];

  /* Calculate the x positions and the right most position. */
  /* x(tn) = x(p(tn)) + length(p(tn)->tn) */
  while ((node = node->next) != NULL) {
    x[Swc_Tree_Node_Data(node)->label] = node->weight + 
      x[Swc_Tree_Node_Data(node->parent)->label];
    xmax = dmax2(x[Swc_Tree_Node_Data(node)->label], xmax);
    if (node->first_child == NULL) {
      isleaf[Swc_Tree_Node_Data(node)->label] = 1;
      leaf_count++;
    }
  }

  
  *dm = 10.0;
  if (leaf_count > 1) {
    *dm = ((double) max_vy - 2.0 * margin) / (leaf_count - 1);
  }

  *xscale = (max_vx - margin * 2) / xmax;

  node = root;
  x[1] += margin;
  double cur_y = margin;
  //double ymax = 0.0;

  /* Calculate y positions of the leaves. */
  while ((node = node->next) != NULL) {
    if (Swc_Tree_Node_Label(node) > 1) {
      x[Swc_Tree_Node_Label(node)] = x[Swc_Tree_Node_Label(node)] * *xscale +
        margin;
      if (isleaf[Swc_Tree_Node_Data(node)->label]) {
        y[Swc_Tree_Node_Data(node)->label] = cur_y;
        decided[Swc_Tree_Node_Data(node)->label] = 1;
        cur_y += *dm;
      }
    }
  }
  
  Swc_Tree_Iterator_Start(tree, 2, FALSE);
  Swc_Tree_Iterator_Start(tree, -1, FALSE);
  /* Calculate the y positions by traversing backward */
  while ((node = Swc_Tree_Next(tree)) != NULL) {
    double tmp_miny = -1.0;
    double tmp_maxy = -1.0;
    if (decided[Swc_Tree_Node_Data(node)->label] == 0) {
      Swc_Tree_Node *child = node->first_child;
      int n = 0;
      cur_y = 0.0;
      while (child != NULL) {
        //cur_y += y[Swc_Tree_Node_Data(child)->label];
        cur_y = y[Swc_Tree_Node_Data(child)->label];
        if (tmp_miny < 0.0) {
          tmp_miny = cur_y;
          tmp_maxy = cur_y;
        } else {
          if (tmp_miny > cur_y) {
            tmp_miny = cur_y;
          } else if (tmp_maxy < cur_y) {
            tmp_maxy = cur_y;
          }
        }
        n++;
        child = child->next_sibling;
      }
      //y[Swc_Tree_Node_Data(node)->label] = cur_y / n;
      y[Swc_Tree_Node_Data(node)->label] = (tmp_miny + tmp_maxy) / 2.0;
      decided[Swc_Tree_Node_Data(node)->label] = 1;
    }
  }

  x[0] = x[1];
  y[0] = y[1];

  /* free <decided> */
  free(decided);
  
  /* free <isleaf> */
  free(isleaf);
}
Esempio n. 6
0
int main(int argc, char *argv[])
{

  static char *Spec[] = {"<dataset:string> | -D <string>", NULL};
  Process_Arguments(argc, argv, Spec, 1);

  char file_path[100];
  if (Is_Arg_Matched("-D")) {
    sprintf(file_path, "%s/error.xml", Get_String_Arg("-D"));
  } else {
    sprintf(file_path, "../data/diadem_%s/error.xml",
	    Get_String_Arg("dataset"));
  }

  xmlDocPtr doc;
  xmlNodePtr cur;

  doc = xmlParseFile(file_path);
  if (doc == NULL) {
    fprintf(stderr, "XML parsing failed.\n");
    return 1;
  }

  cur = xmlDocGetRootElement(doc);
  if (cur == NULL) {
    fprintf(stderr, "empty document\n");
    xmlFreeDoc(doc);
    return 1;
  }

  if (xmlStrcmp(cur->name, (const xmlChar*) "diadem_metric")) {
    fprintf(stderr, "document of wrong type\n");
    xmlFreeDoc(doc);
    return 1;
  }

  cur = cur->xmlChildrenNode;
  char *miss_file = NULL;
  char *golden_file = NULL;
  char *extra_file = NULL;
  char *nearby_file = NULL;
  char *test_file = NULL;
  char *miss_swc_file = NULL;
  char *extra_swc_file = NULL;
  char *nearby_swc_file = NULL;
  char *miss_vlm_file = NULL;
  char *extra_vlm_file = NULL;
  char *nearby_vlm_file = NULL;
  char *miss_score_file = NULL;
  char *extra_score_file = NULL;

  double EuDistThre_xy = 0.0;
  double EuDistThre_z = 0.0;
  double score;

  while (cur != NULL) {
    if (Xml_Node_Is_Element(cur, "miss") == TRUE) {
      miss_file = Xml_Node_String_Value(doc, cur);
    } else if (Xml_Node_Is_Element(cur, "extra") == TRUE) {
      extra_file = Xml_Node_String_Value(doc, cur);
    } else if (Xml_Node_Is_Element(cur, "score") == TRUE) {
      score = Xml_Node_Double_Value(doc, cur);
    } else if (Xml_Node_Is_Element(cur, "golden") == TRUE) {
      golden_file = Xml_Node_String_Value(doc, cur);
    } else if (Xml_Node_Is_Element(cur, "nearby") == TRUE) {
      nearby_file = Xml_Node_String_Value(doc, cur);
    } else if (Xml_Node_Is_Element(cur, "test") == TRUE) {
      test_file = Xml_Node_String_Value(doc, cur);
    } else if (Xml_Node_Is_Element(cur, "miss_swc") == TRUE) {
      miss_swc_file = Xml_Node_String_Value(doc, cur);
    } else if (Xml_Node_Is_Element(cur, "extra_swc") == TRUE) {
      extra_swc_file = Xml_Node_String_Value(doc, cur);
    } else if (Xml_Node_Is_Element(cur, "nearby_swc") == TRUE) {
      nearby_swc_file = Xml_Node_String_Value(doc, cur);
    } else if (Xml_Node_Is_Element(cur, "miss_vlm") == TRUE) {
      miss_vlm_file = Xml_Node_String_Value(doc, cur);
    } else if (Xml_Node_Is_Element(cur, "extra_vlm") == TRUE) {
      extra_vlm_file = Xml_Node_String_Value(doc, cur);
    } else if (Xml_Node_Is_Element(cur, "nearby_vlm") == TRUE) {
      nearby_vlm_file = Xml_Node_String_Value(doc, cur);
    } else if (Xml_Node_Is_Element(cur, "miss_score") == TRUE) {
      miss_score_file = Xml_Node_String_Value(doc, cur);
    } else if (Xml_Node_Is_Element(cur, "extra_score") == TRUE) {
      extra_score_file = Xml_Node_String_Value(doc, cur);
    }else if(Xml_Node_Is_Element(cur, "xyth") == TRUE) {
      EuDistThre_xy = Xml_Node_Double_Value(doc, cur);
    }else if(Xml_Node_Is_Element(cur, "zth") == TRUE) {
      EuDistThre_z = Xml_Node_Double_Value(doc, cur);
    }

    cur = cur->next;
  }

  if ((EuDistThre_xy <= 0.0) || (EuDistThre_z <= 0.0)) {
    fprintf(stderr, "Invalid threshold value\n");
    xmlFreeDoc(doc);
    return 1;
  }

  Swc_Tree *tree = Read_Swc_Tree(golden_file);

  double bound[6];
  Swc_Tree_Bound_Box(tree, bound);
  double marker_ratio = dmax3(bound[3] - bound[0], bound[4] - bound[1],
			      bound[5] - bound[2]) / 512.0;

  Geo3d_Scalar_Field *miss_field = read_node_file(miss_file);
  printf("The missed nodes:\n");
  Print_Geo3d_Scalar_Field(miss_field);

  Geo3d_Scalar_Field *extra_field = read_node_file(extra_file);
  printf("The extra nodes:\n");
  Print_Geo3d_Scalar_Field(extra_field);

  Geo3d_Scalar_Field *nearby_field = read_node_file(nearby_file);
  //    Print_Geo3d_Scalar_Field(nearby_field);

  double wm = darray_sum(miss_field->values, miss_field->size);
  double we = darray_sum(extra_field->values, extra_field->size);
  double wg = round((score * we + wm) / (1 - score));

  //    printf("%g %g %g\n", wm, we, wg);

  Swc_Tree_Iterator_Start(tree, 2, FALSE);
  int max_id = 0;
  Swc_Tree_Node *tn = NULL;
  while ((tn = Swc_Tree_Next(tree)) != NULL) {
    Swc_Tree_Node_Data(tn)->type = 3;
    if (max_id < Swc_Tree_Node_Data(tn)->id) {
      max_id = Swc_Tree_Node_Data(tn)->id;
    }
  }

  uint8 *nearby_mask = u8array_calloc(max_id + 1);

  /* process nearby nodes */
  FILE *fp = NULL;
  FILE *fp3 = NULL;

  if (nearby_swc_file != NULL) {
    fp = fopen(nearby_swc_file, "w");
  }

  if (nearby_vlm_file != NULL) {
    fp3 = fopen(nearby_vlm_file, "w");
  }

  //    printf("Nearby list\n");
  int i;
  for (i = 0; i < nearby_field->size; i++) {
    Swc_Tree_Node *tn = Swc_Tree_Closest_Node(tree, nearby_field->points[i]);

    nearby_mask[Swc_Tree_Node_Data(tn)->id] = 1;

    double w = (1.0+3.0/(1+exp(-(nearby_field->values[i]*2.0-2.0))))
      * marker_ratio;

    if (fp != NULL) {
      fprintf(fp, "%d %d %g %g %g %g %d\n", i + 1, 7,
	      Swc_Tree_Node_Data(tn)->x,
	      Swc_Tree_Node_Data(tn)->y, Swc_Tree_Node_Data(tn)->z,w, -1);
    }

    if (fp3 != NULL) {
      fprintf(fp3, "%g,%g,%g,%g,1,%g\n", Swc_Tree_Node_Data(tn)->x,
	      Swc_Tree_Node_Data(tn)->y, Swc_Tree_Node_Data(tn)->z,
	      w, nearby_field->values[i]);
    }
  }
  if (fp != NULL) {
    fclose(fp);
  }
  if (fp3 != NULL) {
    fclose(fp3);
  }

  /* process missing nodes */
  fp = NULL;
  FILE *fp2 = fopen(miss_score_file, "w");
  fp3 = NULL;

  if (miss_swc_file != NULL) {
    fp = fopen(miss_swc_file, "w");
  }

  if (miss_vlm_file != NULL) {
    fp3 = fopen(miss_vlm_file, "w");
  }

  Swc_Tree *test_tree = Read_Swc_Tree(test_file);

  //    printf("Missing list\n");
  int n_leaves = 0;
  int n_branchings = 0;
  int n_leaves_distance = 0;
  int n_leaves_path = 0;
  int n_branchings_distance = 0;
  int n_branchings_path = 0;

  double score_leaves = 0.0;
  double score_branchings = 0.0;
  double score_leaves_distance = 0.0;
  double score_leaves_path = 0.0;
  double score_branching_distance = 0.0;
  double score_branching_path = 0.0;

  BOOL error_type; // 'true' indicates distance-error, 'false' indicates path-error

  for (i = 0; i < miss_field->size; i++) {
    Swc_Tree_Node *tn = Swc_Tree_Closest_Node(tree, miss_field->points[i]);
    double cur_score = miss_field->values[i] / (wg + we);
    fprintf(fp2, "%4d | %5.2f %5.2f %5.2f | %g | %g\n", Swc_Tree_Node_Data(tn)->id,
	    Swc_Tree_Node_Data(tn)->x, Swc_Tree_Node_Data(tn)->y,
	    Swc_Tree_Node_Data(tn)->z, miss_field->values[i],
	    cur_score);

    Swc_Tree_Node_Data(tn)->type = 2;

    double w = (1.0+3.0/(1+exp(-(miss_field->values[i]*2.0-2.0))))
      * marker_ratio;

    if (fp != NULL) {
      int type = 0;
      if (nearby_mask[Swc_Tree_Node_Data(tn)->id] == 1) {
	type = 1;
      }
      fprintf(fp, "%d %d %g %g %g %g %d\n", i + 1, type,
	      Swc_Tree_Node_Data(tn)->x,
	      Swc_Tree_Node_Data(tn)->y, Swc_Tree_Node_Data(tn)->z, w, -1);
    }

    if (fp3 != NULL) {
      double xy_dist, z_dist;
      Swc_Tree_Node *test_tn;
      double pos[3];
      Swc_Tree_Node_Pos(tn, pos);
      if(Swc_Tree_Node_Is_Branch_Point(tn))
	test_tn = Find_Closest_Branch_Point(test_tree, pos, &xy_dist, &z_dist);
      else
	test_tn = Find_Closest_Leaf_Point(test_tree, pos, &xy_dist, &z_dist);

      if(xy_dist >= EuDistThre_xy || z_dist >= EuDistThre_z){
	fprintf(fp3, "%g,%g,%g,%g,1,%g,[xy-%g z-%g | distance_error], 255, 255, 0\n",Swc_Tree_Node_Data(tn)->x + 1.0,
		Swc_Tree_Node_Data(tn)->y + 1.0, Swc_Tree_Node_Data(tn)->z + 1.0,
		w, miss_field->values[i], xy_dist, z_dist);
	error_type = TRUE;
      }else{
	fprintf(fp3, "%g,%g,%g,%g,1,%g,[xy-%g z-%g | path_error], 255, 0, 255\n",Swc_Tree_Node_Data(tn)->x + 1.0,
		Swc_Tree_Node_Data(tn)->y + 1.0, Swc_Tree_Node_Data(tn)->z + 1.0,
		w, miss_field->values[i], xy_dist, z_dist);
	error_type = FALSE;
      }
    }

    if(miss_field->values[i]==1){
      n_leaves ++;
      score_leaves += cur_score;
      if(error_type){ // distance error
	n_leaves_distance ++;
	score_leaves_distance += cur_score;
      }else{
	n_leaves_path ++;
	score_leaves_path += cur_score;
      }
    }else{
      n_branchings ++;
      score_branchings += cur_score;
      if(error_type){ // distance error
	n_branchings_distance ++;
	score_branching_distance += cur_score;
      }else{
	n_branchings_path ++;
	score_branching_path += cur_score;
      }
    }
  }

  if(fp2 != NULL){
    fprintf(fp2, "\nleaf errors:  \t %d | loss score: %g(%2.1f%%)\n", n_leaves, score_leaves, 100*score_leaves/(1 - score));
    fprintf(fp2, "leaf errors (dist): %d | loss score: %g(%2.1f%%) \n", n_leaves_distance, score_leaves_distance, 100*score_leaves_distance/(1 - score));
    fprintf(fp2, "leaf errors (path): %d | loss score: %g(%2.1f%%) \n", n_leaves_path, score_leaves_path, 100*score_leaves_path/(1 - score));
    fprintf(fp2, "\nbranching errors: \t %d | score loss: %g(%2.1f%%) \n", n_branchings, score_branchings, 100*score_branchings/(1 - score));
    fprintf(fp2, "branching error (dist):  %d | score loss: %g(%2.1f%%) \n", n_branchings_distance, score_branching_distance, 100*score_branching_distance/(1 - score));
    fprintf(fp2, "branching error (path):  %d | score loss: %g(%2.1f%%) \n", n_branchings_path, score_branching_path, 100*score_branching_path/(1 - score));
  }
  if (fp != NULL) {
    fclose(fp);
  }
  fclose(fp2);
  if (fp3 != NULL) {
    fclose(fp3);
  }

  /*
    sprintf(file_path, "../data/diadem_%s/error.swc", Get_String_Arg("dataset"));
    Write_Swc_Tree(file_path, tree);
  */

  tree = test_tree;

  /* process extra nodes*/
  fp = NULL;
  fp2 = fopen(extra_score_file, "w");
  fp3 = NULL;

  if (extra_swc_file != NULL) {
    fp = fopen(extra_swc_file, "w");
  }

  if (extra_vlm_file != NULL) {
    fp3 = fopen(extra_vlm_file, "w");
  }

  //    printf("Extra list\n");
  n_leaves = 0;
  n_branchings = 0;

  score_leaves = 0.0;
  score_branchings = 0.0;


  for (i = 0; i < extra_field->size; i++) {
    Swc_Tree_Node *tn = Swc_Tree_Closest_Node(tree, extra_field->points[i]);
    double cur_score = extra_field->values[i] * (wg - wm) / (wg + we) / (wg + we - extra_field->values[i]);

    fprintf(fp2, "%4d | %5.2f %5.2f %5.2f | %g | %g\n", Swc_Tree_Node_Data(tn)->id,
	    Swc_Tree_Node_Data(tn)->x, Swc_Tree_Node_Data(tn)->y,
	    Swc_Tree_Node_Data(tn)->z, extra_field->values[i], cur_score);

    double w = (1.0+3.0/(1+exp(-(extra_field->values[i]*2.0-2.0))))
      * marker_ratio;

    if (fp != NULL) {
      fprintf(fp, "%d %d %g %g %g %g %d\n", i + 1, 1,
	      Swc_Tree_Node_Data(tn)->x,
	      Swc_Tree_Node_Data(tn)->y, Swc_Tree_Node_Data(tn)->z, w, -1);
    }

    if (fp3 != NULL) {
      fprintf(fp3, "%g,%g,%g,%g,1,%g, error, 255, 255, 0\n", Swc_Tree_Node_Data(tn)->x + 1.0,
	      Swc_Tree_Node_Data(tn)->y + 1.0, Swc_Tree_Node_Data(tn)->z + 1.0,
	      w, extra_field->values[i]);
    }

    if(extra_field->values[i]==1){
      n_leaves ++;
      score_leaves += cur_score;
    }else{
      n_branchings ++;
      score_branchings += cur_score;
    }
  }

  if(fp2 != NULL){
    fprintf(fp2, "\nleaf errors:   %d | loss score: %g(%2.1f%%)\n", n_leaves, score_leaves, 100*score_leaves/(1 - score));
    fprintf(fp2, "branching errors:  %d | score loss: %g(%2.1f%%) \n", n_branchings, score_branchings, 100*score_branchings/(1 - score));
  }

  if (fp != NULL) {
    fclose(fp);
  }
  fclose(fp2);
  if (fp3 != NULL) {
    fclose(fp3);
  }

  xmlFreeDoc(doc);

  printf("Score = %g\n", score);

  return 0;
}
Esempio n. 7
0
static void swc_tree_remove_zjump(Swc_Tree *tree, double thre)
{
  BOOL stop = FALSE;

  while (stop == FALSE) {
    stop = TRUE;
    Swc_Tree_Iterator_Start(tree, SWC_TREE_ITERATOR_DEPTH_FIRST, FALSE);

    double length = 0.0; /* branch length */

    Swc_Tree_Node *tn = NULL;
    Swc_Tree_Node *prev_tn = NULL;
    int state = 0;
    prev_tn = Swc_Tree_Next(tree);
    if (Swc_Tree_Node_Is_Virtual(prev_tn)) {
      prev_tn = Swc_Tree_Next(tree);
    }
    if (Swc_Tree_Node_Is_Branch_Point(prev_tn)) {
      state = 1;
    }

    while ((tn = Swc_Tree_Next(tree)) != NULL) {
      switch (state) {
	case 0: /* wait for starting branching point */
	  if (Swc_Tree_Node_Is_Branch_Point(tn)) {
	    state = 1;
	  }
	  break;
	case 1: /* branching on */
	  if (tn->parent == prev_tn) {
	    length += Swc_Tree_Node_Length(tn);
	    if (Swc_Tree_Node_Is_Branch_Point(tn)) {
	      state = 2;
	    } else if (Swc_Tree_Node_Is_Leaf(tn)) {
	      length = 0.0;
	    }
	  } else {
	    length = Swc_Tree_Node_Length(tn);
	    if (Swc_Tree_Node_Is_Branch_Point(tn)) {
	      state = 2;
	    } 
	  }
	  break;
	default:
	  break;
      }

      if (state == 2) {
	state = 1;

	if (length <= thre) {
	  /* check orientation */
	  Swc_Tree_Node *tmp_tn = tn->parent;
	  double z = 0.0;
	  while (Swc_Tree_Node_Is_Continuation(tmp_tn)) {
	    tmp_tn = tmp_tn->parent;
	  }
	  z = fabs(Swc_Tree_Node_Data(tmp_tn)->z -
	      Swc_Tree_Node_Data(tn)->z);
	  double a = Swc_Tree_Node_Dot(tn->parent, tn, tn->first_child);
	  printf("%g, %g\n", z/length, a);
	  if (z/length > 0.3 /*&& a < 0.7*/) {
	    //Swc_Tree_Node_Label_Branch_U(tn, 5);
	    Swc_Tree_Node_Detach_Parent(tn);
	    stop = FALSE;
	    break;
	  }
	}
	length = 0.0;
      }
      prev_tn = tn;
    }
  }

  Swc_Tree_Set_Type_As_Label(tree);

  Swc_Tree_Resort_Id(tree);
}