ZVoxelArray ZSpGrowParser::extractPath(ssize_t index) { ZVoxelArray path; int width = m_workspace->width; int height = m_workspace->height; if (m_workspace != NULL) { while (index >= 0) { ZVoxel voxel; voxel.setFromIndex(index, width, height); path.append(voxel); if (m_pathMask != NULL) { if (m_pathMask->array[index] == 1) { break; } } assert(index != m_workspace->path[index]); index = m_workspace->path[index]; } } return path; }
Swc_Tree* ZNeuronTracer::trace(double x1, double y1, double z1, double r1, double x2, double y2, double z2, double r2) { if (x1 < 0 || y1 < 0 || z1 < 0 || x1 >= C_Stack::width(m_stack) || y1 >= C_Stack::height(m_stack) || z1 >= C_Stack::depth(m_stack)) { return NULL; } if (ZPoint(x1, y1, z1).distanceTo(x2, y2, z2) > MAX_P2P_TRACE_DISTANCE) { return NULL; } /* int start[3]; int end[3]; start[0] = iround(x1); start[1] = iround(y1); start[2] = iround(z1); end[0] = iround(x2); end[1] = iround(y2); end[2] = iround(z2); */ ZStackGraph stackGraph; stackGraph.setResolution(m_resolution); if (m_backgroundType == NeuTube::IMAGE_BACKGROUND_BRIGHT) { stackGraph.setWeightFunction(Stack_Voxel_Weight); } else { stackGraph.setWeightFunction(Stack_Voxel_Weight_S); } stackGraph.inferWeightParameter(m_stack); int startIndex = C_Stack::indexFromCoord(x1, y1, z1, C_Stack::width(m_stack), C_Stack::height(m_stack), C_Stack::depth(m_stack)); int endIndex = C_Stack::indexFromCoord(x2, y2, z2, C_Stack::width(m_stack), C_Stack::height(m_stack), C_Stack::depth(m_stack)); std::vector<int> path = stackGraph.computeShortestPath(m_stack, startIndex, endIndex); ZVoxelArray voxelArray; for (size_t i = path.size(); i > 0; --i) { int x, y, z; C_Stack::indexToCoord(path[i - 1], C_Stack::width(m_stack), C_Stack::height(m_stack), &x, &y, &z); voxelArray.append(ZVoxel(x, y, z)); } double length = voxelArray.getCurveLength(); double dist = 0.0; for (size_t i = 0; i < path.size(); ++i) { double ratio = dist / length; double r = r1 * ratio + r2 * (1 - ratio); voxelArray.setValue(i, r); if (i < path.size() - 1) { dist += voxelArray[i].distanceTo(voxelArray[i+1]); } } return voxelArray.toSwcTree(); }
vector<ZVoxelArray> ZSpGrowParser::extractAllPath(double lengthThreshold, Stack *ballStack) { bool isPathAvailable = true; const double maskExpansionRadius = 2.0; const double skeletonRadius = 3.0; //Calibrate lengthThreshold -= maskExpansionRadius; vector<ZVoxelArray> pathArray; //While any long path is available while (isPathAvailable) { //Extract the longest path double length = 0.0; ZVoxelArray path = extractLongestPath(&length); cout << "Path length: " << length << endl; cout << "Path size: " << path.size() << endl; if (path.size() == 1) { cout << "Debug here." << endl; } if (length < lengthThreshold) { isPathAvailable = false; } else { pathArray.push_back(path); //Update checkedMask if (m_checkedMask == NULL) { m_checkedMask = Make_Stack(GREY, m_workspace->width, m_workspace->height, m_workspace->depth); Zero_Stack(m_checkedMask); } if (m_pathMask == NULL) { m_pathMask = Make_Stack(GREY, m_workspace->width, m_workspace->height, m_workspace->depth); Zero_Stack(m_pathMask); } if (ballStack != NULL) { //Extract distance field values path.sample(ballStack, DistanceWeight); path.addValue(1.0); path.minimizeValue(skeletonRadius); } else { path.addValue(skeletonRadius); } path.labelStackWithBall(m_pathMask, 1); //Label skeletons with a certain width if (ballStack != NULL) { path.sample(ballStack, DistanceWeight); path.addValue(maskExpansionRadius); } path.labelStackWithBall(m_checkedMask, 1); //Label mask } } return pathArray; }
Swc_Tree* ZNeuronTracer::trace(double x1, double y1, double z1, double r1, double x2, double y2, double z2, double r2) { setTraceScoreThreshold(TRACING_INTERACTIVE); ZIntPoint stackOffset = getStack()->getOffset(); ZPoint targetPos(x2, y2, z2); x1 = iround(x1); y1 = iround(y1); z1 = iround(z1); x2 = iround(x2); y2 = iround(y2); z2 = iround(z2); x1 -= stackOffset.getX(); y1 -= stackOffset.getY(); z1 -= stackOffset.getZ(); x2 -= stackOffset.getX(); y2 -= stackOffset.getY(); z2 -= stackOffset.getZ(); if (x1 < 0 || y1 < 0 || z1 < 0 || x1 >= getStack()->width() || y1 >= getStack()->height() || z1 >= getStack()->depth()) { return NULL; } ZStackGraph stackGraph; if (m_resolution[2] / m_resolution[0] > 3.0) { stackGraph.setZMargin(2); } stackGraph.updateRange( x1, y1, z1, x2, y2, z2, getStack()->width(), getStack()->height(), getStack()->depth()); if (stackGraph.getRoiVolume() > MAX_P2P_TRACE_VOLUME) { return NULL; } stackGraph.setResolution(m_resolution); if (m_vertexOption == ZStackGraph::VO_SURFACE) { stackGraph.setWeightFunction(Stack_Voxel_Weight_I); } else { if (m_usingEdgePath) { stackGraph.setWeightFunction(Stack_Voxel_Weight_S); } else { if (m_backgroundType == NeuTube::IMAGE_BACKGROUND_BRIGHT) { stackGraph.setWeightFunction(Stack_Voxel_Weight_Sr); } else { stackGraph.setWeightFunction(Stack_Voxel_Weight_S); } } } ZIntCuboid box = stackGraph.getRange(); // if (m_usingEdgePath) { // box.setFirstCorner(imin2(x1, x2), imin2(y1, y2), imin2(z1, z2)); // box.setLastCorner(imax2(x1, x2), imax2(y1, y2), imax2(z1, z2)); // } Stack *partial = C_Stack::crop( getIntensityData(), box.getFirstCorner().getX(), box.getFirstCorner().getY(), box.getFirstCorner().getZ(), box.getWidth(), box.getHeight(), box.getDepth(), NULL); /* if (m_bcAdjust) { Stack_Scale(partial, 0, m_greyFactor, m_greyOffset); } */ if (m_usingEdgePath) { Stack *partialEdge = C_Stack::computeGradient(partial); C_Stack::kill(partial); partial = partialEdge; #ifdef _DEBUG_2 C_Stack::write(GET_TEST_DATA_DIR + "/test.tif", partial); #endif } stackGraph.inferWeightParameter(partial); ZVoxelArray voxelArray; std::vector<int> path; if (m_usingEdgePath) { int x0 = box.getFirstCorner().getX(); int y0 = box.getFirstCorner().getY(); int z0 = box.getFirstCorner().getZ(); int startIndex = C_Stack::indexFromCoord( x1 - x0, y1 - y0 , z1 - z0, C_Stack::width(partial), C_Stack::height(partial), C_Stack::depth(partial)); int endIndex = C_Stack::indexFromCoord( x2 - x0, y2 - y0, z2 - z0, C_Stack::width(partial), C_Stack::height(partial), C_Stack::depth(partial)); stackGraph.setRange(0, 0, 0, C_Stack::width(partial) - 1, C_Stack::height(partial) - 1, C_Stack::depth(partial) - 1); path = stackGraph.computeShortestPath( partial, startIndex, endIndex, m_vertexOption); for (size_t i = path.size(); i > 0; --i) { int x, y, z; C_Stack::indexToCoord(path[i - 1], C_Stack::width(partial), C_Stack::height(partial), &x, &y, &z); voxelArray.append(ZVoxel(x + x0, y + y0, z + z0)); } } else { int width = getStack()->width(); int height = getStack()->height(); int depth = getStack()->depth(); int startIndex = C_Stack::indexFromCoord( x1, y1, z1, width, height, depth); int endIndex = C_Stack::indexFromCoord( x2, y2, z2, width, height, depth); path = stackGraph.computeShortestPath( getIntensityData(), startIndex, endIndex, m_vertexOption); // C_Stack::kill(stackField); for (size_t i = path.size(); i > 0; --i) { int x, y, z; C_Stack::indexToCoord(path[i - 1], width, height, &x, &y, &z); voxelArray.append(ZVoxel(x, y, z)); } } C_Stack::kill(partial); double length = voxelArray.getCurveLength(); double dist = 0.0; const std::vector<ZVoxel> &voxelData = voxelArray.getInternalData(); for (size_t i = 0; i < path.size(); ++i) { double ratio = dist / length; double r = r1 * ratio + r2 * (1 - ratio); voxelArray.setValue(i, r); if (i < path.size() - 1) { dist += voxelData[i].distanceTo(voxelData[i+1]); } } Swc_Tree *tree = voxelArray.toSwcTree(); if (tree != NULL) { Swc_Tree_Translate( tree, stackOffset.getX(), stackOffset.getY(), stackOffset.getZ()); ZSwcSignalFitter fitter; fitter.setBackground(m_backgroundType); fitter.setFixingTerminal(true); fitter.fitSignal(tree, getStack(), getSignalChannel()); Swc_Tree_Node *leaf = tree->root; while (SwcTreeNode::firstChild(leaf) != NULL) { leaf = SwcTreeNode::firstChild(leaf); } SwcTreeNode::setPos(leaf, targetPos); } return tree; }