Skip to content

Commit f18a978

Browse files
committed
Add custom minor tick class for polar plots
1 parent c4e98a5 commit f18a978

File tree

1 file changed

+59
-2
lines changed

1 file changed

+59
-2
lines changed

hexrdgui/image_canvas.py

Lines changed: 59 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import copy
22
import math
3+
import logging
34

45
from PySide6.QtCore import QThreadPool, QTimer, Signal, Qt
56
from PySide6.QtWidgets import QFileDialog, QMessageBox
@@ -10,6 +11,7 @@
1011
from matplotlib.patches import Circle
1112
from matplotlib.ticker import AutoLocator, AutoMinorLocator, FuncFormatter
1213

14+
import matplotlib as mpl
1315
import matplotlib.pyplot as plt
1416
import matplotlib.transforms as tx
1517

@@ -1042,7 +1044,7 @@ def finish_show_polar(self, iviewer):
10421044
self.axis.yaxis.set_minor_locator(AutoMinorLocator())
10431045

10441046
self.axis.xaxis.set_major_locator(PolarXAxisTickLocator(self))
1045-
self.axis.xaxis.set_minor_locator(AutoMinorLocator())
1047+
self.axis.xaxis.set_minor_locator(PolarXAxisMinorTickLocator(self))
10461048

10471049
kwargs = {
10481050
'left': True,
@@ -1103,7 +1105,7 @@ def finish_show_polar(self, iviewer):
11031105
axis.yaxis.set_minor_locator(AutoMinorLocator())
11041106

11051107
axis.xaxis.set_major_locator(PolarXAxisTickLocator(self))
1106-
axis.xaxis.set_minor_locator(AutoMinorLocator())
1108+
self.axis.xaxis.set_minor_locator(PolarXAxisMinorTickLocator(self))
11071109

11081110
# change property of ticks
11091111
kwargs = {
@@ -1836,6 +1838,61 @@ def tick_values(self, vmin, vmax):
18361838
# Convert back to tth
18371839
return canvas.polar_x_type_to_tth(values)
18381840

1841+
class PolarXAxisMinorTickLocator(AutoMinorLocator):
1842+
"""Subclass the tick locator so we can modify its behavior
1843+
1844+
We will modify any value ranges provided so that the current x-axis type
1845+
provides nice looking ticks.
1846+
1847+
For instance, for Q, we want to space minor ticks non-linearly between major ticks
1848+
"""
1849+
def __init__(self, canvas, *args, **kwargs):
1850+
super().__init__(*args, **kwargs)
1851+
self._hexrdgui_canvas = canvas
1852+
1853+
def __call__(self):
1854+
canvas = self._hexrdgui_canvas
1855+
if self.axis.get_scale() == 'log':
1856+
logging.warning('PolarXAxisMinorTickLocator does not work on logarithmic scales')
1857+
return []
1858+
1859+
majorlocs = np.unique(self.axis.get_majorticklocs())
1860+
if len(majorlocs) < 2:
1861+
# Need at least two major ticks to find minor tick locations.
1862+
# TODO: Figure out a way to still be able to display minor ticks with less
1863+
# than two major ticks visible. For now, just display no ticks at all.
1864+
return []
1865+
1866+
# Convert to our current x type
1867+
majorlocs = canvas.polar_tth_to_x_type(majorlocs)
1868+
majorstep = majorlocs[1] - majorlocs[0]
1869+
1870+
if self.ndivs is None:
1871+
self.ndivs = mpl.rcParams[
1872+
'ytick.minor.ndivs' if self.axis.axis_name == 'y'
1873+
else 'xtick.minor.ndivs'] # for x and z axis
1874+
1875+
if self.ndivs == 'auto':
1876+
majorstep_mantissa = 10 ** (np.log10(majorstep) % 1)
1877+
ndivs = 5 if np.isclose(majorstep_mantissa, [1, 2.5, 5, 10]).any() else 4
1878+
else:
1879+
ndivs = self.ndivs
1880+
1881+
minorstep = majorstep / ndivs
1882+
1883+
vmin, vmax = sorted(self.axis.get_view_interval())
1884+
# Convert to our current x type
1885+
vmin, vmax = canvas.polar_tth_to_x_type([vmin, vmax])
1886+
t0 = majorlocs[0]
1887+
tmin = round((vmin - t0) / minorstep)
1888+
tmax = round((vmax - t0) / minorstep) + 1
1889+
locs = (np.arange(tmin, tmax) * minorstep) + t0
1890+
1891+
# Convert back to tth
1892+
locs = canvas.polar_x_type_to_tth(locs)
1893+
1894+
return self.raise_if_exceeds(locs)
1895+
18391896

18401897
class PolarXAxisFormatter(FuncFormatter):
18411898
"""Subclass the func formatter so we can keep the default formatter in sync

0 commit comments

Comments
 (0)