Trying to fit a sine function to phased light curve

前端 未结 2 528
孤城傲影
孤城傲影 2020-12-20 02:32
import numpy as np
import matplotlib.pyplot as plt
from lmfit import Model,Parameters


f2= \"KELT_N16_lc_006261_V01_west_tfa.dat\"    
t2=\"TIMES\"   # file name

N         


        
2条回答
  •  青春惊慌失措
    2020-12-20 02:36

    How could we help you with your uncommented code?

    • How do we know what is what and what should it do?
    • What method for fitting are you using?
    • Where is the data and in what form ?

    I would start with computing the approximate sin wave parameters. Let assume you got some input data in form of n points with x,y coordinates. And want to fit a sin wave:

    y(t) = y0+A*sin(x0+x(t)*f)
    

    Where y0 is the y offset, x0 is phase offset, A is amplitude and f is angular frequency.

    I would:

    1. Compute avg y value

      y0 = sum(data[i].y)/n where i={0,1,2,...n-1}
      

      this is the mean value representing possible y offset y0 of your sin wave.

    2. compute avg distance to y0

      d = sum (|data[i].y-y0|)/n where i={0,1,2,...n-1}
      

      If my memory serves well this should be the effective value of amplitude so:

      A = sqrt(2)*d
      
    3. find zero crossings in the dataset

      for this the dataset should be sorted by x so sort it if it is not. Remember index i for: first crossing i0, last crossing i1 and number of crossings found j from this we can estimate frequency and phase offset:

      f=M_PI*double(j-1)/(datax[i1]-datax[i0]);
      x0=-datax[i0]*f;
      

      To determine which half sin wave we aligned to just check the sign of middle point between first two zero crossings

      i1=i0+((i1-i0)/(j-1));
      if (datay[(i0+i1)>>1]<=y0) x0+=M_PI;
      

      Or check for specific zero crossing pattern instead.

      That is all now we have approximate x0,y0,f,A parametters of sinwave.

    Here some C++ code I tested with (sorry I do not use Python):

    //---------------------------------------------------------------------------
    #include 
    // input data
    const int n=5000;
    double datax[n];
    double datay[n];
    // fitted sin wave
    double A,x0,y0,f;
    //---------------------------------------------------------------------------
    void data_generate() // genere random noisy sinvawe
        {
        int i;
        double A=150.0,x0=250.0,y0=200.0,f=0.03,r=20.0;
        double x,y;
        Randomize();
        for (i=0;idatax[i])
            {
            x=datax[i-1]; datax[i-1]=datax[i]; datax[i]=x;
            y=datay[i-1]; datay[i-1]=datay[i]; datay[i]=y;
            e=1;
            }
        // find zero crossings
        for (i=0,j=0;i=+0.75*A) break;
            if (i>=n) break;
            // find point closest to zero
            for (i1=e;efabs(datay[e]-y0)) i1=e;
            if (!j) i0=i1; j++;
            }
        f=2.0*M_PI*double(j-1)/(datax[i1]-datax[i0]);
        x0=-datax[i0]*f;
        }
    //---------------------------------------------------------------------------
    

    And preview:

    The dots are generated noisy data and blue curve is fitted sin wave.

    On top of all this you can build your fitting to increase precision. Does not matter which method you will use for the search around found parameters. For example I would go for:

    • How approximation search works

提交回复
热议问题