<SYSTEM_TASK:>
Solve the following problem using Python, implementing the functions described below, one line at a time
<END_TASK>
<USER_TASK:>
Description:
 def mv_voltage_deviation(network, voltage_levels='mv_lv'):
 """ Checks for voltage stability issues in MV grid. Parameters network : :class:`~.grid.network.Network` voltage_levels : :obj:`str` Specifies which allowed voltage deviations to use. Possible options are: * 'mv_lv' This is the default. The allowed voltage deviation for nodes in the MV grid is the same as for nodes in the LV grid. Further load and feed-in case are not distinguished. * 'mv' Use this to handle allowed voltage deviations in the MV and LV grid differently. Here, load and feed-in case are differentiated as well. Returns ------- :obj:`dict` Dictionary with :class:`~.grid.grids.MVGrid` as key and a :pandas:`pandas.DataFrame<dataframe>` with its critical nodes, sorted descending by voltage deviation, as value. Index of the dataframe are all nodes (of type :class:`~.grid.components.Generator`, :class:`~.grid.components.Load`, etc.) with over-voltage issues. Columns are 'v_mag_pu' containing the maximum voltage deviation as float and 'time_index' containing the corresponding time step the over-voltage occured in as :pandas:`pandas.Timestamp<timestamp>`. Notes ----- Over-voltage is determined based on allowed voltage deviations defined in the config file 'config_grid_expansion' in section 'grid_expansion_allowed_voltage_deviations'. """


    crit_nodes = {}

    v_dev_allowed_per_case = {}
    v_dev_allowed_per_case['feedin_case_lower'] = 0.9
    v_dev_allowed_per_case['load_case_upper'] = 1.1
    offset = network.config[
        'grid_expansion_allowed_voltage_deviations']['hv_mv_trafo_offset']
    control_deviation = network.config[
        'grid_expansion_allowed_voltage_deviations'][
        'hv_mv_trafo_control_deviation']
    if voltage_levels == 'mv_lv':
        v_dev_allowed_per_case['feedin_case_upper'] = \
            1 + offset + control_deviation + network.config[
                'grid_expansion_allowed_voltage_deviations'][
                'mv_lv_feedin_case_max_v_deviation']
        v_dev_allowed_per_case['load_case_lower'] = \
            1 + offset - control_deviation - network.config[
                'grid_expansion_allowed_voltage_deviations'][
                'mv_lv_load_case_max_v_deviation']
    elif voltage_levels == 'mv':
        v_dev_allowed_per_case['feedin_case_upper'] = \
            1 + offset + control_deviation + network.config[
                'grid_expansion_allowed_voltage_deviations'][
                'mv_feedin_case_max_v_deviation']
        v_dev_allowed_per_case['load_case_lower'] = \
            1 + offset - control_deviation - network.config[
                'grid_expansion_allowed_voltage_deviations'][
                'mv_load_case_max_v_deviation']
    else:
        raise ValueError(
            'Specified mode {} is not a valid option.'.format(voltage_levels))
    # maximum allowed apparent power of station in each time step
    v_dev_allowed_upper = \
        network.timeseries.timesteps_load_feedin_case.case.apply(
            lambda _: v_dev_allowed_per_case['{}_upper'.format(_)])
    v_dev_allowed_lower = \
        network.timeseries.timesteps_load_feedin_case.case.apply(
            lambda _: v_dev_allowed_per_case['{}_lower'.format(_)])

    nodes = network.mv_grid.graph.nodes()

    crit_nodes_grid = _voltage_deviation(
        network, nodes, v_dev_allowed_upper, v_dev_allowed_lower,
        voltage_level='mv')

    if not crit_nodes_grid.empty:
        crit_nodes[network.mv_grid] = crit_nodes_grid.sort_values(
            by=['v_mag_pu'], ascending=False)
        logger.debug(
            '==> {} node(s) in MV grid has/have voltage issues.'.format(
                crit_nodes[network.mv_grid].shape[0]))
    else:
        logger.debug('==> No voltage issues in MV grid.')

    return crit_nodes