ederwander
ederwander

Reputation: 3478

how to plot on a smaller scale

I am using matplotlib and I'm finding some problems when trying to plot large vectors. sometimes get "MemoryError" My question is whether there is any way to reduce the scale of values ​​that i need to plot ?

enter image description here

In this example I'm plotting a vector with size 2647296!

is there any way to plot the same values ​​on a smaller scale?

Upvotes: 4

Views: 1228

Answers (2)

DaveTM
DaveTM

Reputation: 756

You can use a min/max for each block of data to subsample the signal.

Window size would have to be determined based on how accurately you want to display your signal and/or how large the window is compared to the signal length.

Example code:

from scipy.io import wavfile
import matplotlib.pyplot as plt

def value_for_window_min_max(data, start, stop):
    min = data[start]
    max = data[start]

    for i in range(start,stop):
        if data[i] < min:
            min = data[i]
        if data[i] > max:
            max = data[i]

    if abs(min) > abs(max):
        return min
    else:
        return max

# This will only work properly if window_size divides evenly into len(data)
def subsample_data(data, window_size):
    print len(data)
    print len(data)/window_size

    out_data = []

    for i in range(0,(len(data)/window_size)):
        out_data.append(value_for_window_min_max(data,i*window_size,i*window_size+window_size-1))

    return out_data


sample_rate, data = wavfile.read('<path_to_wav_file>')

sub_amt = 10
sub_data = subsample_data(data, sub_amt)

print len(data)
print len(sub_data)

fig = plt.figure(figsize=(8,6), dpi=100)
fig.add_subplot(211)
plt.plot(data)
plt.title('Original')
plt.xlim([0,len(data)])
fig.add_subplot(212)
plt.plot(sub_data)
plt.xlim([0,len(sub_data)])
plt.title('Subsampled by %d'%sub_amt)
plt.show()

Output: enter image description here

Upvotes: 1

Jouni K. Sepp&#228;nen
Jouni K. Sepp&#228;nen

Reputation: 44172

It is very unlikely that you have so much resolution on your display that you can see 2.6 million data points in your plot. A simple way to plot less data is to sample e.g. every 1000th point: plot(x[::1000]). If that loses too much and it is e.g. important to see the extremal values, you could write some code to split the long vector into suitably many parts and take the minimum and maximum of each part, and plot those:

tmp = x[:len(x)-len(x)%1000] # drop some points to make length a multiple of 1000
tmp = tmp.reshape((1000,-1)) # split into pieces of 1000 points
tmp = tmp.reshape((-1,1000)) # alternative: split into 1000 pieces
figure(); hold(True)         # plot minimum and maximum in the same figure
plot(tmp.min(axis=0))
plot(tmp.max(axis=0))

Upvotes: 9

Related Questions