r'''Plot moist adiabats.

        Adds saturated pseudo-adiabats (lines of constant equivalent potential
        temperature) to the plot. The default style of these lines is dashed
        blue lines with an alpha value of 0.5. These can be overridden using
        keyword arguments.

        Parameters
        ----------
        p : array_like, optional
            1-dimensional array of pressure values to be included in the moist
            adiabats. If not specified, they will be linearly distributed
            across the current plotted pressure range.
        thetaes : array_like, optional
            1-dimensional array of saturation equivalent potential temperature
            values for moist adiabats. By default these will be generated based
            on the current temperature limits.
        kwargs
            Other keyword arguments to pass to
            `matplotlib.collections.LineCollection`

        See Also
        --------
        plot_dry_adiabats
        `matplotlib.collections.LineCollection`
        `metpy.calc.moist_lapse`

def plot_moist_adiabats(self, p=None, thetaes=None, **kwargs):
        r'''Plot moist adiabats.

        Adds saturated pseudo-adiabats (lines of constant equivalent potential
        temperature) to the plot. The default style of these lines is dashed
        blue lines with an alpha value of 0.5. These can be overridden using
        keyword arguments.

        Parameters
        ----------
        p : array_like, optional
            1-dimensional array of pressure values to be included in the moist
            adiabats. If not specified, they will be linearly distributed
            across the current plotted pressure range.
        thetaes : array_like, optional
            1-dimensional array of saturation equivalent potential temperature
            values for moist adiabats. By default these will be generated based
            on the current temperature limits.
        kwargs
            Other keyword arguments to pass to
            `matplotlib.collections.LineCollection`

        See Also
        --------
        plot_dry_adiabats
        `matplotlib.collections.LineCollection`
        `metpy.calc.moist_lapse`
        '''
        for artist in self._moist_adiabats:
            artist.remove()
        self._moist_adiabats = []

        def dT_dp(y, p0):
            return calculate('Gammam', T=y, p=p0, RH=100., p_units='hPa',
                             T_units='degC')/(
                g0*calculate('rho', T=y, p=p0, p_units='hPa', T_units='degC',
                             RH=100.))*100.

        if thetaes is None:
            xmin, xmax = self.get_xlim()
            thetaes = np.concatenate((np.arange(xmin, 0, 5),
                                      np.arange(0, xmax + 51, 5)))
        # Get pressure levels based on ylims if necessary
        if p is None:
            p = np.linspace(self.get_ylim()[0], self.get_ylim()[1])

        cache_dir = user_cache_dir('atmos')
        if not os.path.isdir(cache_dir):
            os.mkdir(cache_dir)
        cache_filename = os.path.join(cache_dir, 'moist_adiabat_data.npz')
        request_str = 'p:{},\nthetaes:{}'.format(
            np.array_str(p), np.array_str(thetaes))
        t = None
        cached_data = None
        if os.path.isfile(cache_filename):
            cached_data = np.load(cache_filename)
            if request_str in cached_data.keys():
                t = cached_data[request_str]
        if t is None:
            # did not find cached data
            # Assemble into data for plotting
            thetaes_base = odeint(
                dT_dp, thetaes, np.array([1e3, p[0]], dtype=np.float64))[-1, :]
            result = odeint(dT_dp, thetaes_base, p)
            t = result.T
            data_to_cache = {}
            if cached_data is not None:
                data_to_cache.update(cached_data)
            data_to_cache[request_str] = t
            np.savez(cache_filename, **data_to_cache)
        linedata = [np.vstack((ti, p)).T for ti in t]

        # Add to plot
        kwargs.setdefault('clip_on', True)
        kwargs.setdefault('colors', '#166916')
        kwargs.setdefault('linestyles', '-')
        kwargs.setdefault('alpha', 1)
        kwargs.setdefault('linewidth', 0.5)
        kwargs.setdefault('zorder', 1.1)
        collection = LineCollection(linedata, **kwargs)
        self._moist_adiabats.append(collection)
        self.add_collection(collection)
        label_index = closest_val(240., p)
        T_label = t[:, label_index].flatten()
        for i in range(len(thetaes)):
            text = self.text(
                T_label[i], p[label_index],
                '{:.0f}'.format(thetaes[i]),
                fontsize=8, ha='left', va='center', rotation=-65,
                color='#166916', bbox={
                    'facecolor': 'w', 'edgecolor': 'w', 'alpha': 0,
                    }, zorder=1.2)
            text.set_clip_on(True)
            self._moist_adiabats.append(text)