def hourly_features_query(table_name='%(table_name)s', work_day={'begin': 9,
    'end': 17}, early_peak={'begin': 3, 'end': 5}, late_peak={'begin': 10,
    'end': 12}):
    """
    Create hourly features which are part of the final feature set.
    For outgoing and incoming events separately, the percentages of
    number of events (or total duration) happening during several
    predefined periods (input as dictionary with begin and end keys) are being
    calculated. There are three periods:
    workday (wd): Defaults to 9 am to 5 pm. General working hours.
    early peak (ep): Defaults to 3 am to 5 am. Tries to catch blue collar
                     or rural activity.
    late peak (lp): Defaults to 10 am to 12 pm. Tries to catch late
                    risers and white collar activity.
    All these features are bound between 0 and 1.

    Inputs
    ------
    table_name : name of the table the query is supposed to run on,
                 defaulting to '%(table_name)s', i.e. no substitution

    Output
    ------
    Partial final features dataframe which holds features
    calculated on the different time periods during the day.
    """
    query = """
        SELECT
          antenna_id,
          -- og work ratios (workday over whole day)
          SUM(IF(hour BETWEEN %(wd_begin)s AND %(wd_end)s, og_calls, NULL))
           /SUM(og_calls) as og_calls_work_ratio,
          SUM(IF(hour BETWEEN %(wd_begin)s AND %(wd_end)s, og_sms, NULL))
           /SUM(og_sms) as og_sms_work_ratio,
          SUM(IF(hour BETWEEN %(wd_begin)s AND %(wd_end)s, og_vol, NULL))
           /SUM(og_vol) as og_vol_work_ratio,
          -- ic work ratios (workday over whole day)
          SUM(IF(hour BETWEEN %(wd_begin)s AND %(wd_end)s, ic_calls, NULL))
           /SUM(ic_calls) as ic_calls_work_ratio,
          SUM(IF(hour BETWEEN %(wd_begin)s AND %(wd_end)s, ic_sms, NULL))
           /SUM(ic_sms) as ic_sms_work_ratio,
          SUM(IF(hour BETWEEN %(wd_begin)s AND %(wd_end)s, ic_vol, NULL))
           /SUM(ic_vol) as ic_vol_work_ratio,
          -- og peak ratios (early & late peak respectively over whole day)
          SUM(IF(hour BETWEEN %(ep_begin)s AND %(ep_end)s, og_calls,
           NULL))/
            SUM(IF(hour BETWEEN %(lp_begin)s AND %(lp_end)s, og_calls,
             NULL)) as og_calls_peak_ratio,
          SUM(IF(hour BETWEEN %(ep_begin)s AND %(ep_end)s, og_sms, NULL))/
            SUM(IF(hour BETWEEN %(lp_begin)s AND %(lp_end)s, og_sms, NULL))
            as og_sms_peak_ratio,
          SUM(IF(hour BETWEEN %(ep_begin)s AND %(ep_end)s, og_vol, NULL))/
            SUM(IF(hour BETWEEN %(lp_begin)s AND %(lp_end)s, og_vol, NULL))
             as og_vol_peak_ratio,
          -- ic peak ratios (early & late peak respectively over whole day)
          SUM(IF(hour BETWEEN %(ep_begin)s AND %(ep_end)s, ic_calls,
           NULL))/
            SUM(IF(hour BETWEEN %(lp_begin)s AND %(lp_end)s, ic_calls,
             NULL)) as ic_calls_peak_ratio,
          SUM(IF(hour BETWEEN %(ep_begin)s AND %(ep_end)s, ic_sms, NULL))/
            SUM(IF(hour BETWEEN %(lp_begin)s AND %(lp_end)s, ic_sms,
             NULL)) as ic_sms_peak_ratio,
          SUM(IF(hour BETWEEN %(ep_begin)s AND %(ep_end)s, ic_vol, NULL))/
            SUM(IF(hour BETWEEN %(lp_begin)s AND %(lp_end)s, ic_vol,
             NULL)) as ic_vol_peak_ratio

        FROM %(table_name)s
        GROUP BY antenna_id
    """
    return query % {'table_name': table_name, 'wd_begin': work_day['begin'],
        'wd_end': work_day['end'], 'ep_begin': early_peak['begin'],
        'ep_end': early_peak['end'], 'lp_begin': late_peak['begin'],
        'lp_end': late_peak['end']}
