1

Good afternoon everybody, I was putting raw data into numpy arrays, then I wanted to perform operations, as logarithm base 10, with "if"s to those arrays, nevertheless, those numpy arrays are too big and consequently they take a lot of time to complete them.

enter image description here

x = [ 20*math.log10(i) if i>0 and 20*math.log10(i)>=-60 else (-(120+20*math.log10(abs(i))) if i<0 and 20*math.log10(abs(i))>=-60 else -60) for i in a3 ]

In the piece of code before, I use one of the channels array throwed out from the raw audio data, "a3", and I made another array, "x", that will contain an array to plot from -120 to 0, in the y edge. Futhermore, as you could note, I needed to separate positive original elements from numpy array than negative original elements from numpy array, and also 0s, being -60 the after operations 0. Having this final plot: enter image description here

The problem with this code, is that, as I said before, it takes approximately 10 seconds to finish the computing, and this is only for 1 channel, and I need to compute 8 channels, so I need to wait approximately 80 seconds.

I wanted to know if there is a faster way to perform this, in addition, I found out a way to apply numpy.log10 to the whole numpy array, and it compute in less than two seconds:

x = 20*numpy.log10(abs(a3))

But I did not find anything related to manipulate the preferences of that operation, numpy.log10, with ifs, conditionals, or something like that. I really need to identify the negative and positive original values, and also the 0s, and obviously transform the 0 to -60, making the -60 the minimum limit, and the reference point, as the code that I showed you before.

Note: I already tried to do it with loops, like "for" and "while", but it takes way more time than the actual method, like 14 second each one.

Thank you for your responses!!

3
  • 1
    The list comprehension is so long that it's unreadable Commented Jan 2, 2019 at 23:13
  • 3
    x = [ 20*math.log10(i) if i>0 and 20*math.log10(i)>=-60 else (-(120+20*math.log10(abs(i))) if i<0 and 20*math.log10(abs(i))>=-60 else -60) for i in a3 ] is unmaintainable. Please show an example input and output. numpy functions aren't faster when applied in a list comprehension. Commented Jan 2, 2019 at 23:14
  • 1
    Just yesterday I showed how to apply a conditional to np.log, stackoverflow.com/a/53993190/901925 Commented Jan 3, 2019 at 0:24

1 Answer 1

0

In general, when posting questions, its best practice to include a small working example. I know you included a picture of your data, but that is hard for others to use, so it would have been better to just give us a small array of data. This is important, because the solution often depends on the data. For example, all your data is (i think) between -1 and 1 so that log is always negative. If this isn't the case, then your solution might not work.

There is no need to check if i>0 and then apply abs if i is negative. This is exactly what applying abs does in the first place.

As you noticed, we can also use numpy vectorization to avoid the list comprehension. It is usually faster to do something like np.sin(X) than [ np.sin(x) for x in X].

Finally, if you do something like X>0 in numpy, it returns a boolean array saying if each element is >0.

Note that another way to have written your list comprehension would be first take 20*math.log10(abs(i)) and replace all values <-60 with -60 and then anywhere where i<0, flip the data about -60`. We can do this in the vectorized operation.

-120*(a3<0)+np.sign(a3)*np.maximum(20*np.log10(np.abs(a3)),-60)

This can probably be optimized a bit since a3<0 and np.sign(a3) are doing similar things. That said, I'm pretty sure this is faster than list comprehensions.

Sign up to request clarification or add additional context in comments.

2 Comments

Oh, sorry about that, I forget to put the reason about this. I wanted to convert a plot from ratio(percent -1 to 1) to dB (-60 to -60), as Audacity:
Sorry about that, I forget to put the reason about this. I wanted to convert a plot from ratio(percent -1 to 1) to dB (0 to 0, with a central edge of -60), as Audacity. This is a little bit confusing, because, you can't make a plot from 0 to 0 having any central edge, but I realize that in the Audacity representation, it plots in the upper side the positives from the ratio, and in the lower side the negatives from the ratio, and also it represents the zero values as -60. So I change the scale, from positive ratio values -60 to 0, and for negatives -120 to -60, being -120 the negative 0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.