Activities and exchanges

# Activities and Exchanges¶

This notebook shows how to use the `Activity` and `Exchange` classes.

In [1]:

    from brightway2 import *

Let's create a new project just for this notebook

In [2]:

    projects.set_current("cats and dogs")

Let's start with a new database:

In [3]:

    db = Database("a&e")

and insert some basic data:

In [4]:

    db.write({
        ("a&e", "cat"): {
            'name': 'cat',
            'unit': 'kilogram',
            'color': 'black',  # Custom field - you can add whatever fields you need
            'exchanges': [{
                'input': ('a&e', 'cat food'),
                'amount': 10,
                'type': 'technosphere'
            }, {
                'input': ('a&e', 'kitty litter'),
                'amount': 10,
                'type': 'technosphere'
            }, {
                'input': ('a&e', 'smell'),
                'amount': 1,
                'type': 'biosphere'
            }]
        },
        ("a&e", "kitty litter"): {'name': 'yuck'},
        ("a&e", "cat food"): {'name': 'yum'},
        ("a&e", "smell"): {'name': 'stinky', 'type': 'biosphere'},
    })

    Writing activities to SQLite3 database:
    0%  100%
    [####] | ETA[sec]: 0.000
    Total time elapsed: 0.026 sec

    Title: Writing activities to SQLite3 database:
      Started: 07/15/2016 11:50:08
      Finished: 07/15/2016 11:50:08
      Total time elapsed: 0.026 sec
      CPU %: 113.900000
      Memory %: 0.349951

We can get an activity with `.get()`:

In [5]:

    act = db.get("cat")
    act

Out[5]:

    'cat' (kilogram, None, None)

The `cat` process has no categories or location so far. Let's change that:

In [6]:

    act['location'] = 'inside'
    act['categories'] = ['felis', 'catus']
    act

Out[6]:

    'cat' (kilogram, inside, ['felis', 'catus'])

When we are ready, we can save our changes:

In [7]:

    act.save()

We can iterate over the available data fields:

In [8]:

    for key in act:
        print(key, ':', act[key])

    location : inside
    unit : kilogram
    database : a&e
    name : cat
    categories : ['felis', 'catus']
    color : black
    code : cat

Note that the fields `database` and `code` are added automatically for us.

There are only a few methods for an activity. We can see the activity key (combination of database and code):

In [9]:

    act.key

Out[9]:

    ('a&e', 'cat')

We can iterate over all exchanges:

In [10]:

    for exc in act.exchanges():
        print(exc)

    Exchange: 10 None 'yum' (None, None, None) to 'cat' (kilogram, inside, ['felis', 'catus'])>
    Exchange: 10 None 'yuck' (None, None, None) to 'cat' (kilogram, inside, ['felis', 'catus'])>
    Exchange: 1 None 'stinky' (None, None, None) to 'cat' (kilogram, inside, ['felis', 'catus'])>

Or just the technosphere/biosphere/production exchanges:

In [11]:

    print("technosphere:")
    for exc in act.technosphere():
        print(exc)
    print("biosphere:")
    for exc in act.biosphere():
        print(exc)
    print("production:")
    for exc in act.production():
        print(exc)

    technosphere:
    Exchange: 10 None 'yum' (None, None, None) to 'cat' (kilogram, inside, ['felis', 'catus'])>
    Exchange: 10 None 'yuck' (None, None, None) to 'cat' (kilogram, inside, ['felis', 'catus'])>
    biosphere:
    Exchange: 1 None 'stinky' (None, None, None) to 'cat' (kilogram, inside, ['felis', 'catus'])>
    production:

You can also count exchanges (or any of the specific types of exchanges):

In [12]:

    len(act.exchanges())

Out[12]:

    3

There weren't any production exchanges. Brightway2 will add a default production exchanges with amount of 1 when building the technosphere matrix if no production exchange is given.

We can also look at upstream exchanges - those that consume this activity's reference product. We don't have any yet, so let's create a new activity:

In [13]:

    na = db.new_activity("dog")
    na.save()

    ---------------------------------------------------------------------------
    ValidityError                             Traceback (most recent call last)
    <ipython-input-13-1ce2ba0be795> in <module>()
          1 na = db.new_activity("dog")
    ----> 2 na.save()

    /Users/cmutel/local35/bw3/lib/python3.5/site-packages/bw2data/project.py in writable_project(wrapped, instance, args, kwargs)
        383     if projects.read_only:
        384         raise ReadOnlyProject(READ_ONLY_PROJECT)
    --> 385     return wrapped(*args, **kwargs)

    /Users/cmutel/local35/bw3/lib/python3.5/site-packages/bw2data/backends/peewee/proxies.py in save(self)
        104             raise ValidityError("This activity can't be saved for the "
        105                 "following reasons\n\t* " + \
    --> 106                 "\n\t* ".join(self.valid(why=True)[1])
        107             )
        108

    ValidityError: This activity can't be saved for the following reasons
    	* Missing field ``name``

Oops, activities must have names. Let's fix that:

In [14]:

    na['name'] = 'fido'
    na.save()

We will also get a nice error message for invalid new exchanges:

In [15]:

    na.new_exchange().save()

    ---------------------------------------------------------------------------
    ValidityError                             Traceback (most recent call last)
    <ipython-input-15-514e23f89f03> in <module>()
    ----> 1 na.new_exchange().save()

    /Users/cmutel/local35/bw3/lib/python3.5/site-packages/bw2data/project.py in writable_project(wrapped, instance, args, kwargs)
        383     if projects.read_only:
        384         raise ReadOnlyProject(READ_ONLY_PROJECT)
    --> 385     return wrapped(*args, **kwargs)

    /Users/cmutel/local35/bw3/lib/python3.5/site-packages/bw2data/backends/peewee/proxies.py in save(self)
        268             raise ValidityError("This exchange can't be saved for the "
        269                 "following reasons\n\t* " + \
    --> 270                 "\n\t* ".join(self.valid(why=True)[1])
        271             )
        272

    ValidityError: This exchange can't be saved for the following reasons
    	* Missing field ``input``
    	* Invalid or missing field ``amount``
    	* Missing field ``type``

Let's add a link to our cat process. Don't worry, the dog won't really eat the cat!

In [16]:

    new_exc = na.new_exchange(input=act, amount=1, type='technosphere')
    new_exc.save()

We can now see that 'fido' links to 'cat':

In [17]:

    for exc in na.technosphere():
        print(exc)
    for exc in act.upstream():
        print(exc)

    Exchange: 1 kilogram 'cat' (kilogram, inside, ['felis', 'catus']) to 'fido' (None, GLO, None)>
    Exchange: 1 kilogram 'cat' (kilogram, inside, ['felis', 'catus']) to 'fido' (None, GLO, None)>

`exc.input` and `exc.output` will return activities:

In [18]:

    new_exc.input, new_exc.output

Out[18]:

    ('cat' (kilogram, inside, ['felis', 'catus']), 'fido' (None, GLO, None))

Exchanges have a few more methods:

In [19]:

    new_exc.unit, new_exc.amount, new_exc.uncertainty_type

Out[19]:

    ('kilogram', 1, stats_arrays.distributions.undefined.UndefinedUncertainty)

Let's add some uncertainty to this exchange (see http://stats-arrays.readthedocs.org/en/latest/):

In [20]:

    from stats_arrays import NormalUncertainty

    new_exc['uncertainty type'] = NormalUncertainty.id
    new_exc['loc'], new_exc['scale'] = 1, 0.25
    new_exc.save()

We can now get an uncertainty dictionary for use in `stats_arrays` functions:

In [21]:

    new_exc.uncertainty

Out[21]:

    {'loc': 1, 'scale': 0.25, 'uncertainty type': 3}

And can get a random sample:

In [22]:

    new_exc.random_sample(n=10)

Out[22]:

    array([ 0.99004329,  1.07175437,  0.47354696,  1.32863177,  1.38786416,
            1.40075775,  1.12460893,  1.08966507,  1.31904524,  1.27995624])

We can copy activities. This will copy the activities exchanges:

In [23]:

    kudu = act.copy(name="kudu", code='antelope')
    kudu

Out[23]:

    'kudu' (kilogram, inside, ['felis', 'catus'])

In [24]:

    for exc in kudu.exchanges():
        print(exc)

    Exchange: 10 None 'yum' (None, None, None) to 'kudu' (kilogram, inside, ['felis', 'catus'])>
    Exchange: 10 None 'yuck' (None, None, None) to 'kudu' (kilogram, inside, ['felis', 'catus'])>
    Exchange: 1 None 'stinky' (None, None, None) to 'kudu' (kilogram, inside, ['felis', 'catus'])>

Upstream exchanges are (of course) not copied:

In [25]:

    for exc in kudu.upstream():
        print(exc)

You can delete the some or all of an activities exchanges:

In [26]:

    print("Before:",len(kudu.exchanges()))
    kudu.biosphere().delete()
    print("After:", len(kudu.exchanges()))

    Before: 3
    After: 2

You can also delete activities:

In [27]:

    kudu.delete()

Our new activity is no longer in the database:

In [28]:

    kudu in db

Out[28]:

    False

In [ ]: