GreenDelta / openlca-python-tutorial

Explains the usage of the openLCA API from Python (Jython)
Other
59 stars 17 forks source link

Select flow in database by name and provider #7

Open gvoigt opened 6 years ago

gvoigt commented 6 years ago

Getting a flow from the database elcd_3_2_greendelta_v2_16 is no problem with the following function

def find(db, clazz, name):
    """ Find something by name"""
    dao = Daos.createBaseDao(db, clazz)
    for item in dao.getAll():
        if item.name == name:
            return item

But if the flow has several providers how can I pick one? For example I can get the flow transport in t*km but I cannot choose the provider Lorry transport, Euro 0, 1, 2, 3, 4 mix, 22 t total weight, 17,3t max payload - RER. I don't even know how to verify which provider is assigned to the flow.

msrocka commented 6 years ago

The providers cannot be attached to a flow but to an exchange. An exchange is an input or output of a flow in a process. And there it is just a marker for the product system completion algorithms. In general, a provider of a product is a process with this product in an output exchange (and since openLCA 1.6+ a process with a provider of a waste treatment service is a process with a waste flow as input).

There are some helper methods in the openLCA core API for finding providers of flows, e.g.

from org.openlca.core.database import FlowDao, ProcessDao
from org.openlca.core.matrix.cache import FlowTypeTable, ProcessTable

f_table = FlowTypeTable.create(db)
p_table = ProcessTable.create(db, f_table)

my_product = FlowDao(db).getForName('p1')[0]
p_dao = ProcessDao(db)

for process_id in p_table.getProviders(my_product.id):
    process = p_dao.getForId(process_id)
    log.info('{}', process.name)
Brotrand commented 6 years ago

I tried to use your @msrocka code regarding the implementation of providers for flows in a process. The implementation of a flow in the existing process at my database works find, despite the fact that I can´t implement it with the corresbonding unit [t*km]. `

from org.openlca.core.database.derby import DerbyDatabase as Db
from java.io import File
import org.openlca.core.model as model
from org.openlca.core.database import ProcessDao
import util
from org.openlca.core.database import FlowDao
from org.openlca.core.matrix.cache import FlowTypeTable, ProcessTable

if __name__ == '__main__':
db_dir = File('C:\\Users\\user\\openLCA-data-1.4\\databases\\test_ProBas')
db = Db(db_dir)

# PROCESSES
# Find the process to be modified
dao_p = ProcessDao(db)
p = dao_p.getForName("Steel production")[0]

# FLOWS
# f_in is the input flow to be added to the process
f_in = util.find(db, model.Flow, 'Guetertransport-Dienstleistung (LKW-2010-mix-DE)') 
# f_out is the output flow (reference product) of the process
f_out = util.find(db, model.Flow, 'Steel production')

km = model.Unit()
# EXCHANGES
# e_out is the output exchange of the process
e_out = util.find_exchange(f_out, p)
# e_in is the new input exchange to be added to the process
e_in = model.Exchange()
e_in.input = True
e_in.flow = f_in
#e_in.unit = e_out.unit
e_in.unit = km
e_in.amountValue = 1.0
e_in.flowPropertyFactor = f_in.getReferenceFactor()  

f_table = FlowTypeTable.create(db)
p_table = ProcessTable.create(db, f_table)

my_product = FlowDao(db).getForName("Guetertransport-Dienstleistung (LKW-2010-mix-DE)")[0]

for e_in in p_table.getProviders(my_product.id):
    process = dao_p.getForId(e_in)
    log.info('{LKW-2010-mix-DE 2010 (System)}', process.name)    

# Add the input exchange to the process and update the process 
p.exchanges.add(e_in)
util.update(db, p)

db.close()

` I always get the following error:

console: Failed to install '': java.nio.charset.UnsupportedCharsetException: cp0.
log4j:WARN No appenders could be found for logger (org.openlca.core.database.derby)
log4j:WARN Please initialize the log4j system properly.
log4j:WARN See http://logging.apache.org/log4j/1.2/faq.html#noconfig for more info.
Traceback (most recent call last):
File "C:\Users\user\eclipse-workspace\test\Database.py", line 45, in <module>
        for e_in in p_table.getProviders(my_product.id):
AttributeError: 'org.openlca.core.matrix.cache.ProcessTable' object has no attribute 'getProviders'

` What am I doing wrong here? Thanks

msrocka commented 6 years ago

You are using openLCA 1.6, right? The method getProductProviders was renamed to getProviders in version 1.7 (as we now also support "providers of waste treatment services"). You can get the current beta version of openLCA 1.7 from the openLCA web site. Or you could try the getProductProviders method with openLCA 1.6.

Brotrand commented 6 years ago

With getProductProviders it worked. Thank you Yes, I am still using openLCA 1.6 and I will try to switch to the latest version.

Has the command for log.info('{LKW-2010-mix-DE 2010 (System)}', process.name) also changed? Because now, I get the error: `

Traceback (most recent call last):
File "C:\Users\user\eclipse-workspace\test\Database.py", line 47, in <module>
        log.info('{LKW-2010-mix-DE 2010 (System)}', process.name) 
NameError: name 'log' is not defined

`

Brotrand commented 6 years ago

Update: As I don´t have much experience with programming, I don´t know whether the different code I wrote is helpful. Nevertheless, I get the same output. I could update an existing process with a new Input (Flow with the corresbonding provider).

from org.openlca.core.database.derby import DerbyDatabase
from java.io import File
import org.openlca.core.model as model
from org.openlca.core.database import ProcessDao
import util

if __name__ == '__main__':
    folder = 'C:\\Users\\user\\openLCA-data-1.4\\databases\\test_ProBas'
    db = DerbyDatabase(File(folder))

    # Find the process to be modified
    dao = ProcessDao(db)
    p = dao.getForName("Steel production")[0]

# insert Flow and Provider
    transport = util.find(db, model.Flow, 'Guetertransport-Dienstleistung (LKW-2010-mix-DE)') 
    LKW = util.find(db, model.Process, 'LKW-2010-mix-DE 2010 (System)')
    t_in = util.create_exchange(transport, 1.0, is_input=True)
    t_in.defaultProviderId = LKW.id

    p.exchanges.add(t_in)
    util.insert(db, t_in)

    dao.update(p)
    db.close()