Exemple #1
0
class DataGrid(DataGridBase, W.Box):
    """An (overly) opinionated `DataFrame`-backed datagrid
    ``[0.1.6]/datagrid.ts#L64``

    Used JSONModel, which expect JSON Table Schema
    ``[0.1.6]/jsonmodel.ts#L21``
    """

    _model_name = T.Unicode("DataGridModel").tag(sync=True)
    _view_name = T.Unicode("DataGridView").tag(sync=True)

    value = TT.DataFrame(None, allow_none=True).tag(
        sync=True,
        to_json=lambda df, obj: None
        if df is None else json.loads(df.to_json(**TABLE)),
        from_json=lambda value, obj: None
        if value is None else pd.read_json(json.dumps(value), **TABLE),
    )

    def _repr_keys(self):
        """this shouldn't be needed, but we're doing _something wrong_"""
        try:
            super_keys = super()._repr_keys()
            for key in super_keys:
                if key != "value":
                    yield key
        except Exception:
            return
Exemple #2
0
class FrameLinkedPlot(widgets.Box):
    ploty = tl.List(tl.Union([tl.Integer(), tl.Unicode()]), default_value=[0])
    plotx = tl.Union([tl.Integer(), tl.Unicode()], default_value=1)
    stride = tl.Integer(default_value=1)
    title = tl.Unicode(default_value='')

    colvars = tl.List(trait=tl.Union([tt.DataFrame(), tt.Array()]), read_only=True)
    bokeh = tl.Instance(klass=BokehWrapper, read_only=True)
    views = tl.List(trait=NGLViewTrait(), read_only=True)
    sources = tl.List(trait=CDSTrait(), read_only=True)

    _reuse_colvars = tl.Bool(read_only=True)

    def_button_layout = widgets.Layout(height='30px')
    def_view_layout   = dict(width='250px', height='300px', flex='0 0 auto')
    def_figure_layout = widgets.Layout(width='400', height='550')
    def_box_layout    = widgets.Layout(display='flex',
                                    flex_flow='column wrap',
                                    height='650px',
                                    width='100%',
                                    align_items='flex-start')

    def __init__(self, 
        colvars, 
        mdtraj_trajectories, 
        plotx_label=None, 
        ploty_label=None, 
        ploty=None, 
        legendlocation='top_right',
        **kwargs):
        super().__init__(**kwargs)

        # colvars and mdtraj_trajectories can be specified either as a list or a single item
        if isinstance(mdtraj_trajectories, Trajectory):
            mdtrajs = [mdtraj_trajectories]
        else:
            mdtrajs = list(mdtraj_trajectories)

        if isinstance(colvars, DataFrame) or isinstance(colvars, Mapping):
            cvs = [colvars]
        else:
            cvs = list(colvars)

        if len(mdtrajs) != 1 and len(cvs) != len(mdtrajs) and len(ploty) != len(mdtrajs):
            print(len(mdtrajs), len(cvs), len(ploty))
            raise ValueError("Should have either 1 mdtraj trajectory, or one for every colvar")

        # ploty wasn't given to super, so it's currently the default per the traitlet
        # So if it was user-specified, we need to make sure its a list and then
        # throw it in
        if isinstance(ploty, str):
            print("ploty is a str")
            self.ploty = [ploty] * len(cvs)
        elif ploty is not None:
            try:
                self.ploty = list(iter(ploty))
            except TypeError:
                self.ploty = [ploty] * len(cvs)
            else:
                if len(cvs) == 1: cvs = cvs * len(self.ploty)
        if len(cvs) != len(self.ploty):
            raise ValueError("Couldn't broadcast colvars to plotys: {}, {}".format(len(cvs), len(ploty)))

        self.set_trait('colvars', cvs)
        
        self.layout = copy(self.def_box_layout)

        plotx = self.plotx
        ploty = self.ploty

        self._vlines = {}

        TOOLS="crosshair,pan,zoom_in,zoom_out,box_zoom,box_select,undo,reset,"

        hover = HoverTool(tooltips=[
            ("x", "@x (@plotx_label)"),
            ("y", "@y (@ploty_label)"),
            ("time", "@time ns"),
            ("run", "@run")
        ])

        if plotx_label is None:
            plotx_label = "Collective variable {}".format(plotx+1)
        if plotx_label is None:
            ploty_label = "Collective variable {}".format(ploty+1)

        p = figure(
            title=self.title,
            x_axis_label=plotx_label,
            y_axis_label=ploty_label,
            tools=TOOLS)
        p.add_tools(hover)
        figure_layout = copy(self.def_figure_layout)
        bokeh = BokehWrapper(p, layout=figure_layout, showing=False)
        self.set_trait('bokeh', bokeh)

        sources, views = self._init_plots_views(mdtrajs, 
                                                plotx_label, 
                                                ploty_label)

        p.legend.click_policy = "hide"
        p.legend.location = legendlocation
        if len(cvs) == 1 or len(cvs) == len(mdtrajs):
            p.legend.visible = False


        self.set_trait('views', views)
        self.set_trait('sources', sources)

        button = widgets.Button(
            description='Next selected frame',
            disabled=False,
            button_style='', # 'success', 'info', 'warning', 'danger' or ''
            tooltip='Set NGLView frame to the next selected point',
            layout=copy(self.def_button_layout)
        )

        button.on_click(self._on_button_clicked)

        self.children =tuple(self.views + [self.bokeh, button])
        self.bokeh.show()

    def _on_button_clicked(self, b):
        for view in self.views:
            view.next_selected()

    def _init_plots_views(self, mdtraj_trajectories, plotx_label, ploty_label):
        colvars = self.colvars
        stride = self.stride
        plotx = self.plotx
        plotys = self.ploty
        p = self.figure

        n = len(colvars)
        if n >= 3:
            palette = colorblind['Colorblind'][n]
        else:
            palette = colorblind['Colorblind'][3]
        palette = palette[::-1]

        view_layout = widgets.Layout(**self.def_view_layout)
        if len(mdtraj_trajectories) == 1:
            view_layout.width='500px'
            view_layout.height='600px'

        sources = []
        views = []

        for n,(colvar, traj, ploty) in enumerate(zip_longest(colvars, mdtraj_trajectories, plotys)):
            if traj is not None:
                working_traj = traj

            times = working_traj.time[::stride]
            
            if len(colvar) != len(working_traj):
                raise ValueError("Colvar and trajectory should have same number of frames")
            
            if isinstance(colvar, np.ndarray):
                x = colvar[::stride, plotx]
                y = colvar[::stride, ploty]
            else:
                x = colvar[plotx][::stride]
                y = colvar[ploty][::stride]

            if isinstance(ploty, str):
                this_ploty_label = ploty
            elif ploty_label is not None:
                this_ploty_label = ploty_label
            else:
                this_ploty_label = str(ploty)
            ploty_label_list = [this_ploty_label] * len(y)

            source = ColumnDataSource(data={
                'run': [n]*len(x),
                'plotx_label': [plotx_label]*len(x),
                'ploty_label': ploty_label_list,
                'time': times/1000,
                'x': x,
                'y': y,
                'alphas': [(t)/(times[-1]) for t in times]
            })
            sources.append(source)
            
            colour = palette[n-1]
            
            if traj is not None:
                view = show_mdtraj(traj[::stride], gui=False)
                view.observe(self._update_frame, names=['frame']), 
                view._colour = colour
                if len(traj.top.select('protein')):
                    view.clear_representations()
                    view.add_cartoon(selection='polymer', color=colour)
                # view.frame_stride = stride
                view.layout = view_layout
                view._set_sync_camera()
                views.append(view)
                vline = Span(
                    location=view.frame * traj.timestep * stride + traj.time[0],
                    dimension='height',
                    line_color=colour
                )
                self._vlines[view] = vline
                p.add_layout(vline)

            view.link_to_bokeh_ds(source)
            
            p.scatter(x='x', y='y', 
                      source=source, 
                      color=colour, 
                      fill_alpha='alphas',
                      legend=this_ploty_label)

        return sources, views

    @property
    def figure(self):
        return self.bokeh.figure
    
    @property
    def mdtraj_trajectories(self):
        return (view.original_trajectory for view in self.views)

    @property
    def traj(self):
        traj_list = list(self.mdtraj_trajectories)
        first_traj = trajlist.pop()
        for traj in traj_list:
            if traj is not first_traj:
                raise ValueError("FrameLinkedPlot has multiple trajectories")
        return first_traj
            

    @property
    def view(self):
        if len(self.views) == 1:
            return self.views[0]
        else:
            raise ValueError("FrameLinkedPlot has multiple views")

    @property
    def source(self):
        if len(self.views) == 1:
            return self.sources[0]
        else:
            raise ValueError("FrameLinkedPlot has multiple sources")

    def _update_frame(self, changes):
        # selections = [deepcopy(source.selected['1d']) for source in self.sources]
        view = changes['owner']
        new_frame = changes['new']
        traj = view.original_trajectory
        vline = self._vlines[view]
        vline.location = traj.timestep * new_frame + traj.time[0]
        # for sele, src in zip(selections, self.sources):
        #     src.selected['1d'] = sele
        self.bokeh.refresh()
Exemple #3
0
class Case(t.HasTraits):

    name = t.Unicode()
    gen = tt.DataFrame()
    bus = tt.DataFrame()
    load = tt.DataFrame()
    branch = tt.DataFrame()
    bus_name = t.List(t.Unicode())
    gen_name = t.List(t.Unicode())
    branch_name = t.List(t.Unicode())
    unique_gen_names = t.Bool(default_value=True)
    _attributes = t.List(t.Unicode())

    def __init__(self, filename=None, *args, **kwargs):

        super(Case, self).__init__(*args, **kwargs)

        self.gen = pd.DataFrame(columns=list(Generator().traits().keys()))
        self.gen = self.gen.set_index('name')

        self.bus = pd.DataFrame(columns=list(Bus().traits().keys()))
        self.bus = self.bus.set_index('name')

        self.branch = pd.DataFrame(columns=list(Branch().traits().keys()))
        self.branch = self.branch.set_index('name')

        if filename is None:
            self.load_default_case()

        elif filename.endswith('.m'):
            self._attributes = list()
            self.read_matpower(filename)

        else:
            raise NotImplementedError(
                "Unsupported filetype .{fileextension} in {filename}. Please contact the developer"
                .format(fileextension=filename.split('.')[-1],
                        filename=filename))

    def __repr__(self):
        name_string = "name='{name}'".format(
            name=self.name) if self.name != '' else ''
        gen_string = 'Generators={number}'.format(number=len(self.gen_name))
        bus_string = 'Buses={number}'.format(number=len(self.bus_name))
        branch_string = 'Branches={number}'.format(
            number=len(self.branch_name))
        l = [
            s for s in [name_string, gen_string, bus_string, branch_string]
            if s != ''
        ]
        repr_string = ', '.join(l)

        return '<{}.{}({})>'.format(
            self.__class__.__module__.replace('.case.case', '.case'),
            self.__class__.__name__,
            repr_string,
        )

    def load_default_case(self):

        self.add_generator(name='GenCo0',
                           maximum_real_power=100,
                           generator_bus='Bus1')
        self.add_generator(name='GenCo1',
                           maximum_real_power=200,
                           generator_bus='Bus2')
        self.add_bus(name='Bus1',
                     bus_type='SWING',
                     real_power_demand=50,
                     imag_power_demand=0)
        self.add_bus(name='Bus2', real_power_demand=250, imag_power_demand=0)
        self.add_branch(from_bus='Bus1', to_bus='Bus2')

    def add_generator(self, **kwargs):

        model = Generator(**kwargs)
        d = OrderedDict()
        for i in sorted(model.traits().keys()):
            d[i] = getattr(model, i)
        name = d.pop('name')
        self.gen.loc[name] = d

        self.fix_names()

        return model

    def add_bus(self, **kwargs):

        model = Bus(**kwargs)
        d = OrderedDict()
        for i in sorted(model.traits().keys()):
            d[i] = getattr(model, i)
        name = d.pop('name')
        self.bus.loc[name] = d

        self.fix_names()

        return model

    def add_branch(self, **kwargs):

        model = Branch(**kwargs)
        d = OrderedDict()
        for i in sorted(model.traits().keys()):
            d[i] = getattr(model, i)
        name = d.pop('name')
        self.branch.loc[name] = d

        self.fix_names()

        return model

    def fix_names(self):
        self.gen_name = list(self.gen.index)
        self.bus_name = list(self.bus.index)
        self.branch_name = list(self.branch.index)

    def read_matpower(self,
                      filename,
                      auto_assign_names=True,
                      fill_loads=True,
                      remove_empty=True,
                      reset_generator_status=True):

        with open(os.path.abspath(filename)) as f:
            string = f.read()

        gen_list = list()
        for attribute in matpower.find_attributes(string):
            _list = matpower.parse_file(attribute, string)
            if attribute == 'gen':
                for row in _list:
                    model = Generator(**dict(zip(row, row)))
                    s = pd.Series(model._trait_values)
                    gen_list.append(s)

        self.gen = pd.DataFrame(gen_list)

    @property
    def swing_bus(self):
        swing_bus = self.bus[self.bus['bus_type'] == 'SWING'].index[0]
        return swing_bus
Exemple #4
0
class SunRayBlaster(OrthographicRayBlaster):
    # ground: Position of center of ray projection on the ground
    # zenith: Position directly above 'ground' at distance that sun
    #     blaster should be placed.
    # north: Direction of north on ground from 'ground'

    latitude = traitlets.Float()
    longitude = traitlets.Float()
    date = traitlets.Instance(klass=datetime.datetime)

    ground = traittypes.Array().valid(check_dtype("f4"), check_shape(3))
    zenith = traittypes.Array().valid(check_dtype("f4"), check_shape(3))
    north = traittypes.Array().valid(check_dtype("f4"), check_shape(3))

    solar_altitude = traitlets.CFloat()
    solar_azimuth = traitlets.CFloat()
    solar_distance = traitlets.CFloat()
    _solpos_info = traittypes.DataFrame()

    @traitlets.default("_solpos_info")
    def _solpos_info_default(self):
        return pvlib.solarposition.get_solarposition(self.date, self.latitude,
                                                     self.longitude)

    @traitlets.default("solar_altitude")
    def _default_solar_altitude(self):
        solar_altitude = self._solpos_info["apparent_elevation"][0]
        if solar_altitude < 0:
            raise ValueError("For the provided lat, long, date, & time "
                             "the sun will be below the horizon.")
        return solar_altitude

    @traitlets.default("solar_azimuth")
    def _default_solar_azimuth(self):
        return self._solpos_info["azimuth"][0]

    @property
    def zenith_direction(self):
        zd_nonorm = self.zenith - self.ground
        solar_distance = np.linalg.norm(zd_nonorm)
        print("sd zd", solar_distance, zd_nonorm)
        return zd_nonorm / solar_distance

    @traitlets.default("solar_distance")
    def _solar_distance_default(self):
        zd_nonorm = self.zenith - self.ground
        return np.linalg.norm(zd_nonorm)

    def solar_rotation(self, point):
        r"""Rotate a point according to same rotation that moves
        sun from the zenith to it location in the sky.

        Args:
            point (array): 3D point to rotate

        """
        return sun_calc.rotate_u(
            sun_calc.rotate_u(point, np.radians(90 - self.solar_altitude),
                              self.north), np.radians(90 - self.solar_azimuth),
            self.zenith_direction)

    @traitlets.default("forward")
    def _forward_default(self):
        # Negative to point from sun to the earth rather than from
        # eart to the sun
        return -self.solar_rotation(self.zenith_direction)

    @traitlets.default("center")
    def _center_default(self):
        v = self.ground - self.solar_distance * self.forward
        offset = max(
            0.0,
            ((self.height / 2.0) - np.abs(
                np.linalg.norm(v - self.ground) *
                np.tan(np.radians(self.solar_altitude)))) / 2,
        )
        print(offset)
        v = v + offset * self.up
        return v

    @traitlets.default("up")
    def _up_default(self):
        zenith_direction = self.zenith_direction
        east = np.cross(self.north, zenith_direction)
        # The "east" used here is not the "east" used elsewhere.
        # This is the east wrt north etc, but we need an east for blasting from elsewhere.
        return -self.solar_rotation(east)
Exemple #5
0
class NetworkModel(t.HasTraits):
    """The NetworkModel object is created from a PSSTCase object,
    using the PSSTNetwork object. It contains state information neccesary
    to interactively visualize a network.

    Parameters
    ----------
    case : PSSTCase
        An instance of a PSST case.
    sel_bus : str (Default=None)
        The name of a bus in the case to focus on.
    solver : str (Default='glpk')
        The name of the mixed integer solver you wish to use

    Attributes
    ----------
    view_buses : :obj:`list` of :obj:`str`
        The names of the buses to be displayed.
    pos : pandas.DataFrame
        All the x,y positions of all the nodes.
    edges : pandas.DataFrame
        All the edges between nodes, and their x,y coordiantes.
    x_edges, y_edges : numpy.Array
        List of coordinates for 'start' and 'end' node, for all edges in network.

    bus_x_vals, bus_y_vals : numpy.Array
        Arrays containing coordinates of buses to be displayed.
    bus_x_edges, bus_y_edges : numpy.Array
        List of coordinates for 'start' and 'end' bus for each edge to be displayed.
    bus_names: :obj:`list` of :obj:`str`
        List of names of buses to be displayed.

    gen_x_vals, gen_y_vals : numpy.Array
        Arrays containing coordinates of generators to be displayed.
    gen_x_edges, gen_y_edges : numpy.Array
        List of coordinates for 'start' and 'end' generator for each edge to be displayed.
    gen_names: :obj:`list` of :obj:`str`
        List of names of generators to be displayed.

    load_x_vals, load_y_vals : numpy.Array
        Arrays containing coordinates of loads to be displayed.
    load_x_edges, load_y_edges : numpy.Array
        List of coordinates for 'start' and 'end' bus for each edge to be displayed.
    load_names: :obj:`list` of :obj:`str`
        List of names of loads to be displayed.

    """

    case = t.Instance(PSSTCase, help='The original PSSTCase')
    network = t.Instance(PSSTNetwork)
    G = t.Instance(nx.Graph)
    model = t.Instance(PSSTModel, allow_none=True)

    sel_bus = t.Unicode(allow_none=True)
    view_buses = t.List(trait=t.Unicode)
    all_pos = tt.DataFrame(help='DF with all x,y positions of nodes.')
    all_edges = tt.DataFrame()
    pos = tt.DataFrame(help='DF with x,y positions only for display nodes')
    edges = tt.DataFrame()

    x_edges = tt.Array([])
    y_edges = tt.Array([])

    bus_x_vals = tt.Array([])
    bus_y_vals = tt.Array([])
    bus_names = t.List(trait=t.Unicode)
    bus_x_edges = tt.Array([])
    bus_y_edges = tt.Array([])

    gen_x_vals = tt.Array([])
    gen_y_vals = tt.Array([])
    gen_names = t.List(trait=t.Unicode)
    gen_x_edges = tt.Array([])
    gen_y_edges = tt.Array([])

    load_x_vals = tt.Array([])
    load_y_vals = tt.Array([])
    load_names = t.List(trait=t.Unicode)
    load_x_edges = tt.Array([])
    load_y_edges = tt.Array([])

    x_min_view = t.CFloat()
    x_max_view = t.CFloat()
    y_min_view = t.CFloat()
    y_max_view = t.CFloat()

    _VIEW_OFFSET = 50

    def __init__(self, case, sel_bus=None, solver='glpk', *args, **kwargs):
        super(NetworkModel, self).__init__(*args, **kwargs)

        # Store PPSTCase, PSSTNetwork, and networkx.Graph
        self.case = case
        self.network = create_network(case=self.case)
        self.G = self.network.graph

        # Try to solve model
        self.model = build_model(self.case)
        self.model.solve(solver=solver)

        # Make full pos DF.
        self.all_pos = pd.DataFrame(self.network.positions, index=['x', 'y']).T

        # Make full edges DF, with coordinates and branch index
        self.all_edges = pd.DataFrame.from_records(
            [(i, j) for i, j in self.G.edges()], columns=['start', 'end'])
        # ---> Add coordinates
        self.all_edges['start_x'] = self.all_edges['start'].map(
            lambda e: self.all_pos.loc[e]['x'])
        self.all_edges['end_x'] = self.all_edges['end'].map(
            lambda e: self.all_pos.loc[e]['x'])
        self.all_edges['start_y'] = self.all_edges['start'].map(
            lambda e: self.all_pos.loc[e]['y'])
        self.all_edges['end_y'] = self.all_edges['end'].map(
            lambda e: self.all_pos.loc[e]['y'])
        # ---> Add branch index
        # new = case.branch[['F_BUS', 'T_BUS']]
        # new = new.reset_index()
        # new = new.rename_axis({'F_BUS': 'start', 'T_BUS': 'end', 'index': 'branch_idx'}, axis=1)
        # self.all_edges = pd.merge(self.all_edges, new, on=['start', 'end'], how='outer')

        # Make df with all edge data
        self.x_edges = [
            tuple(edge) for edge in self.all_edges[['start_x', 'end_x']].values
        ]
        self.y_edges = [
            tuple(edge) for edge in self.all_edges[['start_y', 'end_y']].values
        ]

        # Set 'start' and 'end' as index for all_edges df
        # Todo: Refactor so this happens later.
        self.all_edges.set_index(['start', 'end'], inplace=True)

        # Set 'sel_bus' (this should in turn set other variables)
        self.sel_bus = sel_bus