void PreCalculate() { if (dataset == null) return; // Extract the relevant data table. var bs = dataset.BodyList; INumberTable nt = dataset.GetNumberTableView(); toIdx = Enumerable.Range(0, bs.Count).Where(i => !bs[i].Disabled).ToArray(); // Indexes of enabled bodies. int N = nt.Rows - pcaSamples; int[] enabledRows = toIdx.Where(i => i < N).ToArray(); if (enabledRows.Length == 0) throw new TException("No data available!"); P = new float[enabledRows.Length][]; MT.Loop(0, P.Length, row => { float[] R = P[row] = new float[nt.Columns]; double[] dsR = nt.Matrix[enabledRows[row]] as double[]; for (int col = 0; col < nt.Columns; col++) R[col] = (float)dsR[col]; }); // Reverse toIdx; int[] rIdx = Enumerable.Repeat(-1, bs.Count).ToArray(); for (int i = 0; i < toIdx.Length; i++) rIdx[toIdx[i]] = i; toIdx = rIdx; using (var gpu = new VisuMap.DxShader.GpuDevice()) dtP = DualAffinity.DotProduct(gpu, P, false); float[] singValues = new float[pcaMax]; float[][] PC = FastPca.DoFastReduction(P, pcaMax, singValues, true); P = VisuMap.MathUtil.NewMatrix<float>(PC.Length, pcaSamples); // P now links data points with the injected points on the main PCA axis. float span = 4.0f * singValues[0]; stepSize = span / (pcaSamples - 1); float x0 = - 0.5f * span; MT.ForEach(PC, (R, row) => { double yy = R.Skip(1).Sum(v => v * v); for (int col = 0; col < pcaSamples; col++) { double x = R[0] - (x0 + col * stepSize); P[row][col] = (float)Math.Sqrt(x * x + yy); } }); }
void PreCalculate() { if (dataset != null) { var bs = dataset.BodyList; INumberTable nt = dataset.GetNumberTableView(); int nrows = nt.Rows - nt.Columns; toIdx = Enumerable.Range(0, bs.Count).Where(i => !bs[i].Disabled).ToArray(); // Indexes of enabled bodies. int[] selectedRows = toIdx.Where(i => i < nrows).ToArray(); int[] selectedColumns = toIdx.Where(i => i >= nrows).Select(i => i - nrows).ToArray(); if ((selectedColumns.Length == 0) || (selectedRows.Length == 0)) { throw new TException("No-zero number of genes and cells must be selected!"); } P = new float[selectedRows.Length][]; MT.Loop(0, P.Length, row => { float[] R = P[row] = new float[selectedColumns.Length]; double[] dsR = nt.Matrix[selectedRows[row]] as double[]; for (int col = 0; col < selectedColumns.Length; col++) { R[col] = (float)dsR[selectedColumns[col]]; } }); // Reverse toIdx; int[] rIdx = Enumerable.Repeat(-1, bs.Count).ToArray(); for (int i = 0; i < toIdx.Length; i++) { rIdx[toIdx[i]] = i; } toIdx = rIdx; } float[][] Q = Transpose(P); // Q is the transpose of P. // Calculate the distance tables for P and Q. bool isPCor = (metricMode == MetricMode.CorCor) || (metricMode == MetricMode.CorEuc); bool isQCor = (metricMode == MetricMode.CorCor) || (metricMode == MetricMode.EucCor); if (isPCor) { Normalize(P); } if (isQCor) { Normalize(Q); } using (var gpu = new VisuMap.DxShader.GpuDevice()) using (var cc = gpu.CreateConstantBuffer <ShaderConstant>(0)) using (var sd = gpu.LoadShader("SingleCellAnalysis.DotProduct.cso", Assembly.GetExecutingAssembly())) { dtP = CallShadere(gpu, cc, sd, P, isPCor); dtQ = CallShadere(gpu, cc, sd, Q, isQCor); } /* * affinity-propagation enhances structure if colums or rows within clusters are * light occupied with high randomness. AP however dilutes clusters with few members. * For instance, singlton gene cluster (with only gene) will suppressed by AP due to * its aggregation with neighboring genes (which should be consdiered as separate * clusters.) * * ProbagateAffinity(dtQ, P); // Column<->Column affinity => Column->Row affinity * ProbagateAffinity(dtP, Q); // Row<->Row affinity => Row->Column affinity. */ // Calculates the distance between rows and columns into P. P = AffinityToDistance(P, Q); Q = null; var app = SingleCellPlugin.App.ScriptApp; double linkBias = app.GetPropertyAsDouble("SingleCell.Separation", 1.0); double pScale = app.GetPropertyAsDouble("SingleCell.CellScale", 1.0); double qScale = app.GetPropertyAsDouble("SingleCell.GeneScale", 1.0); //PowerMatrix(P, linkBias); // Scaling dtP, dtQ to the range of P. Func <float[][], float> aFct = AverageSqrt; double av = aFct(P); pScale *= av / aFct(dtP); qScale *= av / aFct(dtQ); ScaleMatrix(dtP, pScale); ScaleMatrix(dtQ, qScale); //ScaleMatrix(P, linkBias); ShiftMatrix(P, (float)(linkBias * av)); }