示例#1
0
    def __init__(self,
                 shape=(1, 1),
                 alignment='c',
                 float_format='.2f',
                 int_format='d',
                 position='h!',
                 as_float_env=True,
                 top_rule=True,
                 bottom_rule=True,
                 label='',
                 caption='',
                 caption_pos='top',
                 caption_space='6pt'):
        """
        Args:
            shape (tuple of 2 ints): Shape of the table.
            alignment (str or sequence of str, either 'c', 'r', or 'l'): Alignment of the text inside the columns. If a sequence, it should be the same length as the number of columns. If only a string, it will be used for all columns.
            float_format (str): Standard Python float formating available used as default for every float in the table. To change specific cell formats, use the 'change_format' method on a selected area.
            int_format (str): Standard Python int formating available used as default for every int in the table. To change specific cell formats, use the 'change_format' method on a selected area.
            as_float_env (bool): If True (default), will wrap a 'tabular' environment with a floating 'table' environment. If False, only the 'tabular' is constructed.
            position (str, either 'h', 't', 'b', with optional '!'): Position of the float environment. Default is 't'. Combinaisons of letters allow more flexibility. Only valid if as_float_env is True.
            top_rule, bottom_rule (bool): Whether or not the table should have outside rules.
            label (str): Label of the environment.
            caption (str): Caption of the table. Does not apply if 'as_float_env' is False.
            caption_pos (str, either 'top' or 'bottom'): Position of the caption, either above (top) the table or below (bottom). Does not apply if 'as_float_env' is False.
            caption_space (str, valid TeX length): Space between the caption and the table. Can be any valid TeX length. Does not apply if 'as_float_env' is False.
        """
        super().__init__(as_float_env=as_float_env,
                         position=position,
                         label=label,
                         caption=caption,
                         caption_pos=caption_pos,
                         caption_space=caption_space)

        self.tabular = TexEnvironment('tabular')
        self.add_package('booktabs')
        self.body.append(self.tabular)

        self.top_rule = top_rule
        self.bottom_rule = bottom_rule

        self.shape = shape
        self.alignment = [alignment] * shape[1] if len(
            alignment) == 1 else alignment
        self.float_format = float_format
        self.int_format = int_format
        self.data = np.full(shape, '', dtype=object)

        self.rules = {}
        self.multicells = []
        self.highlights = []
        self.formats = np.full(shape, None, dtype=object)
示例#2
0
 def new_subsubsection(self, name, label=''):
     """
     Args:
         name (str): Name of the subsubsection.
         label (str): Label of the subsubsection to refer to.
     """
     return self.new(TexEnvironment('subsubsection', name, label=label))
def plot_palette(
    doc_name,
    palette,
    n_colors=5,
    width=5,
    height=1,
):
    palette.n_colors = n_colors
    palette.tex_colors = []
    palette._init_colors()

    color_width = width / n_colors

    tikzpic = TexEnvironment('tikzpicture')
    tikzpic.add_package('tikz')

    for i, color in zip(range(n_colors), palette):
        pos = i * color_width
        tikzpic += f'\\fill[draw, {build(color, tikzpic)}] ({pos},0) rectangle ({pos+color_width},{height});'

    doc = Document(doc_name, filepath='./palettes/', doc_type='standalone')
    doc += tikzpic
    doc.build(delete_files=['log', 'aux'])
示例#4
0
def plot_palette(doc, palette_name):
    # Create plots to compare the cmaps
    plot = doc.new(
        Plot(
            plot_path=filepath,
            plot_name=filename + '_' + palette_name,
            lines='3pt',
            height='6cm',
        ))
    cmap = PREDEFINED_CMAPS[palette_name]
    palette = PREDEFINED_PALETTES[palette_name]

    # Numer of colors shown in the plot
    n_colors = 25
    interp_param = np.linspace(0, 1, n_colors + 1)

    # Plot the hue(h)-lightness(J) space
    for i, JCh_color in zip(range(n_colors), palette):
        cmap.color_model = 'rgb'  # Default JCh color model takes the hue mod 360 to be a valid color, but this makes the color map look non-continuous. The rgb color model does not process any of the components.
        J1, C1, h1 = cmap(interp_param[i])
        J2, C2, h2 = cmap(interp_param[i + 1])
        cmap.color_model = 'JCh'  # Resetting the color model to the original

        plot.add_plot([h1, h2], [J1, J2], color=JCh_color, line_cap='round')

    plot.x_label = 'Hue angle $h$'
    plot.y_label = 'Lightness $J$'

    plot.caption = f'The \\texttt{{{palette_name}}} color map'

    # Show the generated colors in squares using TikZ.
    for n_colors in [2, 3, 4, 5, 6, 9]:
        doc += f'{n_colors} colors: \\hspace{{10pt}}'
        tikzpicture = doc.new(
            TexEnvironment('tikzpicture', options=['baseline=-.5ex']))
        for i, color in zip(range(n_colors), palette):
            tikzpicture += Node((i, 0), fill=color)
        doc += ' '
示例#5
0
    def __init__(self,
                 *X_Y,
                 plot_name=None,
                 plot_path='.',
                 width=r'.8\textwidth',
                 height=r'.45\textwidth',
                 grid=True,
                 marks=False,
                 lines=True,
                 axis_y='left',
                 axis_x='bottom',
                 position='h!',
                 as_float_env=True,
                 label='',
                 caption='',
                 caption_pos='bottom',
                 caption_space='',
                 **axis_kwoptions):
        """
        Args:
            X_Y (tuple of sequences of points to plot): If only one sequence is passed, it will be considered as the Y
            components of the plot and the X will goes from 0 to len(Y)-1. If more than one sequence is passed,
            the sequences are treated in pairs (X,Y) of sequences of points.
            (This behavior copies matplotlib.pyplot.plot).

            plot_name (str): Name of the plot. Used to save data to a csv.
            plot_path (str): Path of the plot. Used to save data to a csv. Default is current working directory.

            width (str): Width of the figure. Can be any LaTeX length.
            height (str): Height of the figure. Can be any LaTeX length.

            grid (bool or str): Whether if the grid if shown on not. If a string, should be one of pgfplots valid
            argument for 'grid'.
            marks (bool or str): Whether to plot coordinates with or without marks. If a str, should be the radius
            of the marks with any LaTeX length.
            lines (bool or str): Whether to link coordinates with lines or not. If a str, should be the width of the
            lines with any LaTeX length.
            axis_x (str, either 'bottom' or 'top'): Where the x axis should appear (bottom or top).
            axis_y (str, either 'left' or 'right'): Where the y axis should appear (left or right).

            position (str, either 'h', 't', 'b', with optional '!'): Position of the float environment. Default is 't'.
            Combinaisons of letters allow more flexibility. Only valid if as_float_env is True.
            as_float_env (bool): If True (default), will wrap a 'tabular' environment with a floating 'table'
            environment. If False, only the 'tabular' is constructed.
            label (str): Label of the environment.

            caption, caption_pos, caption_space: See _FloatingEnvironment for description.

            axis_kwoptions (dict): pgfplots keyword options for the axis. All underscore will be replaced by spaces
            when converted to LaTeX parameters.
        """
        super().__init__(as_float_env=as_float_env,
                         position=position,
                         label=label,
                         caption=caption,
                         caption_pos=caption_pos,
                         caption_space=caption_space)

        self.add_package('tikz')
        self.add_package('pgfplots')
        self.add_package('pgfplotstable')

        self.tikzpicture = TexEnvironment('tikzpicture')
        self.add_text(self.tikzpicture)

        if grid is True:
            grid = 'major'
        elif grid is False:
            grid = 'none'

        options = (
            'grid style={dashed,gray!50}',
            f'axis y line*={axis_y}',
            f'axis x line*={axis_x}',
            # 'axis line style={-latex}',
        )
        self.axis = TexEnvironment('axis',
                                   options=options,
                                   width=width,
                                   height=height,
                                   grid=grid,
                                   **axis_kwoptions)
        self.tikzpicture.add_text(self.axis)
        # if not marks:
        #     self.axis.options += ['no marks',]

        self.plot_name = plot_name or f"plot-{dt.now().strftime(r'%Y-%m-%d %Hh%Mm%Ss')}"
        self.plot_path = plot_path

        if not marks:
            mark_size = '0pt'
        elif isinstance(marks, str):
            mark_size = marks
        else:
            mark_size = '2pt'

        if not lines:
            line_width = '0pt'
        elif isinstance(lines, str):
            line_width = lines
        else:
            line_width = '1.25pt'

        self.default_plot_kwoptions = {
            'line width': line_width,
            'mark size': mark_size,
        }

        iter_X_Y = iter(X_Y)
        self.plots = []
        for x, y in zip(iter_X_Y, iter_X_Y):
            self.add_plot(x, y)
        if len(X_Y) % 2 != 0:  # Copies matplotlib.pyplot.plot() behavior
            self.add_plot(np.arange(len(X_Y[-1])), X_Y[-1])

        self.matrix_plot = None
示例#6
0
class Plot(FloatingEnvironmentMixin, super_class=FloatingFigure):
    """
    Implements an easy wrapper to plot curves directly into LaTex. Creates a floating figure if wanted and uses
    'pgfplots' to draw the curves.

    It aims to be as easy as matplotlib to use, but to have more beautiful default parameters and to produce directly
    in LaTeX for easy integration into papers.

    Supported options as properties:
    x_min, x_max, y_min, y_max (number): Sets the limits of the axis.
    x_label, y_label (str): Labels of the axes.
    x_ticks, y_ticks (sequence of float): Positions of the ticks on each axis.
    x_ticks_labels, y_ticks_labels (sequence of str): String to print under each ticks. Should be the same length as
    x_ticks and y_ticks.
    legend_position (str): Specifies the corner of the legend. Should be a valid combinaisons of two of 'north', 'west',
     'south' and 'east'.

    If you know the pgfplots library, all 'axis' environment's parameters can be accessed and modified via the
    'self.axis.options' and the 'self.axis.kwoptions' attributes.
    """
    def __init__(self,
                 *X_Y,
                 plot_name=None,
                 plot_path='.',
                 width=r'.8\textwidth',
                 height=r'.45\textwidth',
                 grid=True,
                 marks=False,
                 lines=True,
                 axis_y='left',
                 axis_x='bottom',
                 position='h!',
                 as_float_env=True,
                 label='',
                 caption='',
                 caption_pos='bottom',
                 caption_space='',
                 **axis_kwoptions):
        """
        Args:
            X_Y (tuple of sequences of points to plot): If only one sequence is passed, it will be considered as the Y
            components of the plot and the X will goes from 0 to len(Y)-1. If more than one sequence is passed,
            the sequences are treated in pairs (X,Y) of sequences of points.
            (This behavior copies matplotlib.pyplot.plot).

            plot_name (str): Name of the plot. Used to save data to a csv.
            plot_path (str): Path of the plot. Used to save data to a csv. Default is current working directory.

            width (str): Width of the figure. Can be any LaTeX length.
            height (str): Height of the figure. Can be any LaTeX length.

            grid (bool or str): Whether if the grid if shown on not. If a string, should be one of pgfplots valid
            argument for 'grid'.
            marks (bool or str): Whether to plot coordinates with or without marks. If a str, should be the radius
            of the marks with any LaTeX length.
            lines (bool or str): Whether to link coordinates with lines or not. If a str, should be the width of the
            lines with any LaTeX length.
            axis_x (str, either 'bottom' or 'top'): Where the x axis should appear (bottom or top).
            axis_y (str, either 'left' or 'right'): Where the y axis should appear (left or right).

            position (str, either 'h', 't', 'b', with optional '!'): Position of the float environment. Default is 't'.
            Combinaisons of letters allow more flexibility. Only valid if as_float_env is True.
            as_float_env (bool): If True (default), will wrap a 'tabular' environment with a floating 'table'
            environment. If False, only the 'tabular' is constructed.
            label (str): Label of the environment.

            caption, caption_pos, caption_space: See _FloatingEnvironment for description.

            axis_kwoptions (dict): pgfplots keyword options for the axis. All underscore will be replaced by spaces
            when converted to LaTeX parameters.
        """
        super().__init__(as_float_env=as_float_env,
                         position=position,
                         label=label,
                         caption=caption,
                         caption_pos=caption_pos,
                         caption_space=caption_space)

        self.add_package('tikz')
        self.add_package('pgfplots')
        self.add_package('pgfplotstable')

        self.tikzpicture = TexEnvironment('tikzpicture')
        self.add_text(self.tikzpicture)

        if grid is True:
            grid = 'major'
        elif grid is False:
            grid = 'none'

        options = (
            'grid style={dashed,gray!50}',
            f'axis y line*={axis_y}',
            f'axis x line*={axis_x}',
            # 'axis line style={-latex}',
        )
        self.axis = TexEnvironment('axis',
                                   options=options,
                                   width=width,
                                   height=height,
                                   grid=grid,
                                   **axis_kwoptions)
        self.tikzpicture.add_text(self.axis)
        # if not marks:
        #     self.axis.options += ['no marks',]

        self.plot_name = plot_name or f"plot-{dt.now().strftime(r'%Y-%m-%d %Hh%Mm%Ss')}"
        self.plot_path = plot_path

        if not marks:
            mark_size = '0pt'
        elif isinstance(marks, str):
            mark_size = marks
        else:
            mark_size = '2pt'

        if not lines:
            line_width = '0pt'
        elif isinstance(lines, str):
            line_width = lines
        else:
            line_width = '1.25pt'

        self.default_plot_kwoptions = {
            'line width': line_width,
            'mark size': mark_size,
        }

        iter_X_Y = iter(X_Y)
        self.plots = []
        for x, y in zip(iter_X_Y, iter_X_Y):
            self.add_plot(x, y)
        if len(X_Y) % 2 != 0:  # Copies matplotlib.pyplot.plot() behavior
            self.add_plot(np.arange(len(X_Y[-1])), X_Y[-1])

        self.matrix_plot = None

    x_max = _AxisProperty('xmax')
    x_min = _AxisProperty('xmin')
    y_max = _AxisProperty('ymax')
    y_min = _AxisProperty('ymin')
    x_label = _AxisProperty('xlabel')
    y_label = _AxisProperty('ylabel')
    x_ticks = _AxisTicksProperty('xtick')
    y_ticks = _AxisTicksProperty('ytick')
    x_ticks_labels = _AxisTicksLabelsProperty('xticklabels')
    y_ticks_labels = _AxisTicksLabelsProperty('yticklabels')
    title = _AxisProperty('title')

    legend_position = _AxisProperty('legend pos')

    def add_plot(self,
                 X,
                 Y,
                 *options,
                 legend=None,
                 forget_plot=True,
                 **kwoptions):
        """
        Adds a plot to the axis.

        Args:
            X (sequence of numbers): X coordinates.
            Y (sequence of numbers): Y coordinates.
            options (Tuple[Union(str, TexObject]): Options for the plot. Colors can be specified here as strings of the whole color, e.g. 'black', 'red', 'blue', etc. See pgfplots '\addplot[options]' for possible options. All underscores are replaced by spaces when converted to LaTeX.
            legend (str): Entry of the plot.
            forget_plot (bool): forget_plot is used to correctly present the legend. Default behavior is to add 'forget plot' option when no legend is provided. However, this can lead to incompatibility when plotting histograms. It is advised to set it to False in that case.
            kwoptions (Dict[str, Union(str, TexObject)): Keyword options for the plot. See pgfplots '\addplot[kwoptions]' for possible options. All underscores are replaced by spaces when converted to LaTeX.
        """
        self.axis += LinePlot(X,
                              Y,
                              *options,
                              legend=legend,
                              forget_plot=forget_plot,
                              **kwoptions)

    def add_matrix_plot(self, X, Y, Z, *options, colorbar=True, **kwoptions):
        """
        Adds a matrix plot to the axis.

        Args:
            X (sequence of numbers): X coordinates. Should have the same length as the first dimension of Z.
            Y (sequence of numbers): Y coordinates. Should have the same length as the second dimension of Z.
            Z (Array of numbers of dim (x_dim, y_dim)): Z coordinates.
            options (Union[Tuple[str], str, TexObject]): Options for the plot. See pgfplots '\addplot[options]' for
            possible options. All underscores are replaced by spaces when converted to LaTeX.
            colorbar (str): Colorbar legend.
            kwoptions (tuple of str): Keyword options for the plot. See pgfplots '\addplot[kwoptions]' for possible
            options. All underscores are replaced by spaces when converted to LaTeX.
        """
        if colorbar:
            self.axis.options += ('colorbar', )
            # self.axis.kwoptions['enlargelimits'] = 'false'
        self.axis += MatrixPlot(X, Y, Z, *options, **kwoptions)

    def save_to_csv(self):
        filepath = os.path.join(self.plot_path, self.plot_name + '.csv')
        os.makedirs(self.plot_path, exist_ok=True)
        plots = [obj for obj in self.axis.body if isinstance(obj, _Plot)]
        matrix_plot = None
        for i, plot in enumerate(plots):
            if isinstance(plot, MatrixPlot):
                matrix_plot = plots.pop(i)

        with open(filepath, 'w', newline='') as file:
            writer = csv.writer(file)

            titles = [
                coor for p in plots
                for coor in (f'x{p.id_number}', f'y{p.id_number}')
            ]
            if matrix_plot:
                titles += [
                    f'x{matrix_plot.id_number}', f'y{matrix_plot.id_number}',
                    f'z{matrix_plot.id_number}'
                ]
            writer.writerow(titles)
            data = [x_y for p in plots for x_y in (p.X, p.Y)]
            if matrix_plot:
                XX, YY = np.meshgrid(matrix_plot.X, matrix_plot.Y)
                data += [
                    XX.reshape(-1),
                    YY.reshape(-1),
                    matrix_plot.Z.T.reshape(-1)
                ]

            for row in itertools.zip_longest(*data, fillvalue=''):
                writer.writerow(row)

    def build(self):
        for obj in self.axis.body:
            if isinstance(obj, _Plot):
                # We cannot use os.path.join, since on Windows it uses backslashes,
                # but pgfplots can only read paths with forward slashes.
                plot_filepath = self.plot_path + '/' + self.plot_name + '.csv'
                obj.plot_filepath = plot_filepath.replace('//', '/')

        self.save_to_csv()

        self.axis.options += (
            f"every axis plot/.append style={{{', '.join('='.join([k, v]) for k, v in self.default_plot_kwoptions.items())}}}",
        )

        return super().build()
from python2latex import Document, TexEnvironment

doc = Document(filename='unsupported_env_example',
               doc_type='article',
               filepath='examples/unsupported env example',
               options=('12pt', ))

sec = doc.new_section('Unsupported env')
sec.add_text("This section shows how to create unsupported env if needed.")

sec.add_package(
    'amsmath')  # Add needed packages in any TexEnvironment, at any level
align = sec.new(TexEnvironment('align', label='align_label'))
align.add_text(r"""e^{i\pi} &= \cos \pi + i \sin \pi\\
         &= -1""")  # Use raw strings to alleviate tex writing

tex = doc.build()
print(tex)
示例#8
0
        doc += f'{n_colors} colors: \\hspace{{10pt}}'
        tikzpicture = doc.new(
            TexEnvironment('tikzpicture', options=['baseline=-.5ex']))
        for i, color in zip(range(n_colors), palette):
            tikzpicture += Node((i, 0), fill=color)
        doc += ' '


if __name__ == "__main__":
    # Create document
    filepath = './examples/plot examples/predefined palettes comparison/'
    filename = 'PREDEFINED_PALETTES_comparison'
    doc = Document(filename, doc_type='article', filepath=filepath)

    # Insert title
    center = doc.new(TexEnvironment('center'))
    center += r"\huge \bf Predefined color maps and palettes"

    doc += """\\noindent
    python2latex provides three color maps natively. They are defined in the JCh axes of the CIECAM02 color model, which is linear to human perception of colors. Moreover, three ``dynamic'' palettes have been defined, one for each color map. They are dynamic in that the range of colors used to produce the palette changes with the number of colors needed. This allows for a good repartition of hues and brightness for all choices of number of colors.

    All three color maps have been designed to be colorblind friendly for all types of colorblindness. To do so, all color maps are only increasing or decreasing in lightness, which helps to distinguish hues that may look similar to a colorblind. This also has the advantage that the palettes are also viable in levels of gray.
    """

    # First section
    sec = doc.new_section(r'The \texttt{holi} color map')
    sec += """
    The ``holi'' color map was designed to provide a set of easily distinguishable hues for any needed number of colors. It is optimized for palettes of 5 or 6 colors, but other numbers of color also generate very good palettes. It is colorblind friendly for all types of colorblindness for up to 5 colors, but can still be acceptable for more colors. The name ``holi'' comes from the Hindu festival of colors. This is the default color map of python2latex.

    Below is a graph of the color map in the J-h axes of the CIECAM02 color model, followed by the colors generated according to the number of colors needed.
    """
示例#9
0
class Table(FloatingEnvironmentMixin, super_class=FloatingTable):
    """
    Implements a (floating) 'table' environment. Wraps many features for easy usage and flexibility, such as:
        - Supports slices to set items.
        - Easy and automatic multirow and multicolumn cells.
        - Automatically highlights best value inside a region of the table.
    To do so, the brackets access [] (__getitem__) has been repurposed to select an area and returns a SelectedArea object. Announced features are defined on SelectedArea objects only. To access the actual data inside the table, use the 'data' attribute with brackets.

    TODO:
        - Maybe: Add a 'insert_row' and 'insert_column' methods.
    """
    def __init__(self,
                 shape=(1, 1),
                 alignment='c',
                 float_format='.2f',
                 int_format='d',
                 position='h!',
                 as_float_env=True,
                 top_rule=True,
                 bottom_rule=True,
                 label='',
                 caption='',
                 caption_pos='top',
                 caption_space='6pt'):
        """
        Args:
            shape (tuple of 2 ints): Shape of the table.
            alignment (str or sequence of str, either 'c', 'r', or 'l'): Alignment of the text inside the columns. If a sequence, it should be the same length as the number of columns. If only a string, it will be used for all columns.
            float_format (str): Standard Python float formating available used as default for every float in the table. To change specific cell formats, use the 'change_format' method on a selected area.
            int_format (str): Standard Python int formating available used as default for every int in the table. To change specific cell formats, use the 'change_format' method on a selected area.
            as_float_env (bool): If True (default), will wrap a 'tabular' environment with a floating 'table' environment. If False, only the 'tabular' is constructed.
            position (str, either 'h', 't', 'b', with optional '!'): Position of the float environment. Default is 't'. Combinaisons of letters allow more flexibility. Only valid if as_float_env is True.
            top_rule, bottom_rule (bool): Whether or not the table should have outside rules.
            label (str): Label of the environment.
            caption (str): Caption of the table. Does not apply if 'as_float_env' is False.
            caption_pos (str, either 'top' or 'bottom'): Position of the caption, either above (top) the table or below (bottom). Does not apply if 'as_float_env' is False.
            caption_space (str, valid TeX length): Space between the caption and the table. Can be any valid TeX length. Does not apply if 'as_float_env' is False.
        """
        super().__init__(as_float_env=as_float_env,
                         position=position,
                         label=label,
                         caption=caption,
                         caption_pos=caption_pos,
                         caption_space=caption_space)

        self.tabular = TexEnvironment('tabular')
        self.add_package('booktabs')
        self.body.append(self.tabular)

        self.top_rule = top_rule
        self.bottom_rule = bottom_rule

        self.shape = shape
        self.alignment = [alignment] * shape[1] if len(
            alignment) == 1 else alignment
        self.float_format = float_format
        self.int_format = int_format
        self.data = np.full(shape, '', dtype=object)

        self.rules = {}
        self.multicells = []
        self.highlights = []
        self.formats = np.full(shape, None, dtype=object)

    def __getitem__(self, idx):
        return SelectedArea(self, idx)

    def __setitem__(self, idx, value):
        selected_area = self[idx]
        if isinstance(value, (str, int, float)) and selected_area.size > 1:
            # There are multirows or multicolumns to treat
            selected_area.multicell(value)
        else:
            self.data[idx] = value

    def __repr__(self):
        return repr(self.data)

    def _format_cells(self):
        for i, row in enumerate(self.data):
            for j, value in enumerate(row):
                cell_format = self.formats[i, j]
                if cell_format is not None and not isinstance(
                        cell_format, str):  # Callable
                    self.data[i, j] = cell_format(value)
                elif cell_format is not None and isinstance(
                        value, (float, int)):  # String
                    self.data[i, j] = f'{{:{cell_format}}}'.format(value)
                elif cell_format is None and isinstance(
                        value, float):  # Fallback to default
                    self.data[i, j] = f'{{:{self.float_format}}}'.format(value)
                elif cell_format is None and isinstance(value, int):
                    self.data[i, j] = f'{{:{self.int_format}}}'.format(value)

    def _apply_highlights(self):
        for i, j, highlight in self.highlights:
            if highlight == 'bold':
                highlight = bold
            elif highlight == 'italic':
                highlight = italic
            self.data[i, j] = highlight(self.data[i, j])

    def _generate_table_format(self):
        """
        Generates table format and applies multicells if needed.
        """
        table_format = np.array([[' & '] * (self.shape[1] - 1) + [r'\\']] *
                                self.shape[0],
                                dtype=object)

        for idx, v_align, h_align, v_shift in self.multicells:

            start_i, stop_i, _ = idx[0].indices(self.shape[0])
            start_j, stop_j, _ = idx[1].indices(self.shape[1])

            table_format[start_i, slice(start_j, stop_j - 1)] = ''
            cell_shape = table_format[idx].shape

            if start_i == stop_i - 1:
                self.data[
                    start_i,
                    start_j] = f"\\multicolumn{{{cell_shape[1]}}}{{{h_align}}}{{{self.data[start_i, start_j]}}}"
            else:
                shift = ''
                if v_shift:
                    shift = f'[{v_shift}]'
                self.data[
                    start_i,
                    start_j] = f"\\multirow{{{cell_shape[0]}}}{{{v_align}}}{shift}{{{self.data[start_i, start_j]}}}"

            if start_j < stop_j - 1 and start_i < stop_i - 1:
                self.data[
                    start_i,
                    start_j] = f"\\multicolumn{{{cell_shape[1]}}}{{{h_align}}}{{{self.data[start_i, start_j]}}}"

        return table_format

    def build(self):
        self.tabular.head.parameters += (''.join(self.alignment), )
        if self.top_rule:
            self.tabular.body.append(r"\toprule")

        self._format_cells()
        self._apply_highlights()
        table_format = self._generate_table_format()

        for i, (row, row_format) in enumerate(zip(self.data, table_format)):
            self.tabular.body.append(''.join(
                str(build(item, self)) for pair in zip(row, row_format)
                for item in pair))
            if i in self.rules:
                for rule in self.rules[i]:
                    self.tabular.body.append(build(rule))

        if self.bottom_rule:
            self.tabular.append(r'\bottomrule')

        return super().build()
示例#10
0
    def __init__(self,
                 *X_Y,
                 plot_name=None,
                 plot_path='.',
                 width=r'.8\textwidth',
                 height=r'.45\textwidth',
                 grid=True,
                 grid_style=('dashed', 'gray!50'),
                 marks=False,
                 lines=True,
                 palette=default_palette,
                 axis_y='left',
                 axis_x='bottom',
                 position='h!',
                 as_float_env=True,
                 label='',
                 caption='',
                 caption_pos='bottom',
                 caption_space='',
                 **axis_kwoptions):
        """
        Args:
            X_Y (tuple of sequences of points to plot):
                If only one sequence is passed, it will be considered as the Y components of the plot and the X will goes from 0 to len(Y)-1. If more than one sequence is passed, the sequences are treated in pairs (X,Y) of sequences of points. (This behavior copies matplotlib.pyplot.plot).
            plot_name (str):
                Name of the plot. Used to save data to a csv.
            plot_path (str):
                Path of the plot. Used to save data to a csv. Default is current working directory.
            width (str):
                Width of the figure. Can be any LaTeX length.
            height (str):
                Height of the figure. Can be any LaTeX length.
            grid (Union[bool, str]):
                Whether if the grid if shown on not. If a string, should be one of pgfplots valid argument for 'grid' such as 'major', 'minor' and 'none'. Defaults to 'major'.
            grid_style (Iterable[str]):
                Iterable of options for the grid.
            marks (bool or str):
                Whether to plot coordinates with or without marks. If a str, should be the radius of the marks with any LaTeX length.
            lines (bool or str):
                Whether to link coordinates with lines or not. If a str, should be the width of the lines with any LaTeX length.
            axis_x (str, either 'bottom' or 'top'):
                Where the x axis should appear (bottom or top).
            axis_y (str, either 'left' or 'right'):
                Where the y axis should appear (left or right).
            palette (Union[str, Iterable]):
                Iterable that yields colors to use for line plots or name of the palette. The string can be 'holi' (default), 'aube' and 'aurore' (See the example 'predefined palettes comparison' for details). The iterable should yield either tuple of 3 floats between 0 and 1 interpreted as rgb colors, or python2latex Color objects for more flexibility. If the number of colors is less than the number of line plots, it will loop automatically. Default is 'holi', a dynamic colorblind-friendly palette that will generate as many distinct colors as there are line plots.
            position (str, either 'h', 't', 'b', with optional '!'):
                Position of the float environment. Default is 't'. Combinaisons of letters allow more flexibility. Only valid if as_float_env is True.
            as_float_env (bool):
                If True (default), will wrap a 'tikzpicture' environment with a floating 'figure' environment. If False, only the 'tikzpicture' is constructed.
            label (str):
                Label of the environment.
            caption, caption_pos, caption_space:
                See _FloatingEnvironment for description.
            axis_kwoptions (dict):
                pgfplots keyword options for the axis. All underscore will be replaced by spaces when converted to LaTeX parameters.
        """
        super().__init__(as_float_env=as_float_env,
                         position=position,
                         label=label,
                         caption=caption,
                         caption_pos=caption_pos,
                         caption_space=caption_space)

        self.add_package('tikz')
        self.add_package('pgfplots')
        self.add_package('pgfplotstable')

        self.tikzpicture = self.new(TexEnvironment('tikzpicture'))

        self.plot_name = plot_name or f"plot-{dt.now().strftime(r'%Y-%m-%d %Hh%Mm%Ss')}"
        self.plot_path = plot_path
        self.plot_filepath = os.path.join(self.plot_path,
                                          self.plot_name + '.csv').replace(
                                              '\\', '/')

        self.axis = Axis(width=width,
                         height=height,
                         grid=grid,
                         grid_style=grid_style,
                         marks=marks,
                         lines=lines,
                         palette=palette,
                         axis_y=axis_y,
                         axis_x=axis_x,
                         plot_filepath=self.plot_filepath,
                         **axis_kwoptions)

        self.tikzpicture.add_text(self.axis)

        iter_X_Y = iter(X_Y)
        for x, y in zip(iter_X_Y, iter_X_Y):
            self.axis.add_plot(x, y)
        if len(X_Y) % 2 != 0:  # Copies matplotlib.pyplot.plot() behavior
            self.axis.add_plot(np.arange(len(X_Y[-1])), X_Y[-1])