/// <summary> /// Builds a DCT-interpolated image. /// </summary> /// <param name="info">format of the image.</param> /// <param name="xwaves">number of X waves.</param> /// <param name="ywaves">number of Y waves.</param> /// <param name="pval">the values of a set of sampled points.</param> public DCTInterpolationImage(SySal.Imaging.ImageInfo info, int xwaves, int ywaves, PointValue[] pval) : base(info, new DCT(info.BitsPerPixel / 8, xwaves, ywaves, info.Width, info.Height, pval)) { XWaves = xwaves; YWaves = ywaves; PointValues = pval; NumericalTools.AdvancedFitting.LeastSquares lsq = new NumericalTools.AdvancedFitting.LeastSquares(); NumericalTools.Minimization.ITargetFunction dct = (NumericalTools.Minimization.ITargetFunction)Pixels; double[][] indep = new double[pval.Length][]; double[] dep = new double[pval.Length]; double[] deperr = new double[pval.Length]; int i; for (i = 0; i < indep.Length; i++) { indep[i] = new double[2] { pval[i].X, pval[i].Y }; dep[i] = pval[i].Value; deperr[i] = 1.0; } double[] p = lsq.Fit(dct, xwaves * ywaves, indep, dep, deperr, 10); ((DCT)dct).ParamValues = p; ((DCT)dct).MakeCosValues(); ((DCT)dct).m_CachedValues = new int[info.Width * info.Height]; System.Threading.Thread[] hcomp_Threads = new System.Threading.Thread[info.Height]; int iiy; for (iiy = 0; iiy < info.Height; iiy++) { hcomp_Threads[iiy] = new System.Threading.Thread(new System.Threading.ParameterizedThreadStart(delegate(object oiiiy) { int iiiy = (int)oiiiy; int iix, ix, iy; for (iix = 0; iix < info.Width; iix++) { double dv = 0.0; for (ix = 0; ix < XWaves; ix++) { for (iy = 0; iy < YWaves; iy++) { dv += ((DCT)dct).ParamValues[iy * XWaves + ix] * ((DCT)dct).XCosValues[ix, iix] * ((DCT)dct).YCosValues[iy, iiiy]; } } ((DCT)dct).m_CachedValues[iiiy * info.Width + iix] = (int)Math.Round(dv); } })); hcomp_Threads[iiy].Start(iiy); } for (iiy = 0; iiy < info.Height; iiy++) { hcomp_Threads[iiy].Join(); hcomp_Threads[iiy] = null; } }
/// <summary> /// Computes the momentum and confidence limits using positions and slopes provided. /// </summary> /// <param name="data">the position and slopes of the track (even Z-unordered). The <c>Field</c> member is used to define the plate.</param> /// <returns>the momentum and confidence limits.</returns> public MomentumResult ProcessData(SySal.Tracking.MIPEmulsionTrackInfo[] data) { int i; MomentumResult result = new MomentumResult(); System.Collections.ArrayList tr = new System.Collections.ArrayList(); tr.AddRange(data); tr.Sort(new DataSorter()); int nseg = tr.Count; int npl = (int)(((SySal.Tracking.MIPEmulsionTrackInfo)tr[tr.Count - 1]).Field - ((SySal.Tracking.MIPEmulsionTrackInfo)tr[0]).Field) + 1; if (nseg < 2) { throw new Exception("PMSang - Warning! nseg < 2 (" + nseg + ")- impossible to estimate momentum!"); } if (npl < nseg) { throw new Exception("PMSang - Warning! npl < nseg (" + npl + ", " + nseg + ")"); } int plmax = (int)((SySal.Tracking.MIPEmulsionTrackInfo)tr[tr.Count - 1]).Field + 1; if (plmax < 1 || plmax > 1000) { throw new Exception("PMSang - Warning! plmax = " + plmax + " - correct the segments PID's!"); } float xmean, ymean, zmean, txmean, tymean, wmean; float xmean0, ymean0, zmean0, txmean0, tymean0, wmean0; FitTrackLine(tr, out xmean0, out ymean0, out zmean0, out txmean0, out tymean0, out wmean0); float tmean = (float)Math.Sqrt(txmean0 * txmean0 + tymean0 * tymean0); SySal.Tracking.MIPEmulsionTrackInfo aas; float sigmax = 0, sigmay = 0; for (i = 0; i < tr.Count; i++) { aas = (SySal.Tracking.MIPEmulsionTrackInfo)tr[i]; sigmax += (float)((txmean0 - aas.Slope.X) * (txmean0 - aas.Slope.X)); sigmay += (float)((tymean0 - aas.Slope.Y) * (tymean0 - aas.Slope.Y)); } sigmax = (float)(Math.Sqrt(sigmax / tr.Count)); sigmay = (float)(Math.Sqrt(sigmay / tr.Count)); for (i = 0; i < tr.Count; i++) { aas = (SySal.Tracking.MIPEmulsionTrackInfo)tr[i]; if (Math.Abs(aas.Slope.X - txmean0) > 3 * sigmax || Math.Abs(aas.Slope.Y - tymean0) > 3 * sigmay) { aas.Slope.X = 0; aas.Slope.Y = 0; } } FitTrackLine(tr, out xmean0, out ymean0, out zmean0, out txmean0, out tymean0, out wmean0); float PHI = (float)Math.Atan2(txmean0, tymean0); for (i = 0; i < tr.Count; i++) { aas = (SySal.Tracking.MIPEmulsionTrackInfo)tr[i]; float slx = (float)(aas.Slope.Y * Math.Cos(-PHI) - aas.Slope.X * Math.Sin(-PHI)); float sly = (float)(aas.Slope.X * Math.Cos(-PHI) + aas.Slope.Y * Math.Sin(-PHI)); aas.Slope.X = slx; aas.Slope.Y = sly; } FitTrackLine(tr, out xmean, out ymean, out zmean, out txmean, out tymean, out wmean); // -- start calcul -- int minentr = C.MinEntries; // min number of entries in the cell to accept the cell for fitting int stepmax = npl - 1; //npl/minentr; // max step int size = stepmax + 1; // vectors size int maxcell = 14; double[] da = new double[Math.Min(size, maxcell)]; double[] dax = new double[Math.Min(size, maxcell)]; double[] day = new double[Math.Min(size, maxcell)]; int[] nentr = new int[Math.Min(size, maxcell)]; int[] nentrx = new int[Math.Min(size, maxcell)]; int[] nentry = new int[Math.Min(size, maxcell)]; SySal.Tracking.MIPEmulsionTrackInfo s1, s2; int ist; for (ist = 1; ist <= stepmax; ist++) // cycle by the step size { int i1; for (i1 = 0; i1 < nseg - 1; i1++) // cycle by the first seg { s1 = (SySal.Tracking.MIPEmulsionTrackInfo)tr[i1]; /* ???? KRYSS: how could this be null ???? if(!s1) continue; */ int i2; for (i2 = i1 + 1; i2 < nseg; i2++) // cycle by the second seg { s2 = (SySal.Tracking.MIPEmulsionTrackInfo)tr[i2]; /* ???? KRYSS: how could this be null ???? if(!s2) continue; */ int icell = (int)Math.Abs(s2.Field - s1.Field); if (icell > maxcell) { continue; } if (icell == ist) { if (s2.Slope.X != 0 && s1.Slope.X != 0) { dax[icell - 1] += (float)((Math.Atan(s2.Slope.X) - Math.Atan(s1.Slope.X)) * (Math.Atan(s2.Slope.X) - Math.Atan(s1.Slope.X))); nentrx[icell - 1] += 1; } if (s2.Slope.Y != 0 && s1.Slope.Y != 0) { day[icell - 1] += (float)((Math.Atan(s2.Slope.Y) - Math.Atan(s1.Slope.Y)) * (Math.Atan(s2.Slope.Y) - Math.Atan(s1.Slope.Y))); nentry[icell - 1] += 1; } if (s2.Slope.X != 0.0 && s1.Slope.X != 0.0 && s2.Slope.Y != 0.0 && s1.Slope.Y != 0.0) { da[icell - 1] += (float)(((Math.Atan(s2.Slope.X) - Math.Atan(s1.Slope.X)) * (Math.Atan(s2.Slope.X) - Math.Atan(s1.Slope.X))) + ((Math.Atan(s2.Slope.Y) - Math.Atan(s1.Slope.Y)) * (Math.Atan(s2.Slope.Y) - Math.Atan(s1.Slope.Y)))); nentr[icell - 1] += 1; } } } } } if (m_DiffLog != null) { m_DiffLog.WriteLine("Entries: " + da.Length); int u; m_DiffLog.WriteLine("3D"); for (u = 0; u < nentr.Length; u++) { m_DiffLog.WriteLine(u + " " + nentr[u] + " " + da[u]); } m_DiffLog.WriteLine("Longitudinal"); for (u = 0; u < nentrx.Length; u++) { m_DiffLog.WriteLine(u + " " + nentrx[u] + " " + dax[u]); } m_DiffLog.WriteLine("Transverse"); for (u = 0; u < nentry.Length; u++) { m_DiffLog.WriteLine(u + " " + nentry[u] + " " + day[u]); } m_DiffLog.Flush(); } float Zcorr = (float)Math.Sqrt(1 + txmean0 * txmean0 + tymean0 * tymean0); // correction due to non-zero track angle and crossed lead thickness int maxX = 0, maxY = 0, max3D = 0; // maximum value for the function fit double[][] vindx = new double[Math.Min(size, maxcell)][]; double[][] errvindx = new double[Math.Min(size, maxcell)][]; double[][] vindy = new double[Math.Min(size, maxcell)][]; double[][] errvindy = new double[Math.Min(size, maxcell)][]; double[][] vind3d = new double[Math.Min(size, maxcell)][]; double[][] errvind3d = new double[Math.Min(size, maxcell)][]; double[] errda = new double[Math.Min(size, maxcell)]; double[] errdax = new double[Math.Min(size, maxcell)]; double[] errday = new double[Math.Min(size, maxcell)]; System.Collections.ArrayList ar_vindx = new System.Collections.ArrayList(); System.Collections.ArrayList ar_errvindx = new System.Collections.ArrayList(); System.Collections.ArrayList ar_vindy = new System.Collections.ArrayList(); System.Collections.ArrayList ar_errvindy = new System.Collections.ArrayList(); System.Collections.ArrayList ar_vind3d = new System.Collections.ArrayList(); System.Collections.ArrayList ar_errvind3d = new System.Collections.ArrayList(); System.Collections.ArrayList ar_da = new System.Collections.ArrayList(); System.Collections.ArrayList ar_dax = new System.Collections.ArrayList(); System.Collections.ArrayList ar_day = new System.Collections.ArrayList(); System.Collections.ArrayList ar_errda = new System.Collections.ArrayList(); System.Collections.ArrayList ar_errdax = new System.Collections.ArrayList(); System.Collections.ArrayList ar_errday = new System.Collections.ArrayList(); ist = 0; int ist1 = 0, ist2 = 0; // use the counter for case of missing cells for (i = 0; i < vind3d.Length /* size */; i++) { if (nentrx[i] >= minentr && Math.Abs(dax[i]) < 0.1) { if (ist >= vindx.Length) { continue; } ar_vindx.Add(new double[1] { i + 1 }); ar_errvindx.Add(new double[1] { .25 }); ar_dax.Add(Math.Sqrt(dax[i] / (nentrx[i] * Zcorr))); ar_errdax.Add((double)ar_dax[ar_dax.Count - 1] / Math.Sqrt(2 * nentrx[i])); ist++; maxX = ist; } if (nentry[i] >= minentr && Math.Abs(day[i]) < 0.1) { if (ist1 >= vindy.Length) { continue; } ar_vindy.Add(new double[1] { i + 1 }); ar_errvindy.Add(new double[1] { .25 }); ar_day.Add(Math.Sqrt(day[i] / (nentry[i] * Zcorr))); ar_errday.Add((double)ar_day[ar_day.Count - 1] / Math.Sqrt(2 * nentry[i])); ist1++; maxY = ist1; } if (nentr[i] >= minentr / 2 && Math.Abs(da[i]) < 0.1) { if (ist2 >= vind3d.Length) { continue; } ar_vind3d.Add(new double[1] { i + 1 }); ar_errvind3d.Add(new double[1] { .25 }); ar_da.Add(Math.Sqrt(da[i] / (2 * nentr[i] * Zcorr))); ar_errda.Add((double)ar_da[ar_da.Count - 1] / Math.Sqrt(4 * nentr[i])); ist2++; max3D = ist2; } } vindx = (double[][])ar_vindx.ToArray(typeof(double[])); vindy = (double[][])ar_vindy.ToArray(typeof(double[])); vind3d = (double[][])ar_vind3d.ToArray(typeof(double[])); errvindx = (double[][])ar_errvindx.ToArray(typeof(double[])); errvindy = (double[][])ar_errvindy.ToArray(typeof(double[])); errvind3d = (double[][])ar_errvind3d.ToArray(typeof(double[])); da = (double[])ar_da.ToArray(typeof(double)); dax = (double[])ar_dax.ToArray(typeof(double)); day = (double[])ar_day.ToArray(typeof(double)); errda = (double[])ar_errda.ToArray(typeof(double)); errdax = (double[])ar_errdax.ToArray(typeof(double)); errday = (double[])ar_errday.ToArray(typeof(double)); float dt = (float)(C.SlopeError3D_0 + C.SlopeError3D_1 * Math.Abs(tmean) + C.SlopeError3D_2 * tmean * tmean); // measurements errors parametrization dt *= dt; float dtx = (float)(C.SlopeErrorLong_0 + C.SlopeErrorLong_1 * Math.Abs(txmean) + C.SlopeErrorLong_2 * txmean * txmean); // measurements errors parametrization dtx *= dtx; float dty = (float)(C.SlopeErrorTransv_0 + C.SlopeErrorTransv_1 * Math.Abs(tymean) + C.SlopeErrorTransv_2 * tymean * tymean); // measurements errors parametrization dty *= dty; float x0 = (float)(C.RadiationLength / 1000); // the fit results float ePx = 0.0f, ePy = 0.0f; // the estimated momentum float eDPx = 0.0f, eDPy = 0.0f; // the fit error float ePXmin = 0.0f, ePXmax = 0.0f; // momentum 90% errors range float ePYmin = 0.0f, ePYmax = 0.0f; // momentum 90% errors range // the output of PMSang float eP = 0.0f, eDP = 0.0f; float ePmin = 0.0f, ePmax = 0.0f; // momentum 90% errors range /* * eF1X = MCSErrorFunction("eF1X",x0,dtx); eF1X->SetRange(0,14); * eF1X->SetParameter(0,2000.); // starting value for momentum in GeV * eF1Y = MCSErrorFunction("eF1Y",x0,dty); eF1Y->SetRange(0,14); * eF1Y->SetParameter(0,2000.); // starting value for momentum in GeV * eF1 = MCSErrorFunction("eF1",x0,dt); eF1->SetRange(0,14); * eF1->SetParameter(0,2000.); // starting value for momentum in GeV */ NumericalTools.AdvancedFitting.LeastSquares LSF = new NumericalTools.AdvancedFitting.LeastSquares(); LSF.Logger = m_FitLog; float chi2_3D = -1.0f; float chi2_T = -1.0f; float chi2_L = -1.0f; if (max3D > 0) { try { LSF.Fit(new MyNF(x0, dt), 1, vind3d, da, errvind3d, errda, 100); eP = (float)(1.0f / 1000.0f * Math.Abs(LSF.BestFit[0])); eDP = (float)(1.0f / 1000.0f * LSF.StandardErrors[0]); EstimateMomentumError(eP, npl, tymean, out ePmin, out ePmax); chi2_3D = (float)LSF.EstimatedVariance; } catch (Exception) { ePmin = ePmax = eP = -99; } } if (maxX > 0) { try { LSF.Fit(new MyNF(x0, dtx), 1, vindx, dax, errvindx, errdax, 100); ePx = (float)(1.0f / 1000.0f * Math.Abs(LSF.BestFit[0])); eDPx = (float)(1.0f / 1000.0f * LSF.StandardErrors[0]); EstimateMomentumError(ePx, npl, txmean, out ePXmin, out ePXmax); chi2_L = (float)LSF.EstimatedVariance; } catch (Exception) { ePXmin = ePXmax = ePx = -99; } } if (maxY > 0) { try { LSF.Fit(new MyNF(x0, dty), 1, vindy, day, errvindy, errday, 100); ePy = (float)(1.0f / 1000.0f * Math.Abs(LSF.BestFit[0])); eDPy = (float)(1.0f / 1000.0f * LSF.StandardErrors[0]); EstimateMomentumError(ePy, npl, tmean, out ePYmin, out ePYmax); chi2_T = (float)LSF.EstimatedVariance; } catch (Exception) { ePYmin = ePYmax = ePy = -99; } } result.ConfidenceLevel = 0.90; if (!C.IgnoreLongitudinal && !C.IgnoreTransverse) { result.Value = Math.Round(eP / 0.01) * 0.01; result.LowerBound = Math.Round(ePmin / 0.01) * 0.01; result.UpperBound = Math.Round(ePmax / 0.01) * 0.01; if (tmean > 0.2 && ((chi2_T >= 0.0 && chi2_T < chi2_3D) || (chi2_3D < 0.0 && chi2_T >= 0.0))) { result.Value = Math.Round(ePy / 0.01) * 0.01; result.LowerBound = Math.Round(ePYmin / 0.01) * 0.01; result.UpperBound = Math.Round(ePYmax / 0.01) * 0.01; } } else if (!C.IgnoreTransverse && C.IgnoreLongitudinal) { result.Value = Math.Round(ePy / 0.01) * 0.01; result.LowerBound = Math.Round(ePYmin / 0.01) * 0.01; result.UpperBound = Math.Round(ePYmax / 0.01) * 0.01; } else if (!C.IgnoreLongitudinal && C.IgnoreTransverse) { result.Value = Math.Round(ePx / 0.01) * 0.01; result.LowerBound = Math.Round(ePXmin / 0.01) * 0.01; result.UpperBound = Math.Round(ePXmax / 0.01) * 0.01; } else { result.Value = result.LowerBound = result.UpperBound = -99; throw new Exception("Both projections are disabled in scattering estimation!"); } return(result); }