{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "## CSCS530 Winter 2015\n", "#### Complex Systems 530 - Computer Modeling of Complex Systems (Winter 2015)\n", "\n", " * Course ID: CMPLXSYS 530\n", " * Course Title: Computer Modeling of Complex Systems\n", " * Term: Winter 2015\n", " * Schedule: Wednesdays and Friday, 1:00-2:30PM ET\n", " * Location: 120 West Hall (http://www.lsa.umich.edu/cscs/research/computerlab)\n", " * Teachers: [Mike Bommarito](https://www.linkedin.com/in/bommarito) and [Sarah Cherng](https://www.linkedin.com/pub/sarah-cherng/35/1b7/316)\n", "\n", "#### [View this repository on NBViewer](http://nbviewer.ipython.org/github/mjbommar/cscs-530-w2015/tree/master/)\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Storing Model Results\n", "\n", " In this notebook, we'll learn a common pattern for storing the results of a model run. Specifically, we'll:\n", " \n", " * create a __model results__ folder to store all output\n", " * create a __per-run__ results folder to store output for a single model run\n", " * learn to save our model parameters\n", " * learn to save figures\n", " * learn to save tabular data\n", " \n", " We'll do this using the basic HIV model.\n", " \n", " __N.B.__: We won't be dealing with RNG seeds in this notebook. However, please see the supplemental notebook for instruction on properly setting, using, and recording the RNG seed.\n", " " ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# Local Imports\n", "\n", " In the first import section, we use an import from _our own module_. We took the imports and class definitions (``Model``, ``Person``) from our notebooks and pasted them into a ``.py`` file, creating a module. Please review the ``hiv_model.py`` file to understand how this works. " ] }, { "cell_type": "code", "execution_count": 33, "metadata": { "collapsed": true }, "outputs": [], "source": [ "# Imports\n", "from hiv_model import Model, Person" ] }, { "cell_type": "code", "execution_count": 2, "metadata": { "collapsed": false }, "outputs": [ { "name": "stderr", "output_type": "stream", "text": [ ":0: FutureWarning: IPython widgets are experimental and may change in the future.\n" ] } ], "source": [ "# Imports\n", "import datetime\n", "import os\n", "import time\n", "\n", "# Scientific computing imports\n", "import numpy\n", "import matplotlib.pyplot as plt\n", "import networkx\n", "import pandas\n", "import seaborn; seaborn.set()\n", "\n", "# Import widget methods\n", "from IPython.html.widgets import *" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# Testing our model output functions\n", "\n", " In this section, we'll define our model output functions. These will manage:\n", " \n", " * creating output directories\n", " * creating output CSV files\n", " * creating output figures\n", " \n", " We'll create one sample model, run it, and then test our methods." ] }, { "cell_type": "code", "execution_count": 3, "metadata": { "collapsed": false }, "outputs": [], "source": [ "# Create our test model\n", "m = Model(grid_size=10, num_people=10)\n", "for t in xrange(10):\n", " m.step()" ] }, { "cell_type": "code", "execution_count": 30, "metadata": { "collapsed": false }, "outputs": [], "source": [ "# Now, we'll define our methods to store a model's output\n", "\n", "def store_model_parameters(model, run_output_path):\n", " \"\"\"\n", " Store model parameters from a model to the run output path.\n", " \"\"\"\n", " # Create parameters dictionary\n", " model_parameters = {\"grid_size\": model.grid_size,\n", " \"num_people\": model.num_people,\n", " \"min_subsidy\": model.min_subsidy,\n", " \"max_subsidy\": model.max_subsidy,\n", " \"min_condom_budget\": model.min_condom_budget,\n", " \"max_condom_budget\": model.max_condom_budget,\n", " \"condom_cost\": model.condom_cost,\n", " \"min_prob_hookup\": model.min_prob_hookup,\n", " \"max_prob_hookup\": model.max_prob_hookup,\n", " \"prob_transmit\": model.prob_transmit,\n", " \"prob_transmit_condom\": model.prob_transmit_condom,\n", " }\n", " # Convert to dataframe and save\n", " model_parameters_df = pandas.DataFrame(model_parameters.items(),\n", " columns=[\"parameter\", \"value\"])\n", " model_parameters_df.to_csv(os.path.join(run_output_path, \"parameters.csv\"))\n", " \n", "\n", "def store_model_csv(model, run_output_path):\n", " \"\"\"\n", " Store CSV data from a model to the run output path.\n", " \"\"\"\n", " # Create interaction dataframe\n", " try:\n", " interaction_df = pandas.DataFrame(model.history_interactions,\n", " columns=[\"time\", \"agent_a\", \"agent_b\", \"use_condom\", \"is_transmission\"])\n", " except ValueError:\n", " # Sometimes, we have no interactions in \"sparse\" parameter configurations.\n", " interaction_df = pandas.DataFrame(columns=[\"time\", \"agent_a\", \"agent_b\", \"use_condom\", \"is_transmission\"])\n", " \n", " # Create time series data frame\n", " tsdata_df = pandas.DataFrame(model.history_num_infected,\n", " columns=[\"num_infected\"])\n", " tsdata_df[\"num_interactions\"] = model.history_num_interactions\n", " tsdata_df[\"num_interactions_condoms\"] = model.history_num_interactions_condoms\n", " \n", " # Save the dataframes\n", " interaction_df.to_csv(os.path.join(run_output_path, \"interactions.csv\"))\n", " tsdata_df.to_csv(os.path.join(run_output_path, \"timeseries.csv\"))\n", "\n", " \n", "def store_model_figures(model, run_output_path):\n", " \"\"\"\n", " Store figures data from a model to the run output path.\n", " \"\"\"\n", " # Plot time series of infections and interactions.\n", " f = plt.figure(figsize=(10, 8))\n", " \n", " # Create our top panel\n", " plt.subplot(211)\n", " plt.plot(model.history_num_infected)\n", " plt.legend((\"Number of infections\"), loc=\"best\")\n", " \n", " # Create our bottom panel and add the legend\n", " plt.subplot(212)\n", " plt.plot(numpy.array(model.history_num_interactions) - numpy.array(model.history_num_interactions_condoms))\n", " plt.plot(model.history_num_interactions_condoms)\n", " plt.legend((\"Number of interactions without condoms\",\n", " \"Number of interactions with condoms\"),\n", " loc=\"best\")\n", " plt.tight_layout()\n", " \n", " # Save\n", " plt.savefig(os.path.join(run_output_path, \"infections_interactions.png\"))\n", " \n", " # Next, plot the initial and final space timesteps.\n", " \n", " # Get colormap\n", " cmap = seaborn.cubehelix_palette(light=1, as_cmap=True)\n", "\n", " # Plot initial step.\n", " f = plt.figure(figsize=(10, 10))\n", " plt.title(\"Infected space at t={0}\".format(0))\n", " plt.pcolor(model.get_space_infected(0), vmin=-1, vmax=1, cmap=cmap)\n", " ax = f.gca()\n", " ax.set_aspect(1./ax.get_data_ratio()) \n", " plt.tight_layout()\n", " plt.colorbar()\n", " \n", " # Save\n", " plt.savefig(os.path.join(run_output_path, \"space_initial.png\"))\n", " \n", " # Plot final step\n", " plt.title(\"Infected space at t={0}\".format(model.t-1))\n", " plt.pcolor(model.get_space_infected(model.t-1), vmin=-1, vmax=1, cmap=cmap)\n", " ax = f.gca()\n", " ax.set_aspect(1./ax.get_data_ratio()) \n", " plt.tight_layout()\n", " plt.colorbar()\n", " \n", " # Save\n", " plt.savefig(os.path.join(run_output_path, \"space_final.png\")) \n", " \n", "\n", "def store_model(model, output_path=\"output\"):\n", " \"\"\"\n", " Store a model to the model output path.\n", " \"\"\"\n", " # First, we need to make sure the directory exists.\n", " try:\n", " os.makedirs(output_path)\n", " except:\n", " pass\n", " \n", " \"\"\"\n", " Next, we need to create a unique timestamp for the model.\n", " We'll do that using a timestamp of the form: YYYYMMDD-Run#\n", " \n", " We then need to create that directory too.\n", " \"\"\"\n", " timestamp_suffix = time.strftime(\"%Y%m%d\")\n", " \n", " run_id = 0\n", " run_output_path = os.path.join(output_path,\n", " \"run-{0}-{1}\".format(timestamp_suffix,\n", " run_id))\n", " # Get a unique run #\n", " while os.path.exists(run_output_path):\n", " run_id += 1\n", " run_output_path = os.path.join(output_path,\n", " \"run-{0}-{1}\".format(timestamp_suffix,\n", " run_id)) \n", "\n", " try:\n", " os.makedirs(run_output_path)\n", " except:\n", " pass\n", " \n", " \"\"\"\n", " Finally, we need to store data and figures to the path.\n", " \"\"\"\n", " store_model_parameters(model, run_output_path)\n", " store_model_csv(model, run_output_path)\n", " store_model_figures(model, run_output_path)" ] }, { "cell_type": "code", "execution_count": 36, "metadata": { "collapsed": false }, "outputs": [], "source": [ "# Finally, test our output method with the model.\n", "store_model(m)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# Running our parameter sweep" ] }, { "cell_type": "code", "execution_count": 37, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Running 10 samples for subsidy value 0.0, prob_hookup value 0.1\n", "Running 10 samples for subsidy value 0.0, prob_hookup value 0.5\n", "Running 10 samples for subsidy value 0.0, prob_hookup value 0.9\n", "Running 10 samples for subsidy value 0.33, prob_hookup value 0.1\n", "Running 10 samples for subsidy value 0.33, prob_hookup value 0.5\n", "Running 10 samples for subsidy value 0.33, prob_hookup value 0.9\n", "Running 10 samples for subsidy value 0.66, prob_hookup value 0.1\n", "Running 10 samples for subsidy value 0.66, prob_hookup value 0.5\n", "Running 10 samples for subsidy value 0.66, prob_hookup value 0.9\n", "Running 10 samples for subsidy value 1.0, prob_hookup value 0.1\n", "Running 10 samples for subsidy value 1.0, prob_hookup value 0.5\n", "Running 10 samples for subsidy value 1.0, prob_hookup value 0.9\n" ] } ], "source": [ "# Set number of samples per value and steps per sample\n", "num_samples = 10\n", "num_steps = 100\n", "\n", "# Set basic model parameters\n", "grid_size = 10\n", "num_people =10\n", "\n", "# Set subsidy values to \"sweep\" over\n", "subsidy_sweep_values = [0.0, 0.33, 0.66, 1.0]\n", "prob_hookup_values = [0.1, 0.5, 0.9]\n", "subsidy_sweep_output = []\n", "\n", "# Iterate over subsidy\n", "for subsidy_value in subsidy_sweep_values:\n", " # Iterate over prob_hookup\n", " for prob_hookup_value in prob_hookup_values:\n", " print(\"Running {0} samples for subsidy value {1}, prob_hookup value {2}\"\\\n", " .format(num_samples, subsidy_value, prob_hookup_value))\n", " for n in xrange(num_samples):\n", " # Output info\n", " m = Model(grid_size=grid_size,\n", " num_people=num_people,\n", " min_condom_budget=0.0,\n", " max_condom_budget=1.0,\n", " min_prob_hookup=prob_hookup_value-0.1,\n", " max_prob_hookup=prob_hookup_value+0.1,\n", " min_subsidy=subsidy_value,\n", " max_subsidy=subsidy_value)\n", "\n", " # Run the model for num-steps\n", " for t in xrange(num_steps):\n", " m.step()\n", "\n", " # Output our model\n", " store_model(m)" ] } ], "metadata": { "kernelspec": { "display_name": "Python 2", "language": "python", "name": "python2" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 2 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython2", "version": "2.7.3" } }, "nbformat": 4, "nbformat_minor": 0 }