/// <summary> /// Performs multiple matching. /// </summary> /// <param name="refmap">the reference map.</param> /// <param name="mmaps">the list of track maps to be merged.</param> /// <returns>the result of pattern matching with each track pattern.</returns> public MapResult[] Map(SySal.Tracking.MIPEmulsionTrackInfo[] refmap, params SySal.Tracking.MIPEmulsionTrackInfo[][] mmaps) { SySal.Processing.QuickMapping.Configuration qmc = (SySal.Processing.QuickMapping.Configuration)m_QM.Config; qmc.FullStatistics = !m_Config.FavorSpeedOverAccuracy; qmc.UseAbsoluteReference = true; qmc.PosTol = m_Config.PosTol; qmc.SlopeTol = m_Config.SlopeTol; MapResult[] mres = new MapResult[mmaps.Length]; int i; for (i = 0; i < mmaps.Length; i++) { SySal.Scanning.PostProcessing.PatternMatching.TrackPair [] pairs = m_QM.Match(refmap, mmaps[i], 0.0, m_Config.MaxPosOffset, m_Config.MaxPosOffset); mres[i].Valid = (mres[i].Matches = pairs.Length) >= m_Config.MinMatches; if (pairs.Length <= 0) { mres[i].Valid = false; continue; } SySal.BasicTypes.Vector2 dp = new SySal.BasicTypes.Vector2(); SySal.BasicTypes.Vector2 dp2 = new SySal.BasicTypes.Vector2(); SySal.BasicTypes.Vector2 ds = new SySal.BasicTypes.Vector2(); SySal.BasicTypes.Vector2 ds2 = new SySal.BasicTypes.Vector2(); double dx, dy; foreach (SySal.Scanning.PostProcessing.PatternMatching.TrackPair p in pairs) { dx = (p.First.Info.Intercept.X - p.Second.Info.Intercept.X); dy = (p.First.Info.Intercept.Y - p.Second.Info.Intercept.Y); dp.X += dx; dp.Y += dy; dp2.X += (dx * dx); dp2.Y += (dy * dy); dx = (p.First.Info.Slope.X - p.Second.Info.Slope.X); dy = (p.First.Info.Slope.Y - p.Second.Info.Slope.Y); ds.X += dx; ds.Y += dy; ds2.X += (dx * dx); ds2.Y += (dy * dy); } dp.X /= pairs.Length; dp.Y /= pairs.Length; dp2.X = Math.Sqrt(dp2.X / pairs.Length - dp.X * dp.X); dp2.Y = Math.Sqrt(dp2.Y / pairs.Length - dp.Y * dp.Y); ds.X /= pairs.Length; ds.Y /= pairs.Length; ds2.X = Math.Sqrt(ds2.X / pairs.Length - ds.X * ds.X); ds2.Y = Math.Sqrt(ds2.Y / pairs.Length - ds.Y * ds.Y); mres[i].DeltaPos = dp; mres[i].DeltaPosRMS = dp2; mres[i].DeltaSlope = ds; mres[i].DeltaSlopeRMS = ds2; } return(mres); }
/// <summary> /// Maps a pattern of tracks onto another one. /// </summary> /// <param name="refpattern">the reference pattern.</param> /// <param name="mappattern">the pattern to be mapped.</param> /// <param name="flt">the filter function for mapping.</param> /// <param name="logstrw">the output stream where logging information is written; set to <c>null</c> to disable logging.</param> /// <returns>the transformation obtained.</returns> public SySal.DAQSystem.Scanning.IntercalibrationInfo MapTransform(SySal.Tracking.MIPEmulsionTrackInfo[] refpattern, SySal.Tracking.MIPEmulsionTrackInfo[] mappattern, MapManager.dMapFilter flt, System.IO.TextWriter logstrw) { SySal.DAQSystem.Scanning.IntercalibrationInfo calinfo = new SySal.DAQSystem.Scanning.IntercalibrationInfo(); try { if (logstrw != null) { logstrw.WriteLine("Begin pattern mapping."); } calinfo.MXX = calinfo.MYY = 1.0; calinfo.MXY = calinfo.MYX = 0.0; calinfo.RX = calinfo.RY = calinfo.TX = calinfo.TY = calinfo.TZ = 0.0; int nr = refpattern.Length; int na = mappattern.Length; if (logstrw != null) { logstrw.WriteLine("Ref tracks: " + nr); logstrw.WriteLine("Add tracks: " + na); } if (nr == 0 || na == 0) { return(calinfo); } SySal.BasicTypes.Rectangle refrect = new SySal.BasicTypes.Rectangle(); SySal.BasicTypes.Rectangle addrect = new SySal.BasicTypes.Rectangle(); SySal.Tracking.MIPEmulsionTrackInfo refinfo = refpattern[0]; SySal.Tracking.MIPEmulsionTrackInfo addinfo = mappattern[0]; refrect.MinX = refrect.MaxX = refinfo.Intercept.X; refrect.MinY = refrect.MaxY = refinfo.Intercept.Y; addrect.MinX = addrect.MaxX = addinfo.Intercept.X; addrect.MinY = addrect.MaxY = addinfo.Intercept.Y; int i; for (i = 1; i < nr; i++) { refinfo = refpattern[i]; if (refinfo.Intercept.X < refrect.MinX) { refrect.MinX = refinfo.Intercept.X; } else if (refinfo.Intercept.X > refrect.MaxX) { refrect.MaxX = refinfo.Intercept.X; } if (refinfo.Intercept.Y < refrect.MinY) { refrect.MinY = refinfo.Intercept.Y; } else if (refinfo.Intercept.Y > refrect.MaxY) { refrect.MaxY = refinfo.Intercept.Y; } } for (i = 1; i < na; i++) { addinfo = mappattern[i]; if (addinfo.Intercept.X < addrect.MinX) { addrect.MinX = addinfo.Intercept.X; } else if (addinfo.Intercept.X > addrect.MaxX) { addrect.MaxX = addinfo.Intercept.X; } if (addinfo.Intercept.Y < addrect.MinY) { addrect.MinY = addinfo.Intercept.Y; } else if (addinfo.Intercept.Y > addrect.MaxY) { addrect.MaxY = addinfo.Intercept.Y; } } SySal.BasicTypes.Rectangle maprect = new SySal.BasicTypes.Rectangle(); maprect.MinX = Math.Max(refrect.MinX, addrect.MinX); maprect.MaxX = Math.Min(refrect.MaxX, addrect.MaxX); maprect.MinY = Math.Max(refrect.MinY, addrect.MinY); maprect.MaxY = Math.Min(refrect.MaxY, addrect.MaxY); int xcells = (int)Math.Ceiling((maprect.MaxX - maprect.MinX) / m_Config.MapSize); int ycells = (int)Math.Ceiling((maprect.MaxY - maprect.MinY) / m_Config.MapSize); if (logstrw != null) { logstrw.WriteLine("Ref rect: " + refrect.MinX + " " + refrect.MaxX + " " + refrect.MinY + " " + refrect.MaxY); logstrw.WriteLine("Map rect: " + addrect.MinX + " " + addrect.MaxX + " " + addrect.MinY + " " + addrect.MaxY); logstrw.WriteLine("Common rect: " + maprect.MinX + " " + maprect.MaxX + " " + maprect.MinY + " " + maprect.MaxY); logstrw.WriteLine("X cells: " + xcells + " Y cells: " + ycells); } if (xcells <= 0 || ycells <= 0) { return(calinfo); } int ix, iy; System.Collections.ArrayList[,] rmaps = new System.Collections.ArrayList[ycells, xcells]; System.Collections.ArrayList[,] amaps = new System.Collections.ArrayList[ycells, xcells]; for (ix = 0; ix < xcells; ix++) { for (iy = 0; iy < ycells; iy++) { rmaps[iy, ix] = new System.Collections.ArrayList(); amaps[iy, ix] = new System.Collections.ArrayList(); } } for (i = 0; i < nr; i++) { refinfo = refpattern[i]; ix = (int)((refinfo.Intercept.X - maprect.MinX) / m_Config.MapSize); if (ix < 0 || ix >= xcells) { continue; } iy = (int)((refinfo.Intercept.Y - maprect.MinY) / m_Config.MapSize); if (iy < 0 || iy >= ycells) { continue; } if (flt == null || flt(refinfo)) { rmaps[iy, ix].Add(refinfo); } } for (i = 0; i < na; i++) { addinfo = mappattern[i]; ix = (int)((addinfo.Intercept.X - maprect.MinX) / m_Config.MapSize); if (ix < 0 || ix >= xcells) { continue; } iy = (int)((addinfo.Intercept.Y - maprect.MinY) / m_Config.MapSize); if (iy < 0 || iy >= ycells) { continue; } if (flt == null || flt(addinfo)) { amaps[iy, ix].Add(addinfo); } } System.Collections.ArrayList mres = new System.Collections.ArrayList(); for (ix = 0; ix < xcells; ix++) { for (iy = 0; iy < ycells; iy++) { SySal.Tracking.MIPEmulsionTrackInfo[] ri = (SySal.Tracking.MIPEmulsionTrackInfo[])rmaps[iy, ix].ToArray(typeof(SySal.Tracking.MIPEmulsionTrackInfo)); if (ri.Length <= 0) { continue; } SySal.Tracking.MIPEmulsionTrackInfo[] ai = (SySal.Tracking.MIPEmulsionTrackInfo[])amaps[iy, ix].ToArray(typeof(SySal.Tracking.MIPEmulsionTrackInfo)); if (ai.Length <= 0) { continue; } MapResult mr = Map(ri, ai)[0]; if (mr.Valid) { SySal.BasicTypes.Vector2 p = new SySal.BasicTypes.Vector2(); p.X = maprect.MinX + m_Config.MapSize * (ix + 0.5); p.Y = maprect.MinY + m_Config.MapSize * (iy + 0.5); mres.Add(new object[] { p, mr }); logstrw.WriteLine("Z ix " + ix + " iy " + iy + " matches " + mr.Matches + " X " + p.X + " Y " + p.Y + " DeltaX/Y " + mr.DeltaPos.X + "/" + mr.DeltaPos.Y + " RMSX/Y " + mr.DeltaPosRMS.X + "/" + mr.DeltaPosRMS.Y + " DeltaSX/Y " + mr.DeltaSlope.X + "/" + mr.DeltaSlope.Y + " RMSX/Y " + mr.DeltaSlopeRMS.X + "/" + mr.DeltaSlopeRMS.Y); } else if (logstrw != null) { logstrw.WriteLine("Z ix " + ix + " iy " + iy + " matches " + mr.Matches); } } } double[,] inXY = new double[mres.Count, 2]; double[,] dXY = new double[mres.Count, 2]; for (i = 0; i < mres.Count; i++) { object[] o = (object[])mres[i]; inXY[i, 0] = ((SySal.BasicTypes.Vector2)o[0]).X; inXY[i, 1] = ((SySal.BasicTypes.Vector2)o[0]).Y; dXY[i, 0] = -((MapResult)o[1]).DeltaPos.X; dXY[i, 1] = -((MapResult)o[1]).DeltaPos.Y; if (logstrw != null) { logstrw.WriteLine("Zone " + i + " matches " + ((MapResult)o[1]).Matches + " " + inXY[i, 0] + " " + inXY[i, 1] + " " + dXY[i, 0] + " " + dXY[i, 1]); } } switch (mres.Count) { case 0: return(calinfo); case 1: return(calinfo = TransformFitter.FindTranslation(inXY, dXY)); case 2: return(calinfo = TransformFitter.FindRototranslation(inXY, dXY)); default: try { return(calinfo = TransformFitter.FindAffineTransformation(inXY, dXY)); } catch (Exception) { return(calinfo = TransformFitter.FindRototranslation(inXY, dXY)); } } } finally { if (logstrw != null) { logstrw.WriteLine("End mapping with RX/Y " + calinfo.RX + "/" + calinfo.RY + " MXX/XY/YX/YY " + calinfo.MXX + "/" + calinfo.MXY + "/" + calinfo.MYX + "/" + calinfo.MYY + " TX/Y " + calinfo.TX + "/" + calinfo.TY + "."); } } }