{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "2dd23757-7cba-44b2-844a-5eff30aa513c",
   "metadata": {},
   "source": [
    "# *When* should you create an object?"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "23edffdb-a40e-4ef3-abf7-3c5a0bf2953b",
   "metadata": {},
   "source": [
    "## Complicated Data Structures (continued)\n",
    "\n",
    "Here is my solution to the previous problem."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "19700de0-83ff-4633-b321-8de9b096ea30",
   "metadata": {},
   "source": [
    "Now, let's define the object with a new `class`."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "1b1ad2f4-85ad-4583-88c4-d3faccfcf3d2",
   "metadata": {},
   "outputs": [],
   "source": [
    "class InstrumentData:\n",
    "    \"\"\"\n",
    "    This class defined the instrument data\n",
    "    \"\"\"\n",
    "    \n",
    "    def __init__(self, **data):\n",
    "        self.__data = data\n",
    "    \n",
    "    def get_time(self, var):\n",
    "        return [tpl[0] for tpl in self.__data[var]]\n",
    "\n",
    "    def get_variable(self, var):\n",
    "        return [tpl[1] for tpl in self.__data[var]]\n",
    "    \n",
    "    def integrate_trapezoid(self, var):\n",
    "        x, y = list(map(list, zip(*self.__data[var])))\n",
    "        return sum(0.5*(x[i] - x[i-1])*(y[i] + y[i-1]) for i in range(1, len(x)))"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "cecf81bf-935b-4dd9-8893-424ad03a1a20",
   "metadata": {},
   "source": [
    "And then let's rewrite the `read_instrument_data` function to work with this new class:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "eaad029e-9dfe-49e6-bccd-ae68d408d599",
   "metadata": {},
   "outputs": [],
   "source": [
    "def read_instrument_data(filename):\n",
    "    instrument_data = {}\n",
    "    with open(filename) as f:\n",
    "        for record in f:\n",
    "            var,time,value = record.split(',')\n",
    "            if var not in instrument_data:\n",
    "                instrument_data[var] = []\n",
    "            instrument_data[var].append((float(time), float(value)))\n",
    "    return InstrumentData(**instrument_data)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "57481674-622b-42a2-8ead-c516770003bf",
   "metadata": {},
   "source": [
    "And now we can an instance of the `InstrumentData` class:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "396f92b8-bcd7-49e5-8e4c-3cf121633c5d",
   "metadata": {},
   "outputs": [],
   "source": [
    "instrument_data = read_instrument_data('instrument1.csv')"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "c6fea16b-91ec-4bd6-a1be-4453604349c9",
   "metadata": {},
   "source": [
    "Let's try our this solution and compare with our previous results."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "7730905d-9774-45a6-b23a-f47f2932e6b1",
   "metadata": {},
   "outputs": [],
   "source": [
    "x = instrument_data.get_time('A')\n",
    "x"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "80b02172-940b-47a3-a119-da61361bec5f",
   "metadata": {},
   "outputs": [],
   "source": [
    "y = instrument_data.get_variable('A')\n",
    "y"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "3d7975a5-e732-41cc-aad6-1c9761884cb0",
   "metadata": {},
   "outputs": [],
   "source": [
    "instrument_data.integrate_trapezoid('A')"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "be48a845-2eda-4180-8b59-a8914d670a51",
   "metadata": {},
   "source": [
    "Looks correct!"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "a45a777a-b20d-4197-91ba-5ed27c7edea1",
   "metadata": {},
   "source": [
    "## Key Takeaway\n",
    "\n",
    "Together, the `read_instrument_data` function and the `InstrumentData` class work together to *hide* the structure of the data from the user.  Once the data is handed off to the object, the user never sees it again.  It is never passed *explicitly* between functions, and therefore there is no temptation to modify the data directly.  This is safer, and if you want to eventually let the user add to or modify the data, you can add functions to the *InstrumentData* class to allow that.  But the class itself controls how the user interacts with the data in a way that is (hopefully) more intuitive."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "9c0078c4-5f5c-4cc5-ad4b-31fb5865b817",
   "metadata": {},
   "source": [
    "|    |    |    |\n",
    "| :- | -- | -: |\n",
    "| [[Home]](../index.ipynb) | <img width=\"100%\" height=\"1\" src=\"../images/empty.png\"/> | [&laquo;&nbsp;Previous](07.ipynb)&nbsp;\\|&nbsp;[Next&nbsp;&raquo;](09.ipynb) |"
   ]
  }
 ],
 "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.9.7"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}