exoplanetsgraph.py (34963B)
1 #Embedded file name: C:\BuildAgent\work\20d73f1b24eed06e\eve\release\V24.01\packages\projectdiscovery\client\projects\exoplanets\graphs\exoplanetsgraph.py 2 from __future__ import absolute_import 3 from carbonui.graphs.axis import AutoTicksAxis 4 from carbonui.graphs.graph import GraphArea 5 from carbonui.graphs.grid import Grid 6 from carbonui.graphs.minimap import MiniMap 7 from carbonui.graphs.pointgraph import PointGraph 8 from carbonui.primitives.container import Container 9 from eve.client.script.ui.control.eveLoadingWheel import LoadingWheel 10 from evegraphics import settings as gfxsettings 11 from projectdiscovery.client.projects.exoplanets.graphs.consensusgraph import ConsensusGraph 12 from projectdiscovery.client.projects.exoplanets.graphs.exoplanetsminigraph import ExoPlanetsMiniGraph 13 from projectdiscovery.client.projects.exoplanets.graphs.exoplanetsbasegraph import ExoPlanetsGraphContainer 14 from carbonui.primitives.line import Line 15 from carbonui.uianimations import animations as uianimations 16 from itertools import izip 17 from projectdiscovery.client import const 18 from projectdiscovery.client.projects.exoplanets.exoplanetsutil import calibration, binning, result, zoom 19 from projectdiscovery.client.projects.exoplanets.graphs.resulticongraph import ResultIconGraph 20 from projectdiscovery.client.projects.exoplanets.graphtools.magnifyingglasstool import MagnifyingGlassTool, MagnifyingGlassScalingOrientation 21 from projectdiscovery.client.projects.exoplanets.transitinformationcontainer import TransitInformationContainer 22 import carbonui.const as uiconst 23 import carbonui.graphs.axis as axis 24 import carbonui.graphs.axislabels as axislabels 25 from . import animations 26 import trinity 27 import geo2 28 import blue 29 import math 30 import localization 31 FOLD_ANIMATION_MAX_TIME = 0.5 32 33 class ExoPlanetsGraph(ExoPlanetsGraphContainer): 34 __notifyevents__ = ExoPlanetsGraphContainer.__notifyevents__ + ['OnProjectDiscoveryResultBackButtonPressed'] 35 default_mini_map_color = (1.0, 36 1.0, 37 1.0, 38 0.09) 39 40 def ApplyAttributes(self, attributes): 41 self._audio_service = sm.GetService('audio') 42 self.setup_binning_fidelity() 43 self._mini_graph = None 44 self._mini_map = None 45 self._mini_map_area = None 46 self._loading_wheel = None 47 self._is_time_axis_dirty = False 48 self._is_mini_map_hidden = False 49 self._desired_animation_zoom = None 50 self._m_update_progression = 0 51 self._is_zoom_animation = False 52 self._is_update_animation = False 53 self._is_calibration_animation = False 54 self._is_fold_animation = False 55 self._m_calibration_progression = 0 56 self._calibration_marking_start_points = [] 57 self._calibration_marking_end_points = [] 58 self._calibration_marking_color = (1, 1, 1, 1) 59 self._calibration_axis = None 60 self._calibration_graph = None 61 self._start_animation_data = [] 62 self._end_animation_data = [] 63 self._consensus_vertical_axis = None 64 self._consensus_time_axis = None 65 self._consensus_graph = None 66 self._interval_mapping = {} 67 self._is_result_shown = False 68 self._correct_horizontal_axis = None 69 self._missed_horizontal_axis = None 70 self._incorrect_horizontal_axis = None 71 self._correct_graph = None 72 self._missed_graph = None 73 self._incorrect_graph = None 74 self._fold_result_state = None 75 self._fold_result_points_indices = [] 76 self._correct_point_indices = [] 77 self._missed_point_indices = [] 78 self._incorrect_point_indices = [] 79 self._result_icon_graphs = [] 80 self._correct_intervals = [] 81 self._incorrect_intervals = [] 82 self._missed_intervals = [] 83 self._last_scroll_time = 0 84 self._scroll_reset_time = 1 85 self._is_scroll_reset = True 86 super(ExoPlanetsGraph, self).ApplyAttributes(attributes) 87 self.pickState = uiconst.TR2_SPS_ON 88 self._setup_layout() 89 90 def setup_binning_fidelity(self): 91 shader_quality = gfxsettings.Get(gfxsettings.GFX_SHADER_QUALITY) 92 self.animation_binning_fidelity = 15 if shader_quality == 1 else 1 93 self.binning_fidelity = 1 94 95 def graph_update(self): 96 while not self.destroyed: 97 current_time = trinity.device.animationTime 98 if self.is_mouse_moved: 99 self.is_mouse_moved = False 100 self.on_mouse_move() 101 if self.is_wheel_scrolled: 102 self.is_wheel_scrolled = False 103 self.on_mouse_wheel(self.scroll_amount) 104 if self._is_time_axis_dirty: 105 self.on_time_axis_changed() 106 if not self._is_scroll_reset and current_time >= self._last_scroll_time + self._scroll_reset_time: 107 self._is_scroll_reset = True 108 if not self.is_animation_running(): 109 self.on_graph_movement_stopped() 110 blue.synchro.Yield() 111 self.unlock_graph_updates() 112 113 def disable_point_graph(self): 114 if self._main_graph: 115 self._main_graph.set_show_status_of_point_graph(False) 116 117 def enable_point_graph(self): 118 if self._main_graph: 119 self._main_graph.set_show_status_of_point_graph(True) 120 if not self.is_animation_running() and self._is_scroll_reset: 121 self._main_graph.show_point_graph() 122 123 def on_mouse_wheel(self, amount): 124 if self.is_folding(): 125 self._scroll_fade() 126 super(ExoPlanetsGraph, self).on_mouse_wheel(amount) 127 128 def _scroll_fade(self, *args, **kwargs): 129 self._is_scroll_reset = False 130 self._last_scroll_time = trinity.device.animationTime 131 self.on_graph_movement() 132 133 def _setup_layout(self): 134 self._graph_container = None 135 if self._loading_wheel: 136 self._loading_wheel.Close() 137 self._loading_wheel = None 138 if self._graph_data: 139 self.SetState(uiconst.UI_NORMAL) 140 self.setup_graph() 141 sm.ScatterEvent('OnEnableDetrend') 142 else: 143 self.SetState(uiconst.UI_DISABLED) 144 self._setup_waiting_screen() 145 146 def setup_graph(self): 147 self._audio_service.SendUIEvent(const.Sounds.MainImageLoadStop) 148 self._graph_container = Container(name='graphContainer', parent=self, align=uiconst.TOALL) 149 self._consensus_vertical_axis = AutoTicksAxis(dataRange=(0, 1.6), tickCount=10, tickFilter=consensus_tick_filter, labelFormat=consensus_label_format) 150 self._flux_axis = self._flux_axis_type(self.get_range_of_flux(), tickCount=4, margins=(0.01, 0.01)) 151 self._time_axis = self._time_axis_type(self.get_time_values(self._graph_data), margins=(0.01, 0.01)) 152 self._category_axes.append(self._time_axis) 153 Line(parent=self._graph_container, align=uiconst.TOBOTTOM, opacity=0.2) 154 self._setup_mini_map_area() 155 Line(parent=self._graph_container, align=uiconst.TOBOTTOM, opacity=0.2) 156 self._time_labels = axislabels.AxisLabels(name='ExoPlanetsTimeLabels', parent=self._graph_container, align=uiconst.TOBOTTOM, height=30, axis=self._time_axis, orientation=axis.AxisOrientation.HORIZONTAL, minFactor=0, maxFactor=1, textAlignment=uiconst.CENTER) 157 Line(parent=self._graph_container, align=uiconst.TOBOTTOM, opacity=0.05) 158 self._tooltip_area = Container(name='TooltipArea', parent=self._graph_container, align=uiconst.TOALL) 159 if self._tool: 160 self.set_tool(self._tool) 161 self._consensus_graph_area = GraphArea(name='ConsensusGraphArea', parent=self._graph_container, align=uiconst.TOALL, clipChildren=False, state=uiconst.UI_PICKCHILDREN, opacity=0) 162 self._graph_area = GraphArea(name='GraphArea', parent=self._graph_container, align=uiconst.TOALL, state=uiconst.UI_PICKCHILDREN) 163 self._transit_info_container = TransitInformationContainer(name='TransitInfoContainer', parent=self._graph_area, align=uiconst.CENTERRIGHT, height=60, width=500, top=30, padRight=10, buttonFunc=None) 164 self._flux_labels = axislabels.AxisLabels(name='ExoPlanetsFluxLabels', parent=self._graph_area, align=uiconst.TOLEFT_NOPUSH, width=100, axis=self._flux_axis, orientation=axis.AxisOrientation.VERTICAL, minFactor=1, maxFactor=0, textAlignment=uiconst.CENTERLEFT) 165 self._consensus_labels = axislabels.AxisLabels(name='ConsensusLabels', parent=self._consensus_graph_area, align=uiconst.TORIGHT_NOPUSH, width=100, axis=self._consensus_vertical_axis, orientation=axis.AxisOrientation.VERTICAL, minFactor=1, maxFactor=0, textAlignment=uiconst.CENTERRIGHT) 166 self.set_fux_display_state(FluxDisplayState.RELATIVE) 167 self._graph_area.AddAxis(orientation=axis.AxisOrientation.VERTICAL, axis=self._flux_axis, minFactor=1.0, maxFactor=0.0) 168 self._graph_area.AddAxis(orientation=axis.AxisOrientation.HORIZONTAL, axis=self._time_axis) 169 self._create_graph_from_data(self._graph_data) 170 self.horizontalLines = Grid(parent=self._graph_area, axis=self._flux_axis, orientation=axis.AxisOrientation.VERTICAL, color=(1, 1, 1, 0.05), minFactor=1.0, maxFactor=0.0) 171 self._consensus_lines = Grid(parent=self._consensus_graph_area, axis=self._consensus_vertical_axis, orientation=axis.AxisOrientation.VERTICAL, color=(1, 1, 1, 0.05), minFactor=1.0, maxFactor=0.0) 172 173 def _setup_waiting_screen(self): 174 self._audio_service.SendUIEvent(const.Sounds.MainImageLoadPlay) 175 self._loading_wheel = LoadingWheel(name='LoadingWheel', parent=self, align=uiconst.CENTER) 176 177 def _setup_mini_map_area(self): 178 self._mini_map_area = Container(name='MiniMapArea', parent=self._graph_container, align=uiconst.TOBOTTOM, height=80) 179 self._mini_map_area.pickState = uiconst.TR2_SPS_ON 180 self._setup_zoom_mini_map() 181 182 def _setup_zoom_mini_map(self): 183 self._control_axis = self._time_axis_type(self.get_time_values(self._graph_data)[:1], dataRange=(self._time_axis.get_min_value(), self._time_axis.get_max_value())) 184 self._category_axes.append(self._control_axis) 185 self._control_axis.onChange.connect(self._set_time_axis_dirty) 186 self._mini_map = MiniMap(name='MiniMap', parent=self._mini_map_area, align=uiconst.TOALL, controlAxis=self._control_axis, state=uiconst.UI_PICKCHILDREN) 187 self._mini_map.slider.name = 'ExoPlanetsZoomSlider' 188 self._mini_map.slider.beforeAxisUpdate.connect(self.lock_graph_updates) 189 self._mini_map.slider.onSliderStart.connect(self.on_graph_movement) 190 self._mini_map.slider.onSliderReleased.connect(self.on_graph_movement_stopped) 191 self._mini_map.slider.onSliderWheel.connect(self._scroll_fade) 192 self._mini_map.slider.pickState = uiconst.TR2_SPS_ON 193 self._mini_graph = ExoPlanetsMiniGraph(name='MiniGraph', parent=self._mini_map_area, align=uiconst.TOALL, opacity=1, state=uiconst.UI_NORMAL) 194 self._mini_graph.set_data(self._graph_data) 195 self._mini_graph.set_tool(MagnifyingGlassTool(scaling_orientation=MagnifyingGlassScalingOrientation.HORIZONTAL, adjust_flux_zoom=False, on_click=lambda t1, t2, f1, f2: (self.zoom(t1, t2) if not self.is_folding() else None))) 196 self.zoom(*self._control_axis.get_visible_range()) 197 198 def Close(self): 199 if self._mini_map: 200 self._control_axis.onChange.disconnect(self._set_time_axis_dirty) 201 self._mini_map.slider.beforeAxisUpdate.disconnect(self.lock_graph_updates) 202 self._mini_map.slider.onSliderStart.disconnect(self.on_graph_movement) 203 self._mini_map.slider.onSliderReleased.disconnect(self.on_graph_movement_stopped) 204 self._mini_map.slider.onSliderWheel.disconnect(self._scroll_fade) 205 super(ExoPlanetsGraph, self).Close() 206 207 def setup_result_graph(self, correct_intervals, missed_intervals, incorrect_intervals, interval_mapping): 208 self._interval_mapping = interval_mapping 209 self._correct_intervals = correct_intervals 210 self._missed_intervals = missed_intervals 211 self._incorrect_intervals = incorrect_intervals 212 self._correct_point_indices, self._missed_point_indices, self._incorrect_point_indices = result.categorize_point_indices_to_result(self._graph_data, correct_intervals, missed_intervals, incorrect_intervals) 213 self._show_result_graph() 214 self._show_result_icon_graphs(correct_intervals, missed_intervals, incorrect_intervals) 215 216 def _show_result_graph(self): 217 self.clear_result_graph() 218 if self.is_folding(): 219 points = [ self._graph_data[i] for i in self._fold_result_points_indices ] 220 color = const.Colors.GREEN if self._fold_result_state == result.ResultStates.CORRECT else const.Colors.YELLOW 221 self._correct_horizontal_axis, self._correct_graph = self._create_result_graph_components(points, color, points_size=3) 222 uianimations.BlinkIn(self._correct_graph) 223 return 224 correct_points = [ self._graph_data[i] for i in self._correct_point_indices ] 225 missed_points = [ self._graph_data[i] for i in self._missed_point_indices ] 226 incorrect_points = [ self._graph_data[i] for i in self._incorrect_point_indices ] 227 self._correct_horizontal_axis, self._correct_graph = self._create_result_graph_components(correct_points, const.Colors.GREEN) 228 self._missed_horizontal_axis, self._missed_graph = self._create_result_graph_components(missed_points, const.Colors.YELLOW) 229 self._incorrect_horizontal_axis, self._incorrect_graph = self._create_result_graph_components(incorrect_points, const.Colors.RED) 230 self._is_result_shown = True 231 uianimations.BlinkIn(self._correct_graph) 232 uianimations.BlinkIn(self._missed_graph) 233 uianimations.BlinkIn(self._incorrect_graph) 234 235 def clear_result_graph(self): 236 if self._correct_graph: 237 self._correct_graph.Close() 238 if self._missed_graph: 239 self._missed_graph.Close() 240 if self._incorrect_graph: 241 self._incorrect_graph.Close() 242 self._correct_horizontal_axis = None 243 self._missed_horizontal_axis = None 244 self._incorrect_horizontal_axis = None 245 self._correct_graph = None 246 self._missed_graph = None 247 self._incorrect_graph = None 248 249 def _create_result_graph_components(self, points, color, points_size = 4): 250 time_values = self.get_time_values(points) 251 flux_values = self.get_flux_values(points) 252 category_axis = self._time_axis_type(time_values, dataRange=(self._time_axis.get_min_value(), self._time_axis.get_max_value())) 253 category_axis.set_zoom(*self._control_axis.get_visible_range()) 254 if self.is_folding(): 255 category_axis.fold(self._fold_center, self._period_length) 256 self._category_axes.append(category_axis) 257 self._graph_area.AddAxis(orientation=axis.AxisOrientation.HORIZONTAL, axis=category_axis) 258 graph = PointGraph(name='ResultGraph', parent=self._graph_area, categoryAxis=category_axis, valueAxis=self._flux_axis, values=flux_values, pointColor=color, pointSize=points_size, state=uiconst.UI_DISABLED, idx=0) 259 return (category_axis, graph) 260 261 def _show_result_icon_graphs(self, correct_intervals, missed_intervals, incorrect_intervals): 262 axis1, graph1 = self._create_result_icon_graph_components(correct_intervals, 'res:/UI/Texture/classes/ProjectDiscovery/result_success.png', const.Colors.GREEN, localization.GetByLabel('UI/ProjectDiscovery/exoplanets/CorrectClickForInfo')) 263 axis2, graph2 = self._create_result_icon_graph_components(missed_intervals, 'res:/UI/Texture/classes/ProjectDiscovery/result_missed.png', const.Colors.YELLOW, localization.GetByLabel('UI/ProjectDiscovery/exoplanets/MissedClickForInfo')) 264 axis3, graph3 = self._create_result_icon_graph_components(incorrect_intervals, 'res:/UI/Texture/classes/ProjectDiscovery/result_fail.png', const.Colors.RED, localization.GetByLabel('UI/ProjectDiscovery/exoplanets/IncorrectClickForInfo')) 265 self._result_icon_graphs = [graph1, graph2, graph3] 266 267 def _get_intervals_centers(self, intervals): 268 return [ interval[0] * 0.5 + interval[1] * 0.5 for interval in intervals ] 269 270 def _create_result_icon_graph_components(self, intervals, icon_path, color, tooltip): 271 interval_centers = self._get_intervals_centers(intervals) 272 category_axis = self._time_axis_type(interval_centers, dataRange=(self._time_axis.get_min_value(), self._time_axis.get_max_value())) 273 self._category_axes.append(category_axis) 274 self._graph_area.AddAxis(orientation=axis.AxisOrientation.HORIZONTAL, axis=category_axis) 275 graph = ResultIconGraph(name='ResultIconGraph', parent=self._graph_area, categoryAxis=category_axis, color=color, iconPath=icon_path, tooltipMessage=tooltip, transitIntervals=intervals, onClick=self._on_result_click, intervalMapping=self._interval_mapping) 276 return (category_axis, graph) 277 278 def _hide_icon_graphs(self, is_hidden = True): 279 for graph in self._result_icon_graphs: 280 graph.state = uiconst.UI_DISABLED if is_hidden else uiconst.UI_PICKCHILDREN 281 animation = uianimations.BlinkOut if is_hidden else uianimations.BlinkIn 282 animation(graph) 283 284 def _on_result_click(self, minimum, maximum): 285 self._hide_icon_graphs() 286 287 def calibrate_in(): 288 self.clear_result_graph() 289 self.calibrate_to_folded_mode(marker.get_center(), marker.get_period_length(), callback=lambda : self._show_result_graph() or sm.ScatterEvent('OnEnableDetrend') or sm.ScatterEvent('OnShowProjectDiscoveryResultBackButton')) 290 291 self.hide_mini_map_zoom(True, duration=0.5) 292 if (minimum, maximum) in self._interval_mapping: 293 marker = self._interval_mapping[minimum, maximum] 294 self._fold_result_points_indices, self._fold_result_state = result.get_intervals_points_indices_of_same_state(self._correct_intervals, self._missed_intervals, self._incorrect_intervals, (minimum, maximum), self._interval_mapping, self._graph_data) 295 sm.ScatterEvent('OnDisplayTransitInformation', marker, state=self._fold_result_state) 296 if len(marker.get_centers()) > 1: 297 sm.ScatterEvent('OnDisableDetrend') 298 self.reset_zoom(callback=calibrate_in) 299 return 300 else: 301 sm.ScatterEvent('OnDisplayTransitInformation', None, epoch=round(0.5 * minimum + 0.5 * maximum - self._graph_data[0][0], 3)) 302 sm.ScatterEvent('OnShowProjectDiscoveryResultBackButton') 303 self.zoom_animated(minimum - (maximum - minimum) * 2, maximum + (maximum - minimum) * 2, max_duration=0.5) 304 305 def OnProjectDiscoveryResultBackButtonPressed(self, *args, **kwargs): 306 self._hide_icon_graphs(False) 307 if self.is_folding(): 308 self.calibrate_to_unfolded_mode(callback=lambda : self.show_mini_map_zoom(True, 0.5) or sm.ScatterEvent('OnDisplayTransitMarkers')) 309 else: 310 self.reset_zoom() 311 self.show_mini_map_zoom(True, 0.5) 312 sm.ScatterEvent('OnHideTransitInformation') 313 314 def setup_consensus_graph(self, consensus_data, transit_markers): 315 if not consensus_data: 316 return 317 time_values = [] 318 for min_time, max_time, value in consensus_data: 319 time_values.append(min_time) 320 time_values.append(max_time) 321 322 uianimations.BlinkOut(self.horizontalLines, startVal=0.05, endVal=0.0) 323 uianimations.BlinkIn(self._consensus_graph_area) 324 self._consensus_time_axis = self._time_axis_type(time_values) 325 self._consensus_graph_area.AddAxis(orientation=axis.AxisOrientation.VERTICAL, axis=self._consensus_vertical_axis, minFactor=1.0, maxFactor=0.0) 326 self._consensus_graph_area.AddAxis(orientation=axis.AxisOrientation.HORIZONTAL, axis=self._consensus_time_axis) 327 self._category_axes.append(self._consensus_time_axis) 328 self._consensus_graph = ConsensusGraph(name='ConsensusGraph', parent=self._consensus_graph_area, categoryAxis=self._consensus_time_axis, valueAxis=self._consensus_vertical_axis, values=[ point[2] for point in consensus_data ], transitMarkers=transit_markers, onClick=lambda minimum, maximum: self.zoom_animated(minimum - (maximum - minimum) * 2, maximum + (maximum - minimum) * 2, max_duration=0.5)) 329 self._consensus_graph_area.opacity = 0 330 uianimations.FadeIn(self._consensus_graph_area) 331 self._consensus_graph.Animate(animations.AnimationType.GROW, animations.AnimationDynamics.RANDOM, 1.0) 332 uianimations.FadeTo(self._graph_area, startVal=self._graph_area.opacity, endVal=0.5) 333 334 def get_time_visible_range(self): 335 return self._control_axis.get_visible_range() 336 337 def reset_zoom(self, callback = None): 338 if not self.is_zoom(): 339 invoke_callback(callback) 340 else: 341 self.zoom_animated(self._time_axis.get_min_value(), self._time_axis.get_max_value(), callback=callback) 342 343 def zoom_animated(self, minimum_time, maximum_time, max_duration = 1.0, callback = None): 344 minimum_time = min(max(minimum_time, self._graph_data[0][0]), self._graph_data[-1][0]) 345 maximum_time = min(max(maximum_time, self._graph_data[0][0]), self._graph_data[-1][0]) 346 start_zoom = self.get_time_visible_range() 347 end_zoom = (minimum_time, maximum_time) 348 if start_zoom == end_zoom: 349 invoke_callback(callback) 350 return 351 self._desired_animation_zoom = (minimum_time, maximum_time) 352 self._zoom_animation_callback = callback 353 duration = zoom.get_zoom_animation_duration(start_zoom, end_zoom, max_duration=max_duration) 354 self._is_zoom_animation = True 355 self.state = uiconst.UI_DISABLED 356 self._on_animation() 357 uianimations.MorphVector2(self, '_zoom', self._zoom, end_zoom, duration, callback=self._after_zoom_animation) 358 359 def _after_zoom_animation(self): 360 self._is_zoom_animation = False 361 min_time, max_time = self._desired_animation_zoom[0], self._desired_animation_zoom[1] 362 self._desired_animation_zoom = None 363 self.zoom(min_time, max_time) 364 self.state = uiconst.UI_NORMAL 365 self._on_animation_stopped() 366 invoke_callback(self._zoom_animation_callback) 367 self._zoom_animation_callback = None 368 369 def _point_graph_toggle(self, *args): 370 if self._main_graph: 371 self._is_point_graph = not self._main_graph.get_show_status_of_point_graph() 372 self._main_graph.set_show_status_of_point_graph(self._is_point_graph) 373 self._main_graph.hide_point_graph() if not self._is_point_graph else self._main_graph.show_point_graph() 374 375 def update_data(self, data, new_zoomed_range = None, adjust_zoom = True): 376 super(ExoPlanetsGraph, self).update_data(data, new_zoomed_range, adjust_zoom) 377 if not self._is_mini_map_hidden and not self.is_animation_running(): 378 self._mini_graph.update_data(data) 379 380 def update_animated(self, data, callback = None): 381 382 def update_callback(): 383 self._is_update_animation = False 384 self.update_data(self._original_data) 385 self._on_animation_stopped() 386 invoke_callback(callback) 387 388 self.lock_graph_updates() 389 self._is_update_animation = True 390 self._on_animation() 391 self._original_data = data 392 self._start_animation_data = binning.bin(self.get_graph_data(), self.animation_binning_fidelity) 393 self._end_animation_data = binning.bin(data, self.animation_binning_fidelity) 394 uianimations.MorphScalar(self, '_update_progression', 0, 1, 0.5, callback=update_callback) 395 396 def clean_container(self): 397 if self._tool: 398 self._tooltip.SetParent(None) 399 super(ExoPlanetsGraph, self).clean_container() 400 self._consensus_graph = None 401 self._consensus_graph_area = None 402 self._consensus_time_axis = None 403 self._consensus_vertical_axis = None 404 self._is_result_shown = False 405 self.clear_result_graph() 406 407 def _set_time_axis_dirty(self, *args): 408 self._is_time_axis_dirty = True 409 410 def on_time_axis_changed(self, *args): 411 self.lock_graph_updates() 412 min_value, max_value = self.get_time_visible_range() 413 self.zoom(min_value, max_value) 414 self._is_time_axis_dirty = False 415 416 def hide_mini_map_zoom(self, is_animate = False, duration = 1.0, callback = None): 417 418 def animation_callback(): 419 self._mini_map.state = uiconst.UI_HIDDEN 420 invoke_callback(callback) 421 422 if is_animate: 423 uianimations.FadeOut(self._mini_map, duration=duration, callback=animation_callback) 424 else: 425 animation_callback() 426 427 def show_mini_map_zoom(self, is_animate = False, duration = 1.0, callback = None): 428 429 def animation_callback(): 430 invoke_callback(callback) 431 432 self._mini_map.SetState(uiconst.UI_NORMAL) 433 self._mini_map.pickState = uiconst.TR2_SPS_CHILDREN 434 if is_animate: 435 uianimations.FadeIn(self._mini_map, duration=duration, callback=animation_callback) 436 else: 437 animation_callback() 438 439 def fold_animated(self, center, period): 440 441 def animation_callback(): 442 self._is_fold_animation = False 443 self.state = uiconst.UI_NORMAL 444 self.fold(center, period) 445 self._on_animation_stopped() 446 447 if self._is_folding: 448 animated_center = self._reverse_engineer_center_fix(center, period) 449 else: 450 time_values = [ time for time, flux in self._graph_data ] 451 min_time, max_time = time_values[0], time_values[-1] 452 self._period_length = max_time - min_time 453 self._fold_center = min_time + self._period_length / 2.0 454 animated_center = self._fold_center 455 if (self._fold_center, self._period_length) == (center, period): 456 return 457 self._is_fold_animation = True 458 self._on_animation() 459 self.state = uiconst.UI_DISABLED 460 duration = self.get_fold_animation_time(animated_center) 461 uianimations.MorphVector2(self, '_fold_variables', (self._fold_center, self._period_length), (animated_center, period), duration, callback=animation_callback) 462 463 def get_fold_animation_time(self, fold_center): 464 max_length = (self._time_axis.get_max_value() - self._time_axis.get_min_value()) / 2.0 465 diff_center = math.fabs(fold_center - self._fold_center) 466 return diff_center / max_length * FOLD_ANIMATION_MAX_TIME 467 468 def calibrate_to_folded_mode(self, calibration_center, calibration_period, transit_selection = None, duration = 1.0, callback = None): 469 470 def animation_callback(): 471 self._on_calibration_animation_ended(True, transit_selection, calibration_center, calibration_period, callback) 472 473 if self.is_folding(): 474 invoke_callback(callback) 475 return 476 self._remove_transit_selections_not_in_list([transit_selection]) 477 if transit_selection and transit_selection.get_period_length(): 478 self._calibration_axis = self._transit_selection_graphs[0].category_axis 479 self._calibration_marking_start_points = transit_selection.get_centers() 480 self._calibration_marking_end_points = calibration.get_end_time_values(start_time_values=self._calibration_marking_start_points, center=calibration_center, period=calibration_period, min_time=min(self.get_time_values(self._graph_data)), max_time=max(self.get_time_values(self._graph_data))) 481 self.state = uiconst.UI_DISABLED 482 self._is_calibration_animation = True 483 self._on_animation() 484 self._original_data = self.get_graph_data() 485 self._start_animation_data = binning.bin(self.get_graph_data(), self.animation_binning_fidelity) 486 self._end_animation_data = calibration.get_end_data(self._start_animation_data, calibration_center, calibration_period) 487 uianimations.MorphScalar(self, '_calibration_progression', 0, 1, duration=duration, callback=animation_callback) 488 489 def calibrate_to_unfolded_mode(self, transit_selection = None, duration = 1.0, callback = None): 490 491 def animation_callback(): 492 self._on_calibration_animation_ended(False, transit_selection, callback=callback) 493 494 if not self.is_folding(): 495 invoke_callback(callback) 496 return 497 self.state = uiconst.UI_DISABLED 498 self._is_calibration_animation = True 499 self._on_animation() 500 self._original_data = self.get_graph_data() 501 self._end_animation_data = binning.bin(self.get_graph_data(), self.animation_binning_fidelity) 502 self._start_animation_data = calibration.get_end_data(self._end_animation_data, self._fold_center, self._period_length) 503 self._remove_transit_selections_not_in_list([transit_selection]) 504 if transit_selection and transit_selection.get_period_length(): 505 self._calibration_axis = self._transit_selection_graphs[0].category_axis 506 self._calibration_marking_end_points = transit_selection.get_centers() 507 self._calibration_marking_start_points = calibration.get_end_time_values(start_time_values=self._calibration_marking_end_points, center=transit_selection.get_center(), period=transit_selection.get_period_length(), min_time=min(self.get_time_values(self._graph_data)), max_time=max(self.get_time_values(self._graph_data))) 508 self.unfold() 509 self.update_data(self._start_animation_data) 510 uianimations.MorphScalar(self, '_calibration_progression', 0, 1, duration=duration, callback=animation_callback) 511 512 def _on_calibration_animation_ended(self, is_folding, transit_selection, center = None, period = None, callback = None): 513 if transit_selection: 514 points = self._calibration_marking_start_points if is_folding else self._calibration_marking_end_points 515 self._calibration_axis.set_data_points(points) 516 self._calibration_axis = None 517 self._calibration_marking_start_points = [] 518 self._calibration_marking_end_points = [] 519 self._is_calibration_animation = False 520 self.update_data(self._original_data) 521 if is_folding: 522 self.fold(center, period) 523 self.state = uiconst.UI_NORMAL 524 self._on_animation_stopped() 525 invoke_callback(callback) 526 527 def _on_animation(self): 528 self._hide_graph_labels() 529 self.on_graph_movement() 530 if self._is_result_shown: 531 self.clear_result_graph() 532 533 def _on_animation_stopped(self): 534 if not self.is_animation_running(): 535 self._show_graph_labels() 536 self.on_graph_movement_stopped() 537 if self._is_result_shown: 538 self._show_result_graph() 539 540 def _hide_graph_labels(self): 541 uianimations.FadeOut(self._flux_labels, duration=0.1) 542 uianimations.FadeOut(self._time_labels, duration=0.1) 543 544 def _show_graph_labels(self): 545 uianimations.FadeIn(self._flux_labels, duration=0.1) 546 uianimations.FadeIn(self._time_labels, duration=0.1) 547 548 def _reverse_engineer_center_fix(self, next_center, period_length): 549 min_visible, max_visible = self._time_axis.get_visible_range() 550 time_values = self.get_time_values(self._graph_data) 551 min_time, max_time = min(time_values), max(time_values) 552 if next_center < min_visible: 553 while next_center < max_time: 554 next_center += period_length 555 556 elif next_center > max_visible: 557 while next_center > min_time: 558 next_center -= period_length 559 560 return next_center 561 562 def set_fux_display_state(self, state): 563 self._flux_labels.Clear() 564 if self._flux_axis: 565 if state == FluxDisplayState.RELATIVE: 566 flux_values = self.get_flux_values(self._graph_data) 567 self._flux_axis.set_relative_flux_active(flux_values) 568 else: 569 self._flux_axis.set_actual_flux_active() 570 571 def display_transit_markers(self, transit_selections, mini_map_transit_markers = None): 572 super(ExoPlanetsGraph, self).display_transit_markers(transit_selections) 573 if not mini_map_transit_markers: 574 mini_map_transit_markers = [] 575 if self._mini_graph: 576 self._mini_graph.display_transit_markers(mini_map_transit_markers) 577 578 def is_animation_running(self): 579 is_other_animation_running = self._is_calibration_animation or self._is_fold_animation or self._is_update_animation or self._is_zoom_animation 580 return is_other_animation_running 581 582 def unlock_graph_updates(self): 583 super(ExoPlanetsGraph, self).unlock_graph_updates() 584 if self._mini_graph: 585 self._mini_graph.unlock_graph_updates() 586 587 def zoom(self, *args, **kwargs): 588 if self._desired_animation_zoom and self._zoom_replicate_count > 5: 589 self.StopAnimations() 590 invoke_callback(self._after_zoom_animation) 591 return 592 super(ExoPlanetsGraph, self).zoom(*args, **kwargs) 593 594 @property 595 def _calibration_progression(self): 596 return self._m_calibration_progression 597 598 @_calibration_progression.setter 599 def _calibration_progression(self, value): 600 self.lock_graph_updates() 601 self._m_calibration_progression = value 602 data = linearly_interpolate_data(self._start_animation_data, self._end_animation_data, value) 603 self.update_data(data) 604 if self._calibration_marking_start_points: 605 marking = [ (1 - value) * start_time + value * end_time for start_time, end_time in izip(self._calibration_marking_start_points, self._calibration_marking_end_points) ] 606 self._calibration_axis.set_data_points(marking) 607 608 @property 609 def _zoom(self): 610 return self._zoomed_range 611 612 @_zoom.setter 613 def _zoom(self, zoom_range): 614 self.zoom(*zoom_range) 615 616 @property 617 def _fold_variables(self): 618 return (self._fold_center, self._period_length) 619 620 @_fold_variables.setter 621 def _fold_variables(self, _center_and_period): 622 self.fold(*_center_and_period) 623 624 @property 625 def _update_progression(self): 626 return self._m_update_progression 627 628 @_update_progression.setter 629 def _update_progression(self, t): 630 self._m_update_progression = t 631 data = linearly_interpolate_data(self._start_animation_data, self._end_animation_data, t) 632 self.update_data(data) 633 634 635 class FluxDisplayState(object): 636 RELATIVE = 0 637 ACTUAL = 1 638 639 640 def invoke_callback(callback, *args, **kwargs): 641 if callable(callback): 642 callback(*args, **kwargs) 643 644 645 def linearly_interpolate_data(start_data, end_data, t): 646 return [ geo2.Lerp(start, end, t) for start, end in izip(start_data, end_data) ] 647 648 649 def consensus_tick_filter(tick): 650 return tick <= 1.0 651 652 653 def consensus_label_format(tick): 654 return '%s%%' % int(tick * 100)