Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Determine "wiggliness" of set of data - Python

I'm working on a piece of software which needs to implement the wiggliness of a set of data. Here's a sample of the input I would receive, merged with the lightness plot of each vertical pixel strip: alt text

It is easy to see that the left margin is really wiggly (i.e. has a ton of minima/maxima), and I want to generate a set of critical points of the image. I've applied a Gaussian smoothing function to the data ~ 10 times, but it seems to be pretty wiggly to begin with.

Any ideas?

Here's my original code, but it does not produce very nice results (for the wiggliness):

def local_maximum(list, center, delta):
  maximum = [0, 0]

  for i in range(delta):
    if list[center + i] > maximum[1]: maximum = [center + i, list[center + i]]
    if list[center - i] > maximum[1]: maximum = [center - i, list[center - i]]

  return maximum

def count_maxima(list, start, end, delta, threshold = 10):
      count = 0

  for i in range(start + delta, end - delta):
    if abs(list[i] - local_maximum(list, i, delta)[1]) < threshold: count += 1

  return count

def wiggliness(list, start, end, delta, threshold = 10):
  return float(abs(start - end) * delta) / float(count_maxima(list, start, end, delta, threshold))
like image 425
Blender Avatar asked Nov 16 '10 06:11

Blender


2 Answers

Take a look at lowpass/highpass/notch/bandpass filters, fourier transforms, or wavelets. The basic idea is there's lots of different ways to figure out the frequency content of a signal quantized over different time-periods.

If we can figure out what wiggliness is, that would help. I would say the leftmost margin is wiggly b/c it has more high-frequency content, which you could visualize by using a fourier transform.

If you take a highpass filter of that red signal, you'll get just the high frequency content, and then you can measure the amplitudes and do thresholds to determine wiggliness. But I guess wiggliness just needs more formalism behind it.

like image 133
gtrak Avatar answered Sep 18 '22 13:09

gtrak


For things like these, numpy makes things much easier, as it provides useful functions for manipulating vector data, e.g. adding a scalar to each element, calculating the average value etc.

For example, you might try with zero crossing rate of either the original data-wiggliness1 or the first difference-wiggliness2 (depending on what wiggliness is supposed to be, exactly-if global trends are to be ignored, you should probably use the difference data). For x you would take the slice or window of interest from the original data, getting a sort of measure of local wiggliness. If you use the original data, after removing the bias you might also want to set all values smaller than some threshold to 0 to ignore low-amplitude wiggles.

import numpy as np

def wiggliness1(x):
    #remove bias:
    x=x-np.average(x)
    #calculate zero crossing rate:
    np.sum(np.abs(np.sign(np.diff(x))))


def wiggliness(x):
    #calculate zero crossing rate of the first difference:
    return np.sum(np.abs(np.sign(np.diff(np.sign(np.diff(x))))))
like image 23
miro Avatar answered Sep 18 '22 13:09

miro