private void check(final Image real, final Image imag, final Axes axes) { messenger.log("Real input image of type " + real.type()); messenger.log("Imaginary input image of type " + imag.type()); final Dimensions rdims = real.dimensions(); final Dimensions idims = imag.dimensions(); if (!rdims.equals(idims)) throw new IllegalStateException("Real and imaginary images have different dimensions"); if (axes.x && !FMath.power2(rdims.x)) throw new IllegalStateException("Real and imaginary x-size not a power of 2"); if (axes.y && !FMath.power2(rdims.y)) throw new IllegalStateException("Real and imaginary y-size not a power of 2"); if (axes.z && !FMath.power2(rdims.z)) throw new IllegalStateException("Real and imaginary z-size not a power of 2"); if (axes.t && !FMath.power2(rdims.t)) throw new IllegalStateException("Real and imaginary t-size not a power of 2"); if (axes.c && !FMath.power2(rdims.c)) throw new IllegalStateException("Real and imaginary c-size not a power of 2"); }
public Image run(final Image image, final double scale) { System.out.println(scale); if (scale <= 0) throw new IllegalArgumentException("Smoothing scale less than or equal to 0"); final Dimensions dims = image.dimensions(); final Aspects asps = image.aspects(); if (asps.x <= 0) throw new IllegalStateException("Aspect-ratio value in x-dimension less than or equal to 0"); if (asps.y <= 0) throw new IllegalStateException("Aspect-ratio value in y-dimension less than or equal to 0"); if (asps.z <= 0) throw new IllegalStateException("Aspect-ratio value in z-dimension less than or equal to 0"); /* * It's very important to annotate whether it is a reference soft copy * or a deep copy. The code shows if image is the type of FloatImage, * just use the "object" if not, create a new FloatImage object which * don't share the pixels data. */ final Image smoothImage = (image instanceof FloatImage) ? image : new FloatImage(image); // It's relationship of Deep Copy not just Reference final Image Hxx = differentiator.run(smoothImage.duplicate(), scale, 2, 0, 0); final Image Hxy = differentiator.run(smoothImage.duplicate(), scale, 1, 1, 0); final Image Hxz = differentiator.run(smoothImage.duplicate(), scale, 1, 0, 1); final Image Hyy = differentiator.run(smoothImage.duplicate(), scale, 0, 2, 0); final Image Hyz = differentiator.run(smoothImage.duplicate(), scale, 0, 1, 1); final Image Hzz = differentiator.run(smoothImage, scale, 0, 0, 2); Hxx.axes(Axes.X); Hxy.axes(Axes.X); Hxz.axes(Axes.X); Hyy.axes(Axes.X); Hyz.axes(Axes.X); Hzz.axes(Axes.X); final double[] ahxx = new double[dims.x]; final double[] ahxy = new double[dims.x]; final double[] ahxz = new double[dims.x]; final double[] ahyy = new double[dims.x]; final double[] ahyz = new double[dims.x]; final double[] ahzz = new double[dims.x]; final Coordinates coords = new Coordinates(); for (coords.c = 0; coords.c < dims.c; ++coords.c) for (coords.t = 0; coords.t < dims.t; ++coords.t) for (coords.z = 0; coords.z < dims.z; ++coords.z) for (coords.y = 0; coords.y < dims.y; ++coords.y) { Hxx.get(coords, ahxx); Hxy.get(coords, ahxy); Hxz.get(coords, ahxz); Hyy.get(coords, ahyy); Hyz.get(coords, ahyz); Hzz.get(coords, ahzz); for (int x = 0; x < dims.x; ++x) { final double fhxx = ahxx[x]; final double fhxy = ahxy[x]; final double fhxz = ahxz[x]; final double fhyy = ahyy[x]; final double fhyz = ahyz[x]; final double fhzz = ahzz[x]; final double a = -(fhxx + fhyy + fhzz); final double b = fhxx * fhyy + fhxx * fhzz + fhyy * fhzz - fhxy * fhxy - fhxz * fhxz - fhyz * fhyz; final double c = fhxx * (fhyz * fhyz - fhyy * fhzz) + fhyy * fhxz * fhxz + fhzz * fhxy * fhxy - 2 * fhxy * fhxz * fhyz; final double q = (a * a - 3 * b) / 9; final double r = (a * a * a - 4.5 * a * b + 13.5 * c) / 27; final double sqrtq = (q > 0) ? Math.sqrt(q) : 0; final double sqrtq3 = sqrtq * sqrtq * sqrtq; double absh1, absh2, absh3; double value1, value2, value3; if (sqrtq3 == 0) { absh1 = absh2 = absh3 = 0; value1 = value2 = value3 = 0; } else { final double rsqq3 = r / sqrtq3; final double angle = (rsqq3 * rsqq3 <= 1) ? Math.acos(rsqq3) : Math.acos(rsqq3 < 0 ? -1 : 1); value1 = -2 * sqrtq * Math.cos(angle / 3) - a / 3; value2 = -2 * sqrtq * Math.cos((angle + TWOPI) / 3) - a / 3; value3 = -2 * sqrtq * Math.cos((angle - TWOPI) / 3) - a / 3; absh1 = Math.abs(value1); absh2 = Math.abs(value2); absh3 = Math.abs(value3); } // get the characteristic value's absolute value be ordered by |a1| >= |a2| >= |a3| if (absh2 < absh3) { final double tmp = value2; value2 = value3; value3 = tmp; } if (absh1 < absh2) { final double tmp1 = value1; value1 = value2; value2 = tmp1; if (absh2 < absh3) { final double tmp2 = value2; value2 = value3; value3 = tmp2; } } ahxx[x] = frangi(value1, value2, value3); } Hxx.set(coords, ahxx); } return Hxx; }
/** * Finds local extrema in an image. A local extremum is defined as an image element whose value is * either larger (maximum) or smaller (minimum) than those of all its neighboring elements. If the * size of the image in the z-dimension equals {@code 1}, this method considers 8-connected * neighbors in x-y space, otherwise it considers 26-connected neighbors in x-y-z space. For * border elements, neighboring positions outside the image are ignored. The method searches for * local extrema in every x-y(-z) subimage in a 5D image. * * @param image the input image in which local extrema are to be found. * @param type the type of extrema to be found. Can be any or both (by addition) of {@link * #MAXIMA} or {@link #MINIMA}. * @param mode determines how the found extrema are stored and returned. Can be any or both (by * addition) of {@link #DETECT} or {@link #EXTRACT}. * @return if {@code mode} includes {@code DETECT}, the {@code image} is overwritten with the * detection results: local maxima are set to {@code 255}, local minima to {@code 127}, and * all other elements to {@code 0}. Otherwise the image is left unaltered. If {@code mode} * includes {@code EXTRACT}, a new two-element {@code Vector} of {@code Vector<Coordinates>} * objects is returned, containing the coordinates of all found local maxima (element {@code * 0}) and local minima (element {@code 1}). Otherwise the method returns {@code null}. * @exception NullPointerException if {@code image} is {@code null}. */ public Vector<Vector<Coordinates>> run(final Image image, final int type, final int mode) { messenger.log(ImageScience.prelude() + "Extremizer"); final Timer timer = new Timer(); timer.messenger.log(messenger.log()); timer.start(); // Initialize: final Dimensions dims = image.dimensions(); messenger.log( "Input image dimensions: (x,y,z,t,c) = (" + dims.x + "," + dims.y + "," + dims.z + "," + dims.t + "," + dims.c + ")"); final boolean detect = (mode & DETECT) > 0; final boolean extract = (mode & EXTRACT) > 0; String detex = null; if (detect) { detex = extract ? "Detecting and extracting" : "Detecting"; } else if (extract) { detex = "Extracting"; } else { messenger.log("Neither detection nor extraction mode was selected"); return null; } final boolean maxima = (type & MAXIMA) > 0; final boolean minima = (type & MINIMA) > 0; String maxmin = null; if (maxima) { maxmin = minima ? "maxima and minima" : "maxima"; } else if (minima) { maxmin = "minima"; } else { messenger.log("Neither maxima nor minima type was selected"); return null; } final String demm = detex + " " + maxmin; final Vector<Coordinates> camax = extract ? new Vector<Coordinates>(dims.x, dims.x) : null; final Vector<Coordinates> camin = extract ? new Vector<Coordinates>(dims.x, dims.x) : null; messenger.status("Finding extrema..."); // Find extrema: if (dims.z == 1) { // 2D case messenger.log(demm + " in 2D using 8-connectivity"); progressor.steps(dims.c * dims.t * dims.y); progressor.start(); image.axes(Axes.X); final Coordinates c0 = new Coordinates(); c0.x = -1; final Coordinates c1 = new Coordinates(); c1.x = -1; double[] mm = new double[dims.x + 2]; double[] a0 = new double[dims.x + 2]; double[] a1 = new double[dims.x + 2]; double[] a2 = new double[dims.x + 2]; double[] at = null; final int dimsxp1 = dims.x + 1; final int dimsym1 = dims.y - 1; final boolean dimsyis1 = (dims.y == 1); for (c0.c = c1.c = 0; c0.c < dims.c; ++c0.c, ++c1.c) { for (c0.t = c1.t = 0; c0.t < dims.t; ++c0.t, ++c1.t) { for (c0.y = 0, c1.y = 1; c0.y < dims.y; ++c0.y, ++c1.y) { set(mm, NEX); if (c0.y == 0) { image.get(c0, a1); if (!dimsyis1) image.get(c1, a2); } else { at = a0; a0 = a1; a1 = a2; a2 = at; if (c0.y < dimsym1) image.get(c1, a2); } // Find maxima: if (maxima) { if (c0.y == 0) { set(a0, DMIN); if (dimsyis1) set(a2, DMIN); } else if (c0.y == dimsym1) set(a2, DMIN); border(a0, DMIN); border(a1, DMIN); border(a2, DMIN); for (int x = 1, xm1 = 0, xp1 = 2; x < dimsxp1; ++x, ++xm1, ++xp1) { final double vx = a1[x]; if (vx > a0[xm1] && vx > a0[x] && vx > a0[xp1] && vx > a2[xm1] && vx > a2[x] && vx > a2[xp1] && vx > a1[xm1] && vx > a1[xp1]) { if (extract) camax.add(new Coordinates(xm1, c0.y, 0, c0.t, c0.c)); mm[x] = MAX; } } } // Find minima: if (minima) { if (c0.y == 0) { set(a0, DMAX); if (dimsyis1) set(a2, DMAX); } else if (c0.y == dimsym1) set(a2, DMAX); border(a0, DMAX); border(a1, DMAX); border(a2, DMAX); for (int x = 1, xm1 = 0, xp1 = 2; x < dimsxp1; ++x, ++xm1, ++xp1) { final double vx = a1[x]; if (vx < a0[xm1] && vx < a0[x] && vx < a0[xp1] && vx < a2[xm1] && vx < a2[x] && vx < a2[xp1] && vx < a1[xm1] && vx < a1[xp1]) { if (extract) camin.add(new Coordinates(xm1, c0.y, 0, c0.t, c0.c)); mm[x] = MIN; } } } if (detect) image.set(c0, mm); progressor.step(); } } } } else { // 3D case messenger.log(demm + " in 3D using 26-connectivity"); final int ysteps = (maxima ? dims.y : 0) + (minima ? dims.y : 0); progressor.steps(dims.c * dims.t * dims.z * ysteps); progressor.start(); image.axes(Axes.X + Axes.Y); final Coordinates c0 = new Coordinates(); c0.x = c0.y = -1; final Coordinates c1 = new Coordinates(); c1.x = c1.y = -1; double[][] mm = new double[dims.y + 2][dims.x + 2]; double[][] a0 = new double[dims.y + 2][dims.x + 2]; double[][] a1 = new double[dims.y + 2][dims.x + 2]; double[][] a2 = new double[dims.y + 2][dims.x + 2]; double[][] at = null; final int dimsxp1 = dims.x + 1; final int dimsyp1 = dims.y + 1; final int dimszm1 = dims.z - 1; for (c0.c = c1.c = 0; c0.c < dims.c; ++c0.c, ++c1.c) { for (c0.t = c1.t = 0; c0.t < dims.t; ++c0.t, ++c1.t) { for (c0.z = 0, c1.z = 1; c0.z < dims.z; ++c0.z, ++c1.z) { set(mm, NEX); if (c0.z == 0) { image.get(c0, a1); image.get(c1, a2); } else { at = a0; a0 = a1; a1 = a2; a2 = at; if (c0.z < dimszm1) image.get(c1, a2); } // Find maxima: if (maxima) { if (c0.z == 0) set(a0, DMIN); else if (c0.z == dimszm1) set(a2, DMIN); border(a0, DMIN); border(a1, DMIN); border(a2, DMIN); for (int y = 1, ym1 = 0, yp1 = 2; y < dimsyp1; ++y, ++ym1, ++yp1) { final double[] a0ym1 = a0[ym1], a0y = a0[y], a0yp1 = a0[yp1]; final double[] a1ym1 = a1[ym1], a1y = a1[y], a1yp1 = a1[yp1]; final double[] a2ym1 = a2[ym1], a2y = a2[y], a2yp1 = a2[yp1]; final double[] mmy = mm[y]; for (int x = 1, xm1 = 0, xp1 = 2; x < dimsxp1; ++x, ++xm1, ++xp1) { final double vx = a1y[x]; if (vx > a0ym1[xm1] && vx > a0ym1[x] && vx > a0ym1[xp1] && vx > a0y[xm1] && vx > a0y[x] && vx > a0y[xp1] && vx > a0yp1[xm1] && vx > a0yp1[x] && vx > a0yp1[xp1] && vx > a1ym1[xm1] && vx > a1ym1[x] && vx > a1ym1[xp1] && vx > a1y[xm1] && vx > a1y[xp1] && vx > a1yp1[xm1] && vx > a1yp1[x] && vx > a1yp1[xp1] && vx > a2ym1[xm1] && vx > a2ym1[x] && vx > a2ym1[xp1] && vx > a2y[xm1] && vx > a2y[x] && vx > a2y[xp1] && vx > a2yp1[xm1] && vx > a2yp1[x] && vx > a2yp1[xp1]) { if (extract) camax.add(new Coordinates(xm1, ym1, c0.z, c0.t, c0.c)); mmy[x] = MAX; } } progressor.step(); } } // Find minima: if (minima) { if (c0.z == 0) set(a0, DMAX); else if (c0.z == dimszm1) set(a2, DMAX); border(a0, DMAX); border(a1, DMAX); border(a2, DMAX); for (int y = 1, ym1 = 0, yp1 = 2; y < dimsyp1; ++y, ++ym1, ++yp1) { final double[] a0ym1 = a0[ym1], a0y = a0[y], a0yp1 = a0[yp1]; final double[] a1ym1 = a1[ym1], a1y = a1[y], a1yp1 = a1[yp1]; final double[] a2ym1 = a2[ym1], a2y = a2[y], a2yp1 = a2[yp1]; final double[] mmy = mm[y]; for (int x = 1, xm1 = 0, xp1 = 2; x < dimsxp1; ++x, ++xm1, ++xp1) { final double vx = a1y[x]; if (vx < a0ym1[xm1] && vx < a0ym1[x] && vx < a0ym1[xp1] && vx < a0y[xm1] && vx < a0y[x] && vx < a0y[xp1] && vx < a0yp1[xm1] && vx < a0yp1[x] && vx < a0yp1[xp1] && vx < a1ym1[xm1] && vx < a1ym1[x] && vx < a1ym1[xp1] && vx < a1y[xm1] && vx < a1y[xp1] && vx < a1yp1[xm1] && vx < a1yp1[x] && vx < a1yp1[xp1] && vx < a2ym1[xm1] && vx < a2ym1[x] && vx < a2ym1[xp1] && vx < a2y[xm1] && vx < a2y[x] && vx < a2y[xp1] && vx < a2yp1[xm1] && vx < a2yp1[x] && vx < a2yp1[xp1]) { if (extract) camin.add(new Coordinates(xm1, ym1, c0.z, c0.t, c0.c)); mmy[x] = MIN; } } progressor.step(); } } if (detect) image.set(c0, mm); } } } } // Finish up: messenger.status(""); progressor.stop(); timer.stop(); if (detect) image.name(image.name() + " extrema"); final Vector<Vector<Coordinates>> vvc = new Vector<Vector<Coordinates>>(2); vvc.add(camax); vvc.add(camin); return vvc; }
/** * Mirrors an image. * * @param image the input image to be mirrored. The image is overwritten with the results of * mirroring. * @param axes indicates the axes along which to mirror. The image is mirrored in each dimension * for which the corresponding boolean field of this parameter is {@code true}. * @exception NullPointerException if any of the parameters is {@code null}. */ public void run(final Image image, final Axes axes) { messenger.log(ImageScience.prelude() + "Mirror"); // Initialize timer: final Timer timer = new Timer(); timer.messenger.log(messenger.log()); timer.start(); // Check parameters: messenger.log("Checking parameters"); final Dimensions dims = image.dimensions(); messenger.log( "Input image dimensions: (x,y,z,t,c) = (" + dims.x + "," + dims.y + "," + dims.z + "," + dims.t + "," + dims.c + ")"); // Mirror input image: messenger.log("Mirroring " + image.type()); progressor.steps( (axes.x ? dims.c * dims.t * dims.z : 0) + (axes.y ? dims.c * dims.t * dims.z : 0) + (axes.z ? dims.c * dims.t * (1 + (dims.z - 1) / 2) : 0) + (axes.t ? dims.c * (1 + (dims.t - 1) / 2) * dims.z : 0) + (axes.c ? (1 + (dims.c - 1) / 2) * dims.t * dims.z : 0)); progressor.start(); image.axes(Axes.X); // Mirror in x-dimension if requested: if (axes.x) { messenger.log("Mirroring in x-dimension"); messenger.status("Mirroring in x-dimension..."); final Coordinates c = new Coordinates(); final double[] a = new double[dims.x]; final int dimsxm1 = dims.x - 1; final int maxx = dimsxm1 / 2; for (c.c = 0; c.c < dims.c; ++c.c) { for (c.t = 0; c.t < dims.t; ++c.t) { for (c.z = 0; c.z < dims.z; ++c.z) { for (c.y = 0; c.y < dims.y; ++c.y) { image.get(c, a); for (int x1 = 0, x2 = dimsxm1; x1 <= maxx; ++x1, --x2) { final double tmp = a[x2]; a[x2] = a[x1]; a[x1] = tmp; } image.set(c, a); } progressor.step(); } } } } // Mirror in y-dimension if requested: if (axes.y) { messenger.log("Mirroring in y-dimension"); messenger.status("Mirroring in y-dimension..."); final Coordinates c1 = new Coordinates(); final Coordinates c2 = new Coordinates(); final double[] a1 = new double[dims.x]; final double[] a2 = new double[dims.x]; final int dimsym1 = dims.y - 1; final int maxy = dimsym1 / 2; for (c1.c = c2.c = 0; c1.c < dims.c; ++c1.c, ++c2.c) { for (c1.t = c2.t = 0; c1.t < dims.t; ++c1.t, ++c2.t) { for (c1.z = c2.z = 0; c1.z < dims.z; ++c1.z, ++c2.z) { for (c1.y = 0, c2.y = dimsym1; c1.y <= maxy; ++c1.y, --c2.y) { image.get(c1, a1); image.get(c2, a2); image.set(c1, a2); image.set(c2, a1); } progressor.step(); } } } } // Mirror in z-dimension if requested: if (axes.z) { messenger.log("Mirroring in z-dimension"); messenger.status("Mirroring in z-dimension..."); final Coordinates c1 = new Coordinates(); final Coordinates c2 = new Coordinates(); final double[] a1 = new double[dims.x]; final double[] a2 = new double[dims.x]; final int dimszm1 = dims.z - 1; final int maxz = dimszm1 / 2; for (c1.c = c2.c = 0; c1.c < dims.c; ++c1.c, ++c2.c) { for (c1.t = c2.t = 0; c1.t < dims.t; ++c1.t, ++c2.t) { for (c1.z = 0, c2.z = dimszm1; c1.z <= maxz; ++c1.z, --c2.z) { for (c1.y = c2.y = 0; c1.y < dims.y; ++c1.y, ++c2.y) { image.get(c1, a1); image.get(c2, a2); image.set(c1, a2); image.set(c2, a1); } progressor.step(); } } } } // Mirror in t-dimension if requested: if (axes.t) { messenger.log("Mirroring in t-dimension"); messenger.status("Mirroring in t-dimension..."); final Coordinates c1 = new Coordinates(); final Coordinates c2 = new Coordinates(); final double[] a1 = new double[dims.x]; final double[] a2 = new double[dims.x]; final int dimstm1 = dims.t - 1; final int maxt = dimstm1 / 2; for (c1.c = c2.c = 0; c1.c < dims.c; ++c1.c, ++c2.c) { for (c1.t = 0, c2.t = dimstm1; c1.t <= maxt; ++c1.t, --c2.t) { for (c1.z = c2.z = 0; c1.z < dims.z; ++c1.z, ++c2.z) { for (c1.y = c2.y = 0; c1.y < dims.y; ++c1.y, ++c2.y) { image.get(c1, a1); image.get(c2, a2); image.set(c1, a2); image.set(c2, a1); } progressor.step(); } } } } // Mirror in c-dimension if requested: if (axes.c) { messenger.log("Mirroring in c-dimension"); messenger.status("Mirroring in c-dimension..."); final Coordinates c1 = new Coordinates(); final Coordinates c2 = new Coordinates(); final double[] a1 = new double[dims.x]; final double[] a2 = new double[dims.x]; final int dimscm1 = dims.c - 1; final int maxc = dimscm1 / 2; for (c1.c = 0, c2.c = dimscm1; c1.c <= maxc; ++c1.c, --c2.c) { for (c1.t = c2.t = 0; c1.t < dims.t; ++c1.t, ++c2.t) { for (c1.z = c2.z = 0; c1.z < dims.z; ++c1.z, ++c2.z) { for (c1.y = c2.y = 0; c1.y < dims.y; ++c1.y, ++c2.y) { image.get(c1, a1); image.get(c2, a2); image.set(c1, a2); image.set(c2, a1); } progressor.step(); } } } } // Finish up: image.name(image.name() + " mirrored"); messenger.status(""); progressor.stop(); timer.stop(); }
private void fft(final Image real, final Image imag, final Axes axes, final int sign) { final Timer timer = new Timer(); timer.messenger.log(messenger.log()); timer.start(); // Initialize: check(real, imag, axes); final Coordinates c = new Coordinates(); final Dimensions dims = real.dimensions(); if (sign == -1) messenger.status("Forward FFT..."); else messenger.status("Inverse FFT..."); double[] re = null, im = null; double scale = 1; progressor.steps( (axes.x ? dims.c * dims.t * dims.z * dims.y : 0) + (axes.y ? dims.c * dims.t * dims.z * dims.x : 0) + (axes.z ? dims.c * dims.t * dims.z * dims.y : 0) + (axes.t ? dims.c * dims.t * dims.z * dims.y : 0) + (axes.c ? dims.c * dims.t * dims.z * dims.y : 0)); progressor.start(); // Transform in x-dimension if active: if (axes.x) { messenger.log(" FFT in x-dimension..."); scale *= dims.x; c.reset(); real.axes(Axes.X); imag.axes(Axes.X); re = new double[dims.x]; im = new double[dims.x]; for (c.c = 0; c.c < dims.c; ++c.c) for (c.t = 0; c.t < dims.t; ++c.t) for (c.z = 0; c.z < dims.z; ++c.z) for (c.y = 0; c.y < dims.y; ++c.y) { real.get(c, re); imag.get(c, im); fft(re, im, sign); real.set(c, re); imag.set(c, im); progressor.step(); } } // Transform in y-dimension if active: if (axes.y) { messenger.log(" FFT in y-dimension..."); scale *= dims.y; c.reset(); real.axes(Axes.Y); imag.axes(Axes.Y); re = new double[dims.y]; im = new double[dims.y]; for (c.c = 0; c.c < dims.c; ++c.c) for (c.t = 0; c.t < dims.t; ++c.t) for (c.z = 0; c.z < dims.z; ++c.z) for (c.x = 0; c.x < dims.x; ++c.x) { real.get(c, re); imag.get(c, im); fft(re, im, sign); real.set(c, re); imag.set(c, im); progressor.step(); } } // Transform in z-dimension if active: if (axes.z) { messenger.log(" FFT in z-dimension..."); scale *= dims.z; c.reset(); real.axes(Axes.Z); imag.axes(Axes.Z); re = new double[dims.z]; im = new double[dims.z]; for (c.c = 0; c.c < dims.c; ++c.c) for (c.t = 0; c.t < dims.t; ++c.t) for (c.y = 0; c.y < dims.y; ++c.y) { for (c.x = 0; c.x < dims.x; ++c.x) { real.get(c, re); imag.get(c, im); fft(re, im, sign); real.set(c, re); imag.set(c, im); } progressor.step(dims.z); } } // Transform in t-dimension if active: if (axes.t) { messenger.log(" FFT in t-dimension..."); scale *= dims.t; c.reset(); real.axes(Axes.T); imag.axes(Axes.T); re = new double[dims.t]; im = new double[dims.t]; for (c.c = 0; c.c < dims.c; ++c.c) for (c.z = 0; c.z < dims.z; ++c.z) for (c.y = 0; c.y < dims.y; ++c.y) { for (c.x = 0; c.x < dims.x; ++c.x) { real.get(c, re); imag.get(c, im); fft(re, im, sign); real.set(c, re); imag.set(c, im); } progressor.step(dims.t); } } // Transform in c-dimension if active: if (axes.c) { messenger.log(" FFT in c-dimension..."); scale *= dims.c; c.reset(); real.axes(Axes.C); imag.axes(Axes.C); re = new double[dims.c]; im = new double[dims.c]; for (c.t = 0; c.t < dims.t; ++c.t) for (c.z = 0; c.z < dims.z; ++c.z) for (c.y = 0; c.y < dims.y; ++c.y) { for (c.x = 0; c.x < dims.x; ++c.x) { real.get(c, re); imag.get(c, im); fft(re, im, sign); real.set(c, re); imag.set(c, im); } progressor.step(dims.c); } } // Scale correction in case of inverse transform: if (sign == 1) { messenger.log(" Scale correction..."); real.divide(scale); imag.divide(scale); } messenger.log("Done"); messenger.status(""); progressor.stop(); timer.stop(); }