0

I have a list of about 100 numbers. I know that the data reasonably fits some sine function. I'd like to create some kind of curve. Ideally, I'd like to extract the amplitude, phase, and frequency. Any suggestions or ideas?

for example: inputList = [x1,...,x100]

and I'm trying to figure out some function that does this

def fitCurve(inputList): A = amplitude(inputList) #calculate frequency #calculate phase

def amplitude(data):
    return (max(data) - min(data))/2

def frequency(data):
    #my first intuition is to find the first peak, but I'm not sure how to find the second one

def phase(data):
   #not sure what to do here at all...
jsh123
  • 19
  • 2
  • 2
    Would you be ok with me writing some code for you to do this? – par Dec 11 '14 at 06:59
  • That would be much appreciated. – jsh123 Dec 11 '14 at 07:02
  • @jsh123 Keep in mind that comment was probably a joke, you need to provide some sample data and code if you would like your question answered. – jamylak Dec 11 '14 at 07:03
  • oh...Sorry, I'm new here. The problem is pretty straightforward, but I'm running into a great deal of difficulty. – jsh123 Dec 11 '14 at 07:09
  • 1
    jsh123: This feels a lot like homework and no one is going to do that for you. Why don't you actually try to solve the problem yourself, and then ask us when you have a specific question about your implementation. – par Dec 11 '14 at 07:10
  • This sounds tricky from a mathematical point of view. Do you have a starting idea of the range of amplitue, freq, and phase? If so this might help http://stackoverflow.com/a/16716964/1470749. – 101 Dec 11 '14 at 07:15
  • This isn't homework. I don't really have a clue how to calculate frequency. I'm asking if there exists some method of finding sine frequency given a set of data points. I'm already familiar with scipy.optimize, but I was hoping someone with more experience had a more mature answer. – jsh123 Dec 11 '14 at 07:17
  • @figs I've looked at that implementation. Unfortunately, I was hoping this could work on randomly generated data, so no preconceived information beforehand. I found guessing with the mean yields rather poor results. – jsh123 Dec 11 '14 at 07:19
  • Your question is getting interesting. Edit it and discuss what you've tried, what isn't working, and what you're hoping to achieve and you'll get better responses! – par Dec 11 '14 at 07:22
  • @par edited, but I don't know if I added anything of value. – jsh123 Dec 11 '14 at 07:28
  • Instead of looking for absolute peaks, try looking for inflection points. – tzaman Dec 11 '14 at 07:32
  • @tzaman How would I do that given just a list of data points? – jsh123 Dec 11 '14 at 07:40
  • I'm not sure how this would be done without having a starting point, for instance imagine a sine wave with practically infinite frequency, it would fit any data perfectly! – 101 Dec 11 '14 at 07:46
  • A typical scipy fitting example (of a sine curve) is http://wiki.scipy.org/Cookbook/FittingData . –  Dec 11 '14 at 07:52

1 Answers1

1

I am not going to give you code, but this is probably what I would try. Success is highly dependant on how good your data is. For the last step, to get the final values for amplitude, frequency and phase, you could use some optimization framework. It's just that this usually requires a pretty good initial solution. But if we assume that the data is generated as x(t) = A*sin(2*pi*f*t + phi) + w(t) where w(t) is additive, zero-mean, noise the following could work:

  1. Estimate the frequency by finding the peak in the amplitude spectrum of the signal, using the DFT.
  2. Estimate the amplitude by looking at the maximum/minimum signal value. Some pre-filtering (simple low pass?) might be required to get a good estimate.
  3. Use optimization to find phase and fine tune the amplitude and frequency.
Hannes Ovrén
  • 21,229
  • 9
  • 65
  • 75