Skip to content

ResultArtist

ResultArtist

A class for rendering simulation results as animated GIFs.

Source code in pylattica/visualization/result_artist.py
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
class ResultArtist:
    """A class for rendering simulation results as animated GIFs."""

    def __init__(self, step_artist: StructureArtist, result: SimulationResult):
        """Instantiates the ResultArtist class.

        Parameters
        ----------
        step_artist : StructureArtist
            The artist that should be used to render each step of the simulation.
        result : SimulationResult
            The result to render.
        """
        self._step_artist = step_artist
        self.result = result

    def _get_images(self, **kwargs):
        draw_freq = kwargs.get("draw_freq", 1)
        indices = list(range(0, len(self.result), draw_freq))
        imgs = []

        if sys.platform.startswith("win"):
            for idx in indices:
                label = f"Step {idx}"
                step_kwargs = {**kwargs, "label": label}
                step = self.result.get_step(idx)
                img = self._step_artist.get_img(step, **step_kwargs)
                imgs.append(img)
        else:
            PROCESSES = mp.cpu_count()
            global _dsr_globals  # pylint: disable=global-variable-not-assigned
            _dsr_globals["artist"] = self._step_artist

            with mp.get_context("fork").Pool(PROCESSES) as pool:
                params = []
                for idx in indices:
                    label = f"Step {idx}"
                    step_kwargs = {**kwargs, "label": label}
                    step = self.result.get_step(idx)
                    params.append([step, step_kwargs])

                for img in pool.starmap(_get_img_parallel, params):
                    imgs.append(img)

        return imgs

    def jupyter_show_step(
        self,
        step_no: int,
        cell_size=20,
    ) -> None:
        """In a jupyter notebook environment, visualizes the step as a color coded phase grid.

        Parameters
        ----------
        step_no : int
            The step of the simulation to visualize
        cell_size : int, optional
            The size of each simulation cell, in pixels, by default 20
        """
        label = f"Step {step_no}"  # pragma: no cover
        step = self.result.get_step(step_no)  # pragma: no cover
        self._step_artist.jupyter_show(
            step, label=label, cell_size=cell_size
        )  # pragma: no cover

    def jupyter_play(
        self,
        cell_size: int = 20,
        wait: int = 1,
    ):
        """In a jupyter notebook environment, plays the simulation visualization back by showing a
        series of images with {wait} seconds between each one.

        Parameters
        ----------
        cell_size : int, optional
            The sidelength of a grid cell in pixels. Defaults to 20., by default 20
        wait : int, optional
            The time duration between frames in the animation. Defaults to 1., by default 1
        """
        from IPython.display import clear_output, display  # pragma: no cover

        imgs = self._get_images(cell_size=cell_size)  # pragma: no cover
        for img in imgs:  # pragma: no cover
            clear_output()  # pragma: no cover
            display(img)  # pragma: no cover
            time.sleep(wait)  # pragma: no cover

    def to_gif(self, filename: str, **kwargs) -> None:
        """Saves the simulation result result as an animated GIF.

        Parameters
        ----------
        filename : str
            The filename for the resulting file.
        """
        wait = kwargs.get("wait", 0.8)
        imgs = self._get_images(**kwargs)
        img_names = []
        for idx, img in enumerate(imgs):
            fname = f"tmp_pylat_step_{idx}.png"
            img.save(fname)
            img_names.append(fname)

        reloaded_imgs = []
        for fname in img_names:
            reloaded_imgs.append(Image.open(fname))

        reloaded_imgs[0].save(
            filename,
            save_all=True,
            append_images=reloaded_imgs[1:],
            duration=wait * 1000,
            loop=0,
        )

        for fname in img_names:
            os.remove(fname)

__init__(step_artist, result)

Instantiates the ResultArtist class.

Parameters
StructureArtist

The artist that should be used to render each step of the simulation.

SimulationResult

The result to render.

Source code in pylattica/visualization/result_artist.py
17
18
19
20
21
22
23
24
25
26
27
28
def __init__(self, step_artist: StructureArtist, result: SimulationResult):
    """Instantiates the ResultArtist class.

    Parameters
    ----------
    step_artist : StructureArtist
        The artist that should be used to render each step of the simulation.
    result : SimulationResult
        The result to render.
    """
    self._step_artist = step_artist
    self.result = result

jupyter_play(cell_size=20, wait=1)

In a jupyter notebook environment, plays the simulation visualization back by showing a series of images with {wait} seconds between each one.

Parameters
int, optional

The sidelength of a grid cell in pixels. Defaults to 20., by default 20

int, optional

The time duration between frames in the animation. Defaults to 1., by default 1

Source code in pylattica/visualization/result_artist.py
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
def jupyter_play(
    self,
    cell_size: int = 20,
    wait: int = 1,
):
    """In a jupyter notebook environment, plays the simulation visualization back by showing a
    series of images with {wait} seconds between each one.

    Parameters
    ----------
    cell_size : int, optional
        The sidelength of a grid cell in pixels. Defaults to 20., by default 20
    wait : int, optional
        The time duration between frames in the animation. Defaults to 1., by default 1
    """
    from IPython.display import clear_output, display  # pragma: no cover

    imgs = self._get_images(cell_size=cell_size)  # pragma: no cover
    for img in imgs:  # pragma: no cover
        clear_output()  # pragma: no cover
        display(img)  # pragma: no cover
        time.sleep(wait)  # pragma: no cover

jupyter_show_step(step_no, cell_size=20)

In a jupyter notebook environment, visualizes the step as a color coded phase grid.

Parameters
int

The step of the simulation to visualize

int, optional

The size of each simulation cell, in pixels, by default 20

Source code in pylattica/visualization/result_artist.py
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
def jupyter_show_step(
    self,
    step_no: int,
    cell_size=20,
) -> None:
    """In a jupyter notebook environment, visualizes the step as a color coded phase grid.

    Parameters
    ----------
    step_no : int
        The step of the simulation to visualize
    cell_size : int, optional
        The size of each simulation cell, in pixels, by default 20
    """
    label = f"Step {step_no}"  # pragma: no cover
    step = self.result.get_step(step_no)  # pragma: no cover
    self._step_artist.jupyter_show(
        step, label=label, cell_size=cell_size
    )  # pragma: no cover

to_gif(filename, **kwargs)

Saves the simulation result result as an animated GIF.

Parameters
str

The filename for the resulting file.

Source code in pylattica/visualization/result_artist.py
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
def to_gif(self, filename: str, **kwargs) -> None:
    """Saves the simulation result result as an animated GIF.

    Parameters
    ----------
    filename : str
        The filename for the resulting file.
    """
    wait = kwargs.get("wait", 0.8)
    imgs = self._get_images(**kwargs)
    img_names = []
    for idx, img in enumerate(imgs):
        fname = f"tmp_pylat_step_{idx}.png"
        img.save(fname)
        img_names.append(fname)

    reloaded_imgs = []
    for fname in img_names:
        reloaded_imgs.append(Image.open(fname))

    reloaded_imgs[0].save(
        filename,
        save_all=True,
        append_images=reloaded_imgs[1:],
        duration=wait * 1000,
        loop=0,
    )

    for fname in img_names:
        os.remove(fname)