예제 #1
0
파일: tz_swc.c 프로젝트: Vaa3D/vaa3d_tools
Graph* Swc_Arraylist_Graph(const Swc_Arraylist *sc, int *q)
{
  BOOL is_owner = TRUE;

  if (q != NULL) {
    is_owner = FALSE;
  }

  q = Swc_Arraylist_Queue(sc, q);
  Graph *graph = Make_Graph(sc->length, sc->length - 1, FALSE);
  Graph_Set_Directed(graph, TRUE);

  int i;
  for (i = 0; i < sc->length; i++) {
    if (q[i] >= 0) {
      Graph_Add_Edge(graph, q[i], i);
    }
  }

  if (is_owner == TRUE) {
    free(q);
  }

  return graph;
}
예제 #2
0
void solve() {
	scanf("%d", &n);
	for (int i = 0; i < n; i++) scanf("%lf%lf", &p[i].x, &p[i].y), p[i].index = i, p[i].in = NULL;
	Alloc_memory(); sort(p, p + n);
	for (int i = 0; i < n; i++) Q[i] = p + i;
	edge *L, *R; Divide(0, n - 1, &L, &R);
	M = 0; Make_Graph(); Kruskal();
}
예제 #3
0
Graph* Stack_Label_Field_Neighbor_Graph(Stack *stack, int threshold,
    Objlabel_Workspace *ow)
{
  TZ_ASSERT(stack->kind == GREY16, "Invalid stack kind");
  STACK_OBJLABEL_OPEN_WORKSPACE(stack, ow);


  Graph *graph = Make_Graph(0, 1, TRUE);
  graph->nvertex = Stack_Max(stack, NULL) + 1;

  Graph_Workspace *gw = New_Graph_Workspace();

  uint16_t *signal_array = (uint16_t*) stack->array;

  int neighbor_offset[26];
  int is_in_bound[26];

  Stack_Neighbor_Offset(ow->conn, stack->width, stack->height, neighbor_offset);

  /* Identify number of objects */
  int object_number = 0;
  int width = stack->width;
  int height = stack->height;
  int depth = stack->depth;
  size_t voxelNumber = Stack_Voxel_Number(stack);
  size_t index;

  //Stack *mask = Make_Stack(GREY, width, height, depth);

  for (index = 0; index < voxelNumber; ++index) {
    if (object_number < signal_array[index]) {
      object_number = signal_array[index];
    }

    if (ow->init_chord == TRUE) {
      ow->chord->array[index] = -1;
    }

    //mask->array[index] = 0;
  }

  //uint8_t *visited = mask->array;

  Int_Arraylist *seed_head = Make_Int_Arraylist(object_number + 1, 0);
  Int_Arraylist *seed_tail = Make_Int_Arraylist(object_number + 1, 0);
  Int_Arraylist *seed_point = Make_Int_Arraylist(object_number + 1, 0);
  int i;
  for (i = 0; i < seed_head->length; ++i) {
    seed_head->array[i] = -1;
    seed_point->array[i] = -1;
    seed_tail->array[i] = -1;
  }

  int *seed_queue = ow->chord->array;

  /* Initialize the seeds for each object */
  for (index = 0; index < voxelNumber; ++index) {
    uint16_t object_label = signal_array[index];
    int *current_seed_head = seed_head->array + object_label;
    int *current_seed_tail = seed_tail->array + object_label;
    int *current_seed_point = seed_point->array + object_label;
    int nbound = Stack_Neighbor_Bound_Test_I(ow->conn, width, height, depth,
        index, is_in_bound);
    if (is_border_voxel(signal_array, index, ow->conn,
          neighbor_offset, is_in_bound, nbound) == TRUE) { 
      //visited[index] = 1;
      if (*current_seed_head < 0) {
        *current_seed_head = index;
        *current_seed_tail = index;
        *current_seed_point = *current_seed_head;
      } else {
        seed_queue[*current_seed_point] = index;
        *current_seed_point = index;
      }
    }
  }

  int current_level = 0;
  /* While the current growing level is below the threshold */
  while (current_level < threshold) {
    /* Grow each object */
    uint16_t object_label;
    for (object_label = 1; object_label <= object_number; ++object_label) {
      int current_tail = seed_tail->array[object_label];
      int new_tail = current_tail;
      int seed = seed_head->array[object_label];
      while (seed >= 0) {
        int nbound = Stack_Neighbor_Bound_Test_I(ow->conn, width, height, depth,
            seed, is_in_bound);
        int j;
        for (j = 0; j < ow->conn; ++j) {
          if (nbound == ow->conn || is_in_bound[j]) {
            int neighbor_index = seed + neighbor_offset[j];
            uint16_t neighbor_label = signal_array[neighbor_index];
            if (neighbor_label == 0) {
              seed_queue[new_tail] = neighbor_index;
              new_tail = neighbor_index;
              signal_array[neighbor_index] = object_label;
              //visited[neighbor_index] = 1;
            } else if (neighbor_label != object_label) {
              /* If x-y does not exist */
              if (Graph_Edge_Index_U(object_label, neighbor_label, gw)
                  < 0) {
                double weight = current_level * 2;
                if (object_label > neighbor_label) {
                  weight += 1.0;
                }
                Graph_Add_Weighted_Edge(graph, 
                    object_label, neighbor_label, weight);
                Graph_Expand_Edge_Table(object_label, neighbor_label,
                    graph->nedge - 1, gw);
              }
            }
          }
        }
        if (seed == current_tail) {
          break;
        }
        seed = seed_queue[seed];
      }

      if (current_tail >= 0) {
        seed_head->array[object_label] = seed_queue[current_tail];
        seed_tail->array[object_label] = new_tail;
      }
    }

    ++current_level;
  }

  Kill_Int_Arraylist(seed_head);
  Kill_Int_Arraylist(seed_tail);
  Kill_Int_Arraylist(seed_point);

  Kill_Graph_Workspace(gw);

  STACK_OBJLABEL_CLOSE_WORKSPACE(ow);

  //Kill_Stack(mask);

  return graph;
}
예제 #4
0
/**
 * Stack_Build_Seed_Graph_Gg() allows users to build a seed graph using 
 * approximate geodesdic distances. The workspace should be created by
 * Make_Objlabel_Workspace_Gg() and initialized by Init_Objlabel_Workspace_Gg()
 * if necessary.
 */
Graph* Stack_Build_Seed_Graph_Gg(Stack *stack, int *seed, int nseed,
				BOOL weighted, Objlabel_Workspace *ow)
{
  if (stack->kind != GREY16) {
    PRINT_EXCEPTION("Unsupported stack kind", "The stack must be GREY16");
    return NULL;
  }
  
  int i, j, k;

  uint16 *level = (uint16 *) ow->u;
  uint16 *mask = (uint16 *) stack->array;

  const int conn = 26;

  /* each seed has a queue */
  int *queue_head = iarray_malloc(nseed); /* queue_head malloced */
  int *queue_tail = iarray_malloc(nseed); /* queue_head malloced */
  int *queue_length = iarray_malloc(nseed);  /* queue_length malloced */

  /* At the beginning, each queue has one element, the corresponding seed */
  iarraycpy(queue_head, seed, 0, nseed);
  iarraycpy(queue_tail, seed, 0, nseed);

  for (i = 0; i < nseed; i++) {
    queue_length[i] = 1;
  }

  int neighbor[26];
  int bound[26];
  int nbound;
  int cwidth = stack->width - 1;
  int cheight = stack->height - 1;
  int cdepth = stack->depth - 1;

  BOOL stop = FALSE;
  int x, y, z;

  Stack_Neighbor_Offset(conn, stack->width, stack->height, neighbor);
  
#define STACK_SEED_GRAPH_UPDATE_QUEUE_GG(test)				\
  for (k = 0; k < conn; k++) {						\
    if (test) {								\
      int checking_voxel = queue_head[i] + neighbor[k];			\
      if ((mask[checking_voxel] > 0) && (mask[checking_voxel] != label)) { \
	if (mask[checking_voxel] == 1) {				\
	  ow->chord->array[queue_tail[i]] = checking_voxel;		\
	  queue_tail[i] = checking_voxel;				\
	  mask[checking_voxel] = label;					\
	  level[checking_voxel] = level[queue_head[i]] + 1;		\
	  queue_length[i]++;						\
	} else {							\
	  int v1, v2, tmp;						\
	  v1 = i;							\
	  v2 = mask[checking_voxel] - 2;				\
	  ASSERT(v1 != v2, "Bug in Stack_Build_Seed_Graph_G()");	\
	  if (v1 > v2) {						\
	    SWAP2(v1, v2, tmp);						\
	  }								\
	  if (Graph_Edge_Index(v1, v2, gw) < 0) {			\
	    if (weighted == TRUE) {					\
	      /*double dist = Stack_Util_Voxel_Distance(seed[v1], seed[v2], stack->width, stack->height);*/ \
	      double dist = level[checking_voxel] + level[queue_head[i]]; \
	      Graph_Add_Weighted_Edge(graph, v1, v2, dist);		\
	    } else {							\
	      Graph_Add_Edge(graph, v1, v2);				\
	    }								\
	    Graph_Expand_Edge_Table(v1, v2, graph->nedge -1, gw);	\
	  }								\
	}								\
      }									\
    }									\
  }

  Graph *graph = Make_Graph(nseed, nseed, weighted);
  Graph_Workspace *gw = New_Graph_Workspace();

  while (stop == FALSE) {
    stop = TRUE;
    for (i = 0; i < nseed; i++) {
      if (queue_length[i] > 0) {
	int label = i + 2;
	for (j = 0; j < queue_length[i]; j++) {
	  Stack_Util_Coord(queue_head[i], stack->width, stack->height, 
			   &x, &y, &z);
	  nbound = Stack_Neighbor_Bound_Test(conn, cwidth, cheight, cdepth,
					     x, y, z, bound);
	  if (nbound == conn) {
	    STACK_SEED_GRAPH_UPDATE_QUEUE_GG(1);
	  } else {
	    STACK_SEED_GRAPH_UPDATE_QUEUE_GG(bound[k]);
	  }
	}
	queue_head[i] = ow->chord->array[queue_head[i]];
	queue_length[i]--;
	stop = FALSE;
      }
    }
  }

  free(queue_head); /* queue_head freed */
  free(queue_tail); /* queue_head freed */
  free(queue_length);  /* queue_length freed */

  return graph;
}
예제 #5
0
Graph* Stack_Graph_W(const Stack *stack, Stack_Graph_Workspace *sgw)
{
  int x, y, z;
  int offset = 0;
  int is_in_bound[26];
  int nbound;
  int i;
  int stack_range[6];

  int *range = sgw->range;

  if (range == NULL) {
    stack_range[0] = 0;
    stack_range[1] = stack->width - 1;
    stack_range[2] = 0;
    stack_range[3] = stack->height - 1;
    stack_range[4] = 0;
    stack_range[5] = stack->depth - 1;
  } else {
    stack_range[0] = imax2(0, range[0]);
    stack_range[1] = imin2(stack->width - 1, range[1]);
    stack_range[2] = imax2(0, range[2]);
    stack_range[3] = imin2(stack->height - 1, range[3]);
    stack_range[4] = imax2(0, range[4]);
    stack_range[5] = imin2(stack->depth - 1, range[5]);
  }
  
  int cdepth = stack_range[5] - stack_range[4];
  int cheight = stack_range[3] - stack_range[2];
  int cwidth = stack_range[1] - stack_range[0];
  
  int nvertex = (cwidth + 1) * (cheight + 1) * (cdepth + 1);
  sgw->virtualVertex = nvertex;

  BOOL weighted = TRUE;
  if (sgw->sp_option == 1) {
    weighted = FALSE;
    sgw->intensity = darray_malloc(nvertex + 1);
    sgw->intensity[nvertex] = Infinity;
  }
  Graph *graph = Make_Graph(nvertex, nvertex, weighted);

  int neighbor[26];
  int scan_mask[26];
  Stack_Neighbor_Offset(sgw->conn, cwidth + 1, cheight + 1, neighbor);

  int org_neighbor[26];
  Stack_Neighbor_Offset(sgw->conn, Stack_Width(stack), Stack_Height(stack), 
      org_neighbor);

  double dist[26];
  Stack_Neighbor_Dist_R(sgw->conn, sgw->resolution, dist);
  //const double *dist = Stack_Neighbor_Dist(sgw->conn);
  const int *x_offset = Stack_Neighbor_X_Offset(sgw->conn);
  const int *y_offset = Stack_Neighbor_Y_Offset(sgw->conn);
  const int *z_offset = Stack_Neighbor_Z_Offset(sgw->conn);

  /* go forward */
  for (i = 0; i < sgw->conn; i++) {
    scan_mask[i] = (neighbor[i] > 0);
  }

#define STACK_GRAPH_ADD_EDGE(cond) \
  for (i = 0; i < sgw->conn; i++) { \
    if (cond) { \
      int nx = x + stack_range[0]; \
      int ny = y + stack_range[2]; \
      int nz = z + stack_range[4]; \
      if (Graph_Is_Weighted(graph)) { \
	double weight = dist[i]; \
	if (sgw->wf != NULL) { \
	  sgw->argv[0] = dist[i]; \
	  \
	  sgw->argv[1] = Get_Stack_Pixel((Stack *)stack, nx, ny, nz, 0); \
	  sgw->argv[2] = \
	  Get_Stack_Pixel((Stack *)stack, nx + x_offset[i], \
	      ny + y_offset[i], nz + z_offset[i], 0); \
	  weight = sgw->wf(sgw->argv); \
	} \
	Graph_Add_Weighted_Edge(graph, offset, offset + neighbor[i], \
	    weight); \
      } else { \
	Graph_Add_Edge(graph, offset, offset + neighbor[i]); \
	sgw->intensity[offset] = Get_Stack_Pixel((Stack*) stack, \
	      nx, ny, nz, 0); \
      } \
    } \
  }

  int groupVertexMap[256];
  for (i = 0; i < 256; ++i) {
    groupVertexMap[i] = 0;
  }

  int swidth = cwidth + 1;
  int sarea =  (cwidth + 1) * (cheight + 1);
  int area = stack->width * stack->height;
  for (z = 0; z <= cdepth; z++) {
    for (y = 0; y <= cheight; y++) {
      for (x = 0; x <= cwidth; x++) {
	nbound = Stack_Neighbor_Bound_Test_S(sgw->conn, cwidth, cheight, 
					     cdepth, 
					     x, y, z, is_in_bound);
	size_t offset2 = Stack_Subindex((size_t) offset, stack_range[0],
	    stack_range[2], stack_range[4],
	    swidth, sarea, stack->width, area);

#ifdef _DEBUG_2
        if (offset == 36629) {
          printf("debug here\n");
        }
#endif

	if (nbound == sgw->conn) {
	  STACK_GRAPH_ADD_EDGE((scan_mask[i] == 1) && 
              (sgw->signal_mask == NULL ? 1 : 
               ((sgw->signal_mask->array[offset2] > 0) &&
                (sgw->signal_mask->array[offset2+org_neighbor[i]] > 0))))
	} else {
	  STACK_GRAPH_ADD_EDGE((scan_mask[i] == 1) && is_in_bound[i] && 
	      (sgw->signal_mask == NULL ? 1 : 
	       ((sgw->signal_mask->array[offset2] > 0) &&
		(sgw->signal_mask->array[offset2+org_neighbor[i]]) >
		0)))
	}
	if (sgw->group_mask != NULL) {
          int groupId = sgw->group_mask->array[offset2];
	  if (groupId > 0) {
#ifdef _DEBUG_2
	    sgw->group_mask->array[offset2] = 2;
#endif
            int groupVertex = groupVertexMap[groupId];
            if (groupVertex <= 0) {
              groupVertex = nvertex++;
              groupVertexMap[groupId] = groupVertex;
            }

            Graph_Add_Weighted_Edge(graph, groupVertex, offset, 0.0);
	  }
	}

	offset++;
      }
    }
  }

  return graph;
}
예제 #6
0
Graph* Stack_Graph(const Stack *stack, int conn, const int *range, 
		   Weight_Func_t *wf)
{
  int x, y, z;
  int offset = 0;
  int is_in_bound[26];
  int nbound;
  int i;
  int stack_range[6];

  if (range == NULL) {
    stack_range[0] = 0;
    stack_range[1] = stack->width - 1;
    stack_range[2] = 0;
    stack_range[3] = stack->height - 1;
    stack_range[4] = 0;
    stack_range[5] = stack->depth - 1;
  } else {
    stack_range[0] = imax2(0, range[0]);
    stack_range[1] = imin2(stack->width - 1, range[1]);
    stack_range[2] = imax2(0, range[2]);
    stack_range[3] = imin2(stack->height - 1, range[3]);
    stack_range[4] = imax2(0, range[4]);
    stack_range[5] = imin2(stack->depth - 1, range[5]);
  }
  
  int cdepth = stack_range[5] - stack_range[4];
  int cheight = stack_range[3] - stack_range[2];
  int cwidth = stack_range[1] - stack_range[0];
  
  int nvertex = (cwidth + 1) * (cheight + 1) * (cdepth + 1);

  Graph *graph = Make_Graph(nvertex, nvertex, TRUE);

  int neighbor[26];
  int scan_mask[26];
  Stack_Neighbor_Offset(conn, cwidth + 1, cheight + 1, neighbor);

  const double *dist = Stack_Neighbor_Dist(conn);
  const int *x_offset = Stack_Neighbor_X_Offset(conn);
  const int *y_offset = Stack_Neighbor_Y_Offset(conn);
  const int *z_offset = Stack_Neighbor_Z_Offset(conn);

  double args[3];

  for (i = 0; i < conn; i++) {
    scan_mask[i] = (neighbor[i] > 0);
  }

  for (z = 0; z <= cdepth; z++) {
    for (y = 0; y <= cheight; y++) {
      for (x = 0; x <= cwidth; x++) {
	nbound = Stack_Neighbor_Bound_Test(conn, cwidth, cheight, cdepth, 
					   x, y, z, is_in_bound);
	if (nbound == conn) {
	  for (i = 0; i < conn; i++) {
	    if (scan_mask[i] == 1) {
	      double weight = dist[i];
	      if (wf != NULL) {
		args[0] = dist[i];
		args[1] = Get_Stack_Pixel((Stack *)stack, x + stack_range[0], 
					  y + stack_range[2], 
					  z + stack_range[4], 0);
		args[2] = Get_Stack_Pixel((Stack *)stack, 
					  x + stack_range[0] + x_offset[i],
					  y + stack_range[2] + y_offset[i],
					  z + stack_range[4] + z_offset[i], 0);
		weight = wf(args);
	      }
	      Graph_Add_Weighted_Edge(graph, offset, offset + neighbor[i], 
				      weight);
	    }
	  }
	} else {
	  for (i = 0; i < conn; i++) {
	    if ((scan_mask[i] == 1) && is_in_bound[i]){
	      double weight = dist[i];
	      if (wf != NULL) {
		args[0] = dist[i];
		args[1] = Get_Stack_Pixel((Stack *)stack, x + stack_range[0], 
					  y + stack_range[2], 
					  z + stack_range[4], 0);
		args[2] = Get_Stack_Pixel((Stack *)stack, 
					  x + stack_range[0] + x_offset[i],
					  y + stack_range[2] + y_offset[i],
					  z + stack_range[4] + z_offset[i], 0);
		weight = wf(args);
	      }
	      Graph_Add_Weighted_Edge(graph, offset, offset + neighbor[i], 
				      weight);
	    }
	  }
	}
	offset++;
      }
    }
  }

  return graph;
}
예제 #7
0
int main()
{
#if 0
  char *filepath = "../data/fly_neuron_n2/graph_d.swc";
  
  Neuron_Structure *ns = Neuron_Structure_From_Swc_File(filepath);
  
  Neuron_Component_Arraylist *comp_array =
    Neuron_Structure_Branch_Point(ns);

  filepath = "../data/fly_neuron_n2.tif";
  Stack *stack = Read_Stack(filepath);
  Translate_Stack(stack, COLOR, 1);

  int i;
  Stack_Draw_Workspace *ws = New_Stack_Draw_Workspace();
  for (i = 0; i < comp_array->length; i++) {
    Neuron_Component_Draw_Stack(comp_array->array + i, stack, ws);
  }
  Kill_Stack_Draw_Workspace(ws);

  Write_Stack("../data/test.tif", stack);
#endif

#if 0
  Stack *stack = NULL;

  Locseg_Chain *chain1 = Read_Locseg_Chain("../data/fly_neuron_n3/chain0.tb");
  Locseg_Chain *chain2 = Read_Locseg_Chain("../data/fly_neuron_n3/chain10.tb");

  Connection_Test_Workspace *ws = New_Connection_Test_Workspace();
  Connection_Test_Workspace_Read_Resolution(ws, "../data/fly_neuron_n1.res");

  Neurocomp_Conn conn;
  conn.mode = NEUROCOMP_CONN_HL;
  Locseg_Chain_Connection_Test(chain1, chain2, stack, 1.0, &conn, ws);

  Print_Neurocomp_Conn(&conn);
#endif

#if 0
  Locseg_Chain **chain = (Locseg_Chain**) malloc(sizeof(Locseg_Chain*) * 3);
  chain[0] = Read_Locseg_Chain("../data/mouse_single_org/chain4.tb");
  chain[1] = Read_Locseg_Chain("../data/mouse_single_org/chain19.tb");
  chain[2] = Read_Locseg_Chain("../data/mouse_single_org/chain64.tb");

  Stack *signal = Read_Stack("../data/mouse_single_org.tif");

  Connection_Test_Workspace *ctw = New_Connection_Test_Workspace();
    
  FILE *fp = fopen("../data/mouse_single_org.res", "r");

  darray_fscanf(fp, ctw->resolution, 3);

  Neuron_Component *chain_array = Make_Neuron_Component_Array(3);

  int i;
  for (i = 0; i < 3; i++) {
    Set_Neuron_Component(chain_array + i, 
			 NEUROCOMP_TYPE_LOCSEG_CHAIN, chain[i]);
  }

  Neuron_Structure *ns = Locseg_Chain_Comp_Neurostruct(chain_array, 
						       3, signal, 1.0, ctw);
  Graph *graph = ns->graph;

  Process_Neuron_Structure(ns);

  Print_Neuron_Structure(ns);

  Neuron_Structure_Crossover_Test(ns, 0.5375);

  printf("\ncross over changed: \n");
  Print_Neuron_Structure(ns);
#endif

#if 0
  Neuron_Structure *ns = Make_Neuron_Structure(5);

  Set_Neuron_Component(ns->comp, NEUROCOMP_TYPE_GEO3D_CIRCLE, 
		       New_Geo3d_Circle());
  Set_Neuron_Component(ns->comp + 1, NEUROCOMP_TYPE_GEO3D_CIRCLE, 
		       New_Geo3d_Circle());
  Set_Neuron_Component(ns->comp + 2, NEUROCOMP_TYPE_GEO3D_CIRCLE, 
		       New_Geo3d_Circle());
  Set_Neuron_Component(ns->comp + 3, NEUROCOMP_TYPE_GEO3D_CIRCLE, 
		       New_Geo3d_Circle());
  Set_Neuron_Component(ns->comp + 4, NEUROCOMP_TYPE_GEO3D_CIRCLE, 
		       New_Geo3d_Circle());

  NEUROCOMP_GEO3D_CIRCLE(ns->comp)->radius = 1.5;
  NEUROCOMP_GEO3D_CIRCLE(ns->comp + 1)->radius = 2.5;
  NEUROCOMP_GEO3D_CIRCLE(ns->comp + 2)->radius = 3.5;
  NEUROCOMP_GEO3D_CIRCLE(ns->comp + 3)->radius = 4.5;
  NEUROCOMP_GEO3D_CIRCLE(ns->comp + 4)->radius = 5.5;
 
  ns->graph = Make_Graph(5, 4, 0);
  //Graph_Add_Edge(ns->graph, 0, 1);
  Graph_Add_Edge(ns->graph, 1, 3);
  Graph_Add_Edge(ns->graph, 1, 4);
  Graph_Add_Edge(ns->graph, 0, 2);

  Graph_Set_Directed(ns->graph, TRUE);

  Print_Graph(ns->graph);

  Swc_Tree *tree = Neuron_Structure_To_Swc_Tree_Circle_Z(ns, 1.0, NULL);
  Print_Swc_Tree(tree);

  Swc_Tree_To_Dot_File(tree, "../data/test2.dot");
#endif

#if 0
  int n;
  Neuron_Component *chain_array = Dir_Locseg_Chain_Nc("../data/fly_neuron_n22", 
						      "^chain.*\\.tb", 
						      &n, NULL);
  
  Neuron_Structure *ns =
    Locseg_Chain_Comp_Neurostruct(chain_array, n, NULL, 1.0, NULL);
  
  Process_Neuron_Structure(ns);
  Neuron_Structure* ns2=
      Neuron_Structure_Locseg_Chain_To_Circle(ns);

  Neuron_Structure_To_Tree(ns2);

  Graph_To_Dot_File(ns2->graph, "../data/test.dot");

  Swc_Tree *tree = 
    Neuron_Structure_To_Swc_Tree_Circle_Z(ns2, 1.0, NULL);

  Swc_Tree_Remove_Zigzag(tree);
  //Swc_Tree_Tune_Fork(tree);

  //Print_Swc_Tree(tree);
  Write_Swc_Tree("../data/test.swc", tree);
#endif

#if 0
  Graph *graph = Neuron_Structure_Import_Xml_Graph("../data/mouse_single_org/trueconn2.xml");
  Graph_Normalize_Edge(graph);
  Graph_Remove_Duplicated_Edge(graph);

  Graph *graph2 = Neuron_Structure_Import_Xml_Graph("../data/mouse_single_org/conn.xml");
  Graph_Normalize_Edge(graph2);
  Graph_Remove_Duplicated_Edge(graph2);

  Graph_Workspace *gw = New_Graph_Workspace();
  int n = Graph_Edge_Count(graph, graph2->edges, graph2->nedge, gw);

  printf("fp: %d\n", graph2->nedge - n);
  printf("tp: %d\n", n);
  printf("fn: %d\n", graph->nedge - n);

  double p = (double) n / graph2->nedge;
  double r = (double) n / graph->nedge;
  printf("precision: %g\n", p);
  printf("recall: %g\n", r);
  printf("F-measure: %g\n", 2.0 * (p * r) / (p + r));
#endif

#if 0
  Neuron_Structure *ns = Make_Neuron_Structure(2);
  
  Local_Neuroseg *locseg = New_Local_Neuroseg();

  Locseg_Chain *chain1 = New_Locseg_Chain();
  Locseg_Chain_Add(chain1, locseg, NULL, DL_TAIL);

  Set_Neuron_Component(ns->comp, NEUROCOMP_TYPE_LOCSEG_CHAIN, chain1);

  Locseg_Chain *chain2 = New_Locseg_Chain();
  locseg = New_Local_Neuroseg();
  double bottom[3] = {10, 10, 5};
  double top[3] = {5, 5, 5};
  Local_Neuroseg_Set_Bottom_Top(locseg, bottom, top);
  Locseg_Chain_Add(chain2, locseg, NULL, DL_TAIL);

  Set_Neuron_Component(ns->comp + 1, NEUROCOMP_TYPE_LOCSEG_CHAIN, chain2);
  
  Neurocomp_Conn *conn = New_Neurocomp_Conn();
  Connection_Test_Workspace *ctw = New_Connection_Test_Workspace();
  Locseg_Chain_Connection_Test(chain2, chain1, NULL, 1.0, conn, ctw);

  Neuron_Structure_Add_Conn(ns, 1, 0, conn);

  Print_Neuron_Structure(ns);

  Neuron_Structure *ns2 = 
    Neuron_Structure_Locseg_Chain_To_Circle_S(ns, 1.0, 1.0);

  Neuron_Structure_To_Swc_File(ns2, "../data/test.swc");
#endif

#if 0
  int n;
  
  Locseg_Chain **chain_array = Dir_Locseg_Chain_Nd("../data/diadem_a1_part3", 
						   "^chain.*\\.tb", &n, NULL);
  /*
  Locseg_Chain **chain_array = 
    Locseg_Chain_Import_List("../data/diadem_a1_part2/good_tube.txt", &n);
  */
  //n = 100;
  /*
  Locseg_Chain **chain_array = 
    (Locseg_Chain**) malloc(sizeof(Locseg_Chain*) * 2);
  n = 2;
  chain_array[0] = Read_Locseg_Chain("../data/diadem_a1_part2/chain58.tb");
  chain_array[1] = Read_Locseg_Chain("../data/diadem_a1_part2/chain154.tb");
  */

  Stack *stack = Read_Stack("../data/diadem_a1_part3.tif");

  Stack *mask = Make_Stack(GREY, stack->width, stack->height, stack->depth);
  Zero_Stack(mask);
  Sp_Grow_Workspace *sgw = New_Sp_Grow_Workspace();
  sgw->size = Stack_Voxel_Number(stack);
  sgw->resolution[0] = 0.0375 * 2.0;
  sgw->resolution[1] = 0.0375 * 2.0;
  sgw->resolution[2] = 0.33;
  Sp_Grow_Workspace_Set_Mask(sgw, mask->array);
  sgw->wf = Stack_Voxel_Weight_S;

  Stack_Sp_Grow_Infer_Parameter(sgw, stack);

  Neuron_Structure *ns = 
    Locseg_Chain_Sp_Grow_Reconstruct(chain_array, n, stack, 1.0, sgw);
  
  Print_Neuron_Structure(ns);
  
  Graph_To_Dot_File(ns->graph, "../data/test.dot");

  //Neuron_Structure_To_Swc_File(ns, "../data/test.swc");
  Neuron_Structure *ns2 = 
    Neuron_Structure_Locseg_Chain_To_Circle_S(ns, 1.0, 1.0);
  //double root[3] = {31, 430, 0};
  double root[3] = {1221, 449, 8.5};
  Swc_Tree *tree = Neuron_Structure_To_Swc_Tree_Circle_Z(ns2, 1.0, root);
  Swc_Tree_Clean_Root(tree);
  Swc_Tree_Resort_Id(tree);
  Write_Swc_Tree("../data/test.swc", tree);
#endif

#if 0
  int n;
  Locseg_Chain **chain_array = Dir_Locseg_Chain_Nd("../data/diadem_e1", 
						   "^chain.*\\.tb", &n, NULL);
  //n = 100;
  /*
  Locseg_Chain **chain_array = 
    (Locseg_Chain**) malloc(sizeof(Locseg_Chain*) * 2);
  n = 2;
  chain_array[0] = Read_Locseg_Chain("../data/diadem_a1_part2/chain58.tb");
  chain_array[1] = Read_Locseg_Chain("../data/diadem_a1_part2/chain154.tb");
  */

  Stack *stack = Read_Stack("../data/diadem_e1.tif");

  Stack *mask = Make_Stack(GREY, stack->width, stack->height, stack->depth);
  Zero_Stack(mask);
  Sp_Grow_Workspace *sgw = New_Sp_Grow_Workspace();
  sgw->size = Stack_Voxel_Number(stack);
  sgw->resolution[0] = 0.3296485;
  sgw->resolution[1] = 0.3296485;
  sgw->resolution[2] = 1.0;
  Sp_Grow_Workspace_Set_Mask(sgw, mask->array);
  sgw->wf = Stack_Voxel_Weight_S;

  Stack_Sp_Grow_Infer_Parameter(sgw, stack);

  Neuron_Structure *ns = 
    Locseg_Chain_Sp_Grow_Reconstruct(chain_array, n, stack, 1.0, sgw);
  
  Print_Neuron_Structure(ns);
  
  //Neuron_Structure_To_Swc_File(ns, "../data/test.swc");
  Neuron_Structure *ns2 = 
    Neuron_Structure_Locseg_Chain_To_Circle_S(ns, 1.0, 1.0);

  Graph_To_Dot_File(ns2->graph, "../data/test.dot");

  double root[3] = {31, 430, 0};
  //double root[3] = {4882, 1797, 19};
  Swc_Tree *tree = Neuron_Structure_To_Swc_Tree_Circle_Z(ns2, 1.0, root);
  //Swc_Tree_Clean_Root(tree);
  Swc_Tree_Resort_Id(tree);

  Write_Swc_Tree("../data/test2.swc", tree);
#endif

#if 0
  int n;
  Locseg_Chain **chain_array = 
    Dir_Locseg_Chain_Nd("../data/benchmark/stack_graph/fork", "^chain.*\\.tb", 
			&n, NULL);

  Stack *stack = Read_Stack("../data/benchmark/stack_graph/fork/fork.tif");
  Stack *mask = Make_Stack(GREY, stack->width, stack->height, stack->depth);
  Zero_Stack(mask);
  Sp_Grow_Workspace *sgw = New_Sp_Grow_Workspace();
  sgw->size = Stack_Voxel_Number(stack);
  Sp_Grow_Workspace_Set_Mask(sgw, mask->array);
  sgw->wf = Stack_Voxel_Weight_S;

  Stack_Sp_Grow_Infer_Parameter(sgw, stack);
  Neuron_Structure *ns = 
    Locseg_Chain_Sp_Grow_Reconstruct(chain_array, n, stack, 1.0, sgw);
  
  Neuron_Structure *ns2 = 
    Neuron_Structure_Locseg_Chain_To_Circle_S(ns, 1.0, 1.0);
  Swc_Tree *tree = Neuron_Structure_To_Swc_Tree_Circle_Z(ns2, 1.0, NULL);
  //Swc_Tree_Clean_Root(tree);
  Swc_Tree_Resort_Id(tree);
  Write_Swc_Tree("../data/test.swc", tree);
#endif

#if 0
  int n = 3;
  Locseg_Chain **chain_array = 
    (Locseg_Chain**) malloc(sizeof(Locseg_Chain) * n);
  chain_array[0] = Read_Locseg_Chain("/Users/zhaot/Work/neurolabi/data/benchmark/stack_graph/fork/chain0.tb");
  chain_array[1] = Read_Locseg_Chain("/Users/zhaot/Work/neurolabi/data/benchmark/stack_graph/fork/chain1.tb");
  chain_array[2] = New_Locseg_Chain();
  
  printf("%d\n", Locseg_Chain_Is_Empty(chain_array[2]));

  Stack *stack = Read_Stack("../data/benchmark/stack_graph/fork/fork.tif");
  Stack *mask = Make_Stack(GREY, stack->width, stack->height, stack->depth);
  Zero_Stack(mask);
  Sp_Grow_Workspace *sgw = New_Sp_Grow_Workspace();
  sgw->size = Stack_Voxel_Number(stack);
  Sp_Grow_Workspace_Set_Mask(sgw, mask->array);
  sgw->wf = Stack_Voxel_Weight_S;

  Stack_Sp_Grow_Infer_Parameter(sgw, stack);
  Neuron_Structure *ns = 
    Locseg_Chain_Sp_Grow_Reconstruct(chain_array, n, stack, 1.0, sgw);
  
  Neuron_Structure *ns2 = 
    Neuron_Structure_Locseg_Chain_To_Circle_S(ns, 1.0, 1.0);
  Swc_Tree *tree = Neuron_Structure_To_Swc_Tree_Circle_Z(ns2, 1.0, NULL);
  //Swc_Tree_Clean_Root(tree);
  Swc_Tree_Remove_Zigzag(tree);
  Swc_Tree_Resort_Id(tree);
  Write_Swc_Tree("../data/test2.swc", tree);
#endif

#if 0
  Neuron_Structure *ns = New_Neuron_Structure();
  ns->graph = New_Graph();

  Graph_Add_Edge(ns->graph, 0, 1);
  Graph_Add_Edge(ns->graph, 0, 2);
  Graph_Add_Edge(ns->graph, 2, 3);
  Graph_Add_Edge(ns->graph, 2, 4);
  Graph_Add_Edge(ns->graph, 4, 5);
  Graph_Add_Edge(ns->graph, 5, 6);
  
  ns->conn = (Neurocomp_Conn*) malloc(sizeof(Neurocomp_Conn) * ns->graph->nedge);

  ns->conn[0].info[0] = 0;
  ns->conn[0].info[1] = 0;
  ns->conn[0].cost = 0.0;
  ns->conn[0].mode = NEUROCOMP_CONN_LINK;

  ns->conn[1].info[0] = 1;
  ns->conn[1].info[1] = 1;
  ns->conn[1].cost = 0.0;
  ns->conn[1].mode = NEUROCOMP_CONN_LINK;

  ns->conn[2].info[0] = 0;
  ns->conn[2].info[1] = 0;
  ns->conn[2].cost = 0.0;
  ns->conn[2].mode = NEUROCOMP_CONN_LINK;

  ns->conn[3].info[0] = 1;
  ns->conn[3].info[1] = 0;
  ns->conn[3].cost = 1.0;
  ns->conn[3].mode = NEUROCOMP_CONN_HL;

  ns->conn[4].info[0] = 0;
  ns->conn[4].info[1] = 1;
  ns->conn[4].cost = 0.0;
  ns->conn[4].mode = NEUROCOMP_CONN_LINK;

  ns->conn[5].info[0] = 1;
  ns->conn[5].info[1] = 1;
  ns->conn[5].cost = 1.0;
  ns->conn[5].mode = NEUROCOMP_CONN_LINK;

  Neuron_Structure_Merge_Locseg_Chain(ns);
  
#endif

#if 0
  Neuron_Structure *ns = New_Neuron_Structure();
  ns->graph = New_Graph();
  ns->comp = Dir_Locseg_Chain_Nc("../data/diadem_e3", "^chain.*\\.tb", 
				 &(ns->graph->nvertex), NULL);

  Graph_Add_Edge(ns->graph, 0, 1);
  Graph_Add_Edge(ns->graph, 0, 2);
  Graph_Add_Edge(ns->graph, 2, 3);
  Graph_Add_Edge(ns->graph, 3, 4);
  Graph_Add_Edge(ns->graph, 4, 5);
  
  ns->conn = (Neurocomp_Conn*) malloc(sizeof(Neurocomp_Conn) * ns->graph->nedge);

  ns->conn[0].info[0] = 0;
  ns->conn[0].info[1] = 0;
  ns->conn[0].cost = 0.0;
  ns->conn[0].mode = NEUROCOMP_CONN_LINK;

  ns->conn[1].info[0] = 0;
  ns->conn[1].info[1] = 0;
  ns->conn[1].cost = 0.0;
  ns->conn[1].mode = NEUROCOMP_CONN_LINK;

  ns->conn[2].info[0] = 0;
  ns->conn[2].info[1] = 0;
  ns->conn[2].cost = 1.0;
  ns->conn[2].mode = NEUROCOMP_CONN_LINK;

  ns->conn[3].info[0] = 0;
  ns->conn[3].info[1] = 0;
  ns->conn[3].cost = 2.0;
  ns->conn[3].mode = NEUROCOMP_CONN_LINK;

  ns->conn[4].info[0] = 0;
  ns->conn[4].info[1] = 0;
  ns->conn[4].cost = 0.0;
  ns->conn[4].mode = NEUROCOMP_CONN_LINK;

  int i;
  for (i = 0; i < ns->graph->nvertex; i++) {
    printf("%d ", Locseg_Chain_Length(NEUROCOMP_LOCSEG_CHAIN(ns->comp+i)));
  }
  printf("\n");

  Neuron_Structure_Merge_Locseg_Chain(ns);  

  for (i = 0; i < ns->graph->nvertex; i++) {
    printf("%d ", Locseg_Chain_Length(NEUROCOMP_LOCSEG_CHAIN(ns->comp+i)));
  }
  printf("\n");

#endif

#if 0
  int n;
  Locseg_Chain **chain_array = Dir_Locseg_Chain_Nd("../data/diadem_e1", 
						   "^chain.*\\.tb", &n, NULL);
  Stack *stack = Read_Stack("../data/diadem_e1.tif");

  Stack *mask = Make_Stack(GREY, stack->width, stack->height, stack->depth);
  Zero_Stack(mask);
  Sp_Grow_Workspace *sgw = New_Sp_Grow_Workspace();
  sgw->size = Stack_Voxel_Number(stack);
  sgw->resolution[0] = 0.3296485;
  sgw->resolution[1] = 0.3296485;
  sgw->resolution[2] = 1.0;
  Sp_Grow_Workspace_Set_Mask(sgw, mask->array);
  sgw->wf = Stack_Voxel_Weight_S;

  Stack_Sp_Grow_Infer_Parameter(sgw, stack);

  Neuron_Structure *ns = 
    Locseg_Chain_Sp_Grow_Reconstruct(chain_array, n, stack, 1.0, sgw);  
  
  Neuron_Structure_Merge_Locseg_Chain(ns);
  int i;
  char filepath[100];
  for (i = 0; i < ns->graph->nvertex; i++) {
    Locseg_Chain_Regularize(NEUROCOMP_LOCSEG_CHAIN(ns->comp+i));
    if (Locseg_Chain_Is_Empty(NEUROCOMP_LOCSEG_CHAIN(ns->comp+i)) == FALSE) {
      sprintf(filepath, "../data/tmp/chain%d.tb", i);
      Write_Locseg_Chain(filepath, NEUROCOMP_LOCSEG_CHAIN(ns->comp+i));
    }
  }
#endif

#if 0
  Stack *stack = Read_Stack("../data/benchmark/fork2/fork2.tif");

  Neuron_Structure *ns = New_Neuron_Structure();
  ns->graph = New_Graph();
  ns->comp = Dir_Locseg_Chain_Nc("../data/benchmark/fork2/tubes",
				 "^chain.*\\.tb", &(ns->graph->nvertex), NULL);

  coordinate_3d_t roots[3];
  roots[0][0] = 51;
  roots[0][1] = 23;
  roots[0][2] = 60;

  roots[1][0] = 51;
  roots[1][1] = 23;
  roots[1][2] = 40;

  roots[2][0] = 25;
  roots[2][1] = 76;
  roots[2][2] = 60;

  Neuron_Structure_Break_Root(ns, roots, 3);
  Neuron_Structure_Load_Root(ns, roots, 3);

  Connection_Test_Workspace *ctw = New_Connection_Test_Workspace();
  ctw->dist_thre = 100.0;
  ctw->sp_test = FALSE;
  
  Locseg_Chain_Comp_Neurostruct_W(ns, stack, 1.0, ctw);

  Process_Neuron_Structure(ns);
  Neuron_Structure_To_Tree(ns);
  
  /*
  Neuron_Structure_Remove_Conn(ns, 0, 2);
  Neuron_Structure_Remove_Conn(ns, 2, 0);
  */

  Neuron_Structure_Remove_Negative_Conn(ns);

  Neuron_Structure* ns2= NULL;
  
  ns2 = Neuron_Structure_Locseg_Chain_To_Circle_S(ns, 1.0, 1.0);
    
  Neuron_Structure_To_Tree(ns2);
  
  Swc_Tree *tree = Neuron_Structure_To_Swc_Tree_Circle_Z(ns2, 1.0, NULL);
  
  Swc_Tree_Resort_Id(tree);

  Write_Swc_Tree("../data/test3.swc", tree);  
#endif

#if 1
  Stack *stack = NULL;

  Locseg_Chain *chain1 = Read_Locseg_Chain("../data/benchmark/diadem/diadem_e1/chain22.tb");
  Locseg_Chain *chain2 = Read_Locseg_Chain("../data/benchmark/diadem/diadem_e1/chain0.tb");

  Connection_Test_Workspace *ws = New_Connection_Test_Workspace();
  Connection_Test_Workspace_Read_Resolution(ws, "../data/diadem_e3.res");

  Neurocomp_Conn conn;
  conn.mode = NEUROCOMP_CONN_HL;
  Locseg_Chain_Connection_Test(chain1, chain2, stack, 1.0, &conn, ws);

  Print_Neurocomp_Conn(&conn);
#endif

  return 0;
}
예제 #8
0
int main(int argc, char *argv[])
{
  static char *Spec[] = {"[-root_id <int>] [<input:string>]",
    "[-a <string>] [-b <string>]", 
    "[-stitch_script] [-exclude <string>] [-tile_number <int>]",
    NULL};
  Process_Arguments(argc, argv, Spec, 1);

  int *excluded = NULL;
  int nexc = 0;
  int *excluded_pair = NULL;
  int nexcpair = 0;
  if (Is_Arg_Matched("-exclude")) {
    String_Workspace *sw = New_String_Workspace();
    FILE *fp = fopen(Get_String_Arg("-exclude"), "r");
    char *line = Read_Line(fp, sw);
    excluded = String_To_Integer_Array(line, NULL, &nexc);
    line = Read_Line(fp, sw);
    if (line != NULL) {
      excluded_pair = String_To_Integer_Array(line, NULL, &nexcpair);
      nexcpair /= 2;
    }
    Kill_String_Workspace(sw);
    fclose(fp);
  }

  int n = 0;
  Graph *graph = Make_Graph(n + 1, n, TRUE);
  char filepath1[100];
  char filepath2[100];
  int i, j;
  Stack *stack1 = NULL;
  FILE *fp = NULL;
  if (Is_Arg_Matched("-stitch_script")) {
    Cuboid_I *boxes = read_tile_array(Get_String_Arg("-a"), &n);
    for (i = 0; i < n; i++) {
      for (j = i + 1; j < n; j++) {      
	BOOL is_excluded = FALSE;
	int k;
	for (k = 0; k < nexc; k++) {
	  if ((i == excluded[k] - 1) || (j == excluded[k] - 1)) {
	    is_excluded = TRUE;
	    break;
	  }
	}
	for (k = 0; k < nexcpair; k++) {
	  if (((i == excluded_pair[k*2]) && (j == excluded_pair[k*2+1])) ||
	      ((j == excluded_pair[k*2]) && (i == excluded_pair[k*2+1]))) {
	    is_excluded = TRUE;
	    break;
	  }
	}
	/*
	if ((i != 103) && (j != 103) && (i != 115) && (j != 115) && (i != 59) &&
	    (j != 59) && !(i == 116 && j == 116)) {
	    */
	if (is_excluded == FALSE) {
	  Cuboid_I_Overlap_Volume(boxes + i, boxes + j);
	  Cuboid_I ibox;
	  Cuboid_I_Intersect(boxes + i, boxes + j, &ibox);
	  int width, height, depth;
	  Cuboid_I_Size(&ibox, &width, &height, &depth);

	  if ((imax2(width, height) > 1024 / 3) && (imin2(width, height) > 0)) {
	    sprintf(filepath1, "%s/stack/%03d.xml", 
		Get_String_Arg("input"), i + 1);
	    sprintf(filepath2, "%s/stack/%03d.xml", 
		Get_String_Arg("input"), j + 1);
	    if (stack1 == NULL) {
	      stack1 = Read_Stack_U(filepath1);
	    }
	    Stack *stack2 = Read_Stack_U(filepath2);

	    Stack *substack1= Crop_Stack(stack1, ibox.cb[0] - boxes[i].cb[0], 
		ibox.cb[1] - boxes[i].cb[1], 0,
		width, height, stack1->depth, NULL);
	    Stack *substack2 = Crop_Stack(stack2, ibox.cb[0] - boxes[j].cb[0], 
		ibox.cb[1] - boxes[j].cb[1], 0,
		width, height, stack2->depth, NULL);

	    Image *img1 = Proj_Stack_Zmax(substack1);	
	    Image *img2 = Proj_Stack_Zmax(substack2);
	    double w = u16array_corrcoef((uint16_t*) img1->array, 
		(uint16_t*) img2->array, 
		img1->width * img1->height);

	    Kill_Stack(stack2);
	    Kill_Stack(substack1);
	    Kill_Stack(substack2);
	    Kill_Image(img1);
	    Kill_Image(img2);
	    printf("%d, %d : %g\n", i + 1, j + 1, w);
	    Graph_Add_Weighted_Edge(graph, i + 1, j + 1, 1000.0 / (w + 1.0));
	  }
	}
	if (stack1 != NULL) {
	  Kill_Stack(stack1);
	  stack1 = NULL;
	}
      }
    }

    Graph_Workspace *gw = New_Graph_Workspace();
    Graph_To_Mst2(graph, gw);

    Arrayqueue q = Graph_Traverse_B(graph, Get_Int_Arg("-root_id"), gw);

    Print_Arrayqueue(&q);

    int *grown = iarray_malloc(graph->nvertex);
    for (i = 0; i < graph->nvertex; i++) {
      grown[i] = 0;
    }

    int index  = Arrayqueue_Dequeue(&q);
    grown[index] = 1;

    char stitch_p_file[5][500];
    FILE *pfp[5];
    for (i = 0; i < 5; i++) {
      sprintf(stitch_p_file[i], "%s/stitch/stitch_%d.sh", Get_String_Arg("input"), i);
      pfp[i] = fopen(stitch_p_file[i], "w");
    }

    sprintf(filepath1, "%s/stitch/stitch_all.sh", Get_String_Arg("input"));

    fp = GUARDED_FOPEN(filepath1, "w");
    fprintf(fp, "#!/bin/bash\n");

    int count = 0;
    while ((index = Arrayqueue_Dequeue(&q)) > 0) {
      for (i = 0; i < graph->nedge; i++) {
	int index2 = -1;
	if (index == graph->edges[i][0]) {
	  index2 = graph->edges[i][1];
	} else if (index == graph->edges[i][1]) {
	  index2 = graph->edges[i][0];
	}

	if (index2 > 0) {
	  if (grown[index2] == 1) {
	    char cmd[500];
	    sprintf(filepath2, "%s/stitch/%03d_%03d_pos.txt",
		Get_String_Arg("input"), index2, index);
	    sprintf(cmd, 
		"%s/stitchstack %s/stack/%03d.xml %s/stack/%03d.xml -o %s", 
		Get_String_Arg("-b"), Get_String_Arg("input"),
		index2, Get_String_Arg("input"), index, filepath2);
	    fprintf(fp, "%s\n", cmd);
	    count++;
	    fprintf(pfp[count%5], "%s\n", cmd);
	    /*
	    if (!fexist(filepath2)) {
	      system(cmd);
	    }
	    */
	    grown[index] = 1;
	    break;
	  }
	}
      }
    }

    fclose(fp);  
    for (i = 0; i < 5; i++) {
      fprintf(pfp[i], "touch %s/stitch/stitch_%d_done\n", 
	  Get_String_Arg("input"), i);
      fclose(pfp[i]);
    }
    return 0;
  }
  
  sprintf(filepath1, "%s/stitch/stitch_all.sh", Get_String_Arg("input"));
  fp = GUARDED_FOPEN(filepath1, "r");

//#define MAX_TILE_INDEX 153
  int tile_number = Get_Int_Arg("-tile_number");
  int max_tile_index = tile_number + 1;

  char *line = NULL;
  String_Workspace *sw = New_String_Workspace();
  int id[2];
  char filepath[100];
  int offset[max_tile_index][3];
  int relative_offset[max_tile_index][3];
  int array[max_tile_index];

  for (i = 0; i < max_tile_index; i++) {
    array[i] = -1;
    offset[i][0] = 0;
    offset[i][1] = 0;
    offset[i][2] = 0;
    relative_offset[i][0] = 0;
    relative_offset[i][1] = 0;
    relative_offset[i][2] = 0;
  }

  while ((line = Read_Line(fp, sw)) != NULL) {
    char *remain = strsplit(line, ' ', 1);
    if (String_Ends_With(line, "stitchstack")) {
      String_To_Integer_Array(remain, id, &n);
      id[0] = id[1];
      id[1] = id[3];
      array[id[1]] = id[0];

      sprintf(filepath, "%s/stitch/%03d_%03d_pos.txt", Get_String_Arg("input"),
	      id[0], id[1]);
      if (!fexist(filepath)) {
	fprintf(stderr, "file %s does not exist\n", filepath);
	return 1;
      }
      FILE *fp2 = GUARDED_FOPEN(filepath, "r");
      line = Read_Line(fp2, sw);
      line = Read_Line(fp2, sw);
      int tmpoffset[8];
      String_To_Integer_Array(line, tmpoffset, &n);
      relative_offset[id[1]][0] = tmpoffset[2];
      relative_offset[id[1]][1] = tmpoffset[3];
      relative_offset[id[1]][2] = tmpoffset[4];

      fclose(fp2);
    }
  }
  
  for (i = 1; i < max_tile_index; i++) {
    BOOL is_excluded = FALSE;
    int k;
    for (k = 0; k < nexc; k++) {
      if (i == excluded[k]) {
	is_excluded = TRUE;
	break;
      }
    }
    /*if ((i == 104) || (i == 116) || (i == 60) || (i == 152)) {*/
    if (is_excluded) {
      printf("%d: (0, 0, 10000)\n", i);
    } else {
      int index = i;
      while (index >= 0) {
	offset[i][0] += relative_offset[index][0];
	offset[i][1] += relative_offset[index][1];
	offset[i][2] += relative_offset[index][2];
	index = array[index];
      }
      printf("%d: (%d, %d, %d)\n", i, offset[i][0], offset[i][1], offset[i][2]);
    }
  }

  fclose(fp);

  return 0;
}