Python [Python] Optimization: determining gradient with variable window size

Click For Summary
The discussion revolves around optimizing a Python program that analyzes data from a mechanical testing experiment on rocks. The current implementation for estimating the gradient is inefficient, taking about four minutes to process, primarily due to a loop that checks for significant differences in data points within a growing window. The user seeks advice on improving this method, acknowledging its sensitivity to noise and the handling of array boundaries.Suggestions include using a Gaussian blur to smooth the data before calculating the gradient, which can help mitigate noise issues. An alternative approach involves leveraging Fourier transforms to compute the gradient more efficiently. The user has attempted smoothing and central differences but found the results still noisy, indicating a challenge in balancing noise reduction with data integrity. Overall, the thread highlights the need for more efficient algorithms and techniques to handle large datasets effectively while maintaining accuracy.
Avarus
Messages
11
Reaction score
0
Hi all, I'm not quite sure if this is the right place to post my question, so forgive me if its not...

I've written a program in Python that analyses data that I got from a compression experiment (mechanical testing of rocks and such), and I've written a piece of code that estimates the gradient of a given quantity. It seems to work fine, but it is very slow. Whereas the rest of the program does its job in about 10 seconds, this little piece of code takes about 4 minutes to execute.

Code:
# written in Python
while not done:
   i += 10 
   start = n-i
   end = n+i
   if n-i < 0:
      start = 0
      end = n+2*i
   if n+i > len(data)-1:
      end = len(data)-1
      start = n-i
      if start < 0:
         start = 0 
   if absolute(data[start] - data[end]) >= std/0.05:
      done = True
      windows[n] = end - start

Note that this is an excerpt that takes up almost 100% of the function's computation time, so I left out the rest. What does this piece do? It starts with a window of size 10, then checks if the values of the first and last datapoint in this window differ more than a given value (so that the difference is significant). If they do, the window size is correct, if they don't, the window size grows by 20 and check again, etc. The if statements in there are to make sure the window does not fall outside the data.

So I know this method works, but I realize this is horribly inefficient, since most window sizes are about 400 in width, some even up to 2000. Having about 500,000 datapoints to process, this loop occurs about 10,000,000 times for the entire dataset. My mathematical basis for these kind of things is not too good, but do you guys perhaps know a more elegant method? Or do you have any other optimization tips?

Thanks
 
Technology news on Phys.org


Your approach is rather sensitive to noise - a single outlier can give you unexpectedly narrow windows at ten-pixel intervals on either side of it. Also, you are handling the ends of the array differently. You either need to change end=n+2*i to just end=n+i in the first if, or start=n-i to start=n-2*i in the second.

If you're not wedded to this idea, I can offer an alternative:
- Smooth your function using a Gaussian blur
- Calculate the gradient of that smoothed function

It turns out that you can do this by populating an array with the first derivative of a Gaussian function, Fourier transforming it, Fourier transforming your data, multiplying the arrays point-by-point, and inverse Fourier transforming the product. If you can install the numpy library, that will do 99.9% of the hard work for you - happy to help.
 


Ibix said:
Your approach is rather sensitive to noise - a single outlier can give you unexpectedly narrow windows at ten-pixel intervals on either side of it. Also, you are handling the ends of the array differently. You either need to change end=n+2*i to just end=n+i in the first if, or start=n-i to start=n-2*i in the second.

If you're not wedded to this idea, I can offer an alternative:
- Smooth your function using a Gaussian blur
- Calculate the gradient of that smoothed function

It turns out that you can do this by populating an array with the first derivative of a Gaussian function, Fourier transforming it, Fourier transforming your data, multiplying the arrays point-by-point, and inverse Fourier transforming the product. If you can install the numpy library, that will do 99.9% of the hard work for you - happy to help.

Thanks for the suggestions. What I did not include into this post is that the slope will be calculated using OLS over the number of datapoints that are required to make the slope significant, i.e. the difference between the starting and end point being 20x standard deviation of the noise.

I've tried smoothing the signal and calculating the gradient using central differences, but that still resulted into very noisy results. More smoothing would result into 'cutting corners' off my data...


So again, thanks for your suggestions, but I've been there already.
 
Learn If you want to write code for Python Machine learning, AI Statistics/data analysis Scientific research Web application servers Some microcontrollers JavaScript/Node JS/TypeScript Web sites Web application servers C# Games (Unity) Consumer applications (Windows) Business applications C++ Games (Unreal Engine) Operating systems, device drivers Microcontrollers/embedded systems Consumer applications (Linux) Some more tips: Do not learn C++ (or any other dialect of C) as a...

Similar threads

Replies
3
Views
2K
  • · Replies 11 ·
Replies
11
Views
923
  • · Replies 15 ·
Replies
15
Views
2K
  • · Replies 6 ·
Replies
6
Views
4K
  • · Replies 56 ·
2
Replies
56
Views
10K
Replies
7
Views
2K
  • · Replies 2 ·
Replies
2
Views
2K
  • · Replies 9 ·
Replies
9
Views
3K
Replies
55
Views
6K
  • · Replies 8 ·
Replies
8
Views
3K