PlotAC.py 6.62 KiB
# PlotAC.py -- Pamhyr
# Copyright (C) 2023-2024  INRAE
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program.  If not, see <https://www.gnu.org/licenses/>.

# -*- coding: utf-8 -*-

import logging

from tools import timer
from View.Tools.PamhyrPlot import PamhyrPlot

logger = logging.getLogger()


class PlotAC(PamhyrPlot):
    def __init__(self, canvas=None, trad=None, data=None, toolbar=None,
                 parent=None):
        super(PlotAC, self).__init__(
            canvas=canvas,
            trad=trad,
            data=data,
            toolbar=toolbar,
            parent=parent
        )

        self._isometric_axis = False

        self._auto_relim_update = True
        self._autoscale_update = True

        self.label_x = self._trad["transverse_abscissa"]
        self.label_y = self._trad["unit_height"]

        self.label_previous_plot_selected = self._trad["prev_cs"]
        self.label_plot_selected = self._trad["cs"]
        self.label_next_plot_selected = self._trad["next_cs"]

        self.previous_plot_selected = None
        self.plot_selected = None
        self.next_plot_selected = None

    @timer
    def draw(self):
        self.init_axes()

        if self.data.number_profiles == 0:
            return

        np = len(self.data.profiles)
        if np < 2:
            return

        self.draw_current()
        self.draw_gl()

        self.canvas.axes.legend(fancybox=True, shadow=True, fontsize=8)

        self.idle()
        self._init = True

    def draw_current(self):
        profile_id = 0
        profile = self.data.profile(profile_id)
        station = profile.get_station()
        elevation = profile.z()
        gl = profile.names()

        self.previous_plot_selected, = self.canvas.axes.plot(
            [], [],
            label=self.label_previous_plot_selected,
            lw=1.5, linestyle='--', color=self.color_plot_previous
        )

        self.plot_selected, = self.canvas.axes.plot(
            station, elevation,
            label=self.label_plot_selected,
            color=self.color_plot_current, lw=1.5
        )

        next_id = profile_id + 1
        station_next = self.data.profile(next_id).get_station()
        elevation_next = self.data.profile(next_id).z()

        self.next_plot_selected, = self.canvas.axes.plot(
            station_next, elevation_next,
            label=self.label_next_plot_selected,
            color=self.color_plot_next, lw=1.6, linestyle='--'
        )
        self.canvas.axes.set_visible(False)

    def draw_gl(self):
        if self._current_data_update:
            profile_id = self._current_data
        else:
            profile_id = 0

        profile = self.data.profile(profile_id)
        if profile is None:
            return

        station = profile.get_station()
        elevation = profile.z()
        gl = profile.names()

        self.annotation = []
        self.complete_gl, self.incomplete_gl = self.data.compute_guidelines()

        lcomplete = list(self.complete_gl)
        lincomplete = list(self.incomplete_gl)

        self.color_complete_gl = self.colors
        self.color_incomplete_gl = 2 * ["grey"]

        x_gl_complete = []
        y_gl_complete = []
        x_gl_incomplete = []
        y_gl_incomplete = []

        for i, txt in enumerate(gl):
            if txt == "":
                continue

            if txt.strip() in self.complete_gl:
                color = self.color_complete_gl[
                    lcomplete.index(txt) % len(self.color_complete_gl)
                ]
            else:
                color = self.color_incomplete_gl[
                    lincomplete.index(txt)
                ]

            annotation = self.canvas.axes.annotate(
                txt, (station[i], elevation[i]),
                horizontalalignment='left',
                verticalalignment='top',
                annotation_clip=True,
                fontsize=11, color=color
            )

            annotation.set_position((station[i] + 0., elevation[i] + 0.))
            self.annotation.append(annotation)

            if txt.strip() in self.complete_gl:
                x_gl_complete.append(station[i])
                y_gl_complete.append(elevation[i])
            else:
                x_gl_incomplete.append(station[i])
                y_gl_incomplete.append(elevation[i])

    @timer
    def update(self):
        if not self._init:
            self.draw()
            return

        if self.data is None:
            return

        self.update_current()
        self.update_gl()

        self.update_idle()

    def update_current(self):
        if self._current_data_update:
            profile_id = self._current_data
            previous_id = profile_id - 1
            next_id = profile_id + 1

            self.previous_plot_selected.set_visible(False)
            self.plot_selected.set_visible(False)
            self.next_plot_selected.set_visible(False)

            self.previous_plot_selected.set_data([], [])
            self.plot_selected.set_data([], [])
            self.next_plot_selected.set_data([], [])

            if 0 <= previous_id < self.data.number_profiles:
                self.previous_plot_selected.set_data(
                    self.data.profile(previous_id).get_station(),
                    self.data.profile(previous_id).z()
                )
                self.previous_plot_selected.set_visible(True)

            if 0 <= profile_id < self.data.number_profiles:
                self.plot_selected.set_data(
                    self.data.profile(profile_id).get_station(),
                    self.data.profile(profile_id).z()
                )
                self.plot_selected.set_visible(True)

            if 0 <= next_id < self.data.number_profiles:
                self.next_plot_selected.set_data(
                    self.data.profile(next_id).get_station(),
                    self.data.profile(next_id).z()
                )
                self.next_plot_selected.set_visible(True)

            self.canvas.axes.set_visible(True)

    def update_full(self):
        self.draw()

    def update_gl(self):
        for a in self.annotation:
            a.remove()

        self.annotation[:] = []
        self.draw_gl()