{ "cells": [ { "cell_type": "markdown", "metadata": { "input_collapsed": false }, "source": [ "# Exporting Burst Data\n", "\n", "*This notebook is part of a [tutorial series](https://github.com/OpenSMFS/FRETBursts_notebooks) for the [FRETBursts](http://opensmfs.github.io/FRETBursts/) burst analysis software.*" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "> In this notebook, show a few example of how to export [FRETBursts](http://opensmfs.github.io/FRETBursts/) \n", "> burst data to a file.\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "
\n", "Please cite FRETBursts in publications or presentations!\n", "
" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# Loading the software" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We start by loading **`FRETBursts`**:" ] }, { "cell_type": "code", "execution_count": 1, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ " - Optimized (cython) burst search loaded.\n", " - Optimized (cython) photon counting loaded.\n", "--------------------------------------------------------------\n", " You are running FRETBursts (version 0.7+46.ge31fadb.dirty).\n", "\n", " If you use this software please cite the following paper:\n", "\n", " FRETBursts: An Open Source Toolkit for Analysis of Freely-Diffusing Single-Molecule FRET\n", " Ingargiola et al. (2016). http://dx.doi.org/10.1371/journal.pone.0160716 \n", "\n", "--------------------------------------------------------------\n" ] } ], "source": [ "from fretbursts import *" ] }, { "cell_type": "code", "execution_count": 2, "metadata": {}, "outputs": [], "source": [ "sns = init_notebook()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# Downloading the data file" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The full list of smFRET measurements used in the [FRETBursts tutorials](https://github.com/OpenSMFS/FRETBursts_notebooks) \n", "can be found on [Figshare](http://dx.doi.org/10.6084/m9.figshare.1456362).\n", "\n", "This is the file we will download:" ] }, { "cell_type": "code", "execution_count": 3, "metadata": {}, "outputs": [], "source": [ "url = 'http://files.figshare.com/2182601/0023uLRpitc_NTP_20dT_0.5GndCl.hdf5'" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "
\n", "You can change the url variable above to download your own data file.\n", "This is useful if you are executing FRETBursts online and you want to use\n", "your own data file. See \n", "First Steps.\n", "
\n", "\n", "Here, we download the data file and put it in a folder named `data`, \n", "inside the notebook folder:" ] }, { "cell_type": "code", "execution_count": 4, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "URL: http://files.figshare.com/2182601/0023uLRpitc_NTP_20dT_0.5GndCl.hdf5\n", "File: 0023uLRpitc_NTP_20dT_0.5GndCl.hdf5\n", " \n", "File already on disk: /home/paul/Disk/Python/OpenSMFS/FRETBursts_notebooks/notebooks/data/0023uLRpitc_NTP_20dT_0.5GndCl.hdf5 \n", "Delete it to re-download.\n" ] } ], "source": [ "download_file(url, save_dir='./data')" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "> **NOTE**: If you modified the `url` variable providing an invalid URL\n", "> the previous command will fail. In this case, edit the cell containing \n", "> the `url` and re-try the download." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# Loading the data file" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Here, we can directly define the file name to be loaded:" ] }, { "cell_type": "code", "execution_count": 5, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "'./data/0023uLRpitc_NTP_20dT_0.5GndCl.hdf5'" ] }, "execution_count": 5, "metadata": {}, "output_type": "execute_result" } ], "source": [ "filename = \"./data/0023uLRpitc_NTP_20dT_0.5GndCl.hdf5\"\n", "filename" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Let's check that the file exists:" ] }, { "cell_type": "code", "execution_count": 6, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Perfect, file found!\n" ] } ], "source": [ "import os\n", "if os.path.isfile(filename):\n", " print(\"Perfect, file found!\")\n", "else:\n", " print(\"Sorry, file:\\n%s not found\" % filename)" ] }, { "cell_type": "code", "execution_count": 7, "metadata": {}, "outputs": [], "source": [ "d = loader.photon_hdf5(filename)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# μs-ALEX parameters\n", "\n", "At this point, timestamps and detectors numbers are contained in the `ph_times_t` and `det_t` attributes of `d`. Let's print them:" ] }, { "cell_type": "code", "execution_count": 8, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "([array([ 146847, 188045, 294124, ..., 47999863658,\n", " 47999877783, 47999955353])],\n", " [array([0, 1, 1, ..., 1, 1, 0], dtype=uint32)])" ] }, "execution_count": 8, "metadata": {}, "output_type": "execute_result" } ], "source": [ "d.ph_times_t, d.det_t" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We need to define some ALEX parameters: " ] }, { "cell_type": "code", "execution_count": 9, "metadata": {}, "outputs": [], "source": [ "d.add(det_donor_accept = (0, 1), \n", " alex_period = 4000,\n", " offset = 700,\n", " D_ON = (2180, 3900), \n", " A_ON = (200, 1800))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Here the parameters are:\n", "\n", "- `det_donor_accept`: donor and acceptor channels\n", "- `alex_period`: length of excitation period (in timestamps units)\n", "- `D_ON` and `A_ON`: donor and acceptor excitation windows\n", "- `offset`: the offset between the start of alternation and start of timestamping \n", " (see also [Definition of alternation periods](http://photon-hdf5.readthedocs.org/en/latest/phdata.html#definition-of-alternation-periods)).\n", "\n", "To check that the above parameters are correct, we need to plot the histogram of timestamps (modulo the alternation period) and superimpose the two excitation period definitions to it:" ] }, { "cell_type": "code", "execution_count": 10, "metadata": {}, "outputs": [ { "data": { "image/png": "iVBORw0KGgoAAAANSUhEUgAAAzkAAAG8CAYAAAD98GtbAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjUuMiwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy8qNh9FAAAACXBIWXMAAA9hAAAPYQGoP6dpAACPFElEQVR4nOzdeXwTZf4H8M9M0iO9ixyVFqioLQoFyuFB4adYEMHSIlgUpFZEERFFYBdBlxVBDg9kpYggK8cWUbBFFhAErcAqq1D3VQSroshZpS1HSs8kTWZ+f5SMTZOWJE2aNnzerxemfeaZZ54nkzHz7XOMIMuyDCIiIiIiIi8heroCRERERERErsQgh4iIiIiIvAqDHCIiIiIi8ioMcoiIiIiIyKswyCEiIiIiIq/CIIeIiIiIiLwKgxwiIiIiIvIqDHKIiIiIiMirMMghIiIiIiKvovZ0BbyBLMuQJNnl5Yqi4JZyIcuQjdWA7IayHSAAEEQBsiTDszVxD7avKSsjQFD7AILg8qJdeR3KsoxqqRoyJJeU5wrmc+jNvL2NLbF9AkT4iD4Q7Lhm3fVdKIqCXccnopaJQY4LSJKMS5cqXFqmWi0iPDwQpaWVMBpde0Mk63WQj/0A+KgBtY9Ly3aEShQREuKP0lIdTFLzuelzFbaviRirgWojhNhuEPz8XVq0q69DnUmHIxfz4CP6wEf03LVnJqpEBIf4o6xUB8nkfZ9RwPvb2BLbVy1Vo1qqRvfr4uGvaviaded3YatWgVCpGOQQeSsGOdcytQ8EH1+PHV5QiRB8/SD4ShBayJezI9i+piEDQLXRY8d3ho/oA1+Vn6erAZVKhJ/KDwaVDFMz6l1yJW9vY0ttX7VU7ekqEJGX45wcIiIiIiLyKgxyiIiIiIjIqzDIISIiIiIir8Igh4iIiIiIvAqDHCIiIiIi8ioMcoiIiIiIyKswyCEiIiIiIq/CIIeIiIiIiLwKgxwiIiIiIvIqDHKIiIiIiMirMMghIiIiIiKvwiCHiIiIiIi8CoMcIiIiIiLyKmpPV4Bcy/TWHKC0xHpDSBhU0+c3eX2IiIiIiJqaQ0HOyZMnsW3bNhw4cABnzpyBXq9Hx44dcd999yE9PR0BAQEW+S9cuIAlS5Zg//79KCsrQ3R0NNLS0jB69Gib5e/YsQNr1qzB8ePHodFokJCQgBkzZiAyMtIqrzvLbtFKS4DLWk/XgoiIiIjIYxwKcrKzs/HBBx9g4MCBSEpKgo+PDw4ePIh//OMf2LVrFzZv3gx/f38AQGlpKcaOHYuioiKkp6cjKioKOTk5mDNnDoqLizFlyhSLsjds2ID58+ejV69emD17NrRaLdavX4/c3FxkZWWhXbt2Sl53lu01RAEIDgPKSgBJ9nRtiIiIiIiajENBzpAhQzBx4kSEhIQoaWPGjEGnTp2wcuVKZGdn45FHHgEArF69GqdPn0ZGRgbuvfdeAMDo0aMxadIkrFy5EikpKejQoQMAQKvVYsmSJejatSsyMzOhVtdUa8CAAUhNTcWyZcuwYMEC5ZjuLNtrBIdBNTcDprnPsmeHiIiIiK4pDi08EBcXZxHgmA0dOhQAcOzYMSVt+/btiIqKUoIQs/Hjx6O6uhq7du1S0nJyclBZWYm0tDQlCDEfr2/fvti1axcMBkOTlE22SR+8C+m9N2z/++BdT1ePiIiIiEjhkoUHioqKAADXXXcdAOD8+fM4d+4ckpKSrPLGx8dDEAQcOXJESTP/HB8fbzP/oUOHcOLECXTp0sWtZV+rpA/eBSrKbW8MDIL4yNM128tLm7ZiREREREROaHSQYzKZsGLFCqjVagwfPhzAn0FPRESEVX5fX1+Eh4ejsLBQSSsuLq43v3m+TFFREbp06eLWshtDrXbtatwqlWjxaovhjZesV1IruwwIgCDU1EkSALnW7wBgWDIf8vlCQBAhi0LDwYtQUwdJqPkZgggEBtVsqygHZEnJ43gbhVqv3reaOdvXNGSTCKhFiGoRggeuQ0eoIUKlFiGqRJeV2RiiKNR69Xx93MHb29gS2ydChAoi1Crxqt+drr4Gieja0egg59VXX8Xhw4fx/PPPo3PnzgAAnU4HoCbosMXPz0/JAwBVVVX15vfz87PI486ynSWKAsLDAxtVRn1CQjT1brtQUQqprMQiTRBq/iOqRISHB+KCSoQk/vk7AFyoLIOpsqIms2DeqYYYHAoAkMvLIMsSRFFESIgGJaIISRAgBocg7C9/BwCUvDkPUtllCJUVkN57o1YZwQh5aprdbQwM9Lc7b0vE9rmXbBAhVcnwCwuE4O+eujR0HTqiyigiyOCPAB9/+Kn8XFKmKwQGNZ+6uIu3t7Eltc/XJEBVLSEsPAAatX3XlquuQSK6djQqyFm6dCk2btyI1NRUTJo0SUk3r7BW31wXnU6H1q1bK79rNBolv3+dmxS9Xm+Rx51lO0uSZJSWVjaqjLpUqprgorS0CiaTZDOPySRBlmRAECGEhFpuCwyBVluh5JFNErTaij/3k+Wa4CYwWNlHCAyGmDYZAFC98jWgvBSmslJcfH3ulV4bGSZJQmlpTVBokiRAliHLJosepdp5Gm6jgMBAf1RU6GAyed8KcGxf05ANBkCvQ2VJBQQ/k0vLtuc6dITOqEN5uQ4mlQiDyvOfCVEUEBjkh4pyPSQvXYXR29vYEtunN+lRZdKhxLcSOnXD15Wrr8HaQkI07CEi8mJOBzkZGRlYuXIlRowYgXnz5kGo1RtgHgZWe9iYmV6vR0lJCfr06aOktW3bVskfHR1tkd88PM1cpjvLbgyj0bX/8zUzmaR6y5ZlADKAkFCIL2fYrJM5jyz/WUdZvvJFGBAE8cm/Wh2vJpP5nwSU1RrOJtfKExBUk8esoqzmQLXzNEi8ckzZ4S8vu+YReZzz7WsZmkf7ZEkCjBIkowRB1fTXoSOMJgkmowQJEkxoDp+JmnMoSd76GQW8v40tr33SlevAaJJgtPM6cNU1SETXDqeCnOXLl2P58uVITk7GokWLIIqWfwlp06YNIiIicPjwYat9Dx8+DFmWERcXp6TFxcVh06ZNyMvLswpE8vLyEBAQoAyFc2fZXq2spGY5aaBm3s7VmOfdNJBeN5CQ3nujZn5PRZnF8DXzfi4NPFy0EELLCJaosUxvzbGev2YWEgbV9PlNWh8iIiJyL4eDnOXLlyMjIwPDhw/H4sWLrQIcs6SkJPzzn//Enj17LJZ6Xrt2LdRqNYYNG6akJSYmYsGCBcjMzMTw4cOVpZ6PHj2K3NxcjBw50mJOjTvL9lqSXOt5OVcf0tCom3tZtg5AykstA5/AIKgefcb5Y5jVHnJn7km6gqvGkaK0hM+LIiIiuoY4FOR88MEHyMjIQPv27ZGQkIAdO3ZYbG/dujUSEhIAABMnTsTu3bsxc+ZM5OfnIyoqCjk5Odi7dy8mT56sPKwTAFq1aoVp06Zh4cKFSEtLQ0pKCrRaLdatW4fWrVtj6tSpFsdxZ9leJyTMOk2WAJ0OCHDxYgm2en9qBxDuCCYCgyFOrBlyp/QkmTkSwDQQLJEXEQUgOKzm57KSmuCfiIiIvI5DQc7Ro0cBAH/88QdmzZpltf22225TgpzQ0FBs3LgRS5cuxebNm1FeXo5OnTph7ty5GDNmjNW+6enpCA8Px9q1a7Fw4UJoNBr069cP06dPt5oz486yvY2tYTiyXgf52A9AIxdcqMtW749Vb4o5gKgoQ/XK11AiilcWMIDrhoeZh8tVlNX8bk8A01CwZEO9vUQOtsFV5ZCdgsOgmlszf80091n27hAREXkph4KcxYsXY/HixXbnb9u2LRYtWmR3/uTkZCQnJ3u8bHKdeuftXBnSJgmCsliBkqehYWZm5gDGlrrD5RwMYOxSXy9RrWF5koCapbc1gRDGTrLO21A5V2FPcMQAioiIiK5VjX5ODpFDag9pEwBRFGEqK60ZQmfm7DwZOxZLcDlzL5GtYXkCIAkCZEmCYHtv63LsHSpnz3vE+UZERER0jWKQQ02qdg+C+fkHF1+fW7NMdUPDzOrTwGpvDap7LGdd6SWy2WtSWY7aXVQ285iPby7H0Z4me4IjRwMoIiIiohaOQQ41Hw0MM3P7sWyxtRR2rW212ZyPtPpKEFVR3qhhco0Ojurmaahdyj5XH/YmBwUDz8xwtDkKu4Yl2qiPVT0+Wg2Ul0H29weEOqs9cnloIiKiaxKDHPI4ITDYdgeDO4aZOTKkzZ5AyB6yZF1OUIh99QIcG3ZWO4Cpr5fK0XbVc3y51hg8pwIWVw2nq6yo6TUz6ICrDwwkIiKiawCDHPI4ddrkJntSt11D2hwJrhrIKwQG18w5Mq8eV2sfpyb+2xq+V/f4DQUw9rTL2WFvjQlYGhqWaONYVgFVZfmf5YSE1/xsXh7a/BDcshLn6kZEREQtEoMcojpctfKYOm0yQkI0KC2tck0Q19DwvYYCmCvb7GmXzSFtjgyNczBgqV1ug/WxKKeegCo41Hp5aIuH4BIREdG1gkEOUXNkz7CzWly+JLSzQ/XsCVhcteiDOaCSZUCSgODQP7fZeghuQ+lERETkVRjkEDVHrpoP5Cg7eoQazZm2NdCzJFcbgKoqCLHdlOxcbICIiOjaxiCHqDlpiiCjAY4tw12Okjfn1cw5sqdXpjHPMfJU0EdEREQtEoMcombE5cPO3EmWIJVdrglA7Hj8jlNta4qgz7w4gRmXnSYiImrxGOQQkWPMwYUA69XjXNzb1CRBHxcnICIi8joMcojIIebAQ6USXbt6XFOruwiBedlpIiIiavEY5BDRNanukDRl2WkiIiJq8URPV4CIiIiIiMiVGOQQEREREZFXYZBDRERERERehUEOERERERF5FQY5RERERETkVRjkEBERERGRV2GQQ0REREREXoVBDhEREREReRU+DLQFMb01Bygt+TOhrKS+rERERERE1ywGOS1JaQmfyE5EREREdBUMcloiUQCCw/78PSSsvpxERERERNccBjktUXAYVHMzPF0LIiIiIqJmiQsPEBERERGRV2GQQ0REREREXoVBDhEREREReRXOySEiaoauX7UKqrJym9tMwUE499RTTVwjagjPFxFR88Igh4ioGVKVlUNVVubpapCdGjpfqrIyRL25RPn9Wg16zIGgDBmSLEGt1sAEEQgJg2r6fE9Xj4i8jMNBzqpVq5Cfn4/8/HwUFBQgMjISX375pc28sbGxDZb1/PPP4+mnn7Yrf25uLkJCQizSLly4gCVLlmD//v0oKytDdHQ00tLSMHr0aJtl7NixA2vWrMHx48eh0WiQkJCAGTNmIDIyssF6EhF5jCDAFBQEAFCVlwOy3CSHra9norncoDfbnpPa56tW0NMcAlZPv2fmQFCGDFGWAVEPQAAua2Ga+6xlZgY+RNRIDgc5b731FsLCwnDrrbei7Cr/03799ddtpi9fvhxnzpzBwIEDrbb16dPHZpCi0Wgsfi8tLcXYsWNRVFSE9PR0REVFIScnB3PmzEFxcTGmTJlikX/Dhg2YP38+evXqhdmzZ0Or1WL9+vXIzc1FVlYW2rVrd7WmExE1OVNQEAr+MgMAEPXmEqjKyqAqL3dpz0C7FSsh1vn/uTM35fbcRLvqRtvunhNBgBAWgrKJE+0qt7Fqn6+6bXVlkKqULQhQqQQEmWRAlht8D53tHWzonNVl1zkUBBiDAuFTof8zjQ+6JiIXczjI+eKLL9ChQwcAQFJSEiorK+vNm5KSYpVWWFiIWbNmoVu3bujSpYvV9g4dOtjcr67Vq1fj9OnTyMjIwL333gsAGD16NCZNmoSVK1ciJSVFqadWq8WSJUvQtWtXZGZmQq2uafaAAQOQmpqKZcuWYcGCBVdvPBGRE0xvzQFKS6CGhFuMVRAFEQIE54MTWa73ZtWZHhixvOGbX1NwsM0bdKubeDtuoF0+rMuOnhOxvAzXv/6mRf2boueibvnmINUVar+PoigAkgPBUwO9g7Y+P47Uue45tNhWXlOuKSgIPz07AfGZ2yHULbusxLG2EBHVw+Egxxw4OCs7OxuSJCE1NbXePAaDAQaDAUFX/idsy/bt2xEVFaUEOGbjx4/H3r17sWvXLky88pe7nJwcVFZWIi0tTQlwACAuLg59+/bFrl278PLLL8PX17dRbSMisqm05MpfqmWopWoIggABgkUWm3/1r8MUbPn/RPMNau2eHXtuSOv2AsC8T62b39rHPPfUUzZv0BsKWEzBwRZ1tOKiYV0N9pzULre0tE7d6w+oPD1Uz56eE+XzIQiQQkOAklK7e4ka6h282vtvPq9W9XHiHJqe/zt8VP6WaXOfZa8OEblEky48IMsytmzZAo1Gg6SkJJt5du/ejW3btsFkMiEsLAyDBg3C888/jzZt2ih5zp8/j3PnztksIz4+HoIg4MiRI0qa+ef4+Hib+Q8dOoQTJ07Y7Fmyl1rt2tW4VSrR4hUAJAGQBUAQGnc82SRCUouAKEJQeW4VcZVKqPXqfauZs31NQzaJgFqEqBYhNOK6sHV92boOG1M2BBHGoCD4lFcCcs2NatSSt2qOUecmXCEIyvGLJz9tsen619+s2a+enh1TSEhNuixblKMqr7DoBZCu3BybgoNxbuZfrMpRXalH3frUTqt98ysFBaFo8iSLOprbqvw1v9ax2q1YCbG8TnBSp8623pervT/tVqysOZ5KgGSSIcPyfa57Y+7IubCqc62gw5E61y2nwePbIAUHo+yVlxD8t1chlpY6fHwlzcZnyFRnHmzt81qXrXbUxxQUAJVahFolWn2X1b0OXXUNEtG1p0mDnG+//RYFBQUYOXKkzV6auLg4DBkyBNHR0aiqqsLBgwexZcsWHDhwAJs3b0bbtm0BAEVFRQCAiIgIqzJ8fX0RHh6OwsJCJa24uLje/Oa5OEVFRU4HOaIoIDw80Kl9ryYk5M+5SBdUIiRRgKgSG3U8WaeCPsgfosYfgq+fK6rZKIGB/lfP1IKxfe4lG0RIVTL8wgIh+Dtfl4aur9rXYWPKRlg4/pg5AR0XvgNV6ZUgo/zKjaX4Z8+OFPrnzaUQHIzgENvtEsJCAJVgc5sUHIzyvzyH0JcXQLxcCqGiHFFLanouhIpyCKIAWRAghfwZnDR0LJVKqBkWpRKUPOY0KTQE5a+8ZJE/uO5+5rYKqLmDrVVO5aznLfa1Vefa7Sr7y3M261NX3XIBIPjNZRbzj8TLfwYU9Z0LobQMgixb1Kf2fgBstqsuc50bLMfG8Rt0JbgUbbwfddtqPu+189T3GTJ/fqwOV081bL3X9dGb9AiqrkRYeAA0astrq77rsLHXIBFde5o0yPn4448BAKNGjbK5PSsry+L35ORk9O3bFy+88AIyMjIwf37NSis6nQ4A6h1e5ufnp+QBgKqqqnrz+/n5WeRxhiTJKC2tf26SM1QqESEhGpSWVsFkkgAAJpMEWZIhmyRotRVOly3rdZDKdUC1AMFXclWVHaZSCQgM9EdFhQ4mk/eNwWb7moZsMAB6HSpLKiD4mZwux9b1Zes6rMvwxks1w9HqCgmD718XWJZtlFBerkN1QADkei49m38tL9XZzHvVyfSlupoJ6ZIMQAa0l4GanyADkEJqegEqyvWQzPMg6jmWUk5JKYL+9uqVCpRBkmWYTDLK6tkvQBMI0cbnQ9IE1ruPrTqbidrLNce349hAzR+hAoP8lDbWfc8a6oEwnwulx6xWfWqfvto9Ho62q75yah+/IaIoIBCAZOP8iHV6hMznvfZ71uBnqIH3tTH0Jj2qTDqU+FZCp7a8EOpeh/Zcg84KCdGwh4jIizVZkHP58mV8/vnn6Ny5M/r06WP3fiNGjMCyZcuwb98+Jc3/yl9rDQaDzX10Oh1at26t/G5emc1gMCj7mun1eos8zjIa3RMsmEySUrZ85RtKlht3PNkoQTZKgI8EwcVfGo6p+XIxmWSXf3k1D2xfU5AlCTBKkIwSBFUjrosGrq/a16HVfpdLbM8hqFWOuWxAhsko4cwT4+GraqAX1YXvpykosN65GtKVHnVJsuMcmsuQZevhVHL9+//xVAM30fXsY6vO9c6vaeDYNWo+p/W1scH6XaljQ++hzXk6DrSrwXIaKOtPNe1TSrV1fmA5l8YUFOjRa1YySTAZJRhNEoywrEd912FD1yARkS1NFuRs27YNBoMBDz74oMP7RkZGIi8vT/ndPMSs9pA0M71ej5KSEotAyjzMrbCwENHR0Rb5zUPfuIQ0ETWKKADBYc1udaiGJsqrVGK9w4/qqrvogb3bnGGrzg0tBuBurlpswJ2LFkhBQY4HUEREXqzJgpysrCz4+PhgxIgRDu0nyzLOnDlj0TPTpk0bRERE4PDhw1b5Dx8+DFmWERcXp6TFxcVh06ZNyMvLswpy8vLyEBAQgM6dOztULyIiC8FhUM3N+HN1qLKSPx9wWFbi0aq5gqdvkj19/OauaPIkL+0xJiJyTpMMRj169Ch+/vlnDBw4ENddd53NPBcuXLCZnpmZicLCQtxzzz0W6UlJSSgoKMCePXss0teuXQu1Wo1hw4YpaYmJidBoNMjMzITRaLSoV25uLoYOHcrlo4nItSS5Jti5rG1WPTtERETXAod7crZu3Yo//vgDAHDp0iVUV1djxYoVAICQkBCMGzfOah/zggINDVVbtWoVvvnmG9x9991o37499Ho9Dh48iL179yI6OhpTpkyxyD9x4kTs3r0bM2fORH5+PqKiopCTk4O9e/di8uTJFs/zadWqFaZNm4aFCxciLS0NKSkp0Gq1WLduHVq3bo2pU6c6+jYQEdkWElbvJrmeZ4wQERGRazkc5GRnZ+PQoUMWaW+//TaAmrkzdYMcnU6HTz/9FBERERgwYEC95d5xxx04ceIEtm3bBq1WC0EQ0LFjR0yaNAlPPPEEguvcHISGhmLjxo1YunQpNm/ejPLycnTq1Alz587FmDFjrMpPT09HeHg41q5di4ULF0Kj0aBfv36YPn065+MQkcuops+vd1u1SQdczKt3OxEREbmGw0FOZmamQ/n9/f3x3XffXTVfYmIiEhMTHSq7bdu2WLRokd35k5OTkZyc7NAxiIiIiIioZeEC8URERERE5FUY5BARERERkVdhkENERERERF6lyZ6TQ0TU0pnemgOUllgmesEzcIiIiLwNgxwiInuVltQ894aIiIiaNQY5RESOEgUgOMwyrYHn4xAREVHTYpBDROSo4DCo5mZ4uhZERERUDy48QEREREREXoVBDhEREREReRUGOURERERE5FUY5BARERERkVfhwgNERETUvJSVwDT3WUgCcEElwhQYAnHafE/XiohaEAY5REQtxLL8t1BWXWqVHuwTgue6TvdAjYjcRJKBy1rIAiCJAmCSPF0jImphGOQQETXCC4emQWuwfkBouG84XrttqUuPVVZdilLDZZeWSdSs1H3eVNllALInakJELRyDHCKi2q4MkwFg11AZrUELrf6Sdbr+EiZ+/ZhFWqhPKFJveNhmOfX10lhUrboMACAIIoJ9glFWXQZZ5l+4yXuoplteZ9IrzwJlJZ6pDBG1aAxyiIhquzJMBoBDQ2UEQUCYb7hFwFM3+GkoIHGklybYJxgv9ZyLBYfnuqRn5x9H30SpoeEA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O3bsQFxcHJYvX46IiAiXHKu5+vvf/46AgAAMGjQInTt3RklJCbZs2YInn3wSzz//PJ5++mmL/O+99x60Wi1uvfVWVFVV2XxgvdlPP/2Ehx56CKGhoXjooYfQrl07nD59Gh999BE+//xzZGVl4eabb1by5+TkYMqUKbjpppswffp0GAwGbNiwAWPGjMGHH35oV6Bz+fJlnDp1Cv3790f79u3h7++PU6dOISsrCzt37sSmTZssjvnpp59ixowZiIqKwlNPPQWNRoM9e/bghRdeQGFhISZNmmRRviN1rK6uxoQJE3D06FGMHTsWsbGxyM3NxZIlS3Dy5EmH5ts3hEEOERERkZOu878Om4dv9nQ1MHr7aJf1LN1yyy1ISUmxSJs1axZWr16NJUuWYOLEidiyZYvL/uLuThUVFQgMDHR4vzfffBN33HEHBEFQ0saNG4cRI0bgnXfewdixYxEaGqps+9e//oX27dtDFEU89dRTDQY5H374IfR6PVavXo0uXboo6T179sQzzzyDf//73/jLX/4CADAajZg/fz7atm2LDz/8EEFBQQCAoUOH4v7778eiRYuwbt26q7anc+fO+PDDD63ShwwZgtTUVPzrX//C/PnzlWO++uqruO6667BlyxaEhIQo7X/yySexfPly3H///crjWhytY3Z2Ng4fPoxZs2Zh/PjxAIDU1FQEBwdjw4YNGDVqFPr06XPVNl0NFx4gIiIiogYJgoCJEyfi/vvvx7Fjx7Bz506L7VqtFq+++iruvvtudOvWDf3798dLL72E4uJii3wHDx5EbGwstmzZgo8//hjDhg1Dt27dMHDgQKxevdrmsb/88kuMHTsW8fHx6NmzJx588EHs2LHDKl9aWhruuecenD17Fs899xxuu+029OrVC0BN78Fvv/2mPOvxau68806LAAcANBoN7r77blRXV1s9+zEqKgqiaN9tdVlZGYCaVYJrM//u7++vpOXm5uLcuXNITU1VggcAaN++PYYMGYJvv/0WRUVFdh3XlqioKAA1PT1mv/76Ky5duoTExEQlwAFqPgMjRoxAdXU1tm3b5nQdt2/fDn9/f6tHvpgDntplNwaDHCIiIiKyy+jRowEA+/btU9LKy8sxduxYbNiwAXfeeSdefPFFDB48GJ988glGjx6NCxese5g+/PBDvPvuuxg+fDhmzZqFNm3a4M0338T27dst8m3atAlPP/00Ll68iKeeegrPPvssqqurMWPGDKxcab3AQkVFBcaNGwe1Wo3nn38ezz77LACgqKgIw4YNwwsvvNCo9ptv1q+7zvkhiv369QMAzJw5E0eOHEFRUREOHjyIuXPn4vrrr1feYwA4evQoACA+Pt6qnPj4eMiyjB9++MHuY1dXV+PSpUsoLi7Gd999p/QY3X333UoevV4PoCaoq8scgB05csSpOkqShPz8fNxyyy0WwRxQE3C1adNGKa+xmn8/IxERERE1C+bhVadOnVLSVq9ejRMnTuDFF19Eenq6kh4fH4+//vWvePvtt5WhUGbnzp3Dzp07lZ6CUaNGYeDAgdiwYQOGDx8OACgtLcXixYsRGRmJrKws5cHwY8eOxUMPPYSMjAwkJyejffv2SrklJSV45pln8Nxzz7m87T///DM+//xz9O7dWxmq5YxRo0bh7Nmz+Ne//oXU1FQlvXfv3sjKykLr1q2VNHNQZWsOlDmtoaFxdX399dcW82latWqFmTNnYuTIkUpadHQ0VCoVDh06BFmWLXq0Dh48CAAWPWKO1PHy5cuoqqqqd05XREQEfv/9d7vb0xD25BAREVGzUmLQYuLXj+F0+WlodVr8XlHg6SrRFebhSOXl5UraF198gbCwMIwdO9Yi7/Dhw9GpUyd8/vnnVuWMGjXKYiiURqNBz549LYKnAwcOoLKyEmlpaUqAY877+OOPw2g04ssvv7Qq2zzsqTbzQ+rtfah9XRcvXsQzzzwDX19fq4DNUaIoon379ujbty/+/ve/Y8WKFZg6dSp++eUXPPnkkygpKVHyVlVVAQB8fX2tyjGn6XQ6u4/do0cPrF27Fu+++y5mzJiB66+/HuXl5TAajUqesLAwPPDAA/jxxx8xa9Ys/Pzzzzh9+jRWr16Njz/+2OqYjtTR/GorLwD4+fk51J6GsCeHiIiImhVZlqHVX4JJMkKSAaNs8nSV6ApzcFN77sXZs2dxyy23wMfHxyKvIAi46aabkJOTg/Lycot9zHNBagsLC7O4wT979iwA4KabbrLKa16ty5zHrFWrVhYBkSuUlJRg/PjxKC4uxqpVq3DjjTc2qrylS5di48aN2LVrl9Jrk5iYiL59+2LcuHF49913MXv2bAB/DhkzGAxW5ZiHlZmHfVVUVKCystIiT2hoqEVA0apVK2W43D333IOUlBQkJyfj4sWLmDdvnpJvzpw5EAQBW7ZswdatWwHUnJ958+bhr3/9q8W5dKSO5ldbeYGaIKjuMDZnsSeHiIiImoVw33CE+7VS/lHz89NPPwEAbrjhBrvy17esdWOftVNfubbmkTSGOcA5ceIEli9frgQIzqqursaaNWvQu3dvi2FpANC3b1+0adNGGRIGAO3atQNge0ha3WFia9asQf/+/S3+5eXlNVifdu3aoV+/fsjKyrIIPPz9/fHqq6/im2++wcaNG/Hxxx/jq6++wq233gqgZrU2Z+oYGhoKf3//eofYFRUVuWx5cvbkEBERUbPw2m1LLX4/+e9kAEbbmckjNm+uWS574MCBSlqHDh1w6tQpVFdXW/Xm/PbbbwgPD7f4y7+9zPNejh8/jgEDBlhs+/XXXwHA5kMsXeXy5ct4/PHH8euvvyIjIwN33XVXo8vUarUwGAwWw8Nqq66uhsn0Z89lXFwcACAvLw8JCQkWefPy8iAIArp16wYAGDFiBHr37m2Rp/YS1fXR6XQwmUwoLy9Hq1aWf1wIDQ21KHP//v0AYPFAVEfqKIoiunbtivz8fKtem4KCApw/fx733HPPVetsD/bkEBEREVGDZFnG6tWrsXPnTtxyyy0YOnSosm3QoEEoKSnBpk2bLPb59NNPcfr0adx7771OHTMhIQEBAQHYsGGDxRwgvV6PtWvXQq1WWwRbDXF0CenLly9j/Pjx+OWXX7Bs2TK7j3M1rVu3RlhYGL777juroXY5OTkoKSlRggagpnenXbt2+Pjjjy3egz/++AO7d+/G7bffrvSkdOjQAf369bP4Z36Wj60V7oCaAPLbb79Fhw4drAKcus6ePYvVq1cjOjra4vw7UkcASEpKgk6ns3puj/lZOsnJyQ3Ww17sySEiIiIixU8//YR///vfAIDKykqcOXMGX375JU6dOoXu3btj+fLlFsPNnnzySezevRuvvvoqfvzxR8TFxeHXX3/Fpk2bEBER4fRKZyEhIXjhhRfw8ssvY9SoURg1ahTUajW2bduGn376CdOmTbNYWa0h5iWkb7vtNrsWHxg/fjzy8/Nx//33o6ysTHk/zHr16mWxwtqXX36Jn3/+GQBw+vRpAMCKFSuU7ZMnTwZQ05Px7LPPYv78+Rg9ejQefvhhRERE4NixY9i8eTNCQkLw1FNPKfup1WrMmTMHzz77LMaMGYOHHnoIBoMBGzZsAABl7s7VrFq1Cv/9739x1113ITIyErIs45dffsH27dtRXV2Nl19+2SL/Rx99hH379qF3794IDw/HiRMn8PHHH0OlUuHtt9+2mOfjaB1TU1PxySef4I033sDvv/+O2NhYfPfdd9i6dStSUlJc8iBQgEEOERERkdMu6i5i9PbRV8/YBPVwlZ07d2Lnzp0QRREBAQFo06YNunXrhhkzZiAxMdFqPk1QUBA+/PBDLF++HF988QW2bduGsLAwjBgxAs8995zV3BNHPPzww2jTpg3++c9/YsWKFZBlGTfffDPefPNNZalpd8jPzwdQ0xv16aefWm1ftGiRRZCzZ88efPLJJxZ53n77beVnc5ADAOPGjcMNN9yANWvWIDs7G5cuXUJYWBjuu+8+TJkyBZ06dbIoZ/DgwVi9ejXeeecdvPnmm1CpVOjduzemT59u13A0oGZ4YWFhIT777DNcvHgRJpMJ7dq1w3333YfHH38cN998s0X+m266CZ9++inef/99lJeXo02bNrj//vvx9NNPW/TKOFNHHx8frFmzBsuWLcNnn32Gjz76CO3bt8e0adPwxBNP2NUeewhyfTO3yG4mk4RLlypcWqb0yrMQykogB4dBfDnDpWXLeh3kYz8AGg0EH9tL+DUFlUpESIgGpaVVMJkkj9XDXdi+piFXG4CqKgix3SD4uWZFFjO1WkR4eCC02goYjRImfv0YtPpLCPdrhff6r3O4PJ1JhyMX8xCgDoCvys+ldXWGSiUiOMQfZaU6r/yMAt7fxpbYPoNJj0pjJbpfFw9/VcPX7Mm/JiO40oiyADVueMM1T0E3a9UqECqV86P2R28fjQtVtocAeVJrTWtsHr7Z09Ug8jj25BARERE5qJV/81z9rbnWi6ipMcghIiIictDKwSs9XQUiagBXVyMiIiIiIq/CIIeIiIiIiLwKgxwiIiIiIvIqDHKIiIiIiMirMMghIiIiIiKvwiCHiIiIiIi8CoMcIiIiIiLyKnxODhFRPf7yzfMoM12G0WSCLAMlBq2nq0RERER2YJBDRFQPreESSgxaSJLs6aoQERGRAxjkEBFdhSgICPUNV34Pr/UzERERNT8McoiIriLMLxyrEtZ5uhpE1IxcenkGpJLmN4RVDAtHq1eWeLoaRB7HIIeIiIjIQVKJFlLJJU9Xw23KysrQv39/6HQ6LFq0CCNHjvR0lRpl3bp1CAkJaXQ7Ll++jK1bt2L//v347bffoNVqcf311+O2227D5MmTcf3111vtYzAY8N5772Hr1q0oLCxEmzZtMGzYMEyZMgUajcYq/w8//IClS5fi8OHDkCQJ3bp1w3PPPYe+ffvaXc+dO3fiq6++wg8//IDffvsNJpMJOTk5iIqKspm/oKAAK1euxLfffovi4mKEhYWhW7dueOKJJ9CrV69G1dHR9ruKw0HOqlWrkJ+fj/z8fBQUFCAyMhJffvllvfkvXLiAJUuWYP/+/SgrK0N0dDTS0tIwevRom/l37NiBNWvW4Pjx49BoNEhISMCMGTMQGRnZpGUTERERXZUgQgwN83QtIF0uAWTJZeVt374der0eHTt2RFZWVosPcv71r38hMjKy0e34/vvvsXjxYtxxxx145JFHEB4ejl9//RWbNm3Crl278NFHH+Gmm26y2Ocvf/kLdu/ejZSUFPTt2xc///wz1q5dix9++AFr166FKP652PGRI0eQlpaG6667DpMnT4avry82b96Mxx57DKtXr0a/fv3squeHH36I77//Hl26dEHHjh1x8uTJevMWFRVh1KhRkCQJDz/8MDp27IiioiJ89NFHGDduHFavXo2EhASn6+hI+13J4SDnrbfeQlhYGG699VaUlZU1mLe0tBRjx45FUVER0tPTERUVhZycHMyZMwfFxcWYMmWKRf4NGzZg/vz56NWrF2bPng2tVov169cjNzcXWVlZaNeuXZOUTURERGQPMTQMrd9e4+lq4MLUx13as5SVlYW+ffti6NCheOWVV3DixAl07tzZZeW3VJ07d8Znn32GTp06WaTffffdGD9+PJYtW4Zly5Yp6V999RV2796NtLQ0/O1vf1PSIyMj8dprr2H79u1ISUlR0hcsWABRFLFhwwa0b98eADBixAjcf//9eOWVV/DZZ59BEISr1vO1115D27ZtoVarMW/evAaDnK1bt6KkpATvvPMOBg0apKQnJiZixIgRyMrKsghyHKmjo+13JYdDpy+++AIHDx7E2rVr0bZt2wbzrl69GqdPn8Ybb7yB6dOnY/To0Vi1ahUGDhyIlStX4uzZs0perVaLJUuWoGvXrsjMzMSYMWMwefJk/POf/8T58+ctPjDuLpuIiIjoWvXzzz8jPz8fDzzwAJKSkuDr64vs7GybeQ0GA1avXo2U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VSCiBvApWERERERE5FUY5BARERFRi/Lss8/i2LFjnI9D9WKQQ0REREREXoVBDhEREREReRUGOURERERE5FUY5BARERERkVdhkENERERERF6FQQ4REREREXkVBjlERERERORVGOQQEREREZFXYZBDRERERERehUEOERERERF5FQY5RERERETkVRjkEBERERGRV2GQQ0REREREXoVBDhEREREReRUGOURERERE5FUY5BARERERkVdhkENERERERF6FQQ4REREREXkVBjlERERERORVGOQQEREREZFXYZBDRERERERehUEOERERERF5FQY5RERERETkVRjkEBERERGRV2GQQ0REREREXoVBDhEREREReRW1OwvPyMjA8uXL6z+4Wo38/Pyr5n300Ufx0ksvWaXv2LEDa9aswfHjx6HRaJCQkIAZM2YgMjLSKu+FCxewZMkS7N+/H2VlZYiOjkZaWhpGjx7tZOuIiIiIiKg5cmuQM3jwYHTs2NEq/dixY3j//fcxcOBAq22zZ89GeHi4RdqNN95olW/Dhg2YP38+evXqhdmzZ0Or1WL9+vXIzc1FVlYW2rVrp+QtLS3F2LFjUVRUhPT0dERFRSEnJwdz5sxBcXExpkyZ4oLWEhERERFRc+DWIKdLly7o0qWLVfrf//53AMCDDz5otW3QoEGIiopqsFytVoslS5aga9euyMzMhFpd04wBAwYgNTUVy5Ytw4IFC5T8q1evxunTp5GRkYF7770XADB69GhMmjQJK1euREpKCjp06OB0O4mIiIiIqPlo8jk5VVVV+PTTT9GuXTsMGDDAZp7y8nJUV1fXW0ZOTg4qKyuRlpamBDgAEBcXh759+2LXrl0wGAxK+vbt2xEVFaUEOGbjx49HdXU1du3a1chWERERERFRc+HWnhxbdu3ahfLycqSlpUGlUlltT0lJQXl5OURRxC233IInnngCw4YNs8hz5MgRAEB8fLzV/vHx8Th06BBOnDiBLl264Pz58zh37hySkpJs5hUEQSmvMdRq18aLBkGo+UEQXF62bBIhqUVAFCGoPLf2hEol1Hr1vjUw2L6mIZtEQC1CVIsQXHytCBCUV1dch2qIUKlFiCoRKg9ee2aiKNR69Xx93MHb29gS2ydChAoi1CrRoevK1d+FROTdmjzIycrKgiAIGDVqlEV6cHAwUlNT0atXL4SFheHM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7+OGG25wqNysrCxcf/31uHTpErKzs/H888/bva/589YSg5zff/8dy5cvR2RkpFWQ07dvXxw5cgRq9bX5dfT+++97ugpERF7p2vxWoSaRkpJi8fvBgwexcuVKxMbGWm2j5mPw4MH49NNPMXv2bPj6+irpR44cwS+//IKkpCTs2LHDYh9ZljF16lT8+OOPmDdvHh566CGL7Y899hjGjRuHGTNmICsrCzfffLPF9jZt2lh9Jp577jkcOHAAU6ZMwdNPP41///vfDvV8OOv8+fOYPHkyTCYTNm7ciO7duyvbHnnkEezfvx/PPPMMnn76aWzduhX+/v52lavVapGTk4OJEyfit99+wyeffILnnnsOouj5UcMVFRUIDAz0yLFFUYSfn59Hju0pkiTBYDDA39/f4hojIiLX8fy3K9EVtubkmNMuXbqEWbNm4fbbb0d8fDwmT56M8+fPAwA2bdqEoUOHIi4uDkOGDMHnn39us/ydO3dizJgxiI+PR48ePZCamorPPvvMKt++ffswbtw43HHHHYiLi0P//v0xadIk/PrrrwBqhjwtX74cAJCYmIjY2FiLOQW//fYb5s6di/vvv1851siRI7F582arY2VkZCA2NhbHjx/HggUL0L9/f/Ts2RPp6ek4ceIEAGDPnj144IEH0L17dwwcOBAffvihVTnmsff//e9/MXr0aPTo0QP9+vXDq6++ioqKCntPAQBg5MiRuHz5Mr744guL9C1btqBVq1YYOHCg1T579+7Fd999h6FDh1oFOADQoUMHzJs3DzqdzqG5JgkJCXjhhRdQUVGBVatWOdQOZ73//vu4dOkSpk+fbhHgmN1111149NFHcfLkSWRlZdld7rZt21BdXY0RI0bggQceQGFhIb766qur7meeswIAn3zyifJ5qzuPw97Pt/mz8s033yj5J02aBKBmiF9aWhp+/fVXTJgwAfHx8ejduzeee+455XozKyoqwuLFi5GSkoK+ffsiLi4Ow4YNw3vvvQeTyaTky8jIwKOPPgoAmD17tlJ/81yR+ubkVFVVYenSpbj33nvRrVs33HHHHXj++edx8uRJi3y15zB98cUXGDlypHLdvvbaazAajVd9j2u/L/ZeQ2VlZXjjjTcwePBgpX7Tp0/H2bNnLfJt2bIFsbGx+O9//4t33nkHgwYNQlxcHHbu3Amg/jk5//vf/zBhwgT0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q9Uqv//2228AYHXjVtuFCxcA1AQbX375JebNm4clS5agV69eGDBgAO6//360bt3arrpWVFRg+fLl2LVrF86dO2e1vbS01CrN0fb9/vvvVul1h+8ANTesISEhFjen9ggNDcWgQYPwySefIDk5Gd9++y3mzJlTb/7awUtYWFi9+ewNhurbz92T483l2xOElZeX27WMdFVVFT799FPcdtttuHDhgvJZ8/HxwQ033ICsrCw89thjTtfZkc+3WadOnerNa2txB/M5LSkpUdKMRiPee+89/Pvf/8bp06et5orY+pzb6+zZs2jdurUyFLS2mJgYfPvttygoKECXLl3srrc9nx17rqFLly6hpKQE33zzTb2Boq2hodHR0Vc9PlAzxwgAbrrpJqtt5kDGPO/H/Gqr3rb2JyK6ljDIoRZBpVI5lF6b+ebrvffeg4+Pj8085huCsLAwZGVl4X//+x8OHDiA7777Dq+99hqWLVuGFStW2LWM8YwZM7Bv3z6MHj0affv2RWhoKNRqNfbv349169ZBkiSrfeqbL2NP+8xq9wTVJstyvdsaMnLkSOzcuRNz5syBj48PkpKS6s178803Iz8/Hz/++CP69etXbz1+/PFH+Pr62n3DB9T0hp08eRJt27ZVggrzX8R1Ol29+1VVVdm8SW5IUFAQ2rdvj5MnT6KyshIBAQE28506dQoVFRW47bbbrlrm7t27UV5ejv3792P//v0283z//ffo0aOHQ3U1c+TzbVa7t7Guhj5ztQOZRYsWYcOGDRg2bBgmTZqEVq1awcfHB/n5+XjzzTdtfs7tVTdgsmebvfVuiD3XkLms22+/3e65PgDsXoXP3rrWZqvezlzzRETehEEOeb3o6Gh89dVXiIiIsOsBpaIoom/fvsrE/t9++w0jR45ERkaGEuTUdwNRWlqKffv2ISUlRZl4bfbf//63kS1p2PHjx63SiouLUVZW5tTSywkJCbj++utx4MABJCUlNfg8oMGDB2Pr1q3YtGlTvUHO/v37UVRUhHvvvdehZXO3bNmC6upqi1XdwsPDERAQoPRi1GUePmTrWT9XM3jwYKxfvx6ffPKJ1YR9s02bNgEA7r333quWl5WVhTZt2uBvf/ub1TZJkjBz5kxkZ2c7HeQ4+vl2lW3btqFv375YunSpRbqtoZSO3nB37NgR//nPf6DVaq0C1ePHj0MURave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\n", "text/plain": [ "
" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "bpl.plot_alternation_hist(d)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "If the previous alternation histogram looks correct, \n", "the corresponding definitions of the excitation periods can be applied to the data using the following command:" ] }, { "cell_type": "code", "execution_count": 11, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "# Total photons (after ALEX selection): 2,259,522\n", "# D photons in D+A excitation periods: 721,537\n", "# A photons in D+A excitation periods: 1,537,985\n", "# D+A photons in D excitation period: 1,434,842\n", "# D+A photons in A excitation period: 824,680\n", "\n" ] } ], "source": [ "loader.alex_apply_period(d)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "If the previous histogram does not look right, the parameters in the `d.add(...)` cell can be modified and checked by running the histogram plot cell until everything looks fine. Don't forget to apply the \n", "parameters with `loader.usalex_apply_period(d)` as a last step.\n", "\n", "> **NOTE:** After applying the ALEX parameters a new array of \n", "> timestamps containing only photons inside the excitation periods \n", "> is created (name `d.ph_times_m`). To save memory, by default, \n", "> the old timestamps array (`d.ph_times_t`) is deleted. Therefore, \n", "> in the following, when we talk about all-photon selection we always \n", "> refer to all photons inside both excitation periods." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# Background and burst search" ] }, { "cell_type": "code", "execution_count": 12, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ " - Calculating BG rates ... Channel 0\n", "[DONE]\n" ] } ], "source": [ "d.calc_bg(bg.exp_fit, time_s=30, tail_min_us='auto', F_bg=1.7)" ] }, { "cell_type": "code", "execution_count": 13, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ " - Performing burst search (verbose=False) ...[DONE]\n", " - Calculating burst periods ...[DONE]\n", " - Counting D and A ph and calculating FRET ... \n", " - Applying background correction.\n", " [DONE Counting D/A]\n" ] } ], "source": [ "d.burst_search(L=10, m=10, F=6)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "First we filter the bursts to avoid creating big files:" ] }, { "cell_type": "code", "execution_count": 14, "metadata": {}, "outputs": [], "source": [ "ds = d.select_bursts(select_bursts.size, th1=60)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# Exporting Burst Data" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "By burst-data we mean all the scalar burst parameters, e.g. size, duration, background, etc...\n", "\n", "We can easily get a table (a pandas DataFrame) with all the burst data as follows:" ] }, { "cell_type": "code", "execution_count": 15, "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
size_rawt_startt_stopi_starti_stopbg_periodwidth_msbg_adbg_ddbg_aabg_daESndnantndanaaspot
01471.7324561.7355305276542203.0740122.9939761.7958061.7380860.2497760.3242230.57100454.20419426.006024140.472131-0.24977660.2619140
12131.7929931.7958785961617302.8845132.8094101.6851031.6309400.2343780.4208860.64848077.31489756.190590205.8745470.76562272.3690600
22302.0235452.0263376757698602.7919622.7192701.6310361.5786110.2268580.4518000.46703857.36896447.280730224.071083-0.226858119.4213890
31133.1138803.116244104031051502.3639132.3023651.3809731.3365860.1920770.1664620.98459588.61902717.697635107.980076-0.1920771.6634140
4783.1297073.133044105481062503.3376503.2507501.9498211.8871500.2711970.1377020.99840961.0501799.74925070.912280-0.2711970.1128500
\n", "
" ], "text/plain": [ " size_raw t_start t_stop i_start i_stop bg_period width_ms \\\n", "0 147 1.732456 1.735530 5276 5422 0 3.074012 \n", "1 213 1.792993 1.795878 5961 6173 0 2.884513 \n", "2 230 2.023545 2.026337 6757 6986 0 2.791962 \n", "3 113 3.113880 3.116244 10403 10515 0 2.363913 \n", "4 78 3.129707 3.133044 10548 10625 0 3.337650 \n", "\n", " bg_ad bg_dd bg_aa bg_da E S nd \\\n", "0 2.993976 1.795806 1.738086 0.249776 0.324223 0.571004 54.204194 \n", "1 2.809410 1.685103 1.630940 0.234378 0.420886 0.648480 77.314897 \n", "2 2.719270 1.631036 1.578611 0.226858 0.451800 0.467038 57.368964 \n", "3 2.302365 1.380973 1.336586 0.192077 0.166462 0.984595 88.619027 \n", "4 3.250750 1.949821 1.887150 0.271197 0.137702 0.998409 61.050179 \n", "\n", " na nt nda naa spot \n", "0 26.006024 140.472131 -0.249776 60.261914 0 \n", "1 56.190590 205.874547 0.765622 72.369060 0 \n", "2 47.280730 224.071083 -0.226858 119.421389 0 \n", "3 17.697635 107.980076 -0.192077 1.663414 0 \n", "4 9.749250 70.912280 -0.271197 0.112850 0 " ] }, "execution_count": 15, "metadata": {}, "output_type": "execute_result" } ], "source": [ "bursts = bext.burst_data(ds, include_bg=True, include_ph_index=True)\n", "bursts.head(5) # display first 5 bursts" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Once we have the DataFrame, saving it to disk in CSV format is trivial:" ] }, { "cell_type": "code", "execution_count": 16, "metadata": {}, "outputs": [], "source": [ "bursts.to_csv('%s_burst_data.csv' % filename.replace('.hdf5', ''))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# Exporting Bursts Timestamps" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "A convenient way to deal with timestamps (and nanotimes if available) \n", "of photons inside bursts is exporting them as a DataFrame.\n", "The function `bext.burst_photons` ([documentation](http://fretbursts.readthedocs.io/en/latest/plugins.html#fretbursts.burstlib_ext.burst_photons)) \n", "will export this \"photon data\"\n", "with one row per photon. The columns are `timestamp` and, if available,\n", "`nanotime`." ] }, { "cell_type": "code", "execution_count": 17, "metadata": {}, "outputs": [ { "name": "stderr", "output_type": "stream", "text": [ "/home/paul/anaconda3/envs/Py38/lib/python3.8/site-packages/fretbursts/burstlib_ext.py:436: FutureWarning: arrays to stack must be passed as a \"sequence\" type such as list or tuple. Support for non-sequence iterables such as generators is deprecated as of NumPy 1.16 and will raise an error in the future.\n", " times_arr = np.hstack(\n", "/home/paul/anaconda3/envs/Py38/lib/python3.8/site-packages/fretbursts/burstlib_ext.py:438: FutureWarning: arrays to stack must be passed as a \"sequence\" type such as list or tuple. Support for non-sequence iterables such as generators is deprecated as of NumPy 1.16 and will raise an error in the future.\n", " stream_arr = np.hstack(\n" ] }, { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
timestampstream
burstph
00138596500AexAem
1138622303DexDem
2138626950DexDem
3138641792AexAem
4138643022DexDem
\n", "
" ], "text/plain": [ " timestamp stream\n", "burst ph \n", "0 0 138596500 AexAem\n", " 1 138622303 DexDem\n", " 2 138626950 DexDem\n", " 3 138641792 AexAem\n", " 4 138643022 DexDem" ] }, "execution_count": 17, "metadata": {}, "output_type": "execute_result" } ], "source": [ "burstph = bext.burst_photons(ds)\n", "burstph.head()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "This DataFrame has a two-level index (the first two columns): one is \n", "the burst number and the other is the photon number within each burst.\n", "The photon number starts at 0 for the first photon of each burst.\n", "\n", "As with any DataFrame, saving to disk is trivial:" ] }, { "cell_type": "code", "execution_count": 18, "metadata": {}, "outputs": [], "source": [ "burstph.to_csv('photon_data.csv')" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "To read the data back use:" ] }, { "cell_type": "code", "execution_count": 19, "metadata": {}, "outputs": [], "source": [ "import pandas as pd" ] }, { "cell_type": "code", "execution_count": 20, "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
timestampstream
burstph
00138596500AexAem
1138622303DexDem
2138626950DexDem
3138641792AexAem
4138643022DexDem
\n", "
" ], "text/plain": [ " timestamp stream\n", "burst ph \n", "0 0 138596500 AexAem\n", " 1 138622303 DexDem\n", " 2 138626950 DexDem\n", " 3 138641792 AexAem\n", " 4 138643022 DexDem" ] }, "execution_count": 20, "metadata": {}, "output_type": "execute_result" } ], "source": [ "burstph2 = pd.read_csv('photon_data.csv', index_col=(0, 1))\n", "burstph2.head()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Verify the data we read is the same:" ] }, { "cell_type": "code", "execution_count": 21, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "timestamp True\n", "stream True\n", "dtype: bool" ] }, "execution_count": 21, "metadata": {}, "output_type": "execute_result" } ], "source": [ "(burstph2 == burstph).all()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Using the timestamps DataFrame\n", "\n", "Operations on the photon-data DataFrame are very simple.\n", "\n", "### Transform the timestamps\n", "\n", "An example of a transformation is rescaling to get timestamps in seconds:" ] }, { "cell_type": "code", "execution_count": 22, "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
timestampstreamtimes_s
burstph
00138596500AexAem1.732456
1138622303DexDem1.732779
2138626950DexDem1.732837
3138641792AexAem1.733022
4138643022DexDem1.733038
\n", "
" ], "text/plain": [ " timestamp stream times_s\n", "burst ph \n", "0 0 138596500 AexAem 1.732456\n", " 1 138622303 DexDem 1.732779\n", " 2 138626950 DexDem 1.732837\n", " 3 138641792 AexAem 1.733022\n", " 4 138643022 DexDem 1.733038" ] }, "execution_count": 22, "metadata": {}, "output_type": "execute_result" } ], "source": [ "burstph['times_s'] = burstph.timestamp * d.clk_p\n", "burstph.head()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Compute burst-wise quantities\n", "\n", "We can compute burst-wise quantities in one step without looping \n", "using standard [pandas group-by/apply](https://pandas.pydata.org/pandas-docs/stable/groupby.html) operations.\n", "\n", "To do that, we group rows (photons) by `'burst'` and compute an arbitrary\n", "function on each burst (for example the mean time):" ] }, { "cell_type": "code", "execution_count": 23, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "burst\n", "0 1.734081\n", "1 1.794125\n", "2 2.025197\n", "3 3.115339\n", "4 3.131453\n", " ... \n", "983 597.336390\n", "984 597.537687\n", "985 598.285494\n", "986 598.396130\n", "987 598.865273\n", "Name: times_s, Length: 988, dtype: float64" ] }, "execution_count": 23, "metadata": {}, "output_type": "execute_result" } ], "source": [ "burstph.groupby('burst')['times_s'].mean()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# Another example of exporting bursts timestamps\n", "\n", "> **NOTE**: This section is provided as an example. Exporting timestamps in this way\n", "> is not recommended. Use the approach in the previous section instead.\n", "> The example here is an old example reported for educational purposes only." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Exporting timestamps and other photon-data for each bursts is a little trickier\n", "because the data is less uniform (i.e. each burst has a different number of photons).\n", "In the following example, we will save a `csv` file with variable-length columns.\n", "Each burst is represented by to lines: one line for timestamps and one line for the\n", "photon-stream (excitation/emission period) the timestamps belongs to.\n", "\n", "Let's start by creating an array of photon streams containing\n", "one of the values 0, 1, 2 or 3 for each timestamp.\n", "These values will correspond to the DexDem, DexAem, AexDem, AemAem\n", "photon streams respectively." ] }, { "cell_type": "code", "execution_count": 24, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "[array([False, True, True, ..., False, True, False])]" ] }, "execution_count": 24, "metadata": {}, "output_type": "execute_result" } ], "source": [ "ds.A_ex" ] }, { "cell_type": "code", "execution_count": 25, "metadata": {}, "outputs": [], "source": [ "#{0: DexDem, 1:DexAem, 2: AexDem, 3: AemAem}" ] }, { "cell_type": "code", "execution_count": 26, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "array([1, 3, 3, ..., 1, 3, 0], dtype=int8)" ] }, "execution_count": 26, "metadata": {}, "output_type": "execute_result" } ], "source": [ "(ds.A_ex[0].view('int8') << 1) + ds.A_em[0].view('int8')" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Now we define an header documenting the file format. We will also include the \n", "filename of the measurement. \n", "\n", "This is just an example including nanotimes:" ] }, { "cell_type": "code", "execution_count": 27, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "# BPH2CSV: ./data/0023uLRpitc_NTP_20dT_0.5GndCl.hdf5\n", "# Lines per burst: 3\n", "# - timestamps (int64): in 12.5 ns units\n", "# - nanotimes (int16): in raw TCSPC unit (3.3ps)\n", "# - stream (uint8): the photon stream according to the mapping {0: DexDem, 1: DexAem, 2: AexDem, 3: AemAem}\n", "\n" ] } ], "source": [ "header = \"\"\"\\\n", "# BPH2CSV: %s\n", "# Lines per burst: 3\n", "# - timestamps (int64): in 12.5 ns units\n", "# - nanotimes (int16): in raw TCSPC unit (3.3ps)\n", "# - stream (uint8): the photon stream according to the mapping {0: DexDem, 1: DexAem, 2: AexDem, 3: AemAem}\n", "\"\"\" % filename\n", "print(header)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "And this is header we are going to use:" ] }, { "cell_type": "code", "execution_count": 28, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "# BPH2CSV: ./data/0023uLRpitc_NTP_20dT_0.5GndCl.hdf5\n", "# Lines per burst: 2\n", "# - timestamps (int64): in 12.5 ns units\n", "# - stream (uint8): the photon stream according to the mapping {0: DexDem, 1: DexAem, 2: AexDem, 3: AemAem}\n", "\n" ] } ], "source": [ "header = \"\"\"\\\n", "# BPH2CSV: %s\n", "# Lines per burst: 2\n", "# - timestamps (int64): in 12.5 ns units\n", "# - stream (uint8): the photon stream according to the mapping {0: DexDem, 1: DexAem, 2: AexDem, 3: AemAem}\n", "\"\"\" % filename\n", "print(header)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We can now save the data to disk:" ] }, { "cell_type": "code", "execution_count": 29, "metadata": {}, "outputs": [], "source": [ "out_fname = '%s_burst_timestamps.csv' % filename.replace('.hdf5', '')\n", "dx = ds\n", "ich = 0\n", "\n", "bursts = dx.mburst[ich]\n", "timestamps = dx.ph_times_m[ich]\n", "stream = (dx.A_ex[ich].view('int8') << 1) + dx.A_em[ich].view('int8')\n", "with open(out_fname, 'wt') as f:\n", " f.write(header)\n", " for times, period in zip(bl.iter_bursts_ph(timestamps, bursts),\n", " bl.iter_bursts_ph(stream, bursts)):\n", " times.tofile(f, sep=',')\n", " f.write('\\n')\n", " period.tofile(f, sep=',')\n", " f.write('\\n')" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Read the file back\n", "\n", "For consistency check, we can read back the data we just saved.\n", "As an exercise we will put the results in a pandas DataFrame\n", "which is more convenient than an array for holding this data." ] }, { "cell_type": "code", "execution_count": 30, "metadata": {}, "outputs": [], "source": [ "import pandas as pd" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We start reading the header and computing \n", "some file-specific constants. " ] }, { "cell_type": "code", "execution_count": 31, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "# BPH2CSV: ./data/0023uLRpitc_NTP_20dT_0.5GndCl.hdf5\n", "# Lines per burst: 2\n", "# - timestamps (int64): in 12.5 ns units\n", "# - stream (uint8): the photon stream according to the mapping {0: DexDem, 1: DexAem, 2: AexDem, 3: AemAem}\n", "\n" ] } ], "source": [ "with open(out_fname) as f:\n", " lines = []\n", " lines.append(f.readline())\n", " while lines[-1].startswith('#'):\n", " lines.append(f.readline())\n", " header = ''.join(lines[:-1])\n", "print(header)" ] }, { "cell_type": "code", "execution_count": 32, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "(4, 2)" ] }, "execution_count": 32, "metadata": {}, "output_type": "execute_result" } ], "source": [ "stream_map = {0: 'DexDem', 1: 'DexAem', 2: 'AexDem', 3: 'AemAem'}\n", "nrows = int(header.split('\\n')[1].split(':')[1].strip())\n", "header_len = len(header.split('\\n')) - 1\n", "header_len, nrows" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "As a test, we load the data for the first burst into a dataframe, converting the numerical column \"streams\"\n", "into photon-stream names (strings). The new column is of type categorical, so it will take very little space:" ] }, { "cell_type": "code", "execution_count": 33, "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
timestampstream
0138596500AemAem
1138622303DexDem
2138626950DexDem
3138641792AemAem
4138643022DexDem
.........
142138788833AemAem
143138790337DexDem
144138790703DexAem
145138790873DexAem
146138842421DexDem
\n", "

147 rows × 2 columns

\n", "
" ], "text/plain": [ " timestamp stream\n", "0 138596500 AemAem\n", "1 138622303 DexDem\n", "2 138626950 DexDem\n", "3 138641792 AemAem\n", "4 138643022 DexDem\n", ".. ... ...\n", "142 138788833 AemAem\n", "143 138790337 DexDem\n", "144 138790703 DexAem\n", "145 138790873 DexAem\n", "146 138842421 DexDem\n", "\n", "[147 rows x 2 columns]" ] }, "execution_count": 33, "metadata": {}, "output_type": "execute_result" } ], "source": [ "burstph = (pd.read_csv(out_fname, skiprows=header_len, nrows=nrows, header=None).T\n", " .rename(columns={0: 'timestamp', 1: 'stream'}))\n", "StreamCategorical = pd.api.types.CategoricalDtype(categories=['DexDem', 'DexAem', 'AexDem', 'AemAem'], ordered=True)\n", "burstph.stream = (burstph.stream\n", " .apply(lambda x: stream_map[pd.to_numeric(x)])\n", " .astype(StreamCategorical))\n", "burstph" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "For reading the whole file I use a different approach. First, I load the entire file \n", "in two lists of lists (one for timestamps and one for the stream). Next, I create\n", "a single DataFrame with a third column indicating the burst index." ] }, { "cell_type": "code", "execution_count": 34, "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
timestampstreamiburst
0138596500AemAem0
1138622303DexDem0
2138626950DexDem0
3138641792AemAem0
4138643022DexDem0
............
23232747909435404DexAem987
23232847909438825DexAem987
23232947909451409DexDem987
23233047909458878DexAem987
23233147909462189DexDem987
\n", "

232332 rows × 3 columns

\n", "
" ], "text/plain": [ " timestamp stream iburst\n", "0 138596500 AemAem 0\n", "1 138622303 DexDem 0\n", "2 138626950 DexDem 0\n", "3 138641792 AemAem 0\n", "4 138643022 DexDem 0\n", "... ... ... ...\n", "232327 47909435404 DexAem 987\n", "232328 47909438825 DexAem 987\n", "232329 47909451409 DexDem 987\n", "232330 47909458878 DexAem 987\n", "232331 47909462189 DexDem 987\n", "\n", "[232332 rows x 3 columns]" ] }, "execution_count": 34, "metadata": {}, "output_type": "execute_result" } ], "source": [ "import csv\n", "from builtins import int # python 2 workaround, can be removed on python 3\n", "\n", "# Read data in two list of lists\n", "t_list, s_list = [], []\n", "with open(out_fname) as f:\n", " for i in range(header_len):\n", " f.readline()\n", " csvreader = csv.reader(f) \n", " for row in csvreader:\n", " t_list.append([int(v) for v in row])\n", " s_list.append([int(v) for v in next(csvreader)])\n", "\n", "# Turn the inner list into pandas.DataFrame\n", "d_list = []\n", "for ib, (t, s) in enumerate(zip(t_list, s_list)):\n", " d_list.append(\n", " pd.DataFrame({'timestamp': t, 'stream': s}, columns=['timestamp', 'stream'])\n", " .assign(iburst=ib)\n", " )\n", "\n", "# Concatenate dataframes\n", "burstph = pd.concat(d_list, ignore_index=True)\n", "\n", "# Convert stream column into categorical\n", "StreamCategorical = pd.api.types.CategoricalDtype(categories=['DexDem', 'DexAem', 'AexDem', 'AemAem'], ordered=True)\n", "burstph.stream = (burstph.stream\n", " .apply(lambda x: stream_map[pd.to_numeric(x)])\n", " .astype(StreamCategorical))\n", "burstph" ] }, { "cell_type": "code", "execution_count": 35, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "timestamp int64\n", "stream category\n", "iburst int64\n", "dtype: object" ] }, "execution_count": 35, "metadata": {}, "output_type": "execute_result" } ], "source": [ "burstph.dtypes" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "This was just an example. There are certainly more efficient ways \n", "to read the file into a DataFrame. Please feel free to contribute\n", "new methods to illustrate a different (more efficient or simpler)\n", "approach." ] } ], "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.13" }, "nav_menu": {}, "toc": { "nav_menu": { "height": "174px", "width": "252px" }, "number_sections": false, "sideBar": true, "skip_h1_title": false, "toc_cell": false, "toc_position": { "height": "592px", "left": "0px", "right": "958px", "top": "111px", "width": "257px" }, "toc_section_display": "block", "toc_window_display": true } }, "nbformat": 4, "nbformat_minor": 1 }