/* * Copyright (C) 2014 - Martin Berger * Copyright (C) 2017 - Christopher Syben * CONRAD is developed as an Open Source project under the GNU General Public License (GPL). */ package edu.stanford.rsl.conrad.data.generic.complex; import ij.ImageJ; import edu.stanford.rsl.conrad.data.generic.datatypes.Complex; import edu.stanford.rsl.conrad.data.numeric.Grid2D; import edu.stanford.rsl.tutorial.phantoms.SheppLogan; public class ComplexGrid2D extends ComplexGrid { /** Linear float array stores the complex numbers in an alternating manner [Re1, Imag1, Re2, Imag2, ..., ReN,ImagN]. */ private float[] buffer; private int offset; private ComplexGrid1D[] subGrids = null; public ComplexGrid2D(int width, int height) { this(new float[width*height*2],0,width,height); } public ComplexGrid2D(float[] buffer, int offset, int width, int height){ this.buffer = buffer; this.offset = offset; this.spacing = new double[] {1,1}; this.origin = new double[2]; this.size = new int[]{width,height}; initialize(width, height); notifyAfterWrite(); } public ComplexGrid2D(ComplexGrid2D input){ this.offset = 0; this.size = new int[] {input.getSize()[0],input.getSize()[1]}; this.spacing = new double[] {input.spacing[0],input.spacing[1]}; this.origin = new double[] {input.origin[0],input.origin[1]}; buffer = new float[input.getNumberOfElements()*2]; System.arraycopy(input.getBuffer(), input.getOffset()*2, this.buffer, 0, this.buffer.length); initialize(input.getSize()[0],input.getSize()[1]); if(input.openCLactive) activateCL(); } public ComplexGrid2D(Grid2D input){ this.offset = 0; this.size = new int[] {input.getSize()[0],input.getSize()[1]}; this.spacing = new double[] {input.getSpacing()[0],input.getSpacing()[1]}; this.origin = new double[] {input.getOrigin()[0],input.getOrigin()[1]}; buffer = new float[input.getNumberOfElements()*2]; for (int i = 0; i < input.getBuffer().length; i++) { this.buffer[i*2]=input.getBuffer()[i]; } initialize(input.getSize()[0],input.getSize()[1]); } protected void initialize(int width, int height) { for (int i = 0; i < 2; ++i) { assert size[i] > 0 : "Size values have to be greater than zero!"; } subGrids = new ComplexGrid1D[size[1]]; for (int i = 0; i < height; ++i) { subGrids[i] = new ComplexGrid1D(this.buffer, i*size[0]+offset, size[0]); } } public void fftshift() { ComplexGrid1D[] unshifted = subGrids.clone(); for(int i = 0; i < subGrids.length;i++ ){ unshifted[i].fftshift(); } int height = this.getSize()[1]; int pH = (int)Math.ceil(height/2.0); for(int j = pH; j < this.getSize()[1];j++) { this.setSubGrid(j-pH,unshifted[j]); } for(int j = 0; j < pH;j++) { this.setSubGrid(j+height-pH,unshifted[j]); } } public float[] getBuffer(){ notifyBeforeRead(); return buffer; } public void multiplyAtIndex(int i, int j, float val) { multiplyAtIndex(i, j, val, 0); } public void multiplyAtIndex(int i, int j, float real, float imag) { Complex in = new Complex(real,imag); multiplyAtIndex(i,j,in); } public void multiplyAtIndex(int i, int j, Complex in) { setAtIndex(i, j, getAtIndex(i,j).mul(in)); } public void divideAtIndex(int i, int j, float val) { divideAtIndex(i, j, val, 0); } public void divideAtIndex(int i, int j, float real, float imag) { Complex in = new Complex(real,imag); divideAtIndex(i, j, in); } public void divideAtIndex(int i, int j, Complex in) { setAtIndex(i, j, getAtIndex(i, j).div(in)); } public void addAtIndex(int i, int j, float val) { addAtIndex(i, j, val, 0); } public void addAtIndex(int i, int j, float real, float imag) { Complex in = new Complex(real,imag); addAtIndex(i, j, in); } public void addAtIndex(int i, int j, Complex in) { setAtIndex(i, j, getAtIndex(i, j).add(in)); } public void subtractAtIndex(int i, int j, float val) { subtractAtIndex(i, j, val, 0); } public void subtractAtIndex(int i, int j, float real, float imag) { Complex in = new Complex(real,imag); subtractAtIndex(i, j,in); } public void subtractAtIndex(int i, int j, Complex in) { setAtIndex(i, j, getAtIndex(i, j).sub(in)); } public void setAtIndex(int i, int j, float val){ setAtIndex(i, j,val,0); } public void setAtIndex(int i, int j, float real, float imag){ Complex in = new Complex(real,imag); setAtIndex(i, j, in); } public void setAtIndex(int i, int j, Complex val){ getSubGrid(j).setAtIndex(i,val); notifyAfterWrite(); } public Complex getAtIndex(int i, int j){ notifyBeforeRead(); return getSubGrid(j).getAtIndex(i); } public ComplexGrid1D getSubGrid(int j){ notifyBeforeRead(); return this.subGrids[j]; } public void setSubGrid(int j, ComplexGrid1D collumn){ subGrids[j]=collumn; notifyAfterWrite(); } @Override public Complex getValue(int... idx) { return getAtIndex(idx[0],idx[1]); } @Override public ComplexGrid clone() { notifyBeforeRead(); return new ComplexGrid2D(this); } @Override public String toString() { String result = new String(); result += "["; for (int j = 0; j < size[1]; ++j) { if (j != 0) result += "; "; result += getSubGrid(j).toString(); } result += "]"; return result; } @Override public Grid2D getRealGrid() { return getRealSubGrid(0, 0, size[0], size[1]); } @Override public Grid2D getImagGrid() { return getImagSubGrid(0, 0, size[0], size[1]); } @Override public Grid2D getMagGrid() { return getMagSubGrid(0, 0, size[0], size[1]); } @Override public Grid2D getPhaseGrid() { return getPhaseSubGrid(0, 0, size[0], size[1]); } public Grid2D getRealSubGrid(final int startX, final int startY, final int lengthX, final int lengthY){ Grid2D subgrid = new Grid2D(lengthX,lengthY); for (int i=0; i < lengthX; ++i){ for (int j=0; j < lengthY; ++j){ subgrid.setAtIndex(i,j, (float)this.getAtIndex(startX+i,startY+j).getReal()); } } return subgrid; } public Grid2D getImagSubGrid(final int startX, final int startY, final int lengthX, final int lengthY){ Grid2D subgrid = new Grid2D(lengthX,lengthY); for (int i=0; i < lengthX; ++i){ for (int j=0; j < lengthY; ++j){ subgrid.setAtIndex(i,j, (float)this.getAtIndex(startX+i,startY+j).getImag()); } } return subgrid; } public Grid2D getMagSubGrid(final int startX, final int startY, final int lengthX, final int lengthY){ Grid2D subgrid = new Grid2D(lengthX,lengthY); for (int i=0; i < lengthX; ++i){ for (int j=0; j < lengthY; ++j){ subgrid.setAtIndex(i,j, (float)this.getAtIndex(startX+i,startY+j).getMagn()); } } return subgrid; } public Grid2D getPhaseSubGrid(final int startX, final int startY, final int lengthX, final int lengthY){ Grid2D subgrid = new Grid2D(lengthX,lengthY); for (int i=0; i < lengthX; ++i){ for (int j=0; j < lengthY; ++j){ subgrid.setAtIndex(i,j, (float)this.getAtIndex(startX+i,startY+j).getAngle()); } } return subgrid; } @Override public void setValue(Complex val, int... idx) { setAtIndex(idx[0], idx[1], val); } @Override public float[] getAslinearMemory() { notifyBeforeRead(); return buffer; } @Override public void setAslinearMemory(float[] buffer) { this.buffer = buffer; notifyAfterWrite(); } @Override public float getRealAtIndex(int... idx) { return getSubGrid(idx[1]).getRealAtIndex(idx[0]); } @Override public void setRealAtIndex(float val, int... idx) { getSubGrid(idx[1]).setRealAtIndex(val,idx[0]); notifyAfterWrite(); } @Override public float getImagAtIndex(int... idx) { return getSubGrid(idx[1]).getImagAtIndex(idx[0]); } @Override public void setImagAtIndex(float val, int... idx) { getSubGrid(idx[1]).setImagAtIndex(val,idx[0]); notifyAfterWrite(); } public int getOffset() { return offset; } public static void main(String[] args) { new ImageJ(); ComplexGrid2D bla = new ComplexGrid2D(new SheppLogan(64)); ComplexGrid2D gc = new ComplexGrid2D(bla); ComplexGrid2D gc1 = new ComplexGrid2D(gc); bla.show(); Fourier ft = new Fourier(); ft.fft(gc); ft.ifft(gc); ft.fft2(gc1); ft.ifft2(gc1); ComplexGridOperator gop = new ComplexGridOperator(); ComplexGrid diff = bla.clone(); gop.subtractBy(diff, gc); ComplexGrid diff1 = bla.clone(); gop.subtractBy(diff1, gc1); diff.show(); diff1.show(); gc.show(); gc1.show(); } }