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 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()); }