def trajectories(frame, data, f, parameters=None, call_num=None):
    #This can only be run on a linked trajectory
    method_key = get_method_key('trajectories', call_num=call_num)
    x_col_name = parameters[method_key]['x_column']
    y_col_name = parameters[method_key]['y_column']

    #In this case subset_df is only used to get the particle_ids and colours of trajectories.
    subset_df = get_class_subset(data, f, parameters, method=method_key)
    particle_ids = subset_df['particle'].values

    colours = colour_array(subset_df, f, parameters, method=method_key)
    thickness = get_param_val(parameters[method_key]['thickness'])
    traj_length = get_param_val(parameters[method_key]['traj_length'])

    if (f-traj_length) < 0:
        traj_length = f

    df = data.df.sort_index()
    df.index.name='frame'
    df['frame'] = df.index
    df2 = df.loc[f-traj_length:f]

    df3 = df2.set_index(['particle','frame']).sort_index(level='particle')

    for index, particle in enumerate(particle_ids):
        traj_pts = df3[[x_col_name,y_col_name]].loc[particle]
        traj_pts = np.array(traj_pts.values, np.int32).reshape((-1,1,2))
        frame = cv2.polylines(frame,[traj_pts],False,colours[index],thickness)
    return frame
def circles(frame, data, f, parameters=None, call_num=None):
    '''
    Function draws circles on an image at x,y locations. If data.df['r'] exists
    circles have this radius, else 'r' col is created with value set from annotation
    sub dictionary.

    :param frame: frame to be annotated should be 3 colour channel
    :param data: datastore with particle information
    :param f: frame number
    :param parameters: annotation sub dictionary

    :return: annotated frame
    '''
    method_key = get_method_key('circles', call_num=call_num)
    if 'r' not in list(data.df.columns):
        data.add_particle_property('r', get_param_val(parameters[method_key]['radius']))
    thickness = get_param_val(parameters[method_key]['thickness'])

    subset_df = get_class_subset(data, f, parameters, method=method_key)
    circles = subset_df[['x', 'y', 'r']].values
    colours = colour_array(subset_df, f, parameters, method=method_key)
    for i, circle in enumerate(circles):
        try:
            frame = cv2.circle(frame, (int(circle[0]), int(circle[1])), int(circle[2]), colours[i], thickness)
        except:
            print('Failed plotting circle, check data is valid')
    return frame
def contours(frame, data, f, parameters=None, call_num=None):
    method_key = get_method_key('contours', call_num=call_num)
    thickness = get_param_val(parameters[method_key]['thickness'])
    subset_df = get_class_subset(data, f, parameters, method=method_key)
    contour_pts = subset_df[['contours']].values
    colours = colour_array(subset_df, f, parameters, method=method_key)

    for index, contour in enumerate(contour_pts):
       frame = _draw_contours(frame, contour, col=colours[index],
                                       thickness=thickness)
    return frame
def boxes(frame, data, f, parameters=None, call_num=None):
    method_key = get_method_key('boxes', call_num=call_num)
    thickness = get_param_val(parameters[method_key]['thickness'])
    subset_df = get_class_subset(data, f, parameters, method=method_key)
    box_pts = subset_df[['box']].values

    colours = colour_array(subset_df, f, parameters, method=method_key)
    sz = np.shape(frame)
    for index, box in enumerate(box_pts):
        if contour_inside_img(sz, box):
            frame = _draw_contours(frame, box, col=colours[index],
                                       thickness=get_param_val(parameters[method_key]['thickness']))
    return frame
def networks(frame, data, f, parameters=None, call_num=None):
    method_key = get_method_key('networks', call_num=call_num)
    df = get_class_subset(data, f, parameters, method=method_key)
    df = df.set_index('particle')
    particle_ids = df.index.values
    colours = colour_array(df, f, parameters, method=method_key)
    thickness = get_param_val(parameters[method_key]['thickness'])

    for index, particle in enumerate(particle_ids):
        pt = df.loc[particle, ['x', 'y']].values
        pt1 = (int(pt[0]), int(pt[1]))
        neighbour_ids = df.loc[particle, 'neighbours']
        for index2, neighbour in enumerate(neighbour_ids):
            pt = df.loc[neighbour, ['x','y']].values
            pt2 = (int(pt[0]), int(pt[1]))
            frame = cv2.line(frame,pt1, pt2, colours[index], thickness, lineType=cv2.LINE_AA)
    return frame
def vectors(frame, data, f, parameters=None, call_num=None):
    method_key = get_method_key('vectors', call_num=call_num)
    dx = parameters[method_key]['dx_column']
    dy = parameters[method_key]['dy_column']

    vectors = data.get_info(f, ['x', 'y',dx, dy])

    thickness = get_param_val(parameters[method_key]['thickness'])
    line_type = 8
    tipLength = 0.01*get_param_val(parameters[method_key]['tip_length'])
    vector_scale = 0.01*get_param_val(parameters[method_key]['vector_scale'])

    colours = colour_array(data.df, f, parameters, method=method_key)

    for i, vector in enumerate(vectors):
        frame = cv2.arrowedLine(frame, (int(vector[0]), int(vector[1])),
                                (int(vector[0]+vector[2]*vector_scale),int(vector[1]+vector[3]*vector_scale)),
                                color=colours[i], thickness=thickness,line_type=line_type,shift=0,tipLength=tipLength)
    return frame