Beispiel #1
0
 private static void applyLhs(
     final float w1,
     final float[][][] wp,
     final float[][][] p2,
     final float[][][] p3,
     final float[][][] x,
     final float[][][] y) {
   final int n3 = x.length;
   Parallel.loop(
       1,
       n3,
       2,
       new Parallel.LoopInt() { // i3 = 1, 3, 5, ...
         public void compute(int i3) {
           applyLhsSlice3(i3, w1, wp, p2, p3, x, y);
         }
       });
   Parallel.loop(
       2,
       n3,
       2,
       new Parallel.LoopInt() { // i3 = 2, 4, 6, ...
         public void compute(int i3) {
           applyLhsSlice3(i3, w1, wp, p2, p3, x, y);
         }
       });
 }
Beispiel #2
0
  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);
  }
Beispiel #3
0
 /**
  * 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;
 }
Beispiel #4
0
  public float[][][][] flattenWithShifts(
      final Sampling s1, final float[][][] r, final float[][][] f) {
    cleanShifts(r);
    final int n3 = r.length;
    final int n2 = r[0].length;
    final int n1 = r[0][0].length;
    // Compute u1(x1,x2,x3).
    final double f1 = s1.getFirst();
    final double d1 = s1.getDelta();
    final float[][][] u1 = r;
    for (int i3 = 0; i3 < n3; ++i3) {
      for (int i2 = 0; i2 < n2; ++i2) {
        for (int i1 = 0; i1 < n1; ++i1) {
          float x1i = (float) (f1 + i1 * d1);
          u1[i3][i2][i1] = (float) (x1i + r[i3][i2][i1] * d1);
        }
      }
    }

    // Compute x1(u1,u2).
    final float[][][] x1 = new float[n3][n2][n1];
    final InverseInterpolator ii = new InverseInterpolator(s1, s1);
    Parallel.loop(
        n3,
        new Parallel.LoopInt() {
          public void compute(int i3) {
            for (int i2 = 0; i2 < n2; ++i2) ii.invert(u1[i3][i2], x1[i3][i2]);
          }
        });

    final SincInterpolator si = new SincInterpolator();
    final float[][][] g = new float[n3][n2][n1];
    Parallel.loop(
        n3,
        new Parallel.LoopInt() {
          public void compute(int i3) {
            for (int i2 = 0; i2 < n2; ++i2)
              si.interpolate(n1, d1, f1, f[i3][i2], n1, x1[i3][i2], g[i3][i2]);
          }
        });
    return new float[][][][] {g, u1};
  }
Beispiel #5
0
 private static void smooth2(final float sigma, final float[][][] s, final float[][][] x) {
   final int n3 = x.length;
   Parallel.loop(
       n3,
       new Parallel.LoopInt() {
         public void compute(int i3) {
           float[][] s3 = (s != null) ? s[i3] : null;
           float[][] x3 = x[i3];
           smooth2(sigma, s3, x3);
         }
       });
 }
Beispiel #6
0
 private void removeAverage(final float[][][] x) {
   final int n1 = x[0][0].length;
   Parallel.loop(
       1,
       n1,
       2,
       new Parallel.LoopInt() { // i1 = 1, 3, 5, ...
         public void compute(int i1) {
           removeAverage(i1, x);
         }
       });
   Parallel.loop(
       2,
       n1,
       2,
       new Parallel.LoopInt() { // i1 = 2, 4, 6, ...
         public void compute(int i1) {
           removeAverage(i1, x);
         }
       });
 }
Beispiel #7
0
  /**
   * Gets mappings computed from specified slopes and planarities.
   *
   * @param s1 sampling of 1st dimension.
   * @param s2 sampling of 2nd dimension.
   * @param p2 array of slopes of image features.
   * @param ep array of planarities of image features.
   */
  public Mappings getMappingsFromSlopes(
      Sampling s1, Sampling s2, Sampling s3, float[][][] p2, float[][][] p3, float[][][] ep) {
    // Sampling parameters.
    final int n1 = s1.getCount();
    final int n2 = s2.getCount();
    final int n3 = s3.getCount();
    float d1 = (float) s1.getDelta();
    float d2 = (float) s2.getDelta();
    float d3 = (float) s3.getDelta();
    float f1 = (float) s1.getFirst();

    // If necessary, convert units for slopes to samples per sample.
    if (d1 != d2) p2 = mul(d2 / d1, p2);
    if (d1 != d3) p3 = mul(d3 / d1, p3);

    // Compute shifts r(x1,x2,x3), in samples.
    float[][][] b = new float[n3][n2][n1]; // right-hand side
    float[][][] r = new float[n3][n2][n1]; // shifts, in samples
    VecArrayFloat3 vb = new VecArrayFloat3(b);
    VecArrayFloat3 vr = new VecArrayFloat3(r);
    Smoother3 smoother3 = new Smoother3(n1, n2, n3, _sigma1, _sigma2, _sigma3, ep);
    A3 a3 = new A3(smoother3, _weight1, ep, p2, p3);
    CgSolver cs = new CgSolver(_small, _niter);
    makeRhs(ep, p2, p3, b);
    smoother3.applyTranspose(b);
    cs.solve(a3, vb, vr);
    smoother3.apply(r);
    cleanShifts(r);

    // Compute u1(x1,x2,x3).
    final float[][][] u1 = r;
    for (int i3 = 0; i3 < n3; ++i3) {
      for (int i2 = 0; i2 < n2; ++i2) {
        for (int i1 = 0; i1 < n1; ++i1) {
          float x1i = f1 + i1 * d1;
          u1[i3][i2][i1] = x1i + r[i3][i2][i1] * d1;
        }
      }
    }

    // Compute x1(u1,u2).
    final float[][][] x1 = b;
    final InverseInterpolator ii = new InverseInterpolator(s1, s1);
    Parallel.loop(
        n3,
        new Parallel.LoopInt() {
          public void compute(int i3) {
            for (int i2 = 0; i2 < n2; ++i2) ii.invert(u1[i3][i2], x1[i3][i2]);
          }
        });

    return new Mappings(s1, s2, s3, u1, x1);
  }
Beispiel #8
0
 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;
 }
Beispiel #9
0
 @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;
 }
Beispiel #10
0
 @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;
 }
Beispiel #11
0
 // Smoothing for dimension 3.
 private static void smooth3(final float sigma, final float[][][] s, final float[][][] x) {
   final int n2 = x[0].length;
   final int n3 = x.length;
   Parallel.loop(
       n2,
       new Parallel.LoopInt() {
         public void compute(int i2) {
           float[][] s2 = (s != null) ? new float[n3][] : null;
           float[][] x2 = new float[n3][];
           for (int i3 = 0; i3 < n3; ++i3) {
             if (s != null) s2[i3] = s[i3][i2];
             x2[i3] = x[i3][i2];
           }
           smooth2(sigma, s2, x2);
         }
       });
 }
Beispiel #12
0
 private float[][][] apply(final float[][][] ux, final float[][][] f) {
   final int n1 = s1.getCount();
   final int n2 = s2.getCount();
   final int n3 = s3.getCount();
   final double d1 = s1.getDelta();
   final double f1 = s1.getFirst();
   final SincInterpolator si = new SincInterpolator();
   final float[][][] g = new float[n3][n2][n1];
   Parallel.loop(
       n3,
       new Parallel.LoopInt() {
         public void compute(int i3) {
           for (int i2 = 0; i2 < n2; ++i2)
             si.interpolate(n1, d1, f1, f[i3][i2], n1, ux[i3][i2], g[i3][i2]);
         }
       });
   return g;
 }
Beispiel #13
0
 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;
           }
         }
       });
 }
Beispiel #14
0
  /**
   * 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;
  }
Beispiel #15
0
 /**
  * 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;
             }
           }
         }
       });
 }
Beispiel #16
0
 public float[][][] findScreenPoints(
     final float smin,
     final float[][][] ss,
     final float[][][] u1,
     final float[][][] u2,
     final float[][][] u3) {
   final int n3 = ss.length;
   final int n2 = ss[0].length;
   final int n1 = ss[0][0].length;
   final Sampling s1 = new Sampling(n1);
   final Sampling s2 = new Sampling(n2);
   final Sampling s3 = new Sampling(n3);
   final float[][][] mk = new float[n3][n2][n1];
   final SincInterpolator si = new SincInterpolator();
   si.setExtrapolation(SincInterpolator.Extrapolation.CONSTANT);
   Parallel.loop(
       1,
       n3 - 1,
       new Parallel.LoopInt() {
         public void compute(int i3) {
           for (int i2 = 1; i2 < n2 - 1; ++i2) {
             for (int i1 = 1; i1 < n1 - 1; ++i1) {
               float sxi = ss[i3][i2][i1];
               float u1i = u1[i3][i2][i1] * 2f;
               float u2i = u2[i3][i2][i1] * 2f;
               float u3i = u3[i3][i2][i1] * 2f;
               float x1m = i1 - u1i;
               float x2m = i2 - u2i;
               float x3m = i3 - u3i;
               float x1p = i1 + u1i;
               float x2p = i2 + u2i;
               float x3p = i3 + u3i;
               float sxm = si.interpolate(s1, s2, s3, ss, x1m, x2m, x3m);
               float sxp = si.interpolate(s1, s2, s3, ss, x1p, x2p, x3p);
               if (sxi > sxm && sxi > sxp && sxi > smin) mk[i3][i2][i1] = sxi;
             }
           }
         }
       });
   return mk;
 }
Beispiel #17
0
  public float[][][] scalarField(final int n1, final int n2, final int n3, FaultCell[] fc) {
    final int d2 = 10;
    final int d3 = 10;
    final int d1 = 20;
    final float v = -1.f;
    float sigmaNor = 4.0f;
    float sigmaPhi = 6.0f;
    float sigmaTheta = 20.0f;
    final float sw = 1.0f / (sigmaNor * sigmaNor);
    final float sv = 1.0f / (sigmaPhi * sigmaPhi);
    final float su = 1.0f / (sigmaTheta * sigmaTheta);
    int nc = fc.length;
    final float[] wp = new float[nc];
    final float[][] xf = new float[3][nc];
    final float[][] xs = new float[nc][6];
    final float[][] ws = new float[nc][6];
    final float[][] us = new float[nc][6];
    final float[][] vs = new float[nc][6];
    setKdTreePoints(fc, xf, xs, ws, us, vs, wp);
    final int[] bs1 = setBounds(n1, xf[0]);
    final int[] bs2 = setBounds(n2, xf[1]);
    final int[] bs3 = setBounds(n3, xf[2]);
    final KdTree kt = new KdTree(xf);
    final float[][][] sf = fillfloat(v, n1, n2, n3);
    Parallel.loop(
        bs3[0],
        bs3[1],
        1,
        new Parallel.LoopInt() {
          public void compute(int i3) {
            float[] xmin = new float[3];
            float[] xmax = new float[3];
            System.out.println("i3=" + i3);
            for (int i2 = bs2[0]; i2 < bs2[1]; ++i2) {
              for (int i1 = bs1[0]; i1 < bs1[1]; ++i1) {
                float[] y = new float[] {i1, i2, i3};
                int ne = kt.findNearest(y);
                float x1 = xf[0][ne];
                float x2 = xf[1][ne];
                float x3 = xf[2][ne];
                float dd = distance(new float[] {x1, x2, x3}, y);
                if (dd > 16.0f) {
                  continue;
                }
                getRange(d1, d2, d3, i1, i2, i3, n1, n2, n3, xmin, xmax);
                int[] id = kt.findInRange(xmin, xmax);
                int nd = id.length;
                if (nd < 50) {
                  continue;
                }
                sf[i3][i2][i1] = 0.0f;
                float wps = 0.0f;
                for (int ik = 0; ik < nd; ++ik) {
                  int ip = id[ik];
                  float wpi = pow(wp[ip], 8.0f);
                  float w1s = ws[ip][0];
                  float w2s = ws[ip][1];
                  float w3s = ws[ip][2];
                  float w12 = ws[ip][3];
                  float w13 = ws[ip][4];
                  float w23 = ws[ip][5];

                  float u1s = us[ip][0];
                  float u2s = us[ip][1];
                  float u3s = us[ip][2];
                  float u12 = us[ip][3];
                  float u13 = us[ip][4];
                  float u23 = us[ip][5];

                  float v1s = vs[ip][0];
                  float v2s = vs[ip][1];
                  float v3s = vs[ip][2];
                  float v12 = vs[ip][3];
                  float v13 = vs[ip][4];
                  float v23 = vs[ip][5];

                  float x1m = i1 - xs[ip][0];
                  float x2m = i2 - xs[ip][1];
                  float x3m = i3 - xs[ip][2];

                  float x1p = i1 - xs[ip][3];
                  float x2p = i2 - xs[ip][4];
                  float x3p = i3 - xs[ip][5];

                  float x1sm = x1m * x1m;
                  float x2sm = x2m * x2m;
                  float x3sm = x3m * x3m;
                  float x12m = x1m * x2m;
                  float x13m = x1m * x3m;
                  float x23m = x2m * x3m;

                  float x1sp = x1p * x1p;
                  float x2sp = x2p * x2p;
                  float x3sp = x3p * x3p;
                  float x12p = x1p * x2p;
                  float x13p = x1p * x3p;
                  float x23p = x2p * x3p;

                  float g11m = w1s * x1sm + w12 * x12m + w13 * x13m;
                  float g12m = u1s * x1sm + u12 * x12m + u13 * x13m;
                  float g13m = v1s * x1sm + v12 * x12m + v13 * x13m;
                  float g21m = w12 * x12m + w2s * x2sm + w23 * x23m;
                  float g22m = u12 * x12m + u2s * x2sm + u23 * x23m;
                  float g23m = v12 * x12m + v2s * x2sm + v23 * x23m;
                  float g31m = w13 * x13m + w23 * x23m + w3s * x3sm;
                  float g32m = u13 * x13m + u23 * x23m + u3s * x3sm;
                  float g33m = v13 * x13m + v23 * x23m + v3s * x3sm;

                  float g11p = w1s * x1sp + w12 * x12p + w13 * x13p;
                  float g12p = u1s * x1sp + u12 * x12p + u13 * x13p;
                  float g13p = v1s * x1sp + v12 * x12p + v13 * x13p;
                  float g21p = w12 * x12p + w2s * x2sp + w23 * x23p;
                  float g22p = u12 * x12p + u2s * x2sp + u23 * x23p;
                  float g23p = v12 * x12p + v2s * x2sp + v23 * x23p;
                  float g31p = w13 * x13p + w23 * x23p + w3s * x3sp;
                  float g32p = u13 * x13p + u23 * x23p + u3s * x3sp;
                  float g33p = v13 * x13p + v23 * x23p + v3s * x3sp;

                  float gssm =
                      (g11m + g21m + g31m) * sw
                          + (g12m + g22m + g32m) * su
                          + (g13m + g23m + g33m) * sv;
                  float gssp =
                      (g11p + g21p + g31p) * sw
                          + (g12p + g22p + g32p) * su
                          + (g13p + g23p + g33p) * sv;

                  sf[i3][i2][i1] += (exp(-gssp) - exp(-gssm)) * wpi;
                  wps += wpi;
                }
                sf[i3][i2][i1] /= wps;
              }
            }
          }
        });
    return sf;
  }
Beispiel #18
0
  public float[][][] scalarFieldM(
      final int n1,
      final int n2,
      final int n3,
      final FaultCell[] fc,
      final float[][][] fp,
      final float[][][] ft) {
    final int d2 = 10;
    final int d3 = 10;
    final int d1 = 10;
    // final float v = -1.f;
    final float v = 0.0f;
    float sigmaNor = 4.0f;
    float sigmaPhi = 10.0f;
    float sigmaTheta = 20.0f;
    final float sw = 1.0f / (sigmaNor * sigmaNor);
    final float sv = 1.0f / (sigmaPhi * sigmaPhi);
    final float su = 1.0f / (sigmaTheta * sigmaTheta);
    int nc = fc.length;
    final float[] wp = new float[nc];
    final float[][] xf = new float[3][nc];
    final float[][] xs = new float[nc][3];
    final float[][] ws = new float[nc][6];
    final float[][] us = new float[nc][6];
    final float[][] vs = new float[nc][6];
    setKdTreePointsM(fc, xf, xs, ws, us, vs, wp);
    final int[] bs1 = setBounds(n1, xf[0]);
    final int[] bs2 = setBounds(n2, xf[1]);
    final int[] bs3 = setBounds(n3, xf[2]);
    final KdTree kt = new KdTree(xf);
    final float[][][] sf = fillfloat(v, n1, n2, n3);
    final float[][][] fpp = copy(fp);
    final float[][][] ftp = copy(ft);
    Parallel.loop(
        bs3[0],
        bs3[1],
        1,
        new Parallel.LoopInt() {
          public void compute(int i3) {
            float[] xmin = new float[3];
            float[] xmax = new float[3];
            System.out.println("i3=" + i3);
            for (int i2 = bs2[0]; i2 < bs2[1]; ++i2) {
              for (int i1 = bs1[0]; i1 < bs1[1]; ++i1) {
                float[] y = new float[] {i1, i2, i3};
                int ne = kt.findNearest(y);
                float x1 = xf[0][ne];
                float x2 = xf[1][ne];
                float x3 = xf[2][ne];
                float dd = distance(new float[] {x1, x2, x3}, y);
                if (dd > 50.0f) {
                  continue;
                }
                getRange(d1, d2, d3, i1, i2, i3, n1, n2, n3, xmin, xmax);
                int[] id = kt.findInRange(xmin, xmax);
                int nd = id.length;
                if (nd < 1) {
                  continue;
                }
                sf[i3][i2][i1] = 0.0f;
                float wps = 0.0f;
                float fpa = 0.0f;
                float fta = 0.0f;
                float fps = 0.0f;
                float fts = 0.0f;
                for (int ik = 0; ik < nd; ++ik) {
                  int ip = id[ik];
                  float wpi = pow(wp[ip], 8.0f);
                  float w1s = ws[ip][0];
                  float w2s = ws[ip][1];
                  float w3s = ws[ip][2];
                  float w12 = ws[ip][3];
                  float w13 = ws[ip][4];
                  float w23 = ws[ip][5];

                  float u1s = us[ip][0];
                  float u2s = us[ip][1];
                  float u3s = us[ip][2];
                  float u12 = us[ip][3];
                  float u13 = us[ip][4];
                  float u23 = us[ip][5];

                  float v1s = vs[ip][0];
                  float v2s = vs[ip][1];
                  float v3s = vs[ip][2];
                  float v12 = vs[ip][3];
                  float v13 = vs[ip][4];
                  float v23 = vs[ip][5];

                  float dx1 = i1 - xs[ip][0];
                  float dx2 = i2 - xs[ip][1];
                  float dx3 = i3 - xs[ip][2];

                  float d11 = dx1 * dx1;
                  float d12 = dx1 * dx2;
                  float d13 = dx1 * dx3;
                  float d22 = dx2 * dx2;
                  float d23 = dx2 * dx3;
                  float d33 = dx3 * dx3;

                  float g11 = w1s * d11 + w12 * d12 + w13 * d13;
                  float g12 = u1s * d11 + u12 * d12 + u13 * d13;
                  float g13 = v1s * d11 + v12 * d12 + v13 * d13;
                  float g21 = w12 * d12 + w2s * d22 + w23 * d23;
                  float g22 = u12 * d12 + u2s * d22 + u23 * d23;
                  float g23 = v12 * d12 + v2s * d22 + v23 * d23;
                  float g31 = w13 * d13 + w23 * d23 + w3s * d33;
                  float g32 = u13 * d13 + u23 * d23 + u3s * d33;
                  float g33 = v13 * d13 + v23 * d23 + v3s * d33;
                  float gss = 0.0f;
                  gss += (g11 + g21 + g31) * sw;
                  gss += (g12 + g22 + g32) * su;
                  gss += (g13 + g23 + g33) * sv;
                  float sfi = exp(-gss) * wpi;
                  sf[i3][i2][i1] += sfi;

                  int j1 = fc[ip].i1;
                  int j2 = fc[ip].i2;
                  int j3 = fc[ip].i3;

                  int k1 = fc[ne].i1;
                  int k2 = fc[ne].i2;
                  int k3 = fc[ne].i3;
                  float fpr = fpp[k3][k2][k1];
                  float fpi = fpp[j3][j2][j1];
                  if (abs(fpr - fpi) <= 30) {
                    fps += sfi;
                    fpa += fpp[j3][j2][j1] * sfi;
                  }
                  fts += sfi;
                  fta += ftp[j3][j2][j1] * sfi;
                  wps += wpi;
                }
                ft[i3][i2][i1] = fta / fts;
                fp[i3][i2][i1] = fpa / fps;
                sf[i3][i2][i1] /= wps;
              }
            }
          }
        });
    return sf;
  }