{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Pandora: a new stereo matching framework\n",
    "<img src=\"img/logo-cnes-triangulaire.jpg\" width=\"200\" height=\"200\">\n",
    "\n",
    "*Cournet, M., Sarrazin, E., Dumas, L., Michel, J., Guinet, J., Youssefi, D., Defonte, V., Fardet, Q., 2020. Ground-truth generation and disparity estimation for optical satellite imagery. ISPRS - International Archives of the Photogrammetry, Remote Sensing and Spatial Information Sciences.*"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Analysis demo"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Imports and external functions"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "import os\n",
    "import matplotlib.pyplot as plt\n",
    "import numpy as np\n",
    "import rasterio\n",
    "from pathlib import Path\n",
    "from IPython.display import Image\n",
    "import copy\n",
    "import xarray as xr"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "import bokeh.plotting as bpl\n",
    "from bokeh.plotting import figure\n",
    "from bokeh.layouts import row, column\n",
    "from bokeh.models import ColorBar, BasicTicker, LinearColorMapper, Legend\n",
    "from bokeh.io import show, output_notebook\n",
    "from jupyter_dash import JupyterDash\n",
    "from dash import dcc, html"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Imports of custom functions for visualization"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from snippets.utils import *"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Imports of pandora "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Load pandora imports\n",
    "import pandora\n",
    "from pandora.img_tools import create_dataset_from_inputs, get_metadata\n",
    "from pandora.check_configuration import check_pipeline_section, concat_conf, get_config_pipeline, check_datasets\n",
    "from pandora.state_machine import PandoraMachine\n",
    "from pandora import import_plugin, check_conf"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "(Optional) If Pandora plugins are to be used, import them"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Available Pandora Plugins include :\n",
    "- MC-CNN Matching cost computation\n",
    "- SGM Optimization"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 1. Load plugins, input images and ground truth"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Import installed plugins"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Load plugins\n",
    "import_plugin()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Provide output directory to write results"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "output_dir = os.path.join(os.getcwd(),\"output\")\n",
    "# If necessary, create output dir\n",
    "Path(output_dir).mkdir(exist_ok=True,parents=True)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Provide input data"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Paths to left and right images\n",
    "img_left_path = \"data/Cones_LEFT.tif\"\n",
    "img_right_path = \"data/Cones_RIGHT.tif\"\n",
    "# Paths to masks (None if not provided)\n",
    "left_mask_path = None\n",
    "right_mask_path = None\n",
    "# No data\n",
    "no_data_left = np.nan\n",
    "no_data_right = np.nan"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Read input data and convert to dataset"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "input_config = {\n",
    "    \"left\": {\"img\": img_left_path, \"mask\": left_mask_path, \"disp\": [-60, 0], \"nodata\": no_data_left},\n",
    "    \"right\": {\"img\": img_right_path, \"mask\": right_mask_path, \"disp\": None, \"nodata\": no_data_right},\n",
    "}"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "img_left = create_dataset_from_inputs(input_config=input_config[\"left\"])\n",
    "img_right = create_dataset_from_inputs(input_config=input_config[\"right\"])"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Check datasets: shape, format and content"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "check_datasets(img_left, img_right)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Visualize input data"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "show_input_images(img_left, img_right)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Load ground truth if available"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# If occlusion mask exists, adapt it to Pandora's convention before creating the ground_truth\n",
    "# Masks known valid value. If None, the lowest value in the mask will be considered \n",
    "valid_value = 1\n",
    "adapted_mask_path = adapt_occlusion_mask(mask_path = \"data/Occlusion_LEFT.png\", output_dir = output_dir, valid_value = valid_value, title = \"adapted_occlusion_mask\")\n",
    "\n",
    "# Read image of ground_thruth\n",
    "ground_truth_input_config = {\"img\": \"data/Cones_LEFT_GT.tif\", \"nodata\": np.inf, \"mask\": adapted_mask_path, \"disp\":[-60, 0]}\n",
    "ground_truth = create_dataset_from_inputs(input_config=ground_truth_input_config)\n",
    "# Convert disparity map to Pandora's convention\n",
    "ground_truth[\"disparity_map\"] = xr.DataArray(np.copy(ground_truth.im),dims=['row', 'col'])\n",
    "ground_truth[\"disparity_map\"].values = - ground_truth[\"disparity_map\"].values\n",
    "ground_truth[\"validity_mask\"] = xr.DataArray(np.copy(ground_truth.msk),dims=['row', 'col'])\n",
    "ground_truth[\"validity_mask\"].values = np.zeros(ground_truth[\"msk\"].values.shape, dtype = int)\n",
    "inv_idx = np.where(ground_truth[\"msk\"].values != 0)\n",
    "ground_truth[\"validity_mask\"].values[inv_idx] = pandora.constants.PANDORA_MSK_PIXEL_OCCLUSION"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Visualize ground truth"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "The different types of masks can be selected for visualization"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "plot_disparity(ground_truth)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 1. Run Pandora and analyze output disparity and statistics"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Define pipeline for Zncc matching cost "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "user_cfg_zncc = {\n",
    "    'input': {\n",
    "        \"left\": {\n",
    "            \"img\": img_left_path,\n",
    "            \"disp\": [-60, 0],\n",
    "            \"mask\": left_mask_path,\n",
    "        },\n",
    "        \"right\": {\n",
    "            \"img\": img_right_path,\n",
    "            \"mask\": right_mask_path\n",
    "        }\n",
    "    },\n",
    "    'pipeline': { \n",
    "        'matching_cost': {'matching_cost_method': 'zncc', 'window_size': 5, 'subpix': 1},\n",
    "        'disparity': {'disparity_method':'wta', \"invalid_disparity\": \"NaN\"},\n",
    "        'refinement': {'refinement_method': 'vfit'},\n",
    "        'validation': {'validation_method': 'cross_checking_accurate'},\n",
    "    }\n",
    "}"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Instantiate and run the machine with the configuration"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "pandora_machine = PandoraMachine()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "disp_min = user_cfg_zncc[\"input\"][\"left\"][\"disp\"][0]\n",
    "disp_max = user_cfg_zncc[\"input\"][\"left\"][\"disp\"][1]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "metadata_left = get_metadata(user_cfg_zncc[\"input\"][\"left\"][\"img\"], (disp_min, disp_max))\n",
    "metadata_right = get_metadata(user_cfg_zncc[\"input\"][\"right\"][\"img\"], disparity=None)\n",
    "user_cfg_pipeline = get_config_pipeline(user_cfg_zncc)\n",
    "cfg_pipeline_zncc = check_pipeline_section(user_cfg_pipeline, metadata_left, metadata_right, pandora_machine)['pipeline']"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "pandora_machine.run_prepare(user_cfg_zncc, img_left, img_right, disp_min, disp_max)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "left_disp_zncc, right_disp_zncc = pandora.run(pandora_machine, img_left, img_right, user_cfg_zncc)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Visualize output disparity "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "plot_disparity(left_disp_zncc)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Visually compare the disparity map with the ground truth"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "compare_2_disparities(left_disp_zncc, \"Disparity map Zncc\", ground_truth, \"Ground Truth\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Obtain error and statistics between the disparity map and the ground truth at a given threshold "
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Statistics are computed as defined in D. Scharstein and R. Szeliski. A taxonomy and evaluation of dense two-frame stereo correspondence algorithms.\n",
    "International Journal of Computer Vision, 47(1/2/3):7-42, April-June 2002.\n",
    "Microsoft Research Technical Report MSR-TR-2001-81, November 2001, part 5.1 Evaluation methodology, pp 11. "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "threshold = 1\n",
    "error_zncc, total_bad_percentage, mean_error, std_error, invalid_percentage = get_error(left_disp_zncc, ground_truth, threshold)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "print(\"Threshold = {}\".format(threshold))\n",
    "print(\"Total bad error point percentage = {:.2f}\".format(total_bad_percentage))\n",
    "print(\"Mean error = {:.2f}\".format(mean_error))\n",
    "print(\"Std error = {:.2f}\".format(std_error))\n",
    "print(\"Invalid point percentage = {:.2f}%\".format(invalid_percentage))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Visualize disparity map and its error at a given threhold"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "compare_disparity_and_error(left_disp_zncc, \"Disparity map Zncc\", error_zncc, \"Error with threshold 1\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 2. Run Pandora step by step and analyze intermediate results"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Define pipeline for Census matching cost and SGM optimization"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "user_cfg_census_sgm = {\n",
    "    'input': {\n",
    "        \"left\": {\n",
    "            \"img\": img_left_path,\n",
    "            \"disp\": [-60, 0],\n",
    "            \"mask\": left_mask_path,\n",
    "        },\n",
    "        \"right\": {\n",
    "            \"img\": img_right_path,\n",
    "            \"mask\": right_mask_path\n",
    "        }\n",
    "    },\n",
    "    'pipeline': { \n",
    "        'matching_cost': {'matching_cost_method': 'census', 'window_size': 5, 'subpix': 1},\n",
    "        'optimization' : {'optimization_method': 'sgm'},\n",
    "        'disparity': {'disparity_method':'wta', \"invalid_disparity\": \"NaN\"},\n",
    "        'filter': {'filter_method': 'median'},\n",
    "        'refinement': {'refinement_method': 'vfit'},\n",
    "        'validation': {'validation_method': 'cross_checking_accurate'},\n",
    "    }\n",
    "}"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Instantiate and run the machine with the configuration"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "pandora_machine = PandoraMachine()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "disp_min = user_cfg_census_sgm[\"input\"][\"left\"][\"disp\"][0]\n",
    "disp_max = user_cfg_census_sgm[\"input\"][\"left\"][\"disp\"][1]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "metadata_left = get_metadata(user_cfg_census_sgm[\"input\"][\"left\"][\"img\"], (disp_min, disp_max))\n",
    "metadata_right = get_metadata(user_cfg_census_sgm[\"input\"][\"right\"][\"img\"], disparity=None)\n",
    "user_cfg_pipeline = get_config_pipeline(user_cfg_census_sgm)\n",
    "cfg_pipeline_census_sgm = check_pipeline_section(user_cfg_pipeline, metadata_left, metadata_right, pandora_machine)['pipeline']"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "pandora_machine.run_prepare(user_cfg_census_sgm, img_left, img_right)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Run matching cost"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "pandora_machine.run('matching_cost', user_cfg_census_sgm)\n",
    "left_cv_census = copy.deepcopy(pandora_machine.left_cv)\n",
    "right_cv_census = copy.deepcopy(pandora_machine.right_cv)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Run optimization"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "pandora_machine.run('optimization', user_cfg_census_sgm)\n",
    "left_cv_census_sgm = copy.deepcopy(pandora_machine.left_cv)\n",
    "right_cv_census_sgm = copy.deepcopy(pandora_machine.right_cv)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Run disparity"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "pandora_machine.run('disparity', user_cfg_census_sgm)\n",
    "left_disparity_map_census_sgm = copy.deepcopy(pandora_machine.left_disparity)\n",
    "right_disparity_map_census_sgm = copy.deepcopy(pandora_machine.right_disparity)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Visualize Census cost volume with optimization"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Warning : cost volume may take a long time to appear (30s)\n",
    "plot_1_cost_volume(left_cv_census_sgm, left_disparity_map_census_sgm, \"Cost volume with Census matching cost and SGM optimization\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Run filter"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "pandora_machine.run('filter', user_cfg_census_sgm)\n",
    "left_disparity_map_census_sgm_filtered = copy.deepcopy(pandora_machine.left_disparity)\n",
    "right_disparity_map_census_sgm_filtered = copy.deepcopy(pandora_machine.right_disparity)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Visualize disparity map before and after filter"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "compare_2_disparities(left_disparity_map_census_sgm, \"Disparity map Census SGM\", left_disparity_map_census_sgm_filtered, \"Disparity map Census SGM filtered\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Run refinement"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "pandora_machine.run('refinement', user_cfg_census_sgm)\n",
    "left_disparity_map_census_sgm_refined = copy.deepcopy(pandora_machine.left_disparity)\n",
    "right_disparity_map_census_sgm_refined = copy.deepcopy(pandora_machine.right_disparity)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Visualize disparity map before and after refinement"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "compare_2_disparities(left_disparity_map_census_sgm_filtered, \"Disparity map Census SGM\", left_disparity_map_census_sgm_refined, \"Disparity map Census SGM refined\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Run validation"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "pandora_machine.run('validation', user_cfg_census_sgm)\n",
    "left_disparity_map_census_sgm_validated = copy.deepcopy(pandora_machine.left_disparity)\n",
    "right_disparity_map_census_sgm_validated = copy.deepcopy(pandora_machine.right_disparity)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Visualize disparity map before and after validation"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "compare_2_disparities(left_disparity_map_census_sgm_filtered, \"Disparity map Census SGM\", left_disparity_map_census_sgm_validated, \"Disparity map Census SGM after validation\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Obtain error and statistics between the disparity map and the ground truth at a given threshold "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "threshold = 1\n",
    "error_census_sgm, total_bad_percentage, mean_error, std_error, invalid_percentage = get_error(left_disparity_map_census_sgm, ground_truth, threshold)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Visualize 3 chosen disparity maps and one error map at a given threhold"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "compare_3_disparities_and_error(left_disparity_map_census_sgm, \"Disparity map Census SGM after disparity step\", left_disparity_map_census_sgm_validated, \"Disparity map Census SGM after validation\", ground_truth, \"Ground truth\", error_census_sgm, \"Error Census SGM after validation, threshold 1\",)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 2.1 To see the effect of SGM optimization, define pipeline for Census matching cost WITHOUT SGM optimization"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "user_cfg_census = {\n",
    "    'input': {\n",
    "        \"left\": {\n",
    "            \"img\": img_left_path,\n",
    "            \"disp\": [-60, 0],\n",
    "            \"mask\": left_mask_path,\n",
    "        },\n",
    "        \"right\": {\n",
    "            \"img\": img_right_path,\n",
    "            \"mask\": right_mask_path,\n",
    "        }\n",
    "    },\n",
    "    'pipeline': {\n",
    "        'matching_cost': {'matching_cost_method': 'census', 'window_size': 5, 'subpix': 1},\n",
    "        'disparity': {'disparity_method':'wta', \"invalid_disparity\": \"NaN\"},\n",
    "        'filter': {'filter_method': 'median'},\n",
    "        'refinement': {'refinement_method': 'vfit'},\n",
    "        'validation': {'validation_method': 'cross_checking_accurate'},\n",
    "    }\n",
    "}"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Instantiate and run the machine with the configuration"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "pandora_machine = PandoraMachine()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "disp_min = user_cfg_census[\"input\"][\"left\"][\"disp\"][0]\n",
    "disp_max = user_cfg_census[\"input\"][\"left\"][\"disp\"][1]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "metadata_left = get_metadata(user_cfg_census[\"input\"][\"left\"][\"img\"], (disp_min, disp_max))\n",
    "metadata_right = get_metadata(user_cfg_census[\"input\"][\"right\"][\"img\"], disparity=None)\n",
    "user_cfg_pipeline = get_config_pipeline(user_cfg_census)\n",
    "cfg_pipeline_census = check_pipeline_section(user_cfg_pipeline, metadata_left, metadata_right, pandora_machine)['pipeline']"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "pandora_machine.run_prepare(user_cfg_census, img_left, img_right)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Run matching cost"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "pandora_machine.run('matching_cost', user_cfg_census)\n",
    "left_cv_census = copy.deepcopy(pandora_machine.left_cv)\n",
    "right_cv_census = copy.deepcopy(pandora_machine.right_cv)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Run disparity"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "pandora_machine.run('disparity', user_cfg_census)\n",
    "left_disparity_map_census = copy.deepcopy(pandora_machine.left_disparity)\n",
    "right_disparity_map_census = copy.deepcopy(pandora_machine.right_disparity)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Compare Census cost volume without and with optimization"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Cost volume from current pipeline without optimization\n",
    "cv_census = get_3D_cost_volume(left_cv_census, left_disparity_map_census)\n",
    "# Cost volume from previous pipeline with SGM optimization\n",
    "cv_census_sgm = get_3D_cost_volume(left_cv_census_sgm, left_disparity_map_census_sgm)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "external_stylesheets = ['https://codepen.io/chriddyp/pen/bWLwgP.css']\n",
    "app = JupyterDash(__name__, external_stylesheets=external_stylesheets)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# This check is necessary for the notebooks_tests \n",
    "if app is not None:\n",
    "    app.layout = html.Div(children=[\n",
    "        html.Div([\n",
    "            html.Div([\n",
    "                html.Div(children='''\n",
    "                    Cost volume from current pipeline without optimization.\n",
    "                '''),\n",
    "                dcc.Graph(\n",
    "                    id='graph1',\n",
    "                    figure=cv_census,\n",
    "                    style={'width': '100vh', 'height': '100vh'}\n",
    "                ),  \n",
    "            ], className=\"six columns\"),\n",
    "            html.Div([\n",
    "                html.Div(children='''\n",
    "                    Cost volume from previous pipeline with SGM optimization\n",
    "                '''),\n",
    "                dcc.Graph(\n",
    "                    id='graph2',\n",
    "                    figure=cv_census_sgm,\n",
    "                    style={'width': '100vh', 'height': '100vh'}\n",
    "                ),  \n",
    "            ], className=\"six columns\"),\n",
    "        ], className = 'row'),\n",
    "    ])"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### Unfortunately, the following function does not work with Binder, given the current network incompatibilities between Binder-Jupyter-Bokehserver. \n",
    "\n",
    "#### To do so, please run the notebook locally."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# This check is necessary for the notebooks_tests \n",
    "if app is not None:\n",
    "    app.run_server(mode='inline', debug=True)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Run filter"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "pandora_machine.run('filter', user_cfg_census)\n",
    "left_disp_map_census_filtered = copy.deepcopy(pandora_machine.left_disparity)\n",
    "right_disp_map_census_filtered = copy.deepcopy(pandora_machine.right_disparity)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Run refinement"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "pandora_machine.run('refinement', user_cfg_census)\n",
    "left_disp_map_census_refined = copy.deepcopy(pandora_machine.left_disparity)\n",
    "right_disp_map_census_refined = copy.deepcopy(pandora_machine.right_disparity)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Run validation"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "pandora_machine.run('validation', user_cfg_census)\n",
    "left_disp_map_census_validated = copy.deepcopy(pandora_machine.left_disparity)\n",
    "right_disp_map_census_validated = copy.deepcopy(pandora_machine.right_disparity)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Compare disparity map without and with optimization"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Disparity map from current pipeline without optimization and disparity map from previous pipeline\n",
    "\n",
    "compare_2_disparities(left_disp_map_census_validated, \"Disparity map Census\", left_disparity_map_census_sgm_validated, \"Disparity map Census with SGM optimization\")"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3 (ipykernel)",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.8.5"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 4
}