Search code examples
pythonmanim

In manim, how do you set the text of the axis labels different to the axis units?


I want to have years on the x axis, starting at 1970 through to 2019. But when I set min x at 1970 in config, the x axis doesn't appear (I assume because it starts at 0 by default and if I set 1970 as first year, that is way off to the right).

I have had to settle for now with just showing the unit text on the x axis.

How do I fix this? My guess is that I need to tell manim the label text is different than the units of the axis, but I am not sure how - or even if that is the right approach.

Here's the code:

class TimeGraph(GraphFromData):

    CONFIG = {
            "x_min": 0,
            "x_max": 49,
            "x_tick_frequency": 5,
            "unit_size": 2,
            "y_min": 0,
            "y_max": 600,
            "y_tick_frequency": 100,
            "unit_size": 0.5,
            "x_axis_width": 12,
            "y_axis_height": 6,
            "axes_color": "#3A749C",
            "x_label_color": "#3A749C",
            "y_label_color": "#3A749C",
            "label_nums_color": "#3A749C",
            "y_label_direction": LEFT,
            "x_label_direction": DOWN,
            "camera_config": {
                    "background_color": WHITE,
            },
            "x_label_font_size": 0.5,
            "y_label_font_size": 0.5,
    }

    def construct(self):

            vector = np.array([-5, -3, 0])
            self.graph_origin = vector
            self.setup_axes()

            # Get coords
            coords = get_coords_from_excel(
                    "projects/carbon_debt/data_excel", sheet_name="unga_env"
            )

            dots = self.get_dots_from_coords(coords)
            dots.set_color("#E89F99")
            dots.set_stroke(color="#3A749C", width=1)

            self.add(dots)

    def setup_axes(self):
            GraphScene.setup_axes(self)
            init_label_x = 0
            end_label_x = 45
            step_x = 5
            init_label_y = 100
            end_label_y = 600
            step_y = 100

            self.x_axis.add_numbers(
                    *range(init_label_x, end_label_x + step_x, step_x),
            )
            self.y_axis.add_numbers(*range(init_label_y, end_label_y + step_y, step_y))

            self.add(self.x_axis)
            self.add(self.y_axis)

Solution

  • I figured it out. The solution is courtesy of TheoremOfBeethoven lessons, in particular the one on 2D plots, class called Plot5 (code here)

    A way of doing this is to make a VGroup of tuples with the axis position and the axis label and within the setup_axes method of the scene, create a TexMobject for each of the labels and position it at the axis position. The code to add to the setup_axes method would resemble the below.

    Outside of this setup_axes method you can obviously create your own values_x by iterating over x axis unit values and the list of labels you want. Call it self.values_x and call it from within the setup_axes method.

        values_x = [
            (3.5, "3.5"),  # (position 3.5, label "3.5")
            (4.5, "\\frac{9}{2}"),  # (position 4.5, label "9/2")
        ]
        self.x_axis_labels = VGroup()  # Create a group named x_axis_labels
        #   pos.   tex.
        for x_val, x_tex in values_x:
            tex = TexMobject(x_tex)  # Convert string to tex
            tex.set_color(self.label_nums_color)
            tex.scale(self.x_label_font_size)
            tex.next_to(self.coords_to_point(x_val, 0), DOWN)  # Put tex on the position
            self.x_axis_labels.add(tex)  # Add tex in graph