{"body": "
\n

# How to use Collectors with SimPy\u00b6

\n

If you have read and understood the previous sections, you won\u2019t have any trouble using Collectors to monitor your simulation processes.

\n

We\u2019ll now discuss two examples that show different ways Collectors can be used: You can either use one collector instance per process or let one instance monitor multiple processes at once.

\n

You should one collector per process if each process belongs to another class or if each process collects its data at another time. If your processes are all instances of the same class and if each instance collects data at the same time, you only need to use one collector instance. That might save you some memory.

\n
\n

## One collector per process\u00b6

\n

In the following example a `Process` is created. In\neach step, it generates some random numbers and then holds for a random amount\nof time (that\u2019s why we need one collector per process here).

\n

The process also creates one collector (`self.monitor`) which will collect the\nsimulation time, the values for `a` and `b`, the manually passed values for\n`diff` and finally the square of `c`. The resulting collector instance will\nthus have the attributes `time`, `a`, `b`, `diff` and `square`.

\n

After the simulation has finished, NumPy arrays\nwill be created and show how you can easily work with them or create some charts\nusing Matplotlib.

\n

    >>> import random\n>>>\n>>> import matplotlib.pyplot as plt\n>>> from numpy import array, float64\n>>> from SimPy.Simulation import Simulation, Process, hold\n>>>\n>>> from collectors import Collector, get, manual\n>>>\n>>>\n>>> class MyProc(Process):\n...     def __init__(self, sim):\n...         Process.__init__(self, sim=sim)\n...         self.a = 0\n...         self.b = 0\n...         self.c = 0\n...\n...         self.monitor = Collector(\n...             ('time', sim.now),\n...             get(self, 'a', 'b'),\n...             ('diff', manual),\n...             ('square', lambda: self.c ** 2),\n...         )\n...\n...     def run(self):\n...         while True:\n...             self.a += random.random()\n...             self.b += random.randint(1, 2)\n...             self.c += random.randint(2, 4)\n...\n...             self.monitor(diff=self.c-self.b)\n...\n...             yield hold, self, random.randint(1, 4)\n...\n>>> # Run the simulation\n>>> random.seed(42)\n>>> sim = Simulation()\n>>> proc = MyProc(sim)\n>>> sim.activate(proc, proc.run())\n>>> sim.simulate(until=10)\n'SimPy: Normal exit'\n>>>\n>>> # NumPy helps you with the statistics and other calculations.\n>>> # Note: specification of dtype gives you a massive speed-up!\n>>> a = array(proc.monitor.a, dtype=float64)\n>>> # NumPy: average, std. deviation, variance\n>>> print 'a stats:', a.mean(), a.std(), a.var()\na stats: 2.04867732762 0.947900129333 0.898514655189\n>>>\n>>> # This one creates a multi-dimensional array\n>>> np_mon = array(proc.monitor, dtype=float64)\n>>> # Get the average of all monitored proc.b\n>>> print 'b stats:', np_mon[2].mean()\nb stats: 5.57142857143\n>>> # Get the std. deviation of all monitored proc.c\n>>> print 'c stats:', np_mon[3].std()\nc stats: 3.09047252183\n>>>\n>>> # Matplotlib plots your data:\n>>> # Either directly from a monitor ...\n>>> p = plt.plot(proc.monitor.time, proc.monitor.a, 'b')\n>>> # ... or the NumPy array\n>>> p = plt.plot(np_mon[0], np_mon[2], 'r')\n>>> plt.show()\n

\n
\n
\n
\n

## One collector for multiple processes\u00b6

\n

This example shows a very simple process whose PEM will be executed each time\nstep. This enables us to use one collector instance to monitor the attribute\n`a` of all processes and the simulation time.

\n

We also use SimPy\u2019s brand-new `peek()` and\n`step()` methods here which will be introduced\nwith version 2.1.

\n

    >>> from SimPy.Simulation import Simulation, Process, hold\n>>> from collectors import Collector, get_objects\n>>>\n>>> class MyProc(Process):\n...     """docstring for MyProc2"""\n...     def __init__(self, sim, pid):\n...         Process.__init__(self, sim=sim)\n...         self._pid = 'p%d' % pid\n...         self.a = 0\n...\n...     def run(self):\n...         while True:\n...             self.a += 1\n...\n>>> sim = Simulation()\n>>> procs = [MyProc(sim, i) for i in range(10)]\n>>> for proc in procs:\n...     sim.activate(proc, proc.run())\n...\n>>> # This coll. will have the attributes "t", "p0_a", "p1_a", ..., "p9_a"\n>>> # and monitor the simulation time as well as the values of "a" for each\n>>> # process.\n>>> monitor = Collector(('t', sim.now), get_objects(procs, 'pid', 'a'))\n>>>\n>>> # Run the simulation by using the band-new "peek()" and "step()".\n>>> while sim.peek() < 10:\n...     sim.step()\n...     monitor()\n

\n
\n
\n
\n", "display_toc": true, "title": "How to use Collectors with SimPy", "sourcename": "simpy.txt", "current_page_name": "simpy", "next": {"link": "../ref/", "title": "API-Reference"}, "rellinks": [["genindex", "General Index", "I", "index"], ["modindex", "Global Module Index", "M", "modules"], ["ref/index", "API-Reference", "N", "next"], ["storages", "How to use the storage backends", "P", "previous"]], "meta": {}, "parents": [], "toc": "

\n
- How to use Collectors with SimPy
  \n
  - One collector per process
  \n
  - One collector for multiple processes
  \n
  \n
\n

\n", "prev": {"link": "../storages/", "title": "How to use the storage backends"}, "metatags": ""}