{"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"pygments_lexer":"ipython3","nbconvert_exporter":"python","version":"3.6.4","file_extension":".py","codemirror_mode":{"name":"ipython","version":3},"name":"python","mimetype":"text/x-python"}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"markdown","source":"## Overview\nWhat we are trying to do in this notebook is to fix a path looks obviously wrong, crossing a wall such as the image in the left.\n\n<img src= \"https://i.imgur.com/a8B34Hm.png\" alt =\"the structure of the model\" style='width: 500px;'>\n\nTo make it work, I converted the maps into character [in this notebook](https://www.kaggle.com/kokitanisaka/create-arrayed-map).\n\nIn this notebook, we apply push to corridor, snap to grid and device based leakage pp. And then fix the wrongly made waypoints.","metadata":{}},{"cell_type":"code","source":"import pandas as pd\nimport numpy as np\nimport glob\nfrom scipy.spatial.distance import cdist\nimport json\nimport matplotlib.pylab as plt\nimport pickle\n\nfrom shapely.geometry import Point, LineString\nfrom tqdm import tqdm\nimport warnings\nfrom shapely.geometry import Polygon\nfrom shapely.ops import nearest_points\nimport multiprocessing\nimport os\nimport math\nfrom collections import deque\n\nimport multiprocessing\nfrom multiprocessing import Pool\n\nnum_cores = multiprocessing.cpu_count()\n\nwarnings.simplefilter('ignore')\n\nimport re\nimport types\ndef imports():\n    for name, val in globals().items():\n        # module imports\n        if isinstance(val, types.ModuleType):\n            yield name, val\n        # functions / callables\n        if hasattr(val, '__call__'):\n            yield name, val\nnp.seterr(divide='ignore', invalid='ignore')\nnoglobal = lambda fn: types.FunctionType(fn.__code__, dict(imports()))","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"SNAP_THRESHOLD = 20\nFIND_DIST_THRESHOLD = 20\nTHRESHOLD_AREA = 3\nAPPLY_LEAK_FIRST = True\nsubmission_path = '../input/self-attentintive-lstm-by-keras/submission.csv'\n\nexample_site='5a0546857ecc773753327266'\nexample_floorNo='B1'","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"submission = pd.read_csv(submission_path)\ntarget_sites = submission['site_path_timestamp'].apply(lambda x: x.split('_')[0]).unique()\n\nsubmission['site'] = submission.apply(lambda x: x['site_path_timestamp'].split('_')[0], axis=1)\nsubmission['path'] = submission.apply(lambda x: x['site_path_timestamp'].split('_')[1], axis=1)\nsubmission['timestamp'] = submission.apply(lambda x: x['site_path_timestamp'].split('_')[2], axis=1)","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"metadata = pd.DataFrame(glob.glob('../input/indoor-location-navigation/metadata/*'))\nmetadata.columns=['path']\nmetadata['site'] = metadata['path'].apply(lambda x: x.split('/')[-1])\nmetadata = metadata[metadata['site'].isin(target_sites)]['path'].values","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Device Based Leak PP","metadata":{}},{"cell_type":"code","source":"def device_based_leak_pp(sub):\n    df_leak = pd.read_pickle('../input/indoor-support-data/df_leak.pkl')\n    df_leak = df_leak.rename({'path_id':'path'}, axis=1)    \n    df_sub = sub.copy()\n    list_path = df_sub[\"path\"].unique()\n    for path in tqdm(list_path):\n        df_sub_path = df_sub.query(\"path == @path\")\n        start_idx = df_sub.loc[df_sub[\"path\"] == path].index.min()\n        end_idx = df_sub.loc[df_sub[\"path\"] == path].index.max()\n        start_x = df_sub_path.at[start_idx,\"x\"]\n        start_y = df_sub_path.at[start_idx,\"y\"]\n        end_x = df_sub_path.at[end_idx,\"x\"]\n        end_y = df_sub_path.at[end_idx,\"y\"]\n        start_x_leak = df_leak.query(\"path == @path\")[\"start_waypoint_x\"].iloc[0]\n        start_y_leak = df_leak.query(\"path == @path\")[\"start_waypoint_y\"].iloc[0]\n        end_x_leak = df_leak.query(\"path == @path\")[\"end_waypoint_x\"].iloc[0]\n        end_y_leak = df_leak.query(\"path == @path\")[\"end_waypoint_y\"].iloc[0]\n        if not np.isnan(start_x_leak):\n            df_sub.at[start_idx,\"x\"] = start_x_leak\n            df_sub.at[start_idx,\"y\"] = start_y_leak\n        if not np.isnan(end_x_leak):\n            df_sub.at[end_idx,\"x\"] = end_x_leak\n            df_sub.at[end_idx,\"y\"] = end_y_leak\n    return df_sub","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Snap to Grid","metadata":{}},{"cell_type":"code","source":"floor_map = {\"B2\":-2, \"B1\":-1, \"F1\":0, \"F2\": 1, \"F3\":2,\n             \"F4\":3, \"F5\":4, \"F6\":5, \"F7\":6,\"F8\":7,\"F9\":8,\n             \"1F\":0, \"2F\":1, \"3F\":2, \"4F\":3, \"5F\":4, \"6F\":5,\n             \"7F\":6, \"8F\": 7, \"9F\":8}","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train_waypoints = pd.read_csv('../input/indoor-location-train-waypoints/train_waypoints.csv')\ntrain_waypoints['x_coord'] = train_waypoints['x'].apply(lambda x: math.floor(x))\ntrain_waypoints['y_coord'] = train_waypoints['y'].apply(lambda x: math.floor(x))\ntrain_waypoints['wall_dist'] = -1\n\ntrain_waypoints = train_waypoints.drop_duplicates(subset=['path', 'x', 'y'])","metadata":{"_kg_hide-input":true,"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# snap to grid        \ndef split_col(df):\n    df = pd.concat([\n        df['site_path_timestamp'].str.split('_', expand=True) \\\n        .rename(columns={0:'site',\n                         1:'path',\n                         2:'timestamp'}),\n        df\n    ], axis=1).copy()\n    return df\n\ndef plot_preds(\n    site,\n    floorNo,\n    sub=None,\n    true_locs=None,\n    base=\"../input/indoor-location-navigation\",\n    show_train=True,\n    show_preds=True,\n    fix_labels=True,\n    map_floor=None\n):\n    \"\"\"\n    Plots predictions on floorplan map.\n    \n    map_floor : use a different floor's map\n    \"\"\"\n    if map_floor is None:\n        map_floor = floorNo\n    # Prepare width_meter & height_meter (taken from the .json file)\n    floor_plan_filename = f\"{base}/metadata/{site}/{map_floor}/floor_image.png\"\n    json_plan_filename = f\"{base}/metadata/{site}/{map_floor}/floor_info.json\"\n    with open(json_plan_filename) as json_file:\n        json_data = json.load(json_file)\n\n    width_meter = json_data[\"map_info\"][\"width\"]\n    height_meter = json_data[\"map_info\"][\"height\"]\n\n    floor_img = plt.imread(f\"{base}/metadata/{site}/{map_floor}/floor_image.png\")\n\n    fig, ax = plt.subplots(figsize=(12, 12))\n    plt.imshow(floor_img)\n\n    if show_train:\n        true_locs = true_locs.query('site == @site and floorNo == @map_floor').copy()\n        true_locs[\"x_\"] = true_locs[\"x\"] * floor_img.shape[0] / height_meter\n        true_locs[\"y_\"] = (\n            true_locs[\"y\"] * -1 * floor_img.shape[1] / width_meter\n        ) + floor_img.shape[0]\n        true_locs.query(\"site == @site and floorNo == @map_floor\").groupby(\"path\").plot(\n            x=\"x_\",\n            y=\"y_\",\n            style=\"+\",\n            ax=ax,\n            label=\"train waypoint location\",\n            color=\"grey\",\n            alpha=0.5,\n        )\n\n    if show_preds:\n        sub = sub.query('site == @site and floorNo == @floorNo').copy()\n        sub[\"x_\"] = sub[\"x\"] * floor_img.shape[0] / height_meter\n        sub[\"y_\"] = (\n            sub[\"y\"] * -1 * floor_img.shape[1] / width_meter\n        ) + floor_img.shape[0]\n        for path, path_data in sub.query(\n            \"site == @site and floorNo == @floorNo\"\n        ).groupby(\"path\"):\n            path_data.plot(\n                x=\"x_\",\n                y=\"y_\",\n                style=\".-\",\n                ax=ax,\n                title=f\"{site} - floor - {floorNo}\",\n                alpha=1,\n                label=path,\n            )\n    if fix_labels:\n        handles, labels = ax.get_legend_handles_labels()\n        by_label = dict(zip(labels, handles))\n        plt.legend(\n            by_label.values(), by_label.keys(), loc=\"center left\", bbox_to_anchor=(1, 0.5)\n        )\n    return fig, ax\n\ndef sub_process(sub, train_waypoints):\n    train_waypoints['isTrainWaypoint'] = True\n    sub = split_col(sub[['site_path_timestamp','floor','x','y']]).copy()\n    sub = sub.merge(train_waypoints[['site','floorNo','floor']].drop_duplicates(), how='left')\n    sub = sub.merge(\n        train_waypoints[['x','y','site','floor','isTrainWaypoint']].drop_duplicates(),\n        how='left',\n        on=['site','x','y','floor']\n             )\n    sub['isTrainWaypoint'] = sub['isTrainWaypoint'].fillna(False)\n    return sub.copy()\n\ndef add_xy(df):\n    df['xy'] = [(x, y) for x,y in zip(df['x'], df['y'])]\n    return df\n\ndef closest_point(point, points):\n    \"\"\" Find closest point from a list of points. \"\"\"\n    return points[cdist([point], points).argmin()]\n\ndef snap_to_grid(sub, threshold, more_than = 0):\n    \"\"\"\n    Snap to grid if within a threshold.\n    \n    x, y are the predicted points.\n    x_, y_ are the closest grid points.\n    _x_, _y_ are the new predictions after post processing.\n    \"\"\"\n    sub['_x_'] = sub['x']\n    sub['_y_'] = sub['y']\n    cond = (more_than <= sub['dist']) & (sub['dist'] < threshold)\n    sub.loc[cond, '_x_'] = sub.loc[cond]['x_']\n    sub.loc[cond, '_y_'] = sub.loc[cond]['y_']\n    return sub.copy()\n\ndef snap(sub, train_waypoints, threshold=0, more_than=0):\n    sub = sub_process(sub, train_waypoints)\n    \n    sub = add_xy(sub)\n    train_waypoints = add_xy(train_waypoints)\n\n    ds = []\n    for (site, myfloor), d in sub.groupby(['site','floor']):\n        true_floor_locs = train_waypoints.loc[(train_waypoints['floor'] == myfloor) &\n                                              (train_waypoints['site'] == site)] \\\n            .reset_index(drop=True)\n        if len(true_floor_locs) == 0:\n            print(f'Skipping {site} {myfloor}')\n            continue\n        d['matched_point'] = [closest_point(x, list(true_floor_locs['xy'])) for x in d['xy']]\n        d['x_'] = d['matched_point'].apply(lambda x: x[0])\n        d['y_'] = d['matched_point'].apply(lambda x: x[1])\n        ds.append(d)\n\n    sub = pd.concat(ds)\n    \n    # Calculate the distances\n    sub['dist'] = np.sqrt( (sub.x-sub.x_)**2 + (sub.y-sub.y_)**2 )\n\n    sub_pp = snap_to_grid(sub, threshold=threshold, more_than=more_than)\n\n    sub_pp = sub_pp[['site_path_timestamp','floor','_x_','_y_','site','path','floorNo']] \\\n        .rename(columns={'_x_':'x', '_y_':'y'})\n    \n    if example_site is not None:\n        plot_preds(example_site, example_floorNo, sub_pp,\n                   train_waypoints, show_preds=True)\n        plt.show()\n    \n    return sub_pp","metadata":{"_kg_hide-input":true,"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Push to Corridor","metadata":{}},{"cell_type":"code","source":"def fix_prediction(args):\n    # Unpack\n    (site, floor), df = args\n    \n    # Find the file path\n    floor_name = os.listdir('../input/indoor-location-navigation-scaled-geojson/scaled_geojson/' + site)\n    for name in floor_name:\n        if floor_map[name] == floor:\n            file = '../input/indoor-location-navigation-scaled-geojson/scaled_geojson/' + site + '/' + name + '/shapely_geometry.pkl'\n            break\n            \n    # Open the corridor\n    with open(file, 'rb') as f:\n        corridor = pickle.load(f)\n        \n    # Find the outside-corridor points and force them into the corridor\n    out_corridor = []\n    out_corridor_idx = []\n    corridor_nearest_points = []\n    for i in range(df.shape[0]):\n        p = Point(df[['x', 'y']].iloc[i].values)\n        if not p.within(corridor):\n            out_corridor.append(p)\n            out_corridor_idx.append(df[['x', 'y']].index[i])\n            nearest_p, _ = nearest_points(corridor, p)\n            x, y = nearest_p.xy[0][0], nearest_p.xy[1][0]\n            corridor_nearest_points.append([x, y])\n    \n    if len(corridor_nearest_points) != 0:\n        df.loc[out_corridor_idx, ['x', 'y']] = np.array(corridor_nearest_points)\n    \n    return df\n\ndef push_to_corridor(ss):\n    ss[['site', 'path', 'timestamp']] = np.array([i.split('_') for i in ss.site_path_timestamp])\n\n    processes = multiprocessing.cpu_count()\n    with multiprocessing.Pool(processes = processes) as pool:\n        dfs = pool.imap_unordered(fix_prediction, ss.groupby(['site', 'floor']))\n        dfs = tqdm(dfs)\n        dfs = list(dfs)\n    return pd.concat(dfs).sort_values('site_path_timestamp')[['site_path_timestamp', 'floor', 'x', 'y']]","metadata":{"_kg_hide-input":true,"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"snapped_submission = submission\nsnapped_submission = push_to_corridor(snapped_submission)\nsnapped_submission = snap(snapped_submission, train_waypoints, 5)\nif APPLY_LEAK_FIRST:\n    snapped_submission = device_based_leak_pp(snapped_submission)\n\nsubmission['x_org'] = submission['x']\nsubmission['y_org'] = submission['y']\n\nsubmission['x'] = snapped_submission['x']\nsubmission['y'] = snapped_submission['y']","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Fix the Snapped Waypoints","metadata":{}},{"cell_type":"code","source":"class Node:\n    def __init__(self, row, col, aa):\n        self.col = col\n        self.row = row\n        self.nears = [[row,col+1],[row,col-1],[row+1,col],[row-1,col]]\n        self.step = -1\n        self.aa = aa\n        \n    def __repr__(self):\n        return f'Node row:{self.row} Node col:{self.col} nears:{self.nears} step:{self.step}'\n    \n    def has_visited(self):\n        return self.step != -1\n    \n    def show(self):\n        if self.step == 0:\n            return 0\n        \n        if self.aa == '*':\n            return self.aa\n        \n        return str(self.step)[0] if self.step != -1 else self.aa\n    \n    def reset(self):\n        self.step = -1","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def create_nodes(array_map):\n    nodes = []\n    for i in range(len(array_map)): \n        nodes.append([])\n        for j in range(len(array_map[0])):\n            nodes[i].append(Node(i, j, array_map[i][j])) \n\n    return nodes\n\ndef snap_dist(x, path_row):\n    return math.sqrt((path_row['x_org'] - x['x']) ** 2 + (path_row['y_org'] - x['y']) ** 2)","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def get_xy(x, y, nodes):\n    if x <= 0: x = 0\n    if x >= len(nodes):  x = len(nodes) - 1\n    if y <= 0:  y = 0\n    if y >= len(nodes[0]):  y = len(nodes[0]) - 1\n        \n    return x, y\n\n@noglobal\ndef calc_distance_to_waypoints_considering_wall(\n        start_x, start_y,  \n        array_map, nodes_template, waypoints_template, path_row, SNAP_THRESHOLD, FIND_DIST_THRESHOLD):\n    \n    nodes = None\n    nodes = nodes_template.copy()\n    for node in nodes:\n        for cell in node:\n            cell.reset()\n    \n    waypoints = waypoints_template.copy()\n\n    waypoints['snap_dist'] = waypoints.apply(lambda x: snap_dist(x, path_row), axis=1)\n    waypoints = waypoints[waypoints['snap_dist']<=SNAP_THRESHOLD]\n\n    queue = deque()\n    nodes[start_x][start_y].step = 0\n    \n    queue.append(nodes[start_x][start_y])\n    num_found_waypoints = 0\n    farthest_step = 0\n    step = 0\n    break_fg = False\n    while queue:\n        node = queue.popleft() \n        step = node.step + 1\n        if step > farthest_step:\n            farthest_step = step\n        \n        nears = node.nears\n        for i, near in enumerate(nears):\n            \n            near_x, near_y = get_xy(near[0], near[1], nodes)\n            try:\n                ext_node = nodes[near_x][near_y]\n            except:\n                print(f'{len(nodes)}:{len(nodes[0])} - {near_x}:{near_y}')\n            map_point = array_map[near_x][near_y]\n            if not ext_node.has_visited():\n                if map_point == '.':\n                    ext_node.step = step\n                    queue.append(ext_node)\n                elif map_point == '*':\n                    ext_node.step = step\n                    queue.append(ext_node)\n                    num_found_waypoints += 1\n                    \n                    waypoints.loc[(waypoints['x_coord']==near_x) & (waypoints['y_coord']==near_y), 'wall_dist'] = step\n\n                    if num_found_waypoints >= len(waypoints):\n                        break_fg = True\n                        break\n                        \n        if farthest_step >= FIND_DIST_THRESHOLD:\n            break\n        if break_fg: \n            break\n    \n    return waypoints[waypoints['wall_dist']!=-1].sort_values(['snap_dist', 'wall_dist'], ascending=True).head(1), nodes, waypoints","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def get_line(x):\n    return LineString([Point(x['x'], x['y']), (Point(x['x_lag'], x['y_lag']))])\n\ndef intersection(x, corridor):\n    if math.isnan(x['x_lag']): return None\n\n    return corridor.intersection(x['line_lag'].buffer(2))\n\ndef intersection_area(x, corridor):\n    if math.isnan(x['x_lag']): return None\n\n    length = x['line_lag'].length\n    \n    if length == 0: return 0\n    \n    return x['intersection'].area / x['line_lag'].length","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"data = submission\n\ndata = data.sort_values('site_path_timestamp')\ndata['x_lag'] = data.groupby('path')['x'].shift()\ndata['y_lag'] = data.groupby('path')['y'].shift()\ndata['x_lead'] = data.groupby('path')['x'].shift(-1)\ndata['y_lead'] = data.groupby('path')['y'].shift(-1)\n\n\nfor site in tqdm(target_sites):\n    \n    metadata_floor_paths = glob.glob(f'../input/indoor-location-navigation/metadata/{site}/*')\n    \n    for metadata_floor_path in metadata_floor_paths:\n        floor = metadata_floor_path.split('/')[-1]\n        floor_val = floor_map[floor]\n\n        corridor_path = f'../input/indoor-location-navigation-scaled-geojson/scaled_geojson/{site}/{floor}/shapely_geometry.pkl'\n        with open(corridor_path, 'rb') as f:\n            corridor = pickle.load(f)\n        minx, miny, maxx, maxy = corridor.bounds\n        all_area = Polygon([(0, 0), (maxx, 0), (maxx, maxy), (0, maxy)])\n        all_area = all_area.difference(corridor)\n            \n        with open(f'../input/indoor-array-map/{site}_{floor}_array_map.pkl' ,'rb') as f:\n            array_map = np.array(pickle.load(f)).T\n            \n        nodes_template = create_nodes(array_map)\n\n        waypoints = train_waypoints[(train_waypoints['site']==site) & (train_waypoints['floor']==floor_val)]\n            \n        floor_data = data[(data['site']==site) & (data['floor']==floor_val)]\n        \n        for path, path_group in floor_data.groupby('path'):\n\n            path_group['x_upd'] = 0\n            path_group['y_upd'] = 0\n            path_group['line_lag'] = path_group.apply(lambda x: get_line(x), axis=1)\n            path_group['intersection'] = path_group.apply(lambda x: intersection(x, all_area), axis=1)\n            path_group['intersection_area'] = path_group.apply(lambda x: intersection_area(x, all_area) , axis=1)\n                \n            for i in path_group.index:\n\n                path_row = path_group.loc[i, :]\n\n                # skip the first step\n                if math.isnan(path_row['x_lag']): continue\n\n                # check if the line crosses the wall\n                line_from_to = LineString([Point(path_row['x_lag'], path_row['y_lag']), \n                                           Point(path_row['x'], path_row['y'])])\n                line_crosses = corridor.crosses(line_from_to)\n                if not line_crosses: continue\n                if path_row['intersection_area'] <= THRESHOLD_AREA: continue\n\n                # update the current point to a valid one\n                start_x, start_y = get_xy(math.floor(path_row['x_lag']), math.floor(path_row['y_lag']), nodes_template)\n                \n                nearest_wp, res_nodes, possible_wps = calc_distance_to_waypoints_considering_wall(start_x, start_y, array_map, nodes_template, waypoints, path_row,\n                                                                                                  SNAP_THRESHOLD, FIND_DIST_THRESHOLD)\n                if nearest_wp.shape[0] != 0:\n                    rep_x = nearest_wp['x'].values[0]\n                    rep_y = nearest_wp['y'].values[0]\n                    path_group.loc[i, 'x_upd'] = rep_x\n                    path_group.loc[i, 'y_upd'] = rep_y\n                    path_group.loc[i + 1, 'x_lag'] = rep_x\n                    path_group.loc[i + 1, 'y_lag'] = rep_y\n                    path_group = path_group[~path_group['x'].isna()]\n\n                    path_group['line_lag'] = path_group.apply(lambda x: get_line(x), axis=1)\n                    path_group['intersection'] = path_group.apply(lambda x: intersection(x, all_area), axis=1)\n                    path_group['intersection_area'] = path_group.apply(lambda x: intersection_area(x, all_area) , axis=1)\n                    \n                    data.loc[i, 'x'] = rep_x\n                    data.loc[i, 'y'] = rep_y\n                    \n                    \n            # fix the points outside the map\n            def floor_type(x, array_map):\n                _x = math.floor(x['x'])\n                _y = math.floor(x['y'])\n                return array_map[_x][_y]\n\n            path_group['floor_type'] = path_group.apply(lambda x: floor_type(x, array_map), axis=1)\n            walls = path_group[path_group['floor_type']=='#']\n             \n            for i, wall in walls.iterrows():\n                waypoints['dist'] = waypoints.apply(lambda x: math.sqrt((x['x'] - wall['x_org']) ** 2 + (x['y'] - wall['y_org']) ** 2), axis=1)\n                nearest = waypoints[waypoints['dist']<=6].sort_values('dist')\n                if nearest.shape[0] != 0:\n                    nearest = nearest.head(1)\n                    data.loc[i, 'x'] = nearest['x'].values[0]\n                    data.loc[i, 'y'] = nearest['y'].values[0]\n                else:\n                    _x = data.loc[i, 'x_org']\n                    _y = data.loc[i, 'y_org']\n\n                    if array_map[math.floor(_x)][math.floor(_y)] == '#':\n                        nearest = waypoints.sort_values('dist').head(1)\n                        data.loc[i, 'x'] = nearest['x'].values[0]\n                        data.loc[i, 'y'] = nearest['y'].values[0]\n                    else:\n                        data.loc[i, 'x'] = _x\n                        data.loc[i, 'y'] = _y\n","metadata":{"scrolled":true,"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Display Utils","metadata":{}},{"cell_type":"code","source":"def display_nodes_map(nodes, possible_wps):\n    ns = np.array(nodes)\n    \n    for i, r in possible_wps.iterrows():\n        ns[r['x_coord']][r['y_coord']] = '+'\n    \n    ns = ns.T\n    for line in reversed(ns):\n        print()\n        for cell in line:\n            try:\n                print(cell.show(), end='')\n            except:\n                print(cell, end='')\n            \ndef display_aa_map(array_map, nodes, deg_point=None):\n    ar_map = array_map.copy()\n    \n    for node in nodes:\n        for cell in node:\n            if cell.has_visited():\n                ar_map[cell.row][cell.col] = str(cell.step)[0]\n                #print(f'{cell.row}:{cell.col}')\n\n    if deg_point is not None:\n        ar_map[math.floor(deg_point[0])][math.floor(deg_point[1])] = '$' # 指定したポイントの表示\n                \n    ar_map = np.array(ar_map.T)\n    \n    for line in reversed(ar_map):\n        print()\n        for cell in line:\n            print(cell, end='')","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"#tmp_waypoints\ndisplay_nodes_map(res_nodes, possible_wps)","metadata":{"_kg_hide-output":true,"scrolled":true,"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"data = data.sort_values('site_path_timestamp')\ndata[['site_path_timestamp', 'floor', 'x', 'y']].to_csv('fsw.csv', index=False)\n","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"print(f\"fixed points : {data[data['x']!=submission['x']].shape[0]}\")\n","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"example_site='5d27097f03f801723c320d97'\nexample_floorNo='F5'\n","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Before Fix (snap to grid had been not applied)\nsnap(pd.read_csv(submission_path), train_waypoints)","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Before Fix (snap to grid had been applied)\nsnap(snapped_submission, train_waypoints)","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# After fix\nsnap(data, train_waypoints)","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{},"execution_count":null,"outputs":[]}]}