<SYSTEM_TASK:>
Solve the following problem using Python, implementing the functions described below, one line at a time
<END_TASK>
<USER_TASK:>
Description:
 def density_hub(self, weather_df):
 r""" Calculates the density of air at hub height. The density is calculated using the method specified by the parameter `density_model`. Previous to the calculation of the density the temperature at hub height is calculated using the method specified by the parameter `temperature_model`. Parameters weather_df : pandas.DataFrame DataFrame with time series for temperature `temperature` in K, pressure `pressure` in Pa and/or density `density` in kg/m³, depending on the `density_model` used. The columns of the DataFrame are a MultiIndex where the first level contains the variable name (e.g. temperature) and the second level contains the height at which it applies (e.g. 10, if it was measured at a height of 10 m). See documentation of :func:`ModelChain.run_model` for an example on how to create the weather_df DataFrame. Returns ------- density_hub : pandas.Series or numpy.array Density of air in kg/m³ at hub height. Notes ----- If `weather_df` contains data at different heights the data closest to the hub height are used. If `interpolation_extrapolation` is used to calculate the density at hub height, the `weather_df` must contain at least two time series for density. """

        if self.density_model != 'interpolation_extrapolation':
            temperature_hub = self.temperature_hub(weather_df)

        # Calculation of density in kg/m³ at hub height
        if self.density_model == 'barometric':
            logging.debug('Calculating density using barometric height '
                          'equation.')
            closest_height = weather_df['pressure'].columns[
                min(range(len(weather_df['pressure'].columns)),
                    key=lambda i: abs(weather_df['pressure'].columns[i] -
                                      self.power_plant.hub_height))]
            density_hub = density.barometric(
                weather_df['pressure'][closest_height], closest_height,
                self.power_plant.hub_height, temperature_hub)
        elif self.density_model == 'ideal_gas':
            logging.debug('Calculating density using ideal gas equation.')
            closest_height = weather_df['pressure'].columns[
                min(range(len(weather_df['pressure'].columns)),
                    key=lambda i: abs(weather_df['pressure'].columns[i] -
                                      self.power_plant.hub_height))]
            density_hub = density.ideal_gas(
                weather_df['pressure'][closest_height], closest_height,
                self.power_plant.hub_height, temperature_hub)
        elif self.density_model == 'interpolation_extrapolation':
            logging.debug('Calculating density using linear inter- or '
                          'extrapolation.')
            density_hub = tools.linear_interpolation_extrapolation(
                weather_df['density'], self.power_plant.hub_height)
        else:
            raise ValueError("'{0}' is an invalid value. ".format(
                             self.density_model) + "`density_model` " +
                             "must be 'barometric', 'ideal_gas' or " +
                             "'interpolation_extrapolation'.")
        return density_hub