/* * 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 java.util.Arrays; import edu.stanford.rsl.conrad.data.generic.datatypes.Complex; import edu.stanford.rsl.conrad.data.numeric.Grid1D; /** * Class to use complex numbers in a grid structure. * Internally float arrays are used. The real and imaginary parts are stored in an alternating manner. * @author akmaier / berger * */ public class ComplexGrid1D extends ComplexGrid { /** Linear float array stores the complex numbers in an alternating manner [Re1, Imag1, Re2, Imag2, ..., ReN,ImagN]. */ private float[] buffer; /** offset for shifted access due to the compatibility with a Grid2DComplex. */ private int offset = 0; public ComplexGrid1D(int width) { buffer = new float[width*2]; this.size = new int[] {width}; this.offset = 0; init(); notifyAfterWrite(); } public ComplexGrid1D(float[] buffer, int offset, int width){ this.buffer = buffer; this.size = new int[] {width}; this.offset = offset; init(); notifyAfterWrite(); } public ComplexGrid1D(Grid1D grid){ this(grid.getSize()[0]); final int inputSize = grid.getSize()[0]; for (int i=0; i < inputSize;++i){ this.setAtIndex(i, grid.getAtIndex(i)); } this.size = new int[]{grid.getSize()[0]}; this.origin = new double[]{grid.getOrigin()[0]}; this.spacing = new double[]{grid.getSpacing()[0]}; this.offset = 0; notifyAfterWrite(); } public ComplexGrid1D(ComplexGrid1D grid){ this(grid.getSize()[0]); final int inputSize = grid.getSize()[0]; for (int i=0; i < inputSize;++i){ this.setAtIndex(i, grid.getAtIndex(i)); } this.size = new int[]{grid.size[0]}; this.origin = new double[]{grid.origin[0]}; this.spacing = new double[]{grid.spacing[0]}; this.offset = 0; if(grid.openCLactive) activateCL(); } public void init(){ this.origin = new double[]{0}; this.spacing = new double[]{1}; } public void fftshift(){ int width = this.size[0]; int startIndex = offset*2; int endIndex = startIndex+(width*2); int pW = (int)Math.ceil(width/2.0); float[] tmpArr = Arrays.copyOfRange(buffer, startIndex, endIndex); for(int i = pW; i < this.getSize()[0];i++) { buffer[startIndex+(i-pW)*2] = tmpArr[(i)*2]; buffer[startIndex+(i-pW)*2+1] = tmpArr[(i)*2+1]; } for(int i = 0; i < pW;i++) { buffer[startIndex + (i+width-pW)*2] = tmpArr[(i)*2]; buffer[startIndex + (i+width-pW)*2+1] = tmpArr[(i)*2+1]; } } public void multiplyAtIndex(int index, float val) { multiplyAtIndex(index, val,0); } public void multiplyAtIndex(int index, float real, float imag) { Complex in = new Complex(real,imag); multiplyAtIndex(index,in); } public void multiplyAtIndex(int index, Complex in) { setAtIndex(index, getAtIndex(index).mul(in)); } public void divideAtIndex(int index, float val) { divideAtIndex(index, val, 0); } public void divideAtIndex(int index, float real, float imag) { Complex in = new Complex(real,imag); divideAtIndex(index,in); } public void divideAtIndex(int index, Complex in) { setAtIndex(index, getAtIndex(index).div(in)); } public void addAtIndex(int index, float val) { addAtIndex(index, val, 0); } public void addAtIndex(int index, float real, float imag) { Complex in = new Complex(real,imag); addAtIndex(index,in); } public void addAtIndex(int index, Complex in) { setAtIndex(index, getAtIndex(index).add(in)); } public void subtractAtIndex(int index, float val) { subtractAtIndex(index, val, 0); } public void subtractAtIndex(int index, float real, float imag) { Complex in = new Complex(real,imag); subtractAtIndex(index,in); } public void subtractAtIndex(int index, Complex in) { setAtIndex(index, getAtIndex(index).sub(in)); } public void setAtIndex(int index, float val){ setAtIndex(index,val,0); } public void setAtIndex(int index, float real, float imag){ Complex in = new Complex(real,imag); setAtIndex(index, in); } public void setAtIndex(int index, Complex val){ buffer[(index+offset)*2]=(float)val.getReal(); buffer[(index+offset)*2+1]=(float)val.getImag(); notifyAfterWrite(); } public Complex getAtIndex(int index){ notifyBeforeRead(); return new Complex(buffer[(index+offset)*2],buffer[(index+offset)*2+1]); } public Grid1D getRealGrid(){ return getRealSubGrid(0, this.size[0]); } public Grid1D getImagGrid(){ return getImagSubGrid(0, this.size[0]); } public Grid1D getMagGrid(){ return getMagSubGrid(0, this.size[0]); } public Grid1D getPhaseGrid(){ return getPhaseSubGrid(0, this.size[0]); } public Grid1D getRealSubGrid(final int startIndex, final int length){ Grid1D subgrid = new Grid1D(length); for (int i=0; i < length; ++i){ subgrid.setAtIndex(i, (float)this.getAtIndex(startIndex+i).getReal()); } return subgrid; } public Grid1D getImagSubGrid(final int startIndex, final int length){ Grid1D subgrid = new Grid1D(new float [length]); for (int i=0; i < length; ++i){ subgrid.setAtIndex(i, (float)this.getAtIndex(startIndex+i).getImag()); } return subgrid; } public Grid1D getMagSubGrid(final int startIndex, final int length){ Grid1D subgrid = new Grid1D(new float [length]); for (int i=0; i < length; ++i){ subgrid.setAtIndex(i, (float)this.getAtIndex(startIndex+i).getMagn()); } return subgrid; } public Grid1D getPhaseSubGrid(final int startIndex, final int length){ Grid1D subgrid = new Grid1D(new float [length]); for (int i=0; i < length; ++i){ subgrid.setAtIndex(i, (float)this.getAtIndex(startIndex+i).getAngle()); } return subgrid; } @Override public Complex getValue(int... idx) { return this.getAtIndex(idx[0]); } @Override public void setValue(Complex val, int... idx) { setAtIndex(idx[0], val); } @Override public ComplexGrid clone() { notifyBeforeRead(); return new ComplexGrid1D(this); } @Override public String toString() { String result = new String(); result += "["; for (int i = 0; i < size[0]; ++i) { if (i != 0) result += ", "; result += getAtIndex(i); } result += "]"; return result; } public float[] getBuffer() { notifyBeforeRead(); return buffer; } public int getOffset() { return offset; } @Override public float[] getAslinearMemory() { notifyBeforeRead(); return buffer; } @Override public void setAslinearMemory(float[] buffer) { this.buffer = buffer; notifyAfterWrite(); } @Override public float getRealAtIndex(int... idx) { notifyBeforeRead(); return buffer[2*(offset+idx[0])]; } @Override public void setRealAtIndex(float val, int... idx) { buffer[2*(offset+idx[0])] = val; notifyAfterWrite(); } @Override public float getImagAtIndex(int... idx) { notifyBeforeRead(); return buffer[2*(idx[0]+offset)+1]; } @Override public void setImagAtIndex(float val, int... idx) { buffer[2*(idx[0]+offset)+1] = val; notifyAfterWrite(); } }