| { |
| "cells": [ |
| { |
| "cell_type": "code", |
| "execution_count": 1, |
| "metadata": { |
| "collapsed": true |
| }, |
| "outputs": [], |
| "source": [ |
| "import logging\n", |
| "reload(logging)\n", |
| "logging.basicConfig(\n", |
| " format='%(asctime)-9s %(levelname)-8s: %(message)s',\n", |
| " datefmt='%I:%M:%S')\n", |
| "\n", |
| "# Enable logging at INFO level\n", |
| "logging.getLogger().setLevel(logging.INFO)" |
| ] |
| }, |
| { |
| "cell_type": "code", |
| "execution_count": 2, |
| "metadata": { |
| "collapsed": false |
| }, |
| "outputs": [ |
| { |
| "name": "stdout", |
| "output_type": "stream", |
| "text": [ |
| "Populating the interactive namespace from numpy and matplotlib\n" |
| ] |
| } |
| ], |
| "source": [ |
| "# Generate plots inline\n", |
| "%pylab inline\n", |
| "\n", |
| "import json\n", |
| "import os\n", |
| "\n", |
| "# Support to access the remote target\n", |
| "import devlib\n", |
| "from env import TestEnv\n", |
| "\n", |
| "# Support to configure and run RTApp based workloads\n", |
| "from wlgen import RTA, Ramp, Step, Pulse, Periodic" |
| ] |
| }, |
| { |
| "cell_type": "markdown", |
| "metadata": {}, |
| "source": [ |
| "# Test environment setup" |
| ] |
| }, |
| { |
| "cell_type": "code", |
| "execution_count": 3, |
| "metadata": { |
| "collapsed": false |
| }, |
| "outputs": [ |
| { |
| "name": "stderr", |
| "output_type": "stream", |
| "text": [ |
| "04:26:17 INFO : Target - Using base path: /home/derkling/Code/lisa\n", |
| "04:26:17 INFO : Target - Loading custom (inline) target configuration\n", |
| "04:26:17 INFO : Target - Devlib modules to load: []\n", |
| "04:26:17 INFO : Target - Connecting host target:\n", |
| "04:26:17 INFO : Target - username : put_here_your_username\n", |
| "04:26:17 INFO : Target - password : \n" |
| ] |
| }, |
| { |
| "name": "stdout", |
| "output_type": "stream", |
| "text": [ |
| "sudo password:········\n" |
| ] |
| }, |
| { |
| "name": "stderr", |
| "output_type": "stream", |
| "text": [ |
| "04:26:21 INFO : Target - Initializing target workdir:\n", |
| "04:26:21 INFO : Target - /tmp\n", |
| "04:26:21 INFO : Target - Topology:\n", |
| "04:26:21 INFO : Target - [[0, 1, 2, 3, 4, 5, 6, 7]]\n", |
| "04:26:21 WARNING : Target - Unable to identify cluster frequencies\n", |
| "04:26:21 INFO : TestEnv - Set results folder to:\n", |
| "04:26:21 INFO : TestEnv - /home/derkling/Code/lisa/results/20160225_162621\n", |
| "04:26:21 INFO : TestEnv - Experiment results available also in:\n", |
| "04:26:21 INFO : TestEnv - /home/derkling/Code/lisa/results_latest\n" |
| ] |
| } |
| ], |
| "source": [ |
| "# Let's use the local host as a target\n", |
| "te = TestEnv(\n", |
| " target_conf={\n", |
| " \"platform\": 'host',\n", |
| " \"username\": 'put_here_your_username'\n", |
| " })" |
| ] |
| }, |
| { |
| "cell_type": "markdown", |
| "metadata": {}, |
| "source": [ |
| "# Create a new RTA workload generator object" |
| ] |
| }, |
| { |
| "cell_type": "markdown", |
| "metadata": {}, |
| "source": [ |
| "The wlgen::RTA class is a workload generator which exposes an API to configure\n", |
| "RTApp based workload as well as to execute them on a target." |
| ] |
| }, |
| { |
| "cell_type": "code", |
| "execution_count": 4, |
| "metadata": { |
| "collapsed": false |
| }, |
| "outputs": [ |
| { |
| "name": "stderr", |
| "output_type": "stream", |
| "text": [ |
| "04:26:21 INFO : WlGen - Setup new workload example\n" |
| ] |
| } |
| ], |
| "source": [ |
| "# Create a new RTApp workload generator\n", |
| "rtapp = RTA(\n", |
| " \n", |
| " target=te.target, # Target execution on the local machine\n", |
| " \n", |
| " name='example', # This is the name of the JSON configuration file reporting\n", |
| " # the generated RTApp configuration\n", |
| " \n", |
| " calibration={0: 10, 1: 11, 2: 12, 3: 13} # These are a set of fake\n", |
| " # calibration values\n", |
| ")" |
| ] |
| }, |
| { |
| "cell_type": "markdown", |
| "metadata": {}, |
| "source": [ |
| "# Workload Generation Examples" |
| ] |
| }, |
| { |
| "cell_type": "markdown", |
| "metadata": {}, |
| "source": [ |
| "## Single periodic task" |
| ] |
| }, |
| { |
| "cell_type": "markdown", |
| "metadata": {}, |
| "source": [ |
| "An RTApp workload is defined by specifying a **kind**, which represents the way\n", |
| "we want to defined the behavior of each task.<br>\n", |
| "The most common kind is **profile**, which allows to define each task using one\n", |
| "of the predefined **profile** supported by the RTA base class.<br>\n", |
| "<br>\n", |
| "The following example shows how to generate a \"periodic\" task<br>" |
| ] |
| }, |
| { |
| "cell_type": "code", |
| "execution_count": 5, |
| "metadata": { |
| "code_folding": [], |
| "collapsed": false |
| }, |
| "outputs": [ |
| { |
| "name": "stderr", |
| "output_type": "stream", |
| "text": [ |
| "04:26:21 INFO : RTApp - Workload duration defined by longest task\n", |
| "04:26:21 INFO : RTApp - Default policy: SCHED_OTHER\n", |
| "04:26:21 INFO : RTApp - ------------------------\n", |
| "04:26:21 INFO : RTApp - task [task_per20], sched: {'policy': 'FIFO'}\n", |
| "04:26:21 INFO : RTApp - | calibration CPU: 0\n", |
| "04:26:21 INFO : RTApp - | loops count: 1\n", |
| "04:26:21 INFO : RTApp - + phase_000001: duration 5.000000 [s] (50 loops)\n", |
| "04:26:21 INFO : RTApp - | period 100000 [us], duty_cycle 20 %\n", |
| "04:26:21 INFO : RTApp - | run_time 20000 [us], sleep_time 80000 [us]\n" |
| ] |
| } |
| ], |
| "source": [ |
| "# Configure this RTApp instance to:\n", |
| "rtapp.conf(\n", |
| " \n", |
| " # 1. generate a \"profile based\" set of tasks\n", |
| " kind='profile',\n", |
| " \n", |
| " # 2. define the \"profile\" of each task\n", |
| " params={\n", |
| " \n", |
| " # 3. PERIODIC task\n", |
| " # \n", |
| " # This class defines a task which load is periodic with a configured\n", |
| " # period and duty-cycle.\n", |
| " # \n", |
| " # This class is a specialization of the 'pulse' class since a periodic\n", |
| " # load is generated as a sequence of pulse loads.\n", |
| " # \n", |
| " # Args:\n", |
| " # cuty_cycle_pct (int, [0-100]): the pulses load [%]\n", |
| " # default: 50[%]\n", |
| " # duration_s (float): the duration in [s] of the entire workload\n", |
| " # default: 1.0[s]\n", |
| " # period_ms (float): the period used to define the load in [ms]\n", |
| " # default: 100.0[ms]\n", |
| " # delay_s (float): the delay in [s] before ramp start\n", |
| " # default: 0[s]\n", |
| " # sched (dict): the scheduler configuration for this task\n", |
| " 'task_per20': Periodic(\n", |
| " period_ms=100, # period\n", |
| " duty_cycle_pct=20, # duty cycle\n", |
| " duration_s=5, # duration\n", |
| " cpus=None, # run on all CPUS\n", |
| " sched={\n", |
| " \"policy\": \"FIFO\", # Run this task as a SCHED_FIFO task\n", |
| " },\n", |
| " delay_s=0 # start at the start of RTApp\n", |
| " ).get(),\n", |
| " \n", |
| " },\n", |
| " \n", |
| " # 4. use this folder for task logfiles\n", |
| " run_dir='/tmp'\n", |
| " \n", |
| ");" |
| ] |
| }, |
| { |
| "cell_type": "markdown", |
| "metadata": {}, |
| "source": [ |
| "The output of the previous cell reports the main properties of the generated\n", |
| "tasks. Thus for example we see that the first task is configure to be:\n", |
| "1. named **task_per20**\n", |
| "2. will be executed as a **SCHED_FIFO** task\n", |
| "3. generating a load which is **calibrated** with respect to the **CPU 0**\n", |
| "3. with one single \"phase\" which defines a peripodic load for the **duration** of **5[s]**\n", |
| "4. that periodic load consistes of **50 cycles**\n", |
| "5. each cycle has a **period** of **100[ms]** and a **duty-cycle** of **20%**\n", |
| "6. which means that the task, for every cycle, will **run** for **20[ms]** and then sleep for **20[ms]** \n", |
| "\n", |
| "All these properties are translated into a JSON configuration file for RTApp.<br>\n", |
| "Let see what it looks like the generated configuration file:" |
| ] |
| }, |
| { |
| "cell_type": "code", |
| "execution_count": 6, |
| "metadata": { |
| "collapsed": false |
| }, |
| "outputs": [ |
| { |
| "name": "stdout", |
| "output_type": "stream", |
| "text": [ |
| "{\n", |
| " \"tasks\": {\n", |
| " \"task_per20\": {\n", |
| " \"policy\": \"SCHED_FIFO\", \n", |
| " \"phases\": {\n", |
| " \"p000001\": {\n", |
| " \"run\": 20000, \n", |
| " \"timer\": {\n", |
| " \"ref\": \"task_per20\", \n", |
| " \"period\": 100000\n", |
| " }, \n", |
| " \"loop\": 50\n", |
| " }\n", |
| " }, \n", |
| " \"loop\": 1\n", |
| " }\n", |
| " }, \n", |
| " \"global\": {\n", |
| " \"duration\": -1, \n", |
| " \"logdir\": \"/tmp\", \n", |
| " \"default_policy\": \"SCHED_OTHER\", \n", |
| " \"calibration\": 10\n", |
| " }\n", |
| "}\n" |
| ] |
| } |
| ], |
| "source": [ |
| "# Dump the configured JSON file for that task\n", |
| "with open(\"./example_00.json\") as fh:\n", |
| " rtapp_config = json.load(fh)\n", |
| "print json.dumps(rtapp_config, indent=4)" |
| ] |
| }, |
| { |
| "cell_type": "markdown", |
| "metadata": {}, |
| "source": [ |
| "## Workload mix" |
| ] |
| }, |
| { |
| "cell_type": "markdown", |
| "metadata": {}, |
| "source": [ |
| "Using the wlgen::RTA workload generator we can easily create multiple tasks, each one with different \"profiles\", which are executed once the rtapp application is started in the target.<br>\n", |
| "<br>\n", |
| "In the following example we configure a workload mix composed by a RAMP task, a STEP task and a PULSE task:" |
| ] |
| }, |
| { |
| "cell_type": "code", |
| "execution_count": 7, |
| "metadata": { |
| "code_folding": [], |
| "collapsed": false |
| }, |
| "outputs": [ |
| { |
| "name": "stderr", |
| "output_type": "stream", |
| "text": [ |
| "04:26:22 INFO : RTApp - Workload duration defined by longest task\n", |
| "04:26:22 INFO : RTApp - Default policy: SCHED_OTHER\n", |
| "04:26:22 INFO : RTApp - ------------------------\n", |
| "04:26:22 INFO : RTApp - task [task_pls5-80], sched: using default policy\n", |
| "04:26:22 INFO : RTApp - | start delay: 0.500000 [s]\n", |
| "04:26:22 INFO : RTApp - | calibration CPU: 0\n", |
| "04:26:22 INFO : RTApp - | loops count: 1\n", |
| "04:26:22 INFO : RTApp - + phase_000001: duration 1.000000 [s] (10 loops)\n", |
| "04:26:22 INFO : RTApp - | period 100000 [us], duty_cycle 65 %\n", |
| "04:26:22 INFO : RTApp - | run_time 65000 [us], sleep_time 35000 [us]\n", |
| "04:26:22 INFO : RTApp - + phase_000002: duration 1.000000 [s] (10 loops)\n", |
| "04:26:22 INFO : RTApp - | period 100000 [us], duty_cycle 5 %\n", |
| "04:26:22 INFO : RTApp - | run_time 5000 [us], sleep_time 95000 [us]\n", |
| "04:26:22 INFO : RTApp - ------------------------\n", |
| "04:26:22 INFO : RTApp - task [task_rmp20_5-60], sched: using default policy\n", |
| "04:26:22 INFO : RTApp - | calibration CPU: 0\n", |
| "04:26:22 INFO : RTApp - | loops count: 1\n", |
| "04:26:22 INFO : RTApp - | CPUs affinity: 0\n", |
| "04:26:22 INFO : RTApp - + phase_000001: duration 1.000000 [s] (10 loops)\n", |
| "04:26:22 INFO : RTApp - | period 100000 [us], duty_cycle 5 %\n", |
| "04:26:22 INFO : RTApp - | run_time 5000 [us], sleep_time 95000 [us]\n", |
| "04:26:22 INFO : RTApp - + phase_000002: duration 1.000000 [s] (10 loops)\n", |
| "04:26:22 INFO : RTApp - | period 100000 [us], duty_cycle 25 %\n", |
| "04:26:22 INFO : RTApp - | run_time 25000 [us], sleep_time 75000 [us]\n", |
| "04:26:22 INFO : RTApp - + phase_000003: duration 1.000000 [s] (10 loops)\n", |
| "04:26:22 INFO : RTApp - | period 100000 [us], duty_cycle 45 %\n", |
| "04:26:22 INFO : RTApp - | run_time 45000 [us], sleep_time 55000 [us]\n", |
| "04:26:22 INFO : RTApp - + phase_000004: duration 1.000000 [s] (10 loops)\n", |
| "04:26:22 INFO : RTApp - | period 100000 [us], duty_cycle 65 %\n", |
| "04:26:22 INFO : RTApp - | run_time 65000 [us], sleep_time 35000 [us]\n", |
| "04:26:22 INFO : RTApp - ------------------------\n", |
| "04:26:22 INFO : RTApp - task [task_stp10-50], sched: using default policy\n", |
| "04:26:22 INFO : RTApp - | start delay: 0.500000 [s]\n", |
| "04:26:22 INFO : RTApp - | calibration CPU: 0\n", |
| "04:26:22 INFO : RTApp - | loops count: 1\n", |
| "04:26:22 INFO : RTApp - + phase_000001: sleep 1.000000 [s]\n", |
| "04:26:22 INFO : RTApp - + phase_000002: duration 1.000000 [s] (10 loops)\n", |
| "04:26:22 INFO : RTApp - | period 100000 [us], duty_cycle 50 %\n", |
| "04:26:22 INFO : RTApp - | run_time 50000 [us], sleep_time 50000 [us]\n" |
| ] |
| } |
| ], |
| "source": [ |
| "# Configure this RTApp instance to:\n", |
| "rtapp.conf(\n", |
| " # 1. generate a \"profile based\" set of tasks\n", |
| " kind='profile',\n", |
| " \n", |
| " # 2. define the \"profile\" of each task\n", |
| " params={\n", |
| " \n", |
| " # 3. RAMP task\n", |
| " #\n", |
| " # This class defines a task which load is a ramp with a configured number\n", |
| " # of steps according to the input parameters.\n", |
| " # \n", |
| " # Args:\n", |
| " # start_pct (int, [0-100]): the initial load [%], (default 0[%])\n", |
| " # end_pct (int, [0-100]): the final load [%], (default 100[%])\n", |
| " # delta_pct (int, [0-100]): the load increase/decrease [%],\n", |
| " # default: 10[%]\n", |
| " # increase if start_prc < end_prc\n", |
| " # decrease if start_prc > end_prc\n", |
| " # time_s (float): the duration in [s] of each load step\n", |
| " # default: 1.0[s]\n", |
| " # period_ms (float): the period used to define the load in [ms]\n", |
| " # default: 100.0[ms]\n", |
| " # delay_s (float): the delay in [s] before ramp start\n", |
| " # default: 0[s]\n", |
| " # loops (int): number of time to repeat the ramp, with the\n", |
| " # specified delay in between\n", |
| " # default: 0\n", |
| " # sched (dict): the scheduler configuration for this task\n", |
| " # cpus (list): the list of CPUs on which task can run\n", |
| " 'task_rmp20_5-60': Ramp(\n", |
| " period_ms=100, # period\n", |
| " start_pct=5, # intial load\n", |
| " end_pct=65, # end load\n", |
| " delta_pct=20, # load % increase...\n", |
| " time_s=1, # ... every 1[s]\n", |
| " cpus=\"0\" # run just on first CPU\n", |
| " ).get(),\n", |
| " \n", |
| " # 4. STEP task\n", |
| " # \n", |
| " # This class defines a task which load is a step with a configured\n", |
| " # initial and final load.\n", |
| " # \n", |
| " # Args:\n", |
| " # start_pct (int, [0-100]): the initial load [%]\n", |
| " # default 0[%])\n", |
| " # end_pct (int, [0-100]): the final load [%]\n", |
| " # default 100[%]\n", |
| " # time_s (float): the duration in [s] of the start and end load\n", |
| " # default: 1.0[s]\n", |
| " # period_ms (float): the period used to define the load in [ms]\n", |
| " # default 100.0[ms]\n", |
| " # delay_s (float): the delay in [s] before ramp start\n", |
| " # default 0[s]\n", |
| " # loops (int): number of time to repeat the ramp, with the\n", |
| " # specified delay in between\n", |
| " # default: 0\n", |
| " # sched (dict): the scheduler configuration for this task\n", |
| " # cpus (list): the list of CPUs on which task can run\n", |
| " 'task_stp10-50': Step(\n", |
| " period_ms=100, # period\n", |
| " start_pct=0, # intial load\n", |
| " end_pct=50, # end load\n", |
| " time_s=1, # ... every 1[s]\n", |
| " delay_s=0.5 # start .5[s] after the start of RTApp\n", |
| " ).get(),\n", |
| " \n", |
| " # 5. PULSE task\n", |
| " #\n", |
| " # This class defines a task which load is a pulse with a configured\n", |
| " # initial and final load.\n", |
| " # \n", |
| " # The main difference with the 'step' class is that a pulse workload is\n", |
| " # by definition a 'step down', i.e. the workload switch from an finial\n", |
| " # load to a final one which is always lower than the initial one.\n", |
| " # Moreover, a pulse load does not generate a sleep phase in case of 0[%]\n", |
| " # load, i.e. the task ends as soon as the non null initial load has\n", |
| " # completed.\n", |
| " # \n", |
| " # Args:\n", |
| " # start_pct (int, [0-100]): the initial load [%]\n", |
| " # default: 0[%]\n", |
| " # end_pct (int, [0-100]): the final load [%]\n", |
| " # default: 100[%]\n", |
| " # NOTE: must be lower than start_pct value\n", |
| " # time_s (float): the duration in [s] of the start and end load\n", |
| " # default: 1.0[s]\n", |
| " # NOTE: if end_pct is 0, the task end after the\n", |
| " # start_pct period completed\n", |
| " # period_ms (float): the period used to define the load in [ms]\n", |
| " # default: 100.0[ms]\n", |
| " # delay_s (float): the delay in [s] before ramp start\n", |
| " # default: 0[s]\n", |
| " # loops (int): number of time to repeat the ramp, with the\n", |
| " # specified delay in between\n", |
| " # default: 0\n", |
| " # sched (dict): the scheduler configuration for this task\n", |
| " # cpus (list): the list of CPUs on which task can run\n", |
| " 'task_pls5-80': Pulse(\n", |
| " period_ms=100, # period\n", |
| " start_pct=65, # intial load\n", |
| " end_pct=5, # end load\n", |
| " time_s=1, # ... every 1[s]\n", |
| " delay_s=0.5 # start .5[s] after the start of RTApp\n", |
| " ).get(),\n", |
| " \n", |
| " \n", |
| " },\n", |
| " \n", |
| " # 6. use this folder for task logfiles\n", |
| " run_dir='/tmp'\n", |
| " \n", |
| ");" |
| ] |
| }, |
| { |
| "cell_type": "code", |
| "execution_count": 8, |
| "metadata": { |
| "collapsed": false |
| }, |
| "outputs": [ |
| { |
| "name": "stdout", |
| "output_type": "stream", |
| "text": [ |
| "{\n", |
| " \"tasks\": {\n", |
| " \"task_rmp20_5-60\": {\n", |
| " \"policy\": \"SCHED_OTHER\", \n", |
| " \"phases\": {\n", |
| " \"p000004\": {\n", |
| " \"run\": 65000, \n", |
| " \"timer\": {\n", |
| " \"ref\": \"task_rmp20_5-60\", \n", |
| " \"period\": 100000\n", |
| " }, \n", |
| " \"loop\": 10\n", |
| " }, \n", |
| " \"p000003\": {\n", |
| " \"run\": 45000, \n", |
| " \"timer\": {\n", |
| " \"ref\": \"task_rmp20_5-60\", \n", |
| " \"period\": 100000\n", |
| " }, \n", |
| " \"loop\": 10\n", |
| " }, \n", |
| " \"p000002\": {\n", |
| " \"run\": 25000, \n", |
| " \"timer\": {\n", |
| " \"ref\": \"task_rmp20_5-60\", \n", |
| " \"period\": 100000\n", |
| " }, \n", |
| " \"loop\": 10\n", |
| " }, \n", |
| " \"p000001\": {\n", |
| " \"run\": 5000, \n", |
| " \"timer\": {\n", |
| " \"ref\": \"task_rmp20_5-60\", \n", |
| " \"period\": 100000\n", |
| " }, \n", |
| " \"loop\": 10\n", |
| " }\n", |
| " }, \n", |
| " \"cpus\": [\n", |
| " 0\n", |
| " ], \n", |
| " \"loop\": 1\n", |
| " }, \n", |
| " \"task_pls5-80\": {\n", |
| " \"policy\": \"SCHED_OTHER\", \n", |
| " \"phases\": {\n", |
| " \"p000002\": {\n", |
| " \"run\": 5000, \n", |
| " \"timer\": {\n", |
| " \"ref\": \"task_pls5-80\", \n", |
| " \"period\": 100000\n", |
| " }, \n", |
| " \"loop\": 10\n", |
| " }, \n", |
| " \"p000001\": {\n", |
| " \"run\": 65000, \n", |
| " \"timer\": {\n", |
| " \"ref\": \"task_pls5-80\", \n", |
| " \"period\": 100000\n", |
| " }, \n", |
| " \"loop\": 10\n", |
| " }, \n", |
| " \"p000000\": {\n", |
| " \"delay\": 500000\n", |
| " }\n", |
| " }, \n", |
| " \"loop\": 1\n", |
| " }, \n", |
| " \"task_stp10-50\": {\n", |
| " \"policy\": \"SCHED_OTHER\", \n", |
| " \"phases\": {\n", |
| " \"p000002\": {\n", |
| " \"run\": 50000, \n", |
| " \"timer\": {\n", |
| " \"ref\": \"task_stp10-50\", \n", |
| " \"period\": 100000\n", |
| " }, \n", |
| " \"loop\": 10\n", |
| " }, \n", |
| " \"p000001\": {\n", |
| " \"sleep\": 1000000, \n", |
| " \"loop\": 1\n", |
| " }, \n", |
| " \"p000000\": {\n", |
| " \"delay\": 500000\n", |
| " }\n", |
| " }, \n", |
| " \"loop\": 1\n", |
| " }\n", |
| " }, \n", |
| " \"global\": {\n", |
| " \"duration\": -1, \n", |
| " \"logdir\": \"/tmp\", \n", |
| " \"default_policy\": \"SCHED_OTHER\", \n", |
| " \"calibration\": 10\n", |
| " }\n", |
| "}\n" |
| ] |
| } |
| ], |
| "source": [ |
| "# Dump the configured JSON file for that task\n", |
| "with open(\"./example_00.json\") as fh:\n", |
| " rtapp_config = json.load(fh)\n", |
| "print json.dumps(rtapp_config, indent=4)" |
| ] |
| } |
| ], |
| "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.9" |
| } |
| }, |
| "nbformat": 4, |
| "nbformat_minor": 0 |
| } |