Function to plot the transport properties.

            Args:
                prop_y: property to plot among ("Conductivity","Seebeck","Kappa","Carrier_conc","Hall_carrier_conc_trace"). Abbreviations are possible, like "S" for "Seebeck"
                prop_x: independent variable in the x-axis among ('mu','doping','temp')
                prop_z: third variable to plot multiple curves ('doping','temp')
                output: 'avg_eigs' to plot the average of the eigenvalues of the properties
                    tensors; 'eigs' to plot the three eigenvalues of the properties
                    tensors.
                dop_type: 'n' or 'p' to specify the doping type in plots that use doping
                    levels as prop_x or prop_z
                doping: list of doping level to plot, useful to reduce the number of curves
                    when prop_z='doping'
                temps: list of temperatures to plot, useful to reduce the number of curves
                    when prop_z='temp'
                xlim: chemical potential range, useful when prop_x='mu'
                ax: figure.axes where to plot. If None, a new figure is produced.

            Example:
            bztPlotter.plot_props('S','mu','temp',temps=[600,900,1200]).show()
            more example are provided in the notebook
            "How to use Boltztra2 interface.ipynb".

def plot_props(self, prop_y, prop_x, prop_z='temp',
                   output='avg_eigs', dop_type='n', doping=None,
                   temps=None, xlim=(-2, 2), ax=None):

        """
            Function to plot the transport properties.

            Args:
                prop_y: property to plot among ("Conductivity","Seebeck","Kappa","Carrier_conc","Hall_carrier_conc_trace"). Abbreviations are possible, like "S" for "Seebeck"
                prop_x: independent variable in the x-axis among ('mu','doping','temp')
                prop_z: third variable to plot multiple curves ('doping','temp')
                output: 'avg_eigs' to plot the average of the eigenvalues of the properties
                    tensors; 'eigs' to plot the three eigenvalues of the properties
                    tensors.
                dop_type: 'n' or 'p' to specify the doping type in plots that use doping
                    levels as prop_x or prop_z
                doping: list of doping level to plot, useful to reduce the number of curves
                    when prop_z='doping'
                temps: list of temperatures to plot, useful to reduce the number of curves
                    when prop_z='temp'
                xlim: chemical potential range, useful when prop_x='mu'
                ax: figure.axes where to plot. If None, a new figure is produced.

            Example:
            bztPlotter.plot_props('S','mu','temp',temps=[600,900,1200]).show()
            more example are provided in the notebook
            "How to use Boltztra2 interface.ipynb".
        """

        props = ("Conductivity", "Seebeck", "Kappa", "Effective_mass",
                 "Power_Factor", "Carrier_conc", "Hall_carrier_conc_trace")
        props_lbl = ("Conductivity", "Seebeck", "$K_{el}$", "Effective mass",
                     "Power Factor", "Carrier concentration", "Hall carrier conc.")
        props_unit = (r"$(\mathrm{kS\,m^{-1}})$", r"($\mu$V/K)", r"$(W / (m \cdot K))$",
                      r"$(m_e)$", r"$( mW / (m\cdot K^2)$", r"$(cm^{-3})$", r"$(cm^{-3})$")

        props_short = [p[:len(prop_y)] for p in props]

        if prop_y not in props_short:
            raise BoltztrapError("prop_y not valid")

        if prop_x not in ('mu', 'doping', 'temp'):
            raise BoltztrapError("prop_x not valid")

        if prop_z not in ('doping', 'temp'):
            raise BoltztrapError("prop_z not valid")

        idx_prop = props_short.index(prop_y)

        leg_title = ""

        mu = self.bzt_transP.mu_r_eV

        if prop_z == 'doping' and prop_x == 'temp':
            p_array = eval("self.bzt_transP." + props[idx_prop] + '_' + prop_z)
        else:
            p_array = eval("self.bzt_transP." + props[idx_prop] + '_' + prop_x)

        if ax is None:
            fig = plt.figure(figsize=(10, 8))

        temps_all = self.bzt_transP.temp_r.tolist()
        if temps is None:
            temps = self.bzt_transP.temp_r.tolist()

        doping_all = self.bzt_transP.doping.tolist()
        if doping is None:
            doping = self.bzt_transP.doping.tolist()

        # special case of carrier and hall carrier concentration 2d arrays (temp,mu)
        if idx_prop in [5, 6]:
            if prop_z == 'temp' and prop_x == 'mu':
                for temp in temps:
                    ti = temps_all.index(temp)
                    prop_out = p_array[ti]  if idx_prop == 6 else np.abs(p_array[ti])
                    plt.semilogy(mu, prop_out, label=str(temp) + ' K')

                plt.xlabel(r"$\mu$ (eV)", fontsize=30)
                plt.xlim(xlim)
            else:
                raise BoltztrapError("only prop_x=mu and prop_z=temp are available for c.c. and Hall c.c.!")

        elif prop_z == 'temp' and prop_x == 'mu':
            for temp in temps:
                ti = temps_all.index(temp)
                prop_out = np.linalg.eigh(p_array[ti])[0]
                if output == 'avg_eigs':
                    plt.plot(mu, prop_out.mean(axis=1), label=str(temp) + ' K')
                elif output == 'eigs':
                    for i in range(3):
                        plt.plot(mu, prop_out[:, i],
                                 label='eig ' + str(i) + ' ' + str(temp) + ' K')

            plt.xlabel(r"$\mu$ (eV)", fontsize=30)
            plt.xlim(xlim)

        elif prop_z == 'temp' and prop_x == 'doping':
            for temp in temps:
                ti = temps_all.index(temp)
                prop_out = np.linalg.eigh(p_array[dop_type][ti])[0]
                if output == 'avg_eigs':
                    plt.semilogx(doping_all, prop_out.mean(axis=1), 's-',
                                 label=str(temp) + ' K')
                elif output == 'eigs':
                    for i in range(3):
                        plt.plot(doping_all, prop_out[:, i], 's-',
                                 label='eig ' + str(i) + ' ' + str(temp) + ' K')
            plt.xlabel(r"Carrier conc. $cm^{-3}$", fontsize=30)
            leg_title = dop_type + "-type"

        elif prop_z == 'doping' and prop_x == 'temp':
            for dop in doping:
                di = doping_all.index(dop)
                prop_out = np.linalg.eigh(p_array[dop_type][:, di])[0]
                if output == 'avg_eigs':
                    plt.plot(temps_all, prop_out.mean(axis=1),
                             's-', label=str(dop) + ' $cm^{-3}$')
                elif output == 'eigs':
                    for i in range(3):
                        plt.plot(temps_all, prop_out[:, i], 's-',
                                 label='eig ' + str(i) + ' ' + str(dop) + ' $cm^{-3}$')

            plt.xlabel(r"Temperature (K)", fontsize=30)
            leg_title = dop_type + "-type"

        plt.ylabel(props_lbl[idx_prop] + ' ' + props_unit[idx_prop], fontsize=30)
        plt.xticks(fontsize=25)
        plt.yticks(fontsize=25)
        plt.legend(title=leg_title if leg_title != "" else "", fontsize=15)
        plt.tight_layout()
        plt.grid()
        return plt