import ChaosDemos.*;
import java.awt.*;
import java.util.*;

//********************************************************************
/**                    
* Poswer spectrum diagnostics for Odes <br>
* @version 24 October 1997
* @author Michael Cross
*/
//********************************************************************

public class OdesSpectrum extends OdesDiagnostics {

 
/** updated number of points in plot */      
      int nplot;
/** index of first data curve */      
      int ncurve1;
/** copy of x */       
      double[] xp={0.,0.,0.,0.};  
/** Number of points in FFT */      
      int fourierLength=256;
/** index of point added to FFT */      
      int fourierIndex;  
/** data for power spectrum */      
      double[] fourierData;   
/** window type in power spectrum */       
      int winNum=2;
/** number of iterations between each point for power spectrum */      
      int FFTskip=1;   
/** number of iterations since last FFT */      
      int skip=1;
      private powerSpectrum mySpectrum;                  
                                  
          
      String xTitle="Frequency";
      String yTitle= "log(Power)";
      

//******************************************************************
/**
* @param inParent parent class
* @see Map1D
*/
//******************************************************************
      public OdesSpectrum(Odes inParent) {
            super(inParent);                           
      }
      
//********************************************************************
/**
* Updates parameters from the text controls in parent class 
*/ 
//********************************************************************            
      public void updateParameters() { 
            super.updateParameters();
            FFTskip=parent.variables.parseTextField(4,FFTskip,true);
            fourierLength=parent.variables.parseTextField(5,fourierLength,true);
            int test=fourierLength;
            int power=0;
            while(test>1) {
                  test=test/2;
                  power++;
            }
            test=1;
            for(int i=0;i<power;i++) test=test*2;
            if(test!=fourierLength) {
                  alertDialog alert = new alertDialog(
                        parent," No. of points must be power of two ");
                  fourierLength=test;
                  parent.variables.setText(5,String.valueOf(fourierLength));
            }
            winNum=parent.variables.parseTextField(6,winNum,0,3);
            parent.graph.setXAxisTitle(xTitle);
            parent.graph.setYAxisTitle(yTitle); 
                                                                 
      }      
                
//*********************************************************************
/**
* Restarts
*/
//*********************************************************************      
      public boolean restart() {
            double data1[] = new double[4];
            double data2[] = new double[4];
            int i,j;

            t=0.;

            if(runTrans) {
                if(!eliminateTransient()) return false;
                runTrans=false;
                parent.status.setText("");
            }                                               
            err=0.;

            nplot=0;
            skip=1;
            fourierData = new double[2*fourierLength];
            double scale=Pi2/(FFTskip*dtp*fourierLength);                                    
            mySpectrum = new powerSpectrum(fourierLength, winNum, scale);
            fourierIndex=0;
            int nit=0;
            parent.status.setText("Calculating spectrum");
            while(mySpectrum.getNumberOfSpectra()==0 && nit < 10000) {
                try {
                  t=parent.solver.timeStep(x,t,dtp);
                } catch (ArithmeticException e) {
                    alertDialog alert = new alertDialog
                              (parent,"Value has diverged. Try again! ");
                return false;
                }                            
                nplot=process(x,nplot);
                nit++;
            }
            if(mySpectrum.getNumberOfSpectra()==0) {
                  alertDialog alert = new alertDialog(
                        parent,"Bad parameter values: no data found");
                  parent.graph.paintAll=true; 
                  parent.graph.repaint();
                  return false;
            }
            parent.status.setText("");
            mySpectrum = new powerSpectrum(fourierLength, winNum, scale);   

            parent.graph.paintAll=true; 
            parent.graph.repaint();
            return true;                  
      }

//*********************************************************************
/**
* Iterates ODEs and updates graph
* @return true if iteration successful
*/
//*********************************************************************      
      public boolean iterate() { 
            double[] moredata = new double[2];
            double[] moredata1 = new double[2];  
            nplot=0;
            try{
                  for(int i=0;i<delay;i++)  
                        t=parent.solver.timeStep(x,t,dt);
            } catch (ArithmeticException e) {
                  alertDialog alert = new alertDialog(
                        parent,"Value has diverged.");
                  return false;
            }                                                
            nplot=process(x,nplot);

            errp=parent.solver.err[plot_x]+parent.solver.err[plot_y];
            if(errp>err) err=errp;                       
            if(parent.showTime)
                  parent.status.setText("     Time ="+(float)t);
            return true;                        
      }
      
//**********************************************************************
/**
* Sets default values of parameters depending on plot type
*/
//**********************************************************************          
      public void setDefaults() {
                   parent.variables.show(4);
                   parent.variables.show(5);                        
                   parent.variables.show(6);                                                      
                   parent.variables.setText(4,"4");
                   parent.variables.setLabelText(4,"Interval");
                   parent.variables.setText(5,"256");
                   parent.variables.setLabelText(5,"Points ");
                   parent.variables.setText(6,"2");
                   parent.variables.setLabelText(6,"Window");                                                        
      
                   parent.topRightPanel.validate();        
      }                                       

//**********************************************************************
/**
* Sets delay for movie iteration
*/
//**********************************************************************      
      public void setDelay(int inDelay) {
            delay=inDelay;
            dt=dtp/((double) delay);
            ntrans=(int) (trans/dtp);         
      } 

//**********************************************************************

/**
* process data
* @param    x variable
* @param    data for plotting
* @param    nplot number of points indata
* @return   nplot new number of points in data
*/          
//**********************************************************************                        

      int process(double x[], int nplot) {
            if(skip==FFTskip) {
                  fourierData[fourierIndex]=x[plot_y];
                  fourierIndex++;
                  fourierData[fourierIndex]=0;
                  fourierIndex++;
                  if(fourierIndex >= 2*fourierLength)  {
                     mySpectrum.transform(fourierData);
                     if(ncurve>=0) ncurve = parent.graph.deleteAllCurves();
                     ncurve = parent.graph.addCurve(
                          fourierData,1+fourierLength/2,Color.blue); 
                     parent.graph.paintAll=true; 
                     parent.graph.repaint();                              
                     fourierIndex=0;
                  }
                  nplot++;
                  skip=1;
            }
            else skip++;                           
            return nplot;
      }
      
}      
