<SYSTEM_TASK:>
Solve the following problem using Python, implementing the functions described below, one line at a time
<END_TASK>
<USER_TASK:>
Description:
 def logarithmic_profile(wind_speed, wind_speed_height, hub_height, roughness_length, obstacle_height=0.0):
 r""" Calculates the wind speed at hub height using a logarithmic wind profile. The logarithmic height equation is used. There is the possibility of including the height of the surrounding obstacles in the calculation. This function is carried out when the parameter `wind_speed_model` of an instance of the :class:`~.modelchain.ModelChain` class is 'logarithmic'. Parameters wind_speed : pandas.Series or numpy.array Wind speed time series. wind_speed_height : float Height for which the parameter `wind_speed` applies. hub_height : float Hub height of wind turbine. roughness_length : pandas.Series or numpy.array or float Roughness length. obstacle_height : float Height of obstacles in the surrounding area of the wind turbine. Set `obstacle_height` to zero for wide spread obstacles. Default: 0. Returns ------- pandas.Series or numpy.array Wind speed at hub height. Data type depends on type of `wind_speed`. Notes ----- The following equation is used [1]_, [2]_, [3]_: .. math:: v_{wind,hub}=v_{wind,data}\cdot \frac{\ln\left(\frac{h_{hub}-d}{z_{0}}\right)}{\ln\left( \frac{h_{data}-d}{z_{0}}\right)} with: v: wind speed, h: height, :math:`z_{0}`: roughness length, d: boundary layer offset (estimated by d = 0.7 * `obstacle_height`) For d = 0 it results in the following equation [2]_, [3]_: .. math:: v_{wind,hub}=v_{wind,data}\cdot\frac{\ln\left(\frac{h_{hub}} {z_{0}}\right)}{\ln\left(\frac{h_{data}}{z_{0}}\right)} :math:`h_{data}` is the height at which the wind speed :math:`v_{wind,data}` is measured and :math:`v_{wind,hub}` is the wind speed at hub height :math:`h_{hub}` of the wind turbine. Parameters `wind_speed_height`, `roughness_length`, `hub_height` and `obstacle_height` have to be of the same unit. References .. [1] Quaschning V.: "Regenerative Energiesysteme". München, Hanser Verlag, 2011, p. 278 .. [2] Gasch, R., Twele, J.: "Windkraftanlagen". 6. Auflage, Wiesbaden, Vieweg + Teubner, 2010, p. 129 .. [3] Hau, E.: "Windkraftanlagen - Grundlagen, Technik, Einsatz, Wirtschaftlichkeit". 4. Auflage, Springer-Verlag, 2008, p. 515 """

    if 0.7 * obstacle_height > wind_speed_height:
        raise ValueError("To take an obstacle height of {0} m ".format(
                         obstacle_height) + "into consideration, wind " +
                         "speed data of a greater height is needed.")
    # Return np.array if wind_speed is np.array
    if (isinstance(wind_speed, np.ndarray) and
            isinstance(roughness_length, pd.Series)):
        roughness_length = np.array(roughness_length)

    return (wind_speed * np.log((hub_height - 0.7 * obstacle_height) /
                                roughness_length) /
            np.log((wind_speed_height - 0.7 * obstacle_height) /
                   roughness_length))