Source code for cytoflowgui.view_plugins.table

#!/usr/bin/env python3.8
# coding: latin-1

# (c) Massachusetts Institute of Technology 2015-2018
# (c) Brian Teague 2018-2022
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 2 of the License, or
# (at your option) any later version.
# 
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
# 
# You should have received a copy of the GNU General Public License
# along with this program.  If not, see <http://www.gnu.org/licenses/>.

"""
Table
-----

Make a table out of a statistic.  The table can then be exported.

.. object:: Statistic

    Which statistic to view.
    
.. object:: Rows

    Which variable to use for the rows

.. object:: Subrows

    Which variable to use for subrows.
    
.. object:: Columns

    Which variable to use for the columns.
    
.. object:: Subcolumns

    Which variable to use for the subcolumns.
    
.. object:: Export

    Export the table to a CSV file.

    
.. plot::
   :include-source: False

    import cytoflow as flow
    import_op = flow.ImportOp()
    import_op.tubes = [flow.Tube(file = "Plate01/RFP_Well_A3.fcs",
                                 conditions = {'Dox' : 10.0}),
                       flow.Tube(file = "Plate01/CFP_Well_A4.fcs",
                                 conditions = {'Dox' : 1.0})]
    import_op.conditions = {'Dox' : 'float'}
    ex = import_op.apply()
    
    ex2 = flow.ThresholdOp(name = 'Threshold',
                           channel = 'Y2-A',
                           threshold = 2000).apply(ex)
    

    ex3 = flow.ChannelStatisticOp(name = "ByDox",
                                  channel = "Y2-A",
                                  by = ['Dox', 'Threshold'],
                                  function = len).apply(ex2) 

    flow.TableView(statistic = ("ByDox", "len"),
                   row_facet = "Dox",
                   column_facet = "Threshold").plot(ex3)    

"""

import pandas as pd

from traits.api import provides, Property, Event, observe, List
from traitsui.api import View, Item, EnumEditor, VGroup, ButtonEditor
from envisage.api import Plugin
from pyface.api import ImageResource, FileDialog, OK

from ..workflow.views import TableWorkflowView
from ..util import DefaultFileDialog
from ..editors import SubsetListEditor, ColorTextEditor, ExtendableEnumEditor, InstanceHandlerEditor
from ..subset_controllers import subset_handler_factory

from .i_view_plugin import IViewPlugin, VIEW_PLUGIN_EXT
from .view_plugin_base import ViewHandler, PluginHelpMixin

    
[docs]class TableHandler(ViewHandler): indices = Property(depends_on = "context.statistics, model.statistic, model.subset") levels = Property(depends_on = "context.statistics, model.statistic") export = Event() view_traits_view = \ View(VGroup( VGroup(Item('statistic', editor = EnumEditor(name='context_handler.statistics_names'), label = "Statistic"), Item('row_facet', editor = ExtendableEnumEditor(name='handler.indices', extra_items = {"None" : ""}), label = "Rows"), Item('subrow_facet', editor = ExtendableEnumEditor(name='handler.indices', extra_items = {"None" : ""}), label = "Subrows"), Item('column_facet', editor = ExtendableEnumEditor(name='handler.indices', extra_items = {"None" : ""}), label = "Columns"), Item('subcolumn_facet', editor = ExtendableEnumEditor(name='handler.indices', extra_items = {"None" : ""}), label = "Subcolumn"), Item('handler.export', editor = ButtonEditor(label = "Export..."), enabled_when = 'result is not None', show_label = False), label = "Table View", show_border = False), VGroup(Item('subset_list', show_label = False, editor = SubsetListEditor(conditions = "handler.levels", editor = InstanceHandlerEditor(view = 'subset_view', handler_factory = subset_handler_factory), mutable = False)), label = "Subset", show_border = False, show_labels = False), Item('context.view_warning', resizable = True, visible_when = 'context.view_warning', editor = ColorTextEditor(foreground_color = "#000000", background_color = "#ffff99")), Item('context.view_error', resizable = True, visible_when = 'context.view_error', editor = ColorTextEditor(foreground_color = "#000000", background_color = "#ff9191")))) view_params_view = View() # empty view -- no parameters for a table view # MAGIC: gets the value for the property indices def _get_indices(self): if not (self.context and self.context.statistics and self.model.statistic in self.context.statistics): return [] stat = self.context.statistics[self.model.statistic] data = pd.DataFrame(index = stat.index) if self.model.subset: data = data.query(self.model.subset) if len(data) == 0: return [] names = list(data.index.names) for name in names: unique_values = data.index.get_level_values(name).unique() if len(unique_values) == 1: data.index = data.index.droplevel(name) return list(data.index.names) # MAGIC: gets the value for the property 'levels' # returns a Dict(Str, pd.Series) def _get_levels(self): if not (self.context and self.context.statistics and self.model.statistic in self.context.statistics): return {} stat = self.context.statistics[self.model.statistic] index = stat.index names = list(index.names) for name in names: unique_values = index.get_level_values(name).unique() if len(unique_values) == 1: index = index.droplevel(name) names = list(index.names) ret = {} for name in names: ret[name] = pd.Series(index.get_level_values(name)).sort_values() ret[name] = pd.Series(ret[name].unique()) return ret @observe('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.model.result.index) data[self.model.result.name] = self.model.result self.model._export_data(data, self.model.result.name, dialog.path)
[docs]@provides(IViewPlugin) class TablePlugin(Plugin, PluginHelpMixin): id = 'edu.mit.synbio.cytoflowgui.view.table' view_id = 'edu.mit.synbio.cytoflow.view.table' short_name = "Table View"
[docs] def get_view(self): return TableWorkflowView()
[docs] def get_handler(self, model, context): if isinstance(model, TableWorkflowView): return TableHandler(model = model, context = context) else: return None
[docs] def get_icon(self): return ImageResource('table')
plugin = List(contributes_to = VIEW_PLUGIN_EXT) def _plugin_default(self): return [self]