{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "d94621c9-dd17-4cab-a081-09b46e2bda97",
   "metadata": {},
   "source": [
    "# MAE experiments\n",
    "\n",
    "This notebook just experiments with the impact of rounding and accuracy on the MAE.\n",
    "\n",
    "To run it you may need to customise it - in my setup all the images are in the `unzip` directory and data files in the `data` directory. My local environmet looks like this\n",
    "- unzip\n",
    "  - planet-dec17\n",
    "    - ... lots of `png` images\n",
    "  - planet-dec18\n",
    "    - ... lots of `png` images\n",
    "  - planet-jun18\n",
    "    - ... lots of `png` images\n",
    "  - planet-jun18\n",
    "    - ... lots of `png` images\n",
    "  -sentinel\n",
    "    - ... lots of `tif` images\n",
    "- data\n",
    "  - auxilary_data_unique.csv\n",
    "  - extra_train.csv\n",
    "  - test.csv\n",
    "  - train-unique.csv\n",
    "\n",
    "## License\n",
    "\n",
    "MG Ferreira<br/>\n",
    "&copy; Ferra Solutions (Pty) Ltd https://www.ferrasolutions.com</br>\n",
    "Note that this is *copyrighted* material.\n",
    "\n",
    "You are welcome to use it to compete, but you can not publish this notebook elsewhere as if you created it, or use it in e.g. a lecture or as part of a paper or in some other setting without written permission from me.\n",
    "\n",
    "## Disclaimer\n",
    "\n",
    "This does not imply anything and is just a toy example to play with at your own risk."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "4f6d791f-57c1-4590-92e8-983771cb40e9",
   "metadata": {},
   "outputs": [],
   "source": [
    "import skimage.io\n",
    "import pandas     as pd\n",
    "import numpy      as np\n",
    "\n",
    "# Data paths - customise for your environment\n",
    "data_path = 'data'\n",
    "img_path  = 'unzip'"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "a39ffd6a-3941-4e06-9f03-58cb2ec68638",
   "metadata": {},
   "outputs": [],
   "source": [
    "# Some utilities, mostly taken from the starter or derived directly from info in the starter\n",
    "CONST_X    = 10.986328125 / 2\n",
    "CONST_Y    = 10.985731758 / 2\n",
    "\n",
    "# Load the training and auxilliary data\n",
    "def load_data ():\n",
    "\n",
    "    train = pd.read_csv ( f'{ data_path }/train-unique.csv' )\n",
    "    aux   = pd.read_csv ( f'{ data_path }/auxilary_data-unique.csv' )\n",
    "    extra = pd.read_csv ( f'{ data_path }/extra_train.csv' )\n",
    "\n",
    "    return pd.concat ( [ train, aux, extra ] )\n",
    "\n",
    "# Get image center in image pixels\n",
    "def img_center_pixels ( img ):\n",
    "\n",
    "    return img.shape [ 1 ] // 2, img.shape [ 0 ] // 2\n",
    "\n",
    "# Given an image and target coordinates, return the target location in image pixels\n",
    "def img_target_pixels ( img, tgtx, tgty ):\n",
    "\n",
    "    ctr = img_center_pixels ( img )\n",
    "\n",
    "    x1 = ctr [ 0 ] - np.round ( tgtx / CONST_X * img.shape [ 1 ] )\n",
    "    y1 = ctr [ 1 ] + np.round ( tgty / CONST_Y * img.shape [ 0 ] )\n",
    "\n",
    "    return int ( x1 ), int ( y1 )\n",
    "\n",
    "# Given an image, the image center and some location in pixels, return the target coordinates\n",
    "def img_pixels_target ( img, pixx, pixy ):\n",
    "\n",
    "    ctr = img_center_pixels ( img )\n",
    "\n",
    "    x   = CONST_X * float ( ctr [ 0 ] - pixx ) / float ( img.shape [ 1 ] )\n",
    "    y   = CONST_Y * float ( pixy - ctr [ 1 ] ) / float ( img.shape [ 0 ] )\n",
    "\n",
    "    return x, y\n",
    "\n",
    "# Supplied - load RGB image\n",
    "def load_RGB_images ( ID ):\n",
    "\n",
    "    # e.g id_0b242e06 -> 0b242e06\n",
    "    name      = ID.split('_')[1]\n",
    "\n",
    "    img_jun17 = skimage.io.imread ( f'{img_path}/planet-jun17/{name}.png' )\n",
    "    img_dec17 = skimage.io.imread ( f'{img_path}/planet-dec17/{name}.png' )\n",
    "    img_jun18 = skimage.io.imread ( f'{img_path}/planet-jun18/{name}.png' )\n",
    "    img_dec18 = skimage.io.imread ( f'{img_path}/planet-dec18/{name}.png' )\n",
    "\n",
    "    return img_jun17, img_dec17, img_jun18, img_dec18\n",
    "\n",
    "# Load the RGB mages and return them as a stack\n",
    "def load_rgb_stack ( ID ):\n",
    "\n",
    "    rgbs = load_RGB_images ( ID )\n",
    "    return np.concatenate ( [ rgbs [ 0 ], rgbs [ 1 ], rgbs [ 2 ], rgbs [ 3 ] ], axis = 2 )"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "d95b9e12-2afd-4a43-9524-6232aae0f2ae",
   "metadata": {},
   "outputs": [],
   "source": [
    "# Iterate through the data and report the perfectly accurate plot center\n",
    "# accurate to a pixel and then accurate to half a pixel\n",
    "\n",
    "data     = load_data ()\n",
    "mae      = 0.0\n",
    "mae_half = 0.0\n",
    "n        = 0\n",
    "\n",
    "for irow, row in data.iterrows ():\n",
    "\n",
    "    img      = load_rgb_stack ( row.ID )\n",
    "    px, py   = img_target_pixels ( img, row.x, row.y )\n",
    "    x, y     = img_pixels_target ( img, px, py )\n",
    "    xu, yu   = img_pixels_target ( img, px + 0.5, py + 0.5 )\n",
    "    xl, yl   = img_pixels_target ( img, px - 0.5, py - 0.5 )\n",
    "    mae      = mae + abs ( x - row.x ) + abs ( y - row.y )\n",
    "    mae_half = mae_half + min ( abs ( xu - row.x ), abs ( x - row.x ), abs ( xl - row.x ) ) \\\n",
    "                        + min ( abs ( yu - row.y ), abs ( y - row.y ), abs ( yl - row.y ) )\n",
    "    n        = n + 2\n",
    "\n",
    "mae      = mae      / n\n",
    "mae_half = mae_half / n\n",
    "\n",
    "print ( f\"MAE accurate to pixel      { mae }\" )\n",
    "print ( f\"MAE accurate to half pixel { mae_half }\" )"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "4b1344ea-7dec-426d-abab-57544f573fd1",
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "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.9.5"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
