Esempio n. 1
0
class WTDescFromWTG(Component):
    """Create a wt_desc from a .wtg WAsP file"""
    # Inputs
    filename = Str(iotype='in', desc='The .wtg file name')

    # Outputs
    wt_desc = VarTree(GenericWindTurbinePowerCurveVT(),
                      iotype='out',
                      desc='The wind turbine power curve')

    def __init__(self, filename=None):
        super(WTDescFromWTG, self).__init__()

        if filename is not None:
            self.filename = filename
            self.execute()

    def execute(self):
        # Reading the .wtg file
        wtg = WTG(self.filename)

        # Filling up the VT
        self.wt_desc.power_curve = wtg.data[:, :2]
        self.wt_desc.c_t_curve = vstack([wtg.data[:, 0], wtg.data[:, 2]]).T
        self.wt_desc.cut_in_wind_speed = wtg.data[0, 0]
        self.wt_desc.cut_out_wind_speed = wtg.data[-1, 0]
        self.wt_desc.air_density = wtg.density
        self.wt_desc.rotor_diameter = wtg.rotor_diameter
        self.wt_desc.power_rating = self.wt_desc.power_curve[:, 1].max()
        self.wt_desc.hub_height = wtg.hub_height
        self.wt_desc.test_consistency()
Esempio n. 2
0
class PlantFromWWF(Component):
    """Create a Plant information from a .wwf WAsP file"""
    # Inputs
    filename = Str(iotype='in', desc='The .wwf file name')
    wt_desc = VarTree(GenericWindTurbinePowerCurveVT(),
                      iotype='in',
                      desc='The wind turbine power curve')

    # Outputs
    wt_layout = VarTree(GenericWindFarmTurbineLayout(),
                        iotype='out',
                        desc='wind turbine properties and layout')
    wind_rose_array = Array(
        iotype='out',
        units='m/s',
        desc='Windrose array [wind_directions, frequency, weibull_A, weibull_k]'
    )

    def execute(self):
        # Reading the .wwf file
        wwf = WWF(self.filename)
        self.wt_layout.wt_list.append(self.wt_desc)
        # self.wt_layout.wt_wind_roses.frequency_array =
        self.wt_layout.configure_single()

        for wt, wr in self.wwf.windroses.iteritems():
            self.wt_layout.wt_positions[i, :] = self.wwf.data[wt][:2]
            self.wt_layout.wt_wind_roses.append(wr)
            i += 1

        self.wt_layout.configure_single()
        # For practical reason we also output the first wind rose array outside
        # the wt_layout
        self.wind_rose_array = self.wt_layout.wt_wind_roses[0]
Esempio n. 3
0
class PlantFromWWH(Component):
    """Create a Plant information from a .wwh WAsP file"""
    # Inputs
    filename = Str(iotype='in', desc='The .wwh file name')

    # Outputs
    wt_layout = VarTree(GenericWindFarmTurbineLayout(),
                        iotype='out',
                        desc='wind turbine properties and layout')
    #wind_rose_array = Array(iotype='out', units='m/s',
    #    desc='Windrose array [wind_directions, frequency, weibull_A, weibull_k]')
    wind_rose_vt = VarTree(WeibullWindRoseVT(),
                           iotype='out',
                           desc='wind turbine Weibull wind rose')

    def __init__(self, filename=None):
        """
        The constructor that can take the wwh filename as optional parameter.
        :param filename: wwh file name [optional]
        :return: self
        """
        super(PlantFromWWH, self).__init__()
        if filename is not None:
            self.filename = filename
            self.execute()

    def execute(self):
        # Reading the .wwf file
        wwh = WWH(self.filename)
        iWT = 0
        for wt, data in wwh.wind_turbines.iteritems():
            turbine = wwh.turbine_descriptions[data['type']]
            self.wt_layout.add_wt(
                WTPC(name='wt_' + wt,
                     position=data['position'][:2],
                     wind_rose=GenericWindRoseVT(
                         weibull_array=data['wind_rose']),
                     power_curve=turbine['data'][:, :2],
                     power_rating=max(turbine['data'][:, 1]),
                     c_t_curve=turbine['data'][:, [0, 2]],
                     cut_in_wind_speed=turbine['data'][0, 0],
                     cut_out_wind_speed=turbine['data'][-1, 0],
                     air_density=turbine['density'],
                     rotor_diameter=turbine['rotor_diameter'],
                     hub_height=data['position'][2]))
            self.wind_rose_vt.add(
                'wt_' + wt, VarTree((WeibullWindRoseVT(data['wind_rose']))))
Esempio n. 4
0
class VariableTree(Container):
    """A tree of variables having the same input or output sense."""

    _iotype = Str('')

    implements(IVariableTree)

    def __init__(self, iotype=''):
        self._parent_ref = None
        super(VariableTree, self).__init__()

        self._iotype = iotype

        # Check for nested VariableTrees in the class definition.
        for name, obj in self.__class__.__dict__.items():
            if isinstance(obj, VariableTree):
                raise TypeError('Nested VariableTrees are not supported,'
                                ' please wrap %s.%s in a VarTree' %
                                (self.__class__.__name__, name))

        self.install_callbacks()

        # register callbacks for our class traits
        for name, trait in self.class_traits().items():
            if not name.startswith('_'):
                self.on_trait_change(self._trait_modified, name)

    @property
    def _parent(self):
        """ Return dereferenced weakref to parent. """
        return None if self._parent_ref is None else self._parent_ref()

    @_parent.setter
    def _parent(self, value):
        """ Set weakref to parent. """
        self._parent_ref = None if value is None else weakref.ref(value)

    def __getstate__(self):
        """ Return state after dereferencing weakref to parent. """
        state = super(VariableTree, self).__getstate__()
        if self._parent_ref is not None:
            state['_parent_ref'] = self._parent_ref()
        return state

    def __setstate__(self, state):
        """ Set state and set weakref to parent. """
        super(VariableTree, self).__setstate__(state)
        if self._parent_ref is not None:
            self._parent_ref = weakref.ref(self._parent_ref)

    @property
    def iotype(self):
        if not self._iotype and isinstance(self.parent, VariableTree):
            self._iotype = self.parent.iotype
        return self._iotype

    @rbac(('owner', 'user'))
    def cpath_updated(self):
        if self.parent:
            if isinstance(self.parent, VariableTree):
                self._iotype = self.parent.iotype
            else:
                t = self.parent.trait(self.name)
                if t and t.iotype:
                    self._iotype = t.iotype
        super(VariableTree, self).cpath_updated()

    @rbac(('owner', 'user'))
    def get_metadata(self, traitpath, metaname=None):
        if metaname == 'iotype':
            return self.iotype
        elif metaname is None:
            meta = super(VariableTree, self).get_metadata(traitpath, metaname)
            meta['iotype'] = self.iotype
            return meta
        else:
            return super(VariableTree, self).get_metadata(traitpath, metaname)

    def copy(self):
        """Returns a deep copy of this VariableTree, without deepcopying its
        parent.  Also installs necessary trait callbacks.
        """
        cp = super(VariableTree, self).copy()
        cp.install_callbacks()
        return cp

    def __deepcopy__(self, memo):
        id_self = id(self)
        if id_self in memo:
            return memo[id_self]

        cp = super(VariableTree, self).__deepcopy__(memo)
        cp.install_callbacks()
        return cp

    def install_callbacks(self):
        """Install trait callbacks on deep-copied VariableTree."""
        self.on_trait_change(self._iotype_modified, '_iotype')
        # _alltraits() is missing some traits after a deepcopy, so use the
        # union of _alltraits() and everything in self.__dict__
        allset = set(self._alltraits().keys())
        allset.update(self.__dict__.keys())
        for name in allset:
            if name not in ('trait_added', 'trait_modified') \
               and not name.startswith('_') and hasattr(self, name):
                self.on_trait_change(self._trait_modified, name)
                obj = getattr(self, name)
                if isinstance(obj, VariableTree) and obj is not self.parent:
                    obj.install_callbacks()

    def add(self, name, obj):
        if not (IVariable.providedBy(obj) or isinstance(obj, VarTree)):
            msg = "a VariableTree may only contain Variables or VarTrees"
            self.raise_exception(msg, TypeError)
        return super(VariableTree, self).add(name, obj)

    def add_trait(self, name, trait, refresh=True):
        super(VariableTree, self).add_trait(name, trait, refresh)
        if not name.startswith('_'):
            self.on_trait_change(self._trait_modified, name)

    def remove_trait(self, name):
        trait = self.get_trait(name)

        # remove the callback
        if trait:
            self.on_trait_change(self._trait_modified, name, remove=True)

        super(VariableTree, self).remove_trait(name)

    def list_vars(self):
        """Return a list of Variables in this VariableTree."""
        return [k for k in self.__dict__.keys() if not k.startswith('_')]

    def _iotype_modified(self, obj, name, old, new):
        for v in self.__dict__.values():
            if isinstance(v, (VariableTree, VarTree)) and v is not self.parent:
                v._iotype = new

    def _trait_modified(self, obj, name, old, new):
        # handle weird traits side-effect from hasattr call
        if name == 'trait_added':
            return
        if isinstance(new, VariableTree):
            obj = getattr(self, name)
            obj.parent = self
            obj._iotype = self._iotype
        if self._iotype == 'in':
            p = self
            path = [name]
            while isinstance(p, VariableTree):
                vt = p
                p = p.parent
                path.append(vt.name)
            # notify parent Component that this VariableTree has been modified
            if p is not None:
                t = p.trait(vt.name)
                if t and t.iotype == 'in':
                    # we need to pass the full pathname of the child that was
                    # actually modified up to the parent component, and we can't
                    # modify the arglist of _input_trait_modified, so instead
                    # call _input_updated explicitly
                    p._input_updated(vt.name, fullpath='.'.join(path[::-1]))

    def get_iotype(self, name):
        """Return the iotype of the Variable with the given name"""
        if self.get_trait(name) is None:
            self.raise_exception("'%s' not found" % name)
        return self.iotype

    def _items(self, visited, recurse=False, **metadata):
        """Return an iterator that returns a list of tuples of the form
        (rel_pathname, obj) for each trait of this VariableTree that matches
        the given metadata. If recurse is True, also iterate through all
        child Containers of each Container found.
        """
        if id(self) not in visited:
            visited.add(id(self))

            if 'iotype' in metadata:
                meta_io = metadata['iotype']
                matches_io = False
                if type(meta_io) is FunctionType:
                    if meta_io(self.iotype):
                        matches_io = True
                elif meta_io == self.iotype:
                    matches_io = True
                if matches_io:
                    newdict = metadata.copy()
                    del newdict['iotype']
            else:
                matches_io = True
                newdict = metadata

            if matches_io:
                for name in self._alltraits(**newdict):
                    if name.startswith('_'):
                        continue
                    obj = getattr(self, name)
                    yield (name, obj)
                    if recurse and is_instance(obj, VariableTree) and \
                       id(obj) not in visited:
                        for chname, child in obj._items(
                                visited, recurse, **metadata):
                            yield ('.'.join((name, chname)), child)

    @rbac(('owner', 'user'))
    def get_req_default(self, vt_required=None):
        """Returns a list of all inputs that are required but still have
        their default value.
        """
        req = []
        if vt_required:
            req_test = [True, False, None]
        else:
            req_test = [True]

        for name, trait in self.traits(type=not_event).items():
            obj = getattr(self, name)
            if obj is self.parent:
                continue
            if is_instance(obj, VariableTree):
                req.extend([
                    '.'.join((self.name, n))
                    for n in obj.get_req_default(vt_required)
                ])
            elif trait.required in req_test:
                try:
                    trait = trait.trait_type
                except:
                    unset = (obj == trait.default)
                else:
                    unset = (obj == trait.default_value)
                if not isinstance(unset, bool):
                    try:
                        unset = unset.all()
                    except:
                        pass
                if unset:
                    req.append('.'.join((self.name, name)))

        return req

    def get_attributes(self, io_only=True, indent=0, parent=''):
        """ Get attributes for this variable tree. Used by the GUI.

        io_only: bool
            Set to True if we only want to populate the input and output
            fields of the attributes dictionary.

        indent: int
            Recursion level (for collapsing tables).

        parent: str
            ID name of parent table line.

        valid: str
            Validity state of the parent table."""

        attrs = {}
        attrs['type'] = type(self).__name__
        self_io = self.iotype

        # Connection information found in parent comp's parent assy
        if not self.parent or not self.parent._parent or \
           isinstance(self.parent, VariableTree):
            connected = []
        else:
            graph = self.parent._parent._depgraph
            if self_io == 'in':
                connected = graph.get_boundary_inputs(connected=True)
            else:
                connected = graph.get_boundary_outputs(connected=True)

        variables = []
        for name in self.list_vars():

            trait = self.get_trait(name)
            meta = self.get_metadata(name)
            value = getattr(self, name)
            ttype = trait.trait_type

            # Each variable type provides its own basic attributes
            attr, slot_attr = ttype.get_attribute(name, value, trait, meta)

            # if this var is the top element of a variable tree, add 'vt' attribute
            if attr.get('ttype') == 'vartree':
                vartable = self.get(name)
                if isinstance(vartable, VariableTree):
                    attr['vt'] = 'vt'

            # Support for expand/collapse
            attr['indent'] = indent
            attr['id'] = '%s.%s' % (parent, name)

            if parent:
                attr['parent'] = parent

            attr['connected'] = ''
            if name in connected:
                connections = self.parent._depgraph.connections_to(name)

                if self_io == 'in':
                    # there can be only one connection to an input
                    attr['connected'] = str([src for src, dst in connections])
                else:
                    attr['connected'] = str([dst for src, dst in connections])
            variables.append(attr)

            # For variables trees only: recursively add the inputs and outputs
            # into this variable list
            if 'vt' in attr:
                vt_attrs = vartable.get_attributes(io_only,
                                                   indent=indent + 1,
                                                   parent=attr['id'])
                if self_io == 'in':
                    variables += vt_attrs['Inputs']
                else:
                    variables += vt_attrs['Outputs']

        if self_io == 'in':
            attrs['Inputs'] = variables
        else:
            attrs['Outputs'] = variables

        return attrs
Esempio n. 5
0
class VariableTree(Container):
    """A tree of variables having the same input or output sense."""

    _iotype = Str('')

    implements(IVariableTree)

    def __init__(self, iotype=''):
        self._parent_ref = None
        super(VariableTree, self).__init__()

        self._iotype = iotype

        # Check for nested VariableTrees in the class definition.
        for name, obj in self.__class__.__dict__.items():
            if isinstance(obj, VariableTree):
                raise TypeError('Nested VariableTrees are not supported,'
                                ' please wrap %s.%s in a VarTree'
                                % (self.__class__.__name__, name))

        self.install_callbacks()

        # register callbacks for our class traits
        for name, trait in self.class_traits().items():
            if not name.startswith('_'):
                self.on_trait_change(self._trait_modified, name)

    @property
    def _parent(self):
        """ Return dereferenced weakref to parent. """
        return None if self._parent_ref is None else self._parent_ref()

    @_parent.setter
    def _parent(self, value):
        """ Set weakref to parent. """
        self._parent_ref = None if value is None else weakref.ref(value)

    def __getstate__(self):
        """ Return state after dereferencing weakref to parent. """
        state = super(VariableTree, self).__getstate__()
        if self._parent_ref is not None:
            state['_parent_ref'] = self._parent_ref()
        return state

    def __setstate__(self, state):
        """ Set state and set weakref to parent. """
        super(VariableTree, self).__setstate__(state)
        if self._parent_ref is not None:
            self._parent_ref = weakref.ref(self._parent_ref)

    @property
    def iotype(self):
        if not self._iotype and isinstance(self.parent, VariableTree):
            self._iotype = self.parent.iotype
        return self._iotype

    @rbac(('owner', 'user'))
    def cpath_updated(self):
        if self.parent:
            if isinstance(self.parent, VariableTree):
                self._iotype = self.parent.iotype
            else:
                t = self.parent.trait(self.name)
                if t and t.iotype:
                    self._iotype = t.iotype
        super(VariableTree, self).cpath_updated()

    @rbac(('owner', 'user'))
    def get_metadata(self, traitpath, metaname=None):
        if metaname == 'iotype':
            return self.iotype
        elif metaname is None:
            meta = super(VariableTree, self).get_metadata(traitpath, metaname)
            meta['iotype'] = self.iotype
            return meta
        else:
            return super(VariableTree, self).get_metadata(traitpath, metaname)

    def copy(self):
        """Returns a deep copy of this VariableTree, without deepcopying its
        parent.  Also installs necessary trait callbacks.
        """
        cp = super(VariableTree, self).copy()
        cp.install_callbacks()
        return cp

    def __deepcopy__(self, memo):
        id_self = id(self)
        if id_self in memo:
            return memo[id_self]

        cp = super(VariableTree, self).__deepcopy__(memo)
        cp.install_callbacks()
        return cp

    def install_callbacks(self):
        """Install trait callbacks on deep-copied VariableTree."""
        self.on_trait_change(self._iotype_modified, '_iotype')
        # _alltraits() is missing some traits after a deepcopy, so use the
        # union of _alltraits() and everything in self.__dict__
        allset = set(self._alltraits().keys())
        allset.update(self.__dict__.keys())
        for name in allset:
            if name not in ('trait_added', 'trait_modified') \
               and not name.startswith('_') and hasattr(self, name):
                self.on_trait_change(self._trait_modified, name)
                obj = getattr(self, name)
                if isinstance(obj, VariableTree) and obj is not self.parent:
                    obj.install_callbacks()

    def add(self, name, obj):
        if not (IVariable.providedBy(obj) or isinstance(obj, VarTree)):
            msg = "a VariableTree may only contain Variables or VarTrees"
            self.raise_exception(msg, TypeError)
        return super(VariableTree, self).add(name, obj)

    def add_trait(self, name, trait, refresh=True):
        super(VariableTree, self).add_trait(name, trait, refresh)
        if not name.startswith('_'):
            self.on_trait_change(self._trait_modified, name)

    def remove_trait(self, name):
        trait = self.get_trait(name)

        # remove the callback
        if trait:
            self.on_trait_change(self._trait_modified, name, remove=True)

        super(VariableTree, self).remove_trait(name)

    def list_vars(self):
        """Return a list of Variables in this VariableTree."""
        return [k for k in self.__dict__.keys() if not k.startswith('_')]

    def _iotype_modified(self, obj, name, old, new):
        for v in self.__dict__.values():
            if isinstance(v, (VariableTree, VarTree)) and v is not self.parent:
                v._iotype = new

    def _trait_modified(self, obj, name, old, new):
        # handle weird traits side-effect from hasattr call
        if name == 'trait_added':
            return
        if isinstance(new, VariableTree):
            obj = getattr(self, name)
            obj.parent = self
            obj._iotype = self._iotype
        if self._iotype == 'in':
            p = self
            path = [name]
            while isinstance(p, VariableTree):
                vt = p
                p = p.parent
                path.append(vt.name)
            # notify parent Component that this VariableTree has been modified
            if p is not None:
                t = p.trait(vt.name)
                if t and t.iotype == 'in':
                    # we need to pass the full pathname of the child that was
                    # actually modified up to the parent component, and we can't
                    # modify the arglist of _input_trait_modified, so instead
                    # call _input_updated explicitly
                    p._input_updated(vt.name, fullpath='.'.join(path[::-1]))

    def get_iotype(self, name):
        """Return the iotype of the Variable with the given name"""
        if self.get_trait(name) is None:
            self.raise_exception("'%s' not found" % name)
        return self.iotype

    def _items(self, visited, recurse=False, **metadata):
        """Return an iterator that returns a list of tuples of the form
        (rel_pathname, obj) for each trait of this VariableTree that matches
        the given metadata. If recurse is True, also iterate through all
        child Containers of each Container found.
        """
        if id(self) not in visited:
            visited.add(id(self))

            if 'iotype' in metadata:
                meta_io = metadata['iotype']
                matches_io = False
                if type(meta_io) is FunctionType:
                    if meta_io(self.iotype):
                        matches_io = True
                elif meta_io == self.iotype:
                    matches_io = True
                if matches_io:
                    newdict = metadata.copy()
                    del newdict['iotype']
            else:
                matches_io = True
                newdict = metadata

            if matches_io:
                for name in self._alltraits(**newdict):
                    if name.startswith('_'):
                        continue
                    obj = getattr(self, name)
                    yield (name, obj)
                    if recurse and is_instance(obj, VariableTree) and \
                       id(obj) not in visited:
                        for chname, child in obj._items(visited, recurse,
                                                        **metadata):
                            yield ('.'.join((name, chname)), child)

    @rbac(('owner', 'user'))
    def get_req_default(self, vt_required=None):
        """Returns a list of all inputs that are required but still have
        their default value.
        """
        req = []
        if vt_required:
            req_test = [True, False, None]
        else:
            req_test = [True]

        for name, trait in self.traits(type=not_event).items():
            obj = getattr(self, name)
            if obj is self.parent:
                continue
            if is_instance(obj, VariableTree):
                req.extend(['.'.join((self.name, n))
                                 for n in obj.get_req_default(vt_required)])
            elif trait.required in req_test:
                try:
                    trait = trait.trait_type
                except:
                    unset = (obj == trait.default)
                else:
                    unset = (obj == trait.default_value)
                if not isinstance(unset, bool):
                    try:
                        unset = unset.all()
                    except:
                        pass
                if unset:
                    req.append('.'.join((self.name, name)))

        return req

    def list_all_vars(self):
        """Return a list of all variables in this VarTree (recursive)."""
        vnames = []
        for name, obj in self.__dict__.items():
            if name.startswith('_'):
                continue
            if isinstance(obj, VariableTree):
                vnames.extend(['.'.join((self.name,n)) for n in obj.list_all_vars()])
            else:
                vnames.append('.'.join((self.name, name)))
        return vnames

    def get_flattened_size(self):
        """Return the size of a flattened float array containing
        all values in the vartree that are flattenable to float
        arrays.  Any values not flattenable to float arrays will
        raise a NoFlatError.
        """
        size = 0
        for key in self.list_vars():
            size += flattened_size(key, getattr(self, key), scope=self)
        return size

    def get_flattened_index(self, name):
        """Return the slice within the flattened array of the
        current vartree that is occupied by the named
        subvar.
        """
        raise NotImplementedError('get_flattened_index not implemented for VarTrees yet')  # FIXME