'Create an event frame for this report
@param start: the start date/time (string, date or datetime)
@param end: the end date/time (string, date or datetime)
@param slots: the slot length (string)
@return: the event frame'

def _event_frame(self, start=None, end=None, slots=None):

    resource = self.resource
    rfields = self.rfields
    STANDARD_SLOT = '1    day'
    now = tp_tzsafe(datetime.datetime.utcnow())
    dtparse = self.dtparse
    start_dt = end_dt = None
    if start:
        if isinstance(start, basestring):
            start_dt = dtparse(start, start=now)
        elif isinstance(start, datetime.datetime):
            start_dt = tp_tzsafe(start)
        else:
            start_dt = tp_tzsafe(datetime.datetime.fromordinal(start.toordinal()))
    if end:
        if isinstance(end, basestring):
            relative_to = (start_dt if start_dt else now)
            end_dt = dtparse(end, start=relative_to)
        elif isinstance(end, datetime.datetime):
            end_dt = tp_tzsafe(end)
        else:
            end_dt = tp_tzsafe(datetime.datetime.fromordinal(end.toordinal()))
    if (not end_dt):
        end_dt = now
    event_start = rfields['event_start']
    if ((not start_dt) and event_start and event_start.field):
        query = (FS(event_start.selector) != None)
        resource.add_filter(query)
        rows = resource.select([event_start.selector], limit=1, orderby=event_start.field, as_rows=True)
        resource.rfilter.filters.pop()
        resource.rfilter.query = None
        if rows:
            first_event = rows.first()[event_start.colname]
            if isinstance(first_event, datetime.date):
                first_event = tp_tzsafe(datetime.datetime.fromordinal(first_event.toordinal()))
            start_dt = first_event
    event_end = rfields['event_end']
    if ((not start_dt) and event_end and event_end.field):
        query = (FS(event_end.selector) != None)
        resource.add_filter(query)
        rows = resource.select([event_end.selector], limit=1, orderby=event_end.field, as_rows=True)
        resource.rfilter.filters.pop()
        resource.rfilter.query = None
        if rows:
            last_event = rows.first()[event_end.colname]
            if isinstance(last_event, datetime.date):
                last_event = tp_tzsafe(datetime.datetime.fromordinal(last_event.toordinal()))
            start_dt = dtparse(('-%s' % STANDARD_SLOT), start=last_event)
    if (not start_dt):
        if (not slots):
            slots = STANDARD_SLOT
        try:
            start_dt = dtparse(('-%s' % slots), start=end_dt)
        except (SyntaxError, ValueError):
            slots = STANDARD_SLOT
            start_dt = dtparse(('-%s' % slots), start=end_dt)
    if (not slots):
        seconds = abs((end_dt - start_dt)).total_seconds()
        day = 86400
        if (seconds < day):
            slots = 'hours'
        elif (seconds < (3 * day)):
            slots = '6    hours'
        elif (seconds < (28 * day)):
            slots = 'days'
        elif (seconds < (90 * day)):
            slots = 'weeks'
        elif (seconds < (730 * day)):
            slots = 'months'
        elif (seconds < (2190 * day)):
            slots = '3    months'
        else:
            slots = 'years'
    ef = S3TimeSeriesEventFrame(start_dt, end_dt, slots)
    return ef
