예제 #1
0
def get_processors(glb_idx: PartialRetrievalDictionary) -> pd.DataFrame:
    procs = set(glb_idx.get(Processor.partial_key()))  # Unique processors
    d = {}
    for p in procs:
        parent_relations = glb_idx.get(
            ProcessorsRelationPartOfObservation.partial_key(child=p))
        d[p.ident] = set([p.parent_processor.ident for p in parent_relations])

    lst = [[
        "ProcessorGroup", "Processor", "ParentProcessor", "SubsystemType",
        "System", "FunctionalOrStructural", "Accounted", "Stock",
        "Description", "GeolocationRef", "GeolocationCode",
        "GeolocationLatLong", "Attributes"
    ]]
    # Elaborate a DAG, then iterate over it
    for ident in list(toposort.toposort_flatten(d)):
        p = glb_idx.get(Processor.partial_key(ident=ident))[0]
        gref = p.geolocation.reference if p.geolocation else ""
        gcode = p.geolocation.code if p.geolocation else ""
        pgroup = p.attributes.get("processor_group")
        fname = p.full_hierarchy_names(glb_idx)[0]
        t = [
            pgroup if pgroup else "", p.name, "",
            p.attributes.get("subsystem_type", ""),
            p.attributes.get("processor_system", ""),
            p.attributes.get("functional_or_structural", ""),
            p.attributes.get("instance_or_archetype", ""),
            p.attributes.get("stock"), "", gref, gcode, "", ""
        ]
        parent_relations = glb_idx.get(
            ProcessorsRelationPartOfObservation.partial_key(child=p))
        if len(parent_relations) == 0:
            lst.append(t)
        else:
            first = True
            for rel in parent_relations:
                t[2] = rel.parent_processor.full_hierarchy_names(glb_idx)[0]
                lst.append(t.copy())
                if first:
                    first = False
                    proper = None
                    for n in p.full_hierarchy_names(glb_idx):
                        if t[2] in n:
                            proper = n
                            break
                    t[1] = proper if proper else t[1]

    return list_to_dataframe(lst)
예제 #2
0
def get_code_hierarchies(glb_idx: PartialRetrievalDictionary) -> pd.DataFrame:
    def hierarchy_to_list(nodes: List[HierarchyNode]) -> List[HierarchyNode]:
        nodes_list = []
        if nodes:
            for node in sorted(nodes, key=lambda n: n.name):
                nodes_list.append(node)
                nodes_list.extend(hierarchy_to_list(list(node.get_children())))
        return nodes_list

    lst = [[
        "Source", "HierarchyGroup", "Hierarchy", "Level", "ReferredHierarchy",
        "Code", "ParentCode", "Label", "Description", "Expression",
        "GeolocationRef", "GeolocationCode", "Attributes"
    ]]
    for hh in glb_idx.get(Hierarchy.partial_key()):
        if hh.hierarchy_type == Taxon:
            for c in hierarchy_to_list(hh.roots):
                lst.append([
                    "", "", c.hierarchy.name,
                    ifnull(c.level, ""),
                    c.referred_node.hierarchy.name if c.referred_node else "",
                    c.name, c.parent.name if c.parent else "", c.label,
                    c.description, "", "", "", ""
                ])

    return list_to_dataframe(lst)
def get_processor(attribute, value, prd: PartialRetrievalDictionary = None):
    """
    Obtain the name of a Processor given the value of an attribute
    (Obtain the registry of objects)

    :param attribute:
    :param value:
    :param prd: A PartialRetrievalDictionary, passed in State "_glb_idx" to the AST evaluator by
    :return:
    """

    if not prd:
        raise Exception(f"No Global-Index parameter passed to Processor function")
    else:
        # Obtain ALL Processors, then ONE having attribute "attribute" with value <value>
        procs = prd.get(Processor.partial_key())
        ret = None
        for proc in procs:
            v = vars(proc).get(attribute)
            if not v:
                v = proc.attributes.get(attribute)
            if v and (strcmp(v, str(value)) or (is_float(value) and float(v) == float(value))):
                ret = proc.name
                break
        if ret:
            return ret
        else:
            raise Exception(f"No Processor found having attribute '{attribute}' with value '{value}'")
def get_interface_type(attribute, value, prd: PartialRetrievalDictionary = None):
    """
    Obtain the name of an InterfaceType given the value of an attribute
    (Obtain the registry of objects)

    :param attribute:
    :param value:
    :param prd: A PartialRetrievalDictionary, passed in State "_glb_idx" to the AST evaluator by
    :return:
    """

    if not prd:
        raise Exception(f"No Global-Index parameter passed to InterfaceType function")
    else:
        # Obtain ALL InterfaceTypes, then ONE having attribute "attribute" with value <value>
        its = prd.get(FactorType.partial_key())
        ret = None
        for it in its:
            v = vars(it).get(attribute)
            if not v:
                v = it.attributes.get(attribute)
            if v and (strcmp(v, str(value)) or (is_float(value) and float(v) == float(value))):
                ret = it.name
                break
        if ret:
            return ret
        else:
            raise Exception(f"No InterfaceType found having attribute '{attribute}' with value '{value}'")
예제 #5
0
 def test_002_serialization_deserialization(self):
     prd = prepare_partial_key_dictionary()
     prd2 = prd.to_pickable()
     s = serialize_from_object(prd2)
     prd2 = deserialize_to_object(s)
     prd = PartialRetrievalDictionary().from_pickable(prd2)
     # Tests
     res = prd.get({"_type": "PartOf"})
     self.assertEqual(len(res), 3)
     res = prd.get({"_type": "PartOf", "_child": "B"})
     self.assertEqual(len(res), 2)
     res = prd.get({"_type": "PartOf", "_parent": "A1"})
     self.assertEqual(len(res), 1)
     res = prd.get({"_type": "PartOf", "_parent": "C"})
     self.assertEqual(len(res), 0)
     res = prd.get({"_typer": "PartOf", "_parent": "C"})
     self.assertEqual(len(res), 0)
예제 #6
0
def get_problem_statement(glb_idx: PartialRetrievalDictionary) -> pd.DataFrame:
    ps = glb_idx.get(ProblemStatement.partial_key())
    if len(ps) == 0:
        ps = [ProblemStatement()]

    lst = [["Scenario", "Parameter", "Value", "Description"]]
    for solving_parameter in ps[0].solving_parameters.items():
        lst.append(["", solving_parameter[0], solving_parameter[1], ""])

    for scenario, params in ps[0].scenarios.items():
        for k, v in params.items():
            lst.append([scenario, k, v, ""])

    return list_to_dataframe(lst)
예제 #7
0
def get_parameters(glb_idx: PartialRetrievalDictionary) -> pd.DataFrame:
    lst = [[
        "Parameter", "Type", "Domain", "Value", "Group", "Description",
        "Attributes"
    ]]
    for p in glb_idx.get(Parameter.partial_key()):
        lst.append([
            p.name, p.type, p._range if p._range else "",
            ifnull(p.default_value, ""),
            ifnull(p.group, ""),
            ifnull(p._description, ""), ""
        ])

    return list_to_dataframe(lst)
def lcia_method(indicator: str, method: str=None, horizon: str=None,
                state: State=None, lcia_methods: PartialRetrievalDictionary=None):
    """

    :param indicator: Indicator name
    :param method: LCIA method weighting
    :param horizon: Time horizon
    :param state: Current values of processor plus parameters
    :param lcia_methods: Where LCIA data is collected
    :return: A dictionary with the
    """
    if indicator is None or indicator.strip() == "":
        return None

    k = dict(d=indicator)
    if method:
        k["m"] = method
    if horizon:
        k["h"] = horizon
    ms = lcia_methods.get(key=k, key_and_value=True)
    indices = create_dictionary()
    for k, v in ms:
        idx_name = f'{k["d"]}_{k["m"]}_{k["h"]}'
        if idx_name in indices:
            lst = indices[idx_name]
        else:
            lst = []
            indices[idx_name] = lst
        lst.append((k["i"], v[0], float(v[1])))

    ifaces = create_dictionary()
    for t in state.list_namespace_variables():
        if not t[0].startswith("_"):
            p = t[1]  # * ureg(iface_unit)
            ifaces[t[0]] = p

    res = dict()
    for name, lst in indices.items():
        interfaces = []
        weights = []  # From "
        for t in lst:
            if t[0] in ifaces:
                v = ifaces[t[0]]  # TODO .to(t[1])
                interfaces.append(v)
                weights.append(t[2])
        # Calculate the value
        ind = np.sum(np.multiply(interfaces, weights))  # * ureg(indicator_unit)
        res[name] = ind

    return res
예제 #9
0
def get_scale_relationships(
        glb_idx: PartialRetrievalDictionary) -> pd.DataFrame:
    lst = [[
        "OriginProcessors", "OriginInterface", "DestinationProcessors",
        "DestinationInterface", "BackInterface", "RelationType", "Weight",
        "ChangeOfTypeScale", "OriginCardinality", "DestinationCardinality",
        "Attributes"
    ]]
    for rel in glb_idx.get(FactorsRelationScaleObservation.partial_key()):
        lst.append([
            rel.origin.processor.name, rel.origin.name,
            rel.destination.processor.name, rel.destination.name, "", "Scale",
            rel.quantity, "", "", "", ""
        ])

    return list_to_dataframe(lst)
예제 #10
0
def get_interface_types(glb_idx: PartialRetrievalDictionary) -> pd.DataFrame:
    lst = [[
        "InterfaceTypeHierarchy", "InterfaceType", "Sphere", "RoegenType",
        "ParentInterfaceType", "Formula", "Description", "Unit",
        "OppositeSubsystemType", "Attributes"
    ]]
    for itype in glb_idx.get(FactorType.partial_key()):
        lst.append([
            itype.hierarchy.name, itype.name, itype.sphere,
            itype.roegen_type.name, itype.parent.name if itype.parent else "",
            "",
            itype.attributes.get("description", ""),
            itype.attributes.get("unit",
                                 ""), itype._opposite_processor_type, ""
        ])
    return list_to_dataframe(lst)
예제 #11
0
def get_processor_names_to_processors_dictionary(
        state: PartialRetrievalDictionary):
    """
    Obtain a dictionary with all processor names (a processor may have multiple names) and
    the corresponding Processor object

    :param state:
    :return:
    """
    ps = state.get(Processor.partial_key())
    ps = set(ps)  # Avoid repeating Processor objects
    d = create_dictionary()
    for p in ps:
        for n in p.full_hierarchy_names(state):
            d[n] = p
    return d
예제 #12
0
def get_exchange_relationships(
        glb_idx: PartialRetrievalDictionary) -> pd.DataFrame:
    lst = [[
        "OriginProcessors", "OriginInterface", "DestinationProcessors",
        "DestinationInterface", "BackInterface", "RelationType", "Weight",
        "ChangeOfTypeScale", "OriginCardinality", "DestinationCardinality",
        "Attributes"
    ]]
    for rel in glb_idx.get(
            FactorsRelationDirectedFlowObservation.partial_key()):
        lst.append([
            rel.source_factor.processor.name, rel.source_factor.name,
            rel.target_factor.processor.name, rel.target_factor.name,
            rel.back_factor.name if rel.back_factor else "", ">", rel.weight,
            "", "", "", ""
        ])

    return list_to_dataframe(lst)
예제 #13
0
def get_scale_change_map(glb_idx: PartialRetrievalDictionary) -> pd.DataFrame:
    lst = [[
        "OriginHierarchy", "OriginInterfaceType", "DestinationHierarchy",
        "DestinationInterfaceType", "OriginContext", "DestinationContext",
        "Scale", "OriginUnit", "DestinationUnit"
    ]]
    for sc in glb_idx.get(
            FactorTypesRelationUnidirectionalLinearTransformObservation.
            partial_key()):
        lst.append([
            sc.origin.hierarchy.name if sc.origin.hierarchy else "",
            sc.origin.name,
            sc.destination.hierarchy.name if sc.destination.hierarchy else "",
            sc.destination.name,
            sc._origin_context.name if sc._origin_context else "",
            sc._destination_context.name if sc._destination_context else "",
            sc._weight, sc._origin_unit, sc._destination_unit
        ])

    return list_to_dataframe(lst)
예제 #14
0
def get_interfaces(glb_idx: PartialRetrievalDictionary) -> pd.DataFrame:
    # Used to examine "value" as expression, and find variables that are interface names vs parameter names
    params = create_dictionary(
        data={p.name: None
              for p in glb_idx.get(Parameter.partial_key())})
    s = State()
    procs = glb_idx.get(Processor.partial_key())
    d = {}
    for p in procs:
        parent_relations = glb_idx.get(
            ProcessorsRelationPartOfObservation.partial_key(child=p))
        d[p.ident] = set([p.parent_processor.ident for p in parent_relations])

    lst = [[
        "Processor", "InterfaceType", "Interface", "Sphere", "RoegenType",
        "Orientation", "OppositeSubsystemType", "GeolocationRef",
        "GeolocationCode", "InterfaceAttributes", "Value", "Unit",
        "RelativeTo", "Uncertainty", "Assessment", "PedigreeMatrix",
        "Pedigree", "Time", "Source", "NumberAttributes", "Comments"
    ]]
    # Elaborate a DAG, then iterate over it
    for ident in list(toposort.toposort_flatten(d)):
        p = glb_idx.get(Processor.partial_key(ident=ident))[0]
        ifaces = glb_idx.get((Factor.partial_key(processor=p)))
        iface_names = create_dictionary(
            data={iface.name: iface
                  for iface in ifaces})
        # Elaborate DAG of Interfaces because of Observations
        d = {}
        for iface in ifaces:
            if iface.ident not in d:
                d[iface.ident] = set()
            for obs in iface.quantitative_observations:
                if obs.relative_factor:
                    d[iface.ident].add(obs.relative_factor.ident)
                # Consider obs.value and non linear dependencies
                if isinstance(obs.value, str):
                    ast = string_to_ast(expression_with_parameters, obs.value)
                    evaluation_issues = []
                    value, unresolved_vars = ast_evaluator(
                        exp=ast,
                        state=s,
                        obj=None,
                        issue_lst=evaluation_issues)
                    for unresolved in unresolved_vars:
                        if unresolved not in params:
                            d[iface.ident].add(iface_names[unresolved].ident)

        for ident2 in list(toposort.toposort_flatten(d)):
            iface = glb_idx.get(Factor.partial_key(ident=ident2))[0]
            lst1 = [
                iface.processor.name, iface.taxon.name, iface.name,
                iface.sphere, iface.roegen_type.name, iface.orientation,
                iface.opposite_processor_type, "", "", ""
            ]
            observations = iface.quantitative_observations
            if len(observations) > 0:
                for obs in observations:
                    lst2 = [
                        obs.value,
                        obs.attributes.get("unit",
                                           ""), obs.relative_factor.name
                        if obs.relative_factor else "",
                        obs.attributes.get("spread", ""),
                        obs.attributes.get("assessment", ""),
                        obs.attributes.get("pedigree_template", ""),
                        obs.attributes.get("pedigree", ""),
                        obs.attributes.get("time", ""),
                        obs.observer.name if obs.observer else "", "",
                        obs.attributes.get("comments", "")
                    ]
                    lst.append(lst1 + lst2)
            else:
                lst.append(lst1 + ["", "", "", "", "", "", "", "", "", ""])

    return list_to_dataframe(lst)
예제 #15
0
def export_model_to_xml(
        registry: PartialRetrievalDictionary
) -> Tuple[str, Dict[str, Processor]]:
    """
    Elaborate an XML string containing the nested processors and their attributes.
    Also the interfaces inside processors
    <processors>
      <root_p1 fullname="" level="" system="" subsystem="" functional="true|false">
        <interfaces>
          <i1 type="" sphere="" roegen_type="" orientation="" opposite_processor_type="" />
          ...
        </interfaces>
        <child_p2>
          ...
        </child_p2>
      </root_p1>
      ...
    </processors>

    Example (abstract):

    '/processors//[level="n"]'

    :param registry:
    :return:
    """
    def xml_processor(p: Processor, registry: PartialRetrievalDictionary,
                      p_map: Dict[str, Processor]):
        """
        Return the XML of a processor
        Recursive into children

        :param p:
        :return:
        """
        def xml_interface(iface: Factor):
            """

            :param iface:
            :return:
            """
            s = f'<{iface.name} type="{iface.taxon.name}" sphere="{iface.sphere}" ' \
                f'roegen_type="{iface.roegen_type}" orientation="{iface.orientation}" ' \
                f'opposite_processor_type="{iface.opposite_processor_type}" />'
            if case_sensitive:
                return s
            else:
                return s.lower()

        children = p.children(registry)
        full_name = p.full_hierarchy_names(registry)[0]
        if case_sensitive:
            p_map[full_name] = p
        else:
            p_map[full_name.lower()] = p

        s = f"""
    <{p.name} fullname="{full_name}" level="{p.level}" system="{p.processor_system}" subsystem="{p.subsystem_type}" functional="{"true" if strcmp(p.functional_or_structural, "Functional") else "false"}" >
        <interfaces>
        {chr(10).join([xml_interface(f) for f in p.factors])}
        </interfaces>
        {chr(10).join([xml_processor(c, registry, p_map) for c in children])}    
    </{p.name}>"""
        if case_sensitive:
            return s
        else:
            return s.lower()

    # Part of relationships
    por = registry.get(ProcessorsRelationPartOfObservation.partial_key())

    # Set of all instance processors NOT touched by part-of relationships
    unaffected_procs = set([
        p for p in registry.get(Processor.partial_key())
        if strcmp(p.instance_or_archetype, "Instance")
    ])
    for po in por:
        try:
            unaffected_procs.remove(po.parent_processor)
        except KeyError:
            pass
        try:
            unaffected_procs.remove(po.child_processor)
        except KeyError:
            pass

    # Keep those affecting Instance processors
    por = [
        po for po in por
        if strcmp(po.parent_processor.instance_or_archetype, "Instance")
    ]

    # Get root processors (set of processors not appearing as child_processor)
    parents = set([po.parent_processor for po in por])
    children = set([po.child_processor for po in por])
    roots = parents.difference(children).union(unaffected_procs)
    # leaves = children.difference(parents)
    result = '<processors>'  # <?xml version="1.0" encoding="utf-8"?>\n
    p_map = {}
    for p in roots:
        result += xml_processor(p, registry, p_map)
    result += "\n</processors>"

    return result, p_map