public SySal.Imaging.Grain3D[] MakeGrainsFromClusters(SySal.Imaging.Cluster3D[][] cls, SySal.BasicTypes.Vector[] positions) { this.DemagCoefficients = new double[0]; this.MatchDX = new double[0]; this.MatchDY = new double[0]; System.Collections.ArrayList adx = new System.Collections.ArrayList(); System.Collections.ArrayList ady = new System.Collections.ArrayList(); int i; int halfw = (int)(C.ImageWidth / 2); int halfh = (int)(C.ImageHeight / 2); ChainCluster[][] planes = new ChainCluster[positions.Length][]; System.Collections.ArrayList demags = new System.Collections.ArrayList(); int plane; double c2x, c2y; double px0 = positions[0].X; double py0 = positions[0].Y; double pz0 = positions[0].Z; for (plane = 0; plane < planes.Length; plane++) { if (Progress != null) { Progress((double)plane / (double)planes.Length * 0.5); } if (ShouldStop != null && ShouldStop()) { return(null); } planes[plane] = new ChainCluster[cls[plane].Length]; SySal.Imaging.Cluster3D [] cplanes = cls[plane]; double px = positions[plane].X; double py = positions[plane].Y; double pz = positions[plane].Z; double pxd = px - px0; double pyd = py - py0; double pzd = pz - pz0; double dmz = OptimizeDemagCoefficient ? 1 : Math.Pow(1.0 + C.DMagDZ, pzd); for (i = 0; i < planes[plane].Length; i++) { ChainCluster cc = new ChainCluster(); cc.Cluster = cplanes[i].Cluster; cc.Id = i; cc.Plane = plane; cc.Z = pz; cc.Cluster.X = (cc.Cluster.X - halfw) * C.Pixel2Micron.X * dmz; // +px; cc.Cluster.Y = (cc.Cluster.Y - halfh) * C.Pixel2Micron.Y * dmz; // +py; c2y = cc.Cluster.X * cc.Cluster.X * C.XYCurvature * cc.Cluster.Y; c2x = cc.Cluster.Y * cc.Cluster.Y * C.XYCurvature * cc.Cluster.X; cc.Cluster.X += c2x; cc.Cluster.Y += c2y; cc.Z += C.ZCurvature * (cc.Cluster.X * cc.Cluster.X + cc.Cluster.Y * cc.Cluster.Y); cc.Cluster.X += pxd; cc.Cluster.Y += pyd; planes[plane][i] = cc; } } if (Progress != null) { Progress(0.5); } for (i = 0; i < planes.Length - 1; i++) { if (Progress != null) { Progress(0.5 + 0.5 * (double)i / (double)(planes.Length - 1)); } if (ShouldStop != null && ShouldStop()) { return(null); } SySal.Tracking.MIPEmulsionTrackInfo[] t1 = new SySal.Tracking.MIPEmulsionTrackInfo[planes[i].Length]; SySal.Tracking.MIPEmulsionTrackInfo[] t2 = new SySal.Tracking.MIPEmulsionTrackInfo[planes[i + 1].Length]; int j; for (j = 0; j < t1.Length; j++) { ChainCluster cc = planes[i][j]; SySal.Tracking.MIPEmulsionTrackInfo info = new SySal.Tracking.MIPEmulsionTrackInfo(); info.Count = (ushort)cc.Cluster.Area; info.AreaSum = (uint)j; info.Intercept.X = cc.Cluster.X; info.Intercept.Y = cc.Cluster.Y; info.Intercept.Z = 0.0; info.Slope.X = info.Slope.Y = info.Slope.Z = 0.0; t1[j] = info; } for (j = 0; j < t2.Length; j++) { ChainCluster cc = planes[i + 1][j]; SySal.Tracking.MIPEmulsionTrackInfo info = new SySal.Tracking.MIPEmulsionTrackInfo(); info.Count = (ushort)cc.Cluster.Area; info.AreaSum = (ushort)j;// cls.Id; info.Intercept.X = cc.Cluster.X + 2.0 * (C.ClusterMatchMaxOffset + C.ClusterMatchPositionTolerance); info.Intercept.Y = cc.Cluster.Y + 2.0 * (C.ClusterMatchMaxOffset + C.ClusterMatchPositionTolerance); info.Intercept.Z = 0.0; info.Slope.X = info.Slope.Y = info.Slope.Z = 0.0; t2[j] = info; } try { SySal.Processing.QuickMapping.Configuration qmc = (SySal.Processing.QuickMapping.Configuration)QM.Config; qmc.FullStatistics = false; qmc.UseAbsoluteReference = true; qmc.PosTol = C.ClusterMatchPositionTolerance * 0.5; qmc.SlopeTol = 1.0; QM.Config = qmc; int bkg = QM.Match(t1, t2, 0.0, C.ClusterMatchPositionTolerance * 0.25, C.ClusterMatchPositionTolerance * 0.25).Length; for (j = 0; j < t2.Length; j++) { ChainCluster cc = planes[i + 1][j]; t2[j].Intercept.X = cc.Cluster.X; t2[j].Intercept.Y = cc.Cluster.Y; } qmc.PosTol = C.ClusterMatchMaxOffset * 0.5; QM.Config = qmc; SySal.Scanning.PostProcessing.PatternMatching.TrackPair[] tp = QM.Match(t1, t2, 0.0, C.ClusterMatchMaxOffset * 0.25, C.ClusterMatchMaxOffset * 0.25); double deltax = 0.0, deltay = 0.0, demagx = 0.0, demagy = 0.0; double dummy = 0.0; double q = (1.0 - (double)bkg / (double)tp.Length) * 0.25; double[,] deltas = new double[tp.Length, 4]; for (j = 0; j < tp.Length; j++) { deltas[j, 0] = tp[j].Second.Info.Intercept.X; deltas[j, 1] = tp[j].Second.Info.Intercept.Y; deltas[j, 2] = tp[j].First.Info.Intercept.X - tp[j].Second.Info.Intercept.X; deltas[j, 3] = tp[j].First.Info.Intercept.Y - tp[j].Second.Info.Intercept.Y; } int[] ids = NumericalTools.Fitting.PeakDataSel(deltas, new double[] { Math.Abs(halfw * C.Pixel2Micron.X) * 0.25, Math.Abs(halfh * C.Pixel2Micron.Y) * 0.25, C.ClusterMatchPositionTolerance * 0.5, C.ClusterMatchPositionTolerance * 0.5 }, -1.0, q); double[] ws = new double[ids.Length]; double[] dws = new double[ids.Length]; for (j = 0; j < ids.Length; j++) { ws[j] = deltas[ids[j], 0]; dws[j] = deltas[ids[j], 2]; } NumericalTools.ComputationResult resx = NumericalTools.Fitting.LinearFitSE(ws, dws, ref demagx, ref deltax, ref dummy, ref dummy, ref dummy, ref dummy, ref dummy); for (j = 0; j < ids.Length; j++) { ws[j] = deltas[ids[j], 1]; dws[j] = deltas[ids[j], 3]; } double dmagdeltaz = positions[i + 1].Z - positions[i].Z; NumericalTools.ComputationResult resy = NumericalTools.Fitting.LinearFitSE(ws, dws, ref demagy, ref deltay, ref dummy, ref dummy, ref dummy, ref dummy, ref dummy); if (resx == NumericalTools.ComputationResult.OK && resy == NumericalTools.ComputationResult.OK) { demags.Add(Math.Log(1.0 + demagx) / dmagdeltaz); demags.Add(Math.Log(1.0 + demagy) / dmagdeltaz); } for (j = 0; j < t2.Length; j++) { ChainCluster cc = planes[i + 1][j]; t2[j].Intercept.X += deltax; t2[j].Intercept.Y += deltay; cc.Cluster.X += deltax; cc.Cluster.Y += deltay; } qmc.PosTol = C.ClusterMatchPositionTolerance * 0.5; QM.Config = qmc; tp = QM.Match(t1, t2, 0.0, C.ClusterMatchPositionTolerance * 0.25, C.ClusterMatchPositionTolerance * 0.25); foreach (SySal.Scanning.PostProcessing.PatternMatching.TrackPair tp1 in tp) { if (planes[i][tp1.First.Info.AreaSum].Next == null && planes[i + 1][tp1.Second.Info.AreaSum].PreviousSize == 0 && (planes[i][tp1.First.Info.AreaSum].Cluster.Area < planes[i + 1][tp1.Second.Info.AreaSum].Cluster.Area && planes[i][tp1.First.Info.AreaSum].Cluster.Area < planes[i][tp1.First.Info.AreaSum].PreviousSize) == false) { planes[i][tp1.First.Info.AreaSum].Next = planes[i + 1][tp1.Second.Info.AreaSum]; planes[i + 1][tp1.Second.Info.AreaSum].PreviousSize = planes[i][tp1.First.Info.AreaSum].Cluster.Area; adx.Add(tp1.First.Info.Intercept.X - tp1.Second.Info.Intercept.X); ady.Add(tp1.First.Info.Intercept.Y - tp1.Second.Info.Intercept.Y); } } } catch (Exception) { } } System.Collections.ArrayList achains = new System.Collections.ArrayList(); System.Collections.ArrayList grains = new System.Collections.ArrayList(); foreach (ChainCluster[] cplane in planes) { foreach (ChainCluster cc in cplane) { if (cc.Next != null) { cc.Next.Id = -1; } if (cc.Id >= 0) { achains.Add(cc); } } } foreach (ChainCluster cc in achains) { int totalc = 1; ChainCluster cc1 = cc.Next; while (cc1 != null) { cc1 = cc1.Next; totalc++; } SySal.Imaging.Cluster3D[] cl3d = new SySal.Imaging.Cluster3D[totalc]; totalc = 0; cc1 = cc; uint gvolume = 0; while (cc1 != null) { double dmz = OptimizeDemagCoefficient ? 1 : Math.Pow(1.0 + C.DMagDZ, positions[cc1.Plane].Z - positions[0].Z); cl3d[totalc].Cluster = cc1.Cluster; cl3d[totalc].Cluster.X = cl3d[totalc].Cluster.X / dmz + positions[0].X; cl3d[totalc].Cluster.Y = cl3d[totalc].Cluster.Y / dmz + positions[0].Y; cl3d[totalc].Layer = (uint)cc1.Plane; cl3d[totalc].Z = cc1.Z; gvolume += cc1.Cluster.Area; cc1 = cc1.Next; totalc++; } if (gvolume < C.MinGrainVolume) { continue; } grains.Add(SySal.Imaging.Grain3D.FromClusterCenters(cl3d)); } this.DemagCoefficients = (double[])demags.ToArray(typeof(double)); this.MatchDX = (double[])adx.ToArray(typeof(double)); this.MatchDY = (double[])ady.ToArray(typeof(double)); if (Progress != null) { Progress(1.0); } return((SySal.Imaging.Grain3D[])grains.ToArray(typeof(SySal.Imaging.Grain3D))); }
private static NumericalTools.ComputationResult IteratedAffineFocusing(double[] DX, double[] DY, double[] X, double[] Y, double[] SX, double[] SY, double postol, ref double[] alignpars) { int iteration, i, j; double xtol = postol; double ytol = postol; NumericalTools.ComputationResult res = NumericalTools.ComputationResult.SingularityEncountered; for (iteration = 0; iteration < 3; iteration++) { double[] mDX; double[] mDY; double[] mSX; double[] mSY; double[] mX; double[] mY; if (iteration == 0) { mDX = DX; mDY = DY; mSX = SX; mSY = SY; mX = X; mY = Y; } else { double dx, dx2sum, dy, dy2sum; dx2sum = dy2sum = 0.0; bool[] take = new bool[DX.Length]; for (i = j = 0; i < take.Length; i++) { if (Math.Abs(dx = (DX[i] - alignpars[0] * X[i] - alignpars[1] * Y[i] - alignpars[4] - alignpars[6] * SX[i])) < xtol && Math.Abs(dy = (DY[i] - alignpars[2] * X[i] - alignpars[3] * Y[i] - alignpars[5] - alignpars[6] * SY[i])) < ytol) { dx2sum += dx * dx; dy2sum += dy * dy; take[i] = true; j++; } } if (j < 2) { return(NumericalTools.ComputationResult.SingularityEncountered); } xtol = 2.0 * Math.Sqrt(dx2sum / (j - 1)); ytol = 2.0 * Math.Sqrt(dy2sum / (j - 1)); mDX = new double[j]; mDY = new double[j]; mSX = new double[j]; mSY = new double[j]; mX = new double[j]; mY = new double[j]; for (i = j = 0; i < take.Length; i++) { if (take[i]) { mDX[j] = DX[i]; mDY[j] = DY[i]; mSX[j] = SX[i]; mSY[j] = SY[i]; mX[j] = X[i]; mY[j] = Y[i]; j++; } } } res = NumericalTools.Fitting.Affine_Focusing(mDX, mDY, mX, mY, mSX, mSY, ref alignpars); } return(res); }