public static void normalizeErrors( float[][][][] e, final float ignoreMin, final float ignoreMax) { final int nl = e[0][0][0].length; final int n1 = e[0][0].length; final int n2 = e[0].length; final int n3 = e.length; final float[][][][] ef = e; MinMax mm = Parallel.reduce( n3, new Parallel.ReduceInt<MinMax>() { public MinMax compute(int i3) { float emin = Float.MAX_VALUE; float emax = -Float.MAX_VALUE; for (int i2 = 0; i2 < n2; ++i2) { for (int i1 = 0; i1 < n1; ++i1) { for (int il = 0; il < nl; ++il) { float ei = ef[i3][i2][i1][il]; if (ei < emin && ei > ignoreMin) emin = ei; if (ei > emax && ei < ignoreMax) emax = ei; } } } return new MinMax(emin, emax); } public MinMax combine(MinMax mm1, MinMax mm2) { return new MinMax(min(mm1.emin, mm2.emin), max(mm1.emax, mm2.emax)); } }); shiftAndScale(mm.emin, mm.emax, e); }
/** * Applies the shifts {@code u} to the trace {@code g}. * * @param sf the sampling that {@code g} is being warped to. * @param u the shifts to apply to {@code g}. * @param sg the sampling of {@code g}. * @param g the trace to be warped. * @return the warped image. */ public static float[][][] applyShifts( Sampling sf, final float[][][] u, Sampling sg, final float[][][] g) { final int n1 = u[0][0].length; final int n2 = u[0].length; final int n3 = u.length; final int ng = g[0][0].length; final double dg = sg.getDelta(); final double df = sf.getDelta(); final double fg = sg.getDelta(); final double ff = sf.getDelta(); final float[][][] hf = new float[n3][n2][n1]; final SincInterp si = new SincInterp(); int n23 = n3 * n2; Parallel.loop( n23, new Parallel.LoopInt() { public void compute(int i23) { int i2 = i23 % n2; int i3 = i23 / n2; double v = ff; for (int i1 = 0; i1 < n1; i1++, v = ff + i1 * df) { hf[i3][i2][i1] = si.interpolate(ng, dg, fg, g[i3][i2], (float) v + u[i3][i2][i1]); } } }); return hf; }
public static float[][] compositeShifts( final Sampling sf, final float[][] u1, final float[][] u2) { int n2 = u1.length; final float[][] uc = new float[n2][]; Parallel.loop( n2, new Parallel.LoopInt() { public void compute(int i2) { uc[i2] = compositeShifts(sf, u1[i2], u2[i2]); } }); return uc; }
@Deprecated public static float[][][] transposeLag23(final float[][][] e) { final int nl = e[0][0].length; final int n1 = e[0].length; final int n2 = e.length; final float[][][] t = new float[n1][n2][nl]; Parallel.loop( n1, new Parallel.LoopInt() { public void compute(int i1) { for (int i2 = 0; i2 < n2; ++i2) t[i1][i2] = e[i2][i1]; } }); return t; }
@Deprecated public static float[][][] transposeLag12(final float[][][] e) { final int nl = e[0][0].length; final int n1 = e[0].length; final int n2 = e.length; final float[][][] t = new float[n2][nl][n1]; Parallel.loop( n2, new Parallel.LoopInt() { public void compute(int i2) { for (int il = 0; il < nl; ++il) for (int i1 = 0; i1 < n1; ++i1) t[i2][il][i1] = e[i2][i1][il]; } }); return t; }
/** * Computes the NRMS value of the warped PS trace {@code h} and the PP trace {@code f}. The NRMS * value is the RMS of the difference between {@code f} and {@code h} divided by the average RMS * of {@code f} and {@code h}. * * @param n1Max the length of {@code f} and {@code h} to use for this computation. * @param f the PP traces. * @param h the warped PS traces. * @return the NRMS value, this measure is between 0.0 and 2.0. */ public static float computeNrms(final int n1Max, final float[][][] f, final float[][][] h) { int n1f = f[0][0].length; int n1h = h[0][0].length; Check.argument(n1Max <= n1f, "n1Max<=n1f"); Check.argument(n1Max <= n1h, "n1Max<=n1h"); final int n3 = f.length; final int n2 = f[0].length; final int n23 = n2 * n3; float scale = 1.0f / (n1Max * n23); float[] rms = Parallel.reduce( n23, new Parallel.ReduceInt<float[]>() { @Override public float[] compute(int i23) { int i2 = i23 % n2; int i3 = i23 / n2; float[] fhdSq = new float[3]; for (int i1 = 0; i1 < n1Max; i1++) { float fv = f[i3][i2][i1]; float hv = h[i3][i2][i1]; fhdSq[0] += fv * fv; fhdSq[1] += hv * hv; fhdSq[2] += (hv - fv) * (hv - fv); } return fhdSq; } @Override public float[] combine(float[] fhdSq1, float[] fhdSq2) { float[] rms = new float[3]; rms[0] = fhdSq1[0] + fhdSq2[0]; rms[1] = fhdSq1[1] + fhdSq2[1]; rms[2] = fhdSq1[2] + fhdSq2[2]; return rms; } }); float frms = sqrt(rms[0] * scale); float hrms = sqrt(rms[1] * scale); float drms = sqrt(rms[2] * scale); float nrms = (2.0f * drms) / (frms + hrms); return nrms; }
public static void normalize(float[][] f, final float nmin, final float nmax) { final int n1 = f[0].length; final int n2 = f.length; final float[][] ff = f; final float vmin = min(f); final float vmax = max(f); final float range = vmax - vmin; final float nrange = nmax - nmin; Parallel.loop( n2, new Parallel.LoopInt() { public void compute(int i2) { for (int i1 = 0; i1 < n1; ++i1) { float vi = ff[i2][i1]; ff[i2][i1] = nrange * (vi - vmin) / range + nmin; } } }); }
/** * Shifts and scales alignment errors to be in range [0,1]. * * @param emin minimum alignment error before normalizing. * @param emax maximum alignment error before normalizing. * @param e input/output array of alignment errors. */ private static void shiftAndScale(float emin, float emax, float[][][] e) { // System.out.println("shiftAndScale: emin="+emin+" emax="+emax); final int nl = e[0][0].length; final int n1 = e[0].length; final int n2 = e.length; final float eshift = emin; final float escale = (emax > emin) ? 1.0f / (emax - emin) : 1.0f; final float[][][] ef = e; Parallel.loop( n2, new Parallel.LoopInt() { public void compute(int i2) { for (int i1 = 0; i1 < n1; ++i1) { for (int il = 0; il < nl; ++il) { ef[i2][i1][il] = (ef[i2][i1][il] - eshift) * escale; } } } }); }