{"cells":[{"metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","trusted":true},"cell_type":"code","source":"# Operating system\nimport sys\nimport os\nfrom pathlib import Path\nos.environ[\"OMP_NUM_THREADS\"] = \"1\"\n\n# math\nimport numpy as np\nimport pandas as pd\nfrom numpy import arange\nimport math\nfrom numpy import linalg as LA\nfrom scipy import stats\n\n# plots\nimport matplotlib.pyplot as plt\nfrom matplotlib.axes import Axes\nfrom matplotlib import animation, rc\nimport matplotlib.colors as colors\nimport plotly.graph_objects as go\nfrom tqdm import tqdm, tqdm_notebook\ntqdm.pandas()\nfrom datetime import timezone, datetime, timedelta\n\n# ML\nimport sklearn\nimport h5py\nimport sklearn.metrics\nfrom sklearn.model_selection import train_test_split\nfrom sklearn.cluster import DBSCAN\nfrom sklearn import metrics\nfrom sklearn.datasets.samples_generator import make_blobs\nfrom sklearn.preprocessing import StandardScaler\n\n# Lyft SDK\n!pip install lyft-dataset-sdk\nfrom lyft_dataset_sdk.utils.map_mask import MapMask\nfrom lyft_dataset_sdk.lyftdataset import LyftDataset\nfrom lyft_dataset_sdk.utils.geometry_utils import view_points, box_in_image, BoxVisibility\nfrom lyft_dataset_sdk.utils.geometry_utils import view_points, transform_matrix\nfrom lyft_dataset_sdk.utils.data_classes import LidarPointCloud, Box, Quaternion\n\nDATA_PATH = './'\nos.system('rm -f data && ln -s /kaggle/input/3d-object-detection-for-autonomous-vehicles/train_data data')\nos.system('rm  -f images && ln -s /kaggle/input/3d-object-detection-for-autonomous-vehicles/train_images images')\nos.system('rm  -f maps && ln -s /kaggle/input/3d-object-detection-for-autonomous-vehicles/train_maps maps')\nos.system('rm  -f lidar && ln -s /kaggle/input/3d-object-detection-for-autonomous-vehicles/train_lidar lidar')\n\nDEBUG = True\ndef log(message):\n    if(DEBUG == True):\n        time_string = datetime.now().strftime('%Y-%m-%d-%H-%M-%S.%f')\n        print(time_string + ' : ', message )","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"LYFT = LyftDataset(data_path=DATA_PATH, json_path=DATA_PATH + 'data', verbose=True)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# Get object size\nwlhs = np.array([ann['size'] for ann in  LYFT.sample_annotation])","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"# Helper Functions"},{"metadata":{"trusted":true},"cell_type":"code","source":"# Unzip lidar files\ndef unzip(row, mode='train'):\n    zip_command = \"unzip ../3d-object-detection-for-autonomous-vehicles.zip \" + mode + '_' + row['filename'].astype(str)           + \" -d \"            + CWD + \"/../data/\"        \n    os.system(zip_command)    \n\ndef removefile(row, mode='train'):\n    rm_command = \"rm -f  \" + CWD + \"/../data/\"+ mode + '_' + row['filename'].astype(str)                  \n    os.system(zip_command)    ","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"def sort_points_by_coord(points, coord):\n    indices = np.argsort(points[:,coord],axis=0).reshape(-1,1)\n    indices = np.repeat(indices, points.shape[-1],axis=-1)\n    # print(indices)\n    sorted = np.take_along_axis(points,indices,axis=0)\n    del indices\n    return sorted\n\ndef sort_points(points):\n    sorted_points = sort_points_by_coord(points, 2)\n    sorted_points = sort_points_by_coord(sorted_points, 1)\n    return sort_points_by_coord(sorted_points, 0)\n    \n# https://www.geeksforgeeks.org/linear-regression-python-implementation/\ndef estimate_regression_coef(points): \n\n    x = points[:,0]\n    y = points[:,1]\n    # number of observations/points \n    n = np.size(x) \n  \n    # mean of x and y vector \n    m_x, m_y = np.mean(x), np.mean(y) \n  \n    # calculating cross-deviation and deviation about x \n    SS_xy = np.sum(y*x) - n*m_y*m_x \n    SS_xx = np.sum(x*x) - n*m_x*m_x \n  \n    # calculating regression coefficients \n    b_1 = SS_xy / SS_xx \n    b_0 = m_y - b_1*m_x \n  \n    return b_1 \n\ndef length_of_xy_diagonal(points):\n    x = points[:,0]\n    y = points[:,1]\n    return LA.norm([np.max(x)- np.min(x), np.max(y)- np.min(y)])\n\ndef length_of_xz_diagonal(points):\n    x = points[:,0]\n    z = points[:,2]\n    return LA.norm([np.max(x)- np.min(x), np.max(z)- np.min(z)])\n\ndef slope(points):\n    x = points[:,0]\n    y = points[:,1]\n    m, _, _, _, _ = stats.linregress(x, y)\n    return m\n\ndef yaw(points):\n#     b1 = estimate_regression_coef (points)\n    b1 = slope(points)\n    if b1 == 0:\n        return math.pi / 2\n    else:\n        return np.arctan(1/b1)\n\ndef rotation_matrix_xy(theta):\n     return np.array([ \n        [math.cos(theta), -math.sin(theta), 0],\n        [math.sin(theta), math.cos(theta), 0],\n        [0, 0, 1],\n    ])\n\n# Rotate point cluster using yaw -> calclulate min, max and construct boxs -> inverse rotate to world coords\ndef get_min_bbox_corners(candidate, yw):\n    xyz = np.delete(candidate, np.s_[3], axis=1) \n    world_to_candidate_rotation_matrix = rotation_matrix_xy(-yw)\n    rotated = np.matmul(xyz, world_to_candidate_rotation_matrix)\n    minx = np.min(rotated[:,0])\n    maxx = np.max(rotated[:,0])\n    miny = np.min(rotated[:,1])\n    maxy = np.max(rotated[:,1])\n    minz = np.min(rotated[:,2])\n    maxz = np.max(rotated[:,2])\n    corners_rotated = np.array([\n        [minx, miny, minz],\n        [maxx, miny, minz],\n        [maxx, miny, maxz],\n        [minx, miny, maxz],               \n        [minx, maxy, minz],\n        [maxx, maxy, minz],\n        [maxx, maxy, maxz],\n        [minx, maxy, maxz],               \n    ])\n    del xyz\n    del rotated\n    corners = np.matmul(corners_rotated, world_to_candidate_rotation_matrix.T)\n    return (corners_rotated, corners)\n\ndef get_centroid(corners):\n    minx = np.min(corners[:,0])\n    maxx = np.max(corners[:,0])\n    miny = np.min(corners[:,1])\n    maxy = np.max(corners[:,1])\n    minz = np.min(corners[:,2])\n    maxz = np.max(corners[:,2])\n    x = (minx + maxx) / 2\n    y = (miny + maxy) / 2\n    z = (minz + maxz) / 2\n    return x, y, z\n\ndef get_dimensions(corners):\n    minx = np.min(corners[:,0])\n    maxx = np.max(corners[:,0])\n    miny = np.min(corners[:,1])\n    maxy = np.max(corners[:,1])\n    minz = np.min(corners[:,2])\n    maxz = np.max(corners[:,2])\n    w = (maxx - minx) \n    l = (maxy - miny) \n    h = (maxz - minz) \n    return w, l, h\n\n# https://www.pyimagesearch.com/2016/11/07/intersection-over-union-iou-for-object-detection/\ndef minmax(box):\n    minx = np.min(box[:,0])\n    maxx = np.max(box[:,0])\n    miny = np.min(box[:,1])\n    maxy = np.max(box[:,1])\n    minz = np.min(box[:,2])\n    maxz = np.max(box[:,2])    \n    return minx, maxx, miny , maxy, minz, maxz\n    \ndef intersection(boxA, boxB):\n    # determine the (x, y)-coordinates of the intersection rectangle\n    minxa, maxxa, minya, maxya, minza, maxza = minmax(boxA)\n    minxb, maxxb, minyb, maxyb, minzb, maxzb = minmax(boxB)\n    xA = max(minxa, minxb)\n    yA = max(minya, minyb)\n    zA = max(minza, minzb)\n    xB = min(maxxa, maxxb)\n    yB = min(maxya, maxyb)\n    zB = min(maxza, maxzb)\n\n    # compute the volume of intersection cuboid\n    intersectionVolume = max(0, xB - xA ) * max(0, yB - yA )  * max(0, zB - zA) \n    return intersectionVolume\n\ndef union(boxA, boxB):\n    aw, al, ah = get_dimensions(boxA)\n    bw, bl, bh = get_dimensions(boxB)\n\n    totalVolume = aw * al * ah + bw * bl * bh - intersection(boxA, boxB)\n    return totalVolume\n\ndef iou(boxA, boxB):\n    return intersection(boxA,boxB) / union(boxA, boxB)\n\ndef make_a_box(minx, maxx, miny, maxy, minz,maxz):\n    return np.array([\n        [minx, miny, minz],\n        [maxx, miny, minz],\n        [maxx, miny, maxz],\n        [minx, miny, maxz],               \n        [minx, maxy, minz],\n        [maxx, maxy, minz],\n        [maxx, maxy, maxz],\n        [minx, maxy, maxz],               \n    ])","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# Extract composite dataframe for list of sample tokens\ndef extract_data_for_clustering(tokens):\n    sampledata_df = pd.DataFrame(LYFT.sample_data)\n    sampledata_df = sampledata_df[sampledata_df['sample_token'].isin(tokens)]\n    sampledata_df = sampledata_df[sampledata_df['fileformat'] == 'bin']\n    sampledata_df.rename(columns={'token':'sampledata_token'}, inplace=True)\n    sampledata_df = sampledata_df[[\n        'sample_token', \n        'sampledata_token',\n        'ego_pose_token', \n        'channel',\n        'calibrated_sensor_token',\n        'fileformat',\n        'filename']]\n\n    ep_df = pd.DataFrame(LYFT.ego_pose)\n    ep_df.rename(columns={'token':'ego_pose_token', 'rotation': 'ep_rotation', 'translation': 'ep_translation'}, inplace=True)\n    ep_df = ep_df[['ego_pose_token',\n                     'ep_rotation',\n                     'ep_translation']]\n    sampledata_df = pd.merge(sampledata_df, ep_df, left_on='ego_pose_token', right_on='ego_pose_token',how='inner')\n\n\n    cs_df = pd.DataFrame(LYFT.calibrated_sensor)\n    cs_df.rename(columns={'token':'calibrated_sensor_token', 'rotation': 'cs_rotation', 'translation': 'cs_translation'}, inplace=True)\n    cs_df = cs_df[['calibrated_sensor_token',\\\n                     'cs_rotation',\\\n                     'cs_translation',\\\n                     'camera_intrinsic'\n                  ]]\n    sampledata_df = pd.merge(sampledata_df, cs_df, left_on='calibrated_sensor_token', right_on='calibrated_sensor_token',how='inner')\n    # sampledata_df['filepath'] = sampledata_df.apply(lambda row: LYFT.get_sample_data_path(row['sampledata_token']), axis=1)\n    sampledata_df['pointcloud'] = sampledata_df.apply(lambda row: LidarPointCloud.from_file(LYFT.get_sample_data_path(row['sampledata_token'])).points, axis=1)\n    sampledata_df = sampledata_df[[\n        'sample_token', \n        'sampledata_token',\n        'ep_rotation',\n        'ep_translation',\n        'channel',\n        'cs_rotation',\n        'cs_translation',\n        # 'filepath',\n        'pointcloud',\n        'fileformat',\n        'filename']]\n    \n    return sampledata_df.copy(deep=True)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"def car_to_world_points_notf (points, translation, rotation):\n    rotated = np.dot(Quaternion(rotation).rotation_matrix, points.T)\n    translated = np.add(rotated.T, translation)\n    return translated\n\ndef sensor_to_car_points_notf (points, translation, rotation):\n    rotated = np.dot(Quaternion(rotation).rotation_matrix, points.T)\n    translated = np.add(rotated.T, translation)\n    return translated\n\n# Take all LIDAR points for a sample and merge them in world coordinates\ndef get_lidar_points_for_clustering(sample_token, token_input, data_path):\n    pt_cloud = np.zeros((0,3))\n    ground_z = -20.0\n    for i in range(len(token_input)):\n\n        sampledatarow = token_input.iloc[i]\n        cs_t = sampledatarow['cs_translation']\n        cs_r = sampledatarow['cs_rotation']\n        ep_t = sampledatarow['ep_translation']\n        ep_r = sampledatarow['ep_rotation']\n        ground_z = min(ground_z, ep_t[2])\n        ego_x = ep_t[0]\n        ego_y = ep_t[1]\n\n        pointcloud = sampledatarow['pointcloud']\n        # pointcloud = get_lidar_pointcloud_for_clustering(sampledatarow['filepath'])\n        pc_points_t = pointcloud.T\n        pc_points_t = pc_points_t[:,:3]\n        pc_points_t = sensor_to_car_points_notf(pc_points_t, cs_t, cs_r)\n\n        pc_points_t = car_to_world_points_notf(pc_points_t, ep_t, ep_r)\n        print(pc_points_t.shape, ground_z, ep_t[2],np.min(pc_points_t[:,2]), np.max(pc_points_t[:,2]))\n        pc_points_t = pc_points_t[pc_points_t[:,0] < (ego_x+100)]\n        pc_points_t = pc_points_t[pc_points_t[:,0] > (ego_x-100)]\n\n        pc_points_t = pc_points_t[pc_points_t[:,1] < (ego_y+100)]\n        pc_points_t = pc_points_t[pc_points_t[:,1] > (ego_y-100)]\n\n\n        pc_points_t = pc_points_t[pc_points_t[:,2] < (ground_z+5.3)]\n        pc_points_t = pc_points_t[pc_points_t[:,2] > (ground_z+1)]\n        print(pc_points_t.shape,  ground_z,ep_t[2], np.min(pc_points_t[:,2]), np.max(pc_points_t[:,2]))\n\n\n        pt_cloud = np.concatenate([pt_cloud, pc_points_t], axis=0)\n        #del pointcloud\n        #del pc_points_t\n    return ground_z,  pt_cloud      ","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# Given a sample token, identify point clusters using DBSCAN with bounding box dimensions for that sample\ndef identify_clusters(sample_token, token_input, data_path, eps=0.3, min_samples=10):\n    yaw_list = []\n    corners_list = []\n    dimensions_list = []\n    xyzs = np.zeros((0,3))\n    wlhs = np.zeros((0,3))\n    xs = []\n    ys = []\n    zs = []\n    ws = []\n    ls = []\n    hs = []\n    equisized = []\n    has_rows = False\n\n    log('getting lidar points' + sample_token)\n    ground_z, all_points = get_lidar_points_for_clustering(sample_token, token_input, data_path)\n    log('got lidar points' + sample_token)\n\n    if(all_points.shape[0] > 0):\n        clusters = DBSCAN(eps=eps, min_samples=min_samples).fit(all_points)\n        log('clustered' + sample_token)\n        labels = clusters.labels_\n        unique_labels = set(labels)\n        points_with_labels = np.concatenate((all_points, labels.reshape((-1,1))), axis=1)\n        noise_points = labels == -1\n        points_with_labels = points_with_labels[~noise_points]\n        if(points_with_labels.shape[0] > 0):\n            ulabels = [x for x in unique_labels if x != -1]\n            # ulabels = unique_labels[unique_labels != -1]\n            if(len(ulabels) > 0):\n                pt_clouds = []\n                max_points = 0\n\n                for ulabel in list(ulabels):\n                    box_pt_cloud = points_with_labels[points_with_labels[:,3] == ulabel]\n\n                    if(box_pt_cloud.shape[0] == 0):\n                        continue\n#                     if(length_of_xy_diagonal(box_pt_cloud) > 26):\n#                         continue;\n                    if(length_of_xz_diagonal(box_pt_cloud) > 10):\n                        continue;\n\n                    yw = yaw(box_pt_cloud)\n                    corners_rotated, corners = get_min_bbox_corners(box_pt_cloud, yw)\n                    if (corners[0][2] > ground_z + 2):\n                        continue\n                    w, l, h = get_dimensions(corners_rotated)\n                    if (w > 5):\n                        continue\n                    if (l > 25):\n                        continue\n                    if (h > 5):\n                        continue\n                    has_rows = True\n                    yaw_list.append(yw)\n                    corners_list.append(corners)\n                    dimensions_list.append((w,l,h))\n                    box_pt_cloud = np.delete(box_pt_cloud, np.s_[3], axis=1)\n\n                    num_points = box_pt_cloud.shape[0]\n\n                    if num_points > max_points:\n                        max_points = num_points\n                    # box_pt_cloud = box_pt_cloud.astype('f')\n                    pt_clouds.append((box_pt_cloud))\n                if(len(pt_clouds) > 0):\n                    for cloud in pt_clouds:\n                        ones = np.ones((cloud.shape[0])).reshape(-1,1)\n                        cloud = np.concatenate((cloud, ones), axis=1)\n                        zeros = np.zeros((max_points - cloud.shape[0],4))\n                        fullsize = np.c_[cloud.T, zeros.T].T\n                        fullsize = fullsize.astype('f')\n                        equisized.append(fullsize)\n#                     del pt_clouds\n#                     del points_with_labels\n#                     del clusters\n                    xyzs = np.array([ get_centroid(c) for c in corners_list])\n                    wlhs = np.array(dimensions_list)\n    log('proposals ready' + sample_token)\n        \n    proposal_df = pd.DataFrame()\n    proposal_df['yaw'] = yaw_list\n    proposal_df['x'] = xyzs[:,0]\n    proposal_df['y'] = xyzs[:,1]\n    proposal_df['z'] = xyzs[:,2]\n    proposal_df['w'] = wlhs[:,0]\n    proposal_df['l'] = wlhs[:,1]\n    proposal_df['h'] = wlhs[:,2]\n    \n    proposal_df['corners'] = corners_list\n    proposal_df['dimensions'] = dimensions_list\n    proposal_df['candidate'] = equisized\n    if(len(equisized)> 0):\n        proposal_df['token'] = sample_token\n    return all_points, has_rows, proposal_df","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"# Logging point clouds with Weights & Biases"},{"metadata":{"trusted":true},"cell_type":"code","source":"# can use master now\n#!pip install --upgrade 'git+git://github.com/wandb/client.git@object3D/lidar#egg=wandb' -qq","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"!pip install --upgrade 'git+https://github.com/wandb/client@point-cloud-artifacts' -qq\nimport wandb\nfrom wandb.keras import WandbCallback\nwandb.init(project=\"lyft-artifacts\")","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# Render pointcloud, annotations and object proposals in 3D\ndef render_act_vs_pred_boxes_in_world(\n        points,\n        act_boxes,\n        pred_box_corners\n    ):\n        \n        # Assign colors to points\n        c = np.array([255, 158, 0]) / 255.0\n        df_tmp = pd.DataFrame(points, columns=[\"x\", \"y\", \"z\"])\n        df_tmp[\"norm\"] = np.sqrt(np.power(df_tmp[[\"x\", \"y\", \"z\"]].values, 2).sum(axis=1))\n        min_val = df_tmp[\"norm\"].min()\n        max_val = df_tmp[\"norm\"].max()\n        \n        df_tmp[\"norm\"] = (df_tmp[\"norm\"]-min_val)/(max_val-min_val)\n        rgb = np.array([colors.hsv_to_rgb([n, 0.4, 0.5]) for n in df_tmp[\"norm\"]]) * 255.0\n        \n        # Fetch points (with associated colors) for logging in W&B later\n        points_rgb = np.array([[p[0], p[1], p[2], c[0], c[1], c[2]] for p, c in zip(points, rgb)])\n\n        scatter = go.Scatter3d(\n            x=df_tmp[\"x\"],\n            y=df_tmp[\"y\"],\n            z=df_tmp[\"z\"],\n            mode=\"markers\",\n            marker=dict(size=1, color=df_tmp[\"norm\"], opacity=0.8),\n        )\n        \n        #wandb.init(anonymous=\"allow\")\n        # wandb.log({\"points\": wandb.Object3D(np.array(points))})\n        # Box Format in Lyft Dataset:\n        #       Boxes:  label: nan, score: nan, xyz: [2172.19, 989.22, -18.46], wlh: [2.08, 5.25, 1.97], rot axis: [0.00, 0.00, 1.00], ang(degrees): -31.70, ang(rad): -0.55, vel: nan, nan, nan, name: car, token: 0504e4480bc4e9aad8c6bd40f1f2311d57379f978201338bbf369f37f1e7b6d2 \n        # print(\"---------\\n\\nBoxes Shape: \", act_boxes.shape)\n        boxes = []\n        # Loop through boxes, fetch xyz coords, width, length, height, axis and rotation\n        for i, box in enumerate(act_boxes):\n            points = box.corners().tolist()\n            a_dict = {\n                        \"corners\": list(zip(*points)),\n                        #\"label\": \"box\",\n                        \"color\": [0,255,0],\n                    }\n            boxes.append(a_dict)\n            \n        for i, box in enumerate(pred_box_corners):\n            a_dict = {\n                        \"corners\": list(zip(*box.T.tolist())),\n                        #\"label\": \"box\",\n                        \"color\": [255,255,0],\n                    }\n            boxes.append(a_dict)\n        \n        boxes = np.array(boxes)\n        \n        # print(\"Points:\", points)\n        # print(\"\\n\\nBoxes: \", boxes,\"\\n\\n\")\n        \n        # Log points and boxes in W&B\n        artifact = wandb.Artifact(\"pointcloud_test_2\", \"dataset\")\n        obj3d = wandb.Object3D(\n                {\n                    \"type\": \"lidar/beta\",\n                    \"points\": points_rgb,\n                    \"boxes\": boxes\n                }\n            )\n        table = wandb.Table([\"Data\"], data=[[obj3d], [obj3d]])\n\n        artifact.add(table, \"table\")\n        \n        run = wandb.init(project=\"lyft-artifacts\")\n        run.log_artifact(artifact)\n        \n        \n        # Code to do the same thing as above in Plotly\n        x_lines = []\n        y_lines = []\n        z_lines = []\n\n        def f_lines_add_nones():\n            x_lines.append(None)\n            y_lines.append(None)\n            z_lines.append(None)\n\n        ixs_box_0 = [0, 1, 2, 3, 0]\n        ixs_box_1 = [4, 5, 6, 7, 4]\n\n        for box in act_boxes:\n            bpoints = view_points(box.corners(), view=np.eye(3), normalize=False)\n            x_lines.extend(bpoints[0, ixs_box_0])\n            y_lines.extend(bpoints[1, ixs_box_0])\n            z_lines.extend(bpoints[2, ixs_box_0])\n            f_lines_add_nones()\n            x_lines.extend(bpoints[0, ixs_box_1])\n            y_lines.extend(bpoints[1, ixs_box_1])\n            z_lines.extend(bpoints[2, ixs_box_1])\n            f_lines_add_nones()\n            for i in range(4):\n                x_lines.extend(bpoints[0, [ixs_box_0[i], ixs_box_1[i]]])\n                y_lines.extend(bpoints[1, [ixs_box_0[i], ixs_box_1[i]]])\n                z_lines.extend(bpoints[2, [ixs_box_0[i], ixs_box_1[i]]])\n                f_lines_add_nones()\n\n        lines = go.Scatter3d(x=x_lines, y=y_lines, z=z_lines, mode=\"lines\", name=\"lines\")\n        \n        cx_lines = []\n        cy_lines = []\n        cz_lines = []\n\n        def cf_lines_add_nones():\n            cx_lines.append(None)\n            cy_lines.append(None)\n            cz_lines.append(None)\n\n        cixs_box_0 = [0, 1, 2, 3, 0]\n        cixs_box_1 = [4, 5, 6, 7, 4]\n\n\n        for corners in pred_box_corners:\n            cpoints = view_points(corners.T, view=np.eye(3), normalize=False)\n            cx_lines.extend(cpoints[0, cixs_box_0])\n            cy_lines.extend(cpoints[1, cixs_box_0])\n            cz_lines.extend(cpoints[2, cixs_box_0])\n            cf_lines_add_nones()\n            cx_lines.extend(cpoints[0, cixs_box_1])\n            cy_lines.extend(cpoints[1, cixs_box_1])\n            cz_lines.extend(cpoints[2, cixs_box_1])\n            cf_lines_add_nones()\n            for i in range(4):\n                cx_lines.extend(cpoints[0, [cixs_box_0[i], cixs_box_1[i]]])\n                cy_lines.extend(cpoints[1, [cixs_box_0[i], cixs_box_1[i]]])\n                cz_lines.extend(cpoints[2, [cixs_box_0[i], cixs_box_1[i]]])\n                cf_lines_add_nones()\n\n        clines = go.Scatter3d(x=cx_lines, y=cy_lines, z=cz_lines, mode=\"lines\", name=\"clines\")\n\n        \n        fig = go.Figure(data=[scatter,lines,clines])\n        # fig = go.Figure(data=[scatter])\n        fig.update_layout(scene_aspectmode=\"data\")\n        fig.show()\n        \n        print(\"---------\\nDone\")","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"Note: The render_clustering() function is called at the end of this notebook to log point clouds to W&B."},{"metadata":{},"cell_type":"markdown","source":"## Helper Functions To Wrangle Lyft Data"},{"metadata":{"trusted":true},"cell_type":"code","source":"def get_sample_tokens(log_token):\n    scene_df =  pd.DataFrame(LYFT.scene)\n    scene_df =  scene_df[scene_df['log_token']==log_token]\n    scene_df.rename(columns={'token':'scene_token'}, inplace=True)\n\n    sample_df = pd.DataFrame(LYFT.sample)\n\n    s_df = pd.merge(sample_df, scene_df, left_on='scene_token', right_on='scene_token',how='inner')\n    s_df = s_df.iloc[:10]\n    return s_df['token']\n\n","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"sdf = pd.DataFrame(LYFT.scene)\nprint(len(sdf))\n\ntoken_ids = [x*18 for x in range(10)]\ntoken_ids[-1] -= 2\nm = sdf['log_token']\nprint(m[109])\n#for i, _id in enumerate(token_ids):\n    #print(\"scene_\" + str(i))\n    #print(m[])\n    #print(_id)\n\nSCENES = [\n    'da4ed9e02f64c544f4f1f10c6738216dcb0e6b0d50952e158e5589854af9f100',\n    '0580c08f0253a9b413c749c89d8a1966d84254f2812b198808964863e9ff5325',\n    '5f385237e9e39d0ec790f927ed56dfb88556c781361b7e0c09ca16874cd7a09b',\n    '8602e56b989742b61894014842a805c83f0adc60bf16a53d74599df79e1191d4',\n    'f6b2b1c59e388a5d6ad4dfc4d3955321c9a308088fc26f0beaca7379672492a5',\n    '0a59784804891232df2fdf2c556f0a4b5f02ff2bfbd5f00822f17b17320d457f',\n    '5f158f2069f5d61b9632659e565b7a1402386d7fa0b44776a9b3944480b48e96',\n    'bf92ccf96999b0432edec30bacaeb94805b607493e54f9097b80bee6ed1919c1',\n    '7e1a16bee39edf643a1fd4440ae6cd90a952deb5c0e9a5a2fc06d85dd2dd1b17',\n    '06257d5293de02fdf8d525d6c563ac308b6028e6fb43432b229ea4263d8fff38'\n]\n#['sample_token']\n#for a in m:\n#    print(a)\n\n#print(m[0])","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"wandb.init(project=\"lyft-artifacts\", name=\"lyft scene 5\")","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"scene_id = SCENES[5]\nwandb.config.update({\"log_token\" : scene_id})\n\n# Compute rough accuracy and mean IOU for given hyperparameters\ndef score_clustering(eps, min_samples):\n    # try another scene here\n    log_token = scene_id\n    #log_token = 'da4ed9e02f64c544f4f1f10c6738216dcb0e6b0d50952e158e5589854af9f100'\n    #log_token= '71dfb15d2f88bf2aab2c5d4800c0d10a76c279b9fda98720781a406cbacc583b'\n    tokens = get_sample_tokens(log_token)\n    tokens = tokens[:2]\n    batch_input = extract_data_for_clustering(tokens)\n    \n    ious = []\n    numcorrect = 0\n    total = 0\n    pred = 0\n    for sample_token in tokens:\n        token_input = batch_input[batch_input['sample_token'] == sample_token]\n        pointcloud, has_rows, proposals_df = identify_clusters(sample_token, token_input, DATA_PATH, eps=eps, min_samples=min_samples)\n        sampledata_token = token_input.iloc[0]['sampledata_token']\n        pred = pred + len(proposals_df)\n        boxes = LYFT.get_boxes(sampledata_token)\n        \n        for i  in range(len(boxes)):\n            total = total+1\n    \n            matches = 0\n            box = boxes[i]\n            act_corners = box.corners().T\n            for j in range(len(proposals_df)):\n                pred_corners = np.array(proposals_df.iloc[j]['corners'])\n                ioveru = iou(act_corners, pred_corners)\n                if ioveru > 0:\n                    matches = matches + 1\n                    ious.append(ioveru)\n            if (matches == 1):\n                numcorrect = numcorrect + 1\n            if (matches == 0):\n                ious.append(0)\n    print(\"eps:%.2f min_samples:%d -> correct:%d actual:%d  pred %d acc:%.4f mean-iou:%.4f max-iou:%.4f\"% (eps, min_samples , numcorrect, total, pred, numcorrect / total, np.mean(ious), np.max(ious))  )\n","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# Render points , actual and proposed bounding boxes in 3d \ndef render_clustering(eps, min_samples):\n    # try another scene here\n    log_token = scene_id\n    #log_token = 'da4ed9e02f64c544f4f1f10c6738216dcb0e6b0d50952e158e5589854af9f100'\n    #log_token= '71dfb15d2f88bf2aab2c5d4800c0d10a76c279b9fda98720781a406cbacc583b'\n    tokens = get_sample_tokens(log_token)\n    tokens = tokens[:2]\n    batch_input = extract_data_for_clustering(tokens)\n    sample_token = tokens[0]\n    token_input = batch_input[batch_input['sample_token'] == sample_token]\n    sampledata_token = token_input.iloc[0]['sampledata_token']\n    pointcloud, has_rows, proposals_df = identify_clusters(sample_token, token_input, DATA_PATH, eps=eps, min_samples=min_samples)\n    plt = render_act_vs_pred_boxes_in_world(pointcloud, LYFT.get_boxes(sampledata_token), proposals_df['corners'])\n    print(pointcloud)","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"## Render point clouds in W&B and in Plotly"},{"metadata":{"trusted":true},"cell_type":"code","source":"render_clustering(1,40)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"","execution_count":null,"outputs":[]}],"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":4,"nbformat_minor":4}