def chooseVariables(self): """Opens a dialog asking user to select columns from a data File that has been selected. THese are then returned as a string suitable for Y cols input""" columns = self.physics.variables.keys() columns.sort() values = zip(range(0, len(columns)), columns) checklist_group = traitsui.Group( '10', # insert vertical space traitsui.Label('Select the additional variables you wish to log'), traitsui.UItem('columns', style='custom', editor=traitsui.CheckListEditor(values=values, cols=6)), traitsui.UItem('selectAllButton')) traits_view = traitsui.View(checklist_group, title='CheckListEditor', buttons=['OK'], resizable=True, kind='livemodal') col = ColumnEditor(numberOfColumns=len(columns)) try: col.columns = [ columns.index(varName) for varName in self.xmlLogVariables ] except Exception as e: logger.error( "couldn't selected correct variable names. Returning empty selection" ) logger.error("%s " % e.message) col.columns = [] col.edit_traits(view=traits_view) logger.debug("value of columns selected = %s ", col.columns) logger.debug("value of columns selected = %s ", [columns[i] for i in col.columns]) return [columns[i] for i in col.columns]
class CameraUI(traits.HasTraits): """Camera settings defines basic camera settings """ camera_control = traits.Instance(Camera, transient = True) cameras = traits.List([_NO_CAMERAS],transient = True) camera = traits.Any(value = _NO_CAMERAS, desc = 'camera serial number', editor = ui.EnumEditor(name = 'cameras')) search = traits.Button(desc = 'camera search action') _is_initialized= traits.Bool(False, transient = True) play = traits.Button(desc = 'display preview action') stop = traits.Button(desc = 'close preview action') on_off = traits.Button('On/Off', desc = 'initiate/Uninitiate camera action') gain = create_range_feature('gain',desc = 'camera gain',transient = True) shutter = create_range_feature('shutter', desc = 'camera exposure time',transient = True) format = create_mapped_feature('format',_FORMAT, desc = 'image format',transient = True) roi = traits.Instance(ROI,transient = True) im_shape = traits.Property(depends_on = 'format.value,roi.values') im_dtype = traits.Property(depends_on = 'format.value') capture = traits.Button() save_button = traits.Button('Save as...') message = traits.Str(transient = True) view = ui.View(ui.Group(ui.HGroup(ui.Item('camera', springy = True), ui.Item('search', show_label = False, springy = True), ui.Item('on_off', show_label = False, springy = True), ui.Item('play', show_label = False, enabled_when = 'is_initialized', springy = True), ui.Item('stop', show_label = False, enabled_when = 'is_initialized', springy = True), ), ui.Group( ui.Item('gain', style = 'custom'), ui.Item('shutter', style = 'custom'), ui.Item('format', style = 'custom'), ui.Item('roi', style = 'custom'), ui.HGroup(ui.Item('capture',show_label = False), ui.Item('save_button',show_label = False)), enabled_when = 'is_initialized', ), ), resizable = True, statusbar = [ ui.StatusItem( name = 'message')], buttons = ['OK']) #default initialization def __init__(self, **kw): super(CameraUI, self).__init__(**kw) self.search_cameras() def _camera_control_default(self): return Camera() def _roi_default(self): return ROI() #@display_cls_error def _get_im_shape(self): top, left, width, height = self.roi.values shape = (height, width) try: colors = _COLORS[self.format.value] if colors > 1: shape += (colors,) except KeyError: raise NotImplementedError('Unsupported format') return shape #@display_cls_error def _get_im_dtype(self): try: return _DTYPE[self.format.value] except KeyError: raise NotImplementedError('Unsupported format') def _search_fired(self): self.search_cameras() #@display_cls_error def search_cameras(self): """ Finds cameras if any and selects first from list """ try: cameras = get_number_cameras() except Exception as e: cameras = [] raise e finally: if len(cameras) == 0: cameras = [_NO_CAMERAS] self.cameras = cameras self.camera = cameras[0] #@display_cls_error def _camera_changed(self): if self._is_initialized: self._is_initialized= False self.camera_control.close() self.message = 'Camera uninitialized' #@display_cls_error def init_camera(self): self._is_initialized= False if self.camera != _NO_CAMERAS: self.camera_control.init(self.camera) self.init_features() self._is_initialized= True self.message = 'Camera initialized' #@display_cls_error def _on_off_fired(self): if self._is_initialized: self._is_initialized= False self.camera_control.close() self.message = 'Camera uninitialized' else: self.init_camera() #@display_cls_error def init_features(self): """ Initializes all features to values given by the camera """ features = self.camera_control.get_camera_features() self._init_single_valued_features(features) self._init_roi(features) #@display_cls_error def _init_single_valued_features(self, features): """ Initializes all single valued features to camera values """ for name, id in list(_SINGLE_VALUED_FEATURES.items()): feature = getattr(self, name) feature.low, feature.high = features[id]['params'][0] feature.value = self.camera_control.get_feature(id)[0] #@display_cls_error def _init_roi(self, features): for i,name in enumerate(('top','left','width','height')): feature = getattr(self.roi, name) low, high = features[FEATURE_ROI]['params'][i] value = self.camera_control.get_feature(FEATURE_ROI)[i] try: feature.value = value finally: feature.low, feature.high = low, high @traits.on_trait_change('format.value') def _on_format_change(self, object, name, value): if self._is_initialized: self.camera_control.set_preview_state(STOP_PREVIEW) self.camera_control.set_stream_state(STOP_STREAM) self.set_feature(FEATURE_PIXEL_FORMAT, [value]) @traits.on_trait_change('gain.value,shutter.value') def _single_valued_feature_changed(self, object, name, value): if self._is_initialized: self.set_feature(object.id, [value]) #@display_cls_error def set_feature(self, id, values, flags = 2): self.camera_control.set_feature(id, values, flags = flags) @traits.on_trait_change('roi.values') def a_roi_feature_changed(self, object, name, value): if self._is_initialized: self.set_feature(FEATURE_ROI, value) try: self._is_initialized= False self.init_features() finally: self._is_initialized= True #@display_cls_error def _play_fired(self): self.camera_control.set_preview_state(STOP_PREVIEW) self.camera_control.set_stream_state(STOP_STREAM) self.camera_control.set_stream_state(START_STREAM) self.camera_control.set_preview_state(START_PREVIEW) #@display_cls_error def _stop_fired(self): self.camera_control.set_preview_state(STOP_PREVIEW) self.camera_control.set_stream_state(STOP_STREAM) self.error = '' #@display_cls_error def _format_changed(self, value): self.camera_control.set_preview_state(STOP_PREVIEW) self.camera_control.set_stream_state(STOP_STREAM) self.camera_control.set_feature(FEATURE_PIXEL_FORMAT, [value],2) #@display_cls_error def _capture_fired(self): self.camera_control.set_stream_state(STOP_STREAM) self.camera_control.set_stream_state(START_STREAM) im = self.capture_image() plt.imshow(im) plt.show() def capture_image(self): im = numpy.empty(shape = self.im_shape, dtype = self.im_dtype) self.camera_control.get_next_frame(im) return im.newbyteorder('>') def save_image(self, fname): """Captures image and saves to format guessed from filename extension""" im = self.capture_image() base, ext = os.path.splitext(fname) if ext == '.npy': numpy.save(fname, im) else: im = toimage(im) im.save(fname) def _save_button_fired(self): f = pyface.FileDialog(action = 'save as') #wildcard = self.filter) if f.open() == pyface.OK: self.save_image(f.path) def capture_HDR(self): pass def __del__(self): try: self.camera_control.set_preview_state(STOP_PREVIEW) self.camera_control.set_stream_state(STOP_STREAM) except: pass
class DataAxis(t.HasTraits): name = t.Str() units = t.Str() scale = t.Float() offset = t.Float() size = t.Int() index_in_array = t.Int() low_value = t.Float() high_value = t.Float() value = t.Range('low_value', 'high_value') low_index = t.Int(0) high_index = t.Int() slice = t.Instance(slice) slice_bool = t.Bool(False) index = t.Range('low_index', 'high_index') axis = t.Array() def __init__(self, size, index_in_array, name='', scale=1., offset=0., units='undefined', slice_bool=False): super(DataAxis, self).__init__() self.name = name self.units = units self.scale = scale self.offset = offset self.size = size self.high_index = self.size - 1 self.low_index = 0 self.index = 0 self.index_in_array = index_in_array self.update_axis() self.on_trait_change(self.update_axis, ['scale', 'offset', 'size']) self.on_trait_change(self.update_value, 'index') self.on_trait_change(self.set_index_from_value, 'value') self.on_trait_change(self._update_slice, 'slice_bool') self.on_trait_change(self.update_index_bounds, 'size') self.slice_bool = slice_bool def __repr__(self): if self.name is not None: return self.name + ' index: ' + str(self.index_in_array) def update_index_bounds(self): self.high_index = self.size - 1 def update_axis(self): self.axis = generate_axis(self.offset, self.scale, self.size) self.low_value, self.high_value = self.axis.min(), self.axis.max() # self.update_value() def _update_slice(self, value): if value is True: self.slice = slice(None) else: self.slice = None def get_axis_dictionary(self): adict = { 'name': self.name, 'scale': self.scale, 'offset': self.offset, 'size': self.size, 'units': self.units, 'index_in_array': self.index_in_array, 'slice_bool': self.slice_bool } return adict def update_value(self): self.value = self.axis[self.index] def value2index(self, value): """Return the closest index to the given value if between the limits, otherwise it will return either the upper or lower limits Parameters ---------- value : float Returns ------- int """ if value is None: return None else: index = int(round((value - self.offset) / \ self.scale)) if self.size > index >= 0: return index elif index < 0: messages.warning("The given value is below the axis limits") return 0 else: messages.warning("The given value is above the axis limits") return int(self.size - 1) def index2value(self, index): return self.axis[index] def set_index_from_value(self, value): self.index = self.value2index(value) # If the value is above the limits we must correct the value self.value = self.index2value(self.index) def calibrate(self, value_tuple, index_tuple, modify_calibration=True): scale = (value_tuple[1] - value_tuple[0]) /\ (index_tuple[1] - index_tuple[0]) offset = value_tuple[0] - scale * index_tuple[0] if modify_calibration is True: self.offset = offset self.scale = scale else: return offset, scale traits_view = \ tui.View( tui.Group( tui.Group( tui.Item(name = 'name'), tui.Item(name = 'size', style = 'readonly'), tui.Item(name = 'index_in_array', style = 'readonly'), tui.Item(name = 'index'), tui.Item(name = 'value', style = 'readonly'), tui.Item(name = 'units'), tui.Item(name = 'slice_bool', label = 'slice'), show_border = True,), tui.Group( tui.Item(name = 'scale'), tui.Item(name = 'offset'), label = 'Calibration', show_border = True,), label = "Data Axis properties", show_border = True,), )
def make_view(self): """Make a traits view (popup window) for this station.""" pax_table_editor = ui.TableEditor( # Only the passenger data relevant when looking at a station. columns = [ui_tc.ObjectColumn(name='label', label='Name'), ui_tc.ObjectColumn(name='_start_time'), ui_tc.ObjectColumn(name='dest_station', label='Destination'), ui_tc.ObjectColumn(name='wait_time', label='Waiting (sec)', format="%.2f"), ui_tc.ObjectColumn(name='will_share', label='Will Share'), ui_tc.ObjectColumn(name='load_delay', label='Time to Board (sec)')], # more... deletable = True, # sort_model = True, auto_size = True, orientation = 'vertical', show_toolbar = True, reorderable = True, # Does this affect the actual boarding order (think no...) rows = 5, row_factory = events.Passenger) groups = ui.VGroup( ui.Group( ui.Label('Waiting Passengers'), ui.Item(name='passengers', show_label = False, editor=pax_table_editor ), show_border = True), # ui.Group( # ui.Label('Load Platform'), # ui.Item(name='load_platform', # show_label = False, # editor=ui.ListEditor(style='custom', # rows=len(self.load_platform)), # style='readonly'), # show_border = True # ), ui.Group( ui.Label('Queue'), ui.Item(name='queue', show_label=False, editor=ui.ListEditor(editor=ui.TextEditor()), style='readonly'), show_border = True # ), # ui.Group( # ui.Label('Unload Platform'), # ui.Item(name='unload_platform', # show_label = False, # editor=ui.ListEditor(style='custom', # rows=len(self.unload_platform)), # style='readonly', # ), # show_border = True, )) view = ui.View(groups, title=self.label, # scrollable = True, resizable = True, height = 700, width = 470 ) return view
class EgertonPanel(t.HasTraits): define_background_window = t.Bool(False) bg_window_size_variation = t.Button() background_substracted_spectrum_name = t.Str('signal') extract_background = t.Button() define_signal_window = t.Bool(False) signal_window_size_variation = t.Button() signal_name = t.Str('signal') extract_signal = t.Button() view = tu.View(tu.Group( tu.Group('define_background_window', tu.Item('bg_window_size_variation', label = 'window size effect', show_label=False), tu.Item('background_substracted_spectrum_name'), tu.Item('extract_background', show_label=False), ), tu.Group('define_signal_window', tu.Item('signal_window_size_variation', label = 'window size effect', show_label=False), tu.Item('signal_name', show_label=True), tu.Item('extract_signal', show_label=False)),)) def __init__(self, SI): self.SI = SI # Background self.bg_span_selector = None self.pl = components.PowerLaw() self.bg_line = None self.bg_cube = None # Signal self.signal_span_selector = None self.signal_line = None self.signal_map = None self.map_ax = None def store_current_spectrum_bg_parameters(self, *args, **kwards): if self.define_background_window is False or \ self.bg_span_selector.range is None: return pars = utils.two_area_powerlaw_estimation( self.SI, *self.bg_span_selector.range,only_current_spectrum = True) self.pl.r.value = pars['r'] self.pl.A.value = pars['A'] if self.define_signal_window is True and \ self.signal_span_selector.range is not None: self.plot_signal_map() def _define_background_window_changed(self, old, new): if new is True: self.bg_span_selector = \ drawing.widgets.ModifiableSpanSelector( self.SI.hse.spectrum_plot.left_ax, onselect = self.store_current_spectrum_bg_parameters, onmove_callback = self.plot_bg_removed_spectrum) elif self.bg_span_selector is not None: if self.bg_line is not None: self.bg_span_selector.ax.lines.remove(self.bg_line) self.bg_line = None if self.signal_line is not None: self.bg_span_selector.ax.lines.remove(self.signal_line) self.signal_line = None self.bg_span_selector.turn_off() self.bg_span_selector = None def _bg_window_size_variation_fired(self): if self.define_background_window is False: return left = self.bg_span_selector.rect.get_x() right = left + self.bg_span_selector.rect.get_width() energy_window_dependency(self.SI, left, right, min_width = 10) def _extract_background_fired(self): if self.pl is None: return signal = self.SI() - self.pl.function(self.SI.energy_axis) i = self.SI.energy2index(self.bg_span_selector.range[1]) signal[:i] = 0. s = Spectrum({'calibration' : {'data_cube' : signal}}) s.get_calibration_from(self.SI) interactive_ns[self.background_substracted_spectrum_name] = s def _define_signal_window_changed(self, old, new): if new is True: self.signal_span_selector = \ drawing.widgets.ModifiableSpanSelector( self.SI.hse.spectrum_plot.left_ax, onselect = self.store_current_spectrum_bg_parameters, onmove_callback = self.plot_signal_map) self.signal_span_selector.rect.set_color('blue') elif self.signal_span_selector is not None: self.signal_span_selector.turn_off() self.signal_span_selector = None def plot_bg_removed_spectrum(self, *args, **kwards): if self.bg_span_selector.range is None: return self.store_current_spectrum_bg_parameters() ileft = self.SI.energy2index(self.bg_span_selector.range[0]) iright = self.SI.energy2index(self.bg_span_selector.range[1]) ea = self.SI.energy_axis[ileft:] if self.bg_line is not None: self.bg_span_selector.ax.lines.remove(self.bg_line) self.bg_span_selector.ax.lines.remove(self.signal_line) self.bg_line, = self.SI.hse.spectrum_plot.left_ax.plot( ea, self.pl.function(ea), color = 'black') self.signal_line, = self.SI.hse.spectrum_plot.left_ax.plot( self.SI.energy_axis[iright:], self.SI()[iright:] - self.pl.function(self.SI.energy_axis[iright:]), color = 'black') self.SI.hse.spectrum_plot.left_ax.figure.canvas.draw() def plot_signal_map(self, *args, **kwargs): if self.define_signal_window is True and \ self.signal_span_selector.range is not None: ileft = self.SI.energy2index(self.signal_span_selector.range[0]) iright = self.SI.energy2index(self.signal_span_selector.range[1]) signal_sp = self.SI.data_cube[ileft:iright,...].squeeze().copy() if self.define_background_window is True: pars = utils.two_area_powerlaw_estimation( self.SI, *self.bg_span_selector.range, only_current_spectrum = False) x = self.SI.energy_axis[ileft:iright, np.newaxis, np.newaxis] A = pars['A'][np.newaxis,...] r = pars['r'][np.newaxis,...] self.bg_sp = (A*x**(-r)).squeeze() signal_sp -= self.bg_sp self.signal_map = signal_sp.sum(0) if self.map_ax is None: f = plt.figure() self.map_ax = f.add_subplot(111) if len(self.signal_map.squeeze().shape) == 2: self.map = self.map_ax.imshow(self.signal_map.T, interpolation = 'nearest') else: self.map, = self.map_ax.plot(self.signal_map.squeeze()) if len(self.signal_map.squeeze().shape) == 2: self.map.set_data(self.signal_map.T) self.map.autoscale() else: self.map.set_ydata(self.signal_map.squeeze()) self.map_ax.figure.canvas.draw() def _extract_signal_fired(self): if self.signal_map is None: return if len(self.signal_map.squeeze().shape) == 2: s = Image( {'calibration' : {'data_cube' : self.signal_map.squeeze()}}) s.xscale = self.SI.xscale s.yscale = self.SI.yscale s.xunits = self.SI.xunits s.yunits = self.SI.yunits interactive_ns[self.signal_name] = s else: s = Spectrum( {'calibration' : {'data_cube' : self.signal_map.squeeze()}}) s.energyscale = self.SI.xscale s.energyunits = self.SI.xunits interactive_ns[self.signal_name] = s
class StationReport(Report): s_list = traits.List traits_view = ui.View( ui.Group( ui.Item('s_list', editor=ui.TabularEditor( adapter=StationTabularAdapater(), operations = [], images = [], editable=False, column_clicked='handler.column_clicked'), show_label=False) ), handler=SortHandler(), kind='live' ) def __init__(self): super(StationReport, self).__init__(title='Stations') self._header = ["id", "Label", "Platforms", "Berths", "Unload", "Load", "Load|Unload", "Queue", "Current Pax", "Pax Created", "Pax Arrived", "Pax Departed", "Min Pax Wait", "Mean Pax Wait", "Max Pax Wait", "Vehicles Arrived", "Min Vehicle Dwell", "Mean Vehicle Dwell", "Max Vehicle Dwell"] # TODO: Berth specific stats? self._lines = [] def update(self): if len(self.s_list) != len(common.stations): self.s_list = common.stations.values() self.s_list.sort() lines = [] for s in self.s_list: assert isinstance(s, Station) berths, unload, load, unload_load, queue = 0, 0, 0, 0, 0 for platform in s.platforms: for berth in platform.berths: berths += 1 if berth.unloading and berth.loading: unload_load += 1 elif berth.unloading: unload += 1 elif berth.loading: load += 1 else: # no loading or unloading capability queue += 1 pax_wait_times = s.all_pax_wait_times() if pax_wait_times: min_pax_wait = sec_to_hms(min(pax_wait_times)) mean_pax_wait = sec_to_hms(sum(pax_wait_times)/len(pax_wait_times)) max_pax_wait = sec_to_hms(max(pax_wait_times)) else: min_pax_wait = "N/A" mean_pax_wait = "N/A" max_pax_wait = "N/A" lines.append(["%d" % s.ID, s.label, "%d" % len(s.platforms), "%d" % berths, "%d" % unload, "%d" % load, "%d" % unload_load, "%d" % queue, "%d" % len(s._passengers), "%d" % sum(1 for pax in s._all_passengers if pax.src_station is s), "%d" % s._pax_arrivals_count, "%d" % s._pax_departures_count, min_pax_wait, mean_pax_wait, max_pax_wait, "inc", # TODO: Vehicle-related stats "inc", "inc", "inc"]) self._lines = lines def __str__(self): line_strings = [self.title, self.FIELD_DELIMITER.join(self._header)] for line in self._lines: line_str = self.FIELD_DELIMITER.join(line) line_strings.append(line_str) return self.LINE_DELIMETER.join(line_strings)
class VehicleReport(Report): v_list = traits.List traits_view = ui.View( ui.Group( ui.Item('v_list', editor=ui.TabularEditor( adapter=VehicleTabularAdapater(), operations = [], images = [], editable=False, column_clicked='handler.column_clicked'), show_label=False) ), handler=SortHandler(), kind='live' ) def __init__(self): super(VehicleReport, self).__init__(title='Vehicles') self._units_notice = "All values reported in units of meters and seconds." self._header = ["id", "Label", "LocId", "Position", "Velocity", "Accel", "TotalPassengers", "MaxPassengers", "TimeWeightedAvePax", "DistWeightedAvePax", "DistTravelled", "EmptyDist", "PassengerMeters", "MaxVelocity", "MinVelocity", "MaxAccel", "MinAccel", "MaxJerk", "MinJerk", ] self._lines = [] def update(self): # Check if the locally cached vehicle list has gotten stale. if len(self.v_list) != len(common.vehicles): self.v_list = common.vehicles.values() self.v_list.sort() lines = [] for v in self.v_list: assert isinstance(v, BaseVehicle) v.update_stats() extrema_velocities, extrema_times = v._spline.get_extrema_velocities() max_vel = max(extrema_velocities) min_vel = min(extrema_velocities) max_jerk = max(v._spline.j) min_jerk = min(v._spline.j) lines.append([str(v.ID), v.label, str(v.loc.ID), "%.3f" % v.pos, "%.3f" % v.vel, "%.3f" % v.accel, str(v.total_pax), str(v.max_pax), "%.2f" % v.time_ave_pax, "%.2f" % v.dist_ave_pax, "%d" % v.dist_travelled, "%d" % v.empty_dist, "%d" % v.pax_dist, "%.3f" % max_vel, "%.3f" % min_vel, "%.3f" % v._spline.get_max_acceleration(), "%.3f" % v._spline.get_min_acceleration(), "%.3f" % max_jerk, "%.3f" % min_jerk ]) self._lines = lines def __str__(self): line_strings = [self.title, self._units_notice, self.FIELD_DELIMITER.join(self._header)] for line in self._lines: line_str = self.FIELD_DELIMITER.join(line) line_strings.append(line_str) return self.LINE_DELIMETER.join(line_strings)
class PaxReport(Report): """List of details for all passengers in a gridview""" passengers = traits.List traits_view = ui.View( ui.Group( ui.Item('passengers', editor=ui.TabularEditor( adapter=PassengerTabularAdapter(), operations = [], images = [], editable=False, column_clicked='handler.column_clicked'), show_label=False) ), handler=SortHandler(), kind='live' ) def __init__(self): super(PaxReport, self).__init__(title="Passengers") self._header = ["id", "CreationTime", "SrcStatId", "DestStatId", "CurrentLocId", "CurrentLocType", "TimeWaiting", "TimeWalking", "TimeRiding", "TotalTime", "Success", "Mass", "WillShare", "UnloadDelay", "LoadDelay", "SrcStationLabel", "DestStationLabel", "CurrLocLabel"] self._lines = [] def update(self): # Check if the locally cached vehicle list has gotten stale. if len(self.passengers) != len(common.passengers): self.passengers = common.passengers.values() self.passengers.sort() lines = [] for pax in self.passengers: assert isinstance(pax, Passenger) lines.append([str(pax.ID), "%.3f" % pax.time, str(pax.src_station.ID), str(pax.dest_station.ID), str(pax.loc.ID), self.type_str(pax.loc), sec_to_hms(pax.wait_time), sec_to_hms(pax.walk_time), sec_to_hms(pax.ride_time), sec_to_hms(pax.total_time), str(pax.trip_success), str(pax.mass), str(pax.will_share), str(pax.unload_delay), str(pax.load_delay), pax.src_station.label, pax.dest_station.label, pax.loc.label]) self._lines = lines def __str__(self): line_strings = [self.title, self.FIELD_DELIMITER.join(self._header)] for line in self._lines: line_str = self.FIELD_DELIMITER.join(line) line_strings.append(line_str) return self.LINE_DELIMETER.join(line_strings)
class Station(traits.HasTraits): platforms = traits.List(traits.Instance(Platform)) track_segments = traits.Set(traits.Instance(TrackSegment)) # Passengers waiting at the station. _passengers = traits.List(traits.Instance(Passenger)) traits_view = ui.View( ui.VGroup( ui.Group( ui.Label('Waiting Passengers'), ## ui.Item(name='_passengers', ## show_label = False, ## editor=Passenger.table_editor ## ), show_border=True)), title='Station', # was: self.label # scrollable = True, resizable=True, height=700, width=470, handler=NoWritebackOnCloseHandler()) table_editor = ui.TableEditor( columns=[ ui_tc.ObjectColumn(name='ID', label='ID', tooltip='Station ID'), ui_tc.ObjectColumn(name='label', label='Label', tooltip='Non-unique identifier'), ui_tc.ExpressionColumn( label='Current Pax', format='%d', expression='len(object._passengers)', tooltip='Number of passengers currently at station.') # TODO: The rest... ], deletable=False, editable=False, sortable=True, sort_model=False, auto_size=True, orientation='vertical', show_toolbar=True, reorderable=False, rows=15, row_factory=traits.This) def __init__(self, ID, label, track_segments, storage_entrance_delay, storage_exit_delay, storage_dict): traits.HasTraits.__init__(self) self.ID = ID self.label = label self.platforms = [] self.track_segments = track_segments self.storage_entrance_delay = storage_entrance_delay self.storage_exit_delay = storage_exit_delay # Keyed by the VehicleModel name (string) with FIFO queues as the values. self._storage_dict = storage_dict self._pax_arrivals_count = 0 self._pax_departures_count = 0 self._pax_times = [(Sim.now(), len(self._passengers)) ] # elements are (time, num_pax) self._all_passengers = [] def __str__(self): if self.label: return self.label else: return str(self.ID) def __hash__(self): return hash(self.ID) def __eq__(self, other): if not isinstance(other, Station): return False else: return self.ID == other.ID def __ne__(self, other): if not isinstance(other, Station): return True else: return self.ID != other.ID def __cmp__(self, other): return cmp(self.ID, other.ID) def startup(self): """Activates all the berths""" for platform in self.platforms: for berth in platform.berths: Sim.activate(berth, berth.run()) def add_passenger(self, pax): """Add a passenger to this station.""" assert pax not in self._passengers self._passengers.append(pax) self._all_passengers.append(pax) self._pax_times.append((Sim.now(), len(self._passengers))) def remove_passenger(self, pax): """Remove a passenger from this station, such as when they load into a vehicle, or when they storm off in disgust...""" self._passengers.remove(pax) self._pax_times.append((Sim.now(), len(self._passengers))) def get_num_passengers(self): return len(self._passengers) num_passengers = property(get_num_passengers) def get_stored_vehicle_count(self, vehicle_model): sv_count = 0 store = self._storage_dict[vehicle_model] sv_count += store.get_stored_vehicle_count() return sv_count def all_pax_wait_times(self): """Returns a list of wait times for all passengers, not just the current ones.""" times = [] for pax in self._all_passengers: for start, end, loc in pax._wait_times: if loc is self: if end is None: times.append(Sim.now() - start) else: times.append(end - start) return times def curr_pax_wait_times(self): """Returns a list of wait times for passengers currently waiting in the station.""" times = [] for pax in self._passengers: for start, end, loc in pax._wait_times: if loc is self: if end is None: times.append(Sim.now() - start) else: times.append(end - start) return times def get_min_all_pax_wait(self): try: return min(self.all_pax_wait_times()) except ValueError: # Empty sequence assert len(self.all_pax_wait_times()) == 0 return 0 min_all_pax_wait = property(get_min_all_pax_wait) def get_mean_all_pax_wait(self): try: wait_times = self.all_pax_wait_times() return sum(wait_times) / len(wait_times) except ZeroDivisionError: return 0 mean_all_pax_wait = property(get_mean_all_pax_wait) def get_max_all_pax_wait(self): try: return max(self.all_pax_wait_times()) except ValueError: # Empty sequence return 0 max_all_pax_wait = property(get_max_all_pax_wait) def get_min_curr_pax_wait(self): try: return min(self.curr_pax_wait_times()) except ValueError: # Empty sequence assert len(self.curr_pax_wait_times()) == 0 return 0 min_curr_pax_wait = property(get_min_curr_pax_wait) def get_mean_curr_pax_wait(self): try: wait_times = self.curr_pax_wait_times() return sum(wait_times) / len(wait_times) except ZeroDivisionError: return 0 mean_curr_pax_wait = property(get_mean_curr_pax_wait) def get_max_curr_pax_wait(self): try: return max(self.curr_pax_wait_times()) except ValueError: # Empty sequence return 0 max_curr_pax_wait = property(get_max_curr_pax_wait)