#!/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/>.
"""
cytoflow.views.scatterplot
--------------------------
A 2-d scatterplot.
`ScatterplotView` -- the `IView` class that makes the plot.
"""
import matplotlib.pyplot as plt
import seaborn as sns
from warnings import warn
from traits.api import provides, Constant, Str
import cytoflow.utility as util
from .i_view import IView
from .base_views import Base2DView
[docs]
@provides(IView)
class ScatterplotView(Base2DView):
"""
Plots a 2-d scatterplot.
Attributes
----------
huechannel : Str
If set, color the points using a normed color scale. The norm function
is set by `huescale`, and the color palette can be changed by passing
the ``palette`` parameter to `plot`.
Examples
--------
Make a little data set.
.. plot::
:context: close-figs
>>> 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()
Plot a density plot
.. plot::
:context: close-figs
>>> flow.ScatterplotView(xchannel = 'V2-A',
... xscale = 'log',
... ychannel = 'Y2-A',
... yscale = 'log',
... huefacet = 'Dox').plot(ex)
"""
id = Constant('cytoflow.view.scatterplot')
friend_id = Constant("Scatter Plot")
huechannel = Str
[docs]
def plot(self, experiment, **kwargs):
"""
Plot a faceted scatter plot view of a channel
Parameters
----------
alpha : float (default = 0.25)
The alpha blending value, between 0 (transparent) and 1 (opaque).
s : int (default = 2)
The size in points^2.
marker : a matplotlib marker style, usually a string
Specfies the glyph to draw for each point on the scatterplot.
See `matplotlib.markers <http://matplotlib.org/api/markers_api.html#module-matplotlib.markers>`_ for examples. Default: 'o'
Notes
-----
Other ``kwargs`` are passed to `matplotlib.pyplot.scatter <https://matplotlib.org/devdocs/api/_as_gen/matplotlib.pyplot.scatter.html>`_
"""
if self.huechannel:
if self.huefacet:
raise util.CytoflowViewError('huefacet',
"Can't set both 'huefacet' and 'huechannel'!")
if self.huechannel not in experiment.channels:
raise util.CytoflowViewError('huechannel',
f"Can't find channel {self.huechannel} in the experiment.")
kwargs.setdefault('palette', 'viridis_r')
kwargs.setdefault('huelabel', self.huechannel)
super().plot(experiment, **kwargs)
def _grid_plot(self, experiment, grid, cmap, **kwargs):
kwargs.setdefault('alpha', 0.25)
kwargs.setdefault('s', 2)
kwargs.setdefault('marker', 'o')
kwargs.setdefault('antialiased', True)
lim = kwargs.pop('lim')
xlim = lim[self.xchannel]
ylim = lim[self.ychannel]
scale = kwargs.pop('scale')
xscale = scale[self.xchannel]
yscale = scale[self.ychannel]
if self.huechannel:
if isinstance(cmap, list):
raise util.CytoflowViewError('palette',
"Must use a continuous palette with huechannel set!")
kwargs['cmap'] = cmap
hue_scale = util.scale_factory(self.huescale,
experiment,
channel = self.huechannel)
norm = hue_scale.norm()
kwargs['norm'] = norm
grid.map(_scatterplot, self.xchannel, self.ychannel, self.huechannel, **kwargs)
else:
norm = None
grid.map(plt.scatter, self.xchannel, self.ychannel, **kwargs)
return dict(xlim = xlim,
xscale = xscale,
ylim = ylim,
yscale = yscale,
norm = norm)
def _update_legend(self, legend):
for lh in legend.legend_handles:
lh.set_alpha(0.8)
lh.set_sizes([10.0])
def _scatterplot(x, y, c, **kwargs):
del kwargs['color']
plt.scatter(x, y, c = c, **kwargs),
util.expand_class_attributes(ScatterplotView)
util.expand_method_parameters(ScatterplotView, ScatterplotView.plot)
if __name__ == '__main__':
import cytoflow as flow
tube1 = flow.Tube(file = '../../cytoflow/tests/data/Plate01/RFP_Well_A3.fcs',
conditions = {"Dox" : 10.0})
tube2 = flow.Tube(file = '../../cytoflow/tests/data/Plate01/CFP_Well_A4.fcs',
conditions = {"Dox" : 1.0})
ex = flow.ImportOp(conditions = {"Dox" : "float"}, tubes = [tube1, tube2])
thresh = flow.ThresholdOp()
thresh.name = "Y2-A+"
thresh.channel = 'Y2-A'
thresh.threshold = 200.0
ex2 = thresh.apply(ex)
scatter = flow.ScatterplotView()
scatter.name = "Scatter"
scatter.xchannel = "FSC-A"
scatter.ychannel = "SSC-A"
scatter.xscale = "logicle"
scatter.yscale = "logicle"
scatter.huefacet = 'Dox'
plt.ioff()
scatter.plot(ex2)
plt.show()