class Range2DPluginOp(Range2DOp, PluginOpMixin): handler_factory = Callable(Range2DHandler, transient = True) xlow = CFloat xhigh = CFloat ylow = CFloat yhigh = CFloat def default_view(self, **kwargs): return Range2DSelectionView(op = self, **kwargs) def get_notebook_code(self, idx): op = Range2DOp() op.copy_traits(self, op.copyable_trait_names()) return dedent(""" op_{idx} = {repr} ex_{idx} = op_{idx}.apply(ex_{prev_idx}) """ .format(repr = repr(op), idx = idx, prev_idx = idx - 1))
class BleedthroughPiecewisePluginView(PluginViewMixin, BleedthroughPiecewiseDiagnostic): handler_factory = Callable(BleedthroughPiecewiseViewHandler) subset = DelegatesTo('op', transient=True) def plot_wi(self, wi): self.plot(wi.previous_wi.result) def should_plot(self, changed, payload): if changed == Changed.ESTIMATE_RESULT: return True return False def get_notebook_code(self, idx): view = BleedthroughPiecewiseDiagnostic() view.copy_traits(self, view.copyable_trait_names()) view.subset = self.subset return dedent(""" op_{idx}.default_view({traits}).plot(ex_{prev_idx}) """.format(traits=traits_str(view), idx=idx, prev_idx=idx - 1))
class AutofluorescencePluginOp(PluginOpMixin, AutofluorescenceOp): handler_factory = Callable(AutofluorescenceHandler) channels = List(Str, estimate = True) blank_file = File(filter = ["*.fcs"], estimate = True) @on_trait_change('channels_items', post_init = True) def _channels_changed(self, obj, name, old, new): self.changed = "estimate" def default_view(self, **kwargs): return AutofluorescencePluginView(op = self, **kwargs) def estimate(self, experiment): if not self.subset: warnings.warn("Are you sure you don't want to specify a subset " "used to estimate the model?", util.CytoflowOpWarning) AutofluorescenceOp.estimate(self, experiment, subset = self.subset) self.changed = "estimate_result" def clear_estimate(self): self._af_median.clear() self._af_stdev.clear() self.changed = "estimate_result" def should_clear_estimate(self, changed): """ Should the owning WorkflowItem clear the estimated model by calling op.clear_estimate()? `changed` can be: - "estimate" -- the parameters required to call 'estimate()' (ie traits with estimate = True metadata) have changed - "prev_result" -- the previous WorkflowItem's result changed """ if changed == "prev_result": return False return True
class PolygonPluginOp(PluginOpMixin, PolygonOp): handler_factory = Callable(PolygonHandler) @on_trait_change('xchannel, ychannel, xscale, yscale', post_init = True) def _reset_polygon(self): self.vertices = [] def default_view(self, **kwargs): return PolygonSelectionView(op = self, **kwargs) def get_notebook_code(self, idx): op = PolygonOp() op.copy_traits(self, op.copyable_trait_names()) return dedent(""" op_{idx} = {repr} ex_{idx} = op_{idx}.apply(ex_{prev_idx}) """ .format(repr = repr(op), idx = idx, prev_idx = idx - 1))
class ThresholdSelectionView(PluginViewMixin, ThresholdSelection): handler_factory = Callable(ThresholdViewHandler, transient=True) op = Instance(IOperation, fixed=True) threshold = DelegatesTo('op', status=True) name = Str def should_plot(self, changed, payload): if changed == Changed.PREV_RESULT or changed == Changed.VIEW: return True else: return False def plot_wi(self, wi): self.plot(wi.previous_wi.result) def get_notebook_code(self, idx): view = ThresholdSelection() view.copy_traits(self, view.copyable_trait_names()) return dedent(""" op_{idx}.default_view({traits}).plot(ex_{prev_idx}) """.format(idx=idx, traits=traits_str(view), prev_idx=idx - 1))
class CommandAction(Action): """The CommandAction class is an Action class that wraps undo/redo commands. It is only useful for commands that do not take any arguments or return any result. """ #### 'CommandAction' interface ############################################ #: The command to create when the action is performed. command = Callable() #: The command stack onto which the command will be pushed when the action #: is performed. command_stack = Instance(ICommandStack) #: This is the data on which the command operates. data = Any() ########################################################################### # 'Action' interface. ########################################################################### def perform(self, event): """This is reimplemented to push a new command instance onto the command stack. """ self.command_stack.push(self.command(data=self.data)) def _name_default(self): """ This gets the action name from the command. """ if self.command: name = self.command().name else: name = "" return name
class HistogramPluginView(PluginViewMixin, HistogramView): handler_factory = Callable(HistogramHandler, transient=True) plotfacet = Str plot_params = Instance(HistogramPlotParams, ()) def enum_plots_wi(self, wi): if not self.plotfacet: return iter([]) if self.plotfacet and self.plotfacet not in wi.result.conditions: raise util.CytoflowViewError( "Plot facet {0} not in the experiment".format(self.huefacet)) values = np.sort(pd.unique(wi.result[self.plotfacet])) return IterWrapper(iter(values), [self.plotfacet]) def plot(self, experiment, plot_name=None, **kwargs): if experiment is None: raise util.CytoflowViewError("No experiment specified") if self.plotfacet and plot_name is not None: experiment = experiment.subset(self.plotfacet, plot_name) HistogramView.plot(self, experiment, **kwargs) def get_notebook_code(self, idx): view = HistogramView() view.copy_traits(self, view.copyable_trait_names()) plot_params_str = traits_str(self.plot_params) return dedent(""" {repr}.plot(ex_{idx}{plot}{plot_params}) """.format(repr=repr(view), idx=idx, plot=", plot_name = " + repr(self.current_plot) if self.plot_names else "", plot_params=", " + plot_params_str if plot_params_str else ""))
class PythonFunctionFactory(FactoryBase): # The code should contain a single function called "process" which is # called with the arguments: relpath, media, dest. relpath is the key of # the media instance in the project dictionary, dest is the destination # directory, this can be empty if not specified. code = Str _func = Callable(transient=True) name = 'PythonFunctionFactory' def make_jobs(self, media_keys, project): self._setup_func() jobs = [] for key in media_keys: media = project.get(key) relpath = media.relpath if not self._done.get(media.path, False): info = "Processing %s" % media.path job = Job(func=self._run, args=[relpath, media, self.dest], info=info) jobs.append(job) return jobs def _setup_func(self): ns = {} code_obj = compile(self.code, '<string>', 'exec') exec(code_obj, ns) self._func = ns['process'] def _run(self, relpath, media, dest): self._func(relpath, media, dest) self._done[media.path] = True def _code_default(self): return "def process(relpath, media, dest): pass"
class Model(HasTraits): text = Unicode() # Make sure we notify every time this is set, even if ``120 == 120.0``. value = Any(comparison_mode=NO_COMPARE) evaluator_func = Callable(int) def default_traits_view(self): traits_view = View( Bound( FormLayout( (u'Text:', TextField(id='field')), (u'Kind:', EnumDropDown(id='combo', values=[ (int, u'Integer'), (float, u'Float'), ])), (u'Value:', Label(id='value')), (u'Text:', Label(id='text')), ), 'field.value := object.text', 'combo.value := object.evaluator_func', 'field.validator << PythonEvalidator(object.evaluator_func)', 'value.text << repr(object.value)', 'text.text << object.text', extra_context=dict(PythonEvalidator=PythonEvalidator), ), resizable=True, ) return traits_view @on_trait_change('text,evaluator_func') def _update_value(self): try: value = self.evaluator_func(self.text) except (TraitError, TypeError, ValueError): value = None self.value = value
class TablePluginView(PluginViewMixin, TableView): handler_factory = Callable(TableHandler) export = Event() # return the result for export result = Instance(pd.Series, status = True) def plot(self, experiment, plot_name = None, **kwargs): TableView.plot(self, experiment, **kwargs) self.result = experiment.statistics[self.statistic] def get_notebook_code(self, idx): view = TableView() view.copy_traits(self, view.copyable_trait_names()) return dedent(""" {repr}.plot(ex_{idx}) """ .format(repr = repr(view), idx = idx)) @on_trait_change('export') def _on_export(self): dialog = DefaultFileDialog(parent = None, action = 'save as', default_suffix = "csv", wildcard = (FileDialog.create_wildcard("CSV", "*.csv") + ';' + #@UndefinedVariable FileDialog.create_wildcard("All files", "*"))) #@UndefinedVariable if dialog.open() != OK: return data = pd.DataFrame(index = self.result.index) data[self.result.name] = self.result self._export_data(data, self.result.name, dialog.path)
class VersionInfo(HasTraits): """ Represents the information about a particular version of an application. """ # The version string that this version = Str() # Customer-facing notes about this version. Typically this is an # HTML document containing the changelog between this version and # the previous version notes = Str() # The location of where to obtain this version. Typically this will # be an HTTP URL, but this can be a URI for a local or LAN item, or # it can be a location = Str() # A function that takes a string (self.version) and returns something # that can be used to compare against the version-parsed version of # another VersionInfo object. version_parser = Callable() def __cmp__(self, other): """ Allows for comparing two VersionInfo objects so they can be presented in version-sorted order. This is where we parse and interpretation of the **version** string attribute. """ # TODO: Do something more intelligent here if self.version_parser is not None: self_ver = self.version_parser(self.version) else: self_ver = self.version if other.version_parser is not None: other_ver = other.version_parser(other.version) else: other_ver = other.version return self_ver < other_ver
class VolumeSlice(Pipeline): """ Plots an interactive image plane sliced through a 3D volume of data supplied as argument. **Function signatures**:: volume_slice(scalars, ...) volume_slice(x, y, z, scalars, ...) scalars is a 3D numpy arrays giving the data on a grid. If 4 arrays, (x, y, z, scalars) are passed, the 3 first arrays give the position, and the last the scalar value. The x, y and z arrays are then supposed to have been generated by `numpy.mgrid`, in other words, they are 3D arrays, with positions lying on a 3D orthogonal and regularly spaced grid with nearest neighbor in space matching nearest neighbor in the array. The function builds a scalar field assuming the points are regularly spaced.""" _source_function = Callable(scalar_field) _pipeline = [ImagePlaneWidgetFactory, ]
class ColorTranslationPluginView(PluginViewMixin, ColorTranslationDiagnostic): handler_factory = Callable(ColorTranslationViewHandler) def plot_wi(self, wi): self.plot(wi.previous_wi.result) def should_plot(self, changed, payload): if changed == Changed.ESTIMATE_RESULT: return True return False def get_notebook_code(self, idx): view = ColorTranslationDiagnostic() view.copy_traits(self, view.copyable_trait_names()) view.subset = self.subset return dedent(""" op_{idx}.default_view({traits}).plot(ex_{prev_idx}) """ .format(traits = traits_str(view), idx = idx, prev_idx = idx - 1))
class GaussianMixture2DPluginView(PluginViewMixin, GaussianMixture2DView): handler_factory = Callable(GaussianMixture2DViewHandler) op = Instance(IOperation, fixed=True) subset = DelegatesTo('op', transient=True) by = DelegatesTo('op', status=True) def plot_wi(self, wi): if wi.current_view_plot_names: self.plot(wi.previous_wi.result, plot_name=wi.current_plot) else: self.plot(wi.previous_wi.result) def enum_plots_wi(self, wi): try: return self.enum_plots(wi.previous_wi.result) except: return [] def should_plot(self, changed): if changed == Changed.RESULT: return False return True
class CustomEditor(BasicEditorFactory): """Editor factory for custom editors.""" #: Editor class to be instantiated. klass = Property() #: Factory function used to create the custom control factory = Callable() #: Arguments to be passed to the user's custom editor factory args = Tuple() def __init__(self, *args, **traits): if len(args) >= 1: self.factory = args[0] self.args = args[1:] super().__init__(**traits) # ------------------------------------------------------------------------- # Property getters # ------------------------------------------------------------------------- def _get_klass(self): """Returns the editor class to be created.""" return toolkit_object("custom_editor:CustomEditor")
class Plot3d(Pipeline): """ Draws lines between points. **Function signatures**:: plot3d(x, y, z, ...) plot3d(x, y, z, s, ...) x, y, z and s are numpy arrays or lists of the same shape. x, y and z give the positions of the successive points of the line. s is an optional scalar value associated with each point.""" tube_radius = Trait(0.025, CFloat, None, adapts='filter.radius', help="""radius of the tubes used to represent the lines, If None, simple lines are used. """) _source_function = Callable(line_source) _pipeline = [StripperFactory, TubeFactory, SurfaceFactory, ] def __call_internal__(self, *args, **kwargs): """ Override the call to be able to choose whether to apply filters. """ self.source = self._source_function(*args, **kwargs) kwargs.pop('name', None) self.store_kwargs(kwargs) # Copy the pipeline so as not to modify it for the next call self.pipeline = self._pipeline[:] if self.kwargs['tube_radius'] is None: self.pipeline.remove(TubeFactory) self.pipeline.remove(StripperFactory) return self.build_pipeline()
class ToolBarSchema(Schema): """ A schema for a Pyface ToolBarManager. """ #: Assign a default ID for tool bar schemas. id = "ToolBar" #: The tool bar's user visible name. Note that this name may not be used on #: all platforms. name = Str("Tool Bar") #: The size of tool images (width, height). image_size = Tuple((16, 16)) #: The orientation of the toolbar. orientation = Enum("horizontal", "vertical") #: Should we display the horizontal divider? show_divider = Bool(True) #: Should we display the name of each tool bar tool under its image? show_tool_names = Bool(True) #: A factory for instantiating a pyface ToolBarManager tool_bar_manager_factory = Callable(ToolBarManager) def create(self, children): traits = dict( id=self.id, name=self.name, image_size=self.image_size, orientation=self.orientation, show_divider=self.show_divider, show_tool_names=self.show_tool_names, ) return self.tool_bar_manager_factory(*children, **traits)
class Contour3d(Pipeline): """ Plots iso-surfaces for a 3D volume of data suplied as arguments. **Function signatures**:: contour3d(scalars, ...) contour3d(x, y, z, scalars, ...) scalars is a 3D numpy arrays giving the data on a grid. If 4 arrays, (x, y, z, scalars) are passed, the 3 first arrays give the position, and the last the scalar value. The x, y and z arrays are then supposed to have been generated by `numpy.mgrid`, in other words, they are 3D arrays, with positions lying on a 3D orthogonal and regularly spaced grid with nearest neighbor in space matching nearest neighbor in the array. The function builds a scalar field assuming the points are regularly spaced.""" _source_function = Callable(scalar_field) _pipeline = [ IsoSurfaceFactory, ]
class NotUsedAnyMore: # dimension dependent tensor mappings # map_tns4_to_tns2 = Callable(map3d_tns4_to_tns2, transient=True) map_eps_eng_to_mtx = Callable(map3d_eps_eng_to_mtx, transient=True) map_sig_eng_to_mtx = Callable(map3d_sig_eng_to_mtx, transient=True) compliance_mapping = Callable(compliance_mapping3d, transient=True) map_sig_mtx_to_eng = Callable(map3d_sig_mtx_to_eng, transient=True) map_eps_mtx_to_eng = Callable(map3d_eps_mtx_to_eng, transient=True) def _get_explorer_config(self): '''Get the specific configuration of this material model in the explorer ''' c = super(MATS3DEval, self)._get_explorer_config() from ibvpy.api import TLine from ibvpy.mats.mats3D.mats3D_explorer_bcond import BCDofProportional3D # overload the default configuration c['bcond_list'] = [ BCDofProportional3D(max_strain=0.005, phi=0., theta=pi / 2.) ] c['tline'] = TLine(step=0.05, max=1) return c
from .include import Include # ------------------------------------------------------------------------- # Trait definitions: # ------------------------------------------------------------------------- # Name of the view trait: AnId = Str(desc="the name of the view") # Contents of the view trait (i.e., a single Group object): Content = Instance(Group, desc="the content of the view") # An optional model/view factory for converting the model into a viewable # 'model_view' object AModelView = Callable( desc="the factory function for converting a model " "into a model/view object" ) # Reference to a Handler object trait: AHandler = Any(desc="the handler for the view") # Dialog window title trait: ATitle = Str(desc="the window title for the view") # User interface 'kind' trait. The values have the following meanings: # # * 'panel': An embeddable panel. This type of window is intended to be used as # part of a larger interface. # * 'subpanel': An embeddable panel that does not display command buttons, # even if the View specifies them. # * 'modal': A modal dialog box that operates on a clone of the object until
class TasbeCalibrationView(PluginViewMixin): handler_factory = Callable(TasbeViewHandler) op = Instance(TasbeCalibrationOp) id = "edu.mit.synbio.cytoflowgui.op_plugins.tasbe" friendly_id = "TASBE Calibration" name = Constant("TASBE Calibration") fsc_channel = DelegatesTo('op') ssc_channel = DelegatesTo('op') _polygon_view = Instance(PolygonSelection, transient = True) interactive = Property(Bool) def _get_interactive(self): if self._polygon_view: return self._polygon_view.interactive else: return False def _set_interactive(self, val): if self._polygon_view: self._polygon_view.interactive = val def plot_wi(self, wi): self.plot(None, plot_name = self.current_plot) def enum_plots(self, experiment): return iter(["Morphology", "Autofluorescence", "Bleedthrough", "Bead Calibration", "Color Translation"]) def enum_plots_wi(self, wi): return iter(["Morphology", "Autofluorescence", "Bleedthrough", "Bead Calibration", "Color Translation"]) def should_plot(self, changed, payload): """ Should the owning WorkflowItem refresh the plot when certain things change? `changed` can be: - Changed.VIEW -- the view's parameters changed - Changed.RESULT -- this WorkflowItem's result changed - Changed.PREV_RESULT -- the previous WorkflowItem's result changed - Changed.ESTIMATE_RESULT -- the results of calling "estimate" changed """ if changed == Changed.VIEW: _, name, _ = payload if self.current_plot == 'Morphology' and (name == 'fsc_channel' or name == 'ssc_channel'): return True elif name == 'current_plot': return True elif changed == Changed.PREV_RESULT: if self.current_plot == payload: return True else: return False def plot(self, experiment, plot_name = None, **kwargs): if plot_name not in ["Morphology", "Autofluorescence", "Bleedthrough", "Bead Calibration", "Color Translation"]: raise util.CytoflowViewError("Which plot do you want? Must be one " "of \"Morphology\", \"Autofluorescence\", " "\"Bleedthrough\", \"Bead Calibration\", " "or \"Color Translation\"") if not self.op._blank_exp: raise util.CytoflowViewError("Must set at least the blank control file!") new_ex = self.op._blank_exp.clone() if plot_name == "Morphology": if not self._polygon_view: self._polygon_view = self.op._polygon_op.default_view() self._polygon_view.plot(new_ex, **kwargs) return else: new_ex = self.op._polygon_op.apply(new_ex) if plot_name == "Autofluorescence": self.op._af_op.default_view().plot(new_ex, **kwargs) return else: new_ex = self.op._af_op.apply(new_ex) if plot_name == "Bleedthrough": self.op._bleedthrough_op.default_view().plot(new_ex, **kwargs) return else: new_ex = self.op._bleedthrough_op.apply(new_ex) if plot_name == "Bead Calibration": self.op._bead_calibration_op.default_view().plot(new_ex, **kwargs) return else: new_ex = self.op._bead_calibration_op.apply(new_ex) if plot_name == "Color Translation": self.op._color_translation_op.default_view().plot(new_ex, **kwargs)
class TasbeCalibrationOp(PluginOpMixin): handler_factory = Callable(TasbeHandler) id = Constant('edu.mit.synbio.cytoflowgui.op_plugins.bleedthrough_piecewise') friendly_id = Constant("Quantitative Pipeline") name = Constant("TASBE") fsc_channel = DelegatesTo('_polygon_op', 'xchannel', estimate = True) ssc_channel = DelegatesTo('_polygon_op', 'ychannel', estimate = True) vertices = DelegatesTo('_polygon_op', 'vertices', estimate = True) channels = List(Str, estimate = True) blank_file = File(filter = ["*.fcs"], estimate = True) bleedthrough_list = List(_BleedthroughControl, estimate = True) beads_name = Str(estimate = True) beads_file = File(filter = ["*.fcs"], estimate = True) units_list = List(_Unit, estimate = True) bead_peak_quantile = Int(80, estimate = True) bead_brightness_threshold = Float(100, estimate = True) bead_brightness_cutoff = util.FloatOrNone("", estimate = True) do_color_translation = Bool(estimate = True) to_channel = Str(estimate = True) translation_list = List(_TranslationControl, estimate = True) mixture_model = Bool(False, estimate = True) do_estimate = Event valid_model = Bool(False, status = True) do_exit = Event input_files = List(File) output_directory = Directory _blank_exp = Instance(Experiment, transient = True) _blank_exp_file = File(transient = True) _blank_exp_channels = List(Str, status = True) _polygon_op = Instance(PolygonOp, kw = {'name' : 'polygon', 'xscale' : 'log', 'yscale' : 'log'}, transient = True) _af_op = Instance(AutofluorescenceOp, (), transient = True) _bleedthrough_op = Instance(BleedthroughLinearOp, (), transient = True) _bead_calibration_op = Instance(BeadCalibrationOp, (), transient = True) _color_translation_op = Instance(ColorTranslationOp, (), transient = True) status = Str(status = True) @on_trait_change('channels[], to_channel, do_color_translation', post_init = True) def _channels_changed(self, obj, name, old, new): for channel in self.channels: if channel not in [control.channel for control in self.bleedthrough_list]: self.bleedthrough_list.append(_BleedthroughControl(channel = channel)) if channel not in [unit.channel for unit in self.units_list]: self.units_list.append(_Unit(channel = channel)) to_remove = [] for control in self.bleedthrough_list: if control.channel not in self.channels: to_remove.append(control) for control in to_remove: self.bleedthrough_list.remove(control) to_remove = [] for unit in self.units_list: if unit.channel not in self.channels: to_remove.append(unit) for unit in to_remove: self.units_list.remove(unit) if self.do_color_translation: to_remove = [] for unit in self.units_list: if unit.channel != self.to_channel: to_remove.append(unit) for unit in to_remove: self.units_list.remove(unit) self.translation_list = [] for c in self.channels: if c == self.to_channel: continue self.translation_list.append(_TranslationControl(from_channel = c, to_channel = self.to_channel)) self.changed = (Changed.ESTIMATE, ('translation_list', self.translation_list)) self.changed = (Changed.ESTIMATE, ('bleedthrough_list', self.bleedthrough_list)) self.changed = (Changed.ESTIMATE, ('units_list', self.units_list)) @on_trait_change('_polygon_op:vertices', post_init = True) def _polygon_changed(self, obj, name, old, new): self.changed = (Changed.ESTIMATE, (None, None)) @on_trait_change("bleedthrough_list_items, bleedthrough_list.+", post_init = True) def _bleedthrough_controls_changed(self, obj, name, old, new): self.changed = (Changed.ESTIMATE, ('bleedthrough_list', self.bleedthrough_list)) @on_trait_change("translation_list_items, translation_list.+", post_init = True) def _translation_controls_changed(self, obj, name, old, new): self.changed = (Changed.ESTIMATE, ('translation_list', self.translation_list)) @on_trait_change('units_list_items,units_list.+', post_init = True) def _units_changed(self, obj, name, old, new): self.changed = (Changed.ESTIMATE, ('units_list', self.units_list)) # def estimate(self, experiment, subset = None): # if not self.subset: # warnings.warn("Are you sure you don't want to specify a subset " # "used to estimate the model?", # util.CytoflowOpWarning) # if experiment is None: # raise util.CytoflowOpError("No valid result to estimate with") # experiment = experiment.clone() if not self.fsc_channel: raise util.CytoflowOpError('fsc_channel', "Must set FSC channel") if not self.ssc_channel: raise util.CytoflowOpError('ssc_channel', "Must set SSC channel") if not self._polygon_op.vertices: raise util.CytoflowOpError(None, "Please draw a polygon around the " "single-cell population in the " "Morphology tab") experiment = self._blank_exp.clone() experiment = self._polygon_op.apply(experiment) self._af_op.channels = self.channels self._af_op.blank_file = self.blank_file self._af_op.estimate(experiment, subset = "polygon == True") self.changed = (Changed.ESTIMATE_RESULT, "Autofluorescence") experiment = self._af_op.apply(experiment) self.status = "Estimating bleedthrough" self._bleedthrough_op.controls.clear() for control in self.bleedthrough_list: self._bleedthrough_op.controls[control.channel] = control.file self._bleedthrough_op.estimate(experiment, subset = "polygon == True") self.changed = (Changed.ESTIMATE_RESULT, "Bleedthrough") experiment = self._bleedthrough_op.apply(experiment) self.status = "Estimating bead calibration" self._bead_calibration_op.beads = BeadCalibrationOp.BEADS[self.beads_name] self._bead_calibration_op.beads_file = self.beads_file self._bead_calibration_op.bead_peak_quantile = self.bead_peak_quantile self._bead_calibration_op.bead_brightness_threshold = self.bead_brightness_threshold self._bead_calibration_op.bead_brightness_cutoff = self.bead_brightness_cutoff self._bead_calibration_op.units.clear() for unit in self.units_list: self._bead_calibration_op.units[unit.channel] = unit.unit self._bead_calibration_op.estimate(experiment) self.changed = (Changed.ESTIMATE_RESULT, "Bead Calibration") if self.do_color_translation: self.status = "Estimating color translation" experiment = self._bead_calibration_op.apply(experiment) self._color_translation_op.mixture_model = self.mixture_model self._color_translation_op.controls.clear() for control in self.translation_list: self._color_translation_op.controls[(control.from_channel, control.to_channel)] = control.file self._color_translation_op.estimate(experiment, subset = 'polygon == True') self.changed = (Changed.ESTIMATE_RESULT, "Color Translation") self.status = "Done estimating" self.valid_model = True def should_clear_estimate(self, changed, payload): """ Should the owning WorkflowItem clear the estimated model by calling op.clear_estimate()? `changed` can be: - Changed.ESTIMATE -- the parameters required to call 'estimate()' (ie traits with estimate = True metadata) have changed - Changed.PREV_RESULT -- the previous WorkflowItem's result changed """ if changed == Changed.ESTIMATE: name, _ = payload if name == 'fsc_channel' or name == 'ssc_channel': return False return True def clear_estimate(self): self._af_op = AutofluorescenceOp() self._bleedthrough_op = BleedthroughLinearOp() self._bead_calibration_op = BeadCalibrationOp() self._color_translation_op = ColorTranslationOp() self.valid_model = False self.changed = (Changed.ESTIMATE_RESULT, self) def should_apply(self, changed, payload): """ Should the owning WorkflowItem apply this operation when certain things change? `changed` can be: - Changed.OPERATION -- the operation's parameters changed - Changed.PREV_RESULT -- the previous WorkflowItem's result changed - Changed.ESTIMATE_RESULT -- the results of calling "estimate" changed """ if changed == Changed.ESTIMATE_RESULT and \ self.blank_file != self._blank_exp_file: return True elif changed == Changed.OPERATION: name, _ = payload if name == "output_directory": return False return True return False def apply(self, experiment): # this "apply" function is a little odd -- it does not return an Experiment because # it always the only WI/operation in the workflow. if self.blank_file != self._blank_exp_file: self._blank_exp = ImportOp(tubes = [Tube(file = self.blank_file)] ).apply() self._blank_exp_file = self.blank_file self._blank_exp_channels = self._blank_exp.channels self.changed = (Changed.PREV_RESULT, None) return out_dir = Path(self.output_directory) for path in self.input_files: in_file_path = Path(path) out_file_path = out_dir / in_file_path.name if out_file_path.exists(): raise util.CytoflowOpError(None, "File {} already exists" .format(out_file_path)) tubes = [Tube(file = path, conditions = {'filename' : Path(path).stem}) for path in self.input_files] for tube in tubes: self.status = "Converting " + Path(tube.file).stem experiment = ImportOp(tubes = [tube], conditions = {'filename' : 'category'}).apply() experiment = self._af_op.apply(experiment) experiment = self._bleedthrough_op.apply(experiment) experiment = self._bead_calibration_op.apply(experiment) if self.do_color_translation: experiment = self._color_translation_op.apply(experiment) ExportFCS(path = self.output_directory, by = ['filename'], _include_by = False).export(experiment) self.input_files = [] self.status = "Done converting!" def default_view(self, **kwargs): return TasbeCalibrationView(op = self, **kwargs) def get_help(self): current_dir = os.path.abspath(__file__) help_dir = os.path.split(current_dir)[0] help_dir = os.path.join(help_dir, "help") help_file = None for klass in self.__class__.__mro__: mod = klass.__module__ mod_html = mod + ".html" h = os.path.join(help_dir, mod_html) if os.path.exists(h): help_file = h break with open(help_file, encoding = 'utf-8') as f: help_html = f.read() return help_html
class KMeansPluginView(PluginViewMixin): handler_factory = Callable(KMeansViewHandler) op = Instance(IOperation, fixed=True) subset = DelegatesTo('op', transient=True) by = DelegatesTo('op', status=True) xchannel = DelegatesTo('op', 'xchannel', transient=True) xscale = DelegatesTo('op', 'xscale', transient=True) ychannel = DelegatesTo('op', 'ychannel', transient=True) yscale = DelegatesTo('op', 'yscale', transient=True) plot_params = Instance(ScatterplotPlotParams, ()) id = "edu.mit.synbio.cytoflowgui.op_plugins.kmeans" friendly_id = "KMeans" name = Constant("KMeans") def plot(self, experiment, **kwargs): KMeans2DView(op=self.op, xchannel=self.xchannel, ychannel=self.ychannel, xscale=self.xscale, yscale=self.yscale).plot(experiment, **kwargs) def plot_wi(self, wi): if wi.result: if self.plot_names: self.plot( wi.result, plot_name=self.current_plot**self.plot_params.trait_get()) else: self.plot(wi.result, **self.plot_params.trait_get()) else: if self.plot_names: self.plot(wi.previous_wi.result, plot_name=self.current_plot, **self.plot_params.trait_get()) else: self.plot(wi.previous_wi.result, **self.plot_params.trait_get()) def enum_plots_wi(self, wi): if wi.result: try: return self.enum_plots(wi.result) except: return [] else: try: return self.enum_plots(wi.previous_wi.result) except: return [] def get_notebook_code(self, idx): view = KMeans2DView() view.copy_traits(self, view.copyable_trait_names()) view.subset = self.subset plot_params_str = traits_str(self.plot_params) return dedent(""" op_{idx}.default_view({traits}).plot(ex_{idx}{plot_params}) """.format(traits=traits_str(view), idx=idx, plot_params=", " + plot_params_str if plot_params_str else ""))
class KMeansPluginOp(PluginOpMixin, KMeansOp): handler_factory = Callable(FlowPeaksHandler) # add "estimate" metadata xchannel = Str(estimate=True) ychannel = Str(estimate=True) xscale = util.ScaleEnum(estimate=True) yscale = util.ScaleEnum(estimate=True) num_clusters = util.PositiveCInt(2, allow_zero=False, estimate=True) by = List(Str, estimate=True) # bits to support the subset editor subset_list = List(ISubset, estimate=True) subset = Property(Str, depends_on="subset_list.str") # MAGIC - returns the value of the "subset" Property, above def _get_subset(self): return " and ".join( [subset.str for subset in self.subset_list if subset.str]) @on_trait_change('subset_list.str') def _subset_changed(self, obj, name, old, new): self.changed = (Changed.ESTIMATE, ('subset_list', self.subset_list)) @on_trait_change('xchannel, ychannel') def _channel_changed(self, obj, name, old, new): self.channels = [] self.scale = {} if self.xchannel: self.channels.append(self.xchannel) if self.xchannel in self.scale: del self.scale[self.xchannel] self.scale[self.xchannel] = self.xscale if self.ychannel: self.channels.append(self.ychannel) if self.ychannel in self.scale: del self.scale[self.ychannel] self.scale[self.ychannel] = self.yscale @on_trait_change('xscale, yscale') def _scale_changed(self, obj, name, old, new): self.scale = {} if self.xchannel: self.scale[self.xchannel] = self.xscale if self.ychannel: self.scale[self.ychannel] = self.yscale def default_view(self, **kwargs): return KMeansPluginView(op=self, **kwargs) def estimate(self, experiment): if not self.xchannel: raise util.CytoflowOpError('xchannel', "Must set X channel") if not self.ychannel: raise util.CytoflowOpError('ychannel', "Must set Y channel") try: super().estimate(experiment, subset=self.subset) except: raise finally: self.changed = (Changed.ESTIMATE_RESULT, self) def clear_estimate(self): self._kmeans.clear() self.changed = (Changed.ESTIMATE_RESULT, self) def get_notebook_code(self, idx): op = KMeansOp() op.copy_traits(self, op.copyable_trait_names()) return dedent(""" op_{idx} = {repr} op_{idx}.estimate(ex_{prev_idx}{subset}) ex_{idx} = op_{idx}.apply(ex_{prev_idx}) """.format(repr=repr(op), idx=idx, prev_idx=idx - 1, subset=", subset = " + repr(self.subset) if self.subset else ""))
class TableFilter(HasPrivateTraits): """ Filter for items displayed in a table. """ #------------------------------------------------------------------------- # Trait definitions: #------------------------------------------------------------------------- # UI name of this filter (so the user can identify it in the UI) name = Str('Default filter') # Default name that can be automatically overridden _name = Str('Default filter') # A user-readable description of what kind of object satisfies the filter desc = Str('All items') # A callable function that returns whether the passed object is allowed # by the filter allowed = Callable(lambda object: True, transient=True) # Is the filter a template (i.e., non-deletable, non-editable)? template = Bool(False) #------------------------------------------------------------------------- # Class constants: #------------------------------------------------------------------------- # Traits that are ignored by the _anytrait_changed() handler ignored_traits = ['_name', 'template', 'desc'] #------------------------------------------------------------------------- # Traits view definitions: #------------------------------------------------------------------------- traits_view = View( 'name{Filter name}', '_', Include('filter_view'), title='Edit Filter', width=0.2, buttons=[ 'OK', 'Cancel', Action(name='Help', action='show_help', defined_when="ui.view_elements.content['filter_view']" ".help_id != ''") ]) searchable_view = View( [[Include('search_view'), '|[]'], ['handler.status~', '|[]<>'], [ 'handler.find_next`Find the next matching item`', 'handler.find_previous`Find the previous matching item`', 'handler.select`Select all matching items`', 'handler.OK`Exit search`', '-<>' ], '|<>'], title='Search for', kind='livemodal', width=0.25) search_view = Group(Include('filter_view')) filter_view = Group() #------------------------------------------------------------------------- # Returns whether a specified object meets the filter/search criteria: # (Should normally be overridden) #------------------------------------------------------------------------- def filter(self, object): """ Returns whether a specified object meets the filter or search criteria. """ return self.allowed(object) #------------------------------------------------------------------------- # Returns a user readable description of what kind of object will # satisfy the filter: # (Should normally be overridden): #------------------------------------------------------------------------- def description(self): """ Returns a user-readable description of what kind of object satisfies the filter. """ return self.desc #------------------------------------------------------------------------- # Edits the contents of the filter: #------------------------------------------------------------------------- def edit(self, object): """ Edits the contents of the filter. """ return self.edit_traits(view=self.edit_view(object), kind='livemodal') def edit_view(self, object): """ Return a view to use for editing the filter. The ''object'' parameter is a sample object for the table that the filter will be applied to. It is supplied in case the filter needs to extract data or metadata from the object. If the table is empty, the ''object'' argument is None. """ return None #------------------------------------------------------------------------- # 'object' interface: #------------------------------------------------------------------------- def __str__(self): return self.name #------------------------------------------------------------------------- # Event handlers: #------------------------------------------------------------------------- def _anytrait_changed(self, name, old, new): if ((name not in self.ignored_traits) and ((self.name == self._name) or (self.name == ''))): self.name = self._name = self.description()
class ObjectColumn(TableColumn): """ A column for editing objects. """ # ------------------------------------------------------------------------- # Trait definitions: # ------------------------------------------------------------------------- #: Name of the object trait associated with this column: name = Str() #: Column label to use for this column: label = Property() #: Trait editor used to edit the contents of this column: editor = Instance(EditorFactory) #: The editor style to use to edit the contents of this column: style = EditorStyle #: Format string to apply to column values: format = Str("%s") #: Format function to apply to column values: format_func = Callable() # ------------------------------------------------------------------------- # Trait view definitions: # ------------------------------------------------------------------------- traits_view = View( [ ["name", "label", "type", "|[Column Information]"], [ "horizontal_alignment{Horizontal}@", "vertical_alignment{Vertical}@", "|[Alignment]", ], ["editable", "9", "droppable", "9", "visible", "-[Options]>"], "|{Column}", ], [ [ "text_color@", "cell_color@", "read_only_cell_color@", "|[UI Colors]", ], "|{Colors}", ], [["text_font@", "|[Font]<>"], "|{Font}"], ["menu@", "|{Menu}"], ["editor@", "|{Editor}"], ) def _get_label(self): """ Gets the label of the column. """ if self._label is not None: return self._label return user_name_for(self.name) def _set_label(self, label): old, self._label = self._label, label if old != label: self.trait_property_changed("label", old, label) def get_raw_value(self, object): """ Gets the unformatted value of the column for a specified object. """ try: return xgetattr(self.get_object(object), self.name) except Exception as e: from traitsui.api import raise_to_debug raise_to_debug() return None def get_value(self, object): """ Gets the formatted value of the column for a specified object. """ try: if self.format_func is not None: return self.format_func(self.get_raw_value(object)) return self.format % (self.get_raw_value(object),) except: logger.exception( "Error occurred trying to format a %s value" % self.__class__.__name__ ) return "Format!" def get_drag_value(self, object): """Returns the drag value for the column. """ return self.get_raw_value(object) def set_value(self, object, value): """ Sets the value of the column for a specified object. """ target, name = self.target_name(object) setattr(target, name, value) def get_editor(self, object): """ Gets the editor for the column of a specified object. """ if self.editor is not None: return self.editor target, name = self.target_name(object) return target.base_trait(name).get_editor() def get_style(self, object): """ Gets the editor style for the column of a specified object. """ return self.style def key(self, object): """ Returns the value to use for sorting. """ return self.get_raw_value(object) def is_droppable(self, object, value): """ Returns whether a specified value is valid for dropping on the column for a specified object. """ if self.droppable: try: target, name = self.target_name(object) target.base_trait(name).validate(target, name, value) return True except: pass return False def target_name(self, object): """ Returns the target object and name for the column. """ object = self.get_object(object) name = self.name col = name.rfind(".") if col < 0: return (object, name) return (xgetattr(object, name[:col]), name[col + 1 :])
class PolygonPluginOp(PolygonOp, PluginOpMixin): handler_factory = Callable(PolygonHandler) def default_view(self, **kwargs): return PolygonSelectionView(op = self, **kwargs)
class LC(HasTraits): '''Loading case class ''' reader = WeakRef lcc_table = WeakRef # name of the file containing the stress resultants # file_name = Str(input=True) # data filter (used to hide unwanted values, e.g. high sigularities etc.) # data_filter = Callable(input=True) # name of the loading case # name = Str(input=True) # category of the loading case # category = Enum('dead-load', 'additional dead-load', 'imposed-load', input=True) # list of keys specifying the names of the loading cases # that can not exist at the same time, i.e. which are exclusive to each other # exclusive_to = List(Str, input=True) def _exclusive_to_default(self): return [] # combination factors (need to be defined in case of imposed loads) # psi_0 = Float(input=True) psi_1 = Float(input=True) psi_2 = Float(input=True) # security factors ULS # gamma_fav = Float(input=True) def _gamma_fav_default(self): if self.category == 'dead-load': return 1.00 if self.category == 'additional dead-load': return 0.00 if self.category == 'imposed-load': return 0.00 gamma_unf = Float(input=True) def _gamma_unf_default(self): if self.category == 'dead-load': return 1.35 if self.category == 'additional dead-load': return 1.35 if self.category == 'imposed-load': return 1.50 # security factors SLS: # (used to distinguish combinations where imposed-loads # or additional-dead-loads are favorable or unfavorable.) # gamma_fav_SLS = Float(input=True) def _gamma_fav_SLS_default(self): if self.category == 'dead-load': return 1.00 elif self.category == 'additional dead-load' or \ self.category == 'imposed-load': return 0.00 gamma_unf_SLS = Float(input=True) def _gamma_unf_SLS_default(self): return 1.00 # original state data (before filtering) # state_data_orig = Property(Dict, depends_on='file_name, lcc_table.data_dir') @cached_property def _get_state_data_orig(self): return self.reader.read_state_data(self.file_name) # state data (after filtering) # state_data_dict = Property( Dict, depends_on='file_name, data_filter, lcc_table.data_dir') @cached_property def _get_state_data_dict(self): d = {} for k, arr in self.state_data_orig.items(): d[k] = self.data_filter(self.lcc_table, arr) return d # if reader == 'RFEM': #sr_columns = List(['mx', 'my', 'mxy', 'nx', 'ny', 'nxy']) # if reader == 'InfoCAD': #sr_columns = List(['mx', 'my', 'mxy', 'nx', 'ny', 'nxy', 'ux_elem', 'uy_elem', 'uz_elem']) # if reader == 'InfoCADRxyz': sr_columns = List(['Rx', 'Ry', 'Rz', 'Mx', 'My', 'Mz']) sr_arr = Property(Array) def _get_sr_arr(self): '''return the stress resultants of the loading case as stack of all sr-column arrays. ''' sd_dict = self.state_data_dict return hstack([sd_dict[sr_key] for sr_key in self.sr_columns])
class MyNewCallable2(HasTraits): value = Callable(pow, allow_none=True) empty_callable = Callable() a_non_none_union = Union(Callable(allow_none=False), Int) a_allow_none_union = Union(Callable(allow_none=True), Int)
class MyNewCallable(HasTraits): value = Callable(default_value=pow, allow_none=False)