Ok so I have the code below for real-time graphing some data from an embedded device received over serial. It's not meant to be a production tool but rather an internal eng tool, hence it's not terribly user-friendly. The problem is that no matter what I do, I can't get minor grid lines to appear, even though here they are set to True, which=both
. I can do anything I want to the major grid lines but the minors won't appear. Any ideas? Here is the code:
import numpy as np
from matplotlib import pyplot as plt
from matplotlib import animation
import serial
SERIAL_PORT_NUM=9
...a bunch of constants...
#windows starts serial port numbers at 1, python starts at 0
SERIAL_PORT_NUM = SERIAL_PORT_NUM - 1
"""
Open the serial port
"""
ser =serial.Serial(port=SERIAL_PORT_NUM,baudrate=115200,bytesize=8,parity='N',stopbits=1,timeout=None,xonxoff=0,rtscts=0)
# First set up the figure, the axis, and the plot element we want to animate
raw_adc_fig = plt.figure()
raw_adc_ax = plt.axes(xlim=(0, 200), ylim=(0, 2047))
raw_adc_ax.grid(True, which='both')
raw_adc_fig.suptitle("Raw ADC data")
plt.ylabel("ADC values (hex)")
plt.xlabel("time (sec)")
raw_adc_line, = raw_adc_ax.plot([], [], lw=2)
def read_serial(serial_port):
tmp = ''
same_line = True
while same_line:
tmp += serial_port.read(1)
if tmp != '':
if tmp[-1] == '*':
same_line = False
tmp = tmp.rstrip()
tmp = tmp.lstrip()
return tmp
def process_serial(input_data):
output_data = 0
intermediate_data = input_data[A_TYPE_START_POS:A_TYPE_STOP_POS + 1]
if( intermediate_data != ''):
output_data = int(intermediate_data , 16 )
else:
print "bad data"
output_data = -100
return output_data
def get_sound_value(serial_port):
cur_line = ''
get_next_line = True
# read in the next line until a sound packet of type A is found
while( get_next_line ):
cur_line = read_serial(serial_port)
if( (cur_line != '') and (cur_line[0:3] == ROUTER_SOUND_DATA) and (len(cur_line) == D_TYPE_STOP_POS + 2) ):
get_next_line = False
sound_value = process_serial(cur_line)
return sound_value
# initialization function: plot the background of each frame
def raw_adc_init():
raw_adc_line.set_data([], [])
return raw_adc_line,
# animation function. This is called sequentially
def raw_adc_animate(i):
sound_data_list.append( get_sound_value(ser) )
y = sound_data_list
if( len(y) == 190 ):
del y[0]
x = np.linspace(0, len(y), len(y))
raw_adc_line.set_data(x, y)
return raw_adc_line,
# call the animator. blit=True means only re-draw the parts that have changed.
raw_adc_anim = animation.FuncAnimation(raw_adc_fig, raw_adc_animate, init_func=raw_adc_init, frames=200, interval=1000, blit=True)
Edit: fixed a bug in opening the serial port. Changed timeout=0
to timeout=None
.
Matplotlib doesn't show the minor ticks / grid by default so you also need explicitly show them using minorticks_on() .
MatPlotLib with Python Make x and y margins 0. To set X-grids, we can pass input ticks points. To lay out the grid lines in current line style, use grid(True) method. To display the figure, use show() method.
On value axes, major grid lines are drawn for every major axis division. Minor grid lines separate the units delineated by major grid lines. Minor grid lines, which can only appear on value axes, appear for every minor axis division. By default, major grid lines appear for value axes.
Unfortunately, ax.grid
is a bit confusing in this regard. (This is a design bug / common gotcha.) It turns the minor grid on, but the minor ticks are still turned off.
What you need to do is call plt.minorticks_on
or ax.minorticks_on
in addition to calling ax.grid(True, which='both')
.
You should use plt.minorticks_on()
.
import matplotlib.pyplot as plt
import numpy as np
fig = plt.figure(1)
ax = fig.add_subplot(111)
x = np.linspace(0,10,41)
y = np.sin(x)
plt.plot(x,y)
plt.grid(b=True, which='major', color='k', linestyle='-')
plt.grid(b=True, which='minor', color='r', linestyle='-', alpha=0.2)
plt.minorticks_on()
plt.show()
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With