Esempio n. 1
0
    def plot_full_render(self, first_render, wave_data_dict, plot_data_state,
                         plot_data_mol, plot_data_concentration, n_steps,
                         vessels: vessel.Vessel, step_num):
        '''
        Method to plot thermodynamic variables and spectral data.
        Plots a significant amount of data for a more in-depth
        understanding of the information portrayed.

        Parameters
        ---------------
        `first_render` : `boolean`
            Indicates whether a plot has been already rendered
        `wave_data_dict` : `dict`
            A dictionary containing all the wave data
        `plot_data_state` : `list`
            A list containing the states to be plotted such as time,
            temperature, volume, pressure, and reactant amounts
        `plot_data_mol` : `list`
            A list containing the molar amounts of reactants and products
        `plot_data_concentration` : `list`
            A list containing the concentration of reactants and products
        `n_steps` : `int`
            The number of increments into which the action is split
        `vessels` : `vessel.Vessel`
            A vessel containing methods to obtain thermodynamic data
        `step_num` : `int`
            The step number the environment is currently on

        Returns
        ---------------
        None

        Raises
        ---------------
        None
        '''

        num_list = [
            plot_data_state[0][0], plot_data_state[1][0],
            plot_data_state[2][0], plot_data_state[3][0]
        ] + self.get_ni_num()

        reactants = []
        for reactant in self.reactants:
            name = reactant.replace("[", "").replace("]", "")
            short_name = name[0:5]
            reactants.append(short_name)

        label_list = ['t', 'T', 'V', 'P'] + reactants

        spectra_len = wave_data_dict["spectra_len"]
        absorb = wave_data_dict["absorb"]
        wave = wave_data_dict["wave"]
        wave_min = wave_data_dict["wave_min"]
        wave_max = wave_data_dict["wave_max"]

        peak = CharacterizationBench().get_spectra_peak(
            vessels, materials=self.materials)
        dash_spectra = CharacterizationBench().get_dash_line_spectra(
            vessels, materials=self.materials)

        # The first render is required to initialize the figure
        if first_render:
            plt.close('all')
            plt.ion()
            self._plot_fig, self._plot_axs = plt.subplots(3,
                                                          3,
                                                          figsize=(24, 12))

            # Time vs. Molar_Amount graph ********************** Index: (0, 0)
            self._plot_lines_amount = np.zeros((self.n.shape[0], 2, 20))
            for i in range(self.n.shape[0]):
                self._plot_lines_amount[i][0][step_num -
                                              1:] = (plot_data_state[0][0])
                self._plot_lines_amount[i][1][step_num -
                                              1:] = (plot_data_mol[i][0])
                self._plot_axs[0, 0].plot(self._plot_lines_amount[i][0],
                                          self._plot_lines_amount[i][1],
                                          label=self.materials[i])
            self._plot_axs[0, 0].set_xlim(
                [0.0, vessels.get_defaultdt() * n_steps])
            self._plot_axs[0, 0].set_ylim([0.0, np.mean(plot_data_mol)])
            self._plot_axs[0, 0].set_xlabel('Time (s)')
            self._plot_axs[0, 0].set_ylabel('Molar Amount (mol)')
            self._plot_axs[0, 0].legend()

            # Time vs. Molar_Concentration graph *************** Index: (0, 1)
            self._plot_lines_concentration = np.zeros((self.n.shape[0], 2, 20))
            total_conc = 0
            for i in range(self.n.shape[0]):
                total_conc += plot_data_concentration[i][0]
            for i in range(self.n.shape[0]):
                self._plot_lines_concentration[i][0][step_num - 1:] = (
                    plot_data_state[0][0])
                self._plot_lines_concentration[i][1][step_num - 1:] = (
                    plot_data_concentration[i][0])
                self._plot_axs[0, 1].plot(self._plot_lines_concentration[i][0],
                                          self._plot_lines_concentration[i][1],
                                          label=self.materials[i])

                self._plot_axs[2, 0].plot(
                    self._plot_lines_concentration[i][0],
                    self._plot_lines_concentration[i][1] / total_conc,
                    label=self.materials[i])

            self._plot_axs[0, 1].set_xlim(
                [0.0, vessels.get_defaultdt() * n_steps])
            self._plot_axs[0,
                           1].set_ylim([0.0,
                                        np.mean(plot_data_concentration)])
            self._plot_axs[0, 1].set_xlabel('Time (s)')
            self._plot_axs[0, 1].set_ylabel('Molar Concentration (mol/L)')
            self._plot_axs[0, 1].legend()

            # Time vs. Temperature + Time vs. Volume graph *************** Index: (0, 2)
            self._plot_lines_temp = np.zeros((1, 2, 20))
            self._plot_lines_temp[0][0][step_num -
                                        1:] = (plot_data_state[0][0])
            self._plot_lines_temp[0][1][step_num -
                                        1:] = (plot_data_state[1][0])
            self._plot_axs[0, 2].plot(self._plot_lines_temp[0][0],
                                      self._plot_lines_temp[0][1],
                                      label='T')
            self._plot_lines_vol = np.zeros((1, 2, 20))
            self._plot_lines_vol[0][0][step_num - 1:] = (plot_data_state[0][0])
            self._plot_lines_vol[0][1][step_num - 1:] = (plot_data_state[2][0])
            self._plot_axs[0, 2].plot(self._plot_lines_vol[0][0],
                                      self._plot_lines_vol[0][1],
                                      label='V')
            self._plot_axs[0, 2].set_xlim(
                [0.0, vessels.get_defaultdt() * n_steps])
            self._plot_axs[0, 2].set_ylim([0, 1.2])
            self._plot_axs[0, 2].set_xlabel('Time (s)')
            self._plot_axs[0, 2].set_ylabel('T and V (map to range [0, 1])')
            self._plot_axs[0, 2].legend()

            # Time vs. Pressure graph *************** Index: (1, 0)
            self._plot_lines_pressure = np.zeros((1, 2, 20))
            self._plot_lines_pressure[0][0][step_num -
                                            1:] = (plot_data_state[0][0])
            self._plot_lines_pressure[0][1][step_num -
                                            1:] = (plot_data_state[3][0])
            self._plot_axs[1, 0].plot(self._plot_lines_pressure[0][0],
                                      self._plot_lines_pressure[0][1],
                                      label='V')
            self._plot_axs[1, 0].set_xlim(
                [0.0, vessels.get_defaultdt() * n_steps])
            self._plot_axs[1, 0].set_ylim([0, vessels.get_pmax()])
            self._plot_axs[1, 0].set_xlabel('Time (s)')
            self._plot_axs[1, 0].set_ylabel('Pressure (kPa)')

            # Solid Spectra graph *************** Index: (1, 1)
            __ = self._plot_axs[1, 1].plot(
                wave,  # wavelength space (ranging from wave_min to wave_max)
                absorb  # absorb spectra
            )[0]

            # dash spectra
            for spectra in dash_spectra:
                self._plot_axs[1, 1].plot(wave, spectra, linestyle='dashed')

            # include the labelling when plotting spectral peaks
            for i in range(len(peak)):
                self._plot_axs[1, 1].scatter(peak[i][0],
                                             peak[i][1],
                                             label=peak[i][2])

            self._plot_axs[1, 1].set_xlim([wave_min, wave_max])
            self._plot_axs[1, 1].set_ylim([0, 1.2])
            self._plot_axs[1, 1].set_xlabel('Wavelength (nm)')
            self._plot_axs[1, 1].set_ylabel('Absorbance')
            self._plot_axs[1, 1].legend()

            # bar chart plotting the time, tempurature, pressure, and amount of each
            # species left in hand *************** Index: (1, 2)
            __ = self._plot_axs[1, 2].bar(range(len(num_list)),
                                          num_list,
                                          tick_label=label_list)[0]
            self._plot_axs[1, 2].set_ylim([0, 1])

            self._plot_axs[2, 0].set_xlim(
                [0.0, vessels.get_defaultdt() * n_steps])
            self._plot_axs[2, 0].set_ylim([0.0, 1.0])
            self._plot_axs[2, 0].set_xlabel('Time (s)')
            self._plot_axs[2, 0].set_ylabel('Purity')
            self._plot_axs[2, 0].legend()

            # draw and show the full graph
            self._plot_fig.canvas.draw()
            plt.show()

        # All other renders serve to update the existing figure with the new current state;
        # it is assumed that the above actions have already been carried out
        else:
            # set data for the Time vs. Molar_Amount graph *************** Index: (0, 0)
            curent_time = plot_data_state[0][-1]

            # update the lines data
            total_conc = 0
            for i in range(self.n.shape[0]):
                total_conc += plot_data_concentration[i][0]
            for i in range(self.n.shape[0]):
                # populate the lines amount array with the updated number of mols
                self._plot_lines_amount[i][0][step_num -
                                              1:] = (plot_data_state[0][0])
                self._plot_lines_amount[i][1][step_num -
                                              1:] = (plot_data_mol[i][0])
                self._plot_axs[0, 0].lines[i].set_xdata(
                    self._plot_lines_amount[i][0])
                self._plot_axs[0, 0].lines[i].set_ydata(
                    self._plot_lines_amount[i][1])

                # populate the lines concentration array with the updated number of concentration
                self._plot_lines_concentration[i][0][step_num - 1:] = (
                    plot_data_state[0][0])
                self._plot_lines_concentration[i][1][step_num - 1:] = (
                    plot_data_concentration[i][0])
                self._plot_axs[0, 1].lines[i].set_xdata(
                    self._plot_lines_concentration[i][0])
                self._plot_axs[0, 1].lines[i].set_ydata(
                    self._plot_lines_concentration[i][1])

                self._plot_axs[2, 0].lines[i].set_xdata(
                    self._plot_lines_concentration[i][0])
                self._plot_axs[2, 0].lines[i].set_ydata(
                    self._plot_lines_concentration[i][1] / total_conc)

            # reset each plot's x-limit because the latest action occurred at a greater time-value
            self._plot_axs[0, 0].set_xlim([0.0, curent_time])
            self._plot_axs[0, 1].set_xlim([0.0, curent_time])

            # reset each plot's y-limit in order to fit and show all materials on the graph
            self._plot_axs[0, 0].set_ylim([0.0, np.mean(plot_data_mol)])
            self._plot_axs[0,
                           1].set_ylim([0.0,
                                        np.mean(plot_data_concentration)])

            # set data for Time vs. Temp and Time vs. Volume graphs *************** Index: (0, 2)
            self._plot_lines_temp[0][0][step_num -
                                        1:] = (plot_data_state[0][0])
            self._plot_lines_temp[0][1][step_num -
                                        1:] = (plot_data_state[1][0])
            self._plot_lines_vol[0][0][step_num - 1:] = (plot_data_state[0][0])
            self._plot_lines_vol[0][1][step_num - 1:] = (plot_data_state[2][0])

            self._plot_axs[0,
                           2].lines[0].set_xdata(self._plot_lines_temp[0][0])
            self._plot_axs[0,
                           2].lines[0].set_ydata(self._plot_lines_temp[0][1])
            self._plot_axs[0, 2].lines[1].set_xdata(self._plot_lines_vol[0][0])
            self._plot_axs[0, 2].lines[1].set_ydata(self._plot_lines_vol[0][1])

            # reset xlimit since t extend
            self._plot_axs[0, 2].set_xlim([0.0, curent_time])

            # set data for Time vs. Pressure graph *************** Index: (1, 0)
            self._plot_lines_pressure[0][0][step_num -
                                            1:] = (plot_data_state[0][0])
            self._plot_lines_pressure[0][1][step_num -
                                            1:] = (plot_data_state[3][0])
            self._plot_axs[1, 0].lines[0].set_xdata(
                self._plot_lines_pressure[0][0])
            self._plot_axs[1, 0].lines[0].set_ydata(
                self._plot_lines_pressure[0][1])

            self._plot_axs[1, 0].set_xlim([0.0, curent_time
                                           ])  # reset xlime since t extend
            self._plot_axs[1,
                           0].set_ylim([0.0,
                                        np.max(plot_data_state[3]) * 1.1])

            # reset the Solid Spectra graph
            self._plot_axs[1, 1].cla()
            __ = self._plot_axs[1, 1].plot(
                wave,  # wavelength space (ranging from wave_min to wave_max)
                absorb,  # absorb spectra
            )[0]

            # obtain the new dash spectra data
            for __, item in enumerate(dash_spectra):
                self._plot_axs[1, 1].plot(wave, item, linestyle='dashed')

            # reset the spectra peak labelling
            for i in range(len(peak)):
                self._plot_axs[1, 1].scatter(peak[i][0],
                                             peak[i][1],
                                             label=peak[i][2])

            self._plot_axs[1, 1].set_xlim([wave_min, wave_max])
            self._plot_axs[1, 1].set_ylim([0, 1.2])
            self._plot_axs[1, 1].set_xlabel('Wavelength (nm)')
            self._plot_axs[1, 1].set_ylabel('Absorbance')
            self._plot_axs[1, 1].legend()

            # bar chart
            self._plot_axs[1, 2].cla()
            __ = self._plot_axs[1, 2].bar(
                range(len(num_list)),
                num_list,
                tick_label=label_list,
            )[0]
            self._plot_axs[1, 2].set_ylim([0, 1])

            # re-draw the graph
            self._plot_fig.canvas.draw()
            plt.pause(0.000001)
Esempio n. 2
0
    def plotting_step(self, t, tmax, vessels: vessel.Vessel):
        '''
        Set up a method to handle the acquisition of the necessary plotting parameters
        from an input vessel.

        Parameters
        ---------------
        `t` : `float`
            Current amount of time
        `tmax` : `float`
            Maximum time allowed
        `vessels` : `vessel.Vessel`
            A vessel containing methods to acquire the necessary parameters

        Returns
        ---------------
        `plot_data_state` : `list`
            A list containing the states to be plotted such as time,
            temperature, volume, pressure, and reactant amounts
        `plot_data_mol` : `list`
            A list containing the molar amounts of reactants and products
        `plot_data_concentration` : `list`
            A list containing the concentration of reactants and products

        Raises
        ---------------
        None
        '''

        # acquire the necessary parameters from the vessel
        T = vessels.get_temperature()
        V = vessels.get_volume()
        # V = 0.0025

        # create containers to hold the plotting parameters
        plot_data_state = [[], [], [], []]
        plot_data_mol = [[] for _ in range(self.n.shape[0])]
        plot_data_concentration = [[] for _ in range(self.n.shape[0])]

        # Record time data
        plot_data_state[0].append(t / tmax)

        # record temperature data
        Tmin = vessels.get_Tmin()
        Tmax = vessels.get_Tmax()
        plot_data_state[1].append((T - Tmin) / (Tmax - Tmin))

        # record volume data
        Vmin = vessels.get_min_volume()
        Vmax = vessels.get_max_volume()
        plot_data_state[2].append((V - Vmin) / (Vmax - Vmin))

        # record pressure data
        P = vessels.get_pressure()
        plot_data_state[3].append(P / vessels.get_pmax())

        # calculate and record the molar concentrations of the reactants and products
        C = vessels.get_concentration(materials=self.materials)
        for j in range(self.n.shape[0]):
            plot_data_mol[j].append(self.n[j])
            plot_data_concentration[j].append(C[j])

        return plot_data_state, plot_data_mol, plot_data_concentration