From df424147820423dc90b0a864db1c8ca1d72d3588 Mon Sep 17 00:00:00 2001 From: Stefan van der Walt Date: Mon, 15 Dec 2014 02:17:22 +0200 Subject: [PATCH 1/5] Improved example notebook generation When examples get converted to notebooks, we use docutils to convert the ReST paragraphs to HTML (markdown). Docutils doesn't understand all of Sphinx's markup, so we have to compromise in certain places. --- doc/ext/plot2rst.py | 54 +++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 50 insertions(+), 4 deletions(-) diff --git a/doc/ext/plot2rst.py b/doc/ext/plot2rst.py index 268ddb63..0b618b3b 100644 --- a/doc/ext/plot2rst.py +++ b/doc/ext/plot2rst.py @@ -66,10 +66,12 @@ Suggested CSS definitions """ import os +import re import shutil import token import tokenize import traceback +import itertools import numpy as np import matplotlib @@ -83,7 +85,7 @@ from skimage.util.dtype import dtype_range from notebook import Notebook from docutils.core import publish_parts - +from sphinx.domains.python import PythonDomain LITERALINCLUDE = """ .. literalinclude:: {src_name} @@ -332,6 +334,8 @@ def write_example(src_name, src_dir, rst_dir, cfg): notebook_path.exists: return + print('plot2rst: %s' % basename) + blocks = split_code_and_text_blocks(example_file) if blocks[0][2].startswith('#!'): blocks.pop(0) # don't add shebang line to rst file. @@ -380,15 +384,57 @@ def write_example(src_name, src_dir, rst_dir, cfg): # Export example to IPython notebook nb = Notebook() - for (cell_type, _, content) in blocks: - content = content.rstrip('\n') + # Add sphinx roles to the examples, otherwise docutils + # cannot compile the ReST for the notebook + sphinx_roles = PythonDomain.roles.keys() + preamble = '\n'.join('.. role:: py:{0}(literal)\n'.format(role) + for role in sphinx_roles) + # Grab all references to inject them in cells where needed + ref_regexp = re.compile('\n(\.\. \[(\d+)\].*(?:\n[ ]{7,8}.*)+)') + math_role_regexp = re.compile(':math:`(.*?)`') + + text = '\n'.join((content for (cell_type, _, content) in blocks + if cell_type != 'code')) + + references = re.findall(ref_regexp, text) + + for (cell_type, _, content) in blocks: if cell_type == 'code': nb.add_cell(content, cell_type='code') else: - content = content.replace('"""', '') + if content.startswith('r'): + content = content.replace('r"""', '') + escaped = False + else: + content = content.replace('"""', '') + escaped = True + + if not escaped: + content = content.replace("\\", "\\\\") + + content = content.replace('.. seealso::', '**See also:**') + content = re.sub(math_role_regexp, r'$\1$', content) + + # Remove math directive when rendering notebooks + # until we implement a smarter way of capturing and replacing + # its content + content = content.replace('.. math::', '') + + if not content.strip(): + continue + + content = (preamble + content).rstrip('\n') content = '\n'.join([line for line in content.split('\n') if not line.startswith('.. image')]) + + # Remove reference links until we can figure out a better way to + # preserve them + for (reference, ref_id) in references: + ref_tag = '[{0}]_'.format(ref_id) + if ref_tag in content: + content = content.replace(ref_tag, ref_tag[:-1]) + html = publish_parts(content, writer_name='html')['html_body'] nb.add_cell(html, cell_type='markdown') From 21d3f151c0531b625f5acce05a85b4da6cb80b13 Mon Sep 17 00:00:00 2001 From: Stefan van der Walt Date: Mon, 15 Dec 2014 02:20:12 +0200 Subject: [PATCH 2/5] Fix warnings generated by gallery examples --- doc/examples/plot_label.py | 3 ++- doc/examples/plot_rag_draw.py | 2 +- doc/examples/plot_regionprops.py | 3 +-- doc/examples/plot_tinting_grayscale_images.py | 10 ++++++---- doc/examples/plot_windowed_histogram.py | 4 +++- 5 files changed, 13 insertions(+), 9 deletions(-) diff --git a/doc/examples/plot_label.py b/doc/examples/plot_label.py index dd3e777d..f80271ce 100644 --- a/doc/examples/plot_label.py +++ b/doc/examples/plot_label.py @@ -19,7 +19,8 @@ import matplotlib.patches as mpatches from skimage import data from skimage.filters import threshold_otsu from skimage.segmentation import clear_border -from skimage.morphology import label, closing, square +from skimage.measure import label +from skimage.morphology import closing, square from skimage.measure import regionprops from skimage.color import label2rgb diff --git a/doc/examples/plot_rag_draw.py b/doc/examples/plot_rag_draw.py index abf2ba08..0c1e1abc 100644 --- a/doc/examples/plot_rag_draw.py +++ b/doc/examples/plot_rag_draw.py @@ -1,5 +1,5 @@ """ -===================================== +====================================== Drawing Region Adjacency Graphs (RAGs) ====================================== diff --git a/doc/examples/plot_regionprops.py b/doc/examples/plot_regionprops.py index 065bae55..c4a8fc29 100644 --- a/doc/examples/plot_regionprops.py +++ b/doc/examples/plot_regionprops.py @@ -11,8 +11,7 @@ import matplotlib.pyplot as plt import numpy as np from skimage.draw import ellipse -from skimage.morphology import label -from skimage.measure import regionprops +from skimage.measure import label, regionprops from skimage.transform import rotate diff --git a/doc/examples/plot_tinting_grayscale_images.py b/doc/examples/plot_tinting_grayscale_images.py index f3ff5466..f4dde6fd 100644 --- a/doc/examples/plot_tinting_grayscale_images.py +++ b/doc/examples/plot_tinting_grayscale_images.py @@ -37,7 +37,7 @@ ax2.imshow(yellow_multiplier * image) In many cases, dealing with RGB values may not be ideal. Because of that, there are many other `color spaces`_ in which you can represent a color image. One -popular color space is called HSV_, which represents hue (~the color), +popular color space is called HSV, which represents hue (~the color), saturation (~colorfulness), and value (~brightness). For example, a color (hue) might be green, but its saturation is how intense that green is---where olive is on the low end and neon on the high end. @@ -46,6 +46,9 @@ In some implementations, the hue in HSV goes from 0 to 360, since hues wrap around in a circle. In scikit-image, however, hues are float values from 0 to 1, so that hue, saturation, and value all share the same scale. +.. _color spaces: + http://en.wikipedia.org/wiki/List_of_color_spaces_and_their_uses + Below, we plot a linear gradient in the hue, with the saturation and value turned all the way up: """ @@ -69,6 +72,8 @@ Notice how the colors at the far left and far right are the same. That reflects the fact that the hues wrap around like the color wheel (see HSV_ for more info). +.. _HSV: http://en.wikipedia.org/wiki/HSL_and_HSV + Now, let's create a little utility function to take an RGB image and: 1. Transform the RGB image to HSV @@ -147,7 +152,4 @@ plt.show() For coloring multiple regions, you may also be interested in `skimage.color.label2rgb `_. -.. _color spaces: - http://en.wikipedia.org/wiki/List_of_color_spaces_and_their_uses -.. _HSV: http://en.wikipedia.org/wiki/HSL_and_HSV """ diff --git a/doc/examples/plot_windowed_histogram.py b/doc/examples/plot_windowed_histogram.py index ebd6ea2f..65e67706 100644 --- a/doc/examples/plot_windowed_histogram.py +++ b/doc/examples/plot_windowed_histogram.py @@ -60,10 +60,12 @@ def windowed_histogram_similarity(image, selem, reference_hist, n_bins): # a measure of distance between histograms X = px_histograms Y = reference_hist + num = (X - Y) ** 2 denom = X + Y + denom[denom == 0] = np.infty frac = num / denom - frac[denom == 0] = 0 + chi_sqr = 0.5 * np.sum(frac, axis=2) # Generate a similarity measure. It needs to be low when distance is high From a38b1c12579214cf77785e9c85f30202b2048c4f Mon Sep 17 00:00:00 2001 From: Stefan van der Walt Date: Mon, 15 Dec 2014 02:20:36 +0200 Subject: [PATCH 3/5] Fix integer division in CLAHE --- skimage/exposure/_adapthist.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/skimage/exposure/_adapthist.py b/skimage/exposure/_adapthist.py index b0c3b952..668d27a6 100644 --- a/skimage/exposure/_adapthist.py +++ b/skimage/exposure/_adapthist.py @@ -136,7 +136,7 @@ def _clahe(image, ntiles_x, ntiles_y, clip_limit, nbins=128): image = pad(image, ((0, h_pad), (0, w_pad)), mode='reflect') h_inner, w_inner = image.shape - bin_size = 1 + NR_OF_GREY / nbins + bin_size = 1 + NR_OF_GREY // nbins lut = np.arange(NR_OF_GREY) lut //= bin_size img_blocks = view_as_blocks(image, (height, width)) From 7f8cd65675180c253bdd8fb2327f3f929de9fb23 Mon Sep 17 00:00:00 2001 From: Stefan van der Walt Date: Mon, 15 Dec 2014 02:21:34 +0200 Subject: [PATCH 4/5] Fix docstring markup errors --- skimage/io/__init__.py | 2 +- skimage/viewer/plugins/base.py | 2 +- skimage/viewer/plugins/color_histogram.py | 18 ++++++++++-------- 3 files changed, 12 insertions(+), 10 deletions(-) diff --git a/skimage/io/__init__.py b/skimage/io/__init__.py index a485250e..d0ec1f43 100644 --- a/skimage/io/__init__.py +++ b/skimage/io/__init__.py @@ -26,7 +26,7 @@ def _format_plugin_info_table(info_table, column_lengths): info_table.insert(0, _separator('=', column_lengths)) info_table.insert(1, ('Plugin', 'Description')) info_table.insert(2, _separator('-', column_lengths)) - info_table.append(_separator('-', column_lengths)) + info_table.append(_separator('=', column_lengths)) def _update_doc(doc): diff --git a/skimage/viewer/plugins/base.py b/skimage/viewer/plugins/base.py index 6b162fd8..def0bfd9 100644 --- a/skimage/viewer/plugins/base.py +++ b/skimage/viewer/plugins/base.py @@ -142,7 +142,7 @@ class Plugin(QtGui.QDialog): plugin += Widget(...) Widgets can adjust required or optional arguments of filter function or - parameters for the plugin. This is specified by the Widget's `ptype'. + parameters for the plugin. This is specified by the Widget's `ptype`. """ if widget.ptype == 'kwarg': name = widget.name.replace(' ', '_') diff --git a/skimage/viewer/plugins/color_histogram.py b/skimage/viewer/plugins/color_histogram.py index 99205c41..52c71786 100644 --- a/skimage/viewer/plugins/color_histogram.py +++ b/skimage/viewer/plugins/color_histogram.py @@ -73,14 +73,16 @@ class ColorHistogram(PlotPlugin): The selected pixels. data : dict The data describing the histogram and the selected region. - Keys: - - 'bins' : array of float, the bin boundaries for both - `a` and `b` channels. - - 'hist' : 2D array of float, the normalized histogram. - - 'edges' : tuple of array of float, the bin edges - along each dimension - - 'extents' : tuple of float, the left and right and - top and bottom of the selected region. + The dictionary contains: + + - 'bins' : array of float + The bin boundaries for both `a` and `b` channels. + - 'hist' : 2D array of float + The normalized histogram. + - 'edges' : tuple of array of float + The bin edges along each dimension + - 'extents' : tuple of float + The left and right and top and bottom of the selected region. """ return (self.mask, self.data) From 655aca6fed065a8cda2a1f9d89fc760228f5e19f Mon Sep 17 00:00:00 2001 From: Stefan van der Walt Date: Mon, 15 Dec 2014 02:22:22 +0200 Subject: [PATCH 5/5] Raise an error that was suppressed to please Travis-CI --- skimage/viewer/utils/core.py | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/skimage/viewer/utils/core.py b/skimage/viewer/utils/core.py index 90521f9c..8aca4e24 100644 --- a/skimage/viewer/utils/core.py +++ b/skimage/viewer/utils/core.py @@ -72,16 +72,13 @@ class RequiredAttr(object): instances = dict() - def __init__(self, msg='Required attribute not set', init_val=None): + def __init__(self, init_val=None): self.instances[self, None] = init_val - self.msg = msg def __get__(self, obj, objtype): value = self.instances[self, obj] if value is None: - # Should raise an error but that causes issues with the buildbot. - warnings.warn(self.msg) - self.__set__(obj, self.init_val) + raise AttributeError('Required attribute not set') return value def __set__(self, obj, value):