|
1 | 1 | import copy |
2 | 2 | import math |
| 3 | +import logging |
3 | 4 |
|
4 | 5 | from PySide6.QtCore import QThreadPool, QTimer, Signal, Qt |
5 | 6 | from PySide6.QtWidgets import QFileDialog, QMessageBox |
|
10 | 11 | from matplotlib.patches import Circle |
11 | 12 | from matplotlib.ticker import AutoLocator, AutoMinorLocator, FuncFormatter |
12 | 13 |
|
| 14 | +import matplotlib as mpl |
13 | 15 | import matplotlib.pyplot as plt |
14 | 16 | import matplotlib.transforms as tx |
15 | 17 |
|
@@ -1042,7 +1044,7 @@ def finish_show_polar(self, iviewer): |
1042 | 1044 | self.axis.yaxis.set_minor_locator(AutoMinorLocator()) |
1043 | 1045 |
|
1044 | 1046 | 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)) |
1046 | 1048 |
|
1047 | 1049 | kwargs = { |
1048 | 1050 | 'left': True, |
@@ -1103,7 +1105,7 @@ def finish_show_polar(self, iviewer): |
1103 | 1105 | axis.yaxis.set_minor_locator(AutoMinorLocator()) |
1104 | 1106 |
|
1105 | 1107 | axis.xaxis.set_major_locator(PolarXAxisTickLocator(self)) |
1106 | | - axis.xaxis.set_minor_locator(AutoMinorLocator()) |
| 1108 | + self.axis.xaxis.set_minor_locator(PolarXAxisMinorTickLocator(self)) |
1107 | 1109 |
|
1108 | 1110 | # change property of ticks |
1109 | 1111 | kwargs = { |
@@ -1836,6 +1838,61 @@ def tick_values(self, vmin, vmax): |
1836 | 1838 | # Convert back to tth |
1837 | 1839 | return canvas.polar_x_type_to_tth(values) |
1838 | 1840 |
|
| 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 | + |
1839 | 1896 |
|
1840 | 1897 | class PolarXAxisFormatter(FuncFormatter): |
1841 | 1898 | """Subclass the func formatter so we can keep the default formatter in sync |
|
0 commit comments