diff --git a/ilp-measurement.ipynb b/ilp-measurement.ipynb
index 1b3a231f0fe5e9490d8db646ceec8160cdab38c9..5c2adb11c6b4710fa5990559bb76dfcb0207d7bc 100644
--- a/ilp-measurement.ipynb
+++ b/ilp-measurement.ipynb
@@ -452,11 +452,11 @@
     "            ax.patch.set_alpha(1)\n",
     "            ax.patch.set_facecolor('white')\n",
     "\n",
-    "        first_ax = ax_arr if one_plot else ax_arr[0]\n",
-    "        plt.suptitle('ILP Generation Time', fontsize = 16)\n",
-    "        first_ax[0].set_title('Java')\n",
-    "        first_ax[1].set_title('Racket')\n",
-    "        first_ax[2].set_title('Larceny')\n",
+    "#        first_ax = ax_arr if one_plot else ax_arr[0]\n",
+    "#        plt.suptitle('ILP Generation Time', fontsize = 16)\n",
+    "#        first_ax[0].set_title('Java')\n",
+    "#        first_ax[1].set_title('Racket')\n",
+    "#        first_ax[2].set_title('Larceny')\n",
     "\n",
     "        # Fine-tune figure; make subplots close to each other and hide x ticks for\n",
     "        # all but bottom plots.\n",
@@ -512,11 +512,11 @@
     "            ax.patch.set_alpha(1)\n",
     "            ax.patch.set_facecolor('white')\n",
     "\n",
-    "        first_ax = ax_arr if one_plot else ax_arr[0]\n",
-    "        plt.suptitle('ILP Solving Time', fontsize = 16)\n",
-    "        first_ax[0].set_title('GLPK (Java)')\n",
-    "        first_ax[1].set_title('GLPK (Scheme)')\n",
-    "        first_ax[2].set_title('Gurobi (Scheme)')\n",
+    "#        first_ax = ax_arr if one_plot else ax_arr[0]\n",
+    "#        plt.suptitle('ILP Solving Time', fontsize = 16)\n",
+    "#        first_ax[0].set_title('GLPK (Java)')\n",
+    "#        first_ax[1].set_title('GLPK (Scheme)')\n",
+    "#        first_ax[2].set_title('Gurobi (Scheme)')\n",
     "\n",
     "        # Fine-tune figure; make subplots close to each other and hide x ticks for\n",
     "        # all but bottom plots.\n",
@@ -611,6 +611,13 @@
     "        draw_comp_sol(change, sol_params)"
    ]
   },
+  {
+   "cell_type": "markdown",
+   "metadata": {},
+   "source": [
+    "## Settings"
+   ]
+  },
   {
    "cell_type": "code",
    "execution_count": 20,
@@ -633,41 +640,51 @@
     "    s1, s2 = ratio.split('To')\n",
     "    return r'${0} \\rightarrow {1}$'.format(strategy_to_titel(s1, lshort)[1:-1], strategy_to_titel(s2, lshort)[1:-1])\n",
     "def change_to_title(change):\n",
-    "    if change == 'complex':\n",
-    "        change = 'mixed'\n",
+    "#    if change == 'complex':\n",
+    "#        change = 'mixed'\n",
     "    return change.title()"
    ]
   },
-  {
-   "cell_type": "markdown",
-   "metadata": {},
-   "source": [
-    "## Boxplots for generation times"
-   ]
-  },
   {
    "cell_type": "code",
-   "execution_count": 88,
+   "execution_count": 21,
    "metadata": {
-    "collapsed": true
+    "collapsed": false
    },
    "outputs": [],
    "source": [
-    "def setBoxColors(bp, c):\n",
-    "    plt.setp(bp['boxes'], color=c)\n",
-    "    plt.setp(bp['caps'], color=c)\n",
-    "#    plt.setp(bp['caps'][1], color=c)\n",
-    "    plt.setp(bp['whiskers'], color=c)\n",
-    "#    plt.setp(bp['whiskers'][1], color=c)\n",
-    "    plt.setp(bp['fliers'], color=c)\n",
-    "#    plt.setp(bp['fliers'][1], color=c)\n",
-    "    plt.setp(bp['medians'], color=c)\n",
-    "strategy_colors = {'noncached':'red', 'flush': 'green', 'normal': 'blue'}"
+    "def setBoxColors(bp, c, c2 = None, apply_to = None):\n",
+    "    if c2 is None:\n",
+    "        c2 = c\n",
+    "    set_c  = functools.partial(plt.setp, color=c)\n",
+    "    set_c2 = functools.partial(plt.setp, color=c2)\n",
+    "    elems_c  = ['boxes', 'caps', 'whiskers', 'fliers']\n",
+    "    elems_c2 = ['medians']\n",
+    "    if apply_to is None:\n",
+    "        # apply to all\n",
+    "        for elem in elems_c:\n",
+    "            set_c(bp[elem])\n",
+    "        for elem in elems_c2:\n",
+    "            set_c2(bp[elem])\n",
+    "    else:\n",
+    "        for elem in elems_c:\n",
+    "            set_c(bp[elem][apply_to])\n",
+    "        for elem in elems_c2:\n",
+    "            set_c2(bp[elem][apply_to])\n",
+    "strategy_colors = {'noncached':'yellow', 'flush': 'cyan', 'normal': 'blue'}\n",
+    "strategy_colors.update({k:('black', 'red') for k in ('NormalToFlushed', 'NormalToNoncached', 'FlushedToNoncached')})"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "metadata": {},
+   "source": [
+    "## Boxplots for generation times"
    ]
   },
   {
    "cell_type": "code",
-   "execution_count": 90,
+   "execution_count": 22,
    "metadata": {
     "collapsed": false,
     "scrolled": false
@@ -682,21 +699,18 @@
       " update,normal,flush,noncached\n",
       " sw,normal,flush,noncached\n",
       " res,normal,flush,noncached\n",
-      " complex,normal,flush,noncached\n",
       " mixed,normal,flush,noncached\n",
       "\n",
       "racket:\n",
       " update,normal,flush,noncached\n",
       " sw,normal,flush,noncached\n",
       " res,normal,flush,noncached\n",
-      " complex,normal,flush,noncached\n",
       " mixed,normal,flush,noncached\n",
       "\n",
       "larceny:\n",
       " update,normal,flush,noncached\n",
       " sw,normal,flush,noncached\n",
       " res,normal,flush,noncached\n",
-      " complex,normal,flush,noncached\n",
       " mixed,normal,flush,noncached\n"
      ]
     }
@@ -706,6 +720,8 @@
     "    sys.stdout.write('\\n{}:'.format(name))\n",
     "#    change, strategy = 'mixed', 'normal'\n",
     "    for change in kinds['changes']:\n",
+    "        if change == 'complex':\n",
+    "            continue\n",
     "#    if True:\n",
     "        sys.stdout.write('\\n {}'.format(change))\n",
     "#        if True:\n",
@@ -716,7 +732,7 @@
     "            setBoxColors(bp, strategy_colors[strategy])\n",
     "            axes = plt.gca()\n",
     "            axes.set_ylim([0,50])\n",
-    "            plt.title('{0} {1} {2}'.format(name.title(), change_to_title(change), strategy_to_titel(strategy)))\n",
+    "#            plt.title('{0} {1} {2}'.format(name.title(), change_to_title(change), strategy_to_titel(strategy)))\n",
     "            plt.ylabel('seconds')\n",
     "            plt.xlabel('step')\n",
     "            if change == 'mixed':\n",
@@ -737,7 +753,7 @@
   },
   {
    "cell_type": "code",
-   "execution_count": 89,
+   "execution_count": 23,
    "metadata": {
     "collapsed": false
    },
@@ -786,7 +802,7 @@
   },
   {
    "cell_type": "code",
-   "execution_count": 22,
+   "execution_count": 24,
    "metadata": {
     "collapsed": false
    },
@@ -814,7 +830,7 @@
     "    #    if True:\n",
     "        cdat = data[change]\n",
     "        plt.boxplot(cdat.transpose())\n",
-    "        plt.title('{0} {1}'.format(name.title(), change_to_title(change)))\n",
+    "#        plt.title('{0} {1}'.format(name.title(), change_to_title(change)))\n",
     "        plt.ylabel('seconds')\n",
     "        plt.xlabel('step')\n",
     "        plt.savefig('pngs/sol_bp_{0}_{1}.png'.format(name,change))\n",
@@ -835,7 +851,7 @@
   },
   {
    "cell_type": "code",
-   "execution_count": 23,
+   "execution_count": 25,
    "metadata": {
     "collapsed": true
    },
@@ -871,7 +887,7 @@
   },
   {
    "cell_type": "code",
-   "execution_count": 24,
+   "execution_count": 26,
    "metadata": {
     "collapsed": false,
     "scrolled": true
@@ -890,7 +906,7 @@
        "dtype([('dir', '<f8'), ('normalBaseline', '<f8'), ('flushedBaseline', '<f8'), ('noncachedBaseline', '<f8'), ('ratioNormalToFlushed', '<f8'), ('ratioNormalToNoncached', '<f8'), ('ratioFlushedToNoncached', '<f8'), ('speedupNormalToFlushed', '<f8'), ('speedupNormalToNoncached', '<f8'), ('speedupFlushedToNoncached', '<f8')])"
       ]
      },
-     "execution_count": 24,
+     "execution_count": 26,
      "metadata": {},
      "output_type": "execute_result"
     }
@@ -910,7 +926,7 @@
   },
   {
    "cell_type": "code",
-   "execution_count": 25,
+   "execution_count": 27,
    "metadata": {
     "collapsed": false,
     "scrolled": false
@@ -944,7 +960,7 @@
   },
   {
    "cell_type": "code",
-   "execution_count": 26,
+   "execution_count": 28,
    "metadata": {
     "collapsed": false
    },
@@ -978,7 +994,7 @@
   },
   {
    "cell_type": "code",
-   "execution_count": 27,
+   "execution_count": 29,
    "metadata": {
     "collapsed": false,
     "scrolled": true
@@ -1011,7 +1027,7 @@
   },
   {
    "cell_type": "code",
-   "execution_count": 28,
+   "execution_count": 30,
    "metadata": {
     "collapsed": false,
     "scrolled": false
@@ -1024,19 +1040,18 @@
       "Loaded 31 (0 zero-values) attribute metric run(s) from profiling/splitted/att-percentages_update.csv\n",
       "Loaded 31 (0 zero-values) attribute metric run(s) from profiling/splitted/att-percentages_sw.csv\n",
       "Loaded 31 (0 zero-values) attribute metric run(s) from profiling/splitted/att-percentages_res.csv\n",
-      "Loaded 11 (0 zero-values) attribute metric run(s) from profiling/splitted/att-percentages_complex.csv\n",
       "Loaded 2 (0 zero-values) attribute metric run(s) from profiling/splitted/att-percentages_mixed.csv\n"
      ]
     }
    ],
    "source": [
     "att_totals = {change: read_att_result(name = 'profiling/splitted/att-percentages_{}.csv'.format(change),\n",
-    "                                      adjust_number = False) for change in kinds['changes']}"
+    "                                      adjust_number = False) for change in kinds['changes'] if change != 'complex'}"
    ]
   },
   {
    "cell_type": "code",
-   "execution_count": 29,
+   "execution_count": 31,
    "metadata": {
     "collapsed": true
    },
@@ -1047,7 +1062,7 @@
   },
   {
    "cell_type": "code",
-   "execution_count": 30,
+   "execution_count": 32,
    "metadata": {
     "collapsed": false
    },
@@ -1061,18 +1076,19 @@
     "    @param:fname_part: unique filename part for storing plot\n",
     "    @param:rotation_xaxis: rotation of xaxis ticks (default: no rotation)\"\"\"\n",
     "    try:\n",
-    "        fig, axes = plt.subplots(ncols=len(kinds['changes']))\n",
+    "        changes_to_draw = [c for c in kinds['changes'] if c != 'complex']\n",
+    "        fig, axes = plt.subplots(ncols=len(changes_to_draw))\n",
     "#        if not rotation_xaxis:\n",
     "#            print dir(fig)\n",
-    "        fig.suptitle(title, fontsize = 16)\n",
+    "#        fig.suptitle(title, fontsize = 16)\n",
     "        l = ['normal', 'flushed']\n",
     "        if PRINT_NONCACHED:\n",
     "            l.append('noncached')\n",
-    "        for i, change in enumerate(kinds['changes']):\n",
+    "        for i, change in enumerate(changes_to_draw):\n",
     "            att_dat = att_totals[change]\n",
     "            axes[i].boxplot([att_dat[fcolumn(name)] for name in x],\n",
     "                             labels = [flabel(name) for name in x])\n",
-    "            axes[i].set_title(change_to_title(change), fontsize=10)\n",
+    "#            axes[i].set_title(change_to_title(change), fontsize=10)\n",
     "            if i > 0:\n",
     "                axes[i].set_yticklabels([])\n",
     "        for ax in axes.flatten():\n",
@@ -1097,20 +1113,86 @@
   },
   {
    "cell_type": "code",
-   "execution_count": 31,
+   "execution_count": 33,
    "metadata": {
     "collapsed": false
    },
-   "outputs": [],
+   "outputs": [
+    {
+     "name": "stdout",
+     "output_type": "stream",
+     "text": [
+      "Drawing baselines\n",
+      "Drawing ratios\n",
+      "Drawing speed-ups\n"
+     ]
+    }
+   ],
    "source": [
     "def baseline(x):\n",
     "    return '{}Baseline'.format('flushed' if x == 'flush' else x)\n",
+    "print 'Drawing baselines'\n",
     "draw_att(kinds['strategies'], baseline, functools.partial(strategy_to_titel, length = lshort),\n",
     "         'Attribute Baselines', 'att_box_bl')\n",
     "x = ['NormalToFlushed', 'NormalToNoncached', 'FlushedToNoncached']\n",
+    "print 'Drawing ratios'\n",
     "draw_att(x, lambda x: 'ratio{}'.format(x), strategy2_to_titel, 'Attribute Ratios', 'att_box_r', rotation_xaxis = 30)\n",
+    "print 'Drawing speed-ups'\n",
     "draw_att(x, lambda x: 'speedup{}'.format(x), strategy2_to_titel, 'Attribute Speedups', 'att_box_sp', rotation_xaxis = 30)"
    ]
+  },
+  {
+   "cell_type": "markdown",
+   "metadata": {},
+   "source": [
+    "## Graph for attribute metrics over steps"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 34,
+   "metadata": {
+    "collapsed": true
+   },
+   "outputs": [],
+   "source": [
+    "def draw_att_graph(kind, nr,log=False):\n",
+    "    f_pattern = 'profiling/splitted/att-totals-{0}-{1}-{2}.csv'\n",
+    "    cs = ['b',(0,0,0.5),'g',(0,0.5,0),'r',(0.7,0,0)]\n",
+    "    def cv_name(x):\n",
+    "        return int(x[-3:])\n",
+    "    try:\n",
+    "        dats = [(s,np.genfromtxt(f_pattern.format(kind,nr,s), delimiter=',', names=True,\n",
+    "                              converters={'name': cv_name})) for s in kinds['strategies']]\n",
+    "        for i,(label,dat) in enumerate(dats):\n",
+    "            plt.plot(dat['comp'],color=cs[2*i], label = label)\n",
+    "            plt.plot(dat['called'], ls=':',color=cs[2*i+1])\n",
+    "            if log:\n",
+    "                ax = plt.gca()\n",
+    "                ax.set_yscale('log')\n",
+    "        plt.legend(loc='best')\n",
+    "        fname_part = '{0}_{1}{2}'.format(kind,nr,'_log' if log else '')\n",
+    "        plt.savefig('doc/{}.pdf'.format(fname_part))\n",
+    "        !pdfcrop {'doc/{}.pdf'.format(fname_part)} {'doc/{}_cropped.pdf'.format(fname_part)} > /dev/null\n",
+    "        plt.savefig('pngs/{}.png'.format(fname_part))\n",
+    "    except Exception as e:\n",
+    "        print 'Error while drawing att graph for {0}: {1}'.format(kind, e)\n",
+    "        traceback.print_exc(file=sys.stdout)\n",
+    "    finally:\n",
+    "        plt.close()    "
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 35,
+   "metadata": {
+    "collapsed": false
+   },
+   "outputs": [],
+   "source": [
+    "draw_att_graph('mixed', '001')\n",
+    "draw_att_graph('mixed', '001', log = True)"
+   ]
   }
  ],
  "metadata": {
diff --git a/ilp_measurement.py b/ilp_measurement.py
index 8ce4b09188aff058de865cd45381fd14afcbd09d..beebcd95f0e8384a2c53aee8f428a3d744895b50 100644
--- a/ilp_measurement.py
+++ b/ilp_measurement.py
@@ -486,6 +486,43 @@ def avg(column, *files):
             return sum(values) / float(len(values))
     print { f : get_average_value(f) for f in files }
 
+@task(name = 'agt')
+def att_graph_totals():
+    def parse_name(d):
+        tokens = d.split('-')
+        if len(tokens) == 2:
+            return (d,'normal')
+        else:
+            return (tokens[0]+'-'+tokens[2],tokens[1])
+    files = glob('profiling/*/*-att.csv')
+    files.sort()
+    # strategy -> dir -> step -> (comp,called)
+    tups = {}
+    last_name = None
+    for f in files:
+        d,b = os.path.split(f)
+        name,strategy = parse_name(os.path.basename(d))
+        dirs  = tups.setdefault(strategy,{})
+        steps = dirs.setdefault(name,{})
+        if last_name != name:
+            last_comp,last_called=0,0
+#            print ' ** reset comp+called', strategy, last_name, '->', name
+        last_name = name
+        with open(f) as fd:
+            r = csv.reader(fd)
+            comp,called = reduce(lambda s,e: (s[0]+int(e[1]),s[1]+int(e[2])) if len(e)>0 else s, r, (-last_comp,-last_called))
+        steps[b[:2]] = (comp,called)
+        last_comp,last_called = (last_comp+comp,last_called+called)
+#        print strategy, name, b, comp, called, '(', last_comp, last_called, ')'
+#    print tups
+    for strategy,dirs in tups.iteritems():
+        for name, steps in dirs.iteritems():
+            with open('profiling/splitted/att-totals-{0}-{1}.csv'.format(name, strategy), 'w') as fd:
+                fd.write('step,comp,called\n')
+                for step in sorted(steps):
+                    csv.writer(fd).writerow([step]+list(steps[step]))
+
+
 if __name__ == '__main__':
     check()
     help()