Exemplo n.º 1
0
    def add_objective(self, building):
        """Creates and adds the meter needed by this objective to the building.

        :param building: the building to modify
        :return: None
        """
        try:
            self.get_objective(building)
        except ValueError:
            pass  # the objective is not present
        else:
            raise ValueError(f'Objective for {repr(self)} already exists')

        mode = ef.get_mode(building)
        new_object_dict = {
            ef.convert_format(field, 'field', mode): getattr(self, attr)
            for attr, field in self.field_pairs if getattr(self, attr)
        }
        if self.frequency is None:
            new_object_dict[ef.convert_format('Reporting_Frequency', 'field',
                                              mode)] = 'Hourly'
        if mode == 'idf':
            building.newidfobject(key=ef.convert_format(
                self.class_name, 'class', mode),
                                  **new_object_dict)
        elif mode == 'json':
            # this is equivalent to appending, but e+ uses a dictionary instead of a list
            objectives = building[self.class_name]
            num = len(objectives)
            new_key = f'{self.class_name} {num}'
            assert new_key not in building, f'The building has incorrectly numbered {self.class_name} entries'
            objectives[new_key] = new_object_dict
Exemplo n.º 2
0
def clear_outputs(building, outputs: Union[str, List[str]] = 'all') -> None:
    """Disable certain types of output.

    :param building: the building to modify
    :param outputs: Can be the class_name of the output to clear,
        a shortcut for different types of output,
        or a list that combines the above.
    :return: None
    """
    # `empty` is used so that different fields do not reference each the same container
    mode = ef.get_mode(building)
    if mode == 'idf':
        building_items = building.idfobjects
        empty = list
    elif mode == 'json':
        building_items = building
        empty = dict
    else:
        raise ModeError(mode)

    def find(prefix):
        return {
            x
            for x in building_items
            if x.startswith(ef.convert_format(prefix, 'class', mode))
        }

    # These lists are probably incomplete!
    class_names = dict()
    # ENVIRONMENTALIMPACTFACTORS adds a bunch of meters, but is not a meter itself
    class_names['output_meters'] = find('Output:Meter:') | {
        'Output:Meter', 'Output:EnvironmentalImpactFactors'
    }
    class_names['internal_meters'] = {'Meter:Custom', 'Meter:CustomDecrement'}
    class_names['tables'] = find('Output:Table:')

    class_names['output'] = find('Output:')
    class_names['outputcontrol'] = find('OutputControl:')

    class_names['meters'] = class_names['output_meters'] | class_names[
        'internal_meters']

    if outputs == 'all':
        outputs = chain(*class_names.values())
    else:
        if isinstance(outputs, str):  # make outputs a list
            outputs = [outputs]
        # convert each element in outputs via the class_names shortcuts
        outputs = set(
            chain(*(class_names.get(output, [output]) for output in outputs)))
    # clear the selected outputs
    for output in outputs:
        building_items[output] = empty()
Exemplo n.º 3
0
    def get(self, building) -> List:
        """Gets the current values of this field from a building

        :param building: the building to retrieve values from
        :return: a list containing the current values of this selector's fields
        """
        mode = ef.get_mode(building)
        objects = self.get_objects(building)
        field_name = ef.convert_format(self.field_name, 'field', mode)
        if mode == 'idf':
            return [getattr(o, field_name) for o in objects]
        if mode == 'json':
            return [o[field_name] for o in objects]
Exemplo n.º 4
0
 def get_objective(self, building):
     mode = ef.get_mode(building)
     if mode == 'idf':
         objectives = building.idfobjects[ef.convert_format(
             self.class_name, 'class', mode)]
     elif mode == 'json':
         objectives = building[ef.convert_format(self.class_name, 'class',
                                                 mode)].values()
     else:
         raise ModeError(mode)
     for objective in objectives:
         if self.check_all(objective, mode):
             return objective
     raise ValueError(f'Cannot find the objective for {repr(self)}')
Exemplo n.º 5
0
    def set(self, building, value) -> None:
        """Sets this field in the building to the provided value

        :param building: the building to modify
        :param value: the value to set this field to
        :return:
        """
        mode = ef.get_mode(building)
        objects = self.get_objects(building)
        field_name = ef.convert_format(self.field_name, 'field', mode)
        if mode == 'idf':
            for o in objects:
                setattr(o, field_name, value)
        if mode == 'json':
            for o in objects:
                assert field_name in o, f'{field_name} not in {repr(o)}'
                o[field_name] = value
Exemplo n.º 6
0
    def get_objects(self, building) -> List:
        """Retrieves the objects that this selector will affect from the building.

        :param building: the building to search
        :return: a list of the objects found
        """
        mode = ef.get_mode(building)
        if mode == 'idf':
            if self.class_name is not None:
                class_name = ef.convert_format(self.class_name, 'class', 'idf')
            else:
                class_name = None
            if self.object_name == '*':
                if class_name is None:
                    raise TypeError(
                        "When object_name='*', class_name must be specified.")
                return building.idfobjects[class_name]
            if self.object_name and class_name:
                # this is probably the most reliable way to select an idfObject.
                return [
                    building.getobject(key=class_name, name=self.object_name)
                ]
            if self.object_name:
                # There should only one object matching the name, assuming the idf is valid
                return [
                    eppySupport.get_idfobject_from_name(
                        building, self.object_name)
                ]
            if class_name is not None:
                # assume that we want the first object matching the key
                # TODO: is this specific enough, or should we remove it? our JSON code does not support this
                return [building.idfobjects[class_name][0]]
            else:  # we have neither object_name nor class_name
                raise TypeError(
                    'Either class_name or object_name must be specified.')
        elif mode == 'json':
            if self.object_name == '*':
                if not self.class_name:
                    raise TypeError(
                        "When object_name='*', class_name must be specified.")
                return list(building[self.class_name].values())
            if self.object_name and self.class_name:
                # this is probably the most reliable way to select an idfObject.
                return [building[self.class_name][self.object_name]]
            if self.object_name:
                # There should only one object matching the name, assuming the building is valid
                result = [
                    obj for objs in building.values()
                    for name, obj in objs.items() if name == self.object_name
                ]
                if len(result) != 1:
                    warnings.warn(
                        f'found {len(result)} objects with object_name: {self.object_name}, expected 1'
                    )
                return result
            if self.class_name:
                result = list(building[self.class_name].items())
                if len(result) == 1:
                    return result
                raise ValueError(
                    f'multiple objects with class_name {self.class_name}.'
                    f'Cannot guarantee a reliable ordering')
            else:  # we have neither object_name nor class_name
                raise TypeError(
                    'Either class_name or object_name must be specified.')
        raise ModeError(mode)