private static void HardThresh(List<List<double>> tree, double sigma, bool isGermline)
{
int treeSize = tree.Count();
List<double> thresholds = new List<double>();
int[] indices = new int[treeSize];
// makes threshold depend on the complexity of wavelet basis functions
if (isGermline)
{
int[] counts = new int[treeSize];
for (int nodeIndex = 0; nodeIndex < treeSize; nodeIndex++)
{
counts[nodeIndex] = (int)Math.Floor(tree[nodeIndex].Count() / 5.0);
indices[nodeIndex] = nodeIndex;
}
// transform number of segments at each wavelet scale into NewMin-NewMax range, use it to weight threshold function
Array.Sort<int>(indices, (a, b) => counts[b].CompareTo(counts[a]));
double NewMax = 1.0;
double NewMin = 0.8;
thresholds = Enumerable.Range(1, treeSize).Select(x => ((double)x * (NewMax - NewMin)) / treeSize + NewMin).ToList();
}
else
{
for (int nodeIndex = 0; nodeIndex < treeSize; nodeIndex++)
{
thresholds.Add(1.0);
indices[nodeIndex] = nodeIndex;
}
}
int subtreeSize = 5;
double n = tree[0][subtreeSize - 1];
for (int nodeIndex = 0; nodeIndex < treeSize; nodeIndex++)
{
int K = (int)Math.Floor(tree[nodeIndex].Count() / 5.0);
for (int k = 0; k < K; k++)
{
// threshold 2x*sigma for TN and ranges from 0.5x to 1.5x *sigma for Germline
// parameters trained on CanvasRegression datasets
if (Math.Abs(tree[nodeIndex][k * subtreeSize + 2 - 1]) <= sigma * (thresholds[indices[nodeIndex]]) * Math.Sqrt(2 * Math.Log(n)))
{
tree[nodeIndex][k * subtreeSize + 2 - 1] = 0;
}
}
}
}