Ejemplo n.º 1
0
    def init_scales(self, layout, x_scale=None, y_scale=None):
        scales = Bunch()

        if x_scale is not None:
            n = layout['SCALE_X'].max()
            scales.x = Scales([x_scale.clone() for i in range(n)])

        if y_scale is not None:
            n = layout['SCALE_Y'].max()
            scales.y = Scales([y_scale.clone() for i in range(n)])

        return scales
Ejemplo n.º 2
0
    def init_scales(self, layout, x_scale=None, y_scale=None):
        scales = Bunch()

        if x_scale is not None:
            n = layout['SCALE_X'].max()
            scales.x = Scales([x_scale.clone() for i in range(n)])

        if y_scale is not None:
            n = layout['SCALE_Y'].max()
            scales.y = Scales([y_scale.clone() for i in range(n)])

        return scales
Ejemplo n.º 3
0
def dual_param(value):
    if is_scalar_or_string(value):
        return Bunch(x=value, y=value)

    with suppress(AttributeError):
        value.x, value.y
        return value

    if len(value) == 2:
        return Bunch(x=value[0], y=value[1])
    else:
        return Bunch(x=value, y=value)
Ejemplo n.º 4
0
 def range(self, panel_params):
     """
     Return the range along the dimensions of the coordinate system
     """
     # Defaults to providing the 2D x-y ranges
     return Bunch(x=panel_params['x_range'],
                  y=panel_params['y_range'])
Ejemplo n.º 5
0
    def _export(self, dir_name, f_base, outline):
        """
        Export figures using the export engine.
        Output: .tex and .pdf (for tikz engine)
        """
        if self.fc_param["engine"] is "Tikz":
            file_tex = os.path.join(dir_name, f_base + ".tex")
            file_pdf = os.path.join(dir_name, f_base + ".pdf")
            tf = TemplateFiller(template="fc_tikz.tex")
            if self.fc_param["annotation.size"] is not None:
                fs = self.fc_param["annotation.size"]
            else:
                fs = 10  # Fallback to default
            figs = []  # List for variables pass to the jinja template
            for item in self.figure_list:
                # TODO: use relative path
                fig = item.subfig
                f_name = item.file_name
                sub_x_ = fig.get_x_fig()
                sub_y_ = fig.get_y_fig()
                sub_w_ = fig.get_w_fig(
                )  # TODO: determine external image size?
                sub_h_ = fig.get_h_fig()
                bc = fig.fig_param["annotation.bc"]
                fc = fig.fig_param["annotation.fc"]
                alpha_ = fig.fig_param["annotation.alpha"]
                text_x_ = fig.get_x_text()
                text_y_ = fig.get_y_text()
                b_ = Bunch(
                    fig_x=fig.x_,
                    fig_y=fig.y_,
                    fig_w=fig.w_,
                    fig_h=fig.h_,
                    sub_x=sub_x_,
                    sub_y=sub_y_,
                    sub_w=sub_w_,
                    sub_h=sub_h_,
                    file_name=f_name,
                    alpha=alpha_,
                    text=fig.anno_text,
                    text_bc=bc,
                    text_fc=fc,
                    text_x=text_x_,
                    text_y=text_y_,
                    outline=outline,
                )
                figs.append(b_)

            tf.render(filename=file_tex,
                      font_size=fs,
                      font_name_main=self.fc_param["annotation.font"],
                      page_width=self.w,
                      page_height=self.h,
                      fig_list=figs)
            # TODO: use tikz engine to generate!
            # Possible to be running the subprocess with different TeX
            # directory. Must define the absolute path!
            subprocess.call(("latexmk", "-xelatex", "-pdf", "-f", "-quiet",
                             "-output-directory=%s" % dir_name, file_tex),
                            stdout=open(os.devnull, "w"))
Ejemplo n.º 6
0
    def get_scales(self, i):
        """
        Return x & y scales for panel i

        Parameters
        ----------
        i : int
          Panel id

        Returns
        -------
        scales : Bunch
          Class attributes *x* for the x scale and *y*
          for the y scale of the panel

        """
        # wrapping with np.asarray prevents an exception
        # on some datasets
        bool_idx = (np.asarray(self.layout['PANEL']) == i)
        xsc = None
        ysc = None

        if self.panel_scales_x:
            idx = self.layout.loc[bool_idx, 'SCALE_X'].values[0]
            xsc = self.panel_scales_x[idx - 1]

        if self.panel_scales_y:
            idx = self.layout.loc[bool_idx, 'SCALE_Y'].values[0]
            ysc = self.panel_scales_y[idx - 1]

        return Bunch(x=xsc, y=ysc)
Ejemplo n.º 7
0
def phasediff(s0, s1, filt, n=1, m=1):
    """
    FUNC: phasediff
    DESCR: Compute the n-m phase difference using the hilbert transform of s0
    and s1 after filtering with filt

    return value is a class with attributes
        s0filt : the filtered s0
        s1filt : the filtered s1
        p0     : the phase of s0
        p1     : the phase of s1
        psi    : the phase difference
        n      : n
        m      : m
    
    """
    s0filt = filt(s0)
    s1filt = filt(s1)

    p0 = hilbert_phaser(s0filt)
    p1 = hilbert_phaser(s1filt)

    return Bunch(
        s0filt=s0filt,
        s1filt=s1filt,
        p0=p0,
        p1=p1,
        psi=m * p0 - n * p1,
        n=n,
        m=m,
    )
Ejemplo n.º 8
0
def parse_options():
    doc = (__doc__ and __doc__.split('\n\n')) or "  "
    op = OptionParser(
        description=doc[0].strip(),
        usage='%prog [options] [--] [backends and switches]',
        #epilog='\n'.join(doc[1:])  # epilog not supported on my python2.4 machine: JDH
    )
    op.disable_interspersed_args()
    op.set_defaults(dirs='pylab,api,units,mplot3d',
                    clean=False,
                    coverage=False,
                    valgrind=False)
    op.add_option('-d',
                  '--dirs',
                  '--directories',
                  type='string',
                  dest='dirs',
                  help=dedent('''
      Run only the tests in these directories; comma-separated list of
      one or more of: pylab (or pylab_examples), api, units, mplot3d'''))
    op.add_option('-b',
                  '--backends',
                  type='string',
                  dest='backends',
                  help=dedent('''
      Run tests only for these backends; comma-separated list of
      one or more of: agg, ps, svg, pdf, template, cairo,
      Default is everything except cairo.'''))
    op.add_option('--clean',
                  action='store_true',
                  dest='clean',
                  help='Remove result directories, run no tests')
    op.add_option('-c',
                  '--coverage',
                  action='store_true',
                  dest='coverage',
                  help='Run in coverage.py')
    op.add_option('-v',
                  '--valgrind',
                  action='store_true',
                  dest='valgrind',
                  help='Run in valgrind')

    options, args = op.parse_args()
    switches = [x for x in args if x.startswith('--')]
    backends = [x.lower() for x in args if not x.startswith('--')]
    if options.backends:
        backends += [be.lower() for be in options.backends.split(',')]

    result = Bunch(dirs=options.dirs.split(','),
                   backends=backends
                   or ['agg', 'ps', 'svg', 'pdf', 'template'],
                   clean=options.clean,
                   coverage=options.coverage,
                   valgrind=options.valgrind,
                   switches=switches)
    if 'pylab_examples' in result.dirs:
        result.dirs[result.dirs.index('pylab_examples')] = 'pylab'
    #print(result)
    return (result)
Ejemplo n.º 9
0
def parse_yahoo_historical(fh, asobject=False, adjusted=True):
    """
    Parse the historical data in file handle fh from yahoo finance and return
    results as a list of

    d, open, close, high, low, volume

    where d is a floating poing representation of date, as returned by date2num

    if adjust=True, use adjusted prices
    """
    results = []

    lines = fh.readlines()

    datefmt = None

    for line in lines[1:]:

        vals = line.split(',')

        if len(vals) != 7: continue
        datestr = vals[0]
        if datefmt is None:
            try:
                datefmt = '%Y-%m-%d'
                dt = datetime.date(*time.strptime(datestr, datefmt)[:3])
            except ValueError:
                datefmt = '%d-%b-%y'  # Old Yahoo--cached file?
        dt = datetime.date(*time.strptime(datestr, datefmt)[:3])
        d = date2num(dt)
        open, high, low, close = [float(val) for val in vals[1:5]]
        volume = int(vals[5])
        if adjusted:
            aclose = float(vals[6])
            m = aclose / close
            open *= m
            high *= m
            low *= m
            close = aclose

        results.append((d, open, close, high, low, volume))
    results.reverse()
    if asobject:
        if len(results) == 0: return None
        else:
            date, open, close, high, low, volume = map(npy.asarray,
                                                       zip(*results))
        return Bunch(date=date,
                     open=open,
                     close=close,
                     high=high,
                     low=low,
                     volume=volume)
    else:

        return results
Ejemplo n.º 10
0
 def set_plot_func(self, plot_func, *args, **argvs):
     """
     Register a plot_func to the fig instance.
     Plot is done only after pagesize is defined
     If tight_layout is used in plot_func,
     figure will give error after using set_size_inches!
     """
     if self.fig_type is "mpl" and self.fig is not None:
         self._plot_func = plot_func
         self._plot_params = Bunch(args=args, argvs=argvs)
Ejemplo n.º 11
0
    def get_metrics(self, font, sym, fontsize, dpi):

        metrics = Bunch(
            advance=0,
            height=0,
            width=0,
            xmin=0,
            xmax=0,
            ymin=0,
            ymax=0,
        )
        return metrics
Ejemplo n.º 12
0
    def create_geoms(self, plot):
        """
        Make information needed to draw a legend for each of the layers.

        For each layer, that information is a dictionary with the geom
        to draw the guide together with the data and the parameters that
        will be used in the call to geom.
        """
        def get_legend_geom(layer):
            if hasattr(layer.geom, 'draw_legend'):
                geom = layer.geom.__class__
            else:
                name = 'geom_{}'.format(layer.geom.legend_geom)
                geom = Registry[name]
            return geom

        # A layer either contributes to the guide, or it does not. The
        # guide entries may be ploted in the layers
        self.glayers = []
        for l in plot.layers:
            exclude = set()
            if isinstance(l.show_legend, dict):
                l.show_legend = rename_aesthetics(l.show_legend)
                exclude = {ae for ae, val in l.show_legend.items() if not val}
            elif l.show_legend not in (None, True):
                continue

            matched = self.legend_aesthetics(l, plot)

            # This layer does not contribute to the legend
            if not set(matched) - exclude:
                continue

            data = self.key[matched].copy()
            data = l.use_defaults(data)

            # override.aes in guide_legend manually changes the geom
            for ae in set(self.override_aes) & set(data.columns):
                data[ae] = self.override_aes[ae]

            geom = get_legend_geom(l)
            data = remove_missing(
                data, l.geom.params['na_rm'],
                list(l.geom.REQUIRED_AES | l.geom.NON_MISSING_AES),
                '{} legend'.format(l.geom.__class__.__name__))
            self.glayers.append(Bunch(geom=geom, data=data, layer=l))

        if not self.glayers:
            return None
        return self
Ejemplo n.º 13
0
    def _get_info(self, font, sym, fontsize, dpi):
        'load the cmfont, metrics and glyph with caching'
        key = font, sym, fontsize, dpi
        tup = self.glyphd.get(key)

        if tup is not None:
            return tup

        if sym in "0123456789()" and font == 'it':
            font = 'rm'
        basename = self.fontmap[font]

        if latex_to_standard.has_key(sym):
            basename, num = latex_to_standard[sym]
            char = chr(num)
        elif len(sym) == 1:
            char = sym
        else:
            raise ValueError('unrecognized symbol "%s"' % (sym))

        try:
            sym = self.fonts[basename].get_name_char(char)
        except KeyError:
            raise ValueError('unrecognized symbol "%s"' % (sym))

        offset = 0
        cmfont = self.fonts[basename]
        fontname = cmfont.get_fontname()

        scale = 0.001 * fontsize

        xmin, ymin, xmax, ymax = [
            val * scale for val in cmfont.get_bbox_char(char)
        ]
        metrics = Bunch(advance=(xmax - xmin),
                        width=cmfont.get_width_char(char) * scale,
                        height=cmfont.get_width_char(char) * scale,
                        xmin=xmin,
                        xmax=xmax,
                        ymin=ymin + offset,
                        ymax=ymax + offset)

        self.glyphd[key] = fontname, basename, metrics, sym, offset, char
        return fontname, basename, metrics, '/' + sym, offset, char
Ejemplo n.º 14
0
    def _get_info(self, font, sym, fontsize, dpi):
        'load the cmfont, metrics and glyph with caching'
        key = font, sym, fontsize, dpi
        tup = self.glyphd.get(key)

        if tup is not None:
            return tup

        basename = self.fontmap[font]

        if latex_to_bakoma.has_key(sym):
            basename, num = latex_to_bakoma[sym]
            sym = self.fonts[basename].get_glyph_name(num)
            num = self.charmaps[basename][num]
        elif len(sym) == 1:
            num = ord(sym)
        else:
            num = 0
            sym = '.notdef'
            raise ValueError('unrecognized symbol "%s, %d"' % (sym, num))

        if basename not in bakoma_fonts:
            bakoma_fonts.append(basename)
        cmfont = self.fonts[basename]
        cmfont.set_size(fontsize, dpi)
        head = cmfont.get_sfnt_table('head')
        glyph = cmfont.load_char(num)

        xmin, ymin, xmax, ymax = [val / 64.0 for val in glyph.bbox]
        if basename == 'cmex10':
            offset = -(head['yMin'] + 512) / head['unitsPerEm'] * 10.
        else:
            offset = 0.
        metrics = Bunch(advance=glyph.linearHoriAdvance / 65536.0,
                        height=glyph.height / 64.0,
                        width=glyph.width / 64.0,
                        xmin=xmin,
                        xmax=xmax,
                        ymin=ymin + offset,
                        ymax=ymax + offset)

        self.glyphd[key] = basename, metrics, sym, offset
        return basename, metrics, '/' + sym, offset
Ejemplo n.º 15
0
    def _get_info(self, font, sym, fontsize, dpi):
        'load the cmfont, metrics and glyph with caching'
        key = font, sym, fontsize, dpi
        tup = self.glyphd.get(key)

        if tup is not None: return tup

        basename = self.fontmap[font]

        if latex_to_bakoma.has_key(sym):
            basename, num = latex_to_bakoma[sym]
            num = self.charmaps[basename][num]
        elif len(sym) == 1:
            num = ord(sym)
        else:
            num = 0
            verbose.report_error('unrecognized symbol "%s"' % sym)

        #print sym, basename, num
        cmfont = self.fonts[basename]
        cmfont.set_size(fontsize, dpi)
        head = cmfont.get_sfnt_table('head')
        glyph = cmfont.load_char(num)

        xmin, ymin, xmax, ymax = [val / 64.0 for val in glyph.bbox]
        if basename == 'cmex10':
            offset = glyph.height / 64.0 / 2 + 256.0 / 64.0 * dpi / 72.0
            #offset = -(head['yMin']+512)/head['unitsPerEm']*10.
        else:
            offset = 0.
        metrics = Bunch(
            advance=glyph.horiAdvance / 64.0,
            height=glyph.height / 64.0,
            width=glyph.width / 64.0,
            xmin=xmin,
            xmax=xmax,
            ymin=ymin + offset,
            ymax=ymax + offset,
        )

        self.glyphd[key] = cmfont, metrics, glyph, offset
        return self.glyphd[key]
Ejemplo n.º 16
0
 def add_figure(self, loc=None, label=True, fig_file=None, **argv):
     # TODO add grid support
     """
     `label` determines whether to add the annotation label or not.
     `**argv` the user-defined fig_param
     User can also pass the `fig` instance to the subfigure
     """
     if self.use_grid is False:
         if loc is None:
             raise ValueError("Must define grids first!")
         if (type(loc) is not tuple) and (type(loc) is not list):
             raise TypeError("The absolute loc must be iterable!")
         if False in [0.0 <= i <= 1.0 for i in loc
                      ]:  # The values of loc should be within 1 and 0!!
             raise ValueError(
                 "The absolute loc value should be within 0 and 1!")
         loc_ = loc  # If grid is not used, the user must give a absolute position
     else:
         if loc is None:
             loc = self.cnt  # assume that the grids are added sequentially
         loc_ = self._treat_grid(loc)
     subfig_ = SubFigure(loc_,
                         fig_file=fig_file,
                         parent_param=self.fc_param,
                         **argv)
     if label is True:
         if self.generator is not None:
             s = next(self.generator)
             subfig_.set_annotation_text(s)
         else:
             s = None
     else:
         s = None
     b_ = Bunch(subfig=subfig_,
                cnt=self.cnt,
                label=label,
                text=s,
                file_name=None)
     self.figure_list.append(b_)
     self.cnt += 1  # In case the adding for figure failed, esp. in commandline mode
     return subfig_, b_.cnt  # User can use the returned instance to call the plot function
Ejemplo n.º 17
0
    def create_geoms(self, plot):
        """
        Make information needed to draw a legend for each of the layers.

        For each layer, that information is a dictionary with the geom
        to draw the guide together with the data and the parameters that
        will be used in the call to geom.
        """
        def get_legend_geom(layer):
            if hasattr(layer.geom, 'draw_legend'):
                geom = layer.geom.__class__
            else:
                name = 'geom_{}'.format(layer.geom.legend_geom)
                geom = Registry[name]
            return geom

        # A layer either contributes to the guide, or it does not. The
        # guide entries may be ploted in the layers
        self.glayers = []
        for l in plot.layers:
            if l.show_legend not in (None, True):
                continue

            matched = self.legend_aesthetics(l, plot)
            # This layer does not contribute to the legend
            if not matched:
                continue

            data = self.key[matched].copy()
            data = l.use_defaults(data)

            # override.aes in guide_legend manually changes the geom
            for ae in set(self.override_aes) & set(data.columns):
                data[ae] = self.override_aes[ae]

            geom = get_legend_geom(l)
            self.glayers.append(Bunch(geom=geom, data=data, layer=l))

        if not self.glayers:
            return None
        return self
Ejemplo n.º 18
0
    def strip_dimensions(self, text_lines, location, pid):
        """
        Calculate the dimension

        Returns
        -------
        out : Bunch
            A structure with all the coordinates required
            to draw the strip text and the background box.
        """
        dpi = 72
        num_lines = len(text_lines)
        get_property = self.theme.themeables.property
        ax = self.axs[pid]
        bbox = ax.get_window_extent().transformed(
            self.figure.dpi_scale_trans.inverted())
        ax_width, ax_height = bbox.width, bbox.height  # in inches
        strip_size = self.strip_size(location, num_lines)
        m1, m2 = self.inner_strip_margins(location)
        m1, m2 = m1 / dpi, m2 / dpi
        margin = 0  # default

        if location == 'right':
            box_x = 1
            box_y = 0
            box_width = strip_size / ax_width
            box_height = 1
            # y & height properties of the background slide and
            # shrink the strip vertically. The y margin slides
            # it horizontally.
            with suppress(KeyError):
                box_y = get_property('strip_background_y', 'y')
            with suppress(KeyError):
                box_height = get_property('strip_background_y', 'height')
            with suppress(KeyError):
                margin = get_property('strip_margin_y')
            x = 1 + (strip_size - m2 + m1) / (2 * ax_width)
            y = (2 * box_y + box_height) / 2
            # margin adjustment
            hslide = 1 + margin * strip_size / ax_width
            x *= hslide
            box_x *= hslide
        else:
            box_x = 0
            box_y = 1
            box_width = 1
            box_height = strip_size / ax_height
            # x & width properties of the background slide and
            # shrink the strip horizontally. The y margin slides
            # it vertically.
            with suppress(KeyError):
                box_x = get_property('strip_background_x', 'x')
            with suppress(KeyError):
                box_width = get_property('strip_background_x', 'width')
            with suppress(KeyError):
                margin = get_property('strip_margin_x')
            x = (2 * box_x + box_width) / 2
            y = 1 + (strip_size - m1 + m2) / (2 * ax_height)
            # margin adjustment
            vslide = 1 + margin * strip_size / ax_height
            y *= vslide
            box_y *= vslide

        dimensions = Bunch(x=x,
                           y=y,
                           box_x=box_x,
                           box_y=box_y,
                           box_width=box_width,
                           box_height=box_height)
        return dimensions
Ejemplo n.º 19
0
    def add(self,
            patchlabel='',
            flows=None,
            orientations=None,
            labels='',
            trunklength=1.0,
            pathlengths=0.25,
            prior=None,
            connect=(0, 0),
            rotation=0,
            **kwargs):
        """
        Add a simple Sankey diagram with flows at the same hierarchical level.

        Return value is the instance of :class:`Sankey`.

        Optional keyword arguments:

          ===============   ===================================================
          Keyword           Description
          ===============   ===================================================
          *patchlabel*      label to be placed at the center of the diagram
                            Note: *label* (not *patchlabel*) will be passed to
                            the patch through ``**kwargs`` and can be used to
                            create an entry in the legend.
          *flows*           array of flow values
                            By convention, inputs are positive and outputs are
                            negative.
          *orientations*    list of orientations of the paths
                            Valid values are 1 (from/to the top), 0 (from/to
                            the left or right), or -1 (from/to the bottom).  If
                            *orientations* == 0, inputs will break in from the
                            left and outputs will break away to the right.
          *labels*          list of specifications of the labels for the flows
                            Each value may be *None* (no labels), '' (just
                            label the quantities), or a labeling string.  If a
                            single value is provided, it will be applied to all
                            flows.  If an entry is a non-empty string, then the
                            quantity for the corresponding flow will be shown
                            below the string.  However, if the *unit* of the
                            main diagram is None, then quantities are never
                            shown, regardless of the value of this argument.
          *trunklength*     length between the bases of the input and output
                            groups
          *pathlengths*     list of lengths of the arrows before break-in or
                            after break-away
                            If a single value is given, then it will be applied
                            to the first (inside) paths on the top and bottom,
                            and the length of all other arrows will be
                            justified accordingly.  The *pathlengths* are not
                            applied to the horizontal inputs and outputs.
          *prior*           index of the prior diagram to which this diagram
                            should be connected
          *connect*         a (prior, this) tuple indexing the flow of the
                            prior diagram and the flow of this diagram which
                            should be connected
                            If this is the first diagram or *prior* is *None*,
                            *connect* will be ignored.
          *rotation*        angle of rotation of the diagram [deg]
                            *rotation* is ignored if this diagram is connected
                            to an existing one (using *prior* and *connect*).
                            The interpretation of the *orientations* argument
                            will be rotated accordingly (e.g., if *rotation*
                            == 90, an *orientations* entry of 1 means to/from
                            the left).
          ===============   ===================================================

        Valid kwargs are :meth:`matplotlib.patches.PathPatch` arguments:

        %(Patch)s

        As examples, ``fill=False`` and ``label='A legend entry'``.
        By default, ``facecolor='#bfd1d4'`` (light blue) and
        ``linewidth=0.5``.

        The indexing parameters (*prior* and *connect*) are zero-based.

        The flows are placed along the top of the diagram from the inside out
        in order of their index within the *flows* list or array.  They are
        placed along the sides of the diagram from the top down and along the
        bottom from the outside in.

        If the the sum of the inputs and outputs is nonzero, the discrepancy
        will appear as a cubic Bezier curve along the top and bottom edges of
        the trunk.

        .. seealso::

            :meth:`finish`
        """
        # Check and preprocess the arguments.
        if flows is None:
            flows = np.array([1.0, -1.0])
        else:
            flows = np.array(flows)
        n = flows.shape[0]  # Number of flows
        if rotation is None:
            rotation = 0
        else:
            # In the code below, angles are expressed in deg/90.
            rotation /= 90.0
        if orientations is None:
            orientations = [0, 0]
        assert len(orientations) == n, (
            "orientations and flows must have the same length.\n"
            "orientations has length %d, but flows has length %d." %
            (len(orientations), n))
        if labels != '' and getattr(labels, '__iter__', False):
            # iterable() isn't used because it would give True if labels is a
            # string
            assert len(labels) == n, (
                "If labels is a list, then labels and flows must have the "
                "same length.\nlabels has length %d, but flows has length %d."
                % (len(labels), n))
        else:
            labels = [labels] * n
        assert trunklength >= 0, (
            "trunklength is negative.\nThis isn't allowed, because it would "
            "cause poor layout.")
        if np.absolute(np.sum(flows)) > self.tolerance:
            verbose.report(
                "The sum of the flows is nonzero (%f).\nIs the "
                "system not at steady state?" % np.sum(flows), 'helpful')
        scaled_flows = self.scale * flows
        gain = sum(max(flow, 0) for flow in scaled_flows)
        loss = sum(min(flow, 0) for flow in scaled_flows)
        if not (0.5 <= gain <= 2.0):
            verbose.report(
                "The scaled sum of the inputs is %f.\nThis may "
                "cause poor layout.\nConsider changing the scale so"
                " that the scaled sum is approximately 1.0." % gain, 'helpful')
        if not (-2.0 <= loss <= -0.5):
            verbose.report(
                "The scaled sum of the outputs is %f.\nThis may "
                "cause poor layout.\nConsider changing the scale so"
                " that the scaled sum is approximately 1.0." % gain, 'helpful')
        if prior is not None:
            assert prior >= 0, "The index of the prior diagram is negative."
            assert min(connect) >= 0, (
                "At least one of the connection indices is negative.")
            assert prior < len(self.diagrams), (
                "The index of the prior diagram is %d, but there are "
                "only %d other diagrams.\nThe index is zero-based." %
                (prior, len(self.diagrams)))
            assert connect[0] < len(self.diagrams[prior].flows), (
                "The connection index to the source diagram is %d, but "
                "that diagram has only %d flows.\nThe index is zero-based." %
                (connect[0], len(self.diagrams[prior].flows)))
            assert connect[1] < n, (
                "The connection index to this diagram is %d, but this diagram"
                "has only %d flows.\n The index is zero-based." %
                (connect[1], n))
            assert self.diagrams[prior].angles[connect[0]] is not None, (
                "The connection cannot be made.  Check that the magnitude "
                "of flow %d of diagram %d is greater than or equal to the "
                "specified tolerance." % (connect[0], prior))
            flow_error = (self.diagrams[prior].flows[connect[0]] +
                          flows[connect[1]])
            assert abs(flow_error) < self.tolerance, (
                "The scaled sum of the connected flows is %f, which is not "
                "within the tolerance (%f)." % (flow_error, self.tolerance))

        # Determine if the flows are inputs.
        are_inputs = [None] * n
        for i, flow in enumerate(flows):
            if flow >= self.tolerance:
                are_inputs[i] = True
            elif flow <= -self.tolerance:
                are_inputs[i] = False
            else:
                verbose.report(
                    "The magnitude of flow %d (%f) is below the "
                    "tolerance (%f).\nIt will not be shown, and it "
                    "cannot be used in a connection." %
                    (i, flow, self.tolerance), 'helpful')

        # Determine the angles of the arrows (before rotation).
        angles = [None] * n
        for i, (orient, is_input) in enumerate(zip(orientations, are_inputs)):
            if orient == 1:
                if is_input:
                    angles[i] = DOWN
                elif not is_input:
                    # Be specific since is_input can be None.
                    angles[i] = UP
            elif orient == 0:
                if is_input is not None:
                    angles[i] = RIGHT
            else:
                assert orient == -1, ("The value of orientations[%d] is %d, "
                                      "but it must be -1, 0, or 1." %
                                      (i, orient))
                if is_input:
                    angles[i] = UP
                elif not is_input:
                    angles[i] = DOWN

        # Justify the lengths of the paths.
        if iterable(pathlengths):
            assert len(pathlengths) == n, (
                "If pathlengths is a list, then pathlengths and flows must "
                "have the same length.\npathlengths has length %d, but flows "
                "has length %d." % (len(pathlengths), n))
        else:  # Make pathlengths into a list.
            urlength = pathlengths
            ullength = pathlengths
            lrlength = pathlengths
            lllength = pathlengths
            d = dict(RIGHT=pathlengths)
            pathlengths = [d.get(angle, 0) for angle in angles]
            # Determine the lengths of the top-side arrows
            # from the middle outwards.
            for i, (angle, is_input,
                    flow) in enumerate(zip(angles, are_inputs, scaled_flows)):
                if angle == DOWN and is_input:
                    pathlengths[i] = ullength
                    ullength += flow
                elif angle == UP and not is_input:
                    pathlengths[i] = urlength
                    urlength -= flow  # Flow is negative for outputs.
            # Determine the lengths of the bottom-side arrows
            # from the middle outwards.
            for i, (angle, is_input, flow) in enumerate(
                    reversed(list(zip(angles, are_inputs, scaled_flows)))):
                if angle == UP and is_input:
                    pathlengths[n - i - 1] = lllength
                    lllength += flow
                elif angle == DOWN and not is_input:
                    pathlengths[n - i - 1] = lrlength
                    lrlength -= flow
            # Determine the lengths of the left-side arrows
            # from the bottom upwards.
            has_left_input = False
            for i, (angle, is_input, spec) in enumerate(
                    reversed(
                        list(
                            zip(angles, are_inputs,
                                zip(scaled_flows, pathlengths))))):
                if angle == RIGHT:
                    if is_input:
                        if has_left_input:
                            pathlengths[n - i - 1] = 0
                        else:
                            has_left_input = True
            # Determine the lengths of the right-side arrows
            # from the top downwards.
            has_right_output = False
            for i, (angle, is_input, spec) in enumerate(
                    zip(angles, are_inputs, list(zip(scaled_flows,
                                                     pathlengths)))):
                if angle == RIGHT:
                    if not is_input:
                        if has_right_output:
                            pathlengths[i] = 0
                        else:
                            has_right_output = True

        # Begin the subpaths, and smooth the transition if the sum of the flows
        # is nonzero.
        urpath = [
            (
                Path.MOVETO,
                [
                    (self.gap - trunklength / 2.0),  # Upper right
                    gain / 2.0
                ]),
            (Path.LINETO, [(self.gap - trunklength / 2.0) / 2.0, gain / 2.0]),
            (Path.CURVE4, [(self.gap - trunklength / 2.0) / 8.0, gain / 2.0]),
            (Path.CURVE4, [(trunklength / 2.0 - self.gap) / 8.0, -loss / 2.0]),
            (Path.LINETO, [(trunklength / 2.0 - self.gap) / 2.0, -loss / 2.0]),
            (Path.LINETO, [(trunklength / 2.0 - self.gap), -loss / 2.0])
        ]
        llpath = [
            (
                Path.LINETO,
                [
                    (trunklength / 2.0 - self.gap),  # Lower left
                    loss / 2.0
                ]),
            (Path.LINETO, [(trunklength / 2.0 - self.gap) / 2.0, loss / 2.0]),
            (Path.CURVE4, [(trunklength / 2.0 - self.gap) / 8.0, loss / 2.0]),
            (Path.CURVE4, [(self.gap - trunklength / 2.0) / 8.0, -gain / 2.0]),
            (Path.LINETO, [(self.gap - trunklength / 2.0) / 2.0, -gain / 2.0]),
            (Path.LINETO, [(self.gap - trunklength / 2.0), -gain / 2.0])
        ]
        lrpath = [(
            Path.LINETO,
            [
                (trunklength / 2.0 - self.gap),  # Lower right
                loss / 2.0
            ])]
        ulpath = [(
            Path.LINETO,
            [
                self.gap - trunklength / 2.0,  # Upper left
                gain / 2.0
            ])]

        # Add the subpaths and assign the locations of the tips and labels.
        tips = np.zeros((n, 2))
        label_locations = np.zeros((n, 2))
        # Add the top-side inputs and outputs from the middle outwards.
        for i, (angle, is_input, spec) in enumerate(
                zip(angles, are_inputs, list(zip(scaled_flows, pathlengths)))):
            if angle == DOWN and is_input:
                tips[i, :], label_locations[i, :] = self._add_input(
                    ulpath, angle, *spec)
            elif angle == UP and not is_input:
                tips[i, :], label_locations[i, :] = self._add_output(
                    urpath, angle, *spec)
        # Add the bottom-side inputs and outputs from the middle outwards.
        for i, (angle, is_input, spec) in enumerate(
                reversed(
                    list(
                        zip(angles, are_inputs,
                            list(zip(scaled_flows, pathlengths)))))):
            if angle == UP and is_input:
                tip, label_location = self._add_input(llpath, angle, *spec)
                tips[n - i - 1, :] = tip
                label_locations[n - i - 1, :] = label_location
            elif angle == DOWN and not is_input:
                tip, label_location = self._add_output(lrpath, angle, *spec)
                tips[n - i - 1, :] = tip
                label_locations[n - i - 1, :] = label_location
        # Add the left-side inputs from the bottom upwards.
        has_left_input = False
        for i, (angle, is_input, spec) in enumerate(
                reversed(
                    list(
                        zip(angles, are_inputs,
                            list(zip(scaled_flows, pathlengths)))))):
            if angle == RIGHT and is_input:
                if not has_left_input:
                    # Make sure the lower path extends
                    # at least as far as the upper one.
                    if llpath[-1][1][0] > ulpath[-1][1][0]:
                        llpath.append(
                            (Path.LINETO, [ulpath[-1][1][0],
                                           llpath[-1][1][1]]))
                    has_left_input = True
                tip, label_location = self._add_input(llpath, angle, *spec)
                tips[n - i - 1, :] = tip
                label_locations[n - i - 1, :] = label_location
        # Add the right-side outputs from the top downwards.
        has_right_output = False
        for i, (angle, is_input, spec) in enumerate(
                zip(angles, are_inputs, list(zip(scaled_flows, pathlengths)))):
            if angle == RIGHT and not is_input:
                if not has_right_output:
                    # Make sure the upper path extends
                    # at least as far as the lower one.
                    if urpath[-1][1][0] < lrpath[-1][1][0]:
                        urpath.append(
                            (Path.LINETO, [lrpath[-1][1][0],
                                           urpath[-1][1][1]]))
                    has_right_output = True
                tips[i, :], label_locations[i, :] = self._add_output(
                    urpath, angle, *spec)
        # Trim any hanging vertices.
        if not has_left_input:
            ulpath.pop()
            llpath.pop()
        if not has_right_output:
            lrpath.pop()
            urpath.pop()

        # Concatenate the subpaths in the correct order (clockwise from top).
        path = (urpath + self._revert(lrpath) + llpath + self._revert(ulpath) +
                [(Path.CLOSEPOLY, urpath[0][1])])

        # Create a patch with the Sankey outline.
        codes, vertices = list(zip(*path))
        vertices = np.array(vertices)

        def _get_angle(a, r):
            if a is None:
                return None
            else:
                return a + r

        if prior is None:
            if rotation != 0:  # By default, none of this is needed.
                angles = [_get_angle(angle, rotation) for angle in angles]
                rotate = Affine2D().rotate_deg(rotation * 90).transform_affine
                tips = rotate(tips)
                label_locations = rotate(label_locations)
                vertices = rotate(vertices)
            text = self.ax.text(0, 0, s=patchlabel, ha='center', va='center')
        else:
            rotation = (self.diagrams[prior].angles[connect[0]] -
                        angles[connect[1]])
            angles = [_get_angle(angle, rotation) for angle in angles]
            rotate = Affine2D().rotate_deg(rotation * 90).transform_affine
            tips = rotate(tips)
            offset = self.diagrams[prior].tips[connect[0]] - tips[connect[1]]
            translate = Affine2D().translate(*offset).transform_affine
            tips = translate(tips)
            label_locations = translate(rotate(label_locations))
            vertices = translate(rotate(vertices))
            kwds = dict(s=patchlabel, ha='center', va='center')
            text = self.ax.text(*offset, **kwds)
        if False:  # Debug
            print("llpath\n", llpath)
            print("ulpath\n", self._revert(ulpath))
            print("urpath\n", urpath)
            print("lrpath\n", self._revert(lrpath))
            xs, ys = list(zip(*vertices))
            self.ax.plot(xs, ys, 'go-')
        patch = PathPatch(
            Path(vertices, codes),
            fc=kwargs.pop('fc', kwargs.pop('facecolor',
                                           '#bfd1d4')),  # Custom defaults
            lw=kwargs.pop('lw', kwargs.pop('linewidth', 0.5)),
            **kwargs)
        self.ax.add_patch(patch)

        # Add the path labels.
        texts = []
        for number, angle, label, location in zip(flows, angles, labels,
                                                  label_locations):
            if label is None or angle is None:
                label = ''
            elif self.unit is not None:
                quantity = self.format % abs(number) + self.unit
                if label != '':
                    label += "\n"
                label += quantity
            texts.append(
                self.ax.text(x=location[0],
                             y=location[1],
                             s=label,
                             ha='center',
                             va='center'))
        # Text objects are placed even they are empty (as long as the magnitude
        # of the corresponding flow is larger than the tolerance) in case the
        # user wants to provide labels later.

        # Expand the size of the diagram if necessary.
        self.extent = (min(np.min(vertices[:, 0]),
                           np.min(label_locations[:, 0]), self.extent[0]),
                       max(np.max(vertices[:, 0]),
                           np.max(label_locations[:, 0]), self.extent[1]),
                       min(np.min(vertices[:, 1]),
                           np.min(label_locations[:, 1]), self.extent[2]),
                       max(np.max(vertices[:, 1]),
                           np.max(label_locations[:, 1]), self.extent[3]))
        # Include both vertices _and_ label locations in the extents; there are
        # where either could determine the margins (e.g., arrow shoulders).

        # Add this diagram as a subdiagram.
        self.diagrams.append(
            Bunch(patch=patch,
                  flows=flows,
                  angles=angles,
                  tips=tips,
                  text=text,
                  texts=texts))

        # Allow a daisy-chained call structure (see docstring for the class).
        return self
Ejemplo n.º 20
0
 def __init__(self, x='identity', y='identity', xlim=None, ylim=None):
     self.trans = Bunch(x=gettrans(x), y=gettrans(y))
     self.limits = Bunch(xlim=xlim, ylim=ylim)
Ejemplo n.º 21
0
 def __init__(self, xlim=None, ylim=None, expand=True):
     self.limits = Bunch(xlim=xlim, ylim=ylim)
     self.expand = expand
Ejemplo n.º 22
0
    base, ext = os.path.splitext(barefname)
    if not ext:
        ext = '.ttf'
        barefname = base + ext
    # First, we search for the font in the system font dir
    for fname in findSystemFonts(fontext=ext[1:]):
        if fname.endswith(barefname):
            filenamesd[face] = fname
            break
    # We check if the for loop above had success. If it failed, we try to
    # find the font in the mpl-data dir
    if not face in filenamesd:
        filenamesd[face] = os.path.join(_path, barefname)
    fonts[face] = FT2Font(filenamesd[face])

svg_elements = Bunch(svg_glyphs=[], svg_lines=[])

esc_char = '\\'
# Grouping delimiters
begin_group_char = '{'
end_group_char = '}'
dec_delim = '.'
word_delim = ' '
mathstyles = ["display", "text", "script", "scriptscript"]
modes = ["mathmode", "displaymathmode"]

# Commands
scripts = ("_", "^")
functions = ("sin", "tan", "cos", "exp", "arctan", "arccos", "arcsin", "cot",
             "lim", "log")
reserved = ("{", "}", "%", "$", "#", "~")
Ejemplo n.º 23
0
hr = fi.readline().replace('#','').replace('\r','').replace('\n','').split(' ')	# remove hashtags and whitespaces
fi.seek(0)	# set pointer at the beginning of an input file
fi.close()	# obvious :)

# delete null strings
while hr.count(''): 				# counter of null strings in the header list, each loop step decreases this value
	del hr[hr.index('')]			# method .index('') returns index of the first occurence of null string

# read data
D = np.loadtxt(args.input_file) 	# "import numpy as np" during pylab import 
no = D[:,0] 						# get the first column of D array, numbers indicating the stars
ismag = np.empty(len(no))
ismag.fill(nocompl)

# bunchlst - list of the Bunches, each Bunch represents 4 columns: instrumental mag, error of instr. mag, standard mag and it's error
Bunchlst = [Bunch(imag = D[:,i], err_imag = D[:,i+1], smag = D[:,i+2], err_smag = D[:,i+3]) for i in range(1, D.shape[1] - 1, 4)]

# search for incomplete pairs of mags, i.e. mags equal nocompl value
for b in Bunchlst:
	b.ismag = np.copy(ismag)
	b.compl = np.logical_not([1 if nocompl in [im,ie,sm,se] else 0 for im,ie,sm,se in zip(b.imag,b.err_imag,b.smag,b.err_smag)])
	for nr, i in enumerate(b.err_imag):
		if i < min_err_mag:
			b.err_imag[nr] = min_err_mag
	for nr, i in enumerate(b.err_smag):
		if i < min_err_mag:
			b.err_smag[nr] = min_err_mag

# only good points to calculate instrumental colors (needed because points come from two different Bunches)
for b1, b2 in zip(Bunchlst, Bunchlst[1:]):
	b1.filt = np.logical_and(b1.compl,b2.compl)
Ejemplo n.º 24
0
               setcolor_nonstroke='scn',
               setdash='d',
               setlinejoin='j',
               setlinecap='J',
               setgstate='gs',
               gsave='q',
               grestore='Q',
               textpos='Td',
               selectfont='Tf',
               textmatrix='Tm',
               show='Tj',
               showkern='TJ',
               setlinewidth='w',
               clip='W')

Op = Bunch(**dict([(name, Operator(value))
                   for name, value in _pdfops.items()]))


class Stream:
    """PDF stream object.

    This has no pdfRepr method. Instead, call begin(), then output the
    contents of the stream by calling write(), and finally call end().
    """
    def __init__(self, id, len, file, extra=None):
        """id: object id of stream; len: an unused Reference object for the
	length of the stream, or None (to use a memory buffer); file:
	a PdfFile; extra: a dictionary of extra key-value pairs to
	include in the stream header """
        self.id = id  # object id
        self.len = len  # id of length object