Beispiel #1
0
        /// <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);
        }
Beispiel #2
0
 public void Execute()
 {
     SySal.Processing.QuickMapping.QuickMapper   QM = new SySal.Processing.QuickMapping.QuickMapper();
     SySal.Processing.QuickMapping.Configuration C  = QM.Config as SySal.Processing.QuickMapping.Configuration;
     C.FullStatistics       = false;
     C.Name                 = "";
     C.PosTol               = m_PosTol;
     C.SlopeTol             = m_SlopeTol;
     C.UseAbsoluteReference = true;
     m_Pairs                = QM.Match(m_rinfo, m_winfo, m_DZ, m_PosSweep, m_PosSweep);
 }
Beispiel #3
0
        private void Compute(bool comp_x, bool comp_y, object btn)
        {
            m_Running = true;
            EnableButtons(btn);
            m_Stop           = false;
            pbProgress.Value = 0.0;
            System.Threading.Thread thread = new System.Threading.Thread(new System.Threading.ThreadStart(delegate()
            {
                try
                {
                    SySal.Processing.QuickMapping.QuickMapper QM    = new SySal.Processing.QuickMapping.QuickMapper();
                    SySal.Processing.QuickMapping.Configuration qmc = (SySal.Processing.QuickMapping.Configuration)QM.Config;
                    qmc.FullStatistics       = false;
                    qmc.UseAbsoluteReference = true;
                    qmc.PosTol   = S.PosTolerance;
                    qmc.SlopeTol = 1.0;
                    QM.Config    = qmc;
                    System.Collections.ArrayList xconv = new System.Collections.ArrayList();
                    System.Collections.ArrayList yconv = new System.Collections.ArrayList();
                    int sfi;
                    for (sfi = 0; sfi < SummaryFiles.Length; sfi++)
                    {
                        QuasiStaticAcquisition Q = new QuasiStaticAcquisition(SummaryFiles[sfi]);
                        foreach (QuasiStaticAcquisition.Sequence seq in Q.Sequences)
                        {
                            int ly;
                            SySal.Imaging.Cluster[] prevC = FilterClusters(seq.Layers[0].ReadClusters());
                            SySal.Imaging.Cluster[] nextC = null;
                            SySal.BasicTypes.Vector prevP = seq.Layers[0].Position;
                            SySal.BasicTypes.Vector nextP = new SySal.BasicTypes.Vector();
                            for (ly = 1; ly < seq.Layers.Length; ly++)
                            {
                                if (m_Stop)
                                {
                                    throw new Exception("Stopped.");
                                }
                                nextC = FilterClusters(seq.Layers[ly].ReadClusters());
                                nextP = seq.Layers[ly].Position;
                                this.Invoke(new dSetValue(SetValue), 100.0 * (((double)seq.Id + (double)(ly - 1) / (double)(seq.Layers.Length - 1)) / (double)(Q.Sequences.Length) + sfi) / SummaryFiles.Length);
                                SySal.BasicTypes.Vector2 dp   = new SySal.BasicTypes.Vector2(seq.Layers[ly].Position - seq.Layers[ly - 1].Position);
                                SySal.BasicTypes.Vector2 dp1  = dp; dp1.X /= S.MinConv; dp1.Y /= S.MinConv;
                                SySal.BasicTypes.Vector2 dp2  = dp; dp2.X /= S.MaxConv; dp2.Y /= S.MaxConv;
                                SySal.BasicTypes.Vector2 da   = new SySal.BasicTypes.Vector2(); da.X = 0.5 * (dp1.X + dp2.X); da.Y = 0.5 * (dp1.Y + dp2.Y);
                                SySal.BasicTypes.Vector2 dext = new SySal.BasicTypes.Vector2(); dext.X = Math.Abs(dp1.X - dp2.X); dext.Y = Math.Abs(dp1.Y - dp2.Y);
                                SySal.Tracking.MIPEmulsionTrackInfo[] prevmap = new SySal.Tracking.MIPEmulsionTrackInfo[prevC.Length];
                                int i;
                                for (i = 0; i < prevC.Length; i++)
                                {
                                    SySal.Tracking.MIPEmulsionTrackInfo info = new SySal.Tracking.MIPEmulsionTrackInfo();
                                    info.Intercept.X = prevC[i].X;
                                    info.Intercept.Y = prevC[i].Y;
                                    prevmap[i]       = info;
                                }
                                SySal.Tracking.MIPEmulsionTrackInfo[] nextmap = new SySal.Tracking.MIPEmulsionTrackInfo[nextC.Length];
                                for (i = 0; i < nextC.Length; i++)
                                {
                                    nextmap[i] = new SySal.Tracking.MIPEmulsionTrackInfo();
                                }
                                double[,] convopt = new double[, ] {
                                    { 1.0, 1.0 }, { -1.0, 1.0 }, { -1.0, -1.0 }, { 1.0, -1.0 }
                                };
                                int o;
                                SySal.Scanning.PostProcessing.PatternMatching.TrackPair[] bestpairs = new SySal.Scanning.PostProcessing.PatternMatching.TrackPair[0];
                                SySal.BasicTypes.Vector2 bestda = new SySal.BasicTypes.Vector2();
                                for (o = 0; o < convopt.GetLength(0); o++)
                                {
                                    try
                                    {
                                        for (i = 0; i < nextC.Length; i++)
                                        {
                                            SySal.Tracking.MIPEmulsionTrackInfo info = nextmap[i];
                                            info.Intercept.X = nextC[i].X + da.X * convopt[o, 0];
                                            info.Intercept.Y = nextC[i].Y + da.Y * convopt[o, 1];
                                            nextmap[i]       = info;
                                        }
                                        SySal.Scanning.PostProcessing.PatternMatching.TrackPair[] prs = QM.Match(prevmap, nextmap, 0.0, dext.X, dext.Y);
                                        if (prs.Length > bestpairs.Length)
                                        {
                                            bestda.X  = da.X * convopt[o, 0];
                                            bestda.Y  = da.Y * convopt[o, 1];
                                            bestpairs = prs;
                                        }
                                    }
                                    catch (Exception xc) { }
                                }

                                if (bestpairs.Length >= S.MinMatches)
                                {
                                    double[] deltas = new double[bestpairs.Length];
                                    for (i = 0; i < bestpairs.Length; i++)
                                    {
                                        deltas[i] = bestpairs[i].First.Info.Intercept.X - nextC[bestpairs[i].Second.Index].X;
                                    }
                                    bestda.X = NumericalTools.Fitting.Quantiles(deltas, new double[] { 0.5 })[0];
                                    if (bestda.X != 0.0)
                                    {
                                        double v = dp.X / bestda.X;
                                        int pos  = xconv.BinarySearch(v);
                                        if (pos < 0)
                                        {
                                            pos = ~pos;
                                        }
                                        xconv.Insert(pos, v);
                                    }
                                    for (i = 0; i < bestpairs.Length; i++)
                                    {
                                        deltas[i] = bestpairs[i].First.Info.Intercept.Y - nextC[bestpairs[i].Second.Index].Y;
                                    }
                                    bestda.Y = NumericalTools.Fitting.Quantiles(deltas, new double[] { 0.5 })[0];
                                    if (bestda.Y != 0.0)
                                    {
                                        double v = dp.Y / bestda.Y;
                                        int pos  = yconv.BinarySearch(v);
                                        if (pos < 0)
                                        {
                                            pos = ~pos;
                                        }
                                        yconv.Insert(pos, v);
                                    }
                                    if (comp_x && xconv.Count > 0)
                                    {
                                        int bmin, bmax;
                                        bmin = (int)Math.Ceiling(xconv.Count * 0.16);
                                        bmax = (int)Math.Floor(xconv.Count * 0.84);
                                        if (bmax < bmin)
                                        {
                                            bmin = bmax;
                                        }
                                        double[] sample1s = (double[])xconv.GetRange(bmin, bmax - bmin + 1).ToArray(typeof(double));
                                        XConv             = NumericalTools.Fitting.Average(sample1s);
                                        this.Invoke(new dSetConv(SetConv), new object[] { true, XConv, 0.5 * (sample1s[sample1s.Length - 1] - sample1s[0]) / Math.Sqrt(sample1s.Length) });
                                    }
                                    if (comp_y && yconv.Count > 0)
                                    {
                                        int bmin, bmax;
                                        bmin = (int)Math.Ceiling(yconv.Count * 0.16);
                                        bmax = (int)Math.Floor(yconv.Count * 0.84);
                                        if (bmax < bmin)
                                        {
                                            bmin = bmax;
                                        }
                                        double[] sample1s = (double[])yconv.GetRange(bmin, bmax - bmin + 1).ToArray(typeof(double));
                                        YConv             = NumericalTools.Fitting.Average(sample1s);
                                        this.Invoke(new dSetConv(SetConv), new object[] { false, YConv, 0.5 * (sample1s[sample1s.Length - 1] - sample1s[0]) / Math.Sqrt(sample1s.Length) });
                                    }
                                }
                                prevP = nextP;
                                prevC = nextC;
                            }
                        }
                    }
                }
                catch (Exception xc1)
                {
                    iLog.Log("Compute", xc1.ToString());
                }
                m_Running = false;
                this.Invoke(new dEnableButtons(EnableButtons), btn);
            }));
            thread.Start();
        }
Beispiel #4
0
        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)));
        }
Beispiel #5
0
        private static void OneZoneIntercalibration(string [] args, ref SySal.DAQSystem.Scanning.IntercalibrationInfo intercal, bool rewrite)
        {
            int i, j, n;
            int MinMatches = Convert.ToInt32(args[8]);

            SySal.Scanning.Plate.IO.OPERA.LinkedZone reflz   = (SySal.Scanning.Plate.IO.OPERA.LinkedZone)SySal.OperaPersistence.Restore(args[1], typeof(SySal.Scanning.Plate.IO.OPERA.LinkedZone));
            SySal.Tracking.MIPEmulsionTrackInfo []   refzone = new SySal.Tracking.MIPEmulsionTrackInfo[reflz.Length];
            for (i = 0; i < refzone.Length; i++)
            {
                refzone[i] = reflz[i].Info;
            }
            reflz = null;
            GC.Collect();
            SySal.Scanning.Plate.IO.OPERA.LinkedZone caliblz   = (SySal.Scanning.Plate.IO.OPERA.LinkedZone)SySal.OperaPersistence.Restore(args[2], typeof(SySal.Scanning.Plate.IO.OPERA.LinkedZone));
            SySal.Tracking.MIPEmulsionTrackInfo []   calibzone = new SySal.Tracking.MIPEmulsionTrackInfo[caliblz.Length];
            for (i = 0; i < calibzone.Length; i++)
            {
                calibzone[i] = caliblz[i].Info;
            }
            if (!rewrite)
            {
                caliblz = null;
            }
            GC.Collect();
            SySal.Processing.QuickMapping.QuickMapper   QMap = new SySal.Processing.QuickMapping.QuickMapper();
            SySal.Processing.QuickMapping.Configuration C    = (SySal.Processing.QuickMapping.Configuration)QMap.Config;
            double postol   = Convert.ToDouble(args[4], System.Globalization.CultureInfo.InvariantCulture);
            double leverarm = Convert.ToDouble(args[6], System.Globalization.CultureInfo.InvariantCulture);

            C.PosTol    = postol + leverarm;
            C.SlopeTol  = Convert.ToDouble(args[5], System.Globalization.CultureInfo.InvariantCulture);
            QMap.Config = C;
            double ZProj     = Convert.ToDouble(args[3], System.Globalization.CultureInfo.InvariantCulture);
            double maxoffset = Convert.ToDouble(args[7], System.Globalization.CultureInfo.InvariantCulture);

            SySal.Scanning.PostProcessing.PatternMatching.TrackPair [] pairs = QMap.Match(refzone, calibzone, ZProj, maxoffset, maxoffset);
            if (pairs.Length < MinMatches)
            {
                Console.Error.WriteLine("Too few matching tracks: " + MinMatches.ToString() + " required, " + pairs.Length + " obtained. Aborting.");
                return;
            }
            Console.WriteLine("Matches: " + pairs.Length);

            n = pairs.Length;
            double [,] indep = new double[2, n];
            double [] dep   = new double[n];
            double [] res   = new double[3];
            double    dummy = 0.0;

            for (i = 0; i < n; i++)
            {
                indep[0, i] = ((SySal.Tracking.MIPEmulsionTrackInfo)(pairs[i].Second.Track)).Intercept.X - intercal.RX;
                indep[1, i] = ((SySal.Tracking.MIPEmulsionTrackInfo)(pairs[i].Second.Track)).Intercept.Y - intercal.RY;
                dep[i]      = pairs[i].First.Info.Intercept.X - intercal.RX;
            }
            NumericalTools.Fitting.MultipleLinearRegression(indep, dep, ref res, ref dummy);
            Console.WriteLine("{0}\t{1}\t{2}\t{3}", res[0], res[1], res[2], dummy);
            intercal.TX = res[0]; intercal.MXX = res[1]; intercal.MXY = res[2];
            for (i = 0; i < n; i++)
            {
                indep[0, i] = ((SySal.Tracking.MIPEmulsionTrackInfo)(pairs[i].Second.Track)).Intercept.X - intercal.RX;
                indep[1, i] = ((SySal.Tracking.MIPEmulsionTrackInfo)(pairs[i].Second.Track)).Intercept.Y - intercal.RY;
                dep[i]      = pairs[i].First.Info.Intercept.Y - intercal.RY;
            }
            NumericalTools.Fitting.MultipleLinearRegression(indep, dep, ref res, ref dummy);
            Console.WriteLine("{0}\t{1}\t{2}\t{3}", res[0], res[1], res[2], dummy);
            intercal.TY = res[0]; intercal.MYX = res[1]; intercal.MYY = res[2];

            System.Collections.ArrayList a_goodpairs = new System.Collections.ArrayList();
            foreach (SySal.Scanning.PostProcessing.PatternMatching.TrackPair p in pairs)
            {
                dummy = Math.Abs(intercal.TX + intercal.MXX * (p.Second.Info.Intercept.X - intercal.RX) + intercal.MXY * (p.Second.Info.Intercept.Y - intercal.RY) - p.First.Info.Intercept.X + intercal.RX);
                if (dummy > postol)
                {
                    continue;
                }
                dummy = Math.Abs(intercal.TY + intercal.MYX * (p.Second.Info.Intercept.X - intercal.RX) + intercal.MYY * (p.Second.Info.Intercept.Y - intercal.RY) - p.First.Info.Intercept.Y + intercal.RY);
                if (dummy > postol)
                {
                    continue;
                }
                a_goodpairs.Add(p);
            }
            Console.WriteLine("remaining " + a_goodpairs.Count);

            SySal.Scanning.PostProcessing.PatternMatching.TrackPair [] goodpairs = (SySal.Scanning.PostProcessing.PatternMatching.TrackPair [])a_goodpairs.ToArray(typeof(SySal.Scanning.PostProcessing.PatternMatching.TrackPair));
            n     = goodpairs.Length;
            indep = new double[2, n];
            dep   = new double[n];
            for (i = 0; i < n; i++)
            {
                indep[0, i] = ((SySal.Tracking.MIPEmulsionTrackInfo)(goodpairs[i].Second.Track)).Intercept.X - intercal.RX;
                indep[1, i] = ((SySal.Tracking.MIPEmulsionTrackInfo)(goodpairs[i].Second.Track)).Intercept.Y - intercal.RY;
                dep[i]      = goodpairs[i].First.Info.Intercept.X - intercal.RX;
            }
            NumericalTools.Fitting.MultipleLinearRegression(indep, dep, ref res, ref dummy);
            Console.WriteLine("{0}\t{1}\t{2}\t{3}", res[0], res[1], res[2], dummy);
            intercal.TX = res[0]; intercal.MXX = res[1]; intercal.MXY = res[2];
            for (i = 0; i < n; i++)
            {
                indep[0, i] = ((SySal.Tracking.MIPEmulsionTrackInfo)(goodpairs[i].Second.Track)).Intercept.X - intercal.RX;
                indep[1, i] = ((SySal.Tracking.MIPEmulsionTrackInfo)(goodpairs[i].Second.Track)).Intercept.Y - intercal.RY;
                dep[i]      = goodpairs[i].First.Info.Intercept.Y - intercal.RY;
            }
            NumericalTools.Fitting.MultipleLinearRegression(indep, dep, ref res, ref dummy);
            Console.WriteLine("{0}\t{1}\t{2}\t{3}", res[0], res[1], res[2], dummy);
            intercal.TY = res[0]; intercal.MYX = res[1]; intercal.MYY = res[2];
            CheckIntercalibration(intercal);
            if (rewrite)
            {
                MyTransformation.Transformation = intercal;
                SySal.OperaPersistence.Persist(args[2], new LinkedZone(caliblz));
            }
        }
Beispiel #6
0
        private static void ThreeZoneIntercalibration(string [] args, ref SySal.DAQSystem.Scanning.IntercalibrationInfo intercal, bool rewrite)
        {
            int i, n;
            int MinMatches = Convert.ToInt32(args[11]);

            SySal.Processing.QuickMapping.QuickMapper   QMap = new SySal.Processing.QuickMapping.QuickMapper();
            SySal.Processing.QuickMapping.Configuration C    = (SySal.Processing.QuickMapping.Configuration)QMap.Config;
            C.PosTol    = Convert.ToDouble(args[8], System.Globalization.CultureInfo.InvariantCulture);
            C.SlopeTol  = Convert.ToDouble(args[9], System.Globalization.CultureInfo.InvariantCulture);
            QMap.Config = C;
            double ZProj     = Convert.ToDouble(args[7], System.Globalization.CultureInfo.InvariantCulture);
            double maxoffset = Convert.ToDouble(args[10], System.Globalization.CultureInfo.InvariantCulture);

            MapPos [] mappositions = new MapPos[3];

            SySal.Scanning.Plate.IO.OPERA.LinkedZone [] savezones = new SySal.Scanning.Plate.IO.OPERA.LinkedZone[3];
            for (n = 0; n < 3; n++)
            {
                SySal.Scanning.Plate.IO.OPERA.LinkedZone reflz   = (SySal.Scanning.Plate.IO.OPERA.LinkedZone)SySal.OperaPersistence.Restore(args[1 + n * 2], typeof(SySal.Scanning.Plate.IO.OPERA.LinkedZone));
                SySal.Tracking.MIPEmulsionTrackInfo []   refzone = new SySal.Tracking.MIPEmulsionTrackInfo[reflz.Length];
                for (i = 0; i < refzone.Length; i++)
                {
                    refzone[i] = reflz[i].Info;
                }
                reflz = null;
                SySal.Scanning.Plate.IO.OPERA.LinkedZone caliblz = (SySal.Scanning.Plate.IO.OPERA.LinkedZone)SySal.OperaPersistence.Restore(args[2 + n * 2], typeof(SySal.Scanning.Plate.IO.OPERA.LinkedZone));
                if (rewrite)
                {
                    savezones[n] = caliblz;
                }
                SySal.Tracking.MIPEmulsionTrackInfo [] calibzone = new SySal.Tracking.MIPEmulsionTrackInfo[caliblz.Length];
                for (i = 0; i < calibzone.Length; i++)
                {
                    calibzone[i] = caliblz[i].Info;
                }
                caliblz = null;
                GC.Collect();
                Console.Write("Zone #" + n.ToString() + " ");
                SySal.Scanning.PostProcessing.PatternMatching.TrackPair [] pairs = QMap.Match(refzone, calibzone, ZProj, maxoffset, maxoffset);
                if (pairs.Length < MinMatches)
                {
                    Console.Error.WriteLine("Too few matching tracks: " + MinMatches.ToString() + " required, " + pairs.Length + " obtained. Aborting.");
                    return;
                }
                Console.WriteLine("Matches: " + pairs.Length);
                mappositions[n].SetFromPairs(pairs);
                mappositions[n].X -= intercal.RX;
                mappositions[n].Y -= intercal.RY;
            }
            double x20 = mappositions[2].X - mappositions[0].X;
            double x10 = mappositions[1].X - mappositions[0].X;
            double y20 = mappositions[2].Y - mappositions[0].Y;
            double y10 = mappositions[1].Y - mappositions[0].Y;
            double det = 1.0 / (x10 * y20 - x20 * y10);
            double u20 = mappositions[2].DX - mappositions[0].DX;
            double v20 = mappositions[2].DY - mappositions[0].DY;
            double u10 = mappositions[1].DX - mappositions[0].DX;
            double v10 = mappositions[1].DY - mappositions[0].DY;

            intercal.MXX  = (u10 * y20 - u20 * y10) * det;
            intercal.MXY  = (u20 * x10 - u10 * x20) * det;
            intercal.MYX  = (v10 * y20 - v20 * y10) * det;
            intercal.MYY  = (v20 * x10 - v10 * x20) * det;
            intercal.TX   = mappositions[0].DX - intercal.MXX * mappositions[0].X - intercal.MXY * mappositions[0].Y;
            intercal.TY   = mappositions[0].DY - intercal.MYX * mappositions[0].X - intercal.MYY * mappositions[0].Y;
            intercal.MXX += 1.0;
            intercal.MYY += 1.0;
            CheckIntercalibration(intercal);
            if (rewrite)
            {
                MyTransformation.Transformation = intercal;
                for (n = 0; n < 3; n++)
                {
                    SySal.OperaPersistence.Persist(args[2 + n * 2], new LinkedZone(savezones[n]));
                }
            }
        }
Beispiel #7
0
        static void Main(string[] args)
        {
            if (args.Length != 13 && args.Length != 4 && args.Length != 2)
            {
                Console.WriteLine("usage: FlattenTLG.exe <cell map> <TLG to be flattened> <output TLG> <min matches>");
                Console.WriteLine("   or");
                Console.WriteLine("usage: FlattenTLG.exe <cell map> <min matches>");
                Console.WriteLine("           (opens a console to query the transformation map generator)");
                Console.WriteLine("   or");
                Console.WriteLine("usage: FlattenTLG.exe <reference TLG (supposed flat)> <TLG to be flattened> <output TLG> <cell size> <slope tol> <pos tol> <pos sweep> <z projection> <selection string> <min matches> <z adjust> <z step> <parallel (true|false)>");
                Console.WriteLine("Selection function variables:");
                foreach (SelFunc sf in KnownFunctions)
                {
                    Console.WriteLine(sf.Name + " -> " + sf.Desc);
                }
                return;
            }
            bool   usereadymap = (args.Length < 13);
            bool   useconsole = (args.Length == 2);
            string reftlg = args[0];
            string worktlg = useconsole ? "" : args[1];
            string outtlg = useconsole ? "" : args[2];
            uint   MinMatches = 0;
            int    xcells = 0;
            int    ycells = 0;
            double cellsize = 0.0;
            int    ix, iy;
            int    i, j, k;

            SySal.BasicTypes.Vector2   Center  = new SySal.BasicTypes.Vector2();
            SySal.BasicTypes.Rectangle WorkRect;
            SySal.Scanning.Plate.IO.OPERA.LinkedZone worklz = null;
            if (useconsole == false)
            {
                worklz   = SySal.DataStreams.OPERALinkedZone.FromFile(worktlg);
                WorkRect = worklz.Extents;
            }
            else
            {
                WorkRect = new SySal.BasicTypes.Rectangle();
            }
            SySal.BasicTypes.Rectangle RefRect = new SySal.BasicTypes.Rectangle();
            RTrackCell[,] WorkCells;
            if (usereadymap)
            {
                MinMatches = Convert.ToUInt32(args[useconsole ? 1 : 3]);
                System.IO.StreamReader cr = new System.IO.StreamReader(args[0]);
                while (cr.EndOfStream == false)
                {
                    System.Text.RegularExpressions.Match m = rx_CellMap.Match(cr.ReadLine());
                    if (m.Success)
                    {
                        RefRect.MinX = Convert.ToDouble(m.Groups[1].Value);
                        RefRect.MaxX = Convert.ToDouble(m.Groups[2].Value);
                        RefRect.MinY = Convert.ToDouble(m.Groups[3].Value);
                        RefRect.MaxY = Convert.ToDouble(m.Groups[4].Value);
                        cellsize     = Convert.ToDouble(m.Groups[5].Value);
                        xcells       = Convert.ToInt32(m.Groups[6].Value);
                        ycells       = Convert.ToInt32(m.Groups[7].Value);
                        break;
                    }
                }
                Center.X  = 0.5 * (RefRect.MinX + RefRect.MaxX);
                Center.Y  = 0.5 * (RefRect.MinY + RefRect.MaxY);
                WorkCells = new RTrackCell[xcells, ycells];
                for (ix = 0; ix < xcells; ix++)
                {
                    for (iy = 0; iy < ycells; iy++)
                    {
                        SySal.BasicTypes.Rectangle rect = new SySal.BasicTypes.Rectangle();
                        rect.MinX                = RefRect.MinX + ix * cellsize;
                        rect.MaxX                = rect.MinX + cellsize;
                        rect.MinY                = RefRect.MinY + iy * cellsize;
                        rect.MaxY                = rect.MinY + cellsize;
                        WorkCells[ix, iy]        = new RTrackCell(rect, Center);
                        WorkCells[ix, iy].Result = NumericalTools.ComputationResult.InvalidInput;
                    }
                }
                while (cr.EndOfStream == false)
                {
                    System.Text.RegularExpressions.Match m = rx_Cell.Match(cr.ReadLine());
                    if (m.Success)
                    {
                        ix = Convert.ToInt32(m.Groups[1].Value);
                        iy = Convert.ToInt32(m.Groups[2].Value);
                        WorkCells[ix, iy].Result           = NumericalTools.ComputationResult.OK;
                        WorkCells[ix, iy].Matches          = Convert.ToInt32(m.Groups[3].Value);
                        WorkCells[ix, iy].Average.X        = Convert.ToDouble(m.Groups[4].Value);
                        WorkCells[ix, iy].Average.Y        = Convert.ToDouble(m.Groups[5].Value);
                        WorkCells[ix, iy].AlignInfo.MXX    = Convert.ToDouble(m.Groups[6].Value);
                        WorkCells[ix, iy].AlignInfo.MXY    = Convert.ToDouble(m.Groups[7].Value);
                        WorkCells[ix, iy].AlignInfo.MYX    = Convert.ToDouble(m.Groups[8].Value);
                        WorkCells[ix, iy].AlignInfo.MYY    = Convert.ToDouble(m.Groups[9].Value);
                        WorkCells[ix, iy].AlignInfo.TX     = Convert.ToDouble(m.Groups[10].Value);
                        WorkCells[ix, iy].AlignInfo.TY     = Convert.ToDouble(m.Groups[11].Value);
                        WorkCells[ix, iy].AlignInfo.TZ     = Convert.ToDouble(m.Groups[12].Value);
                        WorkCells[ix, iy].SlopeAlignInfo.X = Convert.ToDouble(m.Groups[13].Value);
                        WorkCells[ix, iy].SlopeAlignInfo.Y = Convert.ToDouble(m.Groups[14].Value);
                    }
                }
                cr.Close();
                if (useconsole)
                {
                    GridInterpolation G1 = new GridInterpolation(WorkCells, cellsize, RefRect, (int)MinMatches);
                    Console.WriteLine("Type a pair of coordinates ( X Y ) to get the transformation map.\r\nEOF (CTRL+Z to exit).");
                    double x, y;
                    string line;
                    while ((line = Console.ReadLine()) != null)
                    {
                        System.Text.RegularExpressions.Match m = rx_XY.Match(line);
                        x = Convert.ToDouble(m.Groups[1].Value);
                        y = Convert.ToDouble(m.Groups[2].Value);
                        SySal.BasicTypes.Vector dslope = new SySal.BasicTypes.Vector();
                        SySal.DAQSystem.Scanning.IntercalibrationInfo dpos = new SySal.DAQSystem.Scanning.IntercalibrationInfo();
                        bool result = G1.Evaluate(x, y, ref dslope, ref dpos);
                        Console.WriteLine(x + " " + y + " -> " + (result ? "OK" : "FAILED") + " " + dpos.RX + " " + dpos.RY + " " + dpos.MXX + " " + dpos.MXY + " " + dpos.MYX + " " + dpos.MYY + " " + dpos.TX + " " + dpos.TY + " " + dpos.TZ + " " + dslope.X + " " + dslope.Y);
                    }
                    return;
                }
            }
            else
            {
                cellsize = Convert.ToDouble(args[3]);
                double slopetol  = Convert.ToDouble(args[4]);
                double postol    = Convert.ToDouble(args[5]);
                double possweep  = Convert.ToDouble(args[6]);
                double DZ        = Convert.ToDouble(args[7]);
                string selstring = args[8];
                MinMatches = Convert.ToUInt32(args[9]);
                double ZAdj       = Convert.ToDouble(args[10]);
                double ZStep      = Convert.ToDouble(args[11]);
                bool   IsParallel = Convert.ToBoolean(args[12]);
                NumericalTools.CStyleParsedFunction S = new NumericalTools.CStyleParsedFunction(selstring);
                dSel[] pMap = new dSel[S.ParameterList.Length];
                for (j = 0; j < S.ParameterList.Length; j++)
                {
                    string sp = S.ParameterList[j];
                    for (i = 0; i < KnownFunctions.Length && String.Compare(sp, KnownFunctions[i].Name, true) != 0; i++)
                    {
                        ;
                    }
                    if (i == KnownFunctions.Length)
                    {
                        throw new Exception("Unknown parameter \"" + sp + "\".");
                    }
                    pMap[j] = KnownFunctions[i].Evaluate;
                }
                SySal.Scanning.Plate.IO.OPERA.LinkedZone reflz = SySal.DataStreams.OPERALinkedZone.FromFile(reftlg);
                RefRect = reflz.Extents;
                if (WorkRect.MinX > RefRect.MinX)
                {
                    RefRect.MinX = WorkRect.MinX;
                }
                if (WorkRect.MaxX < RefRect.MaxX)
                {
                    RefRect.MaxX = WorkRect.MaxX;
                }
                if (WorkRect.MinY > RefRect.MinY)
                {
                    RefRect.MinY = WorkRect.MinY;
                }
                if (WorkRect.MaxY < RefRect.MaxY)
                {
                    RefRect.MaxY = WorkRect.MaxY;
                }
                Center.X = 0.5 * (RefRect.MinX + RefRect.MaxX);
                Center.Y = 0.5 * (RefRect.MinY + RefRect.MaxY);
                xcells   = (int)Math.Ceiling((RefRect.MaxX - RefRect.MinX) / cellsize);
                ycells   = (int)Math.Ceiling((RefRect.MaxY - RefRect.MinY) / cellsize);
                Console.WriteLine("X/Y Cells: " + xcells + "/" + ycells);
                if (xcells <= 0 || ycells <= 0)
                {
                    throw new Exception("Null working area.");
                }
                RTrackCell[,] RefCells = new RTrackCell[xcells, ycells];
                WorkCells = new RTrackCell[xcells, ycells];
                for (ix = 0; ix < xcells; ix++)
                {
                    for (iy = 0; iy < ycells; iy++)
                    {
                        SySal.BasicTypes.Rectangle rect = new SySal.BasicTypes.Rectangle();
                        rect.MinX         = RefRect.MinX + ix * cellsize;
                        rect.MaxX         = rect.MinX + cellsize;
                        rect.MinY         = RefRect.MinY + iy * cellsize;
                        rect.MaxY         = rect.MinY + cellsize;
                        RefCells[ix, iy]  = new RTrackCell(rect, Center);
                        WorkCells[ix, iy] = new RTrackCell(rect, Center);
                    }
                }
                SySal.Scanning.Plate.IO.OPERA.LinkedZone lz;
                RTrackCell[,] rtc;
                for (i = 0; i < 2; i++)
                {
                    if (i == 0)
                    {
                        lz  = reflz;
                        rtc = RefCells;
                    }
                    else
                    {
                        lz  = worklz;
                        rtc = WorkCells;
                    }
                    for (j = 0; j < lz.Length; j++)
                    {
                        SySal.Scanning.MIPBaseTrack tk = lz[j] as SySal.Scanning.MIPBaseTrack;
                        for (k = 0; k < pMap.Length; k++)
                        {
                            S[k] = pMap[k](tk);
                        }
                        if (S.Evaluate() != 0.0)
                        {
                            ix = (int)((tk.Info.Intercept.X - RefRect.MinX) / cellsize);
                            iy = (int)((tk.Info.Intercept.Y - RefRect.MinY) / cellsize);
                            if (ix >= 0 && ix < xcells && iy >= 0 && iy < ycells)
                            {
                                RTrack rtr = new RTrack();
                                rtr.Slope.X    = tk.Info.Slope.X;
                                rtr.Slope.Y    = tk.Info.Slope.Y;
                                rtr.Position.X = tk.Info.Intercept.X;
                                rtr.Position.Y = tk.Info.Intercept.Y;
                                rtc[ix, iy].Add(rtr);
                            }
                        }
                    }
                }
                for (ix = 0; ix < xcells; ix++)
                {
                    for (iy = 0; iy < ycells; iy++)
                    {
                        Console.WriteLine("Ref " + RefCells[ix, iy].Average.X + " " + RefCells[ix, iy].Average.Y + " " + RefCells[ix, iy].Count);
                        Console.WriteLine("Work " + WorkCells[ix, iy].Average.X + " " + WorkCells[ix, iy].Average.Y + " " + WorkCells[ix, iy].Count);
                    }
                }
                SySal.Processing.QuickMapping.QuickMapper   QM  = new SySal.Processing.QuickMapping.QuickMapper();
                SySal.Processing.QuickMapping.Configuration qmc = QM.Config as SySal.Processing.QuickMapping.Configuration;
                qmc.FullStatistics       = false;
                qmc.UseAbsoluteReference = true;
                qmc.PosTol   = postol;
                qmc.SlopeTol = slopetol;
                for (ix = 0; ix < xcells; ix++)
                {
                    for (iy = 0; iy < ycells; iy++)
                    {
                        SySal.Tracking.MIPEmulsionTrackInfo[] rinfo = new SySal.Tracking.MIPEmulsionTrackInfo[RefCells[ix, iy].Count];
                        SySal.Tracking.MIPEmulsionTrackInfo[] winfo = new SySal.Tracking.MIPEmulsionTrackInfo[WorkCells[ix, iy].Count];
                        for (i = 0; i < 2; i++)
                        {
                            SySal.Tracking.MIPEmulsionTrackInfo[] inf = (i == 0) ? rinfo : winfo;
                            RTrackCell[,] cells = (i == 0) ? RefCells : WorkCells;
                            double dz = (i == 0) ? 0.0 : DZ;
                            for (j = 0; j < inf.Length; j++)
                            {
                                RTrack r = cells[ix, iy].Get(j);
                                inf[j]             = new SySal.Tracking.MIPEmulsionTrackInfo();
                                inf[j].Slope.X     = r.Slope.X;
                                inf[j].Slope.Y     = r.Slope.Y;
                                inf[j].Intercept.X = r.Position.X;
                                inf[j].Intercept.Y = r.Position.Y;
                                inf[j].Intercept.Z = dz;
                            }
                        }
                        SySal.Scanning.PostProcessing.PatternMatching.TrackPair[] pairs = new SySal.Scanning.PostProcessing.PatternMatching.TrackPair[0];
                        double bestdz = 0.0;
                        if (rinfo.Length >= 2 && winfo.Length >= 2)
                        {
                            double dz1;
                            if (IsParallel)
                            {
                                System.Collections.ArrayList thrarr = new System.Collections.ArrayList();
                                for (dz1 = -ZAdj; dz1 <= ZAdj; dz1 += ZStep)
                                {
                                    MapThread mthr = new MapThread();
                                    mthr.m_rinfo    = rinfo;
                                    mthr.m_winfo    = winfo;
                                    mthr.m_DZ       = DZ + dz1;
                                    mthr.m_PosSweep = possweep;
                                    mthr.m_PosTol   = postol;
                                    mthr.m_SlopeTol = slopetol;
                                    mthr.m_Thread   = new System.Threading.Thread(new System.Threading.ThreadStart(mthr.Execute));
                                    mthr.m_Thread.Start();
                                    thrarr.Add(mthr);
                                }
                                foreach (MapThread mt in thrarr)
                                {
                                    mt.m_Thread.Join();
                                    if (mt.m_Pairs.Length > pairs.Length)
                                    {
                                        bestdz = mt.m_DZ - DZ;
                                        pairs  = mt.m_Pairs;
                                    }
                                }
                            }
                            else
                            {
                                for (dz1 = -ZAdj; dz1 <= ZAdj; dz1 += ZStep)
                                {
                                    SySal.Scanning.PostProcessing.PatternMatching.TrackPair[] qairs = QM.Match(rinfo, winfo, DZ + dz1, possweep, possweep);
                                    if (qairs.Length > pairs.Length)
                                    {
                                        bestdz = dz1;
                                        pairs  = qairs;
                                    }
                                }
                            }
                        }
                        double[] alignpars = new double[7];
                        SySal.BasicTypes.Vector2 slopedelta = new SySal.BasicTypes.Vector2();
                        SySal.BasicTypes.Vector2 slopetolv  = new SySal.BasicTypes.Vector2();
                        double[] dslx = new double[pairs.Length];
                        double[] dsly = new double[pairs.Length];
                        for (j = 0; j < pairs.Length; j++)
                        {
                            dslx[j] = pairs[j].First.Info.Slope.X - pairs[j].Second.Info.Slope.X;
                        }
                        PeakFit(dslx, slopetol, out slopedelta.X, out slopetolv.X);
                        for (j = 0; j < pairs.Length; j++)
                        {
                            dsly[j] = pairs[j].First.Info.Slope.Y - pairs[j].Second.Info.Slope.Y;
                        }
                        PeakFit(dsly, slopetol, out slopedelta.Y, out slopetolv.Y);
                        int gooddslopes = 0;
                        for (j = 0; j < pairs.Length; j++)
                        {
                            if ((slopedelta.X - slopetolv.X) < dslx[j] && dslx[j] < (slopedelta.X + slopetolv.X) && (slopedelta.Y - slopetolv.Y) < dsly[j] && dsly[j] < (slopedelta.Y + slopetolv.Y))
                            {
                                gooddslopes++;
                            }
                        }
                        if (gooddslopes > 0)
                        {
                            double[] DX = new double[gooddslopes];
                            double[] DY = new double[gooddslopes];
                            double[] X  = new double[gooddslopes];
                            double[] Y  = new double[gooddslopes];
                            double[] SX = new double[gooddslopes];
                            double[] SY = new double[gooddslopes];
                            for (j = i = 0; j < pairs.Length; j++)
                            {
                                if ((slopedelta.X - slopetolv.X) < dslx[j] && dslx[j] < (slopedelta.X + slopetolv.X) && (slopedelta.Y - slopetolv.Y) < dsly[j] && dsly[j] < (slopedelta.Y + slopetolv.Y))
                                {
                                    X[i]  = pairs[j].Second.Info.Intercept.X - WorkCells[ix, iy].AlignInfo.RX;
                                    Y[i]  = pairs[j].Second.Info.Intercept.Y - WorkCells[ix, iy].AlignInfo.RY;
                                    SX[i] = pairs[j].Second.Info.Slope.X;
                                    SY[i] = pairs[j].Second.Info.Slope.Y;
                                    DX[i] = pairs[j].First.Info.Intercept.X - pairs[j].Second.Info.Intercept.X;
                                    DY[i] = pairs[j].First.Info.Intercept.Y - pairs[j].Second.Info.Intercept.Y;
                                    //System.IO.File.AppendAllText(@"c:\flattentlg.txt", "\r\n" + ix + " " + iy + " " + i + " " + j + " " + pairs.Length + " " + gooddslopes + " " + WorkCells[ix, iy].AlignInfo.RX + " " + WorkCells[ix, iy].AlignInfo.RY + " " + X[i] + " " + Y[i] + " " + SX[i] + " " + SY[i] + "  " + DX[i] + " " + DY[i] + " " + bestdz);
                                    i++;
                                }
                            }
                            WorkCells[ix, iy].Result = IteratedAffineFocusing(DX, DY, X, Y, SX, SY, postol, ref alignpars);
                        }
                        else
                        {
                            WorkCells[ix, iy].Result = NumericalTools.ComputationResult.InvalidInput;
                        }
                        WorkCells[ix, iy].Matches        = pairs.Length;
                        WorkCells[ix, iy].AlignInfo.TZ   = alignpars[6] + bestdz;
                        WorkCells[ix, iy].AlignInfo.TX   = alignpars[4];
                        WorkCells[ix, iy].AlignInfo.TY   = alignpars[5];
                        WorkCells[ix, iy].AlignInfo.MXX  = 1.0 + alignpars[0];
                        WorkCells[ix, iy].AlignInfo.MXY  = 0.0 + alignpars[1];
                        WorkCells[ix, iy].AlignInfo.MYX  = 0.0 + alignpars[2];
                        WorkCells[ix, iy].AlignInfo.MYY  = 1.0 + alignpars[3];
                        WorkCells[ix, iy].SlopeAlignInfo = slopedelta;
                        Console.WriteLine("Fit " + WorkCells[ix, iy].Result + " " + WorkCells[ix, iy].AlignInfo.MXX + " " + WorkCells[ix, iy].AlignInfo.MXY + " " + WorkCells[ix, iy].AlignInfo.MYX + " " + WorkCells[ix, iy].AlignInfo.MYY + " " + WorkCells[ix, iy].AlignInfo.TX + " " + WorkCells[ix, iy].AlignInfo.TY + " " + WorkCells[ix, iy].AlignInfo.TZ + " " + WorkCells[ix, iy].SlopeAlignInfo.X + " " + WorkCells[ix, iy].SlopeAlignInfo.Y);
                    }
                }
                int goodcells = 0;
                for (ix = 0; ix < xcells; ix++)
                {
                    for (iy = 0; iy < ycells; iy++)
                    {
                        if (WorkCells[ix, iy].Result == NumericalTools.ComputationResult.OK && WorkCells[ix, iy].Matches >= MinMatches)
                        {
                            goodcells++;
                        }
                    }
                }
                Console.WriteLine("Good cells: " + goodcells);

                Console.WriteLine("--------CELLS");
                Console.WriteLine("CELLMAP " + RefRect.MinX + " " + RefRect.MaxX + " " + RefRect.MinY + " " + RefRect.MaxY + " " + cellsize + " " + xcells + " " + ycells);
                Console.WriteLine("IX\tIY\tN\tX\tY\tMXX\tMXY\tMYX\tMYY\tTX\tTY\tTZ\tTDSX\tTDSY");
                for (ix = 0; ix < xcells; ix++)
                {
                    for (iy = 0; iy < ycells; iy++)
                    {
                        if (WorkCells[ix, iy].Result == NumericalTools.ComputationResult.OK && WorkCells[ix, iy].Matches >= MinMatches)
                        {
                            Console.WriteLine(ix + "\t" + iy + "\t" + WorkCells[ix, iy].Matches + "\t" + WorkCells[ix, iy].Average.X + "\t" + WorkCells[ix, iy].Average.Y + "\t" + WorkCells[ix, iy].AlignInfo.MXX + "\t" + WorkCells[ix, iy].AlignInfo.MXY + "\t" + WorkCells[ix, iy].AlignInfo.MYX + "\t" + WorkCells[ix, iy].AlignInfo.MYY + "\t" + WorkCells[ix, iy].AlignInfo.TX + "\t" + WorkCells[ix, iy].AlignInfo.TY + "\t" + WorkCells[ix, iy].AlignInfo.TZ + "\t" + WorkCells[ix, iy].SlopeAlignInfo.X + "\t" + WorkCells[ix, iy].SlopeAlignInfo.Y);
                        }
                    }
                }
                Console.WriteLine("--------ENDCELLS");
            }
            SySal.DataStreams.OPERALinkedZone.Writer outlzw = new SySal.DataStreams.OPERALinkedZone.Writer(outtlg, worklz.Id, worklz.Extents, worklz.Center, worklz.Transform);
            outlzw.SetZInfo(worklz.Top.TopZ, worklz.Top.BottomZ, worklz.Bottom.TopZ, worklz.Bottom.BottomZ);
            for (i = 0; i < ((SySal.Scanning.Plate.IO.OPERA.LinkedZone.Side)worklz.Top).ViewCount; i++)
            {
                outlzw.AddView(((SySal.Scanning.Plate.IO.OPERA.LinkedZone.Side)worklz.Top).View(i), true);
            }
            for (i = 0; i < ((SySal.Scanning.Plate.IO.OPERA.LinkedZone.Side)worklz.Bottom).ViewCount; i++)
            {
                outlzw.AddView(((SySal.Scanning.Plate.IO.OPERA.LinkedZone.Side)worklz.Bottom).View(i), false);
            }
            SySal.BasicTypes.Vector proj       = new SySal.BasicTypes.Vector();
            Console.WriteLine("Writing flattened TLG...");
            GridInterpolation G = new GridInterpolation(WorkCells, cellsize, RefRect, (int)MinMatches);

            System.DateTime start = System.DateTime.Now;
            for (i = 0; i < worklz.Length; i++)
            {
                if (i % 1000 == 0)
                {
                    System.DateTime nw = System.DateTime.Now;
                    if ((nw - start).TotalMilliseconds >= 10000)
                    {
                        Console.WriteLine((i * 100 / worklz.Length) + "%");
                        start = nw;
                    }
                }
                SySal.Tracking.MIPEmulsionTrackInfo           baseinfo      = worklz[i].Info;
                SySal.DAQSystem.Scanning.IntercalibrationInfo transforminfo = new SySal.DAQSystem.Scanning.IntercalibrationInfo();
                transforminfo.RX = Center.X;
                transforminfo.RY = Center.Y;
                SySal.BasicTypes.Vector tds = new SySal.BasicTypes.Vector();

                G.Evaluate(baseinfo.Intercept.X, baseinfo.Intercept.Y, ref tds, ref transforminfo);

                proj.X             = -baseinfo.Slope.X * transforminfo.TZ;
                proj.Y             = -baseinfo.Slope.Y * transforminfo.TZ;
                proj.Z             = 0.0;
                baseinfo.Intercept = transforminfo.Transform(baseinfo.Intercept) + proj;
                baseinfo.Slope     = transforminfo.Deform(baseinfo.Slope) + tds;
                SySal.Scanning.MIPIndexedEmulsionTrack toptk      = worklz[i].Top;
                SySal.Tracking.MIPEmulsionTrackInfo    topinfo    = toptk.Info;
                SySal.Scanning.MIPIndexedEmulsionTrack bottomtk   = worklz[i].Bottom;
                SySal.Tracking.MIPEmulsionTrackInfo    bottominfo = bottomtk.Info;
                topinfo.Intercept    = transforminfo.Transform(topinfo.Intercept) + proj;
                topinfo.Slope        = transforminfo.Deform(topinfo.Slope) + tds;
                bottominfo.Intercept = transforminfo.Transform(bottominfo.Intercept) + proj;
                bottominfo.Slope     = transforminfo.Deform(bottominfo.Slope) + tds;
                outlzw.AddMIPEmulsionTrack(topinfo, i, ((SySal.Scanning.Plate.IO.OPERA.LinkedZone.MIPIndexedEmulsionTrack)toptk).View.Id, ((SySal.Scanning.Plate.IO.OPERA.LinkedZone.MIPIndexedEmulsionTrack)toptk).OriginalRawData, true);
                outlzw.AddMIPEmulsionTrack(bottominfo, i, ((SySal.Scanning.Plate.IO.OPERA.LinkedZone.MIPIndexedEmulsionTrack)bottomtk).View.Id, ((SySal.Scanning.Plate.IO.OPERA.LinkedZone.MIPIndexedEmulsionTrack)bottomtk).OriginalRawData, false);
                outlzw.AddMIPBasetrack(baseinfo, i, i, i);
            }
            outlzw.Complete();
            Console.WriteLine("Written \"" + outtlg + "\".");
        }