From f75ed38efafa7a44c71edb9a1ec5f0f94b33743c Mon Sep 17 00:00:00 2001 From: NikosNikolaidis02 Date: Sun, 18 Jun 2023 11:38:30 +0300 Subject: [PATCH 1/9] Resolving issue #26092 --- lib/matplotlib/image.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/lib/matplotlib/image.py b/lib/matplotlib/image.py index 135934a244a8..9aeb33f3deb1 100644 --- a/lib/matplotlib/image.py +++ b/lib/matplotlib/image.py @@ -553,9 +553,11 @@ def _make_image(self, A, in_bbox, out_bbox, clip_bbox, magnification=1.0, else: if A.ndim == 2: # _interpolation_stage == 'rgba' self.norm.autoscale_None(A) - A = self.to_rgba(A) - if A.shape[2] == 3: + A = self.to_rgba(A, alpha=self.get_alpha()) + elif A.shape[2] == 3: A = _rgb_to_rgba(A) + if alpha := self.get_alpha is not None: + A[:, :, 3] = self.get_alpha() alpha = self._get_scalar_alpha() output_alpha = _resample( # resample alpha channel self, A[..., 3], out_shape, t, alpha=alpha) From f673a74ddc1a5f4aef96ce03f1a7a70a77d80874 Mon Sep 17 00:00:00 2001 From: NikosNikolaidis02 Date: Mon, 19 Jun 2023 12:40:58 +0300 Subject: [PATCH 2/9] Fixing issue on testing --- lib/matplotlib/image.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/matplotlib/image.py b/lib/matplotlib/image.py index 9aeb33f3deb1..f0f62db2dd82 100644 --- a/lib/matplotlib/image.py +++ b/lib/matplotlib/image.py @@ -556,7 +556,7 @@ def _make_image(self, A, in_bbox, out_bbox, clip_bbox, magnification=1.0, A = self.to_rgba(A, alpha=self.get_alpha()) elif A.shape[2] == 3: A = _rgb_to_rgba(A) - if alpha := self.get_alpha is not None: + if (alpha := self.get_alpha) is not None: A[:, :, 3] = self.get_alpha() alpha = self._get_scalar_alpha() output_alpha = _resample( # resample alpha channel From 568a52332b29ae423c8edd854b5f42e9b36b9f80 Mon Sep 17 00:00:00 2001 From: NikosNikolaidis02 <92633955+NikosNikolaidis02@users.noreply.github.com> Date: Mon, 19 Jun 2023 16:19:05 +0300 Subject: [PATCH 3/9] Update image.py --- lib/matplotlib/image.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/matplotlib/image.py b/lib/matplotlib/image.py index f0f62db2dd82..7755bb419efd 100644 --- a/lib/matplotlib/image.py +++ b/lib/matplotlib/image.py @@ -557,7 +557,7 @@ def _make_image(self, A, in_bbox, out_bbox, clip_bbox, magnification=1.0, elif A.shape[2] == 3: A = _rgb_to_rgba(A) if (alpha := self.get_alpha) is not None: - A[:, :, 3] = self.get_alpha() + A[:, :, 3] = self.get_alpha alpha = self._get_scalar_alpha() output_alpha = _resample( # resample alpha channel self, A[..., 3], out_shape, t, alpha=alpha) From 69c177ccb6f5888038e13b6bc1eaa1b34b6dc7a3 Mon Sep 17 00:00:00 2001 From: NikosNikolaidis02 Date: Tue, 20 Jun 2023 20:53:45 +0300 Subject: [PATCH 4/9] Updating testing --- lib/matplotlib/image.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/matplotlib/image.py b/lib/matplotlib/image.py index 7755bb419efd..5b1dd732f0e9 100644 --- a/lib/matplotlib/image.py +++ b/lib/matplotlib/image.py @@ -556,8 +556,8 @@ def _make_image(self, A, in_bbox, out_bbox, clip_bbox, magnification=1.0, A = self.to_rgba(A, alpha=self.get_alpha()) elif A.shape[2] == 3: A = _rgb_to_rgba(A) - if (alpha := self.get_alpha) is not None: - A[:, :, 3] = self.get_alpha + if (alpha := self.get_alpha()) is not None: + A[:, :, 3] = self.get_alpha() alpha = self._get_scalar_alpha() output_alpha = _resample( # resample alpha channel self, A[..., 3], out_shape, t, alpha=alpha) From d1df3bc96f6bb24aeed66a86e8fa69a36a8f607a Mon Sep 17 00:00:00 2001 From: NikosNikolaidis02 Date: Fri, 23 Jun 2023 21:22:52 +0300 Subject: [PATCH 5/9] Changing image.py to original --- lib/matplotlib/image.py | 108 +++++++++++++++------------------------- 1 file changed, 41 insertions(+), 67 deletions(-) diff --git a/lib/matplotlib/image.py b/lib/matplotlib/image.py index 5b1dd732f0e9..ade9ba6761f4 100644 --- a/lib/matplotlib/image.py +++ b/lib/matplotlib/image.py @@ -553,11 +553,9 @@ def _make_image(self, A, in_bbox, out_bbox, clip_bbox, magnification=1.0, else: if A.ndim == 2: # _interpolation_stage == 'rgba' self.norm.autoscale_None(A) - A = self.to_rgba(A, alpha=self.get_alpha()) - elif A.shape[2] == 3: + A = self.to_rgba(A) + if A.shape[2] == 3: A = _rgb_to_rgba(A) - if (alpha := self.get_alpha()) is not None: - A[:, :, 3] = self.get_alpha() alpha = self._get_scalar_alpha() output_alpha = _resample( # resample alpha channel self, A[..., 3], out_shape, t, alpha=alpha) @@ -690,50 +688,50 @@ def write_png(self, fname): bytes=True, norm=True) PIL.Image.fromarray(im).save(fname, format="png") - def set_data(self, A): + @staticmethod + def _normalize_image_array(A): """ - Set the image array. - - Note that this function does *not* update the normalization used. - - Parameters - ---------- - A : array-like or `PIL.Image.Image` + Check validity of image-like input *A* and normalize it to a format suitable for + Image subclasses. """ - if isinstance(A, PIL.Image.Image): - A = pil_to_array(A) # Needed e.g. to apply png palette. - self._A = cbook.safe_masked_invalid(A, copy=True) - - if (self._A.dtype != np.uint8 and - not np.can_cast(self._A.dtype, float, "same_kind")): - raise TypeError(f"Image data of dtype {self._A.dtype} cannot be " - "converted to float") - - if self._A.ndim == 3 and self._A.shape[-1] == 1: - # If just one dimension assume scalar and apply colormap - self._A = self._A[:, :, 0] - - if not (self._A.ndim == 2 - or self._A.ndim == 3 and self._A.shape[-1] in [3, 4]): - raise TypeError(f"Invalid shape {self._A.shape} for image data") - - if self._A.ndim == 3: + A = cbook.safe_masked_invalid(A, copy=True) + if A.dtype != np.uint8 and not np.can_cast(A.dtype, float, "same_kind"): + raise TypeError(f"Image data of dtype {A.dtype} cannot be " + f"converted to float") + if A.ndim == 3 and A.shape[-1] == 1: + A = A.squeeze(-1) # If just (M, N, 1), assume scalar and apply colormap. + if not (A.ndim == 2 or A.ndim == 3 and A.shape[-1] in [3, 4]): + raise TypeError(f"Invalid shape {A.shape} for image data") + if A.ndim == 3: # If the input data has values outside the valid range (after # normalisation), we issue a warning and then clip X to the bounds # - otherwise casting wraps extreme values, hiding outliers and # making reliable interpretation impossible. - high = 255 if np.issubdtype(self._A.dtype, np.integer) else 1 - if self._A.min() < 0 or high < self._A.max(): + high = 255 if np.issubdtype(A.dtype, np.integer) else 1 + if A.min() < 0 or high < A.max(): _log.warning( 'Clipping input data to the valid range for imshow with ' 'RGB data ([0..1] for floats or [0..255] for integers).' ) - self._A = np.clip(self._A, 0, high) + A = np.clip(A, 0, high) # Cast unsupported integer types to uint8 - if self._A.dtype != np.uint8 and np.issubdtype(self._A.dtype, - np.integer): - self._A = self._A.astype(np.uint8) + if A.dtype != np.uint8 and np.issubdtype(A.dtype, np.integer): + A = A.astype(np.uint8) + return A + def set_data(self, A): + """ + Set the image array. + + Note that this function does *not* update the normalization used. + + Parameters + ---------- + A : array-like or `PIL.Image.Image` + """ + if isinstance(A, PIL.Image.Image): + A = pil_to_array(A) # Needed e.g. to apply png palette. + self._A = self._normalize_image_array(A) self._imcache = None self.stale = True @@ -1151,23 +1149,15 @@ def set_data(self, x, y, A): (M, N) `~numpy.ndarray` or masked array of values to be colormapped, or (M, N, 3) RGB array, or (M, N, 4) RGBA array. """ + A = self._normalize_image_array(A) x = np.array(x, np.float32) y = np.array(y, np.float32) - A = cbook.safe_masked_invalid(A, copy=True) - if not (x.ndim == y.ndim == 1 and A.shape[0:2] == y.shape + x.shape): + if not (x.ndim == y.ndim == 1 and A.shape[:2] == y.shape + x.shape): raise TypeError("Axes don't match array shape") - if A.ndim not in [2, 3]: - raise TypeError("Can only plot 2D or 3D data") - if A.ndim == 3 and A.shape[2] not in [1, 3, 4]: - raise TypeError("3D arrays must have three (RGB) " - "or four (RGBA) color components") - if A.ndim == 3 and A.shape[2] == 1: - A = A.squeeze(axis=-1) self._A = A self._Ax = x self._Ay = y self._imcache = None - self.stale = True def set_array(self, *args): @@ -1309,28 +1299,13 @@ def set_data(self, x, y, A): - (M, N, 3): RGB array - (M, N, 4): RGBA array """ - A = cbook.safe_masked_invalid(A, copy=True) - if x is None: - x = np.arange(0, A.shape[1]+1, dtype=np.float64) - else: - x = np.array(x, np.float64).ravel() - if y is None: - y = np.arange(0, A.shape[0]+1, dtype=np.float64) - else: - y = np.array(y, np.float64).ravel() - - if A.shape[:2] != (y.size-1, x.size-1): + A = self._normalize_image_array(A) + x = np.arange(0., A.shape[1] + 1) if x is None else np.array(x, float).ravel() + y = np.arange(0., A.shape[0] + 1) if y is None else np.array(y, float).ravel() + if A.shape[:2] != (y.size - 1, x.size - 1): raise ValueError( "Axes don't match array shape. Got %s, expected %s." % (A.shape[:2], (y.size - 1, x.size - 1))) - if A.ndim not in [2, 3]: - raise ValueError("A must be 2D or 3D") - if A.ndim == 3: - if A.shape[2] == 1: - A = A.squeeze(axis=-1) - elif A.shape[2] not in [3, 4]: - raise ValueError("3D arrays must have RGB or RGBA as last dim") - # For efficient cursor readout, ensure x and y are increasing. if x[-1] < x[0]: x = x[::-1] @@ -1338,7 +1313,6 @@ def set_data(self, x, y, A): if y[-1] < y[0]: y = y[::-1] A = A[::-1] - self._A = A self._Ax = x self._Ay = y @@ -1820,4 +1794,4 @@ def thumbnail(infile, thumbfile, scale=0.1, interpolation='bilinear', frameon=False, xticks=[], yticks=[]) ax.imshow(im, aspect='auto', resample=True, interpolation=interpolation) fig.savefig(thumbfile, dpi=dpi) - return fig + return fig \ No newline at end of file From dd48d74846966512ac7a76e7f53fa987432a9d2e Mon Sep 17 00:00:00 2001 From: NikosNikolaidis02 Date: Sat, 24 Jun 2023 23:11:13 +0300 Subject: [PATCH 6/9] Adding function that computes dynamically the number of columns on mathtext symbol tables --- doc/sphinxext/math_symbol_table.py | 30 ++++++++++++++++-------------- 1 file changed, 16 insertions(+), 14 deletions(-) diff --git a/doc/sphinxext/math_symbol_table.py b/doc/sphinxext/math_symbol_table.py index 6609f91bbd10..3dea7ae6e2f4 100644 --- a/doc/sphinxext/math_symbol_table.py +++ b/doc/sphinxext/math_symbol_table.py @@ -2,37 +2,29 @@ from matplotlib import _mathtext, _mathtext_data - symbols = [ ["Lower-case Greek", - 6, r"""\alpha \beta \gamma \chi \delta \epsilon \eta \iota \kappa \lambda \mu \nu \omega \phi \pi \psi \rho \sigma \tau \theta \upsilon \xi \zeta \digamma \varepsilon \varkappa \varphi \varpi \varrho \varsigma \vartheta"""], ["Upper-case Greek", - 8, r"""\Delta \Gamma \Lambda \Omega \Phi \Pi \Psi \Sigma \Theta \Upsilon \Xi \mho \nabla"""], ["Hebrew", - 6, r"""\aleph \beth \daleth \gimel"""], ["Delimiters", - 6, r"""| \{ \lfloor / \Uparrow \llcorner \vert \} \rfloor \backslash \uparrow \lrcorner \| \langle \lceil [ \Downarrow \ulcorner \Vert \rangle \rceil ] \downarrow \urcorner"""], ["Big symbols", - 6, r"""\bigcap \bigcup \bigodot \bigoplus \bigotimes \biguplus \bigvee \bigwedge \coprod \oint \prod \sum \int"""], ["Standard function names", - 6, r"""\arccos \csc \ker \min \arcsin \deg \lg \Pr \arctan \det \lim \gcd \ln \sup \cot \hom \log \tan \coth \inf \max \tanh \sec \arg \dim \liminf \sin \cos \exp \limsup \sinh \cosh"""], ["Binary operation and relation symbols", - 4, r"""\ast \pm \slash \cap \star \mp \cup \cdot \uplus \triangleleft \circ \odot \sqcap \triangleright \bullet \ominus \sqcup \bigcirc \oplus \wedge \diamond \oslash \vee @@ -64,7 +56,6 @@ \Doteq \nsubset \eqcolon \ne """], ["Arrow symbols", - 4, r"""\leftarrow \longleftarrow \uparrow \Leftarrow \Longleftarrow \Uparrow \rightarrow \longrightarrow \downarrow \Rightarrow \Longrightarrow \Downarrow \leftrightarrow \updownarrow @@ -86,8 +77,7 @@ \nLeftrightarrow \to \Swarrow \Searrow \Nwarrow \Nearrow \leftsquigarrow """], - ["Miscellaneous symbols", - 4, + ["Miscellaneous symbols", r"""\neg \infty \forall \wp \exists \bigstar \angle \partial \nexists \measuredangle \eth \emptyset \sphericalangle \clubsuit \varnothing \complement \diamondsuit \imath \Finv \triangledown @@ -98,7 +88,6 @@ \iiint \iint \oiiint"""] ] - def run(state_machine): def render_symbol(sym): if sym.startswith("\\"): @@ -107,11 +96,24 @@ def render_symbol(sym): _mathtext.Parser._function_names): sym = chr(_mathtext_data.tex2uni[sym]) return f'\\{sym}' if sym in ('\\', '|') else sym + + def columns_calculation(list): + remainder = max_columns = columns = 10 + max_remainder = 0 + for columns_number in range(max_columns - 1, 3, -1): + # print(columns_number) + remainder = len(list) % columns_number + if remainder > max_remainder: + columns = columns_number + + return columns lines = [] - for category, columns, syms in symbols: + # for category, columns, syms in symbols: + for category, syms in symbols: syms = sorted(syms.split()) - columns = min(columns, len(syms)) + columns = columns_calculation(syms) + # columns = min(columns, len(syms)) lines.append("**%s**" % category) lines.append('') max_width = max(map(len, syms)) * 2 + 16 From c015de4f4d5c9becb5f780fca6345656829a8363 Mon Sep 17 00:00:00 2001 From: NikosNikolaidis02 Date: Sun, 25 Jun 2023 12:24:08 +0300 Subject: [PATCH 7/9] Adding a new rst file to describe this feature --- doc/users/next_whats_new/mathtext_symbols.rst | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 doc/users/next_whats_new/mathtext_symbols.rst diff --git a/doc/users/next_whats_new/mathtext_symbols.rst b/doc/users/next_whats_new/mathtext_symbols.rst new file mode 100644 index 000000000000..0df7e131f9d9 --- /dev/null +++ b/doc/users/next_whats_new/mathtext_symbols.rst @@ -0,0 +1,5 @@ +``mathtext`` documentation improvements +--------------------------------------- + +The documentation is updated to create all the tables of symbols +by calculating the number of columns in dynamic way in order to have as full of elements rows as possible :ref:`mathtext`. \ No newline at end of file From 4eb859d659bc0b79f2d785690269997793e7f4ae Mon Sep 17 00:00:00 2001 From: NikosNikolaidis02 Date: Mon, 26 Jun 2023 09:49:38 +0300 Subject: [PATCH 8/9] Returning image.py to the initial version --- lib/matplotlib/image.py | 100 +++++++++++++++++++++++++--------------- 1 file changed, 62 insertions(+), 38 deletions(-) diff --git a/lib/matplotlib/image.py b/lib/matplotlib/image.py index ade9ba6761f4..08c70f562b1f 100644 --- a/lib/matplotlib/image.py +++ b/lib/matplotlib/image.py @@ -688,37 +688,6 @@ def write_png(self, fname): bytes=True, norm=True) PIL.Image.fromarray(im).save(fname, format="png") - @staticmethod - def _normalize_image_array(A): - """ - Check validity of image-like input *A* and normalize it to a format suitable for - Image subclasses. - """ - A = cbook.safe_masked_invalid(A, copy=True) - if A.dtype != np.uint8 and not np.can_cast(A.dtype, float, "same_kind"): - raise TypeError(f"Image data of dtype {A.dtype} cannot be " - f"converted to float") - if A.ndim == 3 and A.shape[-1] == 1: - A = A.squeeze(-1) # If just (M, N, 1), assume scalar and apply colormap. - if not (A.ndim == 2 or A.ndim == 3 and A.shape[-1] in [3, 4]): - raise TypeError(f"Invalid shape {A.shape} for image data") - if A.ndim == 3: - # If the input data has values outside the valid range (after - # normalisation), we issue a warning and then clip X to the bounds - # - otherwise casting wraps extreme values, hiding outliers and - # making reliable interpretation impossible. - high = 255 if np.issubdtype(A.dtype, np.integer) else 1 - if A.min() < 0 or high < A.max(): - _log.warning( - 'Clipping input data to the valid range for imshow with ' - 'RGB data ([0..1] for floats or [0..255] for integers).' - ) - A = np.clip(A, 0, high) - # Cast unsupported integer types to uint8 - if A.dtype != np.uint8 and np.issubdtype(A.dtype, np.integer): - A = A.astype(np.uint8) - return A - def set_data(self, A): """ Set the image array. @@ -731,7 +700,38 @@ def set_data(self, A): """ if isinstance(A, PIL.Image.Image): A = pil_to_array(A) # Needed e.g. to apply png palette. - self._A = self._normalize_image_array(A) + self._A = cbook.safe_masked_invalid(A, copy=True) + + if (self._A.dtype != np.uint8 and + not np.can_cast(self._A.dtype, float, "same_kind")): + raise TypeError(f"Image data of dtype {self._A.dtype} cannot be " + "converted to float") + + if self._A.ndim == 3 and self._A.shape[-1] == 1: + # If just one dimension assume scalar and apply colormap + self._A = self._A[:, :, 0] + + if not (self._A.ndim == 2 + or self._A.ndim == 3 and self._A.shape[-1] in [3, 4]): + raise TypeError(f"Invalid shape {self._A.shape} for image data") + + if self._A.ndim == 3: + # If the input data has values outside the valid range (after + # normalisation), we issue a warning and then clip X to the bounds + # - otherwise casting wraps extreme values, hiding outliers and + # making reliable interpretation impossible. + high = 255 if np.issubdtype(self._A.dtype, np.integer) else 1 + if self._A.min() < 0 or high < self._A.max(): + _log.warning( + 'Clipping input data to the valid range for imshow with ' + 'RGB data ([0..1] for floats or [0..255] for integers).' + ) + self._A = np.clip(self._A, 0, high) + # Cast unsupported integer types to uint8 + if self._A.dtype != np.uint8 and np.issubdtype(self._A.dtype, + np.integer): + self._A = self._A.astype(np.uint8) + self._imcache = None self.stale = True @@ -1149,15 +1149,23 @@ def set_data(self, x, y, A): (M, N) `~numpy.ndarray` or masked array of values to be colormapped, or (M, N, 3) RGB array, or (M, N, 4) RGBA array. """ - A = self._normalize_image_array(A) x = np.array(x, np.float32) y = np.array(y, np.float32) - if not (x.ndim == y.ndim == 1 and A.shape[:2] == y.shape + x.shape): + A = cbook.safe_masked_invalid(A, copy=True) + if not (x.ndim == y.ndim == 1 and A.shape[0:2] == y.shape + x.shape): raise TypeError("Axes don't match array shape") + if A.ndim not in [2, 3]: + raise TypeError("Can only plot 2D or 3D data") + if A.ndim == 3 and A.shape[2] not in [1, 3, 4]: + raise TypeError("3D arrays must have three (RGB) " + "or four (RGBA) color components") + if A.ndim == 3 and A.shape[2] == 1: + A = A.squeeze(axis=-1) self._A = A self._Ax = x self._Ay = y self._imcache = None + self.stale = True def set_array(self, *args): @@ -1299,13 +1307,28 @@ def set_data(self, x, y, A): - (M, N, 3): RGB array - (M, N, 4): RGBA array """ - A = self._normalize_image_array(A) - x = np.arange(0., A.shape[1] + 1) if x is None else np.array(x, float).ravel() - y = np.arange(0., A.shape[0] + 1) if y is None else np.array(y, float).ravel() - if A.shape[:2] != (y.size - 1, x.size - 1): + A = cbook.safe_masked_invalid(A, copy=True) + if x is None: + x = np.arange(0, A.shape[1]+1, dtype=np.float64) + else: + x = np.array(x, np.float64).ravel() + if y is None: + y = np.arange(0, A.shape[0]+1, dtype=np.float64) + else: + y = np.array(y, np.float64).ravel() + + if A.shape[:2] != (y.size-1, x.size-1): raise ValueError( "Axes don't match array shape. Got %s, expected %s." % (A.shape[:2], (y.size - 1, x.size - 1))) + if A.ndim not in [2, 3]: + raise ValueError("A must be 2D or 3D") + if A.ndim == 3: + if A.shape[2] == 1: + A = A.squeeze(axis=-1) + elif A.shape[2] not in [3, 4]: + raise ValueError("3D arrays must have RGB or RGBA as last dim") + # For efficient cursor readout, ensure x and y are increasing. if x[-1] < x[0]: x = x[::-1] @@ -1313,6 +1336,7 @@ def set_data(self, x, y, A): if y[-1] < y[0]: y = y[::-1] A = A[::-1] + self._A = A self._Ax = x self._Ay = y From c0fa1d65a54bf65023978b102467181fbf21aecb Mon Sep 17 00:00:00 2001 From: NikosNikolaidis02 Date: Mon, 26 Jun 2023 10:40:45 +0300 Subject: [PATCH 9/9] Resolving conflicts on math_symbol_table.py --- doc/sphinxext/math_symbol_table.py | 56 ++++++++++++++++-------------- 1 file changed, 29 insertions(+), 27 deletions(-) diff --git a/doc/sphinxext/math_symbol_table.py b/doc/sphinxext/math_symbol_table.py index 3dea7ae6e2f4..01fa07990f7b 100644 --- a/doc/sphinxext/math_symbol_table.py +++ b/doc/sphinxext/math_symbol_table.py @@ -2,28 +2,25 @@ from matplotlib import _mathtext, _mathtext_data + symbols = [ ["Lower-case Greek", - r"""\alpha \beta \gamma \chi \delta \epsilon \eta \iota \kappa - \lambda \mu \nu \omega \phi \pi \psi \rho \sigma \tau \theta - \upsilon \xi \zeta \digamma \varepsilon \varkappa \varphi - \varpi \varrho \varsigma \vartheta"""], + (r"\alpha", r"\beta", r"\gamma", r"\chi", r"\delta", r"\epsilon", + r"\eta", r"\iota", r"\kappa", r"\lambda", r"\mu", r"\nu", r"\omega", + r"\phi", r"\pi", r"\psi", r"\rho", r"\sigma", r"\tau", r"\theta", + r"\upsilon", r"\xi", r"\zeta", r"\digamma", r"\varepsilon", r"\varkappa", + r"\varphi", r"\varpi", r"\varrho", r"\varsigma", r"\vartheta")], ["Upper-case Greek", - r"""\Delta \Gamma \Lambda \Omega \Phi \Pi \Psi \Sigma \Theta - \Upsilon \Xi \mho \nabla"""], + (r"\Delta", r"\Gamma", r"\Lambda", r"\Omega", r"\Phi", r"\Pi", r"\Psi", + r"\Sigma", r"\Theta", r"\Upsilon", r"\Xi")], ["Hebrew", - r"""\aleph \beth \daleth \gimel"""], + (r"\aleph", r"\beth", r"\gimel", r"\daleth")], ["Delimiters", - r"""| \{ \lfloor / \Uparrow \llcorner \vert \} \rfloor \backslash - \uparrow \lrcorner \| \langle \lceil [ \Downarrow \ulcorner - \Vert \rangle \rceil ] \downarrow \urcorner"""], + _mathtext.Parser._delims], ["Big symbols", - r"""\bigcap \bigcup \bigodot \bigoplus \bigotimes \biguplus - \bigvee \bigwedge \coprod \oint \prod \sum \int"""], + _mathtext.Parser._overunder_symbols | _mathtext.Parser._dropsub_symbols], ["Standard function names", - r"""\arccos \csc \ker \min \arcsin \deg \lg \Pr \arctan \det \lim - \gcd \ln \sup \cot \hom \log \tan \coth \inf \max \tanh - \sec \arg \dim \liminf \sin \cos \exp \limsup \sinh \cosh"""], + {fr"\{fn}" for fn in _mathtext.Parser._function_names}], ["Binary operation and relation symbols", r"""\ast \pm \slash \cap \star \mp \cup \cdot \uplus \triangleleft \circ \odot \sqcap \triangleright \bullet \ominus @@ -54,7 +51,7 @@ \lneqq \gneqq \ntriangleright \lnsim \gnsim \ntrianglerighteq \coloneq \eqsim \nequiv \napprox \nsupset \doublebarwedge \nVdash \Doteq \nsubset \eqcolon \ne - """], + """.split()], ["Arrow symbols", r"""\leftarrow \longleftarrow \uparrow \Leftarrow \Longleftarrow \Uparrow \rightarrow \longrightarrow \downarrow \Rightarrow @@ -76,8 +73,8 @@ \nrightarrow \nLeftarrow \nRightarrow \nleftrightarrow \nLeftrightarrow \to \Swarrow \Searrow \Nwarrow \Nearrow \leftsquigarrow - """], - ["Miscellaneous symbols", + """.split()], + ["Miscellaneous symbols", r"""\neg \infty \forall \wp \exists \bigstar \angle \partial \nexists \measuredangle \eth \emptyset \sphericalangle \clubsuit \varnothing \complement \diamondsuit \imath \Finv \triangledown @@ -85,13 +82,17 @@ \hslash \vdots \blacksquare \ldots \blacktriangle \ddots \sharp \prime \blacktriangledown \Im \flat \backprime \Re \natural \circledS \P \copyright \ss \circledR \S \yen \AA \checkmark \$ - \iiint \iint \oiiint"""] + \cent \triangle \QED \sinewave \nabla \mho""".split()] ] + def run(state_machine): - def render_symbol(sym): + + def render_symbol(sym, ignore_variant=False): + if ignore_variant and sym != r"\varnothing": + sym = sym.replace(r"\var", "\\") if sym.startswith("\\"): - sym = sym[1:] + sym = sym.lstrip("\\") if sym not in (_mathtext.Parser._overunder_functions | _mathtext.Parser._function_names): sym = chr(_mathtext_data.tex2uni[sym]) @@ -101,7 +102,6 @@ def columns_calculation(list): remainder = max_columns = columns = 10 max_remainder = 0 for columns_number in range(max_columns - 1, 3, -1): - # print(columns_number) remainder = len(list) % columns_number if remainder > max_remainder: columns = columns_number @@ -109,11 +109,14 @@ def columns_calculation(list): return columns lines = [] - # for category, columns, syms in symbols: for category, syms in symbols: - syms = sorted(syms.split()) + syms = sorted(syms, + # Sort by Unicode and place variants immediately + # after standard versions. + key=lambda sym: (render_symbol(sym, ignore_variant=True), + sym.startswith(r"\var")), + reverse=(category == "Hebrew")) # Hebrew is rtl columns = columns_calculation(syms) - # columns = min(columns, len(syms)) lines.append("**%s**" % category) lines.append('') max_width = max(map(len, syms)) * 2 + 16 @@ -157,7 +160,6 @@ def setup(app): for category, columns, syms in symbols: if category == "Standard Function Names": continue - syms = syms.split() for sym in syms: if len(sym) > 1: all_symbols[sym[1:]] = None @@ -167,4 +169,4 @@ def setup(app): print("SYMBOLS NOT IN TABLE:") for sym in _mathtext_data.tex2uni: if sym not in all_symbols: - print(sym) + print(sym) \ No newline at end of file