private void OutputSubDendrite() { DendriteIO io = new DendriteIO(); string rawFilename = Path.GetFileNameWithoutExtension(param.ofname); string dirname = Path.Combine(Path.GetDirectoryName(param.ofname), rawFilename + "-sub"); if (Directory.Exists(dirname)) { Directory.Delete(dirname, true); } Directory.CreateDirectory(dirname); // 出力するファイル名の末尾の桁数 // ファイル名は0オリジンにするので .Count - 1 にしている int digit = (NotMergedSubDendritesIdx.Count - 1).ToString().Length; // 出力するファイル名の末尾のID int sub_dendrite_id = 0; // 独立して存在している(他のノードに併合されていない)側枝ノードを、体積降順で並べ替える var orderByVolume = NotMergedSubDendritesIdx.OrderByDescending(x => sub_dendrites_volume[x]); foreach (int sub_index in orderByVolume) { Dendrite sdendrite = sub_dendrites[sub_index]; IList <DendriteNode> edge = sdendrite.GetEdgeNodes(); sdendrite.ChangeRootNode(edge[0]); string filename = CreateFileNameForSubDendriteIO(dirname, digit, sub_dendrite_id); string path = Path.Combine(dirname, filename); io.SaveToSWC(path, sdendrite); sub_dendrite_id++; if (param.outputVTK) { string vtkFilename = Path.ChangeExtension(filename, "vtk"); string vtkPath = Path.Combine(dirname, vtkFilename); VtkWriter.SaveToVTKLegacy(vtkPath, sdendrite); } } }
public void RelateSwcNode(Dendrite swc) { // addNodeToList(main_dendrite.root, null); の直前で-1を設定したかったけど // unassigned local variableで怒られた(´・ω・`) int currentSubDendriteIndex = -1; var nodeListImg = new List <DendriteNode>(); var node2subindex = new Dictionary <DendriteNode, int>(); Action <DendriteNode, DendriteNode> addNodeToList = null; addNodeToList = (node, parent) => { nodeListImg.Add(node); node2subindex.Add(node, currentSubDendriteIndex); foreach (var next in node.ConnectedNodes) { if (next == parent) { continue; } addNodeToList(next, node); } }; addNodeToList(main_dendrite.root, null); for (int i = 0; i < sub_dendrites.Count; i++) { currentSubDendriteIndex = i; addNodeToList(sub_dendrites[i].root, null); } foreach (var node in nodeListImg) { node.isConnected = false; } var img2swc = new Dictionary <DendriteNode, DendriteNode>(); var que = new Queue <DendriteNode>(); var removeCandidate = new HashSet <int>(); Action <DendriteNode, DendriteNode> mapping = null; mapping = (node, parent) => { Debug.Assert(nodeListImg.Count > 0); var pair = nodeListImg.First(); foreach (var item in nodeListImg) { if (node.EuclideanDistanceTo(item) < node.EuclideanDistanceTo(pair)) { pair = item; } } pair.isConnected = true; img2swc[pair] = node; que.Enqueue(pair); Debug.Assert(node2subindex.ContainsKey(pair)); if (node2subindex[pair] != -1) { removeCandidate.Add(node2subindex[pair]); } foreach (var next in node.ConnectedNodes) { if (next == parent) { continue; } mapping(next, node); } }; mapping(swc.root, null); while (que.Count > 0) { var node = que.Dequeue(); foreach (var next in node.ConnectedNodes) { if (next.isConnected) { continue; } next.isConnected = true; var newNode = new DendriteNode(-1, next.gx, next.gy, next.gz, next.Radius, -1); Debug.Assert(img2swc.ContainsKey(node)); img2swc[node].AddConnectedNode(newNode); newNode.AddConnectedNode(img2swc[node]); que.Enqueue(next); img2swc[next] = newNode; } } swc.ChangeRootNode(swc.root); main_dendrite = swc; int offset = 0; foreach (var item in removeCandidate.ToList().OrderBy(x => x)) { sub_dendrites.RemoveAt(item + offset); sub_dendrites_volume.RemoveAt(item + offset); offset--; } }
public void ConnectSubDendritesToOtherSubDendrites() { var nodelist = new Dictionary <int, List <DendriteNode> >(); foreach (int index in NotMergedSubDendritesIdx) { List <DendriteNode> node = sub_dendrites[index].GetEdgeNodeAndBranchNodes(); nodelist.Add(index, node); } DendriteNode masterNode = null; DendriteNode slaveNode = null; var cache = new Dictionary <Tuple2, NodeIndexer>(); while (true) { // masterとslaveの距離をあらかじめ計算しておいて配列に保存し、ソートしておくことで // 高速に計算できるが、需要がないようなので後回しにする。 // 配列に保存するのは距離がdistanceThreashold以下のものだけにしないとメモリが足りないと思います。 // Masterがどこかのノードに吸収されるかもしれないので、 // UnionFind木で管理しておきましょう int masterIndex = 0; int slaveIndex = 0; double min = Double.MaxValue; foreach (int master in NotMergedSubDendritesIdx) { for (int master2 = 0; master2 < nodelist[master].Count; master2++) { var dictKey = new Tuple2(master, master2); if (cache.ContainsKey(dictKey) == false || nodelist[cache[dictKey].ClusterIdx].Count == 0) { foreach (int slave in NotMergedSubDendritesIdx) { if (master == slave) { continue; } for (int slave2 = 0; slave2 < nodelist[slave].Count; slave2++) { double tmpdist = nodelist[master][master2].EuclideanDistanceTo(nodelist[slave][slave2]); // キャッシュがなかった場合は新しく追加 if (cache.ContainsKey(dictKey) == false) { cache.Add(dictKey, new NodeIndexer(tmpdist, slave, slave2)); } // キャッシュしていたノードが他のノードに併合されたパターン else if (nodelist[cache[dictKey].ClusterIdx].Count == 0) { cache[dictKey] = new NodeIndexer(tmpdist, slave, slave2); } // 再探索時に、キャッシュしていたノードよりも近いノードを見つけた場合には、キャッシュしている値を変更する else if (cache[dictKey].Norm >= tmpdist) { cache[dictKey] = new NodeIndexer(tmpdist, slave, slave2); } if (min >= tmpdist) { min = tmpdist; masterNode = nodelist[slave][slave2]; slaveNode = nodelist[master][master2]; masterIndex = master; slaveIndex = slave; } } } } // キャッシュが存在した場合はそれを利用 else { NodeIndexer nodeIndex = cache[dictKey]; double tmpdist = nodeIndex.Norm; int slave = nodeIndex.ClusterIdx; int slave2 = nodeIndex.NodeIdx; if (min >= tmpdist) { min = tmpdist; masterNode = nodelist[slave][slave2]; slaveNode = nodelist[master][master2]; masterIndex = master; slaveIndex = slave; } } } } if (min <= param.distanceThreshold) { //連結ノードにお互いを追加 masterNode.AddConnectedNode(slaveNode); slaveNode.AddConnectedNode(masterNode); //連結したサブノードリストはメインノードリストに吸収 nodelist[masterIndex].AddRange(nodelist[slaveIndex]); //サブを消去 nodelist[slaveIndex].Clear(); // マージされた NotMergedSubDendritesIdx.Remove(slaveIndex); sub_dendrites_volume[masterIndex] += sub_dendrites_volume[slaveIndex]; sub_dendrites_volume[slaveIndex] = 0; } else { break; } } foreach (int index in NotMergedSubDendritesIdx) { if (nodelist[index].Count > 0) { Dendrite node = sub_dendrites[index]; var edge = node.GetEdgeNodes(); node.ChangeRootNode(edge.Last()); } } }
/// <summary> /// SubDendriteを距離閾値に従ってMainDendriteに接続 /// </summary> public void ConnectSubDendritesToMainDendrite() { // nodelist[0] : main // nodelist[1:] : sub List <List <DendriteNode> > nodelist = new List <List <DendriteNode> >(); //メインクラスタの分岐,端点ノードを取得 List <DendriteNode> pnode = main_dendrite.GetEdgeNodeAndBranchNodes(); nodelist.Add(pnode); NotMergedSubDendritesIdx = new HashSet <int>(); for (int i = 0; i < sub_dendrites.Count; i++) { //サブクラスタの分岐,端点ノードを取得 List <DendriteNode> node = sub_dendrites[i].GetEdgeNodeAndBranchNodes(); nodelist.Add(node); NotMergedSubDendritesIdx.Add(i); } var Q = new SkewHeap <NodeRelation>(); for (int i = 0; i < nodelist[0].Count; i++) { for (int j = 1; j < nodelist.Count; j++) { double normMin = double.MaxValue; int argMin = -1; for (int k = 0; k < nodelist[j].Count; k++) { double d = nodelist[0][i].EuclideanDistanceTo(nodelist[j][k]); if (d <= normMin) { normMin = d; argMin = k; } } if (argMin != -1 && normMin <= param.distanceThreshold) { Q.Push(new NodeRelation(normMin, i, j, argMin)); } } } while (true) { NodeRelation rel = null; while (Q.Empty() == false) { rel = Q.Pop(); if (nodelist[rel.SlaveClusterIdx].Count > 0) { break; } } if (Q.Empty()) { break; } DendriteNode parent = nodelist[0][rel.MasterNodeIdx]; DendriteNode cand = nodelist[rel.SlaveClusterIdx][rel.SlaveNodeIdx]; //連結ノードにお互いを追加 cand.AddConnectedNode(parent); parent.AddConnectedNode(cand); int mainNodeSizePrev = nodelist[0].Count; //連結したサブノードリストはメインノードリストに吸収 nodelist[0].AddRange(nodelist[rel.SlaveClusterIdx]); //サブを消去 nodelist[rel.SlaveClusterIdx].Clear(); // マージされた NotMergedSubDendritesIdx.Remove(rel.SlaveClusterIdx - 1); // 吸収されたサブノードから、吸収されていないサブノードまでの距離を算出 for (int i = mainNodeSizePrev; i < nodelist[0].Count; i++) { for (int j = 1; j < nodelist.Count; j++) { double normMin = double.MaxValue; int argMin = -1; for (int k = 0; k < nodelist[j].Count; k++) { double d = nodelist[0][i].EuclideanDistanceTo(nodelist[j][k]); if (d <= normMin) { normMin = d; argMin = k; } } if (argMin != -1 && normMin <= param.distanceThreshold) { Q.Push(new NodeRelation(normMin, i, j, argMin)); } } } } main_dendrite.ChangeRootNode(main_dendrite.root); pnode = main_dendrite.GetEdgeNodes(); // どうしてFirstでなくてLastなのかよく分からない main_dendrite.ChangeRootNode(pnode.Last()); }