2

I am analyzing an image of two crossing lines (like a + sign) and I am extracting a line of pixels (an nx1 numpy array) perpendicular to one of the lines. This gives me an array of floating point values (representing colors) that I can then plot. I am plotting the data with matplotlib and I get a bunch of noisy data between 180 and 200 with a distinct peak in the middle that spikes down to around 100.

I need to find FWHM of this data. I figured I needed to filter the noise first, so I used a gaussian filter, which smoothed out my data, but its still not super flat at the top.

  1. I was wondering if there is a better way to filter the data.

  2. How can I find the FWHM of this data?

I would like to only use numpy, scipy, and matplotlib if possible.

Here is the original data: Original Data

Here is the filtered data: Filtered Data

Brian Tompsett - 汤莱恩
  • 5,753
  • 72
  • 57
  • 129
SFBA26
  • 870
  • 3
  • 12
  • 24
  • Sorry for the lack of pictures...I can't add pictures until my reputation is above 10 (just signed up today). – SFBA26 Jun 12 '14 at 21:33
  • Welcome to Stack Overflow! It looks like you want us to write some code for you. While many users are willing to produce code for a coder in distress, they usually only help when the poster has already tried to solve the problem on their own. A good way to demonstrate this effort is to include the code you've written so far, example input (if there is any), the expected output, and the output you actually get (console output, stack traces, compiler errors - whatever is applicable). The more detail you provide, the more answers you are likely to receive. Check the [FAQ] and [ask] – Ffisegydd Jun 12 '14 at 21:47
  • The FWHM answer at http://stackoverflow.com/questions/10582795/finding-the-full-width-half-maximum-of-a-peak should point you in the right direction. – Jim Mahoney Jun 13 '14 at 16:59

2 Answers2

0

I ended up not using any filter, but rather used the original data. The procedure I used was:

  • Found the minimum and maximum points and calculated difference = max(arr_y) - min(arr_y)
  • Found the half max (in my case it is half min) HM = difference / 2
  • Found the nearest data point to HM: nearest = (np.abs(arr_y - HM)).argmin()
  • Calculated the distance between nearest and min (this gives me the HWHM)
  • Then simply multiplied by 2 to get the FWHM

I don't know (or think) this is the best way, but it works and seems to be fairly accurate based on comparison.

strpeter
  • 2,562
  • 3
  • 27
  • 48
SFBA26
  • 870
  • 3
  • 12
  • 24
0

Your script does already the correct calculation.

But the error from your distance between nearest and pos_extremum can be reduced when taking the distance between nearest_above and nearest_below - the positions at half the extremal value (maximum/minimum) on both its sides.

import numpy as np

# Example data
arr_x = np.linspace(norm.ppf(0.00001), norm.ppf(0.99999), 10000)
arr_y = norm.pdf(arr_x)

# Effective code
difference = max(arr_y) - min(arr_y)
HM = difference / 2

pos_extremum = arr_y.argmax()  # or in your case: arr_y.argmin()

nearest_above = (np.abs(arr_y[pos_extremum:-1] - HM)).argmin()
nearest_below = (np.abs(arr_y[0:pos_extremum] - HM)).argmin()

FWHM = (np.mean(arr_x[nearest_above + pos_extremum]) - 
        np.mean(arr_x[nearest_below]))

For this example you should receive the relation between FWHM and the standard deviation: FWHM = 2.355 times the standard deviation (here 1) as mentioned on Wikipedia.

strpeter
  • 2,562
  • 3
  • 27
  • 48