Пример #1
0
def _add_single_block(x, y, name, ax):
    """
    Add a single block of two gates.

    Args:
        *x (float)*:
            Layer position.

        *y (float)*:
            Qubit 1 position.

        *name (str)*:
            Gate name.

        *ax (pyplot.Axes)*:
            Axes for the figure.

    Returns (inplace):
        None

    """
    ax.add_patch(
        patches.Rectangle((x, y),
                          0.5,
                          0.5,
                          facecolor='white',
                          edgecolor='black'))
    tp = TextPath((x, y + 0.16), name, size=0.25)
    center = (tp.get_extents().xmax - tp.get_extents().xmin) / 2
    tp = TextPath((x + 0.24 - center, y + 0.16), name, size=0.25)
    ax.add_patch(patches.PathPatch(tp, color="black"))
Пример #2
0
def _add_double_block(x, y, name, ax):
    ax.add_patch(
        patches.Rectangle((x, y),
                          0.5,
                          1.5,
                          facecolor='white',
                          edgecolor='black'))
    tp = TextPath((x, y + 0.66), name, size=0.25)
    center = (tp.get_extents().xmax - tp.get_extents().xmin) / 2
    tp = TextPath((x + 0.24 - center, y + 0.66), name, size=0.25)
    ax.add_patch(patches.PathPatch(tp, color="black"))
Пример #3
0
def text_banner(axes, text, facecolor="red", edgecolor="darkred", linewidth=1,
                alpha=0.3, angleadjust=True, zorder=0):
    """
    Paint text across a hole axes.
    For height > width, angleadjust should be False.
    """

    # draw the text into a patch
    textpath = TextPath((0, 0), text, size=20, transform=axes.transAxes)
    tp_bbox = textpath.get_extents()
    patch = PathPatch(textpath, fc=facecolor, ec=edgecolor, lw=linewidth, alpha=alpha,
                      transform=IdentityTransform(), zorder=11)

    # get angle and scale to transform text to axes coordinates
    ax_bbox = axes.get_window_extent()
    angle = math.atan2(ax_bbox.height, ax_bbox.width) * \
            (ax_bbox.height/ax_bbox.width if angleadjust else 1)
    scale = min(*rotated_scale(tp_bbox.width, tp_bbox.height, angle,
                               ax_bbox.width, ax_bbox.height))*0.95

    # paint the patch into the axes
    offsetbox = AuxTransformBox(Affine2D().rotate(angle).scale(scale))
    offsetbox.add_artist(patch)
    artist = AnnotationBbox(offsetbox, (0.5, 0.5),
                            xycoords='axes fraction',
                            frameon=False)
    artist.set_zorder(zorder)
    axes.add_artist(artist)
Пример #4
0
def make_text_elements(text, x=0.0, y=0.0, width=1.0, height=1.0, color='blue', edgecolor="black",
                       font = FontProperties(family='monospace')):
    tp = TextPath((0.0, 0.0), text, size=1, prop=font)
    bbox = tp.get_extents()
    bwidth = bbox.x1 - bbox.x0
    bheight = bbox.y1 - bbox.y0
    trafo = Affine2D()
    trafo.translate(-bbox.x0, -bbox.y0)
    trafo.scale(1 / bwidth * width, 1 / bheight * height)
    trafo.translate(x,y)
    tp = tp.transformed(trafo)
    return patches.PathPatch(tp, facecolor=color, edgecolor=edgecolor)
Пример #5
0
def drawNT(ax,
           text,
           x=0.0,
           y=0.0,
           width=1.0,
           height=1.0,
           color="#008000",
           edgecolor="None",
           font=FontProperties(family="monospace")):
    tp = TextPath((0.0, 0.0), text, size=1, prop=font)
    bbox = tp.get_extents()
    bwidth = bbox.x1 - bbox.x0
    bheight = bbox.y1 - bbox.y0
    txt = Affine2D()
    txt.translate(-bbox.x0, -bbox.y0)
    txt.scale(1 / bwidth * width, 1 / bheight * height)
    txt.translate(x, y)
    tp = tp.transformed(txt)
    patch = patches.PathPatch(tp, facecolor=color, edgecolor=edgecolor)
    ax.add_patch(patch)
def add_bar_labels(fig, ax, bars, bottom=0):
    transOffset = offset_copy(ax.transData,
                              fig=fig,
                              x=0.,
                              y=-2.,
                              units='points')
    transOffsetUp = offset_copy(ax.transData,
                                fig=fig,
                                x=0.,
                                y=1.,
                                units='points')
    for bar in bars:
        for i, [patch,
                num] in enumerate(zip(bar.patches,
                                      np.arange(len(bar.patches)))):
            if len(bottom) == len(bar): b = bottom[i]
            else: b = bottom
            height = patch.get_height() + b
            xi = patch.get_x() + patch.get_width() / 2.
            va = 'top'
            c = 'w'
            t = TextPath((0, 0),
                         "${xi}$".format(xi=xi),
                         rotation=0,
                         ha='center')
            transform = transOffset
            if patch.get_extents().height <= t.get_extents().height + 5:
                va = 'bottom'
                c = 'k'
                transform = transOffsetUp
            ax.text(xi,
                    height,
                    "${xi}$".format(xi=int(num)),
                    color=c,
                    rotation=0,
                    ha='center',
                    va=va,
                    transform=transform)

    ax.set_xticks([])
Пример #7
0
def add_bar_labels(fig, ax, bars, bottom=0):
    transOffset = offset_copy(ax.transData, fig=fig,
                              x=0., y= -2., units='points')
    transOffsetUp = offset_copy(ax.transData, fig=fig,
                              x=0., y=1., units='points')
    for bar in bars:
        for i, [patch, num] in enumerate(zip(bar.patches, np.arange(len(bar.patches)))):
            if len(bottom) == len(bar): b = bottom[i]
            else: b = bottom
            height = patch.get_height() + b
            xi = patch.get_x() + patch.get_width() / 2.
            va = 'top'
            c = 'w'
            t = TextPath((0, 0), "${xi}$".format(xi=xi), rotation=0, ha='center')
            transform = transOffset
            if patch.get_extents().height <= t.get_extents().height + 5:
                va = 'bottom'
                c = 'k'
                transform = transOffsetUp
            ax.text(xi, height, "${xi}$".format(xi=int(num)), color=c, rotation=0, ha='center', va=va, transform=transform)

    ax.set_xticks([])
Пример #8
0
 def formatDateAxis(self,ax):
     """Formatuje etykiety osi czasu."""
     chartWidth=int(self.fig.get_figwidth()*self.fig.get_dpi()*self.maxSize)        
     t = TextPath((0,0), '9999-99-99', size=7)
     labelWidth = int(t.get_extents().width)    
     num_ticks=chartWidth/labelWidth/2          
     length=len(self.data.date)
     if(length>num_ticks):
         step=length/num_ticks        
     else:
         step=1
     x=range(0,length,step)
     ax.xaxis.set_major_locator(FixedLocator(x))
     ticks=ax.get_xticks()        
     labels=[]        
     for i, label in enumerate(ax.get_xticklabels()):
         label.set_size(7)                       
         index=int(ticks[i])            
         if(index>=len(self.data.date)):
             labels.append('')
         else:
             labels.append(self.data.date[index].strftime("%Y-%m-%d"))            
         label.set_horizontalalignment('center')                                    
     ax.xaxis.set_major_formatter(FixedFormatter(labels))        
Пример #9
0
Файл: kern.py Проект: Dalar/GPy
    def plot_ARD(self, fignum=None, ax=None, title='', legend=False):
        """If an ARD kernel is present, plot a bar representation using matplotlib

        :param fignum: figure number of the plot
        :param ax: matplotlib axis to plot on
        :param title:
            title of the plot,
            pass '' to not print a title
            pass None for a generic title
        """
        if ax is None:
            fig = pb.figure(fignum)
            ax = fig.add_subplot(111)
        else:
            fig = ax.figure
        from GPy.util import Tango
        from matplotlib.textpath import TextPath
        Tango.reset()
        xticklabels = []
        bars = []
        x0 = 0
        for p in self.parts:
            c = Tango.nextMedium()
            if hasattr(p, 'ARD') and p.ARD:
                if title is None:
                    ax.set_title('ARD parameters, %s kernel' % p.name)
                else:
                    ax.set_title(title)
                if p.name == 'linear':
                    ard_params = p.variances
                else:
                    ard_params = 1. / p.lengthscale

                x = np.arange(x0, x0 + len(ard_params))
                bars.append(ax.bar(x, ard_params, align='center', color=c, edgecolor='k', linewidth=1.2, label=p.name))
                xticklabels.extend([r"$\mathrm{{{name}}}\ {x}$".format(name=p.name, x=i) for i in np.arange(len(ard_params))])
                x0 += len(ard_params)
        x = np.arange(x0)
        transOffset = offset_copy(ax.transData, fig=fig,
                                  x=0., y= -2., units='points')
        transOffsetUp = offset_copy(ax.transData, fig=fig,
                                  x=0., y=1., units='points')
        for bar in bars:
            for patch, num in zip(bar.patches, np.arange(len(bar.patches))):
                height = patch.get_height()
                xi = patch.get_x() + patch.get_width() / 2.
                va = 'top'
                c = 'w'
                t = TextPath((0, 0), "${xi}$".format(xi=xi), rotation=0, ha='center')
                transform = transOffset
                if patch.get_extents().height <= t.get_extents().height + 3:
                    va = 'bottom'
                    c = 'k'
                    transform = transOffsetUp
                ax.text(xi, height, "${xi}$".format(xi=int(num)), color=c, rotation=0, ha='center', va=va, transform=transform)
        # for xi, t in zip(x, xticklabels):
        #    ax.text(xi, maxi / 2, t, rotation=90, ha='center', va='center')
        # ax.set_xticklabels(xticklabels, rotation=17)
        ax.set_xticks([])
        ax.set_xlim(-.5, x0 - .5)
        if legend:
            if title is '':
                mode = 'expand'
                if len(bars) > 1:
                    mode = 'expand'
                ax.legend(bbox_to_anchor=(0., 1.02, 1., 1.02), loc=3,
                          ncol=len(bars), mode=mode, borderaxespad=0.)
                fig.tight_layout(rect=(0, 0, 1, .9))
            else:
                ax.legend()
        return ax
Пример #10
0
    def create_picture_from(self, text, format, asbytes=True, context=None):
        """
        Creates a picture from text.

        @param      text        the text
        @param      format      text, json, ...
        @param      context     (str) indication on the content of text (error, ...)
        @param      asbytes     results as bytes or as an image
        @return                 tuple (picture, format) or PIL.Image (if asbytes is False)

        The picture will be bytes, the format png, bmp...
        The size of the picture will depend on the text.
        The longer, the bigger. The method relies on matplotlib
        and then convert the image into a PIL image.

        HTML could be rendered with QWebPage from PyQt (not implemented).
        """
        if not isinstance(text, (str, bytes)):
            text = str(text)
            if "\n" not in text:
                rows = []
                for i in range(0, len(text), 20):
                    end = min(i + 20, len(text))
                    rows.append(text[i:end])
                text = "\n".join(text)
        if len(text) > 200:
            text = text[:200]
        size = len(text) // 10
        figsize = (3 + size, 3 + size)
        lines = text.replace("\t", " ").replace("\r", "").split("\n")

        import matplotlib.pyplot as plt
        from matplotlib.textpath import TextPath
        from matplotlib.font_manager import FontProperties
        fig = plt.figure(figsize=figsize)
        ax = fig.add_subplot(111)
        fp = FontProperties(size=200)

        dx = 0
        dy = 0
        for i, line in enumerate(lines):
            if len(line.strip()) > 0:
                ax.text(0, -dy, line, fontproperties=fp, va='top')
                tp = TextPath((0, -dy), line, prop=fp)
                bb = tp.get_extents()
                dy += bb.height
                dx = max(dx, bb.width)

        ratio = abs(dx) / max(abs(dy), 1)
        ratio = max(min(ratio, 3), 1)
        fig.set_size_inches(int((1 + size) * ratio), 1 + size)
        ax.set_xlim([0, dx])
        ax.set_ylim([-dy, 0])
        ax.set_axis_off()
        sio = BytesIO()
        fig.savefig(sio, format="png")
        plt.close()

        if asbytes:
            b = sio.getvalue(), "png"
            self._check_thumbnail_tuple(b)
            return b
        try:
            from PIL import Image
        except ImportError:  # pragma: no cover
            import Image
        img = Image.open(sio)
        return img
Пример #11
0
    def _make_patch(self):
        """
        Returns an appropriately scaled patch object corresponding to
        the Glyph.
        """

        # Set height
        height = self.ceiling - self.floor

        # If height is zero, set patch to None and return None
        if height == 0.0:
            self.patch = None
            return None

        # Set bounding box for character,
        # leaving requested amount of padding above and below the character
        char_xmin = self.p - self.width / 2.0
        char_ymin = self.floor + self.vpad * height / 2.0
        char_width = self.width
        char_height = height - self.vpad * height
        bbox = Bbox.from_bounds(char_xmin, char_ymin, char_width, char_height)

        # Set font properties of Glyph
        font_properties = FontProperties(family=self.font_name,
                                         weight=self.font_weight)

        # Create a path for Glyph that does not yet have the correct
        # position or scaling
        tmp_path = TextPath((0, 0), self.c, size=1, prop=font_properties)

        # Create create a corresponding path for a glyph representing
        # the max stretched character
        msc_path = TextPath((0, 0),
                            self.dont_stretch_more_than,
                            size=1,
                            prop=font_properties)

        # If need to flip char, do it within tmp_path
        if self.flip:
            transformation = Affine2D().scale(sx=1, sy=-1)
            tmp_path = transformation.transform_path(tmp_path)

        # If need to mirror char, do it within tmp_path
        if self.mirror:
            transformation = Affine2D().scale(sx=-1, sy=1)
            tmp_path = transformation.transform_path(tmp_path)

        # Get bounding box for temporary character and max_stretched_character
        tmp_bbox = tmp_path.get_extents()
        msc_bbox = msc_path.get_extents()

        # Compute horizontal stretch factor needed for tmp_path
        hstretch_tmp = bbox.width / tmp_bbox.width

        # Compute horizontal stretch factor needed for msc_path
        hstretch_msc = bbox.width / msc_bbox.width

        # Choose the MINIMUM of these two horizontal stretch factors.
        # This prevents very narrow characters, such as 'I', from being
        # stretched too much.
        hstretch = min(hstretch_tmp, hstretch_msc)

        # Compute the new character width, accounting for the
        # limit placed on the stretching factor
        char_width = hstretch * tmp_bbox.width

        # Compute how much to horizontally shift the character path
        char_shift = (bbox.width - char_width) / 2.0

        # Compute vertical stetch factor needed for tmp_path
        vstretch = bbox.height / tmp_bbox.height

        # THESE ARE THE ESSENTIAL TRANSFORMATIONS
        # 1. First, translate char path so that lower left corner is at origin
        # 2. Then scale char path to desired width and height
        # 3. Finally, translate char path to desired position
        # char_path is the resulting path used for the Glyph
        transformation = Affine2D() \
            .translate(tx=-tmp_bbox.xmin, ty=-tmp_bbox.ymin) \
            .scale(sx=hstretch, sy=vstretch) \
            .translate(tx=bbox.xmin + char_shift, ty=bbox.ymin)
        char_path = transformation.transform_path(tmp_path)

        # Convert char_path to a patch, which can now be drawn on demand
        self.patch = PathPatch(char_path,
                               facecolor=self.color,
                               zorder=self.zorder,
                               alpha=self.alpha,
                               edgecolor=self.edgecolor,
                               linewidth=self.edgewidth)

        # add patch to axes
        self.ax.add_patch(self.patch)
Пример #12
0
    def plot_ARD(self, fignum=None, ax=None, title='', legend=False):
        """If an ARD kernel is present, plot a bar representation using matplotlib

        :param fignum: figure number of the plot
        :param ax: matplotlib axis to plot on
        :param title:
            title of the plot,
            pass '' to not print a title
            pass None for a generic title
        """
        if ax is None:
            fig = pb.figure(fignum)
            ax = fig.add_subplot(111)
        else:
            fig = ax.figure
        from GPy.util import Tango
        from matplotlib.textpath import TextPath
        Tango.reset()
        xticklabels = []
        bars = []
        x0 = 0
        for p in self.parts:
            c = Tango.nextMedium()
            if hasattr(p, 'ARD') and p.ARD:
                if title is None:
                    ax.set_title('ARD parameters, %s kernel' % p.name)
                else:
                    ax.set_title(title)
                if p.name == 'linear':
                    ard_params = p.variances
                else:
                    ard_params = 1. / p.lengthscale

                x = np.arange(x0, x0 + len(ard_params))
                bars.append(
                    ax.bar(x,
                           ard_params,
                           align='center',
                           color=c,
                           edgecolor='k',
                           linewidth=1.2,
                           label=p.name))
                xticklabels.extend([
                    r"$\mathrm{{{name}}}\ {x}$".format(name=p.name, x=i)
                    for i in np.arange(len(ard_params))
                ])
                x0 += len(ard_params)
        x = np.arange(x0)
        transOffset = offset_copy(ax.transData,
                                  fig=fig,
                                  x=0.,
                                  y=-2.,
                                  units='points')
        transOffsetUp = offset_copy(ax.transData,
                                    fig=fig,
                                    x=0.,
                                    y=1.,
                                    units='points')
        for bar in bars:
            for patch, num in zip(bar.patches, np.arange(len(bar.patches))):
                height = patch.get_height()
                xi = patch.get_x() + patch.get_width() / 2.
                va = 'top'
                c = 'w'
                t = TextPath((0, 0),
                             "${xi}$".format(xi=xi),
                             rotation=0,
                             ha='center')
                transform = transOffset
                if patch.get_extents().height <= t.get_extents().height + 3:
                    va = 'bottom'
                    c = 'k'
                    transform = transOffsetUp
                ax.text(xi,
                        height,
                        "${xi}$".format(xi=int(num)),
                        color=c,
                        rotation=0,
                        ha='center',
                        va=va,
                        transform=transform)
        # for xi, t in zip(x, xticklabels):
        #    ax.text(xi, maxi / 2, t, rotation=90, ha='center', va='center')
        # ax.set_xticklabels(xticklabels, rotation=17)
        ax.set_xticks([])
        ax.set_xlim(-.5, x0 - .5)
        if legend:
            if title is '':
                mode = 'expand'
                if len(bars) > 1:
                    mode = 'expand'
                ax.legend(bbox_to_anchor=(0., 1.02, 1., 1.02),
                          loc=3,
                          ncol=len(bars),
                          mode=mode,
                          borderaxespad=0.)
                fig.tight_layout(rect=(0, 0, 1, .9))
            else:
                ax.legend()
        return ax
Пример #13
0
if __name__ == '__main__':

    import numpy
    from pprint import pprint
    from itertools import islice

    import matplotlib.pyplot as pyplot

    axes = pyplot.gca()

    test_word = "Phillip Seymore Hoffman" # "pearly"

    test_path = TextPath( (0,0), test_word )

    top_box = test_path.get_extents()
    boxes = splitword(top_box, test_path, limit=1)

    # axes.add_patch( PathPatch( test_path, lw=1, facecolor="grey" ) )

    
    for p in cleaned_textpath(test_path):
        axes.add_patch( PathPatch( p, lw=1, facecolor='red', alpha=0.2 ) )

    for box in boxes:
        axes.add_patch( 
                FancyBboxPatch( 
                    (box.xmin, box.ymin), 
                    abs(box.width), abs(box.height),
                    boxstyle="square,pad=0.0",
                    facecolor=(0, 0, 1.0), alpha=0.2 ) )
Пример #14
0
def build_cloud(wordweights, 
        loose=False, seed=None, split_limit=2**-3, pad=1.10, visual_limit=2**-5,
        highest_weight=None ):
    """Convert a list of words and weights into a list of paths and weights.

    You should only use this function if you know what you're doing, or if
    you really don't want to cache the generated paths.  Otherwise just use
    the WordCloud class.

    Args:
        wordweights: An iterator of the form 
                [ (word, weight), (word, weight), ... ]
            such that the weights are in decreasing order.
        loose: If `true', words won't be broken up into rectangles after
            insertion.  This results in a looser cloud, generated faster.
        seed: A random seed to use
        split_limit: When words are approximated by rectangles, the rectangles
            will have dimensions less than split_limit.  Higher values result
            in a tighter cloud, at a cost of more CPU time.  The largest word
            has height 1.0.
        pad: Expand a word's bounding box by a factor of `pad' before
            inserting it.  This can actually result in a tighter cloud if you
            have many small words by leaving space between large words.
        visual_limit: Words with height smaller than visual_limit will be
            discarded.
        highest_weight: Experimental feature.  If you provide an upper bound
            on the weights that will be seen you don't have to provide words
            and weights sorted.  The resulting word cloud will be noticeably
            uglier.

    Generates:
        Tuples of the form (path, weight) such that:
            * No two paths intersect
            * Paths are fairly densely packed around the origin
            * All weights are normalized to fall in the interval [0, 1]
    """
    if seed is not None:
        random.seed(seed)

    font_properties = font_manager.FontProperties(
                family="sans", weight="bold", stretch="condensed")
    xheight = TextPath((0,0), "x", prop=font_properties).get_extents().expanded(pad,pad).height

    # These are magic numbers.  Most wordclouds will not exceed these bounds.
    # If they do, it will have to re-index all of the bounding boxes.
    index_bounds = (-16, -16, 16, 16)
    index = BboxQuadtree(index_bounds)

    if highest_weight is None:
        # Attempt to pull the first word and weight.  If we fail, the wordweights
        # list is empty and we should just quit.
        #
        # All this nonsense is to ensure it accepts an iterator of words
        # correctly.
        iterwords = iter(wordweights)
        try:
            first_word, first_weight = iterwords.next()
            iterwords = chain([(first_word, first_weight)], iterwords)
        except StopIteration:
            return

        # We'll scale all of the weights down by this much.
        weight_scale = 1.0/first_weight
    else:
        weight_scale = 1.0/highest_weight
        iterwords = iter(wordweights)

    bboxes = list()

    bounds = transforms.Bbox(((-0.5, -0.5), (-0.5, -0.5)))
    for tword, tweight in iterwords:
        weight = tweight*weight_scale
        if weight < visual_limit:
            # You're not going to be able to see the word anyway.  Quit
            # rendering words now.
            continue

        word_path = TextPath((0,0), tword, prop=font_properties)
        word_bbox = word_path.get_extents().expanded(pad, pad)
        # word_scale = weight/float(word_bbox.height)
        word_scale = weight/float(xheight)
        
        # When we build a TextPath at (0,0) it doesn't necessarily have
        # its corner at (0,0).  So we have to translate to the origin,
        # scale down, then translate to center it.  Feel free to simplify
        # this if you want.
        word_trans = Affine2D.identity().translate(
                                -word_bbox.xmin,
                                -word_bbox.ymin
                            ).scale(word_scale).translate(
                                -0.5*abs(word_bbox.width)*word_scale,
                                -0.5*abs(word_bbox.height)*word_scale )

        word_path = word_path.transformed(word_trans)

        word_bbox = word_path.get_extents().expanded(pad, pad)

        if weight > split_limit:
            # Big words we place carefully, trying to make the dimensions of
            # the cloud equal and center it around the origin.
            gaps = ( 
                    ("left", bounds.xmin), ("bottom", bounds.ymin), 
                    ("right", bounds.xmax), ("top", bounds.ymax) )
            direction = min(gaps, key=lambda g: abs(g[1]))[0]
        else:
            # Small words we place randomly.
            direction = random.choice( [ "left", "bottom", "right", "top" ] )

        # Randomly place the word along an edge...
        if direction in ( "top", "bottom" ):
            center = random_position(bounds.xmin, bounds.xmax)
        elif direction in ( "right", "left" ):
            center = random_position(bounds.ymin, bounds.ymax)

        # And push it toward an axis.
        if direction == "top":
            bbox = word_bbox.translated( center, index_bounds[3] )
            xpos, ypos = push_bbox_down( bbox, bboxes, index )
        elif direction == "right":
            bbox = word_bbox.translated( index_bounds[2], center )
            xpos, ypos = push_bbox_left( bbox, bboxes, index )
        elif direction == "bottom":
            bbox = word_bbox.translated( center, index_bounds[1] )
            xpos, ypos = push_bbox_up( bbox, bboxes, index )
        elif direction == "left":
            bbox = word_bbox.translated( index_bounds[0], center )
            xpos, ypos = push_bbox_right( bbox, bboxes, index )
    
        # Now alternate pushing the word toward different axes until either
        # it stops movign or we get sick of it.
        max_moves = 2
        moves = 0
        while moves < max_moves and (moves == 0 or prev_xpos != xpos or prev_ypos != ypos):
            moves += 1
            prev_xpos = xpos
            prev_ypos = ypos
            if direction in ["top", "bottom", "vertical"]:
                if xpos > 0:
                    bbox = word_bbox.translated( xpos, ypos )
                    xpos, ypos = push_bbox_left( bbox, bboxes, index )
                elif xpos < 0:
                    bbox = word_bbox.translated( xpos, ypos )
                    xpos, ypos = push_bbox_right( bbox, bboxes, index )
                direction = "horizontal"
            elif direction in ["left", "right", "horizontal"]:
                if ypos > 0:
                    bbox = word_bbox.translated( xpos, ypos )
                    xpos, ypos = push_bbox_down( bbox, bboxes, index )
                elif ypos < 0:
                    bbox = word_bbox.translated( xpos, ypos )
                    xpos, ypos = push_bbox_up( bbox, bboxes, index )
                direction = "vertical"

        wordtrans = Affine2D.identity().translate( xpos, ypos )

        transpath = word_path.transformed(wordtrans)
        bbox = transpath.get_extents()

        # Swallow the new word into the bounding box for the word cloud.
        bounds = matplotlib.transforms.Bbox.union( [ bounds, bbox ] )

        # We need to check if we've expanded past the bounds of our quad tree.
        # If so we'll need to expand the bounds and then re-index.
        new_bounds = index_bounds
        while not BoxifyWord.bbox_covers(
            # FIXME: Why am I not just doing this with a couple of logarithms?
                    matplotlib.transforms.Bbox(((new_bounds[0], new_bounds[1]),
                                                (new_bounds[2], new_bounds[3]))),
                    bounds ):
            new_bounds = tuple( map( lambda x: 2*x, index_bounds ) )

        if new_bounds != index_bounds:
            # We need to re-index.
            index_bounds = new_bounds
            index = BboxQuadtree(index_bounds)
            for i, b in enumerate(bboxes):
                index.add_bbox(i, b)

        # Approximate the new word by rectangles (unless it's too small) and
        # insert them into the index.
        if not loose and max(abs(bbox.width), abs(bbox.height)) > split_limit:
            for littlebox in BoxifyWord.splitword( 
                    bbox, transpath, limit=split_limit ):
                bboxes.append( littlebox )
                index.add_bbox( len(bboxes)-1, littlebox )
        else:
            bboxes.append( bbox )
            index.add_bbox( len(bboxes)-1, bbox )

        yield (transpath, weight)
Пример #15
0
    def create_picture_from(self, text, format, asbytes=True, context=None):
        """
        Creates a picture from text.

        @param      text        the text
        @param      format      text, json, ...
        @param      context     (str) indication on the content of text (error, ...)
        @param      asbytes     results as bytes or as an image
        @return                 tuple (picture, format) or PIL.Image (if asbytes is False)

        The picture will be bytes, the format png, bmp...
        The size of the picture will depend on the text.
        The longer, the bigger. The method relies on matplotlib
        and then convert the image into a PIL image.

        HTML could be rendered with QWebPage from PyQt (not implemented).
        """
        if not isinstance(text, (str, bytes)):
            text = str(text)
            if "\n" not in text:
                rows = []
                for i in range(0, len(text), 20):
                    end = min(i + 20, len(text))
                    rows.append(text[i:end])
                text = "\n".join(text)
        if len(text) > 200:
            text = text[:200]
        size = len(text) // 10
        figsize = (3 + size, 3 + size)
        lines = text.replace("\t", " ").replace("\r", "").split("\n")

        import matplotlib.pyplot as plt
        from matplotlib.textpath import TextPath
        from matplotlib.font_manager import FontProperties
        fig = plt.figure(figsize=figsize)
        ax = fig.add_subplot(111)
        fp = FontProperties(size=200)

        dx = 0
        dy = 0
        for i, line in enumerate(lines):
            if len(line.strip()) > 0:
                ax.text(0, -dy, line, fontproperties=fp, va='top')
                tp = TextPath((0, -dy), line, prop=fp)
                bb = tp.get_extents()
                dy += bb.height
                dx = max(dx, bb.width)

        ratio = abs(dx) / max(abs(dy), 1)
        ratio = max(min(ratio, 3), 1)
        fig.set_size_inches(int((1 + size) * ratio), 1 + size)
        ax.set_xlim([0, dx])
        ax.set_ylim([-dy, 0])
        ax.set_axis_off()
        sio = BytesIO()
        fig.savefig(sio, format="png")
        plt.close()

        if asbytes:
            b = sio.getvalue(), "png"
            self._check_thumbnail_tuple(b)
            return b
        else:
            try:
                from PIL import Image
            except ImportError:
                import Image
            img = Image.open(sio)
            return img