Draw markers at intersections of grid's minor ticks

Viewed 190

I would like to produce a plot with a grid, so that a full line is drawn at major ticks, and intersections of minor ticks are marked by squares (or any customisable marker).

Here is an example of what I'm trying to achieve:enter image description here

I generated this plot with the following code, using RegularPolyCollection:

import numpy as np
import matplotlib.pyplot as plt
from matplotlib.collections import RegularPolyCollection

# Define dimensions and create plotting objects
width_squares = 6
height_squares = 6
figure = plt.figure()
ax = figure.add_subplot(111)

# Define ticks
x_minors = np.linspace(0, width_squares, 5 * width_squares + 1)
x_majors = np.linspace(0, width_squares, width_squares + 1)
y_minors = np.linspace(0, height_squares, 5 * height_squares + 1)
y_majors = np.linspace(0, height_squares, height_squares + 1)

# Set ticks
ax.set_xticks(x_majors)
ax.set_xticks(x_minors, minor=True)
ax.set_yticks(y_majors)
ax.set_yticks(y_minors, minor=True)

# Define window
ax.set_xlim((0, 6))
ax.set_ylim((0, 6))

# Draw the point collection: squares rotated by 45°
offsets = [(x, y) for x in x_minors for y in y_minors]
points = RegularPolyCollection(
    4,
    sizes=(1,),
    offsets=offsets, 
    color=('lightgray',),
    transOffset=ax.transData,
    rotation=0.7857
)
ax.add_collection(points)

# Draw the grid at major ticks
ax.grid(True, which='major', axis='both', color='lightgray')

plt.show()

However, the plot I'm actually trying to produce are way bigger, and performance is at stake. Unfortunately, drawing a large collection of points is very time consuming.

I also investigated based on this question, and I produced a similar result by drawing vertical lines with linestyle set to "None", so that only intersections are marked, but the time consumption is similar to the collection approach.

I suspect there should be a combination of parameters for the plt.grid function that would produce what I want, but I could not understand the effect of markevery and other keyword arguments (while I do understand their meaning when used with Line2D objects).

Is there a standard way to produce such a grid? If so, is it possible to make it little time-consuming?

1 Answers

I am not sure if you tried the version from one of the answers provided in the link you shared. The main modification I had to do was to turn on the minor ticks while getting the x-tick and y-tick data. Do you have any numbers comparing the time complexity for this approach and the Line2D?

# Draw the grid at major ticks
ax.grid(True, which='major', axis='both')
ax.set_aspect('equal')

def set_grid_cross(ax):
    xticks = ax.get_xticks(minor=True)
    yticks = ax.get_yticks(minor=True)
    xgrid, ygrid = np.meshgrid(xticks, yticks)
    kywds = dict() 
    grid_lines = ax.plot(xgrid, ygrid, 'o', ms=2, color='lightgray', alpha=0.5)

set_grid_cross(ax)

enter image description here

Related