Пример #1
0
 def time_format(self, time_format):
     try:
         t = Timeline.app().current.strftime(time_format)  # Throws a ValueError if supplied format is invalid
         self._time_format = time_format
         self.compute_bbox()
     except ValueError:
         post_message("Invalid time specifier", 1)
Пример #2
0
 def RefreshTimeline(self):
     timeline = Timeline.app()
     current = timeline.current
     timeline.reset()
     self.UpdateTimeline(self.project.data_root)
     if current >= timeline.start and current <= timeline.end:
         timeline.current = current
Пример #3
0
    def get_data(self, variable, date=None):
        if self._current_grid is not None and self._current_time == date and self._current_variable == variable:
            return self._current_grid.copy()

        path = os.path.abspath(self.path)
        if self._is_velma and self.time_info.is_temporal:
            if date is None:
                date = Timeline.app().current

            start = self.time_info.timestamps[0]
            end = self.time_info.timestamps[-1]
            if date < start:
                date = start
            elif date > end:
                date = end

            filename = "{}_{}".format(self.data_name, self._loop)
            if self._has_layer:
                filename = filename + '_{}'.format(self._layer)
            filename = filename + "_{}_{}".format(date.year, date.timetuple().tm_yday)
            if self._is_subday:
                filename = filename + '_{:2d}_{:2d}'.format(date.hour, date.minute)
            filename = "{}.asc".format(filename)
            path = os.path.join(os.path.dirname(path), filename)

        with rasterio.open(path) as src:
            self._current_grid = ma.array(src.read(1), mask=np.logical_not(src.read_masks(1)))
        self._current_variable = variable
        self._current_time = date
        return self._current_grid.copy()
Пример #4
0
    def UpdateTimeline(self, root):
        timeline = Timeline.app()
        updated = False
        if root.is_data:
            time_info = root.data.time_info
            if time_info is not None and time_info.is_temporal:
                timestamps = time_info.timestamps

                if not timeline.enabled:
                    timeline.start = timestamps[0]
                    timeline.end = timestamps[-1]
                    updated = True

                if timestamps[0] < timeline.start:
                    timeline.start = timestamps[0]

                if timestamps[-1] > timeline.end:
                    timeline.end = timestamps[-1]

                for t in timestamps:
                    timeline.add_timestamp(t)

        elif root.is_folder:
            for child in root.children:
                updated = updated or self.UpdateTimeline(child)
        return updated
Пример #5
0
    def ApplyFilter(self):
        timeline = Timeline.app()
        start = wx.wxdate2pydate(self.start_ctrl.GetDate())
        end = wx.wxdate2pydate(self.end_ctrl.GetDate())
        interval = self.interval_panel.interval
        time_span = timeline.end - timeline.start
        valid_range = start < end
        valid_interval = timeline.min_step <= interval < time_span

        if valid_range and valid_interval and timeline.enabled:
            timeline.filter_start = start
            timeline.filter_end = end
            timeline.filter_interval = interval
            timeline.use_filter = not (timeline.filter_start == timeline.start
                                       and timeline.filter_end == timeline.end
                                       and timeline.filter_interval
                                       == timeline.min_step)
            self._filter_has_changed = False
            self.RefreshTimeline()
            self.Refresh()
            return True

        else:
            if not valid_range:
                msg = "Invalid filter range - start date exceeds end date."
            elif not valid_interval:
                msg = "Invalid interval - interval is too large or too small."
            else:
                msg = "Invalid filter - unknown error."
            post_message(msg, 1)
            return False
Пример #6
0
 def getData(self, dname, data):
     try:
         node = data[[n.data.data_name for n in data].index(dname)]
     except ValueError:
         return None
     date = Timeline.app().current
     thisdata = node.data.get_data(node.data.variables[0], date=date)
     return thisdata
Пример #7
0
    def load(self, path, controller):

        with open(path) as f:
            data = json.load(f)

        # Migrate imported data to latest version
        if data['version'] < SAVE_FILE_VERSION:
            self.migrate(data)

        self.name = data['name']
        self.data_root = FolderNode.load(data['data_root'],
                                         os.path.dirname(path))
        controller.RefreshTimeline()
        Timeline.app().load_filter(data.get('timeline_filter', None))
        self.visualization_root = FolderNode.load(data['visualization_root'])
        self.exporter = Exporter.load(data.get('exporter', None), self)
        self.is_dirty = False
Пример #8
0
    def color_deltas(self, feature, data):
        """
        Color features based on presence in the Envision Delta Array. Features absent from delta array are colored grey.
        """

        if self.legend is None:
            return GREY

        envision_attribute = self.envision_style[self.current_attribute]
        shp_attribute = envision_attribute.get('column')
        legend = envision_attribute.get('legend')
        value = feature.get('properties').get(shp_attribute)
        idu = int(feature.get('id'))
        minmax = envision_attribute.get('minmax', None)
        string_value = ''

        try:
            if 'delta_array' not in data:
                data['delta_array'] = self.delta_data.get_data(
                    shp_attribute,
                    Timeline.app().current)
                data['index'] = 0
                if data.get('delta_array') is None:
                    self.feature_layer.set_color_function(self.color_shapes)
                    post_message(
                        'Could not retrieve deltas, defaulting to base value.',
                        1)
                    return self.color_shapes(feature, None)

            darray = data.get('delta_array')
            index = data.get('index')

            if darray[index].idu == idu:
                value += darray[index].new_value
                data['index'] += 1
            else:
                if darray[index].idu < idu:
                    while darray[index].idu <= idu:
                        index += 1
                data['index'] = index

                return GREY

        # Handle if we reached the end of the delta array
        except IndexError:
            return GREY

        if minmax is not None:
            for i, pair in enumerate(minmax):
                if pair[0] <= value <= pair[1]:
                    string_value = legend[i].get('label')
                    break

        color = self.legend.get_color(string_value)
        if color is None:
            color = GREY

        return color
Пример #9
0
    def run(self):
        self.task.target = self.exporter.video_frames
        self.encoder.fps = self.exporter.video_fps
        self.task.progress = 0
        self.task.status = Task.RUNNING
        timeline = Timeline.app()
        timeline.current = self.exporter.animation_start
        self.encoder.open(self.path, *self.exporter.size)

        delay = 0  # Give the main thread a chance to catch up
        for frame in range(self.exporter.video_frames):

            # Check if we have any reason to stop
            error = self.task.status == Task.SHOULD_STOP or not self.encoder.is_ok()
            if self.exporter.is_temporal:
                error |= not timeline.current <= self.exporter.animation_end
            if error:
                post_message("There was an error exporting the animation. Export may be incomplete.", 1)
                break

            # Update TaskDialog
            self.task.description = "Exporting frame {} of {}.".format(self.task.progress, self.task.target)

            # Update timeline
            if self.exporter.is_temporal:
                timeline.current = timeline.time_at_index(
                    int(frame * self.exporter.animation_frames / self.exporter.video_frames)
                )

            # Update flythroughs
            for item in self.exporter.items:
                if item.item_type == ExportItem.SCENE and item.flythrough is not None:
                    local_fly_fps = item.flythrough.fps / self.exporter.flythrough_fps
                    item.flythrough.update_camera_to_keyframe(
                        (local_fly_fps * frame * item.flythrough.num_keyframes) / self.exporter.video_frames
                    )

            # Determine max time spend in main thread for rendering, and then add that delay
            t = time.time()
            self.sync_with_main(self.exporter.refresh_item_caches, block=True, delay=delay)
            elapsed = time.time() - t
            if delay == 0:
                delay = elapsed

            # Output items to encoder frame
            frame_bitmap = Image.new("RGB", self.exporter.size, (0, 0, 0))
            for item in self.exporter.items:
                item.draw(frame_bitmap)
            self.encoder.write_frame(frame_bitmap, 1.0 / self.exporter.video_fps)
            if timeline.current > timeline.end:
                break

            self.task.inc_progress()

        self.encoder.finalize()
        self.task.status = Task.COMPLETE
Пример #10
0
 def getData(self, dname, data):
     try:
         node = data[[n.data.data_name for n in data].index(dname)]
     except ValueError:
         return None
     variable = node.data.variables[0]
     stats = node.data.variable_stats(variable)
     date = Timeline.app().current
     thisdata = node.data.get_data(variable, date=date)
     return {'name': dname, 'data': thisdata, 'min': stats.min_value, 'max': stats.max_value}
Пример #11
0
 def OnReset(self, event):
     # Reset timeline filter to start and finish
     timeline = Timeline.app()
     timeline.filter_start = timeline.start
     timeline.filter_end = timeline.end
     timeline.filter_interval = timeline.min_step
     self.interval_panel.interval = timeline.filter_interval
     self._filter_has_changed = False
     self.RefreshTimeline()
     self.Refresh()
Пример #12
0
 def UpdateFromTimeline(self):
     timeline = Timeline.app()
     self._filter_has_changed = False
     self.start_ctrl.SetDateRange(wx.pydate2wxdate(timeline.start),
                                  wx.pydate2wxdate(timeline.end))
     self.start_ctrl.SetDate(wx.pydate2wxdate(timeline.filter_start))
     self.end_ctrl.SetDateRange(wx.pydate2wxdate(timeline.start),
                                wx.pydate2wxdate(timeline.end))
     self.end_ctrl.SetDate(wx.pydate2wxdate(timeline.filter_end))
     self.interval_panel.interval = timeline.filter_interval
     self.Refresh()
Пример #13
0
 def filter_histogram(self):
     if self.attribute_data is not None:
         variable = self._attribute.selected
         stats = self.attribute_data.variable_stats(variable)
         return Histogram(self.attribute_data.get_data(
             variable,
             Timeline.app().current),
                          min_value=stats.min_value,
                          max_value=stats.max_value,
                          nodata_value=stats.nodata_value)
     else:
         return Histogram()
Пример #14
0
 def UpdateEnabledInputs(self):
     timeline = Timeline.app()
     if timeline.enabled:
         maxstep = timeline.end - timeline.start
         minstep = timeline.min_step
         self.days.Enable(maxstep > datetime.timedelta(1, 0, 0)
                          or datetime.timedelta(1, 0, 0) < minstep)
         self.seconds.Enable(maxstep > datetime.timedelta(0, 1, 0)
                             or datetime.timedelta(1, 0, 0) < minstep)
     else:
         self.days.Disable()
         self.seconds.Disable()
Пример #15
0
    def __init__(self, parent, id):
        super().__init__(parent, id)
        self.SetMinSize(wx.Size(200, 40))

        self.timeline_ctrl = TimelineCtrl(self, wx.ID_ANY, Timeline.app())
        self.playback_options_frame = PlaybackOptionsFrame(self, wx.ID_ANY)
        sizer = wx.BoxSizer(wx.HORIZONTAL)
        self.SetSizer(sizer)

        self.step_to_beginning_button = StaticBitmapButton(self, wx.ID_ANY, get_resource_bitmap('step_to_beginning_button.png'),
                                                           wx.DefaultPosition, wx.Size(20, 20))
        self.step_backward_button = StaticBitmapButton(self, wx.ID_ANY, get_resource_bitmap('step_backward_button.png'),
                                                           wx.DefaultPosition, wx.Size(20, 20))
        self.play_button = StaticBitmapButton(self, wx.ID_ANY, get_resource_bitmap('play_button.png'),
                                                           wx.DefaultPosition, wx.Size(20, 20))
        self.step_forward_button = StaticBitmapButton(self, wx.ID_ANY, get_resource_bitmap('step_forward_button.png'),
                                                           wx.DefaultPosition, wx.Size(20, 20))
        self.step_to_end_button = StaticBitmapButton(self, wx.ID_ANY, get_resource_bitmap('step_to_end_button.png'),
                                                           wx.DefaultPosition, wx.Size(20, 20))
        self.playback_options_button = StaticBitmapButton(self, wx.ID_ANY, get_resource_bitmap('playback_options_button.png'),
                                                          wx.DefaultPosition, wx.Size(20, 20))

        self.step_to_beginning_button.SetToolTip("Step to beginning")
        self.step_backward_button.SetToolTip("Step backward one frame")
        self.play_button.SetToolTip("Play animation")
        self.step_forward_button.SetToolTip("Step forward one frame")
        self.step_to_end_button.SetToolTip("Step to end")
        self.playback_options_button.SetToolTip("Expand playback options")

        sizer.Add(self.step_to_beginning_button, 0, wx.RIGHT | wx.ALIGN_CENTER_VERTICAL, 5)
        sizer.Add(self.step_backward_button, 0, wx.RIGHT | wx.ALIGN_CENTER_VERTICAL, 5)
        sizer.Add(self.play_button, 0, wx.RIGHT | wx.ALIGN_CENTER_VERTICAL, 5)
        sizer.Add(self.step_forward_button, 0, wx.RIGHT | wx.ALIGN_CENTER_VERTICAL, 5)
        sizer.Add(self.step_to_end_button, 0, wx.RIGHT | wx.ALIGN_CENTER_VERTICAL, 5)
        sizer.Add(self.timeline_ctrl, 1, wx.LEFT, 8)
        sizer.Add(self.playback_options_button, 0, wx.ALIGN_LEFT | wx.ALIGN_CENTER_VERTICAL, 5)

        self.play_bitmap = get_resource_bitmap('play_button.png')
        self.pause_bitmap = get_resource_bitmap("pause_button.png")

        self.timer = wx.Timer(self, wx.ID_ANY)
        self._playing = False

        self.step_to_beginning_button.Bind(wx.EVT_BUTTON, self.OnStepToBeginningButton)
        self.step_backward_button.Bind(wx.EVT_BUTTON, self.OnStepBackwardButton)
        self.play_button.Bind(wx.EVT_BUTTON, self.OnPlayButton)
        self.step_forward_button.Bind(wx.EVT_BUTTON, self.OnStepForwardButton)
        self.step_to_end_button.Bind(wx.EVT_BUTTON, self.OnStepToEndButton)
        self.playback_options_button.Bind(wx.EVT_BUTTON, self.OnPlaybackOptionsButton)

        self.Bind(wx.EVT_TIMER, self.OnTimer)
        self.Fit()
Пример #16
0
    def get_identify_detail(self, point: Vector3) -> Optional[Dict]:
        if self.terrain_data is not None:
            res = self.terrain_data.resolution
            cell_x = int(round((point.y / res)))
            cell_y = int(round((point.x / res)))

            terrain_attr = self._elevation_attribute.selected
            terrain_ref = self.terrain_data.get_data(terrain_attr)

            if self.attribute_data is not None:
                attribute_ref = self.attribute_data.get_data(
                    self._attribute.selected,
                    Timeline.app().current)
                attr_height, attr_width = attribute_ref.shape
                if 0 <= cell_x < attr_width and 0 <= cell_y < attr_height:

                    result = OrderedDict()
                    result['Point'] = "{}, {}".format(cell_x, cell_y)
                    result['Value'] = attribute_ref[cell_y, cell_x]
                    result['Height'] = terrain_ref[cell_y, cell_x]

                    if self.flow_dir_data is not None:
                        flow_dir_ref = self.flow_dir_data.get_data(
                            self.flow_dir_data.variables[0])
                        direction = flow_dir_ref[cell_y, cell_x]
                        result['Flow Direction (input)'] = direction
                        degrees = 45.0 + 45.0 * direction
                        result[
                            'Flow Direction (degrees)'] = degrees if degrees < 360.0 else degrees - 360.0

                    if self.flow_acc_data is not None:
                        result[
                            'Flow Accumulation'] = self.flow_acc_data.get_data(
                                self.flow_acc_data.variables[0])[cell_y,
                                                                 cell_x]

                    self.selected_point = (cell_x, cell_y)
                    self._needs_boundaries = True
                    self.refresh()

                    return result

        self.selected_point = (-1, -1)
        self._needs_boundaries = True
        self.refresh()

        return None
Пример #17
0
    def get_data(self, variable, date=None):
        if variable != self._current_variable: # read data from disk
            with Dataset(self.path, 'r') as ds:
                slice_to_read = slice(None)
                # If it has a time dimension but no coord var we treat it as non-temporal
                if len(ds.variables[variable].shape) == 3 and not self.time_info.is_temporal:
                    slice_to_read = -1
                self._current_grid = ds.variables[variable][slice_to_read]
            self._current_variable = variable

        slice_to_return = slice(None)
        if self.time_info.is_temporal:
            if date is None:
                date = Timeline.app().current
            slice_to_return = min([i for i in enumerate(self.time_info.timestamps)],
                key=lambda d: abs(d[1] - date))[0]
        return self._current_grid[slice_to_return]
Пример #18
0
    def save(self, path):
        if os.path.exists(path):
            os.remove(path)

        self.name = os.path.split(path)[-1]

        data = {
            'version': SAVE_FILE_VERSION,
            'name': self.name,
            'data_root': self.data_root.serialize(path),
            'visualization_root': self.visualization_root.serialize(),
            'exporter': self.exporter.serialize(),
            'timeline_filter': Timeline.app().serialize_filter()
        }

        with open(path, 'w') as f:
            json.dump(data, f)

        self.is_dirty = False
Пример #19
0
    def _update_terrain_color(self):
        if self.terrain_mesh is not None:
            shader = self.terrain_mesh.shader
            if self.terrain_data and self.attribute_data:
                shader.has_color = True

                # Retrieve color layer
                attribute = self._attribute.selected
                data = self.attribute_data.get_data(attribute,
                                                    Timeline.app().current)

                if type(data) is numpy.ma.MaskedArray:
                    data = data.data

                color_stats = self.attribute_data.variable_stats(attribute)
                if color_stats.nodata_value:
                    shader.nodata_value = color_stats.nodata_value

                self.terrain_mesh.geometry.values = data
                post_redisplay()
            else:
                shader.has_color = False
Пример #20
0
    def refresh_cache(self):

        if self.item_type == self.TIMESTAMP:
            self.compute_bbox()                 # Timestamp label changes based on current time

        snapshot = Image.new("RGBA", self.size, (0, 0, 0, 0))
        draw = ImageDraw.Draw(snapshot)

        if self.item_type == self.SCENE:
            if self.use_flythrough_camera:
                snapshot = self.flythrough.camera.render_to_bitmap(*self.size)
            else:
                snapshot = self.camera.render_to_bitmap(*self.size)
        elif self.item_type == self.LEGEND and self.viz_plugin is not None:
            snapshot = self.viz_plugin.get_legend(*self.size)
        elif self.item_type == self.VISUALIZATION and self.viz_plugin is not None:
            snapshot = self.viz_plugin.visualize(*self.size, back_thread=False)
        elif self.item_type == self.LABEL:
            draw.text((0, 0), self.label, font=self._font)
        elif self.item_type == self.TIMESTAMP:
            draw.text((0, 0), Timeline.app().current.strftime(self._time_format), font=self._font)

        self.cache = snapshot
Пример #21
0
    def __init__(self, parent, id, timeline=None):
        super().__init__(parent, id, style=wx.BORDER_NONE)

        if timeline is None:
            timeline = Timeline.app()

        self.timeline = timeline
        self._scrub_time = None
        self.animation_speed = 1
        self.live_update = False
        self._uniform_time_intervals = False
        self._dragging = False
        self.px_per_step = None
        self._calculate_px_ratio()

        self.Bind(wx.EVT_PAINT, self.OnPaint)
        self.Bind(wx.EVT_ERASE_BACKGROUND, self.OnErase)
        self.Bind(wx.EVT_SIZE, self.OnSize)
        self.Bind(wx.EVT_LEFT_DOWN, self.OnLeftDown)
        self.Bind(wx.EVT_LEFT_UP, self.OnLeftUp)
        self.Bind(wx.EVT_MOTION, self.OnMouseMove)
        self.Bind(wx.EVT_MOUSE_CAPTURE_LOST, self.OnLoseCapture)
        self.Bind(wx.EVT_ENTER_WINDOW, self.OnMouseEnter)
Пример #22
0
    def get_zonal_stats_from_feature(
            self, feature: LinearRing) -> List[Optional[Dict]]:
        results = []
        if self.terrain_data:

            # Normalize feature coordinates to terrain resolution
            t_res = self.terrain_data.resolution
            normalized_coords = [(p[0] / t_res, p[1] / t_res)
                                 for p in feature.coords]

            for plugin in (x for x in (self.terrain_data, self.attribute_data,
                                       self.flow_dir_data, self.flow_dir_data)
                           if x is not None):
                if plugin is self.terrain_data:
                    var = self._elevation_attribute.selected
                elif plugin is self.attribute_data:
                    var = self._attribute.selected
                else:
                    var = ''

                raster = plugin.get_data(var, Timeline.app().current)
                affine = plugin.affine
                var_stats = plugin.variable_stats(var)
                nodata = var_stats.nodata_value
                feat = Polygon(
                    *[[transform.xy(affine, *p) for p in normalized_coords]])

                # Transform normalized raster coordinates to CRS of raster to query and obtain results
                result = zonal_stats(feat,
                                     raster,
                                     affine=affine,
                                     nodata=nodata,
                                     add_stats=self.zonal_stats)[0]
                result['Name'] = plugin.data_name
                results.append(result)
        return results
Пример #23
0
    def OnWindowMenu(self, event):
        event_id = event.GetId()

        if event_id == wx.ID_ABOUT:
            self.OnAboutMenuItem(event)
        elif event_id == wx.ID_EXIT:
            self.main_window.Close()
        elif event_id == MainWindow.MENU_FILE_NEW:
            self.main_window.project_controller.NewProject()
            self.main_window.options_panel.options = None
            self.export_controller.RefreshExporter()
            self.export_controller.Reset()
        elif event_id == MainWindow.MENU_FILE_OPEN:
            self.main_window.project_controller.LoadProjectFromDialog()
            self.export_controller.RefreshExporter()
        elif event_id == MainWindow.MENU_FILE_SAVE:
            self.main_window.project_controller.SaveProject()
        elif event_id == MainWindow.MENU_FILE_SAVEAS:
            self.main_window.project_controller.SaveProjectAs()
        elif event_id == MainWindow.MENU_FILE_ADDDATA:
            self.main_window.project_controller.AddDataFromFile(None)
        elif event_id == MainWindow.MENU_VIEW_ADD_VIEWER:
            self.main_window.viewer_container_panel.AddViewer()
        elif event_id == MainWindow.MENU_VIEW_REMOVE_VIEWER:
            self.main_window.viewer_container_panel.RemoveViewer()
        elif event_id == MainWindow.MENU_VIEW_ADD_GRAPH:
            self.main_window.AddGraphPanel()
        elif event_id == MainWindow.MENU_VIEW_REMOVE_GRAPH:
            self.main_window.RemoveGraphPanel()
        elif event_id == MainWindow.MENU_VIEW_COLLAPSE:
            self.main_window.ToggleProjectPanel()
        elif event_id == MainWindow.MENU_EXPORT_EXPORT:
            self.export_controller.SetExportWindow(
                self.GetDefaultExporter(True))
            self.export_controller.ShowWindow()
        elif event_id == MainWindow.MENU_EXPORT_CURRENT_COPY:
            self.RenderCurrentViewToClipboard()
        elif event_id == MainWindow.MENU_EXPORT_CURRENT_SAVE:
            self.RenderCurrentViewToFile()
        elif event_id == MainWindow.MENU_FLYTHROUGH_GENERATE:
            all_scenes = self.main_window.project_controller.project.all_scenes
            selector = FlythroughSceneSelector(all_scenes, None, wx.ID_ANY)
            if selector.ShowModal() == wx.ID_OK:
                selection = selector.GetSceneChoice()
                for i in range(len(all_scenes)):
                    if i == selection:
                        self.main_window.project_controller.AddFlythrough(
                            all_scenes[i])

        elif event_id == MainWindow.MENU_SYNC_CAMERAS:
            sync = self.main_window.GetToolBar().FindById(
                MainWindow.MENU_SYNC_CAMERAS).IsToggled()
            self.main_window.viewer_container_panel.SyncAllCameras(sync, True)
        elif event_id == MainWindow.MENU_OPEN_TIMELINE_FILTER:
            if Timeline.app().enabled:
                self.time_filter_window.Show()
        elif event_id == MainWindow.MENU_WINDOW_PLUGINS:
            self.plugins_window.Show()
            self.plugins_window.Raise()
        elif event_id == MainWindow.MENU_DEBUG:
            pass
        elif event_id == MainWindow.MENU_DEBUG_TOGGLE_WIREFRAME:
            self.main_window.viewer_container_panel.ToggleWireframe()
        elif event_id == MainWindow.MENU_DEBUG_TOGGLE_SELECTION_VIEW:
            pass  # Todo
        elif event_id == MainWindow.MENU_HELP_REPORT_ISSUE:
            wx.LaunchDefaultBrowser(
                'https://github.com/VISTAS-IVES/pyvistas/issues')

        elif event_id == MainWindow.MENU_LINREG:
            dlg = LinRegDialog(self.main_window)
        elif event_id == MainWindow.MENU_PCA:
            dlg = PcaDialog(self.main_window)
Пример #24
0
 def OnExportFramesInput(self, event):
     input_frames = float(self.export_frames_ctrl.GetValue())
     self.export_length_ctrl.ChangeValue(
         str(Timeline.app().num_timestamps / input_frames))
Пример #25
0
 def OnExportLengthInput(self, event):
     if self.export_frames_ctrl.IsEnabled():
         export_timestamps = Timeline.app(
         ).num_timestamps / self.export_length
         self.export_frames_ctrl.ChangeValue(str(export_timestamps))
Пример #26
0
    def __init__(self, parent, id, enable_frames_input=True):
        super().__init__(parent,
                         id,
                         "Export Options",
                         style=wx.CAPTION | wx.STAY_ON_TOP)
        main_panel = wx.Panel(self, wx.ID_ANY)

        encoder_static = wx.StaticText(main_panel, wx.ID_ANY, "Export As:")
        self.encoder_choice = wx.Choice(main_panel,
                                        wx.ID_ANY,
                                        size=wx.Size(220, -1))

        self.encoder_choice.Append("Video File")
        self.encoder_choice.Append("Individual Image Files")
        self.encoder_choice.SetSelection(0)

        initial_export_length = 30.0

        export_length_static = wx.StaticText(main_panel, wx.ID_ANY,
                                             "Length of export (in seconds):")
        self.export_length_ctrl = FloatCtrl(main_panel,
                                            wx.ID_ANY,
                                            value=initial_export_length,
                                            size=wx.Size(50, -1))

        initial_export_timestamps = Timeline.app(
        ).num_timestamps / initial_export_length

        export_frames_static = wx.StaticText(main_panel, wx.ID_ANY,
                                             "Timestamps per second:")
        self.export_frames_ctrl = FloatCtrl(main_panel,
                                            wx.ID_ANY,
                                            value=initial_export_timestamps,
                                            size=wx.Size(50, -1))

        self.export_frames_ctrl.Enable(enable_frames_input)

        main_sizer = wx.BoxSizer(wx.VERTICAL)
        self.SetSizer(main_sizer)

        main_panel_sizer = wx.BoxSizer(wx.VERTICAL)
        main_panel.SetSizer(main_panel_sizer)

        main_panel_sizer.Add(encoder_static)
        main_panel_sizer.Add(self.encoder_choice, 0, wx.EXPAND)

        export_length_sizer = wx.BoxSizer(wx.HORIZONTAL)
        export_length_sizer.Add(export_length_static, 0, wx.RIGHT, 5)
        export_length_sizer.AddStretchSpacer(2)
        export_length_sizer.Add(self.export_length_ctrl, 0, wx.RIGHT, 5)
        main_panel_sizer.Add(export_length_sizer, 0, wx.ALL | wx.EXPAND, 10)

        export_frames_sizer = wx.BoxSizer(wx.HORIZONTAL)
        export_frames_sizer.Add(export_frames_static, 0, wx.RIGHT, 5)
        export_frames_sizer.AddStretchSpacer(2)
        export_frames_sizer.Add(self.export_frames_ctrl, 0, wx.RIGHT, 5)
        main_panel_sizer.Add(export_frames_sizer, 0, wx.ALL | wx.EXPAND, 10)

        main_sizer.Add(main_panel, 1, wx.EXPAND | wx.ALL, 5)
        main_sizer.Add(self.CreateButtonSizer(wx.OK | wx.CANCEL), 0,
                       wx.EXPAND | wx.ALL, 5)

        self.export_length_ctrl.Bind(EVT_FLOAT, self.OnExportLengthInput)
        self.export_frames_ctrl.Bind(EVT_FLOAT, self.OnExportFramesInput)

        self.Fit()
Пример #27
0
 def RefreshTimeline(self):
     post_timeline_change(Timeline.app().current,
                          TimelineEvent.VALUE_CHANGED)
Пример #28
0
    def GetDefaultExporter(self, add_labels=False):
        exporter = Exporter()
        viewerpanels = self.main_window.viewer_container_panel.GetAllViewerPanels(
        )
        x_offset = 0
        y_offset = 0
        prev_height = 0
        i = 0
        num_columns = self.main_window.viewer_container_panel.num_columns
        for panel in viewerpanels:
            if i % num_columns == 0:
                x_offset = 0
                y_offset = prev_height
                prev_height = 0

            export_item = ExportItem(ExportItem.SCENE, (x_offset, y_offset),
                                     panel.GetSize().Get())
            export_item.camera = panel.camera
            for node in self.main_window.project_controller.project.all_scenes:
                if panel.camera.scene is node.scene:
                    export_item.project_node_id = node.node_id
                    exporter.add_item(export_item)

                    if add_labels:
                        label = ExportItem(ExportItem.LABEL)
                        label.size = (100, 100)
                        label.label = export_item.camera.scene.name
                        label.position = (int(x_offset +
                                              export_item.size[0] / 5 - 50),
                                          int(y_offset +
                                              export_item.size[1] / 5))
                        exporter.add_item(label)

                        timestamp = ExportItem(ExportItem.TIMESTAMP)
                        timestamp.time_format = Timeline.app().time_format
                        timestamp.position = (int(x_offset +
                                                  export_item.size[0] / 2 -
                                                  timestamp.size[0] / 2),
                                              int(y_offset +
                                                  export_item.size[1] / 5))
                        exporter.add_item(timestamp)

                    x_offset += export_item.size[0] + PADDING
                    prev_height = max(prev_height,
                                      export_item.size[1] + PADDING)
                    i += 1

                    break

        x_offset = 0
        y_offset = prev_height

        for panel in self.main_window.graph_panels:
            if panel.visualization is not None:
                node = self.main_window.project_controller.project.find_visualization_node(
                    panel.visualization)
                export_item = ExportItem(ExportItem.VISUALIZATION,
                                         (x_offset, y_offset),
                                         panel.GetSize().Get())
                export_item.viz_plugin = panel.visualization
                export_item.project_node_id = node.node_id
                exporter.add_item(export_item)
                y_offset += export_item.size[1] + PADDING

        exporter.fit_to_items()
        return exporter
Пример #29
0
    def render(self, width, height):
        if self.data is None:
            return

        grid = self.data.get_data(self.attribute_option.selected, Timeline.app().current)

        background_color = self.bg_color_option.value.rgb.rgb_list
        label_color = self.label_color_option.value.rgb.rgb_list
        show_labels = self.labels_option.value
        num_categories = self.num_categories.value
        categories = self.categories_group.flat_list

        unique_values = dict(zip(*numpy.unique(grid, return_counts=True)))  # dictionary of unique values to count
        values = list()
        colors = list()
        labels = list()

        for i in range(num_categories):
            try:
                value, label, color, _ = [opt.value for opt in categories[i*4:i*4+4]]
            except:
                continue    # Bail on this index, the viz is probably updating

            if label == '':
                label = value

            if value in unique_values:
                values.append(unique_values[value])
            else:
                values.append(0)

            colors.append(color.rgb.rgb_list)
            labels.append(label)

        indices = numpy.arange(len(values))
        values = tuple(values)
        labels = tuple(labels)

        fig = pyplot.figure(
            figsize=(width / 100, height / 100), dpi=100, tight_layout=True,
            facecolor=self.bg_color_option.value.rgb.rgb_list
        )

        try:
            ax = fig.add_subplot(1, 1, 1, facecolor=background_color)
            ax.margins(1 / width, 1 / height)

            bars = ax.bar(indices, values, color='r')

            for b in indices:
                bars[b].set_color(colors[b])            # Set unique colors here

            # add some text for labels, title and axes ticks
            ax.set_xticks(indices)
            ax.set_xticklabels(tuple(labels))           # labels go here
            ax.get_xaxis().set_visible(show_labels)

            ax.tick_params(color=label_color)
            for spine in ('left', 'bottom'):
                ax.spines[spine].set_color(label_color)

            for label in ax.get_xticklabels() + ax.get_yticklabels():
                label.set_color(label_color)

            max_value = max(values)

            # attach a text label within each bar displaying the count
            for i, rect in enumerate(bars):
                count = rect.get_height()
                above = count < max_value / 2
                label_height = count + 5 if above else count * 0.5
                va = 'bottom' if above else 'center'
                bg_color = background_color if above else colors[i]
                bar_label_color = (0, 0, 0) if sum([x * 255 for x in bg_color]) > 384 else (1, 1, 1)
                ax.text(rect.get_x() + rect.get_width() / 2., label_height, '%d' % int(count), ha='center', va=va,
                        color=bar_label_color)

            return self.fig_to_pil(fig).resize((width, height))

        finally:
            pyplot.close(fig)
Пример #30
0
    def __init__(self, parent):
        super().__init__(parent,
                         wx.ID_ANY,
                         "Timeline Filter",
                         style=wx.SYSTEM_MENU | wx.CAPTION | wx.CLOSE_BOX
                         | wx.FRAME_FLOAT_ON_PARENT)
        timeline = Timeline.app()
        self._filter_has_changed = False

        main_panel = wx.Panel(self, wx.ID_ANY)

        self.start_ctrl = wx.adv.CalendarCtrl(main_panel,
                                              wx.ID_ANY,
                                              date=wx.pydate2wxdate(
                                                  timeline.start))
        self.start_ctrl.SetDateRange(wx.pydate2wxdate(timeline.start),
                                     wx.pydate2wxdate(timeline.end))

        self.end_ctrl = wx.adv.CalendarCtrl(main_panel,
                                            wx.ID_ANY,
                                            date=wx.pydate2wxdate(
                                                timeline.end))
        self.end_ctrl.SetDateRange(wx.pydate2wxdate(timeline.start),
                                   wx.pydate2wxdate(timeline.end))

        self.apply_button = wx.Button(main_panel, wx.ID_ANY, "Apply")
        self.apply_button.SetDefault()
        self.reset_button = wx.Button(main_panel, wx.ID_ANY, "Reset")

        main_sizer = wx.BoxSizer(wx.VERTICAL)
        self.SetSizer(main_sizer)

        panel_sizer = wx.BoxSizer(wx.VERTICAL)
        main_panel.SetSizer(panel_sizer)

        start_sizer = wx.BoxSizer(wx.VERTICAL)
        start_label = wx.StaticText(main_panel, wx.ID_ANY, "Start Date")
        start_sizer.Add(start_label, 0, wx.ALIGN_CENTER_HORIZONTAL | wx.BOTTOM,
                        10)
        start_sizer.Add(self.start_ctrl)

        end_sizer = wx.BoxSizer(wx.VERTICAL)
        end_label = wx.StaticText(main_panel, wx.ID_ANY, "End Date")
        end_sizer.Add(end_label, 0, wx.ALIGN_CENTER_HORIZONTAL | wx.BOTTOM, 10)
        end_sizer.Add(self.end_ctrl)

        calendar_sizer = wx.BoxSizer(wx.HORIZONTAL)
        calendar_sizer.Add(start_sizer, 0, wx.EXPAND | wx.RIGHT, 10)
        calendar_sizer.Add(end_sizer, 0, wx.EXPAND | wx.LEFT, 10)
        panel_sizer.Add(calendar_sizer, 0, wx.EXPAND | wx.ALL, 10)

        self.interval_panel = TimeIntervalPanel(main_panel, wx.ID_ANY)
        panel_sizer.Add(self.interval_panel, 0, wx.ALIGN_CENTER_HORIZONTAL)

        button_sizer = wx.BoxSizer(wx.HORIZONTAL)
        button_sizer.Add(self.apply_button)
        button_sizer.Add(self.reset_button)
        panel_sizer.Add(button_sizer, 0, wx.ALIGN_RIGHT | wx.RIGHT | wx.BOTTOM,
                        10)

        main_sizer.Add(main_panel, 1, wx.EXPAND)

        self.CenterOnParent()
        self.Fit()

        self.Bind(wx.EVT_SHOW, self.OnShow)
        self.Bind(wx.EVT_CLOSE, self.OnClose)
        self.start_ctrl.Bind(wx.adv.EVT_CALENDAR_SEL_CHANGED, self.OnCalendar)
        self.end_ctrl.Bind(wx.adv.EVT_CALENDAR_SEL_CHANGED, self.OnCalendar)
        self.apply_button.Bind(wx.EVT_BUTTON, self.OnApply)
        self.reset_button.Bind(wx.EVT_BUTTON, self.OnReset)
        self.Refresh()