def eval(gt, input_file, args):
    # Ground Truth
    reader_gt = trajnetplusplustools.Reader(gt, scene_type='paths')
    scenes_gt = [s for _, s in reader_gt.scenes()]
    scenes_id_gt = [s_id for s_id, _ in reader_gt.scenes()]

    # Scene Predictions
    reader_sub = trajnetplusplustools.Reader(input_file, scene_type='paths')
    scenes_sub = [s for _, s in reader_sub.scenes()]

    ## indexes is dictionary deciding which scenes are in which type
    indexes = {}
    for i in range(1, 5):
        indexes[i] = []
    ## sub-indexes
    sub_indexes = {}
    for i in range(1, 5):
        sub_indexes[i] = []
    for scene in reader_gt.scenes_by_id:
        tags = reader_gt.scenes_by_id[scene].tag
        main_tag = tags[0:1]
        sub_tags = tags[1]
        for ii in range(1, 5):
            if ii in main_tag:
                indexes[ii].append(scene)
            if ii in sub_tags:
                sub_indexes[ii].append(scene)

    # Evaluate
    evaluator = TrajnetEvaluator(reader_gt, scenes_gt, scenes_id_gt,
                                 scenes_sub, indexes, sub_indexes, args)
    evaluator.aggregate('kf', args.disable_collision)

    return evaluator.result()
def prepare_data(path, subset='/train/', sample=1.0, goals=True):
    """ Prepares the train/val scenes and corresponding goals 
    
    Parameters
    ----------
    subset: String ['/train/', '/val/']
        Determines the subset of data to be processed
    sample: Float (0.0, 1.0]
        Determines the ratio of data to be sampled
    goals: Bool
        If true, the goals of each track are extracted
        The corresponding goal file must be present in the 'goal_files' folder
        The name of the goal file must be the same as the name of the training file

    Returns
    -------
    all_scenes: List
        List of all processed scenes
    all_goals: Dictionary
        Dictionary of goals corresponding to each dataset file.
        None if 'goals' argument is False.
    Flag: Bool
        True if the corresponding folder exists else False.
    """

    ## Check if folder exists
    if not os.path.isdir(path + subset):
        if 'train' in subset:
            print(path + subset)
            print("Train folder does NOT exist")
            exit()
        if 'val' in subset:
            print("Validation folder does NOT exist")
            return None, None, False

    ## read goal files
    all_goals = {}
    all_scenes = []

    ## List file names
    files = [f.split('.')[-2] for f in os.listdir(path + subset) if f.endswith('.ndjson')]
    ## Iterate over file names
    for file in files:
        reader = trajnetplusplustools.Reader(path + subset + file + '.ndjson', scene_type='paths')
        ## Necessary modification of train scene to add filename
        scene = [(file, s_id, s) for s_id, s in reader.scenes(sample=sample)]
        if goals:
            goal_dict = pickle.load(open('goal_files/' + subset + file +'.pkl', "rb"))
            ## Get goals corresponding to train scene
            all_goals[file] = {s_id: [goal_dict[path[0].pedestrian] for path in s] for _, s_id, s in scene}
        all_scenes += scene

    if goals:
        return all_scenes, all_goals, True
    return all_scenes, None, True
def collision_test(list_sub, name, args):
    """ Simple Collision Test """
    submit_datasets = [args.path + name + '/' + f for f in list_sub if 'collision_test.ndjson' in f]
    if len(submit_datasets):
        # Scene Prediction
        reader_sub = trajnetplusplustools.Reader(submit_datasets[0], scene_type='paths')
        scenes_sub = [s for _, s in reader_sub.scenes()]

        if trajnetplusplustools.metrics.collision(scenes_sub[0][0], scenes_sub[0][1], n_predictions=args.pred_length):
            return "Fail"
        return "Pass"

    return "NA"
def main():
    device = torch.device(
        'cuda') if torch.cuda.is_available() else torch.device('cpu')

    scenes = list(
        trajnetplusplustools.Reader('data/train/biwi_hotel.ndjson').scenes(
            limit=1))

    pool = trajnetbaselines.lstm.Pooling(type_='social')
    model = trajnetbaselines.lstm.LSTM(pool=pool)
    trainer = trajnetbaselines.lstm.trainer.Trainer(model, device=device)
    with torch.autograd.profiler.profile(
            use_cuda=torch.cuda.is_available()) as prof:
        trainer.train(scenes, epoch=0)
    prof.export_chrome_trace('profile_trace.json')
Example #5
0
def eval(input_file, dest_file, simulator, params, type_ids, args):
    print('dataset', input_file)

    reader = trajnetplusplustools.Reader(input_file, scene_type='paths')
    scenes = [s for _, s in reader.scenes()]

    ## Filter scenes according to category type
    # if type_ids is None:
    #     trajectory_type = 3
    #     interaction_type = 2
    #     type_ids = [scene_id for scene_id in reader.scenes_by_id \
    #                 if interaction_type in reader.scenes_by_id[scene_id].tag[1]]

    # scenes = [scenes[type_id] for type_id in type_ids]

    ## If final destination of pedestrian provided
    dest_dict = None
    if dest_file is not None:
        dest_dict = pickle.load(open(dest_file, "rb"))

    evaluator = Evaluator(scenes, dest_dict, params, args)

    ## Evaluate all
    if simulator == 'all':
        for dest_type in ['interp']:
            evaluator.aggregate('orca' + dest_type, orca.predict, dest_type)
            evaluator.aggregate('sf' + dest_type, socialforce.predict,
                                dest_type)
        evaluator.aggregate('kf', kalman.predict)

    # ORCA only
    elif simulator == 'orca':
        for dest_type in ['interp']:
            evaluator.aggregate('orca' + dest_type, orca.predict, dest_type)

    # Social Force only
    elif simulator == 'sf':
        for dest_type in ['interp']:
            evaluator.aggregate('sf' + dest_type, socialforce.predict,
                                dest_type)

    # Kalman only
    elif simulator == 'kf':
        evaluator.aggregate('kf', kalman.predict)

    return evaluator.result()
def main(args=None):
    ## List of .json file inside the args.path (waiting to be predicted by the testing model)
    datasets = sorted([f.split('.')[-2] for f in os.listdir(args.path.replace('_pred', '')) if not f.startswith('.') and f.endswith('.ndjson')])
    all_goals = {}
    seq_length = args.obs_length + args.pred_length

    ## Handcrafted Baselines (if included)
    if args.kf:
        args.output.append('/kf.pkl')
    if args.sf:
        args.output.append('/sf.pkl')
        args.output.append('/sf_opt.pkl')
    if args.orca:
        args.output.append('/orca.pkl')
        args.output.append('/orca_opt.pkl')

    ## Extract Model names from arguments and create its own folder in 'test_pred' for storing predictions
    ## WARNING: If Model predictions already exist from previous run, this process SKIPS WRITING
    for model in args.output:
        model_name = model.split('/')[-1].replace('.pkl', '')
        model_name = model_name + '_modes' + str(args.modes)

        ## Check if model predictions already exist
        if not os.path.exists(args.path):
            os.makedirs(args.path)
        if not os.path.exists(args.path + model_name):
            os.makedirs(args.path + model_name)
        else:
            print('Predictions corresponding to {} already exist.'.format(model_name))
            print('Loading the saved predictions')
            continue

        ## Start writing predictions in dataset/test_pred
        for dataset in datasets:
            # Model's name
            name = dataset.replace(args.path.replace('_pred', '') + 'test/', '') + '.ndjson'
            print('NAME: ', name)

            # Read Scenes from 'test' folder
            reader = trajnetplusplustools.Reader(args.path.replace('_pred', '') + dataset + '.ndjson', scene_type='paths')
            ## Necessary modification of train scene to add filename (for goals)
            scenes = [(dataset, s_id, s) for s_id, s in reader.scenes()]
            ## Consider goals
            ## Goal file must be present in 'goal_files/test_private' folder 
            ## Goal file must have the same name as corresponding test file 
            if args.goals:
                goal_dict = pickle.load(open('goal_files/test_private/' + dataset +'.pkl', "rb"))
                all_goals[dataset] = {s_id: [goal_dict[path[0].pedestrian] for path in s] for _, s_id, s in scenes}

            # Loading the APPROPRIATE model
            ## Keep Adding Different Model Architectures to this List
            print("Model Name: ", model_name)
            if model_name == 'kf':
                print("Kalman")
                predictor = trajnetbaselines.classical.kalman.predict
            elif model_name in {'sf', 'sf_opt'}:
                print("Social Force")
                predictor = trajnetbaselines.classical.socialforce.predict
            elif model_name in {'orca', 'orca_opt'}:
                print("ORCA")
                predictor = trajnetbaselines.classical.orca.predict
            elif 'sgan' in model_name:
                print("SGAN")
                predictor = trajnetbaselines.sgan.SGANPredictor.load(model)
                device = torch.device('cpu')
                predictor.model.to(device)
            elif 'lstm' in model_name:
                print("LSTM")
                predictor = trajnetbaselines.lstm.LSTMPredictor.load(model)
                device = torch.device('cpu')
                predictor.model.to(device)
            else:
                print("Model Architecture not recognized")
                raise ValueError

            # Get the model prediction and write them in corresponding test_pred file
            # VERY IMPORTANT: Prediction Format
            # The predictor function should output a dictionary. The keys of the dictionary should correspond to the prediction modes.
            # ie. predictions[0] corresponds to the first mode. predictions[m] corresponds to the m^th mode.... Multimodal predictions!
            # Each modal prediction comprises of primary prediction and neighbour (surrrounding) predictions i.e. predictions[m] = [primary_prediction, neigh_predictions]
            # Note: Return [primary_prediction, []] if model does not provide neighbour predictions
            # Shape of primary_prediction: Tensor of Shape (Prediction length, 2)
            # Shape of Neighbour_prediction: Tensor of Shape (Prediction length, n_tracks - 1, 2).
            # (See LSTMPredictor.py for more details)
            with open(args.path + '{}/{}'.format(model_name, name), "a") as myfile:
                for filename, scene_id, paths in scenes:
                    ## Extract 1) first_frame, 2) frame_diff 3) ped_ids for writing predictions
                    observed_path = paths[0]
                    frame_diff = observed_path[1].frame - observed_path[0].frame
                    first_frame = observed_path[args.obs_length-1].frame + frame_diff
                    ped_id = observed_path[0].pedestrian
                    ped_id_ = []
                    for j, _ in enumerate(paths[1:]): ## Only need neighbour ids
                        ped_id_.append(paths[j+1][0].pedestrian)

                    ## For each scene, get predictions
                    if model_name == 'sf_opt':
                        predictions = predictor(paths, sf_params=[0.5, 5.0, 0.3], n_predict=args.pred_length, obs_length=args.obs_length) ## optimal sf_params (no collision constraint) [0.5, 1.0, 0.1],
                    elif model_name == 'orca_opt':
                        predictions = predictor(paths, orca_params=[0.4, 1.0, 0.3], n_predict=args.pred_length, obs_length=args.obs_length) ## optimal orca_params (no collision constraint) [0.25, 1.0, 0.3]
                    elif model_name in {'sf', 'orca', 'kf'}:
                        predictions = predictor(paths, n_predict=args.pred_length, obs_length=args.obs_length, args=args)
                    else:
                        goals = get_goals(paths, all_goals, filename, scene_id) ## Zeros if no goals utilized
                        predictions = predictor(paths, goals, n_predict=args.pred_length, obs_length=args.obs_length, modes=args.modes, args=args)

                    ## Write SceneRow
                    scenerow = trajnetplusplustools.SceneRow(scene_id, ped_id, observed_path[0].frame, 
                                                             observed_path[0].frame + seq_length - 1, 2.5, 0)
                    myfile.write(trajnetplusplustools.writers.trajnet(scenerow))
                    myfile.write('\n')

                    for m in range(len(predictions)):
                        prediction, neigh_predictions = predictions[m]
                        ## Write Primary
                        for i in range(len(prediction)):
                            track = trajnetplusplustools.TrackRow(first_frame + i * frame_diff, ped_id,
                                                                  prediction[i, 0].item(), prediction[i, 1].item(), m, scene_id)
                            myfile.write(trajnetplusplustools.writers.trajnet(track))
                            myfile.write('\n')

                        ## Write Neighbours (if non-empty)
                        if len(neigh_predictions):
                            for n in range(neigh_predictions.shape[1]):
                                neigh = neigh_predictions[:, n]
                                for j in range(len(neigh)):
                                    track = trajnetplusplustools.TrackRow(first_frame + j * frame_diff, ped_id_[n],
                                                                          neigh[j, 0].item(), neigh[j, 1].item(), m, scene_id)
                                    myfile.write(trajnetplusplustools.writers.trajnet(track))
                                    myfile.write('\n')
        print('')
Example #7
0
def main():
    parser = argparse.ArgumentParser()
    parser.add_argument('--path',
                        default='trajdata',
                        help='directory of data to test')
    parser.add_argument('--output',
                        required=True,
                        nargs='+',
                        help='relative path to saved model')
    parser.add_argument('--obs_length',
                        default=9,
                        type=int,
                        help='observation length')
    parser.add_argument('--pred_length',
                        default=12,
                        type=int,
                        help='prediction length')
    parser.add_argument('--disable-write',
                        action='store_true',
                        help='disable writing new files')
    parser.add_argument('--disable-collision',
                        action='store_true',
                        help='disable collision metrics')
    parser.add_argument('--labels',
                        required=False,
                        nargs='+',
                        help='labels of models')
    parser.add_argument('--normalize_scene',
                        action='store_true',
                        help='augment scenes')
    parser.add_argument('--unimodal',
                        action='store_true',
                        help='provide unimodal evaluation')
    parser.add_argument('--topk',
                        action='store_true',
                        help='provide topk evaluation')
    parser.add_argument('--multimodal',
                        action='store_true',
                        help='provide multimodal nll evaluation')
    parser.add_argument('--modes',
                        default=1,
                        type=int,
                        help='number of modes to predict')
    parser.add_argument('--scene_type',
                        default=0,
                        type=int,
                        choices=(0, 1, 2, 3, 4),
                        help='type of scene to evaluate')
    parser.add_argument('--thresh',
                        default=0.0,
                        type=float,
                        help='noise thresh')
    parser.add_argument('--ped_type',
                        default='primary',
                        help='type of ped to add noise to')

    args = parser.parse_args()

    scipy.seterr('ignore')

    ## Path to the data folder name to predict
    args.path = 'DATA_BLOCK/' + args.path + '/'

    ## Test_pred: Folders for saving model predictions
    args.path = args.path + 'test_pred/'

    if (not args.unimodal) and (not args.topk) and (not args.multimodal):
        args.unimodal = True  # Compute unimodal metrics by default

    if args.topk:
        args.modes = 3

    if args.multimodal:
        args.modes = 20

    enable_col1 = True

    ## drop pedestrians that appear post observation
    def drop_post_obs(ground_truth, obs_length):
        obs_end_frame = ground_truth[0][obs_length].frame
        ground_truth = [
            track for track in ground_truth if track[0].frame < obs_end_frame
        ]
        return ground_truth

    ## Writes to Test_pred
    ## Does this overwrite existing predictions? No. ###
    datasets = sorted([
        f.split('.')[-2] for f in os.listdir(args.path.replace('_pred', ''))
        if not f.startswith('.') and f.endswith('.ndjson')
    ])

    ## Model names are passed as arguments
    for model in args.output:
        model_name = model.split('/')[-1].replace('.pkl', '')

        # Loading the appropriate model (functionality only for SGAN and LSTM)
        print("Model Name: ", model_name)
        if 'sgan' in model_name:
            predictor = trajnetbaselines.sgan.SGANPredictor.load(model)
            goal_flag = predictor.model.generator.goal_flag
        elif 'vae' in model_name:
            predictor = trajnetbaselines.vae.VAEPredictor.load(model)
            goal_flag = predictor.model.goal_flag
        else:
            predictor = trajnetbaselines.lstm.LSTMPredictor.load(model)
            goal_flag = predictor.model.goal_flag

        # On CPU
        device = torch.device('cpu')
        predictor.model.to(device)

        total_scenes = 0
        average = 0
        final = 0
        gt_col = 0.
        pred_col = 0.
        neigh_scenes = 0
        topk_average = 0
        topk_final = 0
        all_goals = {}
        average_nll = 0

        ## Start writing in dataset/test_pred
        for dataset in datasets:
            # Model's name
            name = dataset.replace(
                args.path.replace('_pred', '') + 'test/', '')

            # Copy file from test into test/train_pred folder
            print('processing ' + name)
            if 'collision_test' in name:
                continue

            ## Filter for Scene Type
            reader_tag = trajnetplusplustools.Reader(
                args.path.replace('_pred', '_private') + dataset + '.ndjson',
                scene_type='tags')
            if args.scene_type != 0:
                filtered_scene_ids = [
                    s_id for s_id, tag, s in reader_tag.scenes()
                    if tag[0] == args.scene_type
                ]
            else:
                filtered_scene_ids = [
                    s_id for s_id, _, _ in reader_tag.scenes()
                ]

            # Read file from 'test'
            reader = trajnetplusplustools.Reader(
                args.path.replace('_pred', '') + dataset + '.ndjson',
                scene_type='paths')
            ## Necessary modification of train scene to add filename (for goals)
            scenes = [(dataset, s_id, s) for s_id, s in reader.scenes()
                      if s_id in filtered_scene_ids]

            ## Consider goals
            ## Goal file must be present in 'goal_files/test_private' folder
            ## Goal file must have the same name as corresponding test file
            if goal_flag:
                goal_dict = pickle.load(
                    open('goal_files/test_private/' + dataset + '.pkl', "rb"))
                all_goals[dataset] = {
                    s_id: [goal_dict[path[0].pedestrian] for path in s]
                    for _, s_id, s in scenes
                }

            ## Get Goals
            if goal_flag:
                scene_goals = [
                    np.array(all_goals[filename][scene_id])
                    for filename, scene_id, _ in scenes
                ]
            else:
                scene_goals = [
                    np.zeros((len(paths), 2)) for _, scene_id, paths in scenes
                ]

            print("Getting Predictions")
            scenes = tqdm(scenes)
            ## Get all predictions in parallel. Faster!
            pred_list = Parallel(n_jobs=12)(
                delayed(process_scene)(predictor, model_name, paths,
                                       scene_goal, args)
                for (_, _, paths), scene_goal in zip(scenes, scene_goals))

            ## GT Scenes
            reader_gt = trajnetplusplustools.Reader(
                args.path.replace('_pred', '_private') + dataset + '.ndjson',
                scene_type='paths')
            scenes_gt = [
                s for s_id, s in reader_gt.scenes()
                if s_id in filtered_scene_ids
            ]
            total_scenes += len(scenes_gt)

            print("Evaluating Predictions")
            scenes = tqdm(scenes)
            for (predictions, (_, scene_id, paths),
                 ground_truth) in zip(pred_list, scenes, scenes_gt):

                ## Extract 1) first_frame, 2) frame_diff 3) ped_ids for writing predictions
                observed_path = paths[0]
                frame_diff = observed_path[1].frame - observed_path[0].frame
                first_frame = observed_path[args.obs_length -
                                            1].frame + frame_diff
                ped_id = observed_path[0].pedestrian
                ped_id_ = []
                for j, _ in enumerate(paths[1:]):  ## Only need neighbour ids
                    ped_id_.append(paths[j + 1][0].pedestrian)

                if args.unimodal:  ## Unimodal
                    ## ADE / FDE
                    prediction, neigh_predictions = predictions[0]
                    prediction = np.round(prediction, 2)
                    ## make Track Rows
                    # primary
                    prediction = [
                        trajnetplusplustools.TrackRow(
                            first_frame + i * frame_diff, ped_id,
                            prediction[i, 0], prediction[i, 1], 0)
                        for i in range(len(prediction))
                    ]

                    primary_tracks = [
                        t for t in prediction if t.prediction_number == 0
                    ]
                    frame_gt = [
                        t.frame for t in ground_truth[0]
                    ][args.obs_length:args.obs_length + args.pred_length]
                    frame_pred = [t.frame for t in primary_tracks]

                    ## To verify if same scene
                    if frame_gt != frame_pred:
                        raise Exception('frame numbers are not consistent')

                    average_l2 = trajnetplusplustools.metrics.average_l2(
                        ground_truth[0][args.obs_length:args.obs_length +
                                        args.pred_length],
                        primary_tracks,
                        n_predictions=args.pred_length)
                    final_l2 = trajnetplusplustools.metrics.final_l2(
                        ground_truth[0][args.obs_length:args.obs_length +
                                        args.pred_length], primary_tracks)

                    # aggregate FDE and ADE
                    average += average_l2
                    final += final_l2

                    ground_truth = drop_post_obs(ground_truth, args.obs_length)
                    ## Collision Metrics
                    for j in range(1, len(ground_truth)):
                        if trajnetplusplustools.metrics.collision(
                                primary_tracks,
                                ground_truth[j],
                                n_predictions=args.pred_length):
                            gt_col += 1
                            break

                    num_gt_neigh = len(ground_truth) - 1
                    num_predicted_neigh = neigh_predictions.shape[1]
                    if num_gt_neigh != num_predicted_neigh:
                        enable_col1 = False
                    # [Col-I] only if neighs in gt = neighs in prediction
                    if enable_col1:
                        neigh_scenes += 1
                        for n in range(neigh_predictions.shape[1]):
                            neigh = neigh_predictions[:, n]
                            neigh = np.round(neigh, 2)
                            neigh_track = [
                                trajnetplusplustools.TrackRow(
                                    first_frame + j * frame_diff, n,
                                    neigh[j, 0], neigh[j, 1], 0)
                                for j in range(len(neigh))
                            ]
                            if trajnetplusplustools.metrics.collision(
                                    primary_tracks,
                                    neigh_track,
                                    n_predictions=args.pred_length):
                                pred_col += 1
                                break

                primary_tracks_all = [
                    trajnetplusplustools.TrackRow(first_frame + i * frame_diff,
                                                  ped_id, x, y, m)
                    for m, (prim, neighs) in predictions.items()
                    for i, (x, y) in enumerate(prim)
                ]

                if args.topk:
                    topk_ade, topk_fde = trajnetplusplustools.metrics.topk(
                        primary_tracks_all,
                        ground_truth[0][args.obs_length:args.obs_length +
                                        args.pred_length],
                        n_predictions=args.pred_length)
                    topk_average += topk_ade
                    topk_final += topk_fde

                if args.multimodal:
                    nll_val = trajnetplusplustools.metrics.nll(
                        primary_tracks_all,
                        ground_truth[0],
                        n_predictions=args.pred_length,
                        n_samples=20)
                    average_nll += nll_val

        if args.unimodal:
            ## Average ADE and FDE
            average /= total_scenes
            final /= total_scenes
            gt_col /= (total_scenes * 0.01)
            if not enable_col1:
                pred_col = -1
            else:
                pred_col /= (neigh_scenes * 0.01)

            print('ADE: ', np.round(average, 3))
            print('FDE: ', np.round(final, 3))
            print("Col-I: ", np.round(pred_col, 2))
            print("Col-II: ", np.round(gt_col, 2))

        if args.topk:
            topk_average /= total_scenes
            topk_final /= total_scenes
            print('Topk_ADE: ', topk_average)
            print('Topk_FDE: ', topk_final)

        if args.multimodal:
            average_nll /= total_scenes
            print('Average NLL: ', average_nll)
def trajectory_type(rows, path, fps, track_id=0, args=None):
    """ Categorization of all scenes """

    ## Read
    reader = trajnetplusplustools.Reader(path, scene_type='paths')
    scenes = [s for _, s in reader.scenes()]
    ## Filtered Frames and Scenes
    new_frames = set()
    new_scenes = []

    start_frames = set()
    ###########################################################################
    # scenes_test helps to handle both test and test_private simultaneously
    # scenes_test correspond to Test
    ###########################################################################
    test = 'test' in path
    if test:
        path_test = path.replace('test_private', 'test')
        reader_test = trajnetplusplustools.Reader(path_test,
                                                  scene_type='paths')
        scenes_test = [s for _, s in reader_test.scenes()]
        ## Filtered Test Frames and Test Scenes
        new_frames_test = set()
        new_scenes_test = []

    ## For ORCA (Sensitivity)
    orca_sensitivity = False
    if args.goal_file is not None:
        goal_dict = pickle.load(open(args.goal_file, "rb"))
        orca_sensitivity = True
        print("Checking sensitivity to initial conditions")

    ## Initialize Tag Stats to be collected
    tags = {1: [], 2: [], 3: [], 4: []}
    mult_tags = {1: [], 2: [], 3: [], 4: []}
    sub_tags = {1: [], 2: [], 3: [], 4: []}
    col_count = 0

    if not scenes:
        raise Exception('No scenes found')

    for index, scene in enumerate(scenes):
        if (index + 1) % 50 == 0:
            print(index)

        ## Primary Path
        ped_interest = scene[0]

        # if ped_interest[0].frame in start_frames:
        #     # print("Got common start")
        #     continue

        # Assert Test Scene length
        if test:
            assert len(scenes_test[index][0]) >= args.obs_len, \
                   'Scene Test not adequate length'

        ## Check Collision
        ## Used in CFF Datasets to account for imperfect tracking
        # if check_collision(scene, args.pred_len):
        #     col_count += 1
        #     continue

        # ## Consider only those scenes where all pedestrians are present
        # # Note: Different from removing incomplete trajectories
        if args.all_present and (not all_ped_present(scene)):
            continue

        ## Get Tag
        tag, mult_tag, sub_tag = get_type(scene, args)

        if np.random.uniform() < args.acceptance[tag - 1]:
            ## Check Validity
            ## Used in ORCA Datasets to account for rounding sensitivity
            # 28-02-2021 14:00 - block uses orca_helper file. Since we do not have rov2 available, we will not use it
            """
            if orca_sensitivity:
                goals = [goal_dict[path[0].pedestrian] for path in scene]
                # print('Type III')
                if orca_validity(scene, goals, args.pred_len, args.obs_len, args.mode):
                    col_count += 1
                    continue
            """

            ## Update Tags
            tags[tag].append(track_id)
            for tt in mult_tag:
                mult_tags[tt].append(track_id)
            for st in sub_tag:
                sub_tags[st].append(track_id)

            ## Define Scene_Tag
            scene_tag = []
            scene_tag.append(tag)
            scene_tag.append(sub_tag)

            ## Filtered scenes and Frames
            # start_frames |= set(ped_interest[i].frame for i in range(len(ped_interest[0:1])))
            # print(start_frames)
            new_frames |= set(ped_interest[i].frame
                              for i in range(len(ped_interest)))
            new_scenes.append(
                trajnetplusplustools.data.SceneRow(track_id,
                                                   ped_interest[0].pedestrian,
                                                   ped_interest[0].frame,
                                                   ped_interest[-1].frame, fps,
                                                   scene_tag))

            ## Append to list of scenes_test as well if Test Set
            if test:
                new_frames_test |= set(ped_interest[i].frame
                                       for i in range(args.obs_len))
                new_scenes_test.append(
                    trajnetplusplustools.data.SceneRow(
                        track_id, ped_interest[0].pedestrian,
                        ped_interest[0].frame, ped_interest[-1].frame, fps, 0))

            track_id += 1

    # Writes the Final Scenes and Frames
    write(rows, path, new_scenes, new_frames)
    if test:
        write(rows, path_test, new_scenes_test, new_frames_test)

    ## Stats

    # Number of collisions found
    print("Col Count: ", col_count)

    if scenes:
        print("Total Scenes: ", index)

        # Types:
        print("Main Tags")
        print("Type 1: ", len(tags[1]), "Type 2: ", len(tags[2]), "Type 3: ",
              len(tags[3]), "Type 4: ", len(tags[4]))
        print("Sub Tags")
        print("LF: ", len(sub_tags[1]), "CA: ", len(sub_tags[2]), "Group: ",
              len(sub_tags[3]), "Others: ", len(sub_tags[4]))

    return track_id
def main():
    parser = argparse.ArgumentParser()
    parser.add_argument('--path',
                        default='trajdata',
                        help='directory of data to test')
    parser.add_argument('--output',
                        required=True,
                        nargs='+',
                        help='relative path to saved model')
    parser.add_argument('--obs_length',
                        default=9,
                        type=int,
                        help='observation length')
    parser.add_argument('--pred_length',
                        default=12,
                        type=int,
                        help='prediction length')
    parser.add_argument('--disable-write',
                        action='store_true',
                        help='disable writing new files')
    parser.add_argument('--disable-collision',
                        action='store_true',
                        help='disable collision metrics')
    parser.add_argument('--labels',
                        required=False,
                        nargs='+',
                        help='labels of models')
    parser.add_argument('--normalize_scene',
                        action='store_true',
                        help='augment scenes')
    parser.add_argument('--goals',
                        action='store_true',
                        help='Considers goals during prediction')
    parser.add_argument('--unimodal',
                        action='store_true',
                        help='provide unimodal evaluation')
    parser.add_argument('--topk',
                        action='store_true',
                        help='provide topk evaluation')
    parser.add_argument('--multimodal',
                        action='store_true',
                        help='provide multimodal nll evaluation')
    parser.add_argument('--modes',
                        default=1,
                        type=int,
                        help='number of modes to predict')
    args = parser.parse_args()

    scipy.seterr('ignore')

    ## Path to the data folder name to predict
    args.path = 'DATA_BLOCK/' + args.path + '/'

    ## Test_pred: Folders for saving model predictions
    args.path = args.path + 'test_pred/'

    if (not args.unimodal) and (not args.topk) and (not args.multimodal):
        args.unimodal = True  # Compute unimodal metrics by default

    if args.multimodal:
        args.modes = 20

    ## Writes to Test_pred
    ## Does this overwrite existing predictions? No. ###
    datasets = sorted([
        f.split('.')[-2] for f in os.listdir(args.path.replace('_pred', ''))
        if not f.startswith('.') and f.endswith('.ndjson')
    ])

    ## Model names are passed as arguments
    for model in args.output:
        model_name = model.split('/')[-1].replace('.pkl', '')

        # Loading the appropriate model (functionality only for SGAN and LSTM)
        print("Model Name: ", model_name)
        if 'sgan' in model_name:
            predictor = trajnetbaselines.sgan.SGANPredictor.load(model)
        else:
            predictor = trajnetbaselines.lstm.LSTMPredictor.load(model)

        # On CPU
        device = torch.device('cpu')
        predictor.model.to(device)

        total_scenes = 0
        average = 0
        final = 0
        gt_col = 0.
        pred_col = 0.
        neigh_scenes = 0
        topk_average = 0
        topk_final = 0
        all_goals = {}
        average_nll = 0

        ## Start writing in dataset/test_pred
        for dataset in datasets:
            # Model's name
            name = dataset.replace(
                args.path.replace('_pred', '') + 'test/', '')

            # Copy file from test into test/train_pred folder
            print('processing ' + name)
            if 'collision_test' in name:
                continue

            # Read file from 'test'
            reader = trajnetplusplustools.Reader(
                args.path.replace('_pred', '') + dataset + '.ndjson',
                scene_type='paths')
            ## Necessary modification of train scene to add filename (for goals)
            scenes = [(dataset, s_id, s) for s_id, s in reader.scenes()]
            ## Consider goals
            ## Goal file must be present in 'goal_files/test_private' folder
            ## Goal file must have the same name as corresponding test file
            if args.goals:
                goal_dict = pickle.load(
                    open('goal_files/test_private/' + dataset + '.pkl', "rb"))
                all_goals[dataset] = {
                    s_id: [goal_dict[path[0].pedestrian] for path in s]
                    for _, s_id, s in scenes
                }

            reader_gt = trajnetplusplustools.Reader(
                args.path.replace('_pred', '_private') + dataset + '.ndjson',
                scene_type='paths')
            scenes_gt = [s for _, s in reader_gt.scenes()]
            total_scenes += len(scenes_gt)

            for i, (filename, scene_id, paths) in enumerate(scenes):
                if i % 100 == 0:
                    print("Scenes evaluated: ",
                          '{}/{}'.format(i, len(scenes_gt)))
                ground_truth = scenes_gt[i]

                ## Convert numpy array to Track Rows ##
                ## Extract 1) first_frame, 2) frame_diff 3) ped_ids for writing predictions
                observed_path = paths[0]
                frame_diff = observed_path[1].frame - observed_path[0].frame
                first_frame = observed_path[args.obs_length -
                                            1].frame + frame_diff
                ped_id = observed_path[0].pedestrian

                goals = get_goals(paths, all_goals, filename,
                                  scene_id)  ## Zeros if no goals utilized
                predictions = predictor(paths,
                                        goals,
                                        n_predict=args.pred_length,
                                        obs_length=args.obs_length,
                                        modes=args.modes,
                                        args=args)

                if args.unimodal:  ## Unimodal
                    ## ADE / FDE
                    prediction, neigh_predictions = predictions[0]
                    prediction = np.round(prediction, 2)
                    ## make Track Rows
                    # primary
                    prediction = [
                        trajnetplusplustools.TrackRow(
                            first_frame + i * frame_diff, ped_id,
                            prediction[i, 0], prediction[i, 1], 0)
                        for i in range(len(prediction))
                    ]

                    primary_tracks = [
                        t for t in prediction if t.prediction_number == 0
                    ]
                    frame_gt = [
                        t.frame for t in ground_truth[0]
                    ][args.obs_length:args.obs_length + args.pred_length]
                    frame_pred = [t.frame for t in primary_tracks]

                    ## To verify if same scene
                    if frame_gt != frame_pred:
                        raise Exception('frame numbers are not consistent')

                    average_l2 = trajnetplusplustools.metrics.average_l2(
                        ground_truth[0][args.obs_length:args.obs_length +
                                        args.pred_length],
                        primary_tracks,
                        n_predictions=args.pred_length)
                    final_l2 = trajnetplusplustools.metrics.final_l2(
                        ground_truth[0][args.obs_length:args.obs_length +
                                        args.pred_length], primary_tracks)

                    # aggregate FDE and ADE
                    average += average_l2
                    final += final_l2

                    ## Collision Metrics
                    for j in range(1, len(ground_truth)):
                        if trajnetplusplustools.metrics.collision(
                                primary_tracks,
                                ground_truth[j],
                                n_predictions=args.pred_length):
                            gt_col += 1
                            break

                    # ## neighbours (if not empty) [Col-I]
                    if neigh_predictions.shape[1]:
                        neigh_scenes += 1
                        for n in range(neigh_predictions.shape[1]):
                            neigh = neigh_predictions[:, n]
                            neigh = np.round(neigh, 2)
                            neigh_track = [
                                trajnetplusplustools.TrackRow(
                                    first_frame + j * frame_diff, n,
                                    neigh[j, 0], neigh[j, 1], 0)
                                for j in range(len(neigh))
                            ]
                            if trajnetplusplustools.metrics.collision(
                                    primary_tracks,
                                    neigh_track,
                                    n_predictions=args.pred_length):
                                pred_col += 1
                                break

                primary_tracks_all = [
                    trajnetplusplustools.TrackRow(first_frame + i * frame_diff,
                                                  ped_id, x, y, m)
                    for m, (prim, neighs) in predictions.items()
                    for i, (x, y) in enumerate(prim)
                ]

                if args.topk:
                    topk_ade, topk_fde = trajnetplusplustools.metrics.topk(
                        primary_tracks_all,
                        ground_truth[0][args.obs_length:args.obs_length +
                                        args.pred_length],
                        n_predictions=args.pred_length)
                    topk_average += topk_ade
                    topk_final += topk_fde

                if args.multimodal:
                    nll_val = trajnetplusplustools.metrics.nll(
                        primary_tracks_all,
                        ground_truth[0],
                        n_predictions=args.pred_length,
                        n_samples=20)
                    average_nll += nll_val

        if args.unimodal:
            ## Average ADE and FDE
            average /= total_scenes
            final /= total_scenes
            gt_col /= (total_scenes * 0.01)
            if neigh_scenes == 0:
                pred_col = -1
            else:
                pred_col /= (neigh_scenes * 0.01)

            print('ADE: ', average)
            print('FDE: ', final)
            print("Col-I: ", pred_col)
            print("Col-II: ", gt_col)

        if args.topk:
            topk_average /= total_scenes
            topk_final /= total_scenes
            print('Topk_ADE: ', topk_average)
            print('Topk_FDE: ', topk_final)

        if args.multimodal:
            average_nll /= total_scenes
            print('Average NLL: ', average_nll)