class ODMR(ManagedJob, GetSetItemsMixin): """Provides ODMR measurements.""" # starting and stopping keep_data = Bool( False) # helper variable to decide whether to keep existing data resubmit_button = Button( label='resubmit', desc= 'Submits the measurement to the job manager. Tries to keep previously acquired data. Behaves like a normal submit if sequence or time bins have changed since previous run.' ) # measurement parameters power = Range(low=-100., high=25., value=-20, desc='Power [dBm]', label='Power [dBm]', mode='text', auto_set=False, enter_set=True) frequency_begin = Range(low=1, high=20e9, value=2.85e9, desc='Start Frequency [Hz]', label='Begin [Hz]', editor=TextEditor(auto_set=False, enter_set=True, evaluate=float, format_str='%e')) frequency_end = Range(low=1, high=20e9, value=2.88e9, desc='Stop Frequency [Hz]', label='End [Hz]', editor=TextEditor(auto_set=False, enter_set=True, evaluate=float, format_str='%e')) frequency_delta = Range(low=1e-3, high=20e9, value=1e6, desc='frequency step [Hz]', label='Delta [Hz]', editor=TextEditor(auto_set=False, enter_set=True, evaluate=float, format_str='%e')) t_pi = Range(low=1., high=100000., value=1000., desc='length of pi pulse [ns]', label='pi [ns]', mode='text', auto_set=False, enter_set=True) laser = Range(low=1., high=10000., value=300., desc='laser [ns]', label='laser [ns]', mode='text', auto_set=False, enter_set=True) wait = Range(low=1., high=10000., value=1000., desc='wait [ns]', label='wait [ns]', mode='text', auto_set=False, enter_set=True) pulsed = Bool(False, label='pulsed') seconds_per_point = Range(low=20e-3, high=1, value=20e-3, desc='Seconds per point', label='Seconds per point', mode='text', auto_set=False, enter_set=True) stop_time = Range( low=1., value=np.inf, desc='Time after which the experiment stops by itself [s]', label='Stop time [s]', mode='text', auto_set=False, enter_set=True) n_lines = Range(low=1, high=10000, value=50, desc='Number of lines in Matrix', label='Matrix lines', mode='text', auto_set=False, enter_set=True) # control data fitting perform_fit = Bool(False, label='perform fit') number_of_resonances = Trait( 'auto', String('auto', auto_set=False, enter_set=True), Int(10000., desc='Number of Lorentzians used in fit', label='N', auto_set=False, enter_set=True)) threshold = Range( low=-99, high=99., value=-50., desc= 'Threshold for detection of resonances [%]. The sign of the threshold specifies whether the resonances are negative or positive.', label='threshold [%]', mode='text', auto_set=False, enter_set=True) # fit result fit_parameters = Array(value=np.array((np.nan, np.nan, np.nan, np.nan))) fit_frequencies = Array(value=np.array((np.nan, )), label='frequency [Hz]') fit_line_width = Array(value=np.array((np.nan, )), label='line_width [Hz]') fit_contrast = Array(value=np.array((np.nan, )), label='contrast [%]') # measurement data frequency = Array() counts = Array() counts_matrix = Array() run_time = Float(value=0.0, desc='Run time [s]', label='Run time [s]') # plotting line_label = Instance(PlotLabel) line_data = Instance(ArrayPlotData) matrix_data = Instance(ArrayPlotData) line_plot = Instance(Plot, editor=ComponentEditor()) matrix_plot = Instance(Plot, editor=ComponentEditor()) def __init__(self): super(ODMR, self).__init__() self._create_line_plot() self._create_matrix_plot() self.on_trait_change(self._update_line_data_index, 'frequency', dispatch='ui') self.on_trait_change(self._update_line_data_value, 'counts', dispatch='ui') self.on_trait_change(self._update_line_data_fit, 'fit_parameters', dispatch='ui') self.on_trait_change(self._update_matrix_data_value, 'counts_matrix', dispatch='ui') self.on_trait_change(self._update_matrix_data_index, 'n_lines,frequency', dispatch='ui') self.on_trait_change( self._update_fit, 'counts,perform_fit,number_of_resonances,threshold', dispatch='ui') def _counts_matrix_default(self): return np.zeros((self.n_lines, len(self.frequency))) def _frequency_default(self): return np.arange(self.frequency_begin, self.frequency_end + self.frequency_delta, self.frequency_delta) def _counts_default(self): return np.zeros(self.frequency.shape) # data acquisition def apply_parameters(self): """Apply the current parameters and decide whether to keep previous data.""" frequency = np.arange(self.frequency_begin, self.frequency_end + self.frequency_delta, self.frequency_delta) if not self.keep_data or np.any(frequency != self.frequency): self.frequency = frequency self.counts = np.zeros(frequency.shape) self.run_time = 0.0 self.keep_data = True # when job manager stops and starts the job, data should be kept. Only new submission should clear data. def _run(self): try: self.state = 'run' self.apply_parameters() if self.run_time >= self.stop_time: self.state = 'done' return # if pulsed, turn on sequence if self.pulsed: ha.PulseGenerator().Sequence( 100 * [(['laser', 'aom', 'red'], self.laser), ([], self.wait), (['mw'], self.t_pi)]) else: ha.PulseGenerator().Open() n = len(self.frequency) """ ha.Microwave().setOutput( self.power, np.append(self.frequency,self.frequency[0]), self.seconds_per_point) self._prepareCounter(n) """ ha.Microwave().setPower(self.power) ha.Microwave().initSweep( self.frequency, self.power * np.ones(self.frequency.shape)) ha.Counter().configure(n, self.seconds_per_point, DutyCycle=0.8) time.sleep(0.5) while self.run_time < self.stop_time: start_time = time.time() if threading.currentThread().stop_request.isSet(): break ha.Microwave().resetListPos() counts = ha.Counter().run() self.run_time += time.time() - start_time self.counts += counts self.counts_matrix = np.vstack( (counts, self.counts_matrix[:-1, :])) self.trait_property_changed('counts', self.counts) """ ha.Microwave().doSweep() timeout = 3. start_time = time.time() while not self._count_between_markers.ready(): time.sleep(0.1) if time.time() - start_time > timeout: print "count between markers timeout in ODMR" break counts = self._count_between_markers.getData(0) self._count_between_markers.clean() """ if self.run_time < self.stop_time: self.state = 'idle' else: self.state = 'done' ha.Microwave().setOutput(None, self.frequency_begin) ha.PulseGenerator().Light() ha.Counter().clear() except: logging.getLogger().exception('Error in odmr.') self.state = 'error' finally: ha.Microwave().setOutput(None, self.frequency_begin) # fitting def _update_fit(self): if self.perform_fit: N = self.number_of_resonances if N != 'auto': N = int(N) try: p = fitting.fit_multiple_lorentzians(self.frequency, self.counts, N, threshold=self.threshold * 0.01) except Exception: logging.getLogger().debug('ODMR fit failed.', exc_info=True) p = np.nan * np.empty(4) else: p = np.nan * np.empty(4) self.fit_parameters = p self.fit_frequencies = p[1::3] self.fit_line_width = p[2::3] N = len(p) / 3 contrast = np.empty(N) c = p[0] pp = p[1:].reshape((N, 3)) for i, pi in enumerate(pp): a = pi[2] g = pi[1] A = np.abs(a / (np.pi * g)) if a > 0: contrast[i] = 100 * A / (A + c) else: contrast[i] = 100 * A / c self.fit_contrast = contrast # plotting def _create_line_plot(self): line_data = ArrayPlotData(frequency=np.array((0., 1.)), counts=np.array((0., 0.)), fit=np.array((0., 0.))) line_plot = Plot(line_data, padding=8, padding_left=64, padding_bottom=32) line_plot.plot(('frequency', 'counts'), style='line', color='blue') line_plot.index_axis.title = 'Frequency [MHz]' line_plot.value_axis.title = 'Fluorescence counts' line_label = PlotLabel(text='', hjustify='left', vjustify='bottom', position=[64, 128]) line_plot.overlays.append(line_label) self.line_label = line_label self.line_data = line_data self.line_plot = line_plot def _create_matrix_plot(self): matrix_data = ArrayPlotData(image=np.zeros((2, 2))) matrix_plot = Plot(matrix_data, padding=8, padding_left=64, padding_bottom=32) matrix_plot.index_axis.title = 'Frequency [MHz]' matrix_plot.value_axis.title = 'line #' matrix_plot.img_plot('image', xbounds=(self.frequency[0], self.frequency[-1]), ybounds=(0, self.n_lines), colormap=Spectral) self.matrix_data = matrix_data self.matrix_plot = matrix_plot def _perform_fit_changed(self, new): plot = self.line_plot if new: plot.plot(('frequency', 'fit'), style='line', color='red', name='fit') self.line_label.visible = True else: plot.delplot('fit') self.line_label.visible = False plot.request_redraw() def _update_line_data_index(self): self.line_data.set_data('frequency', self.frequency * 1e-6) self.counts_matrix = self._counts_matrix_default() def _update_line_data_value(self): self.line_data.set_data('counts', self.counts) def _update_line_data_fit(self): if not np.isnan(self.fit_parameters[0]): self.line_data.set_data( 'fit', fitting.NLorentzians(*self.fit_parameters)(self.frequency)) p = self.fit_parameters f = p[1::3] w = p[2::3] N = len(p) / 3 contrast = np.empty(N) c = p[0] pp = p[1:].reshape((N, 3)) for i, pi in enumerate(pp): a = pi[2] g = pi[1] A = np.abs(a / (np.pi * g)) if a > 0: contrast[i] = 100 * A / (A + c) else: contrast[i] = 100 * A / c s = '' for i, fi in enumerate(f): s += 'f %i: %.6e Hz, HWHM %.3e Hz, contrast %.1f%%\n' % ( i + 1, fi, w[i], contrast[i]) self.line_label.text = s def _update_matrix_data_value(self): self.matrix_data.set_data('image', self.counts_matrix) def _update_matrix_data_index(self): if self.n_lines > self.counts_matrix.shape[0]: self.counts_matrix = np.vstack( (self.counts_matrix, np.zeros((self.n_lines - self.counts_matrix.shape[0], self.counts_matrix.shape[1])))) else: self.counts_matrix = self.counts_matrix[:self.n_lines] self.matrix_plot.components[0].index.set_data( (self.frequency[0] * 1e-6, self.frequency[-1] * 1e-6), (0.0, float(self.n_lines))) # saving data def save_line_plot(self, filename): self.save_figure(self.line_plot, filename) def save_matrix_plot(self, filename): self.save_figure(self.matrix_plot, filename) def save_all(self, filename): self.save_line_plot(filename + '_ODMR_Line_Plot.png') self.save_matrix_plot(filename + '_ODMR_Matrix_Plot.png') self.save(filename + '_ODMR.pys') # react to GUI events def submit(self): """Submit the job to the JobManager.""" self.keep_data = False ManagedJob.submit(self) def resubmit(self): """Submit the job to the JobManager.""" self.keep_data = True ManagedJob.submit(self) def _resubmit_button_fired(self): """React to start button. Submit the Job.""" self.resubmit() traits_view = View(VGroup( HGroup( Item('submit_button', show_label=False), Item('remove_button', show_label=False), Item('resubmit_button', show_label=False), Item('priority', enabled_when='state != "run"'), Item('state', style='readonly'), Item('run_time', style='readonly', format_str='%.f'), Item('stop_time'), ), VGroup( HGroup( Item('power', width=-40, enabled_when='state != "run"'), Item('frequency_begin', width=-80, enabled_when='state != "run"'), Item('frequency_end', width=-80, enabled_when='state != "run"'), Item('frequency_delta', width=-80, enabled_when='state != "run"'), ), HGroup( Item('seconds_per_point', width=-40, enabled_when='state != "run"'), Item('pulsed', enabled_when='state != "run"'), Item('laser', width=-50, enabled_when='state != "run"'), Item('wait', width=-50, enabled_when='state != "run"'), Item('t_pi', width=-50, enabled_when='state != "run"'), ), HGroup( Item('perform_fit'), Item('number_of_resonances', width=-60), Item('threshold', width=-60), Item('n_lines', width=-60), ), HGroup( Item('fit_contrast', style='readonly'), Item('fit_line_width', style='readonly'), Item('fit_frequencies', style='readonly'), ), ), VSplit( Item('matrix_plot', show_label=False, resizable=True), Item('line_plot', show_label=False, resizable=True), ), ), menubar=MenuBar( Menu(Action(action='saveLinePlot', name='SaveLinePlot (.png)'), Action(action='saveMatrixPlot', name='SaveMatrixPlot (.png)'), Action(action='save', name='Save (.pyd or .pys)'), Action(action='saveAll', name='Save All (.png+.pys)'), Action(action='export', name='Export as Ascii (.asc)'), Action(action='load', name='Load'), Action(action='_on_close', name='Quit'), name='File')), title='ODMR', width=900, height=800, buttons=[], resizable=True, handler=ODMRHandler) get_set_items = [ 'frequency', 'counts', 'counts_matrix', 'fit_parameters', 'fit_contrast', 'fit_line_width', 'fit_frequencies', 'perform_fit', 'run_time', 'power', 'frequency_begin', 'frequency_end', 'frequency_delta', 'laser', 'wait', 'pulsed', 't_pi', 'seconds_per_point', 'stop_time', 'n_lines', 'number_of_resonances', 'threshold', '__doc__' ]
class MATS3DScalarDamage(MATS3DEval): r''' Isotropic damage model. ''' node_name = 'Scalar damage' stiffness = tr.Enum("secant", "algorithmic", input=True) r'''Selector of the stiffness calculation. ''' strain_norm = EitherType(klasses=[ Rankine, ], input=True) r'''Selector of the strain norm defining the load surface. ''' epsilon_0 = tr.Float(5e-2, label="eps_0", desc="Strain at the onset of damage", auto_set=False, input=True) r'''Damage function parameter - slope of the damage function. ''' epsilon_f = tr.Float(191e-1, label="eps_f", desc="Slope of the damage function", auto_set=False, input=True) r'''Damage function parameter - slope of the damage function. ''' changed = tr.Event r'''This event can be used by the clients to trigger an action upon the completed reconfiguration of the material model ''' state_var_shapes = {'kappa': (), 'omega': ()} r''' Shapes of the state variables to be stored in the global array at the level of the domain. ''' def init(self, kappa, omega): r''' Initialize the state variables. ''' kappa[...] = 0 omega[...] = 0 def get_corr_pred(self, eps_Emab_n1, tn1, kappa, omega): r''' Corrector predictor computation. ''' I = self.update_state_variables(eps_Emab_n1, kappa, omega) phi_Em = (1.0 - omega) D_Emabcd = np.einsum('...,abcd->...abcd', phi_Em, self.D_abef) sigma_Emab = np.einsum('...abcd,...cd->...ab', D_Emabcd, eps_Emab_n1) # algorithmic switched off - because the derivative # of the strain norm is still not available if False: # algorithmic: D_Emabcd_red_I = self._get_D_abcd_alg_reduction( kappa[I], eps_Emab_n1[I]) D_Emabcd[I] -= D_Emabcd_red_I return sigma_Emab, D_Emabcd def update_state_variables(self, eps_Emab, kappa, omega): eps_eq_Em = self.strain_norm.get_eps_eq(eps_Emab, kappa) f_trial_Em = eps_eq_Em - self.epsilon_0 I = np.where(f_trial_Em > 0) kappa[I] = eps_eq_Em[I] omega[I] = self._get_omega(eps_eq_Em[I]) return I def _get_omega(self, kappa_Em): r''' Return new value of damage parameter @param kappa_Em: maximum strain norm achieved so far ''' omega_Em = np.zeros_like(kappa_Em) epsilon_0 = self.epsilon_0 epsilon_f = self.epsilon_f I = np.where(kappa_Em >= epsilon_0) omega_Em[I] = ( 1.0 - (epsilon_0 / kappa_Em[I] * np.exp(-1.0 * (kappa_Em[I] - epsilon_0) / (epsilon_f - epsilon_0)))) return omega_Em def _get_domega(self, kappa_Em): ''' Return new value of damage parameter derivative @param kappa_Em: maximum strain norm achieved so far ''' epsilon_0 = self.epsilon_0 epsilon_f = self.epsilon_f domega_Em = np.zeros_like(kappa_Em) I = np.where(kappa_Em >= epsilon_0) factor_1 = epsilon_0 / (kappa_Em[I] * kappa_Em[I]) factor_2 = epsilon_0 / (kappa_Em[I] * (epsilon_f - epsilon_0)) domega_Em[I] = ((factor_1 + factor_2) * np.exp(-(kappa_Em[I] - epsilon_0) / (epsilon_f - epsilon_0))) return domega_Em def _get_D_abcd_alg_reduction(self, kappa_Em, eps_Emab_n1): '''Calculate the stiffness term to be subtracted from the secant stiffness to get the algorithmic stiffness. ''' domega_Em = self._get_domega(kappa_Em) deps_eq_Emcd = self.strain_norm.get_deps_eq(eps_Emab_n1) return np.einsum('...,...cd,abcd,...cd->...abcd', domega_Em, deps_eq_Emcd, self.D_abef, eps_Emab_n1) traits_view = View(VSplit( Group(Item('E'), Item('nu'), Item('epsilon_0'), Item('epsilon_f'), Item('strain_norm')), Group( Item('stiffness', style='custom'), Spring(resizable=True), label='Configuration parameters', show_border=True, ), ), resizable=True) tree_view = View( Group(Item('E', full_size=True, resizable=True), Item('nu'), Item('epsilon_0'), Item('epsilon_f'), Item('strain_norm')), ) # Declare and fill-in the rte_dict - it is used by the clients to # assemble all the available time-steppers. # rte_dict = tr.Trait(tr.Dict) def _rte_dict_default(self): return {'sig_app': self.get_sig_app, 'omega': self.get_omega}
def traits_view(self): cols = [ CheckboxColumn(name='status'), ObjectColumn(name='status'), ObjectColumn(name='runid', width=50), ObjectColumn(name='age', width=100), ObjectColumn(name='age_err', width=100, label=PLUSMINUS_ONE_SIGMA), ObjectColumn(name='group'), ObjectColumn(name='aliquot'), ObjectColumn(name='sample') ] gcols = [ ObjectColumn(name='name'), ObjectColumn( name='weighted_mean', label='Wtd. Mean', format='%0.6f', ), ObjectColumn(name='weighted_mean_err', format='%0.6f', label=PLUSMINUS_ONE_SIGMA), ObjectColumn(name='mswd', format='%0.3f', label='MSWD'), ObjectColumn(name='displayn', label='N'), ObjectColumn(name='mean', format='%0.6f', label='Mean'), ObjectColumn(name='std', format='%0.6f', label='Std'), ObjectColumn(name='min', format='%0.6f', label='Min'), ObjectColumn(name='max', format='%0.6f', label='Max'), ObjectColumn(name='dev', format='%0.6f', label='Dev.'), ObjectColumn(name='percent_dev', format='%0.2f', label='% Dev.') ] button_grp = HGroup(UItem('save_button'), UItem('save_as_button'), UItem('clear_button'), UItem('open_via_finder_button'), UItem('add_record_button'), UItem('calculate_button')), repo_grp = VGroup( BorderVGroup(UItem('repo_filter'), UItem('repositories', width=200, editor=ListStrEditor(selected='repository')), label='Repositories'), BorderVGroup(UItem('name_filter'), UItem('names', editor=ListStrEditor(selected='name')), label='DataSets')) record_grp = VSplit( UItem( 'records', editor=TableEditor( columns=cols, selected='selected', sortable=False, edit_on_first_click=False, # clear_selection_on_dclicked=True, menu=MenuManager( Action(name='Group Selected', perform=self._group_selected)), selection_mode='rows')), UItem('groups', editor=TableEditor(columns=gcols))) main_grp = HSplit(repo_grp, record_grp) v = okcancel_view( VGroup(button_grp, main_grp), width=1100, height=500, title='CSV Dataset', # handler=CSVDataSetFactoryHandler() ) return v
class SimArrayView(ModelView): ''' View into the parametric space constructed over the model. The is associated with the PStudySpace instance covering the factor ranges using an n-dimensional array. The view is responsible for transferring the response values into 2D and 3D plots. Depending on the current view specification it also initiates the calculation of response values in the currently viewed subspace of the study. ''' model = Instance(ISimArray) #--------------------------------------------------------------- # PARAMETER RANGE SPECIFICATION #------------------------------------------------------------------- factor_dict = DelegatesTo('model') # alphabetically ordered names of factors # factor_names = DelegatesTo('model') # alphabetically ordered list of factors # factor_list = DelegatesTo('model') #--------------------------------------------------------------- # X-PARAMETER RANGE SPECIFICATION #------------------------------------------------------------------- # Selected factor name for evalution along the X-axis # x_factor_name = Str(factors_modified=True) def _x_factor_name_default(self): return self.factor_names[0] def _x_factor_name_changed(self): if self.x_factor_name == self.y_factor_name: self.y_factor_name = '-' if self.x_factor_name == self.other_factor_name: self.other_factor_name = '-' self.x_factor = self.factor_dict[self.x_factor_name] x_factor = Instance(SimFactor) def _x_factor_default(self): return self.factor_dict[self.factor_names[0]] # index of the currently selected variable x_factor_idx = Property() def _get_x_factor_idx(self): return self.factor_names.index(self.x_factor_name) #--------------------------------------------------------------- # Y-PARAMETER RANGE SPECIFICATION #------------------------------------------------------------------- y_factor_names = Property(depends_on='x_factor_name') @cached_property def _get_y_factor_names(self): current_x_factor = self.x_factor_name current_x_factor_idx = self.factor_names.index(current_x_factor) y_factor_names = self.factor_names[:current_x_factor_idx] + \ self.factor_names[current_x_factor_idx+1:] return ['-'] + y_factor_names # # Selected factor name for evalution of multiple lines # y_factor_name = Str('-', factors_modified=True) def _y_factor_name_changed(self): if self.y_factor_name == self.other_factor_name: self.other_factor_name = '-' if self.y_factor_name == '-': self.y_factor = None else: self.y_factor = self.factor_dict[self.y_factor_name] y_factor = Instance(SimFactor) y_factor_idx = Property() def _get_y_factor_idx(self): return self.factor_names.index(self.y_factor_name) #------------------------------------------------------------------ # OTHER PARAM LEVELS #------------------------------------------------------------------ other_factor_names = Property(depends_on='x_factor_name, y_factor_name') @cached_property def _get_other_factor_names(self): x_factor_idx = self.factor_names.index(self.x_factor_name) y_factor_idx = x_factor_idx if self.y_factor_name != '-': y_factor_idx = self.factor_names.index(self.y_factor_name) ignore_idx = [x_factor_idx, y_factor_idx] ignore_idx.sort() other_factor_names = self.factor_names[:ignore_idx[0] ] + \ self.factor_names[ignore_idx[0]+1: ignore_idx[1]] + \ self.factor_names[ignore_idx[1]+1:] return ['-'] + other_factor_names # # Selected factor name for evalution of multiple lines # other_factor_name = Str('-', factors_modified=True) def _other_factor_name_changed(self): if self.other_factor_name == '-': self.other_factor_levels = [] else: levels = self.factor_dict[self.other_factor_name].level_list self.other_factor_levels = list(levels) other_factor_idx = self.factor_names.index(self.other_factor_name) other_factor_level_idx = self.frozen_factor_levels[ other_factor_idx] self.other_factor_level = self.other_factor_levels[ other_factor_level_idx] other_factor_levels = List other_factor_level = Any def _other_factor_level_changed(self): level_idx = self.other_factor_levels.index(self.other_factor_level) other_factor_idx = self.factor_names.index(self.other_factor_name) self.frozen_factor_levels[other_factor_idx] = level_idx frozen_factor_levels = Array def _frozen_factor_levels_default(self): return zeros(self.model.n_factors, dtype='int_') #--------------------------------------------------------------- # OUTPUT ARRAY SPECIFICATION #------------------------------------------------------------------- outputs = DelegatesTo('model') # extract the available names output_names = DelegatesTo('model') # active selection to be plotted output_name = Str def _output_name_default(self): return self.output_names[0] output_idx = Property(Int, depends_on='output_name') def _get_output_idx(self): return self.output_names.index(self.output_name) def _output_name_changed(self): self.output = self.outputs[self.output_idx] output = Instance(SimOut) def _output_default(self): return self.outputs[0] #--------------------------------------------------------------- # PLOT OBJECT #------------------------------------------------------------------- figure = Instance(Figure) def _figure_default(self): figure = Figure(facecolor='white') figure.add_axes([0.12, 0.13, 0.85, 0.74]) return figure #--------------------------------------------------------------------------- # Public Controller interface #--------------------------------------------------------------------------- def start_study(self, ui_info): self._start_study() def stop_study(self, ui_info): todo = ToDo() todo.configure_traits(kind='modal') def _start_study(self): # identify the runs to be performed # use slices along the varied factors # to obtain the indices of the values. # get the sliced dimensions # factor_levels = [level for level in self.frozen_factor_levels] factor_levels[self.x_factor_idx] = slice(None) if self.y_factor_name != '-': factor_levels[self.y_factor_idx] = slice(None) factor_slices = tuple(factor_levels) # get the response value for the given factor slices # output_array = self.model[factor_slices] # map the array dimensions to the plot axes # figure = self.figure axes = figure.axes[0] axes.clear() x_levels = self.x_factor.level_list if self.y_factor_name == '-': axes.plot(x_levels, output_array[:, self.output_idx] # color = c, linewidth = w, linestyle = s ) else: y_levels = self.y_factor.level_list for i_y, y_level in enumerate(y_levels): index = x_levels # The dimensions of the returned array are given # by the index of the factors within the pstudy # In other words, the subspace to be plotted has # the same order of factors as the original space. # The remapping of the axes must therefore respect # this order and take y data from the first dimension # if y_factor_idx is lower than y_factor_idx # if self.y_factor_idx > self.x_factor_idx: values = output_array[:, i_y, self.output_idx] else: values = output_array[i_y, :, self.output_idx] axes.plot(index, values # color = c, linewidth = w, linestyle = s ) legend = [str(level) for level in y_levels] axes.legend(legend, loc='best') axes.set_xlabel('%s [%s]' % (self.x_factor_name, self.x_factor.unit), weight='semibold') axes.set_ylabel('%s [%s]' % (self.output_name, self.output.unit), weight='semibold') # axes.set_title( 'strength size effect',\ # size = 'large', color = 'black',\ # weight = 'bold', position = (.5,1.03)) axes.set_axis_bgcolor(color='white') # axes.ticklabel_format(scilimits = (-3.,4.)) axes.grid(color='gray', linestyle='--', linewidth=0.1, alpha=0.4) # axes.legend(( legend ), loc = 'best') # axes.set_xscale('log' ) #, subsx = [0, 1, 2, 3 ] ) # axes.set_yscale('log' ) # , subsy = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] ) #axes.set_xlim(10.e-4) self.data_changed = True data_changed = Event traits_view = View( HSplit( VGroup( VGroup( Item('x_factor_name', editor=EnumEditor(name='factor_names'), label='horizontal axis'), Item('y_factor_name', editor=EnumEditor(name='y_factor_names'), label='depth axis'), Item('other_factor_name', editor=EnumEditor(name='other_factor_names'), label='other factors'), Item('other_factor_level', editor=EnumEditor(name='other_factor_levels'), label='viewed level'), label='viewed subspace', id='sim_pstudy.viewmodel.factor.subspace', dock='tab', scrollable=True, ), VGroup( Item('output_name', editor=EnumEditor(name='output_names'), show_label=False), Item('output@', show_label=False, springy=True), label='vertical axis', id='sim_psrudy.viewmodel.control', dock='tab', ), id='sim_pstudy.viewmodel.left', label='studied factors', layout='normal', dock='tab', ), VSplit( VGroup( Item('figure', editor=MPLFigureEditor(), resizable=True, show_label=False), label='plot sheet', id='sim_pstudy.viewmode.figure_window', dock='tab', ), id='sim_pstudy.viewmodel.right', ), id='sim_pstudy.viewmodel.splitter', #group_theme = '@G', #item_theme = '@B0B', #label_theme = '@BEA', ), toolbar=ToolBar(Action(name="Run", tooltip='Start computation', image=ImageResource('kt-start'), action="start_study"), Action(name="Pause", tooltip='Pause computation', image=ImageResource('kt-pause'), action="pause_study"), Action(name="Stop", tooltip='Stop computation', image=ImageResource('kt-stop'), action="stop_study"), image_size=(32, 32), show_tool_names=False, show_divider=True, name='view_toolbar'), title='SimVisage Component: Parametric Studies', id='sim_pstudy.viewmodel', dock='tab', resizable=True, height=0.8, width=0.8, buttons=[OKButton])
class Spotfinder(ManagedJob, GetSetItemsMixin, SpotfinderBasicFunc): X = Array() Y = Array() image = Array() image2 = Array() bwimage = Array() resolution = [[0.1], [0.1]] refpoint = [[0], [0]] # plots plot_data = Instance(ArrayPlotData) scan_plot = Instance(CMapImagePlot) figure = Instance(Plot) bwplot_data = Instance(ArrayPlotData) bwscan_plot = Instance(CMapImagePlot) bwfigure = Instance(Plot) figure_container = Instance(HPlotContainer, editor=ComponentEditor()) confocal = Any(editor=InstanceEditor) ImportImage = Button(label='import image') GetBWimage = Button(label='get bwimage') ProcessBWimage = Button( label='process bwimage', desc='clean image (minarea maxarea) and calculate centroids') MinArea = Int(value=10, label='minarea') MaxArea = Int(value=10, label='maxarea') size = Int(value=2, label='spotarea') BWimageMeth = Enum('simple', 'advanced') BWimageMedian = Int(value=10, label='median size') ImageThreshold = Float( value=50000, desc='This value sets the threshold for the bw image', label='Threshold') BWimageMedian1 = Int(value=10, label='median size') ImageThreshold1 = Float( value=50000, desc='This value sets the threshold for the bw image', label='Threshold') SpotMaxInt = Float( value=5000000, desc= 'This value sets the threshold for maximum allowed mean spot intensity', label='max int') SpotMinInt = Float( value=0, desc= 'This value sets the threshold for minimum allowed mean spot intensity', label='min int') SpotShapeRatio = Float( value=2, desc= 'This value sets the threshold for minimum allowed mean spot intensity', label='shape ratio') ExportTag = Str('nv') ExportButton = Button('Export to auto_focus') Centroids = list() Centroids1 = list() IntWeighting = Bool(True) off_diagonal_account = Bool(True) labels = dict() scaler = [[1], [1]] def __init__(self, confocal, auto_focus, **kwargs): super(Spotfinder, self).__init__(**kwargs) self.confocal = confocal self.auto_focus = auto_focus self.X = numpy.linspace(self.confocal.scanner.getXRange()[0], self.confocal.scanner.getXRange()[-1], self.confocal.resolution + 1) self.Y = numpy.linspace(self.confocal.scanner.getYRange()[0], self.confocal.scanner.getYRange()[-1], self.confocal.resolution + 1) self.image = numpy.zeros((len(self.X), len(self.Y))) self.bwimage = numpy.zeros((len(self.X), len(self.Y))) self._create_plot() self.on_trait_change(self.update_image_plot, 'image', dispatch='ui') self.on_trait_change(self.redraw_image, 'confocal.thresh_high', dispatch='ui') self.on_trait_change(self.redraw_image, 'confocal.thresh_low', dispatch='ui') self.on_trait_change(self.redraw_image, 'confocal.thresh_high', dispatch='ui') self.on_trait_change(self.redraw_image, 'confocal.thresh_low', dispatch='ui') self.on_trait_change(self.set_mesh_and_aspect_ratio, 'X,Y', dispatch='ui') #startup values self.BWimageMedian = 10 self.MinArea = 3 self.MaxArea = 100 def _ExportButton_fired(self): if len(self.labels) is not 0: for label in self.labels.keys(): self.auto_focus.target_name = self.ExportTag + label self.confocal.x = self.labels[label][1] self.confocal.y = self.labels[label][0] #self.confocal.z=self.labels[label][2] self.auto_focus._add_target_button_fired() else: print 'no tartgets to export' def _ImportImage_fired(self): # the long road for extracting the zoom parameters ... Dim = numpy.shape(self.confocal.image) ImagePosX = [self.confocal.X[0], self.confocal.X[-1]] ImagePosY = [self.confocal.Y[0], self.confocal.Y[-1]] ImageRangeX = self.confocal.figure.index_range.get() ImageRangeX = [ ImageRangeX['_low_setting'], ImageRangeX['_high_setting'] ] ImageRangeY = self.confocal.figure.value_range.get() ImageRangeY = [ ImageRangeY['_low_setting'], ImageRangeY['_high_setting'] ] FullRangeX = self.confocal.scanner.getXRange() FullRangeY = self.confocal.scanner.getYRange() resolution = [(ImagePosY[1] - ImagePosY[0]) / Dim[0], (ImagePosX[1] - ImagePosX[0]) / Dim[1]] RangeX = numpy.round( numpy.asarray([ ImageRangeX[0] - ImagePosX[0], ImageRangeX[1] - ImagePosX[0] ]) / resolution[1]) RangeY = numpy.round( numpy.asarray([ ImageRangeY[0] - ImagePosY[0], ImageRangeY[1] - ImagePosY[0] ]) / resolution[0]) self.scaler[0] = FullRangeX[1] / resolution[1] self.scaler[1] = FullRangeY[1] / resolution[0] self.resolution = resolution self.refpoint = [ImagePosY[0], ImagePosX[0]] # import only the part of the image of the zoom self.image = self.confocal.image[RangeY[0]:RangeY[1] + 1, RangeX[0]:RangeX[1] + 1] #self.image2=self.confocal.image self.update_mesh() self.redraw_image() if self.BWimageMeth == 'simple': self.ImageThreshold = numpy.median(self.image) * 1.5 if self.BWimageMeth == 'advanced': self.ImageThreshold = 1.5 self.SpotMaxInt = numpy.max(self.image) self.SpotMinInt = numpy.min(self.image) self.SpotShapeRatio = 2 def _GetBWimage_fired(self): self.bwimage = self.find_bwimage(self.image, Param=self.ImageThreshold, Mode=self.BWimageMeth, Median=self.BWimageMedian) self.bwimage1 = self.image * self.bwimage self.bwplot_data.set_data('bwimage', self.bwimage1) self.remove_all_targets() def _ProcessBWimage_fired(self): self._GetBWimage_fired() [self.bwimage, self.Centroids] = self.find_centroids(self.bwimage, size=self.size, MinArea=self.MinArea, MaxArea=self.MaxArea, th1=self.ImageThreshold1, bw1=self.BWimageMedian1, MinInt=self.SpotMinInt, MaxInt=self.SpotMaxInt, ShapeRatio=self.SpotShapeRatio, image=self.image, intweighting=self.IntWeighting) self.image_handle = self.bwimage + numpy.min(self.image) self.bwplot_data.set_data('bwimage', self.image_handle) for ID, coords in enumerate(self.Centroids): self.add_target(str(ID), coords) def redraw_image(self): self.scan_plot.value_range.high_setting = self.confocal.thresh_high self.scan_plot.value_range.low_setting = self.confocal.thresh_low self.scan_plot.request_redraw() def _create_plot(self): plot_data = ArrayPlotData(image=self.image) plot = Plot(plot_data, width=500, height=500, resizable='hv', aspect_ratio=1.0, padding=8, padding_left=32, padding_bottom=32) plot.img_plot('image', colormap=jet, xbounds=(self.X[0], self.X[-1]), ybounds=(self.Y[0], self.Y[-1]), name='image') image = plot.plots['image'][0] bwplot_data = ArrayPlotData(bwimage=self.bwimage) bwplot = Plot(bwplot_data, width=500, height=500, resizable='hv', aspect_ratio=1.0, padding=8, padding_left=32, padding_bottom=32) bwplot.img_plot('bwimage', colormap=jet, xbounds=(self.X[0], self.X[-1]), ybounds=(self.Y[0], self.Y[-1]), name='bwimage') bwimage = bwplot.plots['bwimage'][0] image.x_mapper.domain_limits = (self.confocal.scanner.getXRange()[0], self.confocal.scanner.getXRange()[1]) image.y_mapper.domain_limits = (self.confocal.scanner.getYRange()[0], self.confocal.scanner.getYRange()[1]) bwimage.x_mapper.domain_limits = (self.confocal.scanner.getXRange()[0], self.confocal.scanner.getXRange()[1]) bwimage.y_mapper.domain_limits = (self.confocal.scanner.getYRange()[0], self.confocal.scanner.getYRange()[1]) colormap = image.color_mapper colorbar = ColorBar(index_mapper=LinearMapper(range=colormap.range), color_mapper=colormap, plot=plot, orientation='v', resizable='v', width=16, height=320, padding=8, padding_left=32) container = HPlotContainer() container.add(plot) container.add(colorbar) container.add(bwplot) container.tools.append(SaveTool(container)) self.plot_data = plot_data self.scan_plot = image self.figure = plot self.bwplot_data = bwplot_data self.bwscan_plot = bwimage self.bwfigure = bwplot self.figure_container = container def update_image_plot(self): self.plot_data.set_data('image', self.image) def update_mesh(self): Info = self.confocal.figure.index_range.get() x1 = Info['_low_setting'] x2 = Info['_high_setting'] Info = self.confocal.figure.value_range.get() y1 = Info['_low_setting'] y2 = Info['_high_setting'] Dim = numpy.shape(self.image) self.Y = numpy.linspace(y1, y2, Dim[0]) self.X = numpy.linspace(x1, x2, Dim[1]) def set_mesh_and_aspect_ratio(self): self.scan_plot.index.set_data(self.X, self.Y) self.bwscan_plot.index.set_data(self.X, self.Y) x1 = self.X[0] x2 = self.X[-1] y1 = self.Y[0] y2 = self.Y[-1] self.figure.aspect_ratio = (x2 - x1) / float((y2 - y1)) self.figure.index_range.low = x1 self.figure.index_range.high = x2 self.figure.value_range.low = y1 self.figure.value_range.high = y2 self.bwfigure.aspect_ratio = (x2 - x1) / float((y2 - y1)) self.bwfigure.index_range.low = x1 self.bwfigure.index_range.high = x2 self.bwfigure.value_range.low = y1 self.bwfigure.value_range.high = y2 def add_target(self, key, coordinates=None): Info = self.confocal.figure.index_range.get() coordinates2 = [[], []] x1 = Info['_low_setting'] Info = self.confocal.figure.value_range.get() y1 = Info['_low_setting'] coordinates[0] = coordinates[0] * self.resolution[0] + y1 coordinates[1] = coordinates[1] * self.resolution[1] + x1 plot = self.scan_plot point = (coordinates[1], coordinates[0]) defaults = { 'component': plot, 'data_point': point, 'label_format': key, 'label_position': 'top right', 'bgcolor': 'transparent', 'text_color': 'red', 'border_visible': False, 'padding_bottom': 8, 'marker': 'cross', 'marker_color': 'red', 'marker_line_color': 'red', 'marker_line_width': 1.4, 'marker_size': 6, 'arrow_visible': False, 'clip_to_plot': False, 'visible': True } self.labels[key] = coordinates label = DataLabel(**defaults) plot.overlays.append(label) plot.request_redraw() self.labels[key] = coordinates def remove_all_targets(self): plot = self.scan_plot new_overlays = [] for item in plot.overlays: if not (isinstance(item, DataLabel) and item.label_format in self.labels): new_overlays.append(item) plot.overlays = new_overlays plot.request_redraw() self.labels.clear() IAN = View(Item('ImportImage', show_label=False, resizable=True)) traits_view = View(VSplit( HGroup( Item('ImportImage', show_label=False, resizable=True), Item('GetBWimage', show_label=False, resizable=True), Item('BWimageMeth', show_label=True, resizable=True), Item('ImageThreshold', show_label=True, resizable=True, width=-30), Item('BWimageMedian', show_label=True, resizable=True, width=-30), Item('ImageThreshold1', show_label=True, resizable=True, width=-30), Item('BWimageMedian1', show_label=True, resizable=True, width=-30)), HGroup(Item('ProcessBWimage', show_label=False, resizable=True), Item('size', show_label=True, resizable=True, width=-30), Item('MinArea', show_label=True, resizable=True, width=-30), Item('MaxArea', show_label=True, resizable=True, width=-30), Item('SpotMinInt', show_label=True, resizable=True, width=-30), Item('SpotMaxInt', show_label=True, resizable=True, width=-30), Item('SpotShapeRatio', show_label=True, resizable=True), Item('IntWeighting'), Item('off_diagonal_account')), HGroup(Item('ExportButton', show_label=False, resizable=True), Item('ExportTag', show_label=False, resizable=True)), Item('figure_container', show_label=False, resizable=True, height=600)), title='SpotFinder', width=1080, height=800, buttons=[], resizable=True, x=0, y=0)
VSplit( VGroup( UItem("source", style="custom"), HGroup( spring, UItem( "handler.run_button", ), visible_when="source is not None", ), ), VGroup( Tabbed( UItem( "demo", style="custom", resizable=True, ), Item( "log", style="readonly", editor=CodeEditor( show_line_numbers=False, selected_color=0xFFFFFF ), label="Output", show_label=False, ), Item( "locals", editor=ShellEditor(share=True), label="Shell", show_label=False, ), visible_when='demo is not None', ), Tabbed( Item( "log", style="readonly", editor=CodeEditor( show_line_numbers=False, selected_color=0xFFFFFF ), label="Output", show_label=False, ), Item( "locals", editor=ShellEditor(share=True), label="Shell", show_label=False, ), visible_when='demo is None', ), ), dock="horizontal", ),
class SwiftConsole(HasTraits): """Traits-defined Swift Console. link : object Serial driver update : bool Update the firmware log_level_filter : str Syslog string, one of "ERROR", "WARNING", "INFO", "DEBUG". """ link = Instance(sbpc.Handler) console_output = Instance(OutputList()) python_console_env = Dict device_serial = Str('') dev_id = Str('') tracking_view = Instance(TrackingView) solution_view = Instance(SolutionView) baseline_view = Instance(BaselineView) skyplot_view = Instance(SkyplotView) observation_view = Instance(ObservationView) networking_view = Instance(SbpRelayView) observation_view_base = Instance(ObservationView) system_monitor_view = Instance(SystemMonitorView) settings_view = Instance(SettingsView) update_view = Instance(UpdateView) imu_view = Instance(IMUView) mag_view = Instance(MagView) spectrum_analyzer_view = Instance(SpectrumAnalyzerView) log_level_filter = Enum(list(SYSLOG_LEVELS.values())) """" mode : baseline and solution view - SPP, Fixed or Float num_sat : baseline and solution view - number of satellites port : which port is Swift Device is connected to directory_name : location of logged files json_logging : enable JSON logging csv_logging : enable CSV logging """ mode = Str('') ins_status_string = Str('') num_sats_str = Str('') cnx_desc = Str('') age_of_corrections = Str('') uuid = Str('') directory_name = Directory json_logging = Bool(True) csv_logging = Bool(False) cnx_icon = Str('') heartbeat_count = Int() last_timer_heartbeat = Int() driver_data_rate = Str() solid_connection = Bool(False) csv_logging_button = SVGButton( toggle=True, label='CSV log', tooltip='start CSV logging', toggle_tooltip='stop CSV logging', filename=resource_filename('console/images/iconic/pause.svg'), toggle_filename=resource_filename('console/images/iconic/play.svg'), orientation='vertical', width=2, height=2, ) json_logging_button = SVGButton( toggle=True, label='JSON log', tooltip='start JSON logging', toggle_tooltip='stop JSON logging', filename=resource_filename('console/images/iconic/pause.svg'), toggle_filename=resource_filename('console/images/iconic/play.svg'), orientation='vertical', width=2, height=2, ) paused_button = SVGButton( label='', tooltip='Pause console update', toggle_tooltip='Resume console update', toggle=True, filename=resource_filename('console/images/iconic/pause.svg'), toggle_filename=resource_filename('console/images/iconic/play.svg'), width=8, height=8) clear_button = SVGButton( label='', tooltip='Clear console buffer', filename=resource_filename('console/images/iconic/x.svg'), width=8, height=8) view = View( VSplit( Tabbed( Tabbed( Item('tracking_view', style='custom', label='Signals', show_label=False), Item('skyplot_view', style='custom', label='Sky Plot', show_label=False), label="Tracking"), Item('solution_view', style='custom', label='Solution'), Item('baseline_view', style='custom', label='Baseline'), VSplit( Item('observation_view', style='custom', show_label=False), Item( 'observation_view_base', style='custom', show_label=False), label='Observations', ), Item('settings_view', style='custom', label='Settings'), Item('update_view', style='custom', label='Update'), Tabbed( Item( 'system_monitor_view', style='custom', label='System Monitor'), Item('imu_view', style='custom', label='IMU'), Item('mag_view', style='custom', label='Magnetometer'), Item( 'networking_view', label='Networking', style='custom', show_label=False), Item( 'spectrum_analyzer_view', label='Spectrum Analyzer', style='custom'), label='Advanced', show_labels=False), show_labels=False), VGroup( VGroup( HGroup( Spring(width=4, springy=False), Item( 'paused_button', show_label=False, padding=0, width=8, height=8), Item( 'clear_button', show_label=False, width=8, height=8), Item('', label='Console Log', emphasized=True), Item( 'csv_logging_button', emphasized=True, show_label=False, width=12, height=-30, padding=0), Item( 'json_logging_button', emphasized=True, show_label=False, width=12, height=-30, padding=0), Item( 'directory_name', show_label=False, springy=True, tooltip='Choose location for file logs. Default is home/SwiftNav.', height=-25, enabled_when='not(json_logging or csv_logging)', editor_args={'auto_set': True}), UItem( 'log_level_filter', style='simple', padding=0, height=8, show_label=True, tooltip='Show log levels up to and including the selected level of severity.\nThe CONSOLE log level is always visible.' ), ), Item( 'console_output', style='custom', editor=InstanceEditor(), height=125, show_label=False, full_size=True), ), HGroup( Spring(width=4, springy=False), Item( '', label='Interface:', emphasized=True, tooltip='Interface for communicating with Swift device' ), Item('cnx_desc', show_label=False, style='readonly'), Item( '', label='FIX TYPE:', emphasized=True, tooltip='Device Mode: SPS, Float RTK, Fixed RTK'), Item('mode', show_label=False, style='readonly'), Item( '', label='#Sats:', emphasized=True, tooltip='Number of satellites used in solution'), Item( 'num_sats_str', padding=2, show_label=False, style='readonly'), Item( '', label='Corr Age:', emphasized=True, tooltip='Age of corrections (-- means invalid / not present)' ), Item( 'age_of_corrections', padding=2, show_label=False, style='readonly'), Item( '', label='INS Status:', emphasized=True, tooltip='INS Status String' ), Item( 'ins_status_string', padding=2, show_label=False, style='readonly', width=6), Spring(springy=True), Item('driver_data_rate', style='readonly', show_label=False), Item( 'cnx_icon', show_label=False, padding=0, width=8, height=8, visible_when='solid_connection', springy=False, editor=ImageEditor( allow_clipping=False, image=ImageResource(resource_filename('console/images/iconic/arrows_blue.png')) )), Item( 'cnx_icon', show_label=False, padding=0, width=8, height=8, visible_when='not solid_connection', springy=False, editor=ImageEditor( allow_clipping=False, image=ImageResource( resource_filename('console/images/iconic/arrows_grey.png') ))), Spring(width=4, height=-2, springy=False), ), Spring(height=1, springy=False), ), ), icon=icon, resizable=True, width=800, height=600, handler=ConsoleHandler(), title=CONSOLE_TITLE) def print_message_callback(self, sbp_msg, **metadata): try: encoded = sbp_msg.payload.encode('ascii', 'ignore') for eachline in reversed(encoded.split('\n')): self.console_output.write_level( eachline, str_to_log_level(eachline.split(':')[0])) except UnicodeDecodeError as e: print("Error encoding msg_print: {}".format(e)) def log_message_callback(self, sbp_msg, **metadata): encoded = sbp_msg.text.decode('utf8') for eachline in reversed(encoded.split('\n')): self.console_output.write_level(eachline, sbp_msg.level) def ext_event_callback(self, sbp_msg, **metadata): e = MsgExtEvent(sbp_msg) print( 'External event: %s edge on pin %d at wn=%d, tow=%d, time qual=%s' % ("Rising" if (e.flags & (1 << 0)) else "Falling", e.pin, e.wn, e.tow, "good" if (e.flags & (1 << 1)) else "unknown")) def cmd_resp_callback(self, sbp_msg, **metadata): r = MsgCommandResp(sbp_msg) print( "Received a command response message with code {0}".format(r.code)) def _paused_button_fired(self): self.console_output.paused = not self.console_output.paused def _log_level_filter_changed(self): """ Takes log level enum and translates into the mapped integer. Integer stores the current filter value inside OutputList. """ self.console_output.log_level_filter = str_to_log_level( self.log_level_filter) def _clear_button_fired(self): self.console_output.clear() def _directory_name_changed(self): if self.baseline_view and self.solution_view: self.baseline_view.directory_name_b = self.directory_name self.solution_view.directory_name_p = self.directory_name self.solution_view.directory_name_v = self.directory_name if self.observation_view and self.observation_view_base: self.observation_view.dirname = self.directory_name self.observation_view_base.dirname = self.directory_name def check_heartbeat(self): # if our heartbeat hasn't changed since the last timer interval the connection must have dropped if self.heartbeat_count == self.last_timer_heartbeat: self.solid_connection = False self.ins_status_string = "None" self.mode = "None" self.num_sats_str = EMPTY_STR else: self.solid_connection = True self.last_timer_heartbeat = self.heartbeat_count total_bytes = self.driver.total_bytes_read self.driver_data_rate = "{0:.2f} KB/s".format((total_bytes - self.last_driver_bytes_read) / (1.2 * 1024)) self.last_driver_bytes_read = total_bytes def update_on_heartbeat(self, sbp_msg, **metadata): self.heartbeat_count += 1 # --- determining which mode, llh or baseline, to show in the status bar --- llh_display_mode = "None" llh_num_sats = 0 llh_is_differential = False baseline_display_mode = "None" baseline_num_sats = 0 baseline_is_differential = False # determine the latest llh solution mode if self.solution_view: llh_solution_mode = self.solution_view.last_pos_mode llh_display_mode = mode_dict.get(llh_solution_mode, EMPTY_STR) if llh_solution_mode > 0 and self.solution_view.last_soln: llh_num_sats = self.solution_view.last_soln.n_sats llh_is_differential = (llh_solution_mode in DIFFERENTIAL_MODES) if getattr(self.solution_view, 'ins_used', False) and llh_solution_mode != DR_MODE: llh_display_mode += "+INS" # determine the latest baseline solution mode if self.baseline_view and self.settings_view and self.settings_view.dgnss_enabled(): baseline_solution_mode = self.baseline_view.last_mode baseline_display_mode = mode_dict.get(baseline_solution_mode, EMPTY_STR) if baseline_solution_mode > 0 and self.baseline_view.last_soln: baseline_num_sats = self.baseline_view.last_soln.n_sats baseline_is_differential = (baseline_solution_mode in DIFFERENTIAL_MODES) # determine the latest INS mode if self.solution_view and (monotonic() - self.solution_view.last_ins_status_receipt_time) < 1: ins_flags = self.solution_view.ins_status_flags ins_mode = ins_flags & 0x7 ins_type = (ins_flags >> 29) & 0x7 odo_status = (ins_flags >> 8) & 0x3 ins_error = (ins_flags >> 4) & 0xF if ins_error != 0: ins_status_string = ins_error_dict.get(ins_error, "Unk Error") else: ins_status_string = ins_type_dict.get(ins_type, "unk") + "-" ins_status_string += ins_mode_dict.get(ins_mode, "unk") if odo_status == 1: ins_status_string += "+Odo" self.ins_status_string = ins_status_string # select the solution mode displayed in the status bar: # * baseline if it's a differential solution but llh isn't # * otherwise llh (also if there is no solution, in which both are "None") if baseline_is_differential and not(llh_is_differential): self.mode = baseline_display_mode self.num_sats_str = "{}".format(baseline_num_sats) else: self.mode = llh_display_mode self.num_sats_str = "{}".format(llh_num_sats) # --- end of status bar mode determination section --- if self.settings_view: # for auto populating surveyed fields self.settings_view.lat = self.solution_view.latitude self.settings_view.lon = self.solution_view.longitude self.settings_view.alt = self.solution_view.altitude if self.baseline_view: if self.baseline_view.age_corrections is not None: self.age_of_corrections = "{0} s".format( self.baseline_view.age_corrections) else: self.age_of_corrections = EMPTY_STR def _csv_logging_button_action(self): if self.csv_logging and self.baseline_view.logging_b and self.solution_view.logging_p and self.solution_view.logging_v: print("Stopped CSV logging") self.csv_logging = False self.baseline_view.logging_b = False self.solution_view.logging_p = False self.solution_view.logging_v = False else: print("Started CSV logging at %s" % self.directory_name) self.csv_logging = True self.baseline_view.logging_b = True self.solution_view.logging_p = True self.solution_view.logging_v = True def _start_json_logging(self, override_filename=None): if override_filename: filename = override_filename else: filename = time.strftime("swift-gnss-%Y%m%d-%H%M%S.sbp.json") filename = os.path.normpath( os.path.join(self.directory_name, filename)) self.logger = s.get_logger(True, filename, self.expand_json) self.forwarder = sbpc.Forwarder(self.link, self.logger) self.forwarder.start() if self.settings_view: self.settings_view._settings_read_all() def _stop_json_logging(self): fwd = self.forwarder fwd.stop() self.logger.flush() self.logger.close() def _json_logging_button_action(self): if self.first_json_press and self.json_logging: print( "JSON Logging initiated via CMD line. Please press button again to stop logging" ) elif self.json_logging: self._stop_json_logging() self.json_logging = False print("Stopped JSON logging") else: self._start_json_logging() self.json_logging = True self.first_json_press = False def _json_logging_button_fired(self): if not os.path.exists(self.directory_name) and not self.json_logging: confirm_prompt = CallbackPrompt( title="Logging directory creation", actions=[ok_button], callback=self._json_logging_button_action) confirm_prompt.text = "\nThe selected logging directory does not exist and will be created." confirm_prompt.run(block=False) else: self._json_logging_button_action() def _csv_logging_button_fired(self): if not os.path.exists(self.directory_name) and not self.csv_logging: confirm_prompt = CallbackPrompt( title="Logging directory creation", actions=[ok_button], callback=self._csv_logging_button_action) confirm_prompt.text = "\nThe selected logging directory does not exist and will be created." confirm_prompt.run(block=False) else: self._csv_logging_button_action() def __enter__(self): return self def __exit__(self, exc_type, exc_value, traceback): self.console_output.close() def __init__(self, link, driver, update, log_level_filter, error=False, cnx_desc=None, json_logging=False, log_dirname=None, override_filename=None, log_console=False, connection_info=None, expand_json=False ): self.error = error self.cnx_desc = cnx_desc self.connection_info = connection_info self.dev_id = cnx_desc self.num_sats_str = EMPTY_STR self.mode = '' self.ins_status_string = "None" self.forwarder = None self.age_of_corrections = '--' self.expand_json = expand_json # if we have passed a logfile, we set our directory to it override_filename = override_filename self.last_status_update_time = 0 self.last_driver_bytes_read = 0 self.driver = driver if log_dirname: self.directory_name = log_dirname if override_filename: override_filename = os.path.join(log_dirname, override_filename) else: self.directory_name = swift_path # Start swallowing sys.stdout and sys.stderr self.console_output = OutputList( tfile=log_console, outdir=self.directory_name) sys.stdout = self.console_output self.console_output.write("Console: " + CONSOLE_VERSION + " starting...") if not error: sys.stderr = self.console_output self.log_level_filter = log_level_filter self.console_output.log_level_filter = str_to_log_level( log_level_filter) try: self.link = link self.link.add_callback(self.print_message_callback, SBP_MSG_PRINT_DEP) self.link.add_callback(self.log_message_callback, SBP_MSG_LOG) self.link.add_callback(self.ext_event_callback, SBP_MSG_EXT_EVENT) self.link.add_callback(self.cmd_resp_callback, SBP_MSG_COMMAND_RESP) self.link.add_callback(self.update_on_heartbeat, SBP_MSG_HEARTBEAT) self.dep_handler = DeprecatedMessageHandler(link) settings_read_finished_functions = [] self.tracking_view = TrackingView(self.link) self.solution_view = SolutionView( self.link, dirname=self.directory_name) self.baseline_view = BaselineView( self.link, dirname=self.directory_name) self.skyplot_view = SkyplotView(self.link, self.tracking_view) self.observation_view = ObservationView( self.link, name='Local', relay=False, dirname=self.directory_name, tracking_view=self.tracking_view) self.observation_view_base = ObservationView( self.link, name='Remote', relay=True, dirname=self.directory_name) self.system_monitor_view = SystemMonitorView(self.link) self.update_view = UpdateView( self.link, download_dir=swift_path, prompt=update, connection_info=self.connection_info) self.imu_view = IMUView(self.link) self.mag_view = MagView(self.link) self.spectrum_analyzer_view = SpectrumAnalyzerView(self.link) settings_read_finished_functions.append( self.update_view.compare_versions) self.networking_view = SbpRelayView(self.link) self.json_logging = json_logging self.csv_logging = False self.first_json_press = True if json_logging: self._start_json_logging(override_filename) self.json_logging = True # we set timer interval to 1200 milliseconds because we expect a heartbeat each second self.timer_cancel = call_repeatedly(1.2, self.check_heartbeat) # Once we have received the settings, update device_serial with # the Swift serial number which will be displayed in the window # title. This callback will also update the header route as used # by the networking view. def update_serial(): mfg_id = None try: self.uuid = self.settings_view.settings['system_info'][ 'uuid'].value mfg_id = self.settings_view.settings['system_info'][ 'serial_number'].value except KeyError: pass if mfg_id: self.device_serial = 'PK' + str(mfg_id) skip_settings_read = False if 'mode' in self.connection_info: if self.connection_info['mode'] == 'file': skip_settings_read = True settings_read_finished_functions.append(update_serial) self.settings_view = SettingsView( self.link, settings_read_finished_functions, skip_read=skip_settings_read) self.update_view.settings = self.settings_view.settings self.python_console_env = { 'send_message': self.link, 'link': self.link, } self.python_console_env.update( self.tracking_view.python_console_cmds) self.python_console_env.update( self.solution_view.python_console_cmds) self.python_console_env.update( self.baseline_view.python_console_cmds) self.python_console_env.update( self.skyplot_view.python_console_cmds) self.python_console_env.update( self.observation_view.python_console_cmds) self.python_console_env.update( self.networking_view.python_console_cmds) self.python_console_env.update( self.system_monitor_view.python_console_cmds) self.python_console_env.update( self.update_view.python_console_cmds) self.python_console_env.update(self.imu_view.python_console_cmds) self.python_console_env.update(self.mag_view.python_console_cmds) self.python_console_env.update( self.settings_view.python_console_cmds) self.python_console_env.update( self.spectrum_analyzer_view.python_console_cmds) except: # noqa import traceback traceback.print_exc() if self.error: os._exit(1)
class MATS2DConduction(MATS2DEval): ''' Elastic Model. ''' implements(IMATSEval) #------------------------------------------------------------------------- # Parameters of the numerical algorithm (integration) #------------------------------------------------------------------------- stress_state = Enum("plane_stress", "plane_strain", "rotational_symetry") #------------------------------------------------------------------------- # Material parameters #------------------------------------------------------------------------- k = Float(1., label="k", desc="conduction", auto_set=False) D_mtx = Property(Array, depends_on='k') @cached_property def _get_D_mtx(self): return self.k * eye(2) # This event can be used by the clients to trigger an action upon # the completed reconfiguration of the material model # changed = Event #------------------------------------------------------------------------- # View specification #------------------------------------------------------------------------- view_traits = View(VSplit(Item('k'), ), resizable=True) #------------------------------------------------------------------------- # Private initialization methods #------------------------------------------------------------------------- #------------------------------------------------------------------------- # Setup for computation within a supplied spatial context #------------------------------------------------------------------------- def new_cntl_var(self): return zeros(3, float_) def new_resp_var(self): return zeros(3, float_) #------------------------------------------------------------------------- # Evaluation - get the corrector and predictor #------------------------------------------------------------------------- def get_corr_pred(self, sctx, eps_app_eng, d_eps, tn, tn1): ''' Corrector predictor computation. @param eps_app_eng input variable - engineering strain ''' # You print the stress you just computed and the value of the apparent # E return dot(self.D_mtx, eps_app_eng), self.D_mtx #------------------------------------------------------------------------- # Subsidiary methods realizing configurable features #------------------------------------------------------------------------- #------------------------------------------------------------------------- # Response trace evaluators #------------------------------------------------------------------------- def get_sig_norm(self, sctx, eps_app_eng): sig_eng, D_mtx = self.get_corr_pred(sctx, eps_app_eng, 0, 0, 0) return array([scalar_sqrt(sig_eng[0]**2 + sig_eng[1]**2)]) # Declare and fill-in the rte_dict - it is used by the clients to # assemble all the available time-steppers. # rte_dict = Trait(Dict) def _rte_dict_default(self): return { 'sig_app': self.get_sig_app, 'eps_app': self.get_eps_app, 'sig_norm': self.get_sig_norm, 'strain_energy': self.get_strain_energy }
class Material(BMCSTreeNode): tree_node_list = List([]) def _tree_node_list_default(self): return [self.omega_fn, ] @on_trait_change('omega_fn_type') def _update_node_list(self): self.tree_node_list = [self.omega_fn] node_name = 'material parameters' E_b = Float(12900.0, MAT=True, label="E_b", desc="bond stiffness", enter_set=True, auto_set=False) gamma = Float(0, MAT=True, label="Gamma", desc="Kinematic hardening modulus", enter_set=True, auto_set=False) K = Float(0, MAT=True, label="K", desc="Isotropic harening", enter_set=True, auto_set=False) tau_bar = Float(5.0, MAT=True, label="Tau_0", desc="yield stress", enter_set=True, auto_set=False) def __init__(self, *args, **kw): super(Material, self).__init__(*args, **kw) self._update_s0() s_0 = Float @on_trait_change('tau_bar,E_b') def _update_s0(self): self.s_0 = self.tau_bar / self.E_b self.omega_fn.s_0 = self.s_0 omega_fn_type = Trait('li', dict(li=LiDamageFn, jirasek=JirasekDamageFn, abaqus=AbaqusDamageFn, FRP=FRPDamageFn), MAT=True, ) @on_trait_change('omega_fn_type,s_0') def _reset_omega_fn(self): self.omega_fn = self.omega_fn_type_(s_0=self.s_0) omega_fn = Instance(IDamageFn, report=True) def _omega_fn_default(self): return LiDamageFn() view = View( Group( VSplit( VGroup( Group( Item('E_b', full_size=True, resizable=True), Item('tau_bar'), show_border=True, label='Bond Stiffness and yield stress' ), Group( Item('gamma', full_size=True, resizable=True), Item('K'), show_border=True, label='Hardening parameters' ), ), Item('omega_fn_type', full_size=True, resizable=True), Group( UItem('omega_fn@', full_size=True, resizable=True), show_border=True, label='Damage function' ), ) ) ) tree_view = view
class MATSCalibDamageFn(MATSExplore): ''' Fitting algorithm for the damage function of the quasi-ductile anisotropic material model. The algorithm uses the TLoop instance to proceed step by step with the computation. The value of the damage function for the time step t_n is identified iteratively by adjusting the values and evaluating the corresponding equilibrated stresses. The control parameters of the algorithm are: @param step_size: time step for fitting the damage parameter. @param tmax: end time for fitting, it might be also be set implicitly for integrity = 1 - full damage of the material. ''' # store the fitted 'PhiFn' in the data base, i.e. 'CCSUniteCell' store_fitted_phi_fn = Bool(True) # default settings are overloaded with settings specified in 'ec_config' max_eps = Property(Float) def _get_max_eps(self): # return 0.007 # set explicit value when calibration is aborted (mean # value of strain) return self.mfn_line_array_target.xdata[-1] n_steps = Int(1) log = Bool(False) # TLine parameter # KMAX = Int tolerance = Float RESETMAX = Float step_size = Property(Float, depends_on='max_eps,n_steps') @cached_property def _get_step_size(self): print('step_size = ', self.max_eps / self.n_steps) return self.max_eps / self.n_steps def run_through(self): '''Run the computation without fitting from the start to the end ''' self.tloop.tline.max = self.tmax self.tloop.tline.step = self.step_size self.tloop.eval() print('ending time', self.tloop.t_n1) # show the response def run_step_by_step(self): '''Run the computation step by step from the start to the end ''' n_steps = int(self.tmax / self.step_size) self.tloop.tline.step = self.step_size current_time = 0. tmax = 0. for i in range(n_steps): print('STEP', i) self.run_one_step() def run_trial_step(self): '''Run the computation one step starting from the current time t_n to iterate the value for phi_new which gives a fit with macroscopic stress curve. NOTE: The trial step does not update 'U_n' or 't_n'! ''' if self.log: print('--------- run trial step: --------- ') if len(self.tloop.U_n) == 0: current_U_n = self.tloop.tstepper.new_cntl_var() print('U_n = None: tloop.tstepper.new_cntl_var()', self.tloop.tstepper.new_cntl_var()) else: current_U_n = self.tloop.U_n[:] current_time = self.tloop.t_n self.run_one_step() # reset the current time back self.tloop.t_n = current_time self.tloop.U_n[:] = current_U_n[:] if self.log: print('--------- end of trial step --------- ') self.tloop.tstepper.sctx.update_state_on = False def run_one_step(self): '''Run the computation one step starting from the current time t_n with the iterated value for phi_new in order to update TLoop and save the new phi value in the array ydata of PhiFnGeneral NOTE: The calculated step does update 'U_n' or 't_n'! ''' self.tloop.tline.step = self.step_size current_time = self.tloop.t_n tmax = current_time + self.step_size self.tloop.tline.max = tmax self.tloop.eval() self.update_e_max_value_new = True #-------------------------------------------------- # Data source for calibration within simdb #-------------------------------------------------- ex_run = Instance(ExRun) composite_tensile_test = Property def _get_composite_tensile_test(self): return self.ex_run.ex_type composite_cross_section = Property def _get_composite_cross_section(self): return self.composite_tensile_test.ccs def get_target_data_exdb_tensile_test(self): '''Use the data from the ExDB ''' ctt = self.composite_tensile_test # save 'sig_eps_arr' in directory "/simdb/simdata/mats_calib_damage_fn" simdata_dir = os.path.join(simdb.simdata_dir, 'mats_calib_damage_fn') if os.path.isdir(simdata_dir) == False: os.makedirs(simdata_dir) ctt_key = str(self.composite_tensile_test.key) filename = os.path.join(simdata_dir, 'eps-sig-arr_' + ctt_key + '.csv') xdata, ydata = ctt.eps_c_interpolated_smoothed[:, None], \ ctt.sig_c_interpolated_smoothed[:, None] eps_sig_arr = np.hstack([xdata, ydata]) print('eps_sig_arr') np.savetxt(filename, eps_sig_arr, delimiter=';') print('eps-sig-data saved to file %s' % (filename)) # smoothed data without jumps with interpolated starting point in the # origin return ctt.eps_c_interpolated_smoothed, ctt.sig_c_interpolated_smoothed # return ctt.eps_c_interpolated, ctt.sig_c_interpolated # original data without jumps with interpolated starting point in the origin # return ctt.eps_ironed, ctt.sig_c_ironed # original data without smoothing (without jumps) # return ctt.eps_smooth, ctt.sig_c_smooth #smoothed data #-------------------------------------------------- # interpolation function for fitting data: #-------------------------------------------------- mfn_line_array_target = Property(Instance(MFnLineArray), depends_on='ex_run') @cached_property def _get_mfn_line_array_target(self): xdata, ydata = self.get_target_data_exdb_tensile_test() print('xdata[-1]', xdata[-1]) return MFnLineArray(xdata=xdata, ydata=ydata) fitted_phi_fn = Instance(MFnLineArray) #--------------------------------------------------------------- # PLOT OBJECT #------------------------------------------------------------------- figure = Instance(Figure) def _figure_default(self): figure = Figure(facecolor='white') figure.add_axes([0.12, 0.13, 0.85, 0.74]) return figure data_changed = Event def init(self): #-------------------------------------------------- # for fitting use 'General'-function for 'phi_fn': #-------------------------------------------------- # The value pair for the piecewise linear definition # of 'phi_fn' value consists of current strain and the # iterated 'phi_value'. The microplanes with a lower # microplane strain level use an interpolated value # for 'phi' self.fitted_phi_fn = self.dim.mats_eval.phi_fn.mfn self.fitted_phi_fn.xdata = [0] self.fitted_phi_fn.ydata = [1] self.fitted_phi_fn.data_changed = True # initialize TLoop parameters: self.tloop.setup() self.tloop.tstepper.sctx.mats_state_array[:] = 0.0 self.tloop.U_n[:] = 0.0 self.tloop.rtrace_mngr.clear() self.tloop.verbose_iteration = False self.tloop.verbose_load_step = False self.tloop.verbose_time = False # set TLine parameters self.tloop.tline.KMAX = self.KMAX self.tloop.tline.tolerance = self.tolerance self.tloop.tline.RESETMAX = self.RESETMAX # store trial step data in the lists if trial steps are to be stored # for the plotting method 'plot_trail_steps' # rec_trial_steps = True phi_trial_list_i = [] sig_trial_list_i = [] phi_trial_list_n = [] sig_trial_list_n = [] def get_lack_of_fit(self, phi_trial): '''Return the difference between the macroscopic stress calculated based on the value of phi_trial (damage at the next step) and the macroscopic stress defined as target data (=fitting curve) ''' if self.log: print('\n') print("#'get_lack_of_fit' for the trial value # START") print(' phi_trial = ', phi_trial) # value of the principle macroscopic strain corresponds to control # variable current_time = self.tloop.t_n if self.log: print(' current_time = ', current_time) print(' step_size = ', self.step_size) # ------------------------------------ # add new pair in fitted_phi_fn # ------------------------------------ # consisting of 'e_max_value_new' and 'phi_trial' x = np.hstack( [self.fitted_phi_fn.xdata[:], current_time + self.step_size]) y = np.hstack([self.fitted_phi_fn.ydata[:], phi_trial]) self.fitted_phi_fn.set(xdata=x, ydata=y) self.fitted_phi_fn.data_changed = True # ------------------------------------ # get state array before trial: # ------------------------------------ mats_state_array_old = copy(self.tloop.tstepper.sctx.mats_state_array) # ------------------------------------ # run trial step: # ------------------------------------ if self.log: print(' reset current_U_n =', self.tloop.U_n) print('CURRENT PHI', self.dim.mats_eval.phi_fn.mfn.ydata) # try the next equilibrium self.run_trial_step() # ------------------------------------ # reset mats_state_array: # ------------------------------------ # Note: the material state array (i.e. the maximum microstrains) are # updated within the iterations of each trial step, therefore a reset # is necessary in order to start each trial step with the same state # variables self.tloop.tstepper.sctx.mats_state_array[:] = mats_state_array_old[:] if self.log: print(' reset state array') # ------------------------------------ # remove trial value in fitted_phi_fn # ------------------------------------ x = self.fitted_phi_fn.xdata[:-1] y = self.fitted_phi_fn.ydata[:-1] self.fitted_phi_fn.set(xdata=x, ydata=y) self.fitted_phi_fn.data_changed = True # ------------------------------------ # get the lack of fit # ------------------------------------ # get calculated value for 'sig_app' based on the current value of 'phi_trial': # and evaluate the difference between the obtained stress and the # measured response self.tloop.rtrace_mngr.rtrace_bound_list[0].redraw() sig_app_trial = self.tloop.rtrace_mngr.rtrace_bound_list[ 0].trace.ydata[-1] # get corresponding value from the target data: sig_app_target = self.mfn_line_array_target.get_value(current_time + self.step_size) # absolut error: lack_of_fit_absolut = sig_app_trial - sig_app_target # relative error: lack_of_fit_relative = lack_of_fit_absolut / sig_app_target if self.log: print(' sig_app_trial ', sig_app_trial) print(' sig_app_target', sig_app_target) print(' lack_of_fit_absolute ', lack_of_fit_absolut) print(' lack_of_fit_relative ', lack_of_fit_relative) print('# get_lack_of_fit # END ') if self.rec_trial_steps: # store all trial values of 'phi_trail' and 'sig_app_trail' within each iteration to a global list # self.phi_trial_list_i.append(phi_trial) self.sig_trial_list_i.append(sig_app_trial) return lack_of_fit_relative param_key = Str('') phi_max_factor = Float(1.0) xtol = Float(1e-6, label='lack-of-fit tolerance') def fit_response(self): '''iterate phi_trial in each incremental step such that the lack of fit between the calculated stress and the target curve is smaller then xtol defined in function 'brentq'. NOTE: the method 'get_lack_of_fit' returns the relative error. ''' self.tloop.reset() phi_old = 1.0 # map the array dimensions to the plot axes # figure = self.figure axes = figure.axes[0] print('n_steps', self.n_steps) for n in range(self.n_steps): axes.clear() phi_new = phi_old # use scipy-functionality to get the iterated value of phi_new # If the trial value calculated with phi_trial = phi_old # is smaller then target value get_lack_of_fit has no sign change # for phi_trial = phi_old and phi_trial = 0. which is a requirement # for the function call 'brentq'. In this case the old value # for phi_trial is used and tloop moves on one step try: # The method brentq has optional arguments such as # 'xtol' - absolut error (default value = 1.0e-12) # 'rtol' - relative error (not supported at the time) # 'maxiter' - maximum numbers of iterations used # # Here xtol is used to specify the allowed RELATIVE error! # therefore the relative lack of fit is returned in # method 'get_lack_of_fit' _xtol = self.xtol phi_max = min(1.0, phi_old * self.phi_max_factor) phi_min = phi_old * 0.2 # 0.0 # phi_old * 0.3 phi_new = brentq(self.get_lack_of_fit, phi_min, phi_max, xtol=_xtol) # @todo: check if 'brenth' gives better fitting results; faster? # phi_new = brenth( self.get_lack_of_fit, 0., phi_old ) print('(#) n = ', n, phi_new, phi_max, phi_old, phi_old - phi_new) except ValueError: if self.log: lof_0 = self.get_lack_of_fit(0.) lof_phi_old = self.get_lack_of_fit(phi_old) print('No sign change between get_lack_of_fit(phi_old) = ', lof_phi_old, ' and ') print('get_lack_of_fit(0.) = ', lof_0) print('Use old value for phi_trial. phi_old = ', phi_old) else: print('(!) n = ', n, phi_new, phi_max, phi_old, phi_old - phi_new) phi_new = phi_old # current time corresponds to the current strain applied # current_time = self.tloop.t_n # replace old 'phi_value' with iterated value: # phi_old = phi_new # get mats_state_array: # mats_state_array = copy(self.tloop.tstepper.sctx.mats_state_array) # update phi_data: # x = np.hstack( [self.fitted_phi_fn.xdata[:], current_time + self.step_size]) y = np.hstack([self.fitted_phi_fn.ydata[:], phi_new]) axes.plot(x, y, color='blue', linewidth=2) self.data_changed = True self.fitted_phi_fn.set(xdata=x, ydata=y) self.fitted_phi_fn.data_changed = True # run one step with the iterated value for phi in order to # update the state array and to move forward one step: if self.log: print('\n') print('### run_one_step ###') print('### step', n, '###') print('### current time:', current_time) if self.rec_trial_steps: # add entries of the iterations ('i') in the current step ('n') # (yields a list of lists) # self.phi_trial_list_n.append(self.phi_trial_list_i) self.sig_trial_list_n.append(self.sig_trial_list_i) # delete the entries of the iterations ('i') in the last step ('n') # and fill it with the iterations of the next step ('n+1') # self.phi_trial_list_i = [] self.sig_trial_list_i = [] self.run_one_step() # print '(g%)' %(n) self.fitted_phi_fn.changed = True def store(self): mats_key = self.dim.mats_eval.__class__.__name__ ctt_key = str(self.composite_tensile_test.key) if self.store_fitted_phi_fn: print( "stored 'fitted_phi_fn' in CCSUnitCell with material model %s and calibration test %s" % (mats_key, ctt_key)) print('ctt_key + self.param_key', ctt_key + self.param_key) self.composite_cross_section.set_param( mats_key, ctt_key + self.param_key, # self.composite_cross_section.set_param(mats_key, # ctt_key, copy(self.fitted_phi_fn)) # save 'sig_eps_arr' in directory # "/simdb/simdata/mats_calib_damage_fn" simdata_dir = os.path.join(simdb.simdata_dir, 'mats_calib_damage_fn') if os.path.isdir(simdata_dir) == False: os.makedirs(simdata_dir) ctt_key = str(self.composite_tensile_test.key) filename = os.path.join( simdata_dir, 'eps-phi-arr_' + ctt_key + self.param_key + '.csv') xdata, ydata = self.fitted_phi_fn.xdata[:, None], self.fitted_phi_fn.ydata[:, None] eps_phi_arr = np.hstack([xdata, ydata]) np.savetxt(filename, eps_phi_arr, delimiter=';') print('eps-phi-data saved to file %s' % (filename)) format_ticks = Bool(False) def plot_trial_steps(self): '''Plot target (sig-eps-curve of the tensile test) and trial curves and corresponding phi function together with trail steps from the iteration process. NOTE: the global variable 'rec_trial_steps' must be set to 'True' in order to store the iteration values within the global variables 'phi_trial_list_n' and 'sig_trial_list_n' n - index of the time steps to be considered i - index of the iteration steps performed in order to fit the target curve ''' #------------------------------------------------------------------- # configure the style of the font to be used for labels and ticks #------------------------------------------------------------------- # from matplotlib.font_manager import FontProperties font = FontProperties() # font.serif : Times, Palatino, New Century Schoolbook, Bookman, Computer Modern Roman # font.sans-serif : Helvetica, Avant Garde, Computer Modern Sans serif # font.cursive : Zapf Chancery # font.monospace : Courier, Computer Modern Typewriter font.set_name('Script MT') # name = ['Times New Roman', 'Helvetica', 'Script MT'] #? font.set_family('serif') # family = ['serif', 'sans-serif', 'cursive', 'fantasy', 'monospace'] font.set_style('normal') # style = ['normal', 'italic', 'oblique'] font.set_size('small') # size = ['xx-small', 'x-small', 'small', 'medium', 'large', 'x-large', 'xx-large', '11'] font.set_variant('normal') # variant= ['normal', 'small-caps'] font.set_weight('medium') # weight = ['light', 'normal', 'medium', 'semibold', 'bold', 'heavy', 'black'] #------------------------------------------------------------------- p.figure(facecolor='white', dpi=600, figsize=(8, 6)) # white background # time list corresponding to the specified numbers of steps and step size # step_list = [n * self.step_size for n in range(self.n_steps + 1)] # get list of lists containing the trial values of 'sig_app' and 'phi_trail' # the lists are defined as global variables of 'MATSCalibDamageFn' and are filled # within the iteration process when the method 'get_lack_of_fit" is called # phi_trial_list_n = [[1.]] + self.phi_trial_list_n sig_trial_list_n = [[0.]] + self.sig_trial_list_n xrange = 10. # plotting range for strain [mm/m] yrange = 15. # plotting range for stress [MPa] for n in range(self.n_steps): for i in range(len(phi_trial_list_n[n + 1])): x = np.array([step_list[n], step_list[n + 1]]) eps = 1000. * x # plot strains in permil on the x-axis #-------------------------------------- # sig-eps trial #-------------------------------------- # plot the numerically calculated sig-eps-curve (tensile test) # (with trial steps) # sig_trail = np.array( [sig_trial_list_n[n][-1], sig_trial_list_n[n + 1][i]]) p.subplot(222) p.plot(eps, sig_trail, color='k', linewidth=1) p.xlabel(r'strain $\varepsilon$ [1E-3]', fontproperties=font) p.ylabel('stress $\sigma$ [MPa]', fontproperties=font) if self.format_ticks: # format ticks for plot p.axis([0, xrange, 0., yrange], fontproperties=font) locs, labels = p.xticks() p.xticks(locs, ["%.0f" % x for x in locs], fontproperties=font) locs, labels = p.yticks() p.yticks(locs, ["%.0f" % x for x in locs], fontproperties=font) #-------------------------------------- # phi_trail #-------------------------------------- # plot the fitted phi-function # (with trial steps) # p.subplot(224) phi_trail = np.array( [phi_trial_list_n[n][-1], phi_trial_list_n[n + 1][i]]) p.plot(eps, phi_trail, color='k', linewidth=1) p.xlabel(r'strain $\varepsilon$ [1E-3]', fontproperties=font) p.ylabel('integrity $\phi$ [-]', fontproperties=font) if self.format_ticks: # format ticks for plot p.yticks([0, 0.2, 0.4, 0.6, 0.8, 1.0]) p.axis([0, xrange, 0., 1.]) locs, labels = p.xticks() p.xticks(locs, ["%.0f" % x for x in locs], fontproperties=font) locs, labels = p.yticks() p.yticks(locs, ["%.1f" % x for x in locs], fontproperties=font) #-------------------------------------- # sig-eps target #-------------------------------------- # plot the sig-eps-target curve (tensile test) # p.subplot(221) eps = 1000. * self.mfn_line_array_target.xdata[:-1] sig_target = self.mfn_line_array_target.ydata[:-1] p.plot(eps, sig_target, color='black', linewidth=1) p.xlabel(r'strain $\varepsilon$ [1E-3]', fontproperties=font) p.ylabel('stress $\sigma$ [MPa]', fontproperties=font) if self.format_ticks: # format ticks for plot p.axis([0, xrange, 0., yrange]) locs, labels = p.xticks() p.xticks(locs, ["%.0f" % x for x in locs], fontproperties=font) locs, labels = p.yticks() p.yticks(locs, ["%.0f" % x for x in locs], fontproperties=font) #-------------------------------------- # phi_trail (final) #-------------------------------------- # plot the corresponding fitted phi-function # (without trial steps) # p.subplot(223) eps = 1000. * self.fitted_phi_fn.xdata[:-1] phi_fn = self.fitted_phi_fn.ydata[:-1] p.plot(eps, phi_fn, color='black', linewidth=1) p.xlabel(r'strain $\varepsilon$ [1E-3]', fontproperties=font) p.ylabel('integrity $\phi$ [-]', fontproperties=font) if self.format_ticks: # format ticks for plot p.yticks([0, 0.2, 0.4, 0.6, 0.8, 1.0]) p.axis([0, xrange, 0., 1.]) locs, labels = p.xticks() p.xticks(locs, ["%.0f" % x for x in locs], fontproperties=font) locs, labels = p.yticks() p.yticks(locs, ["%.1f" % x for x in locs], fontproperties=font) # save figure with calibration process in directory # "/simdb/simdata/lcc_table/output_images/save_fig_to_file.png" simdata_dir = os.path.join(simdb.simdata_dir, 'mats_calib_damage_fn') if os.path.isdir(simdata_dir) == False: os.makedirs(simdata_dir) ctt_key = self.test_key filename = os.path.join(simdata_dir, ctt_key + self.param_key + '.pdf') p.savefig(filename) print('plot_trail_steps.png saved to file %s' % (filename)) filename = os.path.join(simdata_dir, ctt_key + self.param_key + '.png') p.savefig(filename, dpi=600) print('plot_trail_steps.png saved to file %s' % (filename)) p.show() test_key = Property def _get_test_key(self): return str(self.composite_tensile_test.key) #------------------------------------------------------------------------- # User interaction #------------------------------------------------------------------------- toolbar = ToolBar(Action( name="Run Calibration", tooltip='Run damage function calibration for the current parameters', image=ImageResource('kt-start'), action="run_calibration"), image_size=(22, 22), show_tool_names=False, show_divider=True, name='calibration_toolbar') traits_view = View( HSplit( Item('ex_run@', show_label=False), VSplit( Item('dim@', id='mats_calib_damage_fn.run.split', dock='tab', resizable=True, label='experiment run', show_label=False), id='mats_calib_damage_fn.mode_plot_data.vsplit', dock='tab', ), VSplit( Group( Item('figure', editor=MPLFigureEditor(), resizable=True, show_label=False), id='mats_calib_damage_fn.plot_sheet', label='fitted damage function', dock='tab', ), id='mats_calib_damage_fn.plot.vsplit', dock='tab', ), id='mats_calib_damage_fn.hsplit', dock='tab', ), # menubar = self.default_menubar(), resizable=True, toolbar=toolbar, handler=MATSCalibDamageFnController(), title='Simvisage: damage function calibration', id='mats_calib_damage_fn', dock='tab', buttons=[OKButton, CancelButton], height=0.8, width=0.8)
class RTraceDomainInteg(RTraceDomain): ''' Trace encompassing the whole spatial domain. ''' fets_eval = Property def _get_fets_eval(self): return self.sd.fets_eval var_eval = Property def _get_var_eval(self): return self.sd.dots.rte_dict.get(self.var, None) def bind(self): ''' Locate the evaluators ''' pass def setup(self): ''' Setup the spatial domain of the tracer ''' if self.var_eval == None: self.skip_domain = True integ_val = Array(desc='Integral over the domain') def add_current_values(self, sctx, U_k, *args, **kw): ''' Invoke the evaluators in the current context for the specified control vector U_k. ''' if self.var_eval == None: return # Get the domain points # TODO - make this more compact. The element list is assumed to be uniform # so that all element arrays have the same shape. Thus, use slices and vectorized # evaluation to improve the performance sd = self.sd sctx.fets_eval = self.fets_eval field = [] dim_slice = self.fets_eval.dim_slice e_arr_size = self.fets_eval.get_state_array_size() state_array = self.sd.dots.state_array # setup the result array integ_val = zeros((1, ), dtype='float_') for e_id, e in enumerate(sd.elements): sctx.elem_state_array = state_array[e_id * e_arr_size:(e_id + 1) * e_arr_size] sctx.X = e.get_X_mtx() sctx.x = e.get_x_mtx() sctx.elem = e sctx.e_id = e_id field_entry = [] i = 0 for ip, iw in zip(self.fets_eval.ip_coords, self.fets_eval.ip_weights): m_arr_size = self.fets_eval.m_arr_size sctx.mats_state_array = sctx.elem_state_array\ [i * m_arr_size: (i + 1) * m_arr_size] sctx.loc = ip sctx.r_pnt = ip sctx.p_id = i # TODO:check this J_det = self.fets_eval.get_J_det(sctx.r_pnt, sctx.X) si = self.var_eval(sctx, U_k, *args, **kw) iv = si * iw * J_det integ_val += iv i += 1 self.integ_val = integ_val view = View(HSplit( VSplit( VGroup('var', 'idx'), VGroup('record_on', 'clear_on'), Item('integ_val', style='readonly', show_label=False), ), ), resizable=True)
class BCDof(BMCSTreeNode): ''' Implements the IBC functionality for a constrained dof. Example of a complex constraint: For example the specification BCDof( var = 'f', value = 0., dof = 2, link_dofs = [3,4], link_coeffs = [0.5,0.5] ) means that U[2] = 0.5*U[3] + 0.5*U[4] Note that U[2] is non-zero and is regarded as a natural boundary condition. On the the other hand, the specification cos(alpha) * U[2] + sin(slpha) * U[3] = 0.4 can be expressed as for U[2] as U[2] = - sin(alpha) / cos(alpha) * U[3] + 0.4 / cos(alpha) so that the corresponding BCDof specification has the form BCDof( var = 'u', value = 0.4 / cos(alpha), dof = 2, link_dofs = [3], link_coeffs = [-sin(alpha)/cos(alpha) ] ) ''' node_name = 'boundary condition' var = Enum('u', 'f', 'eps', 'sig', label='Variable', BC=True) dof = Int( label='Degree of freedom', BC=True, ) value = Float( label='Value', BC=True, ) link_dofs = List(Int, BC=True, label='Linear dependencies', tooltip='Degrees of freedom linked\n' 'with the current by link coefficients') ''' List of dofs that determine the value of the current dof If this list is empty, then the current dof is prescribed. Otherwise, the dof value is given by the linear combination of DOFs in the list (see the example below) ''' link_coeffs = List(Float, BC=True, label='Link coefficients', tooltip='Multipliers for linear combination\n' 'equation') ''' Coefficients of the linear combination of DOFs specified in the above list. ''' time_function = Instance(TimeFunction, ()) ''' Time function prescribing the evolution of the boundary condition. ''' def _time_function_default(self): return TFMonotonic() def is_essential(self): return self.var == 'u' def is_linked(self): return self.link_dofs != [] def is_constrained(self): ''' Return true if a DOF is either explicitly prescribed or it depends on other DOFS. ''' return self.is_essential() or self.is_linked() def is_natural(self): return self.var == 'f' or self.var == 'eps' or self.var == 'sig' def get_dofs(self): return [self.dof] def setup(self, sctx): ''' Locate the spatial context. ''' return _constraint = Any def register(self, K): '''Register the boundary conditions in the equation system. ''' if self.is_essential(): a = self.dof # affected dof alpha = np.array(self.link_coeffs, np.float_) n_ix_arr = np.array(list(self.link_dofs), dtype=int) self._constraint = K.register_constraint(a=a, u_a=self.value, alpha=alpha, ix_a=n_ix_arr) def apply(self, step_flag, sctx, K, R, t_n, t_n1): ''' According to the kind specification add the ''' if self.is_essential(): # The displacement is applied only in the first iteration step!. # if step_flag == 'predictor': ua_n = self.value * float(self.time_function(t_n)) ua_n1 = self.value * float(self.time_function(t_n1)) u_a = ua_n1 - ua_n elif step_flag == 'corrector': u_a = 0 self._constraint.u_a = u_a elif self.is_natural(): R_a = self.value * float(self.time_function(t_n1)) # Add the value to the proper equation. # # if a is involved in another essential constraint, redistribute # it according to the link coefficients infolved in that constraint! # R[self.dof] += R_a if self.is_linked(): # Prepare the indexes and index arrays # n = self.link_dofs # constraining dofs n_ix = np.ix_(n) # constraining dofs as array # Distribute the load contribution to the proportionally loaded dofs # alpha = np.array(self.link_coeffs, np.float_) R[n_ix] += alpha.transpose() * R_a tree_view = View( VGroup( VSplit( VGroup( Item( 'var', full_size=True, resizable=True, tooltip='Type of variable: u - essential, f- natural'), Item('dof', tooltip='Number of the degree of freedom'), Item('value', tooltip='Value of the boundary condition to\n' 'be multiplied with the time function'), ), UItem('time_function@', full_size=True, springy=True, resizable=True)), )) traits_view = tree_view
class SwiftConsole(HasTraits): """Traits-defined Swift Console. link : object Serial driver update : bool Update the firmware log_level_filter : str Syslog string, one of "ERROR", "WARNING", "INFO", "DEBUG". skip_settings : bool Don't read the device settings. Set to False when the console is reading from a network connection only. """ link = Instance(sbpc.Handler) console_output = Instance(OutputList()) python_console_env = Dict device_serial = Str('') a = Int b = Int tracking_view = Instance(TrackingView) solution_view = Instance(SolutionView) baseline_view = Instance(BaselineView) observation_view = Instance(ObservationView) sbp_relay_view = Instance(SbpRelayView) observation_view_base = Instance(ObservationView) system_monitor_view = Instance(SystemMonitorView) settings_view = Instance(SettingsView) update_view = Instance(UpdateView) log_level_filter = Enum(list(SYSLOG_LEVELS.itervalues())) paused_button = SVGButton( label='', tooltip='Pause console update', toggle_tooltip='Resume console update', toggle=True, filename=os.path.join(os.path.dirname(__file__), 'images', 'iconic', 'pause.svg'), toggle_filename=os.path.join(os.path.dirname(__file__), 'images', 'iconic', 'play.svg'), width=8, height=8) clear_button = SVGButton(label='', tooltip='Clear console buffer', filename=os.path.join(os.path.dirname(__file__), 'images', 'iconic', 'x.svg'), width=8, height=8) view = View(VSplit( Tabbed(Item('tracking_view', style='custom', label='Tracking'), Item('solution_view', style='custom', label='Solution'), Item('baseline_view', style='custom', label='Baseline'), VSplit( Item('observation_view', style='custom', show_label=False), Item('observation_view_base', style='custom', show_label=False), label='Observations', ), Item('settings_view', style='custom', label='Settings'), Item('update_view', style='custom', label='Firmware Update'), Tabbed(Item('system_monitor_view', style='custom', label='System Monitor'), Item('sbp_relay_view', label='SBP Relay', style='custom', show_label=False), Item('python_console_env', style='custom', label='Python Console', editor=ShellEditor()), label='Advanced', show_labels=False), show_labels=False), VGroup( HGroup( Spring(width=4, springy=False), Item('paused_button', show_label=False, width=8, height=8), Item('clear_button', show_label=False, width=8, height=8), Item('', label='Console Log', emphasized=True), Spring(), UItem( 'log_level_filter', style='simple', padding=0, height=8, show_label=True, tooltip= 'Show log levels up to and including the selected level of severity.\nThe CONSOLE log level is always visible.' ), ), Item( 'console_output', style='custom', editor=InstanceEditor(), height=0.3, show_label=False, ), )), icon=icon, resizable=True, width=1000, height=600, handler=ConsoleHandler(), title=CONSOLE_TITLE) def print_message_callback(self, sbp_msg, **metadata): try: encoded = sbp_msg.payload.encode('ascii', 'ignore') for eachline in reversed(encoded.split('\n')): self.console_output.write_level( eachline, str_to_log_level(eachline.split(':')[0])) except UnicodeDecodeError: print "Critical Error encoding the serial stream as ascii." def log_message_callback(self, sbp_msg, **metadata): try: encoded = sbp_msg.text.encode('ascii', 'ignore') for eachline in reversed(encoded.split('\n')): self.console_output.write_level(eachline, sbp_msg.level) except UnicodeDecodeError: print "Critical Error encoding the serial stream as ascii." def ext_event_callback(self, sbp_msg, **metadata): e = MsgExtEvent(sbp_msg) print 'External event: %s edge on pin %d at wn=%d, tow=%d, time qual=%s' % ( "Rising" if (e.flags & (1 << 0)) else "Falling", e.pin, e.wn, e.tow, "good" if (e.flags & (1 << 1)) else "unknown") def _paused_button_fired(self): self.console_output.paused = not self.console_output.paused def _log_level_filter_changed(self): """ Takes log level enum and translates into the mapped integer. Integer stores the current filter value inside OutputList. """ self.console_output.log_level_filter = str_to_log_level( self.log_level_filter) def _clear_button_fired(self): self.console_output.clear() def __init__(self, link, update, log_level_filter, skip_settings=False): self.console_output = OutputList() self.console_output.write("Console: starting...") sys.stdout = self.console_output sys.stderr = self.console_output self.log_level_filter = log_level_filter self.console_output.log_level_filter = str_to_log_level( log_level_filter) try: self.link = link self.link.add_callback(self.print_message_callback, SBP_MSG_PRINT_DEP) self.link.add_callback(self.log_message_callback, SBP_MSG_LOG) self.link.add_callback(self.ext_event_callback, SBP_MSG_EXT_EVENT) settings_read_finished_functions = [] self.tracking_view = TrackingView(self.link) self.solution_view = SolutionView(self.link) self.baseline_view = BaselineView(self.link) self.observation_view = ObservationView(self.link, name='Rover', relay=False) self.observation_view_base = ObservationView(self.link, name='Base', relay=True) self.sbp_relay_view = SbpRelayView(self.link) self.system_monitor_view = SystemMonitorView(self.link) self.update_view = UpdateView(self.link, prompt=update) settings_read_finished_functions.append( self.update_view.compare_versions) # Once we have received the settings, update device_serial with the Piksi # serial number which will be displayed in the window title def update_serial(): serial_string = self.settings_view.settings['system_info'][ 'serial_number'].value self.device_serial = 'PK%04d' % int(serial_string) settings_read_finished_functions.append(update_serial) self.settings_view = \ SettingsView(self.link, settings_read_finished_functions, hide_expert = not args.expert, skip=skip_settings) self.update_view.settings = self.settings_view.settings self.python_console_env = { 'send_message': self.link, 'link': self.link, } self.python_console_env.update( self.tracking_view.python_console_cmds) self.python_console_env.update( self.solution_view.python_console_cmds) self.python_console_env.update( self.baseline_view.python_console_cmds) self.python_console_env.update( self.observation_view.python_console_cmds) self.python_console_env.update( self.sbp_relay_view.python_console_cmds) self.python_console_env.update( self.system_monitor_view.python_console_cmds) self.python_console_env.update( self.update_view.python_console_cmds) self.python_console_env.update( self.settings_view.python_console_cmds) except: import traceback traceback.print_exc()
class Model( HasTraits ): """Model for updating Tree, performs file searches, reads from databases instantiates material models.""" # Sort files and DB entries SORT = Bool(True) # XXX NOT ON VIEW YET... REVERSE = Bool(False) materials_trees = Instance( MaterialList ) #An instance of the tree current_selection = Any() #Used for navigating the table # File and database manager objects FileSearch = Instance(LiveSearch,()) FileDic = Dict #Maintains object representations for files # All material categories ( see update_tree() ) nonmetals = List(IAdapter) metals = List(IAdapter) soprafiles = List(IAdapter) riinfodb = List(IAdapter) nkfiles = List(IAdapter) sopradb = List(IAdapter) xnkdb = List(IAdapter) def __init__(self, *args, **kwds): super(HasTraits, self).__init__(*args, **kwds) self.update_tree() #Necessary to make defaults work def _current_selection_changed(self): # Parse yaml file metadata only when selected to save time try: self.current_selection.read_file_metadata() except Exception: pass # Default Database Files def _sopradb_default(self): """ Read all files from sopra database""" out = [] if config.USESOPRA: for f in os.listdir(sopra_dir): out.append(SopraFileAdapter(file_path = op.join(sopra_dir, f))) return out def _riinfodb_default(self): """ Read all files form RI_INFO database. """ out = [] if config.USERIINFO: for d, folders, files in os.walk(riinfo_dir): if files: for f in files: obj = YamlAdapter(file_path = op.join(d, f), source = 'RIInfo', #<--- CHANGE ADAPTER SOURCE!!! root=riinfo_dir) #THIS WILL SORT out.append(obj) return out def _xnkdb_default(self): """ Read all files from sopra database""" out = [] if config.USESOPRA: for f in os.listdir(XNK_dir): out.append(XNKFileAdapter(file_path = op.join(XNK_dir, f))) return out def _adaptersort(self, thelist): """ Sort a list of IAdapter object by name if self.SORT """ if self.SORT: thelist.sort(key=lambda x: x.name, reverse=self.REVERSE) return thelist # Non-Metals Models ------ def _nonmetals_default(self): return [ AirAdapter(), BasicAdapter(), ConstantAdapter(), DispwaterAdapter(), CauchyAdapter(), SellmeirAdapter() ] # Metal Models Models ------ def _metals_default(self): return [ DrudeBulkAdapter() ] # Files managed by dictionary here @on_trait_change('FileSearch.my_files') def update_file_dic(self): '''Updates file dic, and since my_files won't update redundantly, the dictionary also won't gather duplicate entries''' for afile in self.FileSearch.my_files: # Fit new files to appropriate adapter full_path = afile.full_name base_name = afile.base_name extension = afile.file_ext file_id = afile.fileclass #Specifies which filetype trait object this file should fit (Sopra) if file_id=='XNK': self.FileDic[afile] = XNKFileAdapter(file_path=full_path) elif file_id == 'XNK_csv': self.FileDic[afile] = XNKFileAdapter(file_path=full_path, csv=True) elif file_id=='Sopra': self.FileDic[afile] = SopraFileAdapter(file_path=full_path) else: raise Exception('What kind of file id is %s' % file_id) # When entries in 'my_files' are removed, this syncs the dictionary for key in list(self.FileDic.keys()): if key not in self.FileSearch.my_files: del self.FileDic[key] self.soprafiles= [self.FileDic[k] for k in list(self.FileDic.keys()) if k.fileclass =='Sopra'] # nk files can be csv too, so have this workaround self.nkfiles= [self.FileDic[k] for k in list(self.FileDic.keys()) if k.fileclass in ['XNK', 'XNK_csv']] self.update_tree() def update_tree(self): """ Updates the entire tree """ self.materials_trees = MaterialList( #Composite and Nano materials #------------ NanoMaterials = [ nma.NanoSphereAdapter(), nma.NanoSphereShellAdapter(), nma.DoubleNanoAdapter() ], CompMaterials = [ cma.CompositeAdapter(), cma.CompositeMaterial_EquivAdapter(), cma.SphericalInclusions_ShellAdapter(), cma.SphericalInclusions_DiskAdapter() ], #Bulk Materials #-------- ModelCategories = \ [ Category( name = 'Non-Metals', Materials = self._adaptersort(self.nonmetals) ), Category( name = 'Metals', Materials = self._adaptersort(self.metals) ) ], DBCategories = \ [ Category( name = 'XNK Database', Materials = self._adaptersort(self.xnkdb) ), Category( name = 'Sopra Database', Materials = self._adaptersort(self.sopradb) ), Category( name = 'RIINFO Database', Materials = self._adaptersort(self.riinfodb), ), ], FileCategories = \ [ Category( name = 'Sopra Files', Materials = self._adaptersort(self.soprafiles) ), Category( name = 'NK Files', Materials = self._adaptersort(self.nkfiles) ), ], ) view = View( VSplit( Item( name = 'materials_trees', editor = tree_editor, show_label = False, ), Item('FileSearch', show_label=False), ), title = 'Materials Parser', buttons = OKCancelButtons, resizable = True, style = 'custom', width=.8, height=.8, )
class SimulationConfig(HasStrictTraits): '''Configuration of the optimization problem including the goal functions, and constraints. ''' debug_level = Int(0, label='Debug level', auto_set=False, enter_set=True) r'''Debug level for simulation scheme. ''' goal_function_type = Trait('target_faces', {'none': None, 'target_faces': FuTargetFaces, 'bending potential energy': FuPotEngBending, 'gravity potential energy': FuPotEngGravity, 'total potential energy': FuPotEngTotal }, input_change=True) r'''Type of the goal function. ''' _fu = Instance(IFu) '''Private trait with the goal function object. ''' fu = Property(Instance(IFu), depends_on='goal_function_type') '''Goal function. ''' def _get_fu(self): if self._fu == None: self._fu = self.goal_function_type_() return self._fu def _set_fu(self, value): if not value.__class__ is self.goal_function_type_: raise TypeError('Goal function has type %s but should be %s' % (value.__class__, self.goal_function_type_)) self._fu = value gu = Dict(Str, IGu) '''Dictionary of equality constraints. ''' def _gu_default(self): return {} gu_lst = Property(depends_on='gu') '''List of equality constraints. ''' @cached_property def _get_gu_lst(self): for name, gu in list(self.gu.items()): gu.label = name return list(self.gu.values()) selected_gu = Instance(IGu) hu = Dict(Str, IHu) '''Inequality constraints ''' def _hu_default(self): return {} hu_lst = Property(depends_on='hu') '''List of inequality constraints. ''' @cached_property def _get_hu_lst(self): return list(self.hu.values()) selected_hu = Instance(IHu) has_H = Property(Bool) def _get_has_H(self): return len(self.hu) > 0 show_iter = Bool(False, auto_set=False, enter_set=True) r'''Saves the first 10 iteration steps, so they can be analyzed ''' MAX_ITER = Int(100, auto_set=False, enter_set=True) r'''Maximum number of iterations. ''' acc = Float(1e-4, auto_set=False, enter_set=True) r'''Required accuracy. ''' use_f_du = Bool(True, auto_set=False, enter_set=True) r'''Switch the use of goal function derivatives on. ''' use_G_du = Bool(True, auto_set=False, enter_set=True) r'''Switch the use of constraint derivatives on. ''' use_H_du = Bool(True, auto_set=False, enter_set=True) r'''Switch the use of constraint derivatives on. ''' def validate_input(self): # self.fu.validate_input() for gu in self.gu_lst: gu.validate_input() for hu in self.hu_lst: hu.validate_input() traits_view = View( Tabbed( VSplit( UItem('gu_lst@', editor=gu_list_editor), UItem('selected_gu@'), label='Gu' ), VSplit( UItem('hu_lst@', editor=hu_list_editor), UItem('selected_hu@'), label='Hu' ), ) )
class tcWindow(HasTraits): project = tcProject plot = tcPlot assert True, "tcWindow" def __init__(self, project): self.project = project self.plot = create_timechart_container(project) self.plot_range_tools = self.plot.range_tools self.plot_range_tools.on_trait_change(self._selection_time_changed, "time") self.trait_view().title = self.get_title() def get_title(self): if self.project.filename == "dummy": return "PyTimechart: Please Open a File" return "PyTimechart:" + self.project.filename # Create an action that exits the application. status = Str("Welcome to PyTimechart") traits_view = View( HSplit( VSplit( Item('project', show_label=False, editor=InstanceEditor(view='process_view'), style='custom', width=150), # Item('plot_range_tools', show_label = False, editor=InstanceEditor(view = 'selection_view'), style='custom',width=150,height=100) ), Item('plot', show_label=False, editor=ComponentEditor()), ), toolbar=ToolBar(*_create_toolbar_actions(), image_size=(24, 24), show_tool_names=False), menubar=MenuBar(*_create_menubar_actions()), statusbar=[ StatusItem(name='status'), ], resizable=True, width=1280, height=1024, handler=tcActionHandler()) def _on_open_trace_file(self): if open_file(None) and self.project.filename == "dummy": self._ui.dispose() def _on_view_properties(self): self.plot.options.edit_traits() def _on_exit(self, n=None): self.close() sys.exit(0) def close(self, n=None): pass def _on_about(self): aboutBox().edit_traits() def _on_doc(self): browse_doc() def _selection_time_changed(self): self.status = "selection time:%s" % (self.plot_range_tools.time)
class BMCSVizSheet(ROutputSection): '''Vieualization sheet - controls the time displayed - contains several vizualization adapters. This class could be called BMCSTV - for watching the time dependent response. It can have several channels - in 2D and 3D ''' def __init__(self, *args, **kw): super(BMCSVizSheet, self).__init__(*args, **kw) self.on_trait_change(self.viz2d_list_items_changed, 'viz2d_list_items') name = Str hist = Instance(IHist) min = Float(0.0) '''Simulation start is always 0.0 ''' max = Float(1.0) '''Upper range limit of the current simulator. This range is determined by the the time-loop range of the model. ''' vot = Float def _vot_default(self): return self.min def _vot_changed(self): if self.hist: self.hist.vot = self.vot vot_slider = Range(low='min', high='max', step=0.01, enter_set=True, auto_set=False) '''Time line controlling the current state of the simulation. this value is synchronized with the control time of the time loop setting the tline. The vot_max = tline.max. The value of vot follows the value of tline.val in monitoring mode. By default, the monitoring mode is active with vot = tline.value. When sliding to a value vot < tline.value, the browser mode is activated. When sliding into the range vot > tline.value the monitoring mode is reactivated. ''' def _vot_slider_default(self): return 0.0 mode = Enum('monitor', 'browse') def _mode_changed(self): if self.mode == 'browse': self.offline = False time = Float(0.0) def time_range_changed(self, max_): self.max = max_ def time_changed(self, time): self.time = time if self.mode == 'monitor': self.vot = time self.vot_slider = time def _vot_slider_changed(self): if self.mode == 'browse': if self.vot_slider >= self.time: self.mode = 'monitor' self.vot_slider = self.time self.vot = self.time else: self.vot = self.vot_slider elif self.mode == 'monitor': if self.vot_slider < self.time: self.mode = 'browse' self.vot = self.vot_slider else: self.vot_slider = self.time self.vot = self.time offline = Bool(True) '''If the sheet is offline, the plot refresh is inactive. The sheet starts in offline mode and is activated once the signal run_started has been received. Upon run_finished the the sheet goes directly into the offline mode again. If the user switches to browser mode, the vizsheet gets online and reploting is activated. ''' running = Bool(False) def run_started(self): self.running = True self.offline = False for pp in self.pp_list: pp.clear() self.mode = 'monitor' if self.reference_viz2d: ax = self.reference_axes ax.clear() self.reference_viz2d.reset(ax) def run_finished(self): self.skipped_steps = self.monitor_chunk_size # self.update_pipeline(1.0) self.replot() self.running = False self.offline = True monitor_chunk_size = Int(10, label='Monitor each # steps') skipped_steps = Int(1) @on_trait_change('vot,n_cols') def replot(self): if self.offline: return if self.running and self.mode == 'monitor' and \ self.skipped_steps < (self.monitor_chunk_size - 1): self.skipped_steps += 1 return for pp in self.pp_list: pp.replot(self.vot) # for viz2d, ax in self.axes.items(): # ax.clear() # viz2d.clear() # viz2d.plot(ax, self.vot) # if self.selected_pp: # self.selected_pp.align_xaxis() if self.reference_viz2d: ax = self.reference_axes ax.clear() self.reference_viz2d.clear() self.reference_viz2d.plot(ax, self.vot) self.data_changed = True self.skipped_steps = 0 if self.mode == 'browse': self.update_pipeline(self.vot) else: up = RunThread(self, self.vot) up.start() viz2d_list = List(Viz2D) '''List of visualization adaptors for 2D. ''' viz2d_dict = Property def _get_viz2d_dict(self): return {viz2d.name: viz2d for viz2d in self.viz2d_list} viz2d_names = Property '''Names to be supplied to the selector of the reference graph. ''' def _get_viz2d_names(self): return list(self.viz2d_dict.keys()) viz2d_list_editor_clicked = Tuple viz2d_list_changed = Event def _viz2d_list_editor_clicked_changed(self, *args, **kw): _, column = self.viz2d_list_editor_clicked self.offline = False self.viz2d_list_changed = True if self.plot_mode == 'single': if column.name == 'visible': self.selected_viz2d.visible = True self.plot_mode = 'multiple' else: self.replot() elif self.plot_mode == 'multiple': if column.name != 'visible': self.plot_mode = 'single' else: self.replot() plot_mode = Enum('multiple', 'single') def _plot_mode_changed(self): if self.plot_mode == 'single': self.replot_selected_viz2d() elif self.plot_mode == 'multiple': self.replot() def replot_selected_viz2d(self): for viz2d in self.viz2d_list: viz2d.visible = False self.selected_viz2d.visible = True self.n_cols = 1 self.viz2d_list_changed = True self.replot() def viz2d_list_items_changed(self): self.replot() def get_subrecords(self): '''What is this good for? ''' return self.viz2d_list export_button = Button(label='Export selected diagram') def plot_in_window(self): fig = plt.figure(figsize=(self.fig_width, self.fig_height)) ax = fig.add_subplot(111) self.selected_viz2d.plot(ax, self.vot) fig.show() def _export_button_fired(self, vot=0): print('in export button fired') Thread(target=self.plot_in_window).start() print('thread started') fig_width = Float(8.0, auto_set=False, enter_set=True) fig_height = Float(5.0, auto_set=False, enter_set=True) save_button = Button(label='Save selected diagram') animate_button = Button(label='Animate selected diagram') def _animate_button_fired(self): ad = AnimationDialog(sheet=self) ad.edit_traits() return #========================================================================= # Reference figure serving for orientation. #========================================================================= reference_viz2d_name = Enum('', values="viz2d_names") '''Current name of the reference graphs. ''' def _reference_viz2d_name_changed(self): self.replot() reference_viz2d_cumulate = Bool(False, label='cumulate') reference_viz2d = Property(Instance(Viz2D), depends_on='reference_viz2d_name') '''Visualization of a graph showing the time context of the current visualization state. ''' def _get_reference_viz2d(self): if self.reference_viz2d_name == None: if len(self.viz2d_dict): return self.viz2d_list[0] else: return None return self.viz2d_dict[self.reference_viz2d_name] reference_figure = Instance(Figure) def _reference_figure_default(self): figure = Figure(facecolor='white') figure.set_tight_layout(True) return figure reference_axes = Property(List, depends_on='reference_viz2d_name') '''Derived axes objects reflecting the layout of plot pane and the individual. ''' @cached_property def _get_reference_axes(self): return self.reference_figure.add_subplot(1, 1, 1) selected_viz2d = Instance(Viz2D) def _selected_viz2d_changed(self): if self.plot_mode == 'single': self.replot_selected_viz2d() n_cols = Range(low=1, high=3, value=2, label='Number of columns', tooltip='Defines a number of columns within the plot pane', enter_set=True, auto_set=False) figure = Instance(Figure) tight_layout = Bool(True) def _figure_default(self): figure = Figure(facecolor='white') figure.set_tight_layout(self.tight_layout) return figure visible_viz2d_list = Property( List, depends_on='viz2d_list,viz2d_list_items,n_cols,viz2d_list_changed') '''Derived axes objects reflecting the layout of plot pane and the individual. ''' @cached_property def _get_visible_viz2d_list(self): viz_list = [] for viz2d in self.viz2d_list: if viz2d.visible: viz_list.append(viz2d) return viz_list pp_list = List(PlotPerspective) selected_pp = Instance(PlotPerspective) xaxes = Property(List, depends_on='selected_pp') '''Derived axes objects reflecting the layout of plot pane and the individual. ''' @cached_property def _get_xaxes(self): self.figure.clear() if self.selected_pp: self.selected_pp.figure = self.figure ad = self.selected_pp.axes else: n_fig = len(self.visible_viz2d_list) n_cols = self.n_cols n_rows = (n_fig + n_cols - 1) / self.n_cols ad = { viz2d: self.figure.add_subplot(n_rows, self.n_cols, i + 1) for i, viz2d in enumerate(self.visible_viz2d_list) } return ad data_changed = Event bgcolor = tr.Tuple(1.0, 1.0, 1.0) fgcolor = tr.Tuple(0.0, 0.0, 0.0) scene = Instance(MlabSceneModel) def _scene_default(self): return MlabSceneModel() mlab = Property(depends_on='input_change') '''Get the mlab handle''' def _get_mlab(self): return self.scene.mlab fig = Property() '''Figure for 3D visualization. ''' @cached_property def _get_fig(self): fig = self.mlab.gcf() bgcolor = tuple(self.bgcolor) fgcolor = tuple(self.fgcolor) self.mlab.figure(fig, fgcolor=fgcolor, bgcolor=bgcolor) return fig def show(self, *args, **kw): '''Render the visualization. ''' self.mlab.show(*args, **kw) def add_viz3d(self, viz3d, order=1): '''Add a new visualization objectk.''' viz3d.ftv = self vis3d = viz3d.vis3d name = viz3d.name label = '%s[%s:%s]-%s' % (name, str( vis3d.__class__), str(viz3d.__class__), vis3d) if label in self.viz3d_dict: raise KeyError('viz3d object named %s already registered' % label) viz3d.order = order self.viz3d_dict[label] = viz3d viz3d_dict = tr.Dict(tr.Str, tr.Instance(Viz3D)) '''Dictionary of visualization objects. ''' viz3d_list = tr.Property def _get_viz3d_list(self): map_order_viz3d = {} for idx, (viz3d) in enumerate(self.viz3d_dict.values()): order = viz3d.order map_order_viz3d['%5g%5g' % (order, idx)] = viz3d return [map_order_viz3d[key] for key in sorted(map_order_viz3d.keys())] pipeline_ready = Bool(False) def setup_pipeline(self): if self.pipeline_ready: return self.fig fig = self.mlab.gcf() fig.scene.disable_render = True for viz3d in self.viz3d_list: viz3d.setup() fig.scene.disable_render = False self.pipeline_ready = True def update_pipeline(self, vot): self.setup_pipeline() # get the current constrain information self.vot = vot fig = self.mlab.gcf() fig.scene.disable_render = True for viz3d in self.viz3d_list: viz3d.plot(vot) fig.scene.disable_render = False selected_viz3d = Instance(Viz3D) def _selected_viz3d_changed(self): print('selection done') # Traits view definition: traits_view = View( VSplit( HSplit( Tabbed( UItem( 'pp_list', id='notebook', style='custom', resizable=True, editor=ListEditor( use_notebook=True, deletable=False, # selected='selected_pp', export='DockWindowShell', page_name='.name')), UItem('scene', label='3d scene', editor=SceneEditor(scene_class=MayaviScene)), scrollable=True, label='Plot panel'), VGroup( Item('n_cols', width=250), Item('plot_mode@', width=250), VSplit( UItem('viz2d_list@', editor=viz2d_list_editor, width=100), UItem('selected_viz2d@', width=200), UItem('pp_list@', editor=pp_list_editor, width=100), # UItem('selected_pp@', # width=200), UItem('viz3d_list@', editor=viz3d_list_editor, width=100), UItem('selected_viz3d@', width=200), VGroup( # UItem('export_button', # springy=False, resizable=True), # VGroup( # HGroup( # UItem('fig_width', springy=True, # resizable=False), # UItem('fig_height', springy=True), # ), # label='Figure size' # ), UItem('animate_button', springy=False, resizable=True), ), VGroup( UItem('reference_viz2d_name', resizable=True), UItem( 'reference_figure', editor=MPLFigureEditor(), width=200, # springy=True ), label='Reference graph', )), label='Plot configure', scrollable=True), ), VGroup( HGroup( Item('mode', resizable=False, springy=False), Item('monitor_chunk_size', resizable=False, springy=False), ), Item('vot_slider', height=40), )), resizable=True, width=0.8, height=0.8, buttons=['OK', 'Cancel'])
class RTraceDomainListInteg(RTrace, RTraceDomainList): # sd = Instance( SDomain ) # # rt_domain = Property # def _get_rt_domain(self): # return self.sd.rt_bg_domain label = Str('RTraceDomainInteg') var = Str('') idx = Int(-1, enter_set=True, auto_set=False) save_on = Enum('update', 'iteration') warp = Bool(False) warp_f = Float(1.) warp_var = Str('u') def bind(self): ''' Locate the evaluators ''' def setup(self): ''' Setup the spatial domain of the tracer ''' for sf in self.subfields: sf.setup() subfields = Property @cached_property def _get_subfields(self): # construct the RTraceDomainFields # return [RTraceDomainInteg(var=self.var, idx=self.idx, position=self.position, save_on=self.save_on, warp=self.warp, warp_f=self.warp_f, sd=subdomain) for subdomain in self.sd.nonempty_subdomains] integ_val = Array(desc='Integral over the domain') def add_current_values(self, sctx, U_k, *args, **kw): integ_val = array([0.0], 'float_') for sf in self.subfields: if sf.skip_domain: continue sf.add_current_values(sctx, U_k, *args, **kw) integ_val += sf.integ_val self.integ_val = integ_val def timer_tick(self, e): pass def write(self): pass def clear(self): pass view = View(HSplit(VSplit(VGroup('var', 'idx'), VGroup('record_on', 'clear_on'), Item('integ_val', style='readonly', show_label=False), ), ), resizable=True)
class SwiftConsole(HasTraits): """Traits-defined Swift Console. link : object Serial driver update : bool Update the firmware log_level_filter : str Syslog string, one of "ERROR", "WARNING", "INFO", "DEBUG". skip_settings : bool Don't read the device settings. Set to False when the console is reading from a network connection only. """ link = Instance(sbpc.Handler) console_output = Instance(OutputList()) python_console_env = Dict device_serial = Str('') a = Int b = Int tracking_view = Instance(TrackingView) solution_view = Instance(SolutionView) baseline_view = Instance(BaselineView) observation_view = Instance(ObservationView) networking_view = Instance(SbpRelayView) observation_view_base = Instance(ObservationView) system_monitor_view = Instance(SystemMonitorView) settings_view = Instance(SettingsView) update_view = Instance(UpdateView) log_level_filter = Enum(list(SYSLOG_LEVELS.itervalues())) """" mode : baseline and solution view - SPP, Fixed or Float num_sat : baseline and solution view - number of satellites port : which port is Piksi connected to directory_name : location of logged files json_logging : enable JSON logging csv_logging : enable CSV logging is_valid_directory : check to see if chosen directory is valid """ mode = Str('') num_sats = Int(0) port = Str('') directory_name = Directory json_logging = Bool(True) csv_logging = Bool(False) is_valid_directory = Bool(True) csv_logging_button = SVGButton( toggle=True, label='CSV log', tooltip='start CSV logging', toggle_tooltip='stop CSV logging', filename=os.path.join(determine_path(), 'images', 'iconic', 'pause.svg'), toggle_filename=os.path.join(determine_path(), 'images', 'iconic', 'play.svg'), orientation='vertical', width=2, height=2, ) json_logging_button = SVGButton( toggle=True, label='JSON log', tooltip='start JSON logging', toggle_tooltip='stop JSON logging', filename=os.path.join(determine_path(), 'images', 'iconic', 'pause.svg'), toggle_filename=os.path.join(determine_path(), 'images', 'iconic', 'play.svg'), orientation='vertical', width=2, height=2, ) paused_button = SVGButton(label='', tooltip='Pause console update', toggle_tooltip='Resume console update', toggle=True, filename=os.path.join(determine_path(), 'images', 'iconic', 'pause.svg'), toggle_filename=os.path.join( determine_path(), 'images', 'iconic', 'play.svg'), width=8, height=8) clear_button = SVGButton(label='', tooltip='Clear console buffer', filename=os.path.join(determine_path(), 'images', 'iconic', 'x.svg'), width=8, height=8) view = View(VSplit( Tabbed(Item('tracking_view', style='custom', label='Tracking'), Item('solution_view', style='custom', label='Solution'), Item('baseline_view', style='custom', label='Baseline'), VSplit( Item('observation_view', style='custom', show_label=False), Item('observation_view_base', style='custom', show_label=False), label='Observations', ), Item('settings_view', style='custom', label='Settings'), Item('update_view', style='custom', label='Firmware Update'), Tabbed(Item('system_monitor_view', style='custom', label='System Monitor'), Item('networking_view', label='Networking', style='custom', show_label=False), Item('python_console_env', style='custom', label='Python Console', editor=ShellEditor()), label='Advanced', show_labels=False), show_labels=False), VGroup( VGroup( HGroup( Spring(width=4, springy=False), Item('paused_button', show_label=False, padding=0, width=8, height=8), Item('clear_button', show_label=False, width=8, height=8), Item('', label='Console Log', emphasized=True), Item('csv_logging_button', emphasized=True, show_label=False, width=12, height=-30, padding=0), Item('json_logging_button', emphasized=True, show_label=False, width=12, height=-30, padding=0), Item( 'directory_name', show_label=False, springy=True, tooltip= 'Choose location for file logs. Default is home/SwiftNav.', height=-25, enabled_when='not(json_logging or csv_logging)'), UItem( 'log_level_filter', style='simple', padding=0, height=8, show_label=True, tooltip= 'Show log levels up to and including the selected level of severity.\nThe CONSOLE log level is always visible.' ), ), Item('console_output', style='custom', editor=InstanceEditor(), height=125, show_label=False, full_size=True), ), HGroup( Spring(width=4, springy=False), Item('', label='PORT:', emphasized=True, tooltip='Serial Port that Piksi is connected to'), Item('port', show_label=False, style='readonly'), Item('', label='FIX TYPE:', emphasized=True, tooltip='Piksi Mode: SPS, Float RTK, Fixed RTK'), Item('mode', show_label=False, style='readonly'), Item('', label='#SATS:', emphasized=True, tooltip='Number of satellites acquired by Piksi'), Item('num_sats', padding=2, show_label=False, style='readonly'), ), Spring(height=1, springy=False), ), ), icon=icon, resizable=True, width=800, height=600, handler=ConsoleHandler(), title=CONSOLE_TITLE) def print_message_callback(self, sbp_msg, **metadata): try: encoded = sbp_msg.payload.encode('ascii', 'ignore') for eachline in reversed(encoded.split('\n')): self.console_output.write_level( eachline, str_to_log_level(eachline.split(':')[0])) except UnicodeDecodeError: print "Critical Error encoding the serial stream as ascii." def log_message_callback(self, sbp_msg, **metadata): try: encoded = sbp_msg.text.encode('ascii', 'ignore') for eachline in reversed(encoded.split('\n')): self.console_output.write_level(eachline, sbp_msg.level) except UnicodeDecodeError: print "Critical Error encoding the serial stream as ascii." def ext_event_callback(self, sbp_msg, **metadata): e = MsgExtEvent(sbp_msg) print 'External event: %s edge on pin %d at wn=%d, tow=%d, time qual=%s' % ( "Rising" if (e.flags & (1 << 0)) else "Falling", e.pin, e.wn, e.tow, "good" if (e.flags & (1 << 1)) else "unknown") def _paused_button_fired(self): self.console_output.paused = not self.console_output.paused def _log_level_filter_changed(self): """ Takes log level enum and translates into the mapped integer. Integer stores the current filter value inside OutputList. """ self.console_output.log_level_filter = str_to_log_level( self.log_level_filter) def _clear_button_fired(self): self.console_output.clear() def _directory_name_changed(self): if os.path.isdir(self.directory_name): self.is_valid_directory = True if self.baseline_view and self.solution_view: self.baseline_view.directory_name_b = self.directory_name self.solution_view.directory_name_p = self.directory_name self.solution_view.directory_name_v = self.directory_name if self.observation_view and self.observation_view_base: self.observation_view.dirname = self.directory_name self.observation_view_base.dirname = self.directory_name else: print "Please enter a valid directory!" self.is_valid_directory = False def update_on_heartbeat(self, sbp_msg, **metadata): # First initialize the state to nothing, if we can't update, it will be none temp_mode = "None" temp_num_sats = 0 view = None # If we have a recent baseline update, we use the baseline info if time.time() - self.baseline_view.last_btime_update < 10: view = self.baseline_view # Otherwise, if we have a recent SPP update, we use the SPP elif time.time() - self.solution_view.last_stime_update < 10: view = self.solution_view if view: if view.last_soln: # if all is well we update state temp_mode = view.mode_string(view.last_soln) temp_num_sats = view.last_soln.n_sats self.mode = temp_mode self.num_sats = temp_num_sats if self.settings_view: # for auto populating surveyed fields self.settings_view.lat = self.solution_view.latitude self.settings_view.lon = self.solution_view.longitude self.settings_view.alt = self.solution_view.altitude def _csv_logging_button_fired(self): if self.is_valid_directory: if self.csv_logging and self.baseline_view.logging_b and self.solution_view.logging_p and self.solution_view.logging_v: print "Stopped CSV logging" self.csv_logging = False self.baseline_view.logging_b = False self.solution_view.logging_p = False self.solution_view.logging_v = False else: print "Started CSV logging at %s" % self.directory_name self.csv_logging = True self.baseline_view.logging_b = True self.solution_view.logging_p = True self.solution_view.logging_v = True else: print "Directory not valid" def _start_json_logging(self, override_filename=None): if override_filename: filename = override_filename else: filename = s.logfilename() filename = os.path.normpath(os.path.join(self.directory_name, filename)) self.logger = s.get_logger(True, filename) self.forwarder = sbpc.Forwarder(self.link, self.logger) self.forwarder.start() def _stop_json_logging(self): fwd = self.forwarder fwd.stop() self.logger.flush() self.logger.close() def _json_logging_button_fired(self): if self.is_valid_directory: if self.first_json_press and self.json_logging: print "JSON Logging initiated via CMD line. Please press button again to stop logging" elif self.json_logging: self._stop_json_logging() self.json_logging = False print "Stopped JSON logging" else: self._start_json_logging() self.json_logging = True self.first_json_press = False else: print "Directory not valid" def __init__(self, link, update, log_level_filter, skip_settings=False, error=False, port=None, json_logging=False, log_dirname=None): self.console_output = OutputList() self.console_output.write("Console: starting...") self.error = error sys.stdout = self.console_output self.port = port self.num_sats = 0 self.mode = '' self.forwarder = None # if we have passed a logfile, we set our directory to it override_filename = None swift_path = None home = expanduser("~") swift_path = os.path.normpath(os.path.join(home, 'SwiftNav')) try: os.makedirs(swift_path) except OSError: if not os.path.isdir(swift_path): raise if log_dirname: self.directory_name = log_dirname else: self.directory_name = swift_path if not error: sys.stderr = self.console_output self.log_level_filter = log_level_filter self.console_output.log_level_filter = str_to_log_level( log_level_filter) try: self.link = link self.link.add_callback(self.print_message_callback, SBP_MSG_PRINT_DEP) self.link.add_callback(self.log_message_callback, SBP_MSG_LOG) self.link.add_callback(self.ext_event_callback, SBP_MSG_EXT_EVENT) self.link.add_callback(self.update_on_heartbeat, SBP_MSG_HEARTBEAT) self.dep_handler = DeprecatedMessageHandler(link) settings_read_finished_functions = [] self.tracking_view = TrackingView(self.link) self.solution_view = SolutionView(self.link, dirname=self.directory_name) self.baseline_view = BaselineView(self.link, dirname=self.directory_name) self.observation_view = ObservationView( self.link, name='Local', relay=False, dirname=self.directory_name) self.observation_view_base = ObservationView( self.link, name='Remote', relay=True, dirname=self.directory_name) self.system_monitor_view = SystemMonitorView(self.link) self.update_view = UpdateView(self.link, prompt=update) settings_read_finished_functions.append( self.update_view.compare_versions) self.networking_view = SbpRelayView(self.link) self.json_logging = json_logging self.csv_logging = False self.first_json_press = True if json_logging: self._start_json_logging(override_filename) self.json_logging = True # Once we have received the settings, update device_serial with # the Piksi serial number which will be displayed in the window # title. This callback will also update the header route as used # by the networking view. def update_serial(): serial_string = self.settings_view.settings['system_info'][ 'serial_number'].value self.device_serial = 'PK%04d' % int(serial_string) if serial_string: self.networking_view.set_route(int(serial_string)) settings_read_finished_functions.append(update_serial) self.settings_view = SettingsView(self.link, settings_read_finished_functions, skip=skip_settings) self.update_view.settings = self.settings_view.settings self.python_console_env = { 'send_message': self.link, 'link': self.link, } self.python_console_env.update( self.tracking_view.python_console_cmds) self.python_console_env.update( self.solution_view.python_console_cmds) self.python_console_env.update( self.baseline_view.python_console_cmds) self.python_console_env.update( self.observation_view.python_console_cmds) self.python_console_env.update( self.networking_view.python_console_cmds) self.python_console_env.update( self.system_monitor_view.python_console_cmds) self.python_console_env.update( self.update_view.python_console_cmds) self.python_console_env.update( self.settings_view.python_console_cmds) except: import traceback traceback.print_exc() if self.error: sys.exit(1)
class CounterTrace(FreeJob, GetSetItemsMixin): TraceLength = Range(low=10, high=10000, value=100, desc='Length of Count Trace', label='Trace Length') SecondsPerPoint = Range(low=0.001, high=1, value=0.1, desc='Seconds per point [s]', label='Seconds per point [s]') RefreshRate = Range(low=0.01, high=1, value=0.1, desc='Refresh rate [s]', label='Refresh rate [s]') # trace data C = Array() T = Array() counts = Float(0.0) TracePlot = Instance(Plot) TraceData = Instance(ArrayPlotData) digits_data = Instance(ArrayPlotData) digits_plot = Instance(Plot) def __init__(self): super(CounterTrace, self).__init__() self.on_trait_change(self._update_T, 'T', dispatch='ui') self.on_trait_change(self._update_C, 'C', dispatch='ui') #counter.startCounter() self._create_digits_plot() self.update_digits_plot() def _C_default(self): return numpy.zeros((self.TraceLength, )) def _T_default(self): return self.SecondsPerPoint * numpy.arange(self.TraceLength) def _TraceLength_changed(self): self.C = self._C_default() self.T = self._T_default() def _counts_default(self): return 0 def _SecondsPerPoint_changed(self): self.T = self._T_default() def _update_T(self): self.TraceData.set_data('t', self.T) def _update_C(self): self.TraceData.set_data('y0', self.C / 1e3) #self.TracePlot.request_redraw() def _TraceData_default(self): return ArrayPlotData(t=self.T, y0=self.C / 1e3) def _TracePlot_default(self): plot = Plot(self.TraceData, width=500, height=500, resizable='hv') plot.plot(('t', 'y0'), type='line', color='black', fontsize=20) plot.value_axis.title = 'kcounts / s' return plot def _create_digits_plot(self): data = ArrayPlotData(image=numpy.zeros((2, 2))) plot = Plot(data, width=500, height=500, resizable='hv', aspect_ratio=37.0 / 9, padding=8, padding_left=48, padding_bottom=36) plot.img_plot('image', xbounds=(0, 1), ybounds=(0, 1), colormap=hot) plot.plots['plot0'][0].value_range.high_setting = 1 plot.plots['plot0'][0].value_range.low_setting = 0 plot.x_axis = None plot.y_axis = None self.digits_data = data self.digits_plot = plot @on_trait_change('counts') def update_digits_plot(self): string = ('%5.1f' % self.counts)[:5] + 'k' data = numpy.zeros((37, 9)) for i, char in enumerate(string): data[6 * i + 1:6 * i + 6, 1:-1] = DIGIT[char].transpose() if self.counts >= 2e3: data *= 0.4 self.digits_data.set_data('image', data.transpose()[::-1]) def _run(self): """Acquire Count Trace""" try: self.state = 'run' counter_tr.startCounter() except Exception as e: logging.getLogger().exception(e) raise else: while True: threading.current_thread().stop_request.wait(self.RefreshRate) if threading.current_thread().stop_request.isSet(): break try: self.C = numpy.append(self.C[1:], counter_tr.Count()) self.counts = self.C[-1] / 1000 except Exception as e: logging.getLogger().exception(e) raise finally: self.state = 'idle' counter_tr.stopCounter() traits_view = View(VGroup( HGroup( Item('start_button', show_label=False), Item('stop_button', show_label=False), Item('priority'), Item('state', style='readonly'), ), VSplit(Item('TracePlot', editor=ComponentEditor(), show_label=False), Item('digits_plot', editor=ComponentEditor(), show_label=False)), Item('TraceLength'), HGroup( Item('SecondsPerPoint'), Item('RefreshRate'), ), ), title='Counter Time Trace', width=600, height=600, buttons=[], resizable=True, handler=GetSetItemsHandler())
class RTDofGraph(RTrace, BMCSLeafNode, Vis2D): ''' Collects two response evaluators to make a response graph. The supplied strings for var_x and var_y are used to locate the rte in the current response manager. The bind method is used to navigate to the rte and is stored in here as var_x_eval and var_y_val as Callable object. The request for new response evaluation is launched by the time loop and directed futher by the response manager. This method is used solely for collecting the data, not for their visualization in the viewer. The timer_tick method is invoked when the visualization of the Graph should be synchronized with the actual contents. ''' label = Str('RTDofGraph') var_x = Str('', label='Variable on x', enter_set=True, auto_set=False) cum_x = Bool(label='Cumulative x', enter_set=True, auto_set=False) var_x_eval = Callable(trantient=True) idx_x = Int(-1, enter_set=True, auto_set=False) var_y = Str('', label='Variable on y', enter_set=True, auto_set=False) cum_y = Bool(label='Cumulative y', enter_set=True, auto_set=False) var_y_eval = Callable(trantient=True) idx_y = Int(-1, enter_set=True, auto_set=False) transform_x = Str(enter_set=True, auto_set=False) transform_y = Str(enter_set=True, auto_set=False) trace = Instance(MFnLineArray) _tdata = List(np.float) def _trace_default(self): return MFnLineArray() print_button = ToolbarButton('Print values', style='toolbar', trantient=True) @on_trait_change('print_button') def print_values(self, event=None): print('x:\t', self.trace.xdata, '\ny:\t', self.trace.ydata) _xdata = List(Array(float)) _ydata = List(Array(float)) def bind(self): ''' Locate the evaluators ''' self.var_x_eval = self.rmgr.rte_dict.get(self.var_x, None) if self.var_x_eval == None: raise KeyError('Variable %s not present in the dictionary:\n%s' % \ (self.var_x, list(self.rmgr.rte_dict.keys()))) self.var_y_eval = self.rmgr.rte_dict.get(self.var_y, None) if self.var_y_eval == None: raise KeyError('Variable %s not present in the dictionary:\n%s' % \ (self.var_y, list(self.rmgr.rte_dict.keys()))) def setup(self): self.clear() def close(self): self.write() def write(self): '''Generate the file name within the write_dir and submit the request for writing to the writer ''' # self.writer.scalars_name = self.name file_base_name = 'rtrace_diagramm_%s (%s,%s).dat' % \ (self.label, self.var_x, self.var_y) # full path to the data file file_name = os.path.join(self.dir, file_base_name) # file_rtrace = open( file_name, 'w' ) self.refresh() np.savetxt(file_name, np.vstack([self.trace.xdata, self.trace.ydata]).T) # pickle.dump( self, file_rtrace ) # file.close() def add_current_values(self, sctx, U_k, t, *args, **kw): ''' Invoke the evaluators in the current context for the specified control vector U_k. ''' x = self.var_x_eval(sctx, U_k, *args, **kw) y = self.var_y_eval(sctx, U_k, *args, **kw) self.add_pair(x.flatten(), y.flatten(), t) def add_pair(self, x, y, t): if self.cum_x and len(self._xdata) > 0: self._xdata.append(self._xdata[-1] + x) else: self._xdata.append(np.copy(x)) if self.cum_y and len(self._ydata) > 0: self._ydata.append(self._ydata[-1] + y) else: self._ydata.append(np.copy(y)) self._tdata.append(t) @on_trait_change('idx_x,idx_y') def redraw(self, e=None): if (self._xdata == [] or self._ydata == []): return # xarray = np.array(self._xdata)[:, self.idx_x] yarray = np.array(self._ydata)[:, self.idx_y] if self.transform_x: def transform_x_fn(x): '''makes a callable function out of the Str-attribute "transform_x". The vectorised version of this function is then used to transform the values in "xarray". Note that the function defined in "transform_x" must be defined in terms of a lower case variable "x". ''' return eval(self.transform_x) xarray = np.frompyfunc(transform_x_fn, 1, 1)(xarray) if self.transform_y: def transform_y_fn(y): '''makes a callable function out of the Str-attribute "transform_y". The vectorised version of this function is then used to transform the values in "yarray". Note that the function defined in "transform_y" must be defined in terms of a lower case variable "y". ''' return eval(self.transform_y) yarray = np.frompyfunc(transform_y_fn, 1, 1)(yarray) self.trace.xdata = np.array(xarray) self.trace.ydata = np.array(yarray) self.trace.replot() def timer_tick(self, e=None): # @todo: unify with redraw pass def clear(self): self._xdata = [] self._ydata = [] self._tdata = [] self.trace.clear() self.redraw() viz2d_classes = {'diagram': RTraceViz2D} traits_view = View(VSplit( VGroup( HGroup( VGroup( HGroup(Spring(), Item('var_x', style='readonly'), Item('idx_x', show_label=False)), Item('transform_x')), VGroup( HGroup(Spring(), Item('var_y', style='readonly'), Item('idx_y', show_label=False)), Item('transform_y')), VGroup('record_on', 'clear_on')), HGroup(Item('refresh_button', show_label=False), Item('print_button', show_label=False)), ), Item('trace@', show_label=False, resizable=True), ), buttons=[OKButton, CancelButton], resizable=True, scrollable=True, height=0.5, width=0.5) tree_view = View( Include('actions'), Item('var_x', style='readonly'), Item('idx_x', show_label=False), )
def traits_view(self): tgrp = HGroup( VGroup(icon_button_editor('add_project_button', 'database_add', tooltip='Add project'), show_border=True, label='Project'), VGroup(icon_button_editor('add_material_button', 'database_add', tooltip='Add material'), show_border=True, label='Material'), VGroup(icon_button_editor('add_sample_button', 'database_add', tooltip='Add sample'), show_border=True, label='Sample'), icon_button_editor( 'generate_identifiers_button', 'table_lightning', tooltip='Generate Identifiers for this irradiation'), icon_button_editor( 'preview_generate_identifiers_button', 'document-preview', tooltip= 'Preview identifiers generated for this irradiation level')) project_grp = VGroup(UItem('projects', editor=FilterTabularEditor( editable=False, selected='selected_projects', adapter=ProjectAdapter(), multi_select=True), width=175), show_border=True, label='Projects') sample_grp = VGroup( HGroup( UItem('sample_filter_parameter', editor=EnumEditor(name='sample_filter_parameters')), UItem('sample_filter', editor=ComboboxEditor(name='sample_filter_values'), width=75), icon_button_editor('edit_sample_button', 'database_edit', tooltip='Edit sample in database'), icon_button_editor('add_sample_button', 'database_add', tooltip='Add sample to database')), UItem('samples', editor=TabularEditor(adapter=self.labnumber_tabular_adapter, editable=False, selected='selected_samples', multi_select=False, column_clicked='column_clicked', stretch_last_section=False), width=75)) jgrp = HGroup(UItem('j'), Label(PLUSMINUS_SIGMA), UItem('j_err'), icon_button_editor('estimate_j_button', 'cog'), show_border=True, label='J') ngrp = HGroup(UItem('note'), UItem('weight'), show_border=True, label='Note') # wgrp = HGroup(UItem('weight'), show_border=True, label='Weight') sgrp = HGroup(UItem('invert_flag'), Item('selection_freq', label='Freq'), show_border=True, label='Selection') v = View( VSplit( VGroup( tgrp, HGroup(sgrp, jgrp), # wgrp, ngrp, project_grp), sample_grp)) return v
class FunctionPlotter(HasTraits): figure = Instance(Figure, ()) #❶ code = Code() #❷ points = List(Instance(Point), []) #❸ draw_button = Button("Plot") view = View( VSplit( Item("figure", editor=MPLFigureEditor(toolbar=True), show_label=False), #❶ HSplit( VGroup( Item("code", style="custom"), #❷ HGroup(Item("draw_button", show_label=False), ), show_labels=False), Item("points", editor=point_table_editor, show_label=False) #❸ )), width=800, height=600, title="Function Plotter", resizable=True) ###2### ###3### def __init__(self, **kw): super(FunctionPlotter, self).__init__(**kw) self.figure.canvas_events = [ #❶ ("button_press_event", self.memory_location), ("button_release_event", self.update_location) ] self.button_press_status = None #保存鼠标按键按下时的状态 self.lines = [] #保存所有曲线 self.functions = [] #保存所有的曲线函数 self.env = {} #代码的执行环境 self.axe = self.figure.add_subplot(1, 1, 1) self.axe.callbacks.connect('xlim_changed', self.update_data) #❷ self.axe.set_xlim(0, 1) self.axe.set_ylim(0, 1) self.points_line, = self.axe.plot([], [], "kx", ms=8, zorder=1000) #数据点 ###3### ###6### def update_data(self, axe): xmin, xmax = axe.get_xlim() x = np.linspace(xmin, xmax, 500) for line, func in zip(self.lines, self.functions): y = func(x) line.set_data(x, y) self.update_figure() ###6### ###4### def memory_location(self, evt): if evt.button in (1, 3): self.button_press_status = time.clock(), evt.x, evt.y else: self.button_press_status = None def update_location(self, evt): if evt.button in (1, 3) and self.button_press_status is not None: last_clock, last_x, last_y = self.button_press_status if time.clock() - last_clock > 0.5: #❶ return if ((evt.x - last_x)**2 + (evt.y - last_y)**2)**0.5 > 4: #❷ return if evt.button == 1: if evt.xdata is not None and evt.ydata is not None: point = Point(x=evt.xdata, y=evt.ydata) #❸ self.points.append(point) elif evt.button == 3: if self.points: self.points.pop() #❹ ###4### ###5### @on_trait_change("points[]") def _points_changed(self, obj, name, new): for point in new: point.on_trait_change(self.update_points, name="x, y") #❶ self.update_points() def update_points(self): #❷ arr = np.array([(point.x, point.y) for point in self.points]) if arr.shape[0] > 0: self.points_line.set_data(arr[:, 0], arr[:, 1]) else: self.points_line.set_data([], []) self.update_figure() def update_figure(self): #❸ if self.figure.canvas is not None: #❹ self.figure.canvas.draw_idle() ###5### ###7### def _draw_button_fired(self): self.plot_lines() def plot_lines(self): xmin, xmax = self.axe.get_xlim() #❶ x = np.linspace(xmin, xmax, 500) self.env = { "points": np.array([(point.x, point.y) for point in self.points]) } #❷ exec self.code in self.env results = [] for line in self.lines: line.remove() self.axe.set_color_cycle(None) #重置颜色循环 self.functions = [] self.lines = [] for name, value in self.env.items(): #❸ if name.startswith("_"): #忽略以_开头的名字 continue if callable(value): try: y = value(x) if y.shape != x.shape: #输出数组应该与输入数组的形状一致 raise ValueError( "the return shape is not the same as x") except Exception as ex: import traceback print "failed when call function {}\n".format(name) traceback.print_exc() continue results.append((name, y)) self.functions.append(value) for (name, y), function in zip(results, self.functions): #如果函数有plot_parameters属性,则用其作为plot()的参数 kw = getattr(function, "plot_parameters", {}) #❹ label = kw.get("label", name) line, = self.axe.plot(x, y, label=label, **kw) self.lines.append(line) points = self.env.get("points", None) #❺ if points is not None: self.points = [ Point(x=x, y=y) for x, y in np.asarray(points).tolist() ] self.axe.legend() self.update_figure()
action='handler.employee_department(editor,object)', ), Separator(), CopyAction, CutAction, PasteAction, Separator(), DeleteAction, Separator(), RenameAction, ), view=View( VSplit( HGroup('3', 'name'), HGroup('9', 'title'), HGroup('phone'), spring, id='vsplit', ), id='traitsui.test.tree_editor_test.employee', dock='vertical', ), ), ]) # ------------------------------------------------------------------------- # 'TreeHandler' class: # ------------------------------------------------------------------------- class TreeHandler(Handler):
class Application(HasTraits): scene = Instance(MlabSceneModel, (), editor=SceneEditor()) # The mayavi engine view. engine_view = Instance(EngineView) # We use a traits List to be able to add coils to it coils = List(Loop, value=( Loop(position=(0, 0, -0.05), ), Loop(position=(0, 0, 0.05), ), ), editor=ListEditor(use_notebook=True, deletable=False, style='custom'), ) # The grid of points on which we want to evaluate the field X, Y, Z = np.mgrid[-0.15:0.15:20j, -0.15:0.15:20j, -0.15:0.15:20j] # Avoid rounding issues: f = 1e4 # this gives the precision we are interested by : X = np.round(X * f) / f Y = np.round(Y * f) / f Z = np.round(Z * f) / f Bx = Array(value=np.zeros_like(X)) By = Array(value=np.zeros_like(X)) Bz = Array(value=np.zeros_like(X)) Bnorm = Array(value=np.zeros_like(X)) field = None def __init__(self, **traits): HasTraits.__init__(self, **traits) self.engine_view = EngineView(engine=self.scene.engine) @on_trait_change('scene.activated') def init_view(self): # This gets fired when the viewer of the scene is created self.scene.scene_editor.background = (0, 0, 0) for coil in self.coils: coil.app = self coil.display() coil.mk_B_field() self.visualize_field() def visualize_field(self): self.Bx = np.zeros_like(self.X) self.By = np.zeros_like(self.X) self.Bz = np.zeros_like(self.X) self.Bnorm = np.zeros_like(self.X) for coil in self.coils: if hasattr(coil, 'Bx'): self.Bx += coil.Bx self.By += coil.By self.Bz += coil.Bz self.Bnorm += coil.Bnorm if self.field is None: self.field = self.scene.mlab.pipeline.vector_field( self.X, self.Y, self.Z, self.Bx, self.By, self.Bz, scalars = self.Bnorm, name='B field') vectors = self.scene.mlab.pipeline.vectors(self.field, mode='arrow', resolution=10, mask_points=6, colormap='YlOrRd', scale_factor=2*np.abs(self.X[0,0,0] -self.X[1,1,1]) ) vectors.module_manager.vector_lut_manager.reverse_lut = True vectors.glyph.mask_points.random_mode = False self.scene.mlab.axes() self.scp = self.scene.mlab.pipeline.scalar_cut_plane(self.field, colormap='hot') else: self.field.mlab_source.set(x=self.X, y=self.Y, z=self.Z, u=self.Bx, v=self.By, w=self.Bz, scalars=self.Bnorm) view = View(HSplit( VSplit(Item(name='engine_view', style='custom', resizable=True), Item('coils', springy=True), show_labels=False), 'scene', show_labels=False), resizable=True, title='Coils...', height=0.8, width=0.8, )
class TFunPWLInteractive(MFnLineArray, BMCSLeafNode, Vis2D): '''Interactive time function. ''' node_name = 'time function' t_values = List(Float, [0]) f_values = List(Float, [0]) def reset(self): self.f_values = [0] self.t_values = [0] self.f_value = self.f_min n_f_values = Int(10, input=True, auto_set=False, enter_set=True) f_min = Float(0.0, input=True, auto_set=False, enter_set=True, label='F minimum') f_max = Float(1.0, input=True, auto_set=False, enter_set=True, label='F maximum') t_ref = Float(1.0, auto_set=False, enter_set=True, label='Initial time range') f_value = Range(low='f_min', high='f_max', value=0, input=True, auto_set=False, enter_set=True) enable_slider = Bool(True, disable_on_run=True) run_eagerly = Bool(True, label='Run eagerly') t_snap = Float(0.1, label='Time step to snap to', auto_set=False, enter_set=True) def __init__(self, *arg, **kw): super(TFunPWLInteractive, self).__init__(*arg, **kw) self.xdata = np.array(self.t_values) self.ydata = np.array(self.f_values) d_t = Property(depends_on='t_ref,n_f_values') @cached_property def _get_d_t(self): return self.t_ref / self.n_f_values def _update_xy_arrays(self): delta_f = self.f_value - self.f_values[-1] self.f_values.append(self.f_value) rel_step = delta_f / (self.f_max - self.f_min) delta_t = rel_step * self.t_ref t_value = np.fabs(delta_t) + self.t_values[-1] n_steps = int(t_value / self.t_snap) + 1 t_value = n_steps * self.t_snap self.t_values.append(t_value) self.xdata = np.array(self.t_values) self.ydata = np.array(self.f_values) self.replot() def _f_value_changed(self): self._update_xy_arrays() t_value = self.t_values[-1] f_value = self.f_values[-1] if self.ui: self.ui.model.set_tmax(t_value) if self.run_eagerly: print('LS-run', t_value, f_value) self.ui.run() def get_ty_data(self, vot): return self.t_values, self.f_values viz2d_classes = { 'time_function': TFViz2D, } tree_view = View( VGroup( VSplit( VGroup( VGroup(Include('actions'), ), Tabbed( VGroup( VGroup( UItem('f_value', full_size=True, resizable=True, enabled_when='enable_slider'), ), VGroup( Item('f_max', full_size=True, resizable=True), Item('f_min', full_size=True), Item('n_f_values', full_size=True), Item('t_snap', tooltip='Snap value to round off' 'the value to', full_size=True), ), spring, label='Steering', ), VGroup( Item( 'run_eagerly', full_size=True, resizable=True, tooltip='True - run calculation immediately' 'after moving the value slider; \nFalse - user must' 'start calculation by clicking Run button'), spring, label='Mode', ), ), ), UItem('figure', editor=MPLFigureEditor(), height=300, resizable=True, springy=True), ), )) traits_view = tree_view
class RTraceDomainListField(RTrace, RTraceDomainList): # sd = Instance( SDomain ) # # rt_domain = Property # def _get_rt_domain(self): # return self.sd.rt_bg_domain label = Str('RTraceDomainField') var = Str('') idx = Int(-1, enter_set=True, auto_set=False) position = Enum('nodes', 'int_pnts') save_on = Enum('update', 'iteration') warp = Bool(False) warp_f = Float(1.) warp_var = Str('u') def bind(self): ''' Locate the evaluators ''' def setup(self): ''' Setup the spatial domain of the tracer ''' for sf in self.subfields: sf.setup() subfields = Property(depends_on='sd.changed_structure') @cached_property def _get_subfields(self): # construct the RTraceDomainFields # return [RTraceDomainField(var=self.var, warp_var=self.warp_var, idx=self.idx, position=self.position, save_on=self.save_on, warp=self.warp, warp_f=self.warp_f, sd=subdomain) for subdomain in self.sd.nonempty_subdomains] # TODO: should depend on the time step vtk_data = Property( Instance(tvtk.UnstructuredGrid), depends_on='write_counter') # @cached_property def _get_vtk_data(self): if self.position == 'nodes': ug = self.vtk_node_structure # vtk_r = self.vtk_node_points # vtk_cell_data = self.vtk_node_cell_data elif self.position == 'int_pnts': ug = self.vtk_ip_structure # vtk_r = self.custom_vtk_r # vtk_cell_data = self.custom_vtk_cell_data # ug = self.vtk_structure field_arr = tvtk.DoubleArray(name=self.name) field_arr.from_array(self._get_field_data()) # TODO:naming ug.point_data.add_array(field_arr) # add data for warping if self.warp: warp_arr = tvtk.DoubleArray(name=self.warp_var) warp_arr.from_array(self._get_warp_data()) ug.point_data.add_array(warp_arr) return ug def redraw(self): '''Delegate the calculation to the pipeline ''' # self.mvp_mgrid_geo.redraw() # 'label_scalars') self.mvp_mgrid_geo.rebuild_pipeline(self.vtk_data) # point offset to use when more fields are patched together within # RTDomainList point_offset = Int(0) # cell offset to use when more fields are patched together within # RTDomainList cell_offset = Int(0) def add_current_values(self, sctx, U_k, *args, **kw): for sf in self.subfields: if sf.skip_domain: continue sf.add_current_values(sctx, U_k, *args, **kw) def add_current_displ(self, sctx, U_k): for sf in self.subfields: if sf.skip_domain: continue sf.rmgr = self.rmgr sf.add_current_displ(sctx, U_k) def register_mv_pipelines(self, e): pass # for sf in self.subfields: # sf.register_mv_pipelines( e ) writer = tvtk.UnstructuredGridWriter(file_type='binary') write_counter = Int(0) def write(self): '''Generate the file name within the write_dir and submit the request for writing to the writer ''' # self.writer.scalars_name = self.name file_base_name = self.var + '%(direction)d%(pos)s_%(step)d.vtk' \ % {'direction': (self.idx + 1), "pos": self.position, "step": self.write_counter} # full path to the data file file_name = os.path.join(self.dir, file_base_name) self.writer.input = self.vtk_data self.writer.file_name = file_name self.write_counter += 1 self.writer.write() def timer_tick(self, e=None): # self.changed = True pass def clear(self): for sf in self.subfields: sf.clear() def _get_warp_data(self): vectors_arr_list = [] for sf in self.subfields: if sf.skip_domain: continue sf_warp_data = sf._get_warp_data() if sf_warp_data == None: # all elem are deactivated continue vectors_arr_list.append(sf_warp_data) if len(vectors_arr_list) > 0: return vstack(vectors_arr_list) else: return zeros((0, 3), dtype='float_') def _get_field_data(self): tensors_arr_list = [] for sf in self.subfields: if sf.skip_domain: continue sf_field_data = sf._get_field_data() if sf_field_data == None: # all elem are deactivated continue tensors_arr_list.append(sf_field_data) if len(tensors_arr_list) > 0: return vstack(tensors_arr_list) else: return zeros((0, 3), dtype='float_') #------------------------------------------------------------------------- # Visualization pipelines #------------------------------------------------------------------------- mvp_mgrid_geo = Trait(MVUnstructuredGrid) def _mvp_mgrid_geo_default(self): return MVUnstructuredGrid(name=self.name, warp=self.warp, warp_var=self.warp_var ) view = View(HSplit(VSplit(VGroup('var', 'idx'), VGroup('record_on', 'clear_on'), Item('refresh_button', show_label=False), ), ), resizable=True)
# Cached ylims ylims = None # Figure to display selected dataset and axes for figure figure = Instance(Figure, ()) # -----------------------------------------------------------# # Main Control Panel View ControlPanelView = View(HSplit( UItem('sofq_plot', width=0.8, style='custom', editor=InstanceEditor()), VSplit( UItem('experiment_file', height=0.1, style='custom', editor=InstanceEditor()), UItem('controls', height=0.9, style='custom', editor=InstanceEditor()), ), ), resizable=True, statusbar=[StatusItem(name='load_status')]) # -----------------------------------------------------------# # Main Control Panel Controller class ControlPanelHandler(Handler): def get_parents(self, info, node): # Grab selected Dataset selected = info.object.selected
class SwiftConsole(HasTraits): """Traits-defined Swift Console. link : object Serial driver update : bool Update the firmware log_level_filter : str Syslog string, one of "ERROR", "WARNING", "INFO", "DEBUG". skip_settings : bool Don't read the device settings. Set to False when the console is reading from a network connection only. """ link = Instance(sbpc.Handler) console_output = Instance(OutputList()) python_console_env = Dict device_serial = Str('') dev_id = Str('') tracking_view = Instance(TrackingView) solution_view = Instance(SolutionView) baseline_view = Instance(BaselineView) observation_view = Instance(ObservationView) networking_view = Instance(SbpRelayView) observation_view_base = Instance(ObservationView) system_monitor_view = Instance(SystemMonitorView) settings_view = Instance(SettingsView) update_view = Instance(UpdateView) imu_view = Instance(IMUView) log_level_filter = Enum(list(SYSLOG_LEVELS.itervalues())) """" mode : baseline and solution view - SPP, Fixed or Float num_sat : baseline and solution view - number of satellites port : which port is Swift Device is connected to directory_name : location of logged files json_logging : enable JSON logging csv_logging : enable CSV logging """ mode = Str('') num_sats = Int(0) cnx_desc = Str('') latency = Str('') directory_name = Directory json_logging = Bool(True) csv_logging = Bool(False) cnx_icon = Str('') heartbeat_count = Int() last_timer_heartbeat = Int() solid_connection = Bool(False) csv_logging_button = SVGButton( toggle=True, label='CSV log', tooltip='start CSV logging', toggle_tooltip='stop CSV logging', filename=os.path.join(determine_path(), 'images', 'iconic', 'pause.svg'), toggle_filename=os.path.join(determine_path(), 'images', 'iconic', 'play.svg'), orientation = 'vertical', width=2, height=2, ) json_logging_button = SVGButton( toggle=True, label='JSON log', tooltip='start JSON logging', toggle_tooltip='stop JSON logging', filename=os.path.join(determine_path(), 'images', 'iconic', 'pause.svg'), toggle_filename=os.path.join(determine_path(), 'images', 'iconic', 'play.svg'), orientation = 'vertical', width=2, height=2, ) paused_button = SVGButton( label='', tooltip='Pause console update', toggle_tooltip='Resume console update', toggle=True, filename=os.path.join(determine_path(), 'images', 'iconic', 'pause.svg'), toggle_filename=os.path.join(determine_path(), 'images', 'iconic', 'play.svg'), width=8, height=8 ) clear_button = SVGButton( label='', tooltip='Clear console buffer', filename=os.path.join(determine_path(), 'images', 'iconic', 'x.svg'), width=8, height=8 ) view = View( VSplit( Tabbed( Item('tracking_view', style='custom', label='Tracking'), Item('solution_view', style='custom', label='Solution'), Item('baseline_view', style='custom', label='Baseline'), VSplit( Item('observation_view', style='custom', show_label=False), Item('observation_view_base', style='custom', show_label=False), label='Observations', ), Item('settings_view', style='custom', label='Settings'), Item('update_view', style='custom', label='Firmware Update'), Tabbed( Item('system_monitor_view', style='custom', label='System Monitor'), Item('imu_view', style='custom', label='IMU'), Item('networking_view', label='Networking', style='custom', show_label=False), Item('python_console_env', style='custom', label='Python Console', editor=ShellEditor()), label='Advanced', show_labels=False ), show_labels=False ), VGroup( VGroup( HGroup( Spring(width=4, springy=False), Item('paused_button', show_label=False, padding=0, width=8, height=8), Item('clear_button', show_label=False, width=8, height=8), Item('', label='Console Log', emphasized=True), Item('csv_logging_button', emphasized=True, show_label=False, width=12, height=-30, padding=0), Item('json_logging_button', emphasized=True, show_label=False, width=12, height=-30, padding=0), Item('directory_name', show_label=False, springy=True, tooltip='Choose location for file logs. Default is home/SwiftNav.', height=-25, enabled_when='not(json_logging or csv_logging)', editor_args={'auto_set':True}), UItem('log_level_filter', style='simple', padding=0, height=8, show_label=True, tooltip='Show log levels up to and including the selected level of severity.\nThe CONSOLE log level is always visible.'), ), Item( 'console_output', style='custom', editor=InstanceEditor(), height=125, show_label=False, full_size=True ), ), HGroup( Spring(width=4, springy=False), Item('', label='Interface:', emphasized=True, tooltip='Interface for communicating with Swift device'), Item('cnx_desc', show_label=False, style = 'readonly'), Item('', label='FIX TYPE:', emphasized = True, tooltip='Device Mode: SPS, Float RTK, Fixed RTK'), Item('mode', show_label = False, style = 'readonly'), Item('', label='#Sats:', emphasized=True, tooltip='Number of satellites used in solution'), Item('num_sats', padding=2, show_label=False, style = 'readonly'), Item('', label='Base Latency:', emphasized=True, tooltip='Corrections latency (-1 means no corrections)'), Item('latency', padding=2, show_label=False, style = 'readonly'), Spring(springy=True), Item('cnx_icon', show_label = False, padding=0, width=8, height=8, visible_when='solid_connection', springy=False, editor=ImageEditor(allow_clipping=False, image = ImageResource( 'arrows_blue.png', search_path=[os.path.join(determine_path(), 'images', 'iconic')]))), Item('cnx_icon', show_label = False, padding=0, width=8, height=8, visible_when='not solid_connection', springy=False, editor=ImageEditor(allow_clipping=False, image = ImageResource( 'arrows_grey.png', search_path=[os.path.join(determine_path(), 'images', 'iconic')]))), Spring(width=4, height=-2, springy=False), ), Spring(height=1, springy=False), ), ), icon=icon, resizable=True, width=800, height=600, handler=ConsoleHandler(), title=CONSOLE_TITLE ) def print_message_callback(self, sbp_msg, **metadata): try: encoded = sbp_msg.payload.encode('ascii', 'ignore') for eachline in reversed(encoded.split('\n')): self.console_output.write_level(eachline, str_to_log_level(eachline.split(':')[0])) except UnicodeDecodeError: print "Critical Error encoding the serial stream as ascii." def log_message_callback(self, sbp_msg, **metadata): try: encoded = sbp_msg.text.encode('ascii', 'ignore') for eachline in reversed(encoded.split('\n')): self.console_output.write_level(eachline, sbp_msg.level) except UnicodeDecodeError: print "Critical Error encoding the serial stream as ascii." def ext_event_callback(self, sbp_msg, **metadata): e = MsgExtEvent(sbp_msg) print 'External event: %s edge on pin %d at wn=%d, tow=%d, time qual=%s' % ( "Rising" if (e.flags & (1<<0)) else "Falling", e.pin, e.wn, e.tow, "good" if (e.flags & (1<<1)) else "unknown") def cmd_resp_callback(self, sbp_msg, **metadata): r = MsgCommandResp(sbp_msg) print "Received a command response message with code {0}".format( r.code) def _paused_button_fired(self): self.console_output.paused = not self.console_output.paused def _log_level_filter_changed(self): """ Takes log level enum and translates into the mapped integer. Integer stores the current filter value inside OutputList. """ self.console_output.log_level_filter = str_to_log_level(self.log_level_filter) def _clear_button_fired(self): self.console_output.clear() def _directory_name_changed(self): if self.baseline_view and self.solution_view: self.baseline_view.directory_name_b = self.directory_name self.solution_view.directory_name_p = self.directory_name self.solution_view.directory_name_v = self.directory_name if self.observation_view and self.observation_view_base: self.observation_view.dirname = self.directory_name self.observation_view_base.dirname = self.directory_name def check_heartbeat(self): # if our heartbeat hasn't changed since the last timer interval the connection must have dropped if self.heartbeat_count == self.last_timer_heartbeat: self.solid_connection = False else: self.solid_connection = True self.last_timer_heartbeat = self.heartbeat_count def update_on_heartbeat(self, sbp_msg, **metadata): self.heartbeat_count += 1 # First initialize the state to nothing, if we can't update, it will be none temp_mode = "None" temp_num_sats = 0 view = None if self.baseline_view and self.solution_view: # If we have a recent baseline update, we use the baseline info if time.time() - self.baseline_view.last_btime_update < 10: view = self.baseline_view # Otherwise, if we have a recent SPP update, we use the SPP elif time.time() - self.solution_view.last_stime_update < 10: view = self.solution_view if view: if view.last_soln: # if all is well we update state temp_mode = mode_dict.get(get_mode(view.last_soln), EMPTY_STR) temp_num_sats = view.last_soln.n_sats self.mode = temp_mode self.num_sats = temp_num_sats if self.settings_view: # for auto populating surveyed fields self.settings_view.lat = self.solution_view.latitude self.settings_view.lon = self.solution_view.longitude self.settings_view.alt = self.solution_view.altitude if self.system_monitor_view: if self.system_monitor_view.msg_obs_window_latency_ms != -1: self.latency = "{0} ms".format(self.system_monitor_view.msg_obs_window_latency_ms) else: self.latency = EMPTY_STR def _csv_logging_button_action(self): if self.csv_logging and self.baseline_view.logging_b and self.solution_view.logging_p and self.solution_view.logging_v: print "Stopped CSV logging" self.csv_logging = False self.baseline_view.logging_b = False self.solution_view.logging_p = False self.solution_view.logging_v = False else: print "Started CSV logging at %s" % self.directory_name self.csv_logging = True self.baseline_view.logging_b = True self.solution_view.logging_p = True self.solution_view.logging_v = True def _start_json_logging(self, override_filename=None): if override_filename: filename = override_filename else: filename = time.strftime("swift-gnss-%Y%m%d-%H%M%S.sbp.json") filename = os.path.normpath(os.path.join(self.directory_name, filename)) self.logger = s.get_logger(True, filename) self.forwarder = sbpc.Forwarder(self.link, self.logger) self.forwarder.start() if self.settings_view: self.settings_view._settings_read_button_fired() def _stop_json_logging(self): fwd = self.forwarder fwd.stop() self.logger.flush() self.logger.close() def _json_logging_button_action(self): if self.first_json_press and self.json_logging: print "JSON Logging initiated via CMD line. Please press button again to stop logging" elif self.json_logging: self._stop_json_logging() self.json_logging = False print "Stopped JSON logging" else: self._start_json_logging() self.json_logging = True self.first_json_press = False def _json_logging_button_fired(self): if not os.path.exists(self.directory_name) and not self.json_logging: confirm_prompt = CallbackPrompt( title="Logging directory creation", actions=[ok_button], callback=self._json_logging_button_action ) confirm_prompt.text = "\nThe selected logging directory does not exist and will be created." confirm_prompt.run(block=False) else: self._json_logging_button_action() def _csv_logging_button_fired(self): if not os.path.exists(self.directory_name) and not self.csv_logging: confirm_prompt = CallbackPrompt( title="Logging directory creation", actions=[ok_button], callback=self._csv_logging_button_action ) confirm_prompt.text = "\nThe selected logging directory does not exist and will be created." confirm_prompt.run(block=False) else: self._csv_logging_button_action() def __enter__(self): return self def __exit__(self, exc_type, exc_value, traceback): self.console_output.close() def __init__(self, link, update, log_level_filter, skip_settings=False, error=False, cnx_desc=None, json_logging=False, log_dirname=None, override_filename=None, log_console=False, skylark="", serial_upgrade=False): self.error = error self.cnx_desc = cnx_desc self.dev_id = cnx_desc self.num_sats = 0 self.mode = '' self.forwarder = None self.latency = '--' # if we have passed a logfile, we set our directory to it override_filename = override_filename home = expanduser("~") swift_path = os.path.normpath(os.path.join(home, 'SwiftNav')) if log_dirname: self.directory_name = log_dirname if override_filename: override_filename = os.path.join(log_dirname, override_filename) else: self.directory_name = swift_path # Start swallowing sys.stdout and sys.stderr self.console_output = OutputList(tfile=log_console, outdir=self.directory_name) sys.stdout = self.console_output self.console_output.write("Console: " + CONSOLE_VERSION + " starting..." ) if not error: sys.stderr = self.console_output self.log_level_filter = log_level_filter self.console_output.log_level_filter = str_to_log_level(log_level_filter) try: self.link = link self.link.add_callback(self.print_message_callback, SBP_MSG_PRINT_DEP) self.link.add_callback(self.log_message_callback, SBP_MSG_LOG) self.link.add_callback(self.ext_event_callback, SBP_MSG_EXT_EVENT) self.link.add_callback(self.cmd_resp_callback, SBP_MSG_COMMAND_RESP) self.link.add_callback(self.update_on_heartbeat, SBP_MSG_HEARTBEAT) self.dep_handler = DeprecatedMessageHandler(link) settings_read_finished_functions = [] self.tracking_view = TrackingView(self.link) self.solution_view = SolutionView(self.link, dirname=self.directory_name) self.baseline_view = BaselineView(self.link, dirname=self.directory_name) self.observation_view = ObservationView(self.link, name='Local', relay=False, dirname=self.directory_name) self.observation_view_base = ObservationView(self.link, name='Remote', relay=True, dirname=self.directory_name) self.system_monitor_view = SystemMonitorView(self.link) self.update_view = UpdateView(self.link, download_dir=swift_path, prompt=update, serial_upgrade=serial_upgrade) self.imu_view = IMUView(self.link) settings_read_finished_functions.append(self.update_view.compare_versions) if skylark: import yaml try: skylark_dict = yaml.load(skylark) except yaml.YAMLError: print "Unable to interpret Skylark cmdline argument. It will be ignored." import traceback print traceback.format_exc() skylark_dict = {} else: skylark_dict = {} self.networking_view = SbpRelayView(self.link, **skylark_dict) self.json_logging = json_logging self.csv_logging = False self.first_json_press = True if json_logging: self._start_json_logging(override_filename) self.json_logging = True # we set timer interval to 1200 milliseconds because we expect a heartbeat each second self.timer_cancel = call_repeatedly(1.2, self.check_heartbeat) # Once we have received the settings, update device_serial with # the Swift serial number which will be displayed in the window # title. This callback will also update the header route as used # by the networking view. def update_serial(): uuid = None mfg_id = None try: uuid = self.settings_view.settings['system_info']['uuid'].value mfg_id = self.settings_view.settings['system_info']['serial_number'].value except KeyError: pass if mfg_id: self.device_serial = 'PK' + str(mfg_id)[-6:] self.networking_view.set_route(uuid=uuid, serial_id=mfg_id) if self.networking_view.connect_when_uuid_received: self.networking_view._connect_rover_fired() settings_read_finished_functions.append(update_serial) self.settings_view = SettingsView(self.link, settings_read_finished_functions, skip=skip_settings) self.update_view.settings = self.settings_view.settings self.python_console_env = { 'send_message': self.link, 'link': self.link, } self.python_console_env.update(self.tracking_view.python_console_cmds) self.python_console_env.update(self.solution_view.python_console_cmds) self.python_console_env.update(self.baseline_view.python_console_cmds) self.python_console_env.update(self.observation_view.python_console_cmds) self.python_console_env.update(self.networking_view.python_console_cmds) self.python_console_env.update(self.system_monitor_view.python_console_cmds) self.python_console_env.update(self.update_view.python_console_cmds) self.python_console_env.update(self.imu_view.python_console_cmds) self.python_console_env.update(self.settings_view.python_console_cmds) except: import traceback traceback.print_exc() if self.error: sys.exit(1)
class Mayavi(HasTraits): # The scene model. scene = Instance(MlabSceneModel, ()) # The mayavi engine view. engine_view = Instance(EngineView) # The current selection in the engine tree view. current_selection = Property ###################### view = View(HSplit( VSplit( Item(name='engine_view', style='custom', resizable=True, show_label=False), Item(name='current_selection', editor=InstanceEditor(), enabled_when='current_selection is not None', style='custom', springy=True, show_label=False), ), Item(name='scene', editor=SceneEditor(), show_label=False, resizable=True, height=500, width=500), ), resizable=True, scrollable=True) def __init__(self, **traits): HasTraits.__init__(self, **traits) self.engine_view = EngineView(engine=self.scene.engine) # Hook up the current_selection to change when the one in the engine # changes. This is probably unnecessary in Traits3 since you can show # the UI of a sub-object in T3. self.scene.engine.on_trait_change(self._selection_change, 'current_selection') self.generate_data_mayavi() def generate_data_mayavi(self): """Shows how you can generate data using mayavi instead of mlab.""" from mayavi.sources.api import ParametricSurface from mayavi.modules.api import Outline, Surface e = self.scene.engine s = ParametricSurface() e.add_source(s) e.add_module(Outline()) e.add_module(Surface()) def _selection_change(self, old, new): self.trait_property_changed('current_selection', old, new) def _get_current_selection(self): return self.scene.engine.current_selection