package cquest.quantitation; // // To model using HLSVD the Background signal //------------------------------------------------------------------------ //------------------------------------------------------------------------ import java.awt.BorderLayout; import java.awt.GridLayout; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.util.Date; import java.util.Vector; import javax.swing.JButton; import javax.swing.JCheckBox; import javax.swing.JDialog; import javax.swing.JLabel; import javax.swing.JOptionPane; import javax.swing.JPanel; import javax.swing.border.EtchedBorder; import javax.swing.border.TitledBorder; import javax.swing.event.ChangeEvent; import javax.swing.event.ChangeListener; import cquest.Data; import cquest.utils.WholeNumberField; /** This class performs HLSVD Propack */ public class Svd { //------------------------------------------------------------------------ //variables //------------------------------------------------------------------------ static int REAL = 0; static int IMAG = 1; final int ABS = 2; final int OK = 0; final int CANCEL = 1; static int SIGNAL = 0; protected Data data; /** to store the user choice in the dialog*/ protected int userChoice; /** maximal length of the signal */ static final int MAXLEN = 32768; //2048; /** maximal number of sinusoides*/ static final int KMAX = 50; /** to use HLSVDPROPACK in the static functions. */ public final static int HLSVDPROPACK = 1; public final static int HLSVD = 2; /**number of sinusoids initially wished by user*/ int kuser = 10; /**number of rows of hankel data matrix hx, Lrow < ndp/2*/ int lrow = 500; /**number of sinusoids actually fitted: identical to number of sinvals found by Lanczos = ndiv */ int kfit; int numberOfPointsOfFID; int nbPointsBegin = 0; /** amplitude of the fitted peaks */ double[] ampl; /** phase of the fitted peaks */ double[] phase; /** damping of the fitted peaks */ double[] damp; /** frequency of the fitted peaks */ double[] freq; /** singular values */ double[] sinvals; //ProgressBar progressBar; int iMaxProgress = 0; private boolean isCanceled = false; /** Use Lanczos or Lapack */ private boolean isLanczos = true; /** Use Total-Least-Squares or Least-Squares */ private boolean isTotalLS = false; boolean allSignals = true; boolean isErrorsNeeded = true; //------------------------------------------------------------------------ //constructor //------------------------------------------------------------------------ /** Constructor to quantify only the first signal without errors. * Used in Quest Quantitation. * modified by Michael sdika to remove the need of Mrui. @author Helene */ public Svd(int method, Data d, int r, int k, int points, boolean all, boolean calculateErrors, boolean[][] mrsiSelectionArray, int noiseFromResidu) { //this.mrui = null; this.data = d; String libPath = System.getProperty("java.library.path"); System.out.println("java.library.path=" + libPath); String algoName = ""; switch (method) { case HLSVDPROPACK : { this.isLanczos = true; this.isTotalLS = false; algoName = "HLSVDPropack"; } break; case HLSVD : { this.isLanczos = true; this.isTotalLS = false; algoName = "HLSVD"; } break; default: { System.out.println("Unknown svd method"); } break; } lrow = r; kuser = k; numberOfPointsOfFID = points; allSignals = all; isErrorsNeeded = calculateErrors; // nbPointsBegin= 2; svdCallsWithoutGUI(method,algoName, mrsiSelectionArray, noiseFromResidu); } //------------------------------------------------------------------------ //methods //------------------------------------------------------------------------ /** native method which carries out HLSVD (library hlsvdPropackQuantitation) @param FID @param number of rows of the hankel matrix @param number of sinusoides wished @version %I%, %U%*/ private native void hlsvdPropackQuantitation(double[][] sig, int lrow, int kuser); static { System.loadLibrary("hlsvdPropackQuantitation"); } /** to set the amplitudes array found by the svd process @param amplitudes array @version %I%, %U%*/ private void setAmpl(double[] array) { ampl = array; } /** to set the phases array found by the svd process @param phases array @version %I%, %U%*/ private void setPhase(double[] array) { phase = array; } /** to set the damping array found by the svd process @param damping array @version %I%,%U%*/ private void setDamp(double[] array) { damp = array; } /** to set the frequencies array found by the svd process @param frequencies array @version %I%, %U%*/ private void setFreq(double[] array) { freq = array; } /** to set the singular values array found by the svd process @param singular values array @version %I%, %U%*/ private void setSinvals(double[] array) { sinvals = array; } public void svdCalls(boolean bar) { double step = ((Double) ((Vector) data.getHeader()).elementAt(0)).doubleValue(); double begin, p0; data.findResult(); data.result.nameOfAlgorithm = "HLSVDPropack"; data.result.numberOfPointsInQuantitation = numberOfPointsOfFID; // T.Petit 20/6/2002 data.result.numberOfComponentsAsked = kuser; double[][] signal, tempor; for (int i = 0; i < data.getSignalsNb(); i++) { if (bar) { String sProgressMessage = "Quantifying signal " + (i + 1) + " out of " + data.getSignalsNb() + "..."; System.out.println(sProgressMessage); int iProgressValue = 1; // 50% when only 1 signal. if (data.getSignalsNb() > 1) iProgressValue = i; } p0 = ((double[]) data.getPhases())[0]; begin = ((double[]) data.getPhases())[1]; data.getFIDAt(i).truncatedPoints = nbPointsBegin; int res = 0; signal = new double[2][numberOfPointsOfFID]; tempor = data.getSignal(i); for (int k = 0; k < numberOfPointsOfFID - nbPointsBegin; k++) { signal[REAL][k] = tempor[REAL][k + nbPointsBegin]; signal[IMAG][k] = tempor[IMAG][k + nbPointsBegin]; } long start = (new Date()).getTime(); svdQuantitation(signal, lrow, kuser); // nbPointsBegin leads to the quantification of a // different signal. To translate to obtain the // original signal, the aplitudes and phases have // to be corrected. double dt = data.stepTime; //System.out.println("nb signaux trouves : " + ampl.length); if (nbPointsBegin != 0) for (int k = 0; k < ampl.length; k++) { ampl[k] *= Math.exp(nbPointsBegin * -damp[k]); //*dt/dt phase[k] -= 2 * Math.PI * freq[k] * nbPointsBegin; // *dt/dt while (phase[k] < -Math.PI) phase[k] += 2 * Math.PI; while (phase[k] > Math.PI) phase[k] -= 2 * Math.PI; } if (res == 0) { long end = (new Date()).getTime(); data.result.addFID(end - start, data.stepTime); data.getFIDAt(i).truncatedPoints = nbPointsBegin; String[] names = new String[ampl.length]; for (int k = 0; k < ampl.length; k++) { if (Double.isNaN(ampl[k])) ampl[k] = 0; if (Double.isNaN(damp[k])) damp[k] = 0; if (Double.isNaN(freq[k])) freq[k] = 0; if (Double.isNaN(phase[k])) phase[k] = 0; damp[k] = -damp[k]; names[k] = "peak #" + k; } data.result.setResultAt(i, ampl, damp, (double[]) null, freq, phase); data.result.setSingularValuesAt(i, sinvals); data.result.setNames(names); } else { ; } // In autophasing break loop after the first signal. if (!allSignals) break; if (isCanceled) break; } if (!isCanceled) { System.out.println("Canceled"); } } /** call a svd. * I have added this function to be able to do a svd * without having the GUI running for the command line mode * of QUEST. * method is one of HLTLS HLSVDPROPACK HLSVD HLTLS HSVD * noiseFromResidu see mrui/Preferences.java * * Actually, the svd class should be reimplemented to fully separate * GUI from computation, and this method suppressed. * * @author Michael Sdika * */ public void svdCallsWithoutGUI(int method, String algoName, boolean[][] mrsiSelectionArray, int noiseFromResidu) { data.findResult(); data.result.nameOfAlgorithm = algoName; data.result.numberOfPointsInQuantitation = numberOfPointsOfFID; data.result.numberOfComponentsAsked = kuser; double[] nullVect = new double[kuser]; double[][] signal = new double[2][numberOfPointsOfFID]; for (int i = 0; i < data.getSignalsNb(); i++) { // If MrsiQuantitation: only selected signals quantified. Rest 0 for security. if (mrsiSelectionArray!=null && data.getSignalsNb()>1) { int w = data.dataWidthForMrsi; if (!mrsiSelectionArray[i % w][i / w]) { data.result.addFID(0, data.stepTime); data.result.setResultAt(i, nullVect, nullVect, null, nullVect, nullVect); data.result.setSingularValuesAt(i, nullVect); continue; } } data.getFIDAt(i).truncatedPoints = nbPointsBegin; double[][] tempor = data.getSignal(i); for (int k = 0; k < numberOfPointsOfFID - nbPointsBegin; k++) { signal[REAL][k] = tempor[REAL][k + nbPointsBegin]; signal[IMAG][k] = tempor[IMAG][k + nbPointsBegin]; } long start = (new Date()).getTime(); svdQuantitation(signal, lrow, kuser, method); long end = (new Date()).getTime(); if (nbPointsBegin != 0) for (int k = 0; k < ampl.length; k++) { ampl [k] *= Math.exp(nbPointsBegin * -damp[k]); //*dt/dt phase[k] -= 2 * Math.PI * freq[k] * nbPointsBegin; // *dt/dt while (phase[k] < -Math.PI) phase[k] += 2 * Math.PI; while (phase[k] > Math.PI) phase[k] -= 2 * Math.PI; } data.result.addFID(end-start, data.stepTime); // ?? data.getFIDAt(i).truncatedPoints = nbPointsBegin; String[] names = new String[ampl.length]; for (int k = 0; k < ampl.length; k++) { if (Double.isNaN(ampl[k])) ampl[k] = 0; if (Double.isNaN(damp[k])) damp[k] = 0; if (Double.isNaN(freq[k])) freq[k] = 0; if (Double.isNaN(phase[k])) phase[k] = 0; damp [k] = -damp[k]; names[k] = "peak #" + k; } data.result.setResultAt(i, ampl, damp, (double[]) null, freq, phase); data.result.setSingularValuesAt(i, sinvals); data.result.setNames(names); if (!allSignals) break; } //if (isErrorsNeeded) data.result.setErrors(noiseFromResidu, data.getOriginalLength() / 10); } /** static svdQuantitation method. * (used by staticSVD) * method is HLSVDPROPACK * */ private void svdQuantitation(double[][] signal, int lrow, int kuser, int method) { switch (method) { case HLSVDPROPACK : { System.out.println("!!Launch HLSVD Propack Method !!"); hlsvdPropackQuantitation(signal, lrow, kuser); } break; } } private void svdQuantitation(double[][] signal, int lrow, int kuser) { System.out.println("!!Launch HLSVD Propack Method !!"); hlsvdPropackQuantitation(signal, lrow, kuser); } }