Beispiel #1
0
 def __init__(self):
     self._compartments = Compartment.from_json(load_compartments())
     self._flows = LogicalSet(LogicalFlow)
     self._quantities = LogicalSet(LogicalQuantity)
Beispiel #2
0
class LcFlows(object):

    @classmethod
    def from_json(cls, catalog, j):
        db = cls()
        db._compartments = Compartment.from_json(j['compartments'])

        def to_ref(x):
            return CatalogRef(catalog, int(x['index']), x['entity'])

        for f in j['flows']:
            flow_ref = to_ref(f[0])
            db.add_flow(flow_ref)
            if len(f) > 1:
                for i in range(1, len(f)):
                    db.add_ref(f, to_ref(f[i]))
        for q in j['quantities']:
            q_ref = to_ref(q[0])
            db.add_quantity(q_ref)
            if len(q) > 1:
                for i in range(1, len(q)):
                    db.add_ref(q_ref, to_ref([i]))
        return db

    def __init__(self):
        self._compartments = Compartment.from_json(load_compartments())
        self._flows = LogicalSet(LogicalFlow)
        self._quantities = LogicalSet(LogicalQuantity)

    def compartments(self, cat_ref):
        c = cat_ref.entity()['Compartment']
        return self._compartments.traverse(c)

    def add_compartments(self, cat_ref):
        c = cat_ref.entity()['Compartment']
        return self._compartments.add_subs(c, verbose=True)

    def is_elementary(self, cat_ref):
        comps = self.compartments(cat_ref)
        return comps[-1].elementary

    def list_subcompartments(self, comp_list):
        """
        lists subcompartments of a given compartment string
        :param comp_list:
        :return:
        """
        comps = self._compartments.traverse(comp_list)
        return [x.name for x in comps[-1].subcompartments()]

    def add_flow(self, cat_ref):
        self._flows.add(LogicalFlow.create(cat_ref))
        self._add_flow_cfs(cat_ref)
        try:
            self.compartments(cat_ref)
        except KeyError:
            print('New compartments added!')
            self.add_compartments(cat_ref)

    def _add_flow_cfs(self, cat_ref):
        """
        We only want to add CFs for quantities already IN the database-
        the workflow is first curate the set of quantities of interest; then add flows of interest
        :param cat_ref:
        :return:
        """
        for cf in cat_ref.entity().characterizations():
            q_ref = CatalogRef(cat_ref.catalog, cat_ref.index, cf.quantity)
            if q_ref in self._quantities.keys():
                self.add_cf(q_ref, cf)

    def add_quantity(self, cat_ref):
        self._quantities.add(LogicalQuantity.create(cat_ref))

    def add_exchange(self, flow_ref, exchange):
        """
        exchanges are normally stored with processes; here we want to associate one with a flow
        :param flow_ref: catalog ref of a flow.
        Not sure what this is for, exactly.
        :param exchange:
        :return:
        """
        self._flows[flow_ref].add_exchange(flow_ref, exchange)

    def add_cf(self, q_ref, cf):
        self._quantities[q_ref].add_cf(q_ref, cf)

    def add_ref(self, existing_ref, new_ref):
        if existing_ref in self._flows.keys():
            self._flows.add_ref(existing_ref, new_ref)
            self._add_flow_cfs(new_ref)
        elif existing_ref in self._quantities.keys():
            self._quantities.add_ref(existing_ref, new_ref)
        else:
            raise KeyError("Can't find existing ref %s" % existing_ref)

    def synonyms(self, ref_a, ref_b):
        """
        if two different refs already in the DB should be merged.
        :param ref_a:
        :param ref_b:
        :return:
        """
        if ref_a in self._flows.keys():
            self._flows.mergewith(ref_a, self._flows[ref_b])
        elif ref_a in self._quantities.keys():
            self._quantities.mergewith(ref_a, self._quantities[ref_b])
        else:
            raise KeyError("Can't find existing ref %s" % ref_a)

    def flows(self):
        for f in self._flows.items():
            yield f

    def quantities(self):
        for q in self._quantities.items():
            yield q

    def flow(self, f):
        """
        f can be anything in cat_ref.names()
        :param f:
        :return:
        """
        return self._flows[f]

    def quantity(self, q):
        """
        q can be anything in cat_ref.names()
        :param q:
        :return:
        """
        return self._quantities[q]

    def lcia_methods(self):
        """
        Quantities with an Indicator property are judged to be LCIA methods. We are yielding logical quantities so we
        don't need to worry if there are repeats or inconsistencies- the point of the logical db is to be inclusive
        :return:
        """
        for q in self.quantities():
            for e in q:
                if 'Indicator' in e.entity().keys():
                    yield q
                    break

    def serialize(self):
        self._flows.check()
        self._quantities.check()
        return {
            'compartments': self._compartments.serialize(),
            'flows': self._flows.serialize(),
            'quantities': self._quantities.serialize()
        }