New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add plot.violin() #335
Add plot.violin() #335
Conversation
matplotlib was previously imported as "mpl" in plot_violin code. In FlowCal, matplotlib is not imported under this alias. This commit corrects "mpl" references to "matplotlib".
-Using a pd.Series for `positions` with a 0 position would fail because using `0 in positions` would check if 0 was in the index, not the positions. -x ticks would not be properly labeled under some circumstances because the plot was not properly drawn initially.
Fix plot.violin bug where channel was not extracted from zero, min, or max data.
-Made custom tick locators and formatters aware of min, max, and zero violins. -Exposed min, max, and zero violin tick labels for user to specify if so desired.
Example and tutorial plots (as of 90fed69):
From the tutorial: FlowCal.plot.violin(data=d, channel='FL1', positions=iptg, xlabel='IPTG (uM)') FlowCal.plot.violin(data=d, channel='FL1', positions=iptg, xlabel='IPTG (uM)', yscale='linear', ylim=(0,4000)) FlowCal.plot.violin(data=d, channel='FL1', positions=iptg, xlabel='IPTG (uM)', xscale='log') FlowCal.plot.violin(data=d,
min_data=d[0],
max_data=d[-1],
channel='FL1',
positions=iptg,
xlabel='IPTG (uM)',
xscale='log',
violin_kwargs={'data':{'facecolor':'gray', 'edgecolor':'black'},
'min' :{'facecolor':'black','edgecolor':'black'},
'max' :{'facecolor':'black','edgecolor':'black'}},
draw_summary_stat_kwargs={'data':{'color':'black'},
'min' :{'color':'gray'},
'max' :{'color':'gray'}}) def iptg_hill_model(iptg_concentration):
mn = 20.
mx = 1700.
K = 300.
n = 1.5
if iptg_concentration <= 0:
return mn
else:
return mn + ((mx-mn)/(1+((K/iptg_concentration)**n)))
FlowCal.plot.violin(data=d,
min_data=d[0],
max_data=d[-1],
channel='FL1',
positions=iptg,
xlabel='IPTG (uM)',
xscale='log',
violin_kwargs={'data':{'facecolor':'gray', 'edgecolor':'black'},
'min' :{'facecolor':'black','edgecolor':'black'},
'max' :{'facecolor':'black','edgecolor':'black'}},
draw_summary_stat_kwargs={'data':{'color':'black'},
'min' :{'color':'gray'},
'max' :{'color':'gray'}},
draw_model=True,
draw_model_fxn=iptg_hill_model,
draw_model_kwargs={'color':'gray',
'linewidth':3,
'zorder':-1,
'solid_capstyle':'butt'},
data_xlim=(2e1,2e3)) |
Cool! I'm excited to get this out. I'm gonna start with some high-level questions. I'll get to specific code questions later.
FlowCal.plot.violin(data=d,
min_data=d[0],
max_data=d[-1], It seems that the FCSData objects passed to
|
Just personal preference. I found it helpful to outline the violins with black lines. I also found it helpful to differentiate controls (min and max) with a separate face color. Black and gray seemed like natural grayscale colors that would look clean in a publication. I almost always ended up specifying a new color manually, though.
That was born out of practicality. I was frequently visualizing violins with log-spaced x-positions but also wanting to show a zero violin. We could make it less automatic by only illustrating the zero violin when specified via I might also be open to supporting a
No, Data for minimum and maximum controls can also be separately illustrated via the ``min_data`` and ``max_data`` parameters (here, we use the low and high IPTG concentrations).
Yes, the
That sounds like a good idea. I've made the violins look pretty, and I think the line plot looks kinda tacky, so I'd vote for updating the line plots. Specifically, it seems wider than it needs to be, and both axes are linear – I'd switch them to log to match the violin plot (or maybe symlog x-axis?).
Yes, you should absolutely still be able to use |
There are two extreme ways in which you can construct a plotting function. One is the "minimalist" approach, where the function does only the one thing that makes it "special" (e.g. making a scatter plot where the dots are colored according to density) but leave everything else to matplotlib (axis, labels, limits, etc.). This makes our function behave pretty much like any native matplotlib function. The other is the "rigid" approach, where the function sets the secondary properties in a way that further changes after the function call, such as colors or axis scales, are either impossible or they break the resulting plot. In general, I think been closer to the former is better because it makes the functions more intuitive to use (at least to a person already familiar with matplotlib), but this may get more difficult as the plotting function becomes more complex and/or specialized. I think we have previously done a decent job with FlowCal in making our plotting functions "minimalist", although this is not perfect (e.g. our functions have arguments such as "xaxis" and "saveas" which are not matplotlib standard). I have the impression that this violin function in its current form is more to the "rigid" end of the spectrum, and that comes from the fact that it is currently made to replace a "transfer function" plot (i.e. continuous x axis, making it easy to have a violin for x=0, making it easy to insert min/max violins). In other words, as it stands, this is not just a violin plot function, as you could envision other types (e.g. the one in Felix's paper that substitutes a bar plot). Still, this is a terribly useful function, but I think we need to clearly define what we're trying to do:
Feel free to agree or disagree with whatever. My opinion on what changes, if any, this function needs is still being formed. |
Also apparently this branch has conflicts with develop. I would appreciate if you could fix those. |
Yeah, this is a great point. I've also come over to the camp that "minimalist" is best, and I tried to write Now, you say you perceive We could consider separating out the more advanced features to a separate function, but I initially lean against that because it actually seems less simple to me to have both a
Creating symmetrical violins requires knowing the scale of the x-axis, so Adding support for other types of x-scales might be worth investigating, though (symlog? logicle?).
Agreed. I wasn't comfortable enough with your implementation of logicle scaling to do it on this first pass, though.
Yeah, I can resolve merge conflicts. I may wait until |
FlowCal/plot.py
Outdated
positions_length = len(positions) | ||
|
||
if logx_zero_data is None: | ||
logx_zero_data = zero_data |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe there needs to be a warning here if log_zero_data
is not None? In this case, data[zero_idx]
will be ignored, which may not be immediately obvious to the user.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, I think that's a good idea if we keep this behavior. The silent preference for log_zero_data
over data[zero_idx]
could otherwise be dubious.
You originally weren't sure about this automatic separation of the zero violin, though. I offered the alternative of ignoring data[zero_idx]
if the x-axis is logarithmic, but we never resolved the issue.
FlowCal/plot.py
Outdated
Number of bins to bin population members into along the y-axis. | ||
Ignored if `y_bin_edges` is specified. | ||
y_bin_edges : sequence of scalars, sequence of sequence of scalars, or | ||
mapping to sequence of scalars, optional |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do we expect any mapping other than dictionaries? Dictionaries appear to be the only standard mapping in python. I would suggest simplifying the terminology to "dictionary".
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same with "sequence" -> "list", unless we're expecting an array, for which there is the "array_like" term. This would make it more consistent with the rest of Flowcal.plot
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't know what you mean by "expect". If robust, the function should work with any reasonable input. My nomenclature is intended to be as general as possible and is inspired by Python's Abstract Base Classes (ABCs), which include Sequence
and Mapping
. Moreover, the Sequence
and Mapping
ABCs are used pretty extensively throughout the code. So I guess you could say the code expects anything that is a Sequence
or a Mapping
.
More concretely, Sequence
includes list
and tuple
, and Mapping
includes dict
and OrderedDict
.
It appears ndarray
doesn't quite make the cut for Sequence
: numpy/numpy#2776, numpy/numpy#7315. This could actually be an issue in a few places (e.g. specifying upper_trim_fraction
or lower_trim_fraction
as an ndarray
of floats
); I didn't test ndarrays
extensively.
And array_like
can actually be quite vague: https://stackoverflow.com/a/40380014.
Ultimately, I wanted tuple
to work as well as list
and ndarray
anywhere I said "sequence". pd.Series
and pd.DataFrame
would also be nice, but I consider those the purview of #76.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I understand that you're trying to be general with these abstract classes, but these Sequence
and Mapping
names are not widespread and make the documentation more confusing than it needs to be. I didn't even know of their existence, and only knew where to look them up after seeing that they come from collections
after looking at the code. Furthermore, these are not used anywhere else in FlowCal
, and it is very inconsistent to have one single function that suddenly uses this nomenclature. I'd rather use list
and dictionary
and drop the theoretical compatibility with other Sequence
and Mapping
objects, and gain in terms of documentation readability.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Are you advocating for dumbing down the code? Or just the documentation?
Furthermore, these are not used anywhere else in FlowCal, and it is very inconsistent to have one single function that suddenly uses this nomenclature.
I agree here. Although I'd prefer improving the robustness everywhere else. There are several places where isinstance(..., list)
is used, which unnecessarily prevents other sequence data structures (namely tuple
). The documentation usually specifies list
, at least, but it still feels unnecessarily restrictive. This would obviously have to be a separate issue, though.
We also appear to use numpy array
and array_like
interchangeably in some spots? Which is kinda confusing.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Are you advocating for dumbing down the code? Or just the documentation?
Just for the documentation and error messages. The code looks fine and is probably more robust as you said. We can claim we provide support for the basic data structures and silently provide support for the more general abstract classes.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ahh, OK cool. Yeah, I can get behind that.
FlowCal/plot.py
Outdated
violin's position, 'data'. Min, max, and zero kwargs can be specified | ||
via the 'min', 'max', and 'logx_zero' keys, respectively. If | ||
`violin_kwargs` is a sequence of mappings, min, max, and zero violins | ||
cannot be used. Default = {'facecolor':'gray', 'edgecolor':'black'}. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This needs examples. It's a little hard to understand.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Agreed.
Several parameters behave similarly in this regard. I'm not sure if it's better to make separate examples for all of them or to reorganize the docstring and consolidate like parameters. E.g. adding a "Per-Violin Parameters" section and explaining the different ways they can be specified.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The problem with the "Per-Violin Parameters" idea is that I don't know how sphinx
would parse it when generating the documentation. I'm OK with having examples for every parameter, even if that means that there is some repetition.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
sphinx
parses "Other Parameters" sections for many functions in the plot
module. Is there any reason to believe a "Per-Violin Parameters" section (or an "Advanced Parameters" section for min_data
, max_data
, and log_zero_data
, as discussed previously) would be treated any differently?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There is a documented "Other Parameters" section in the numpydoc
specification.
FlowCal/plot.py
Outdated
and zero `draw_summary_stat_kwargs` can be specified via the 'min', | ||
'max', and 'logx_zero' keys, respectively. If | ||
`draw_summary_stat_kwargs` is a sequence of mappings, min, max, and | ||
zero violins cannot be used. Default = {'color':'black'}. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This also needs examples.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
see response above
FlowCal/plot.py
Outdated
draw_summary_stat_fxn=draw_summary_stat_fxn, | ||
draw_summary_stat_kwargs=v_draw_summary_stat_kwargs) | ||
|
||
if draw_model: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why is this inside the for idx in range(data_length):
? Does this mean that the model plot is made every time a new violin is plotted?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hmm, good catch. Yeah, that should probably be unindented once.
Having read the code, I still think these should be made into two functions. The mere existence of the advanced transfer function-specific parameters complicates how parameters are interpreted, which makes the documentation really hard to follow. For example, Therefore, I think these should be split in the following way:
Also, I like that |
(sorry, I just saw your last summary comment) I think I'd be amenable to most of what you're suggesting.
This sounds good to me. Nice and simple. I'm still not sure how best to handle data at position zero, but I think that'll become clearer after we look into
A better name would help me digest this one. Regarding
That name change sounds good to me. The |
In old-school biology papers, these "transfer functions" are usually called "dose response curves" (e.g. https://academic.oup.com/nar/article/25/6/1203/1197243). I say we fully embrace the function's intended application and use something like
Sounds good to me. |
Hmm, I definitely like |
As we discussed, we should also change the example files with one of the datasets in your paper since they illustrate the features of
|
bc98686 adds a Support for horizontal violins was added symmetrically, so position=0 violins are separately illustrated for both vertical and horizontal violin plots when the position axis is logarithmic. Unit tests still pass in Additional code used for testing: plot.violin() stress test codeimport FlowCal
import numpy as np
import matplotlib.pyplot as plt
filenames = ['FCFiles/Data{:03d}.fcs'.format(i) for i in range(1,5+1)]
d = [FlowCal.io.FCSData(filename) for filename in filenames]
d = [FlowCal.transform.to_rfi(di) for di in d]
iptg = [0, 81, 161, 318, 1000]
figsize=(3,2.5)
plt.figure(figsize=figsize)
FlowCal.plot.violin(data=d, channel='FL1', positions=iptg, xlabel='IPTG (uM)')
plt.figure(figsize=figsize)
FlowCal.plot.violin(data=d, channel='FL1', positions=iptg, xlabel='IPTG (uM)', yscale='linear', ylim=(0,4000), bin_edges=np.linspace(0,4000,101), lower_trim_fraction=0)
plt.figure(figsize=figsize)
FlowCal.plot.violin(data=d, channel='FL1', positions=iptg, xlabel='IPTG (uM)', yscale='linear', ylim=(0,4000), bin_edges=np.linspace(0,4000,101), density=True, lower_trim_fraction=0)
plt.figure(figsize=figsize)
FlowCal.plot.violin(data=d, channel='FL1', positions=iptg, xlabel='IPTG (uM)', yscale='linear', ylim=(0,4000), bin_edges=np.logspace(0,4,101), lower_trim_fraction=0)
plt.figure(figsize=figsize)
FlowCal.plot.violin(data=d, channel='FL1', positions=iptg, xlabel='IPTG (uM)', yscale='linear', ylim=(0,4000), bin_edges=np.logspace(0,4,101), density=True, lower_trim_fraction=0)
plt.figure(figsize=figsize)
FlowCal.plot.violin(data=d, channel='FL1', positions=iptg, xlabel='IPTG (uM)', yscale='log', bin_edges=np.linspace(1,4000,201), lower_trim_fraction=0)
plt.figure(figsize=figsize)
FlowCal.plot.violin(data=d, channel='FL1', positions=iptg, xlabel='IPTG (uM)', yscale='log', bin_edges=np.linspace(1,4000,201), density=True, lower_trim_fraction=0)
plt.figure(figsize=figsize)
FlowCal.plot.violin(data=d, channel='FL1', positions=iptg, xlabel='IPTG (uM)', yscale='log', bin_edges=np.logspace(0,4,101), lower_trim_fraction=0)
plt.figure(figsize=figsize)
FlowCal.plot.violin(data=d, channel='FL1', positions=iptg, xlabel='IPTG (uM)', yscale='log', bin_edges=np.logspace(0,4,101), density=True, lower_trim_fraction=0)
plt.figure(figsize=figsize)
FlowCal.plot.violin(data=d, channel='FL1', positions=iptg, xlabel='IPTG (uM)', xscale='log')
plt.figure(figsize=figsize)
FlowCal.plot.violin(data=d[1:], channel='FL1', positions=iptg[1:], xlabel='IPTG (uM)', xscale='log')
plt.figure(figsize=figsize)
FlowCal.plot.violin(
data=d,
channel='FL1',
positions=iptg,
xlabel='IPTG (uM)',
xscale='log',
violin_width=0.5,
ylim=(1e0,1e4),
xlim=(1e1,1e4),
num_bins=30)
plt.figure(figsize=figsize)
FlowCal.plot.violin(
data=d,
channel='FL1',
positions=iptg,
xlabel='IPTG (uM)',
xscale='log',
violin_width=0.5,
ylim=(1e0,1e4),
xlim=(1e1,1e4),
bin_edges=np.logspace(0,4,30))
plt.figure(figsize=figsize)
FlowCal.plot.violin(
data=d,
channel='FL1',
positions=iptg,
xlabel='IPTG (uM)',
xscale='log',
violin_width=0.5,
ylim=(1e0,1e4),
xlim=(1e1,1e4),
bin_edges=np.logspace(0,4,30),
upper_trim_fraction=0.1,
lower_trim_fraction=0.05)
plt.figure(figsize=figsize)
FlowCal.plot.violin(
data=d,
channel='FL1',
positions=iptg,
xlabel='IPTG (uM)',
xscale='log',
violin_width_to_span_fraction=0.025,
ylim=(1e0,1e4),
xlim=(1e1,1e4),
bin_edges=np.logspace(0,4,30),
upper_trim_fraction=0.1,
lower_trim_fraction=0.05)
plt.figure(figsize=figsize)
FlowCal.plot.violin(
data=d,
channel='FL1',
positions=iptg,
xlabel='IPTG (uM)',
xscale='log',
violin_width=0.5,
ylim=(1e0,1e4),
xlim=(1e1,1e4),
bin_edges=np.logspace(0,4,30),
upper_trim_fraction=0.1,
lower_trim_fraction=0.05,
violin_kwargs={'facecolor':'red', 'edgecolor':'blue'})
plt.figure(figsize=figsize)
FlowCal.plot.violin(
data=d,
channel='FL1',
positions=iptg,
xlabel='IPTG (uM)',
xscale='log',
violin_width=0.5,
ylim=(1e0,1e4),
xlim=(1e1,1e4),
bin_edges=np.logspace(0,4,30),
upper_trim_fraction=0.1,
lower_trim_fraction=0.05,
violin_kwargs={'facecolor':'red', 'edgecolor':'blue'},
draw_summary_stat=False)
plt.figure(figsize=figsize)
FlowCal.plot.violin(
data=d,
channel='FL1',
positions=iptg,
xlabel='IPTG (uM)',
xscale='log',
violin_width=0.5,
ylim=(1e0,1e4),
xlim=(1e1,1e4),
bin_edges=np.logspace(0,4,30),
upper_trim_fraction=0.1,
lower_trim_fraction=0.05,
violin_kwargs={'facecolor':'red', 'edgecolor':'blue'},
draw_summary_stat_fxn=np.median,
draw_summary_stat_kwargs={'color':'green'})
plt.figure(figsize=figsize)
FlowCal.plot.violin(
data=d,
channel='FL1',
positions=iptg,
xlabel='IPTG (uM)',
xscale='log',
violin_width=0.5,
ylim=(1e0,1e4),
xlim=(1e1,1e4),
bin_edges=np.logspace(0,4,30),
upper_trim_fraction=0.1,
lower_trim_fraction=0.05,
violin_kwargs={'facecolor':'red', 'edgecolor':'blue'},
draw_summary_stat_fxn=np.median,
draw_summary_stat_kwargs={'color':'green'},
log_zero_tick_label='test')
plt.figure(figsize=figsize)
FlowCal.plot.violin(
data=d,
channel='FL1',
positions=iptg,
xlabel='IPTG (uM)',
xscale='log',
violin_width=0.5,
ylim=(1e0,1e4),
xlim=(1e1,1e4),
bin_edges=np.logspace(0,4,30),
upper_trim_fraction=0.1,
lower_trim_fraction=0.05,
violin_kwargs={'facecolor':'red', 'edgecolor':'blue'},
draw_summary_stat_fxn=np.median,
draw_summary_stat_kwargs={'color':'green'},
log_zero_tick_label='test',
draw_log_zero_divider_kwargs={'color':'purple'})
plt.figure(figsize=figsize)
FlowCal.plot.violin(
data=d,
channel='FL1',
positions=iptg,
xlabel='IPTG (uM)',
xscale='log',
violin_width=0.5,
ylim=(1e0,1e4),
xlim=(1e1,1e4),
bin_edges=[np.logspace(0,4,30),
np.logspace(0,4,200),
np.logspace(0,4,20),
np.logspace(0,4,200),
np.logspace(0,4,30)],
upper_trim_fraction=[0.1, 0.25, 0.01, 0.1, 0.01],
lower_trim_fraction=[0.25, 0.01, 0.1, 0.05, 0.1],
violin_kwargs=[{'facecolor':'red', 'edgecolor':'purple'},
{'facecolor':'orange', 'edgecolor':'blue'},
{'facecolor':'yellow', 'edgecolor':'green'},
{'facecolor':'green', 'edgecolor':'yellow'},
{'facecolor':'blue', 'edgecolor':'orange'}],
draw_summary_stat_fxn=np.median,
draw_summary_stat_kwargs=[{'color':'blue'},
{'color':'black'},
{'color':'red'},
{'color':'blue'},
{'color':'white'},],
log_zero_tick_label='test',
draw_log_zero_divider_kwargs={'color':'purple'})
###
# vert
###
figsize=(2,2)
plt.figure(figsize=figsize)
FlowCal.plot.violin(data=d, channel='FL1', positions=iptg, ylabel='IPTG (uM)', vert=False)
plt.figure(figsize=figsize)
FlowCal.plot.violin(data=d, channel='FL1', positions=iptg, ylabel='IPTG (uM)', xscale='linear', xlim=(0,4000), bin_edges=np.linspace(0,4000,101), lower_trim_fraction=0, vert=False)
plt.figure(figsize=figsize)
FlowCal.plot.violin(data=d, channel='FL1', positions=iptg, ylabel='IPTG (uM)', xscale='linear', xlim=(0,4000), bin_edges=np.linspace(0,4000,101), density=True, lower_trim_fraction=0, vert=False)
plt.figure(figsize=figsize)
FlowCal.plot.violin(data=d, channel='FL1', positions=iptg, ylabel='IPTG (uM)', xscale='linear', xlim=(0,4000), bin_edges=np.logspace(0,4,101), lower_trim_fraction=0, vert=False)
plt.figure(figsize=figsize)
FlowCal.plot.violin(data=d, channel='FL1', positions=iptg, ylabel='IPTG (uM)', xscale='linear', xlim=(0,4000), bin_edges=np.logspace(0,4,101), density=True, lower_trim_fraction=0, vert=False)
plt.figure(figsize=figsize)
FlowCal.plot.violin(data=d, channel='FL1', positions=iptg, ylabel='IPTG (uM)', xscale='log', bin_edges=np.linspace(1,4000,201), lower_trim_fraction=0, vert=False)
plt.figure(figsize=figsize)
FlowCal.plot.violin(data=d, channel='FL1', positions=iptg, ylabel='IPTG (uM)', xscale='log', bin_edges=np.linspace(1,4000,201), density=True, lower_trim_fraction=0, vert=False)
plt.figure(figsize=figsize)
FlowCal.plot.violin(data=d, channel='FL1', positions=iptg, ylabel='IPTG (uM)', xscale='log', bin_edges=np.logspace(0,4,101), lower_trim_fraction=0, vert=False)
plt.figure(figsize=figsize)
FlowCal.plot.violin(data=d, channel='FL1', positions=iptg, ylabel='IPTG (uM)', xscale='log', bin_edges=np.logspace(0,4,101), density=True, lower_trim_fraction=0, vert=False)
plt.figure(figsize=figsize)
FlowCal.plot.violin(data=d, channel='FL1', positions=iptg, ylabel='IPTG (uM)', yscale='log', vert=False)
plt.figure(figsize=figsize)
FlowCal.plot.violin(data=d[1:], channel='FL1', positions=iptg[1:], ylabel='IPTG (uM)', yscale='log', vert=False)
plt.figure(figsize=figsize)
FlowCal.plot.violin(
data=d,
channel='FL1',
positions=iptg,
ylabel='IPTG (uM)',
yscale='log',
violin_width=0.5,
xlim=(1e0,1e4),
ylim=(1e1,1e4),
num_bins=30,
vert=False)
plt.figure(figsize=figsize)
FlowCal.plot.violin(
data=d,
channel='FL1',
positions=iptg,
ylabel='IPTG (uM)',
yscale='log',
violin_width=0.5,
xlim=(1e0,1e4),
ylim=(1e1,1e4),
bin_edges=np.logspace(0,4,30),
vert=False)
plt.figure(figsize=figsize)
FlowCal.plot.violin(
data=d,
channel='FL1',
positions=iptg,
ylabel='IPTG (uM)',
yscale='log',
violin_width=0.5,
xlim=(1e0,1e4),
ylim=(1e1,1e4),
bin_edges=np.logspace(0,4,30),
upper_trim_fraction=0.1,
lower_trim_fraction=0.05,
vert=False)
plt.figure(figsize=figsize)
FlowCal.plot.violin(
data=d,
channel='FL1',
positions=iptg,
ylabel='IPTG (uM)',
yscale='log',
violin_width_to_span_fraction=0.025,
xlim=(1e0,1e4),
ylim=(1e1,1e4),
bin_edges=np.logspace(0,4,30),
upper_trim_fraction=0.1,
lower_trim_fraction=0.05,
vert=False)
plt.figure(figsize=figsize)
FlowCal.plot.violin(
data=d,
channel='FL1',
positions=iptg,
ylabel='IPTG (uM)',
yscale='log',
violin_width=0.5,
xlim=(1e0,1e4),
ylim=(1e1,1e4),
bin_edges=np.logspace(0,4,30),
upper_trim_fraction=0.1,
lower_trim_fraction=0.05,
violin_kwargs={'facecolor':'red', 'edgecolor':'blue'},
vert=False)
plt.figure(figsize=figsize)
FlowCal.plot.violin(
data=d,
channel='FL1',
positions=iptg,
ylabel='IPTG (uM)',
yscale='log',
violin_width=0.5,
xlim=(1e0,1e4),
ylim=(1e1,1e4),
bin_edges=np.logspace(0,4,30),
upper_trim_fraction=0.1,
lower_trim_fraction=0.05,
violin_kwargs={'facecolor':'red', 'edgecolor':'blue'},
draw_summary_stat=False,
vert=False)
plt.figure(figsize=figsize)
FlowCal.plot.violin(
data=d,
channel='FL1',
positions=iptg,
ylabel='IPTG (uM)',
yscale='log',
violin_width=0.5,
xlim=(1e0,1e4),
ylim=(1e1,1e4),
bin_edges=np.logspace(0,4,30),
upper_trim_fraction=0.1,
lower_trim_fraction=0.05,
violin_kwargs={'facecolor':'red', 'edgecolor':'blue'},
draw_summary_stat_fxn=np.median,
draw_summary_stat_kwargs={'color':'green'},
vert=False)
plt.figure(figsize=figsize)
FlowCal.plot.violin(
data=d,
channel='FL1',
positions=iptg,
ylabel='IPTG (uM)',
yscale='log',
violin_width=0.5,
xlim=(1e0,1e4),
ylim=(1e1,1e4),
bin_edges=np.logspace(0,4,30),
upper_trim_fraction=0.1,
lower_trim_fraction=0.05,
violin_kwargs={'facecolor':'red', 'edgecolor':'blue'},
draw_summary_stat_fxn=np.median,
draw_summary_stat_kwargs={'color':'green'},
log_zero_tick_label='test',
vert=False)
plt.figure(figsize=figsize)
FlowCal.plot.violin(
data=d,
channel='FL1',
positions=iptg,
ylabel='IPTG (uM)',
yscale='log',
violin_width=0.5,
xlim=(1e0,1e4),
ylim=(1e1,1e4),
bin_edges=np.logspace(0,4,30),
upper_trim_fraction=0.1,
lower_trim_fraction=0.05,
violin_kwargs={'facecolor':'red', 'edgecolor':'blue'},
draw_summary_stat_fxn=np.median,
draw_summary_stat_kwargs={'color':'green'},
log_zero_tick_label='test',
draw_log_zero_divider_kwargs={'color':'purple'},
vert=False)
plt.figure(figsize=figsize)
FlowCal.plot.violin(
data=d,
channel='FL1',
positions=iptg,
ylabel='IPTG (uM)',
yscale='log',
violin_width=0.5,
xlim=(1e0,1e4),
ylim=(1e1,1e4),
bin_edges=[np.logspace(0,4,30),
np.logspace(0,4,200),
np.logspace(0,4,20),
np.logspace(0,4,200),
np.logspace(0,4,30)],
upper_trim_fraction=[0.1, 0.25, 0.01, 0.1, 0.01],
lower_trim_fraction=[0.25, 0.01, 0.1, 0.05, 0.1],
violin_kwargs=[{'facecolor':'red', 'edgecolor':'purple'},
{'facecolor':'orange', 'edgecolor':'blue'},
{'facecolor':'yellow', 'edgecolor':'green'},
{'facecolor':'green', 'edgecolor':'yellow'},
{'facecolor':'blue', 'edgecolor':'orange'}],
draw_summary_stat_fxn=np.median,
draw_summary_stat_kwargs=[{'color':'blue'},
{'color':'black'},
{'color':'red'},
{'color':'blue'},
{'color':'white'},],
log_zero_tick_label='test',
draw_log_zero_divider_kwargs={'color':'purple'},
vert=False)
plt.show() plot.violin_dose_response() stress test codeimport FlowCal
import numpy as np
import matplotlib.pyplot as plt
filenames = ['FCFiles/Data{:03d}.fcs'.format(i) for i in range(1,5+1)]
d = [FlowCal.io.FCSData(filename) for filename in filenames]
d = [FlowCal.transform.to_rfi(di) for di in d]
iptg = [0, 81, 161, 318, 1000]
figsize=(3,2.5)
plt.figure(figsize=figsize)
FlowCal.plot.violin_dose_response(data=d, channel='FL1', positions=iptg, xlabel='IPTG (uM)')
plt.figure(figsize=figsize)
FlowCal.plot.violin_dose_response(data=d, channel='FL1', positions=iptg, xlabel='IPTG (uM)', yscale='linear', ylim=(0,4000), bin_edges=np.linspace(0,4000,101), lower_trim_fraction=0)
plt.figure(figsize=figsize)
FlowCal.plot.violin_dose_response(data=d, channel='FL1', positions=iptg, xlabel='IPTG (uM)', yscale='linear', ylim=(0,4000), bin_edges=np.linspace(0,4000,101), density=True, lower_trim_fraction=0)
plt.figure(figsize=figsize)
FlowCal.plot.violin_dose_response(data=d, channel='FL1', positions=iptg, xlabel='IPTG (uM)', yscale='linear', ylim=(0,4000), bin_edges=np.logspace(0,4,101), lower_trim_fraction=0)
plt.figure(figsize=figsize)
FlowCal.plot.violin_dose_response(data=d, channel='FL1', positions=iptg, xlabel='IPTG (uM)', yscale='linear', ylim=(0,4000), bin_edges=np.logspace(0,4,101), density=True, lower_trim_fraction=0)
plt.figure(figsize=figsize)
FlowCal.plot.violin_dose_response(data=d, channel='FL1', positions=iptg, xlabel='IPTG (uM)', yscale='log', bin_edges=np.linspace(1,4000,201), lower_trim_fraction=0)
plt.figure(figsize=figsize)
FlowCal.plot.violin_dose_response(data=d, channel='FL1', positions=iptg, xlabel='IPTG (uM)', yscale='log', bin_edges=np.linspace(1,4000,201), density=True, lower_trim_fraction=0)
plt.figure(figsize=figsize)
FlowCal.plot.violin_dose_response(data=d, channel='FL1', positions=iptg, xlabel='IPTG (uM)', yscale='log', bin_edges=np.logspace(0,4,101), lower_trim_fraction=0)
plt.figure(figsize=figsize)
FlowCal.plot.violin_dose_response(data=d, channel='FL1', positions=iptg, xlabel='IPTG (uM)', yscale='log', bin_edges=np.logspace(0,4,101), density=True, lower_trim_fraction=0)
plt.figure(figsize=figsize)
FlowCal.plot.violin_dose_response(data=d, channel='FL1', positions=iptg, xlabel='IPTG (uM)', xscale='log')
plt.figure(figsize=figsize)
FlowCal.plot.violin_dose_response(data=d[1:], channel='FL1', positions=iptg[1:], xlabel='IPTG (uM)', xscale='log')
plt.figure(figsize=figsize)
FlowCal.plot.violin_dose_response(
data=d,
channel='FL1',
positions=iptg,
xlabel='IPTG (uM)',
xscale='log',
violin_width=0.5,
ylim=(1e0,1e4),
xlim=(1e1,1e4),
num_bins=30)
plt.figure(figsize=figsize)
FlowCal.plot.violin_dose_response(
data=d,
channel='FL1',
positions=iptg,
xlabel='IPTG (uM)',
xscale='log',
violin_width=0.5,
ylim=(1e0,1e4),
xlim=(1e1,1e4),
bin_edges=np.logspace(0,4,30))
plt.figure(figsize=figsize)
FlowCal.plot.violin_dose_response(
data=d,
channel='FL1',
positions=iptg,
xlabel='IPTG (uM)',
xscale='log',
violin_width=0.5,
ylim=(1e0,1e4),
xlim=(1e1,1e4),
bin_edges=np.logspace(0,4,30),
upper_trim_fraction=0.1,
lower_trim_fraction=0.05)
plt.figure(figsize=figsize)
FlowCal.plot.violin_dose_response(
data=d,
channel='FL1',
positions=iptg,
xlabel='IPTG (uM)',
xscale='log',
violin_width_to_span_fraction=0.025,
ylim=(1e0,1e4),
xlim=(1e1,1e4),
bin_edges=np.logspace(0,4,30),
upper_trim_fraction=0.1,
lower_trim_fraction=0.05)
plt.figure(figsize=figsize)
FlowCal.plot.violin_dose_response(
data=d,
channel='FL1',
positions=iptg,
xlabel='IPTG (uM)',
xscale='log',
violin_width=0.5,
ylim=(1e0,1e4),
xlim=(1e1,1e4),
bin_edges=np.logspace(0,4,30),
upper_trim_fraction=0.1,
lower_trim_fraction=0.05,
violin_kwargs={'facecolor':'red', 'edgecolor':'blue'})
plt.figure(figsize=figsize)
FlowCal.plot.violin_dose_response(
data=d,
channel='FL1',
positions=iptg,
xlabel='IPTG (uM)',
xscale='log',
violin_width=0.5,
ylim=(1e0,1e4),
xlim=(1e1,1e4),
bin_edges=np.logspace(0,4,30),
upper_trim_fraction=0.1,
lower_trim_fraction=0.05,
violin_kwargs={'facecolor':'red', 'edgecolor':'blue'},
draw_summary_stat=False)
plt.figure(figsize=figsize)
FlowCal.plot.violin_dose_response(
data=d,
channel='FL1',
positions=iptg,
xlabel='IPTG (uM)',
xscale='log',
violin_width=0.5,
ylim=(1e0,1e4),
xlim=(1e1,1e4),
bin_edges=np.logspace(0,4,30),
upper_trim_fraction=0.1,
lower_trim_fraction=0.05,
violin_kwargs={'facecolor':'red', 'edgecolor':'blue'},
draw_summary_stat_fxn=np.median,
draw_summary_stat_kwargs={'color':'green'})
plt.figure(figsize=figsize)
FlowCal.plot.violin_dose_response(
data=d,
channel='FL1',
positions=iptg,
xlabel='IPTG (uM)',
xscale='log',
violin_width=0.5,
ylim=(1e0,1e4),
xlim=(1e1,1e4),
bin_edges=np.logspace(0,4,30),
upper_trim_fraction=0.1,
lower_trim_fraction=0.05,
violin_kwargs={'facecolor':'red', 'edgecolor':'blue'},
draw_summary_stat_fxn=np.median,
draw_summary_stat_kwargs={'color':'green'},
log_zero_tick_label='test')
plt.figure(figsize=figsize)
FlowCal.plot.violin_dose_response(
data=d,
channel='FL1',
positions=iptg,
xlabel='IPTG (uM)',
xscale='log',
violin_width=0.5,
ylim=(1e0,1e4),
xlim=(1e1,1e4),
bin_edges=np.logspace(0,4,30),
upper_trim_fraction=0.1,
lower_trim_fraction=0.05,
violin_kwargs={'facecolor':'red', 'edgecolor':'blue'},
draw_summary_stat_fxn=np.median,
draw_summary_stat_kwargs={'color':'green'},
log_zero_tick_label='test',
draw_log_zero_divider_kwargs={'color':'purple'})
plt.figure(figsize=figsize)
FlowCal.plot.violin_dose_response(
data=d,
channel='FL1',
positions=iptg,
xlabel='IPTG (uM)',
xscale='log',
violin_width=0.5,
ylim=(1e0,1e4),
xlim=(1e1,1e4),
bin_edges=[np.logspace(0,4,30),
np.logspace(0,4,200),
np.logspace(0,4,20),
np.logspace(0,4,200),
np.logspace(0,4,30)],
upper_trim_fraction=[0.1, 0.25, 0.01, 0.1, 0.01],
lower_trim_fraction=[0.25, 0.01, 0.1, 0.05, 0.1],
violin_kwargs=[{'facecolor':'red', 'edgecolor':'purple'},
{'facecolor':'orange', 'edgecolor':'blue'},
{'facecolor':'yellow', 'edgecolor':'green'},
{'facecolor':'green', 'edgecolor':'yellow'},
{'facecolor':'blue', 'edgecolor':'orange'}],
draw_summary_stat_fxn=np.median,
draw_summary_stat_kwargs=[{'color':'blue'},
{'color':'black'},
{'color':'red'},
{'color':'blue'},
{'color':'white'},],
log_zero_tick_label='test',
draw_log_zero_divider_kwargs={'color':'purple'})
def iptg_hill_model(iptg_concentration):
mn = 20.
mx = 1700.
K = 300.
n = 1.5
if iptg_concentration <= 0:
return mn
else:
return mn + ((mx-mn)/(1+((K/iptg_concentration)**n)))
plt.figure(figsize=figsize)
FlowCal.plot.violin_dose_response(
data=d,
model_fxn=iptg_hill_model,
channel='FL1',
positions=iptg,
xlabel='IPTG (uM)',
xscale='log',
violin_width=0.5,
ylim=(1e0,1e4),
xlim=(1e1,1e4),
bin_edges=[np.logspace(0,4,30),
np.logspace(0,4,200),
np.logspace(0,4,20),
np.logspace(0,4,200),
np.logspace(0,4,30)],
upper_trim_fraction=[0.1, 0.25, 0.01, 0.1, 0.01],
lower_trim_fraction=[0.25, 0.01, 0.1, 0.05, 0.1],
violin_kwargs=[{'facecolor':'red', 'edgecolor':'purple'},
{'facecolor':'orange', 'edgecolor':'blue'},
{'facecolor':'yellow', 'edgecolor':'green'},
{'facecolor':'green', 'edgecolor':'yellow'},
{'facecolor':'blue', 'edgecolor':'orange'}],
draw_summary_stat_fxn=np.median,
draw_summary_stat_kwargs=[{'color':'blue'},
{'color':'black'},
{'color':'red'},
{'color':'blue'},
{'color':'white'},],
min_tick_label='jing',
max_tick_label='gle',
log_zero_tick_label='bells',
draw_log_zero_divider_kwargs={'color':'purple'},
min_bin_edges=np.logspace(0,4,200),
max_bin_edges=np.logspace(0,4,20),
min_upper_trim_fraction=0.2,
min_lower_trim_fraction=0,
max_upper_trim_fraction=0,
max_lower_trim_fraction=0.1,
min_violin_kwargs={'facecolor':'green', 'edgecolor':'purple'},
max_violin_kwargs={'facecolor':'blue', 'edgecolor':'orange'},
min_draw_summary_stat_kwargs={'color':'black'},
max_draw_summary_stat_kwargs={'color':'white'},
draw_min_line_kwargs={'color':'green'},
draw_max_line_kwargs={'color':'blue'},
draw_model_kwargs={'color':'red','linestyle':':'},
draw_minmax_divider_kwargs={'color':'blue','linestyle':'--'})
plt.figure(figsize=figsize)
FlowCal.plot.violin_dose_response(
data=d,
min_data=d[0],
model_fxn=iptg_hill_model,
channel='FL1',
positions=iptg,
xlabel='IPTG (uM)',
xscale='log',
violin_width=0.5,
ylim=(1e0,1e4),
xlim=(1e1,1e4),
bin_edges=[np.logspace(0,4,30),
np.logspace(0,4,200),
np.logspace(0,4,20),
np.logspace(0,4,200),
np.logspace(0,4,30)],
upper_trim_fraction=[0.1, 0.25, 0.01, 0.1, 0.01],
lower_trim_fraction=[0.25, 0.01, 0.1, 0.05, 0.1],
violin_kwargs=[{'facecolor':'red', 'edgecolor':'purple'},
{'facecolor':'orange', 'edgecolor':'blue'},
{'facecolor':'yellow', 'edgecolor':'green'},
{'facecolor':'green', 'edgecolor':'yellow'},
{'facecolor':'blue', 'edgecolor':'orange'}],
draw_summary_stat_fxn=np.median,
draw_summary_stat_kwargs=[{'color':'blue'},
{'color':'black'},
{'color':'red'},
{'color':'blue'},
{'color':'white'},],
min_tick_label='jing',
max_tick_label='gle',
log_zero_tick_label='bells',
draw_log_zero_divider_kwargs={'color':'purple'},
min_bin_edges=np.logspace(0,4,200),
max_bin_edges=np.logspace(0,4,20),
min_upper_trim_fraction=0.2,
min_lower_trim_fraction=0,
max_upper_trim_fraction=0,
max_lower_trim_fraction=0.1,
min_violin_kwargs={'facecolor':'green', 'edgecolor':'purple'},
max_violin_kwargs={'facecolor':'blue', 'edgecolor':'orange'},
min_draw_summary_stat_kwargs={'color':'black'},
max_draw_summary_stat_kwargs={'color':'white'},
draw_min_line_kwargs={'color':'green'},
draw_max_line_kwargs={'color':'blue'},
draw_model_kwargs={'color':'red','linestyle':':'},
draw_minmax_divider_kwargs={'color':'blue','linestyle':'--'})
plt.figure(figsize=figsize)
FlowCal.plot.violin_dose_response(
data=d,
max_data=d[-1],
model_fxn=iptg_hill_model,
channel='FL1',
positions=iptg,
xlabel='IPTG (uM)',
xscale='log',
violin_width=0.5,
ylim=(1e0,1e4),
xlim=(1e1,1e4),
bin_edges=[np.logspace(0,4,30),
np.logspace(0,4,200),
np.logspace(0,4,20),
np.logspace(0,4,200),
np.logspace(0,4,30)],
upper_trim_fraction=[0.1, 0.25, 0.01, 0.1, 0.01],
lower_trim_fraction=[0.25, 0.01, 0.1, 0.05, 0.1],
violin_kwargs=[{'facecolor':'red', 'edgecolor':'purple'},
{'facecolor':'orange', 'edgecolor':'blue'},
{'facecolor':'yellow', 'edgecolor':'green'},
{'facecolor':'green', 'edgecolor':'yellow'},
{'facecolor':'blue', 'edgecolor':'orange'}],
draw_summary_stat_fxn=np.median,
draw_summary_stat_kwargs=[{'color':'blue'},
{'color':'black'},
{'color':'red'},
{'color':'blue'},
{'color':'white'},],
min_tick_label='jing',
max_tick_label='gle',
log_zero_tick_label='bells',
draw_log_zero_divider_kwargs={'color':'purple'},
min_bin_edges=np.logspace(0,4,200),
max_bin_edges=np.logspace(0,4,20),
min_upper_trim_fraction=0.2,
min_lower_trim_fraction=0,
max_upper_trim_fraction=0,
max_lower_trim_fraction=0.1,
min_violin_kwargs={'facecolor':'green', 'edgecolor':'purple'},
max_violin_kwargs={'facecolor':'blue', 'edgecolor':'orange'},
min_draw_summary_stat_kwargs={'color':'black'},
max_draw_summary_stat_kwargs={'color':'white'},
draw_min_line_kwargs={'color':'green'},
draw_max_line_kwargs={'color':'blue'},
draw_model_kwargs={'color':'red','linestyle':':'},
draw_minmax_divider_kwargs={'color':'blue','linestyle':'--'})
plt.figure(figsize=figsize)
FlowCal.plot.violin_dose_response(
data=d,
min_data=d[0],
max_data=d[-1],
model_fxn=iptg_hill_model,
channel='FL1',
positions=iptg,
xlabel='IPTG (uM)',
xscale='log',
violin_width=0.5,
ylim=(1e0,1e4),
xlim=(1e1,1e4),
bin_edges=[np.logspace(0,4,30),
np.logspace(0,4,200),
np.logspace(0,4,20),
np.logspace(0,4,200),
np.logspace(0,4,30)],
upper_trim_fraction=[0.1, 0.25, 0.01, 0.1, 0.01],
lower_trim_fraction=[0.25, 0.01, 0.1, 0.05, 0.1],
violin_kwargs=[{'facecolor':'red', 'edgecolor':'purple'},
{'facecolor':'orange', 'edgecolor':'blue'},
{'facecolor':'yellow', 'edgecolor':'green'},
{'facecolor':'green', 'edgecolor':'yellow'},
{'facecolor':'blue', 'edgecolor':'orange'}],
draw_summary_stat_fxn=np.median,
draw_summary_stat_kwargs=[{'color':'blue'},
{'color':'black'},
{'color':'red'},
{'color':'blue'},
{'color':'white'},],
min_tick_label='jing',
max_tick_label='gle',
log_zero_tick_label='bells',
draw_log_zero_divider_kwargs={'color':'purple'},
min_bin_edges=np.logspace(0,4,200),
max_bin_edges=np.logspace(0,4,20),
min_upper_trim_fraction=0.2,
min_lower_trim_fraction=0,
max_upper_trim_fraction=0,
max_lower_trim_fraction=0.1,
min_violin_kwargs={'facecolor':'green', 'edgecolor':'purple'},
max_violin_kwargs={'facecolor':'blue', 'edgecolor':'orange'},
min_draw_summary_stat_kwargs={'color':'black'},
max_draw_summary_stat_kwargs={'color':'white'},
draw_min_line_kwargs={'color':'green'},
draw_max_line_kwargs={'color':'blue'},
draw_model_kwargs={'color':'red','linestyle':':'},
draw_minmax_divider_kwargs={'color':'blue','linestyle':'--'})
plt.figure(figsize=figsize)
FlowCal.plot.violin_dose_response(
data=d,
min_data=d[0],
max_data=d[-1],
model_fxn=iptg_hill_model,
channel='FL1',
positions=iptg,
xlabel='IPTG (uM)',
xscale='log',
violin_width=0.5,
ylim=(1e0,1e4),
xlim=(1e1,1e4),
bin_edges=[np.logspace(0,4,30),
np.logspace(0,4,200),
np.logspace(0,4,20),
np.logspace(0,4,200),
np.logspace(0,4,30)],
upper_trim_fraction=[0.1, 0.25, 0.01, 0.1, 0.01],
lower_trim_fraction=[0.25, 0.01, 0.1, 0.05, 0.1],
violin_kwargs=[{'facecolor':'red', 'edgecolor':'purple'},
{'facecolor':'orange', 'edgecolor':'blue'},
{'facecolor':'yellow', 'edgecolor':'green'},
{'facecolor':'green', 'edgecolor':'yellow'},
{'facecolor':'blue', 'edgecolor':'orange'}],
draw_summary_stat_fxn=np.median,
draw_summary_stat_kwargs=[{'color':'blue'},
{'color':'black'},
{'color':'red'},
{'color':'blue'},
{'color':'white'},],
min_tick_label='jing',
max_tick_label='gle',
log_zero_tick_label='bells',
draw_log_zero_divider_kwargs={'color':'purple'},
min_bin_edges=np.logspace(0,4,200),
max_bin_edges=np.logspace(0,4,20),
min_upper_trim_fraction=0.2,
min_lower_trim_fraction=0,
max_upper_trim_fraction=0,
max_lower_trim_fraction=0.1,
min_violin_kwargs={'facecolor':'green', 'edgecolor':'purple'},
max_violin_kwargs={'facecolor':'blue', 'edgecolor':'orange'},
min_draw_summary_stat_kwargs={'color':'black'},
max_draw_summary_stat_kwargs={'color':'white'},
draw_min_line_kwargs={'color':'green'},
draw_max_line_kwargs={'color':'blue'},
draw_model_kwargs={'color':'red','linestyle':':'},
draw_minmax_divider_kwargs={'color':'blue','linestyle':'--'},
density=True) Logicle stress test codeimport FlowCal
import numpy as np
import matplotlib.pyplot as plt
d1 = FlowCal.io.FCSData('./Data004.fcs')
d1 = FlowCal.transform.to_rfi(d1)
d2 = FlowCal.io.FCSData('./Data004.fcs')
d2 = FlowCal.transform.to_rfi(d2)
d2[:,'GFP-A'] += 1e3
d2[:,'mCherry-A'] += 1e3
d_max = FlowCal.io.FCSData('./Data004.fcs')
d_max = FlowCal.transform.to_rfi(d_max)
d_max[:,'GFP-A'] += 5e3
d_max[:,'mCherry-A'] += 5e3
figsize=(3,2.5)
plt.figure(figsize=figsize)
FlowCal.plot.violin(data=[d1,d2,d1,d2], channel='GFP-A', yscale='logicle', density=False, num_bins=30, upper_trim_fraction=0, lower_trim_fraction=0, ylim=(-1000,1e5))
plt.figure(figsize=figsize)
FlowCal.plot.violin(data=[d1,d2,d1,d2], channel='GFP-A', yscale='logicle', density=True, num_bins=30, upper_trim_fraction=0, lower_trim_fraction=0, ylim=(-1000,1e5))
plt.figure(figsize=figsize)
FlowCal.plot.violin(data=[d1,d2,d1,d2], channel='GFP-A', yscale='logicle', density=False, num_bins=200, upper_trim_fraction=0, lower_trim_fraction=0, ylim=(-1000,1e5))
plt.figure(figsize=figsize)
FlowCal.plot.violin(data=[d1,d2,d1,d2], channel='GFP-A', yscale='logicle', density=True, num_bins=200, upper_trim_fraction=0, lower_trim_fraction=0, ylim=(-1000,1e5))
plt.figure(figsize=figsize)
FlowCal.plot.violin(data=[d1,d2,d1,d2], channel='GFP-A', yscale='logicle', density=False, bin_edges=np.linspace(-1000,1e4,1000), upper_trim_fraction=0, lower_trim_fraction=0, ylim=(-1000,1e5))
plt.figure(figsize=figsize)
FlowCal.plot.violin(data=[d1,d2,d1,d2], channel='GFP-A', yscale='logicle', density=True, bin_edges=np.linspace(-1000,1e4,1000), upper_trim_fraction=0, lower_trim_fraction=0, ylim=(-1000,1e5))
plt.figure(figsize=figsize)
FlowCal.plot.violin(data=[d1,d2,d1,d2], channel='mCherry-A', yscale='logicle', density=False, num_bins=30, upper_trim_fraction=0, lower_trim_fraction=0)
plt.figure(figsize=figsize)
FlowCal.plot.violin(data=[d1,d2,d1,d2], channel='mCherry-A', yscale='logicle', density=True, num_bins=30, upper_trim_fraction=0, lower_trim_fraction=0)
plt.figure(figsize=figsize)
FlowCal.plot.violin(data=[d1,d2,d1,d2], channel='mCherry-A', yscale='logicle', density=False, num_bins=200, upper_trim_fraction=0, lower_trim_fraction=0)
plt.figure(figsize=figsize)
FlowCal.plot.violin(data=[d1,d2,d1,d2], channel='mCherry-A', yscale='logicle', density=True, num_bins=200, upper_trim_fraction=0, lower_trim_fraction=0)
plt.figure(figsize=figsize)
FlowCal.plot.violin(data=[d1,d2,d1,d2], channel='mCherry-A', yscale='logicle', density=False, bin_edges=np.linspace(-1000,1e4,1000), upper_trim_fraction=0, lower_trim_fraction=0)
plt.figure(figsize=figsize)
FlowCal.plot.violin(data=[d1,d2,d1,d2], channel='mCherry-A', yscale='logicle', density=True, bin_edges=np.linspace(-1000,1e4,1000), upper_trim_fraction=0, lower_trim_fraction=0)
###
# vert
###
figsize=(2.5,3)
plt.figure(figsize=figsize)
FlowCal.plot.violin(data=[d1,d2,d1,d2], channel='GFP-A', xscale='logicle', density=False, num_bins=30, upper_trim_fraction=0, lower_trim_fraction=0, xlim=(-1000,1e5), vert=False)
plt.figure(figsize=figsize)
FlowCal.plot.violin(data=[d1,d2,d1,d2], channel='GFP-A', xscale='logicle', density=True, num_bins=30, upper_trim_fraction=0, lower_trim_fraction=0, xlim=(-1000,1e5), vert=False)
plt.figure(figsize=figsize)
FlowCal.plot.violin(data=[d1,d2,d1,d2], channel='GFP-A', xscale='logicle', density=False, num_bins=200, upper_trim_fraction=0, lower_trim_fraction=0, xlim=(-1000,1e5), vert=False)
plt.figure(figsize=figsize)
FlowCal.plot.violin(data=[d1,d2,d1,d2], channel='GFP-A', xscale='logicle', density=True, num_bins=200, upper_trim_fraction=0, lower_trim_fraction=0, xlim=(-1000,1e5), vert=False)
plt.figure(figsize=figsize)
FlowCal.plot.violin(data=[d1,d2,d1,d2], channel='GFP-A', xscale='logicle', density=False, bin_edges=np.linspace(-1000,1e4,1000), upper_trim_fraction=0, lower_trim_fraction=0, xlim=(-1000,1e5), vert=False)
plt.figure(figsize=figsize)
FlowCal.plot.violin(data=[d1,d2,d1,d2], channel='GFP-A', xscale='logicle', density=True, bin_edges=np.linspace(-1000,1e4,1000), upper_trim_fraction=0, lower_trim_fraction=0, xlim=(-1000,1e5), vert=False)
plt.figure(figsize=figsize)
FlowCal.plot.violin(data=[d1,d2,d1,d2], channel='mCherry-A', xscale='logicle', density=False, num_bins=30, upper_trim_fraction=0, lower_trim_fraction=0, vert=False)
plt.figure(figsize=figsize)
FlowCal.plot.violin(data=[d1,d2,d1,d2], channel='mCherry-A', xscale='logicle', density=True, num_bins=30, upper_trim_fraction=0, lower_trim_fraction=0, vert=False)
plt.figure(figsize=figsize)
FlowCal.plot.violin(data=[d1,d2,d1,d2], channel='mCherry-A', xscale='logicle', density=False, num_bins=200, upper_trim_fraction=0, lower_trim_fraction=0, vert=False)
plt.figure(figsize=figsize)
FlowCal.plot.violin(data=[d1,d2,d1,d2], channel='mCherry-A', xscale='logicle', density=True, num_bins=200, upper_trim_fraction=0, lower_trim_fraction=0, vert=False)
plt.figure(figsize=figsize)
FlowCal.plot.violin(data=[d1,d2,d1,d2], channel='mCherry-A', xscale='logicle', density=False, bin_edges=np.linspace(-1000,1e4,1000), upper_trim_fraction=0, lower_trim_fraction=0, vert=False)
plt.figure(figsize=figsize)
FlowCal.plot.violin(data=[d1,d2,d1,d2], channel='mCherry-A', xscale='logicle', density=True, bin_edges=np.linspace(-1000,1e4,1000), upper_trim_fraction=0, lower_trim_fraction=0, vert=False)
plt.show() I'll leave it up to @castillohair whether to add a horizontal violin plot example to the tutorial. I don't think the example analysis scripts need to be changed. |
yscale=None, | ||
xlim=None, | ||
ylim=None, | ||
vert=True, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There is no docstring for this new parameter.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ooo, good catch. Fixed in 0de9b02.
Instead of a boolean Otherwise, if these are all the changes I can go ahead and update the tutorial. I probably won't add examples of horizontal violins to keep it simple. |
For context, Matplotlib's Seaborn's I chose to conform to Matplotlib (in part because we already do with our |
I see. Following matplotlib's lead seems like a good idea. I'll update the tutorial later todday. |
I had to update way more than I thought because the colormap has changed and most of our documentation images are outdated. I originally had the images on a dropbox folder under my Rice email account. Since I don't have access to it anymore, I can't make changes, so I decided to make the images local to the repo. That will make it easier for anyone continuing this work to keep track of which are being used in which FlowCal version. Here's some screenshots of the new violin section I ended up pushing the violin section towards the end of the plotting tutorial. It feels more like a function to plot datasets (especially if we end with violin_dose_response()), and as such as a more complex function, whereas the others are more geared towards plotting a single sample (hist1d is kind of an exception, but I don't think it's very good for this purpose). Feel free to change things in the new section if you want to. |
Awesome, making images local in the repo is a great improvement. I'm also glad you updated stale images. That's been on my list to check before we release. Some notes on that:
I think the violin plots would also look better with Let me know what you agree with, and I can work on updates. |
I can update the images in Can you update the screenshots in I made up the If you wanna change |
The
Are you just not interested in conforming to Semantic Versioning? I believe there are API-breaking changes (#334, #337, and maybe #340), which would require a MAJOR version bump (i.e., 2.0.0).
Yeah, that seems fine. |
If this is something we have agreed on before, please link the appropriate issue here. But that doesn't look like what most python packages do. We have seen plenty of API-breaking changes on packages that haven't moved from v1.x.x. |
Oh sorry, I thought I had brought this up in the past, perhaps offline, but I can't find any references to it now. Perhaps more important, all these projects rely on robust deprecation policies. They also assume relatively frequent periodic release cycles, which allows them to establish reasonable deprecation timelines (e.g., emit warning for one MINOR release and remove after two MINOR releases). We don't release often, so I don't think this approach works as well for us. Calendar Versioning is another system some use (e.g., Ubuntu and Anaconda). This appears more useful for large projects with many changes and lots of developers that release on consistent timelines, though. I also find Semantic Versioning simple and sensible, so I like it over arbitrarily bumping the MAJOR version number (at present, I'm not sure our MAJOR version number will ever change...). Semantic Versioning would also force us to pay more respect to the public API we present, which we currently change without much concern. We already got off to a bad start, though, as some previous changes didn't bump the MAJOR version number which should have under Semantic Versioning (v1.1.0 being a major example). Whatever versioning policy we adopt, I think we should codify it in our documentation somewhere. |
I fixed the images in the "fundamentals" section of the documentation.
Lol so nobody is actually using it. That matches my observations. The biggest issue I have with semantic versioning (which I would guess a lot of these package maintainers share) is that major version bumps can be given by relatively minor changes (e.g. #337 or #334 are enough to trigger a major version bump), whereas newer functions that are more impactful don't (#335 and #340 constitute "new, backwards compatible functionality ... introduced to the public API", and therefore trigger a minor version bump). That seems backwards. We had already agreed on using the last digit to represent bug fixes that don't change the public API, so the only issue is minor vs. major. I suggest continuing to increase minor version numbers when API changes are relatively minor (e.g. modifying user code after #337 and #334 is trivially easy), and increasing major version numbers when the changes are more fundamental (like the changes we had from 1.0.0 to 1.1.0, which included a FCSData object that behaved significantly differently, or if the Excel UI redesign we talked about ever gets done). This distinction may be subjective, but the end result makes more sense to me that with semantic versioning. Under these, I think the next version number should be 1.3.0. |
I don't agree with this characterization.
Yeah, I can understand how Semantic Versioning might seem counterintuitive from the point of view of the impact of the changes. It is meant to instead communicate whether a new version will break existing user code (at least in theory). This is admittedly a much more user-centric (or package manager-centric) perspective. This can be annoying for developers (who are forced to be more mindful of the public API), but I think it's ultimately better for users.
OK. Can you write a brief description of this versioning policy and put it somewhere? Maybe under the I'll update the |
Version policy was added. If there is nothing more to do here, I will do a final check and merge tomorrow at the latest. |
Awesome, sounds good! |
Oh actually, I've been playing around with using the |
A few thoughts:
|
Yeah, I think you should just go ahead and merge without it. I had forgotten the other I'll respond here if I change my mind later for some reason. |
Additional violin plot test scripts: test_plot_violin.py
import FlowCal
import numpy as np
import matplotlib.pyplot as plt
filenames = ['FCFiles/Data{:03d}.fcs'.format(i) for i in range(1,5+1)]
d = [FlowCal.io.FCSData(filename) for filename in filenames]
d = [FlowCal.transform.to_rfi(di) for di in d]
iptg = [0, 81, 161, 318, 1000]
figsize=(3,2.5)
plt.figure(figsize=figsize)
FlowCal.plot.violin(data=d, channel='FL1', positions=iptg, xlabel='IPTG (uM)')
plt.figure(figsize=figsize)
FlowCal.plot.violin(data=d, channel='FL1', positions=iptg, xlabel='IPTG (uM)', yscale='linear', ylim=(0,4000), bin_edges=np.linspace(0,4000,101), lower_trim_fraction=0)
plt.figure(figsize=figsize)
FlowCal.plot.violin(data=d, channel='FL1', positions=iptg, xlabel='IPTG (uM)', yscale='linear', ylim=(0,4000), bin_edges=np.linspace(0,4000,101), density=True, lower_trim_fraction=0)
plt.figure(figsize=figsize)
FlowCal.plot.violin(data=d, channel='FL1', positions=iptg, xlabel='IPTG (uM)', yscale='linear', ylim=(0,4000), bin_edges=np.logspace(0,4,101), lower_trim_fraction=0)
plt.figure(figsize=figsize)
FlowCal.plot.violin(data=d, channel='FL1', positions=iptg, xlabel='IPTG (uM)', yscale='linear', ylim=(0,4000), bin_edges=np.logspace(0,4,101), density=True, lower_trim_fraction=0)
plt.figure(figsize=figsize)
FlowCal.plot.violin(data=d, channel='FL1', positions=iptg, xlabel='IPTG (uM)', yscale='log', bin_edges=np.linspace(1,4000,201), lower_trim_fraction=0)
plt.figure(figsize=figsize)
FlowCal.plot.violin(data=d, channel='FL1', positions=iptg, xlabel='IPTG (uM)', yscale='log', bin_edges=np.linspace(1,4000,201), density=True, lower_trim_fraction=0)
plt.figure(figsize=figsize)
FlowCal.plot.violin(data=d, channel='FL1', positions=iptg, xlabel='IPTG (uM)', yscale='log', bin_edges=np.logspace(0,4,101), lower_trim_fraction=0)
plt.figure(figsize=figsize)
FlowCal.plot.violin(data=d, channel='FL1', positions=iptg, xlabel='IPTG (uM)', yscale='log', bin_edges=np.logspace(0,4,101), density=True, lower_trim_fraction=0)
plt.figure(figsize=figsize)
FlowCal.plot.violin(data=d, channel='FL1', positions=iptg, xlabel='IPTG (uM)', xscale='log')
plt.figure(figsize=figsize)
FlowCal.plot.violin(data=d[1:], channel='FL1', positions=iptg[1:], xlabel='IPTG (uM)', xscale='log')
plt.figure(figsize=figsize)
FlowCal.plot.violin(
data=d,
channel='FL1',
positions=iptg,
xlabel='IPTG (uM)',
xscale='log',
violin_width=0.5,
ylim=(1e0,1e4),
xlim=(1e1,1e4),
num_bins=30)
plt.figure(figsize=figsize)
FlowCal.plot.violin(
data=d,
channel='FL1',
positions=iptg,
xlabel='IPTG (uM)',
xscale='log',
violin_width=0.5,
ylim=(1e0,1e4),
xlim=(1e1,1e4),
bin_edges=np.logspace(0,4,30))
plt.figure(figsize=figsize)
FlowCal.plot.violin(
data=d,
channel='FL1',
positions=iptg,
xlabel='IPTG (uM)',
xscale='log',
violin_width=0.5,
ylim=(1e0,1e4),
xlim=(1e1,1e4),
bin_edges=np.logspace(0,4,30),
upper_trim_fraction=0.1,
lower_trim_fraction=0.05)
plt.figure(figsize=figsize)
FlowCal.plot.violin(
data=d,
channel='FL1',
positions=iptg,
xlabel='IPTG (uM)',
xscale='log',
violin_width_to_span_fraction=0.025,
ylim=(1e0,1e4),
xlim=(1e1,1e4),
bin_edges=np.logspace(0,4,30),
upper_trim_fraction=0.1,
lower_trim_fraction=0.05)
plt.figure(figsize=figsize)
FlowCal.plot.violin(
data=d,
channel='FL1',
positions=iptg,
xlabel='IPTG (uM)',
xscale='log',
violin_width=0.5,
ylim=(1e0,1e4),
xlim=(1e1,1e4),
bin_edges=np.logspace(0,4,30),
upper_trim_fraction=0.1,
lower_trim_fraction=0.05,
violin_kwargs={'facecolor':'red', 'edgecolor':'blue'})
plt.figure(figsize=figsize)
FlowCal.plot.violin(
data=d,
channel='FL1',
positions=iptg,
xlabel='IPTG (uM)',
xscale='log',
violin_width=0.5,
ylim=(1e0,1e4),
xlim=(1e1,1e4),
bin_edges=np.logspace(0,4,30),
upper_trim_fraction=0.1,
lower_trim_fraction=0.05,
violin_kwargs={'facecolor':'red', 'edgecolor':'blue'},
draw_summary_stat=False)
plt.figure(figsize=figsize)
FlowCal.plot.violin(
data=d,
channel='FL1',
positions=iptg,
xlabel='IPTG (uM)',
xscale='log',
violin_width=0.5,
ylim=(1e0,1e4),
xlim=(1e1,1e4),
bin_edges=np.logspace(0,4,30),
upper_trim_fraction=0.1,
lower_trim_fraction=0.05,
violin_kwargs={'facecolor':'red', 'edgecolor':'blue'},
draw_summary_stat_fxn=np.median,
draw_summary_stat_kwargs={'color':'green'})
plt.figure(figsize=figsize)
FlowCal.plot.violin(
data=d,
channel='FL1',
positions=iptg,
xlabel='IPTG (uM)',
xscale='log',
violin_width=0.5,
ylim=(1e0,1e4),
xlim=(1e1,1e4),
bin_edges=np.logspace(0,4,30),
upper_trim_fraction=0.1,
lower_trim_fraction=0.05,
violin_kwargs={'facecolor':'red', 'edgecolor':'blue'},
draw_summary_stat_fxn=np.median,
draw_summary_stat_kwargs={'color':'green'},
log_zero_tick_label='test')
plt.figure(figsize=figsize)
FlowCal.plot.violin(
data=d,
channel='FL1',
positions=iptg,
xlabel='IPTG (uM)',
xscale='log',
violin_width=0.5,
ylim=(1e0,1e4),
xlim=(1e1,1e4),
bin_edges=np.logspace(0,4,30),
upper_trim_fraction=0.1,
lower_trim_fraction=0.05,
violin_kwargs={'facecolor':'red', 'edgecolor':'blue'},
draw_summary_stat_fxn=np.median,
draw_summary_stat_kwargs={'color':'green'},
log_zero_tick_label='test',
draw_log_zero_divider_kwargs={'color':'purple'})
plt.figure(figsize=figsize)
FlowCal.plot.violin(
data=d,
channel='FL1',
positions=iptg,
xlabel='IPTG (uM)',
xscale='log',
violin_width=0.5,
ylim=(1e0,1e4),
xlim=(1e1,1e4),
bin_edges=[np.logspace(0,4,30),
np.logspace(0,4,200),
np.logspace(0,4,20),
np.logspace(0,4,200),
np.logspace(0,4,30)],
upper_trim_fraction=[0.1, 0.25, 0.01, 0.1, 0.01],
lower_trim_fraction=[0.25, 0.01, 0.1, 0.05, 0.1],
violin_kwargs=[{'facecolor':'red', 'edgecolor':'purple'},
{'facecolor':'orange', 'edgecolor':'blue'},
{'facecolor':'yellow', 'edgecolor':'green'},
{'facecolor':'green', 'edgecolor':'yellow'},
{'facecolor':'blue', 'edgecolor':'orange'}],
draw_summary_stat_fxn=np.median,
draw_summary_stat_kwargs=[{'color':'blue'},
{'color':'black'},
{'color':'red'},
{'color':'blue'},
{'color':'white'},],
log_zero_tick_label='test',
draw_log_zero_divider_kwargs={'color':'purple'})
plt.show() test_plot_violin_vert.py
import FlowCal
import numpy as np
import matplotlib.pyplot as plt
filenames = ['FCFiles/Data{:03d}.fcs'.format(i) for i in range(1,5+1)]
d = [FlowCal.io.FCSData(filename) for filename in filenames]
d = [FlowCal.transform.to_rfi(di) for di in d]
iptg = [0, 81, 161, 318, 1000]
###
# vert
###
figsize=(3,3)
plt.figure(figsize=figsize)
FlowCal.plot.violin(data=d, channel='FL1', positions=iptg, ylabel='IPTG (uM)', vert=False)
plt.figure(figsize=figsize)
FlowCal.plot.violin(data=d, channel='FL1', positions=iptg, ylabel='IPTG (uM)', xscale='linear', xlim=(0,4000), bin_edges=np.linspace(0,4000,101), lower_trim_fraction=0, vert=False)
plt.figure(figsize=figsize)
FlowCal.plot.violin(data=d, channel='FL1', positions=iptg, ylabel='IPTG (uM)', xscale='linear', xlim=(0,4000), bin_edges=np.linspace(0,4000,101), density=True, lower_trim_fraction=0, vert=False)
plt.figure(figsize=figsize)
FlowCal.plot.violin(data=d, channel='FL1', positions=iptg, ylabel='IPTG (uM)', xscale='linear', xlim=(0,4000), bin_edges=np.logspace(0,4,101), lower_trim_fraction=0, vert=False)
plt.figure(figsize=figsize)
FlowCal.plot.violin(data=d, channel='FL1', positions=iptg, ylabel='IPTG (uM)', xscale='linear', xlim=(0,4000), bin_edges=np.logspace(0,4,101), density=True, lower_trim_fraction=0, vert=False)
plt.figure(figsize=figsize)
FlowCal.plot.violin(data=d, channel='FL1', positions=iptg, ylabel='IPTG (uM)', xscale='log', bin_edges=np.linspace(1,4000,201), lower_trim_fraction=0, vert=False)
plt.figure(figsize=figsize)
FlowCal.plot.violin(data=d, channel='FL1', positions=iptg, ylabel='IPTG (uM)', xscale='log', bin_edges=np.linspace(1,4000,201), density=True, lower_trim_fraction=0, vert=False)
plt.figure(figsize=figsize)
FlowCal.plot.violin(data=d, channel='FL1', positions=iptg, ylabel='IPTG (uM)', xscale='log', bin_edges=np.logspace(0,4,101), lower_trim_fraction=0, vert=False)
plt.figure(figsize=figsize)
FlowCal.plot.violin(data=d, channel='FL1', positions=iptg, ylabel='IPTG (uM)', xscale='log', bin_edges=np.logspace(0,4,101), density=True, lower_trim_fraction=0, vert=False)
plt.figure(figsize=figsize)
FlowCal.plot.violin(data=d, channel='FL1', positions=iptg, ylabel='IPTG (uM)', yscale='log', vert=False)
plt.figure(figsize=figsize)
FlowCal.plot.violin(data=d[1:], channel='FL1', positions=iptg[1:], ylabel='IPTG (uM)', yscale='log', vert=False)
plt.figure(figsize=figsize)
FlowCal.plot.violin(
data=d,
channel='FL1',
positions=iptg,
ylabel='IPTG (uM)',
yscale='log',
violin_width=0.5,
xlim=(1e0,1e4),
ylim=(1e1,1e4),
num_bins=30,
vert=False)
plt.figure(figsize=figsize)
FlowCal.plot.violin(
data=d,
channel='FL1',
positions=iptg,
ylabel='IPTG (uM)',
yscale='log',
violin_width=0.5,
xlim=(1e0,1e4),
ylim=(1e1,1e4),
bin_edges=np.logspace(0,4,30),
vert=False)
plt.figure(figsize=figsize)
FlowCal.plot.violin(
data=d,
channel='FL1',
positions=iptg,
ylabel='IPTG (uM)',
yscale='log',
violin_width=0.5,
xlim=(1e0,1e4),
ylim=(1e1,1e4),
bin_edges=np.logspace(0,4,30),
upper_trim_fraction=0.1,
lower_trim_fraction=0.05,
vert=False)
plt.figure(figsize=figsize)
FlowCal.plot.violin(
data=d,
channel='FL1',
positions=iptg,
ylabel='IPTG (uM)',
yscale='log',
violin_width_to_span_fraction=0.025,
xlim=(1e0,1e4),
ylim=(1e1,1e4),
bin_edges=np.logspace(0,4,30),
upper_trim_fraction=0.1,
lower_trim_fraction=0.05,
vert=False)
plt.figure(figsize=figsize)
FlowCal.plot.violin(
data=d,
channel='FL1',
positions=iptg,
ylabel='IPTG (uM)',
yscale='log',
violin_width=0.5,
xlim=(1e0,1e4),
ylim=(1e1,1e4),
bin_edges=np.logspace(0,4,30),
upper_trim_fraction=0.1,
lower_trim_fraction=0.05,
violin_kwargs={'facecolor':'red', 'edgecolor':'blue'},
vert=False)
plt.figure(figsize=figsize)
FlowCal.plot.violin(
data=d,
channel='FL1',
positions=iptg,
ylabel='IPTG (uM)',
yscale='log',
violin_width=0.5,
xlim=(1e0,1e4),
ylim=(1e1,1e4),
bin_edges=np.logspace(0,4,30),
upper_trim_fraction=0.1,
lower_trim_fraction=0.05,
violin_kwargs={'facecolor':'red', 'edgecolor':'blue'},
draw_summary_stat=False,
vert=False)
plt.figure(figsize=figsize)
FlowCal.plot.violin(
data=d,
channel='FL1',
positions=iptg,
ylabel='IPTG (uM)',
yscale='log',
violin_width=0.5,
xlim=(1e0,1e4),
ylim=(1e1,1e4),
bin_edges=np.logspace(0,4,30),
upper_trim_fraction=0.1,
lower_trim_fraction=0.05,
violin_kwargs={'facecolor':'red', 'edgecolor':'blue'},
draw_summary_stat_fxn=np.median,
draw_summary_stat_kwargs={'color':'green'},
vert=False)
plt.figure(figsize=figsize)
FlowCal.plot.violin(
data=d,
channel='FL1',
positions=iptg,
ylabel='IPTG (uM)',
yscale='log',
violin_width=0.5,
xlim=(1e0,1e4),
ylim=(1e1,1e4),
bin_edges=np.logspace(0,4,30),
upper_trim_fraction=0.1,
lower_trim_fraction=0.05,
violin_kwargs={'facecolor':'red', 'edgecolor':'blue'},
draw_summary_stat_fxn=np.median,
draw_summary_stat_kwargs={'color':'green'},
log_zero_tick_label='test',
vert=False)
plt.figure(figsize=figsize)
FlowCal.plot.violin(
data=d,
channel='FL1',
positions=iptg,
ylabel='IPTG (uM)',
yscale='log',
violin_width=0.5,
xlim=(1e0,1e4),
ylim=(1e1,1e4),
bin_edges=np.logspace(0,4,30),
upper_trim_fraction=0.1,
lower_trim_fraction=0.05,
violin_kwargs={'facecolor':'red', 'edgecolor':'blue'},
draw_summary_stat_fxn=np.median,
draw_summary_stat_kwargs={'color':'green'},
log_zero_tick_label='test',
draw_log_zero_divider_kwargs={'color':'purple'},
vert=False)
plt.figure(figsize=figsize)
FlowCal.plot.violin(
data=d,
channel='FL1',
positions=iptg,
ylabel='IPTG (uM)',
yscale='log',
violin_width=0.5,
xlim=(1e0,1e4),
ylim=(1e1,1e4),
bin_edges=[np.logspace(0,4,30),
np.logspace(0,4,200),
np.logspace(0,4,20),
np.logspace(0,4,200),
np.logspace(0,4,30)],
upper_trim_fraction=[0.1, 0.25, 0.01, 0.1, 0.01],
lower_trim_fraction=[0.25, 0.01, 0.1, 0.05, 0.1],
violin_kwargs=[{'facecolor':'red', 'edgecolor':'purple'},
{'facecolor':'orange', 'edgecolor':'blue'},
{'facecolor':'yellow', 'edgecolor':'green'},
{'facecolor':'green', 'edgecolor':'yellow'},
{'facecolor':'blue', 'edgecolor':'orange'}],
draw_summary_stat_fxn=np.median,
draw_summary_stat_kwargs=[{'color':'blue'},
{'color':'black'},
{'color':'red'},
{'color':'blue'},
{'color':'white'},],
log_zero_tick_label='test',
draw_log_zero_divider_kwargs={'color':'purple'},
vert=False)
plt.show() test_plot_violin_dose_response.py
import FlowCal
import numpy as np
import matplotlib.pyplot as plt
filenames = ['FCFiles/Data{:03d}.fcs'.format(i) for i in range(1,5+1)]
d = [FlowCal.io.FCSData(filename) for filename in filenames]
d = [FlowCal.transform.to_rfi(di) for di in d]
iptg = [0, 81, 161, 318, 1000]
figsize=(3,2.5)
plt.figure(figsize=figsize)
FlowCal.plot.violin_dose_response(data=d, channel='FL1', positions=iptg, xlabel='IPTG (uM)')
plt.figure(figsize=figsize)
FlowCal.plot.violin_dose_response(data=d, channel='FL1', positions=iptg, xlabel='IPTG (uM)', yscale='linear', ylim=(0,4000), bin_edges=np.linspace(0,4000,101), lower_trim_fraction=0)
plt.figure(figsize=figsize)
FlowCal.plot.violin_dose_response(data=d, channel='FL1', positions=iptg, xlabel='IPTG (uM)', yscale='linear', ylim=(0,4000), bin_edges=np.linspace(0,4000,101), density=True, lower_trim_fraction=0)
plt.figure(figsize=figsize)
FlowCal.plot.violin_dose_response(data=d, channel='FL1', positions=iptg, xlabel='IPTG (uM)', yscale='linear', ylim=(0,4000), bin_edges=np.logspace(0,4,101), lower_trim_fraction=0)
plt.figure(figsize=figsize)
FlowCal.plot.violin_dose_response(data=d, channel='FL1', positions=iptg, xlabel='IPTG (uM)', yscale='linear', ylim=(0,4000), bin_edges=np.logspace(0,4,101), density=True, lower_trim_fraction=0)
plt.figure(figsize=figsize)
FlowCal.plot.violin_dose_response(data=d, channel='FL1', positions=iptg, xlabel='IPTG (uM)', yscale='log', bin_edges=np.linspace(1,4000,201), lower_trim_fraction=0)
plt.figure(figsize=figsize)
FlowCal.plot.violin_dose_response(data=d, channel='FL1', positions=iptg, xlabel='IPTG (uM)', yscale='log', bin_edges=np.linspace(1,4000,201), density=True, lower_trim_fraction=0)
plt.figure(figsize=figsize)
FlowCal.plot.violin_dose_response(data=d, channel='FL1', positions=iptg, xlabel='IPTG (uM)', yscale='log', bin_edges=np.logspace(0,4,101), lower_trim_fraction=0)
plt.figure(figsize=figsize)
FlowCal.plot.violin_dose_response(data=d, channel='FL1', positions=iptg, xlabel='IPTG (uM)', yscale='log', bin_edges=np.logspace(0,4,101), density=True, lower_trim_fraction=0)
plt.figure(figsize=figsize)
FlowCal.plot.violin_dose_response(data=d, channel='FL1', positions=iptg, xlabel='IPTG (uM)', xscale='log')
plt.figure(figsize=figsize)
FlowCal.plot.violin_dose_response(data=d[1:], channel='FL1', positions=iptg[1:], xlabel='IPTG (uM)', xscale='log')
plt.figure(figsize=figsize)
FlowCal.plot.violin_dose_response(
data=d,
channel='FL1',
positions=iptg,
xlabel='IPTG (uM)',
xscale='log',
violin_width=0.5,
ylim=(1e0,1e4),
xlim=(1e1,1e4),
num_bins=30)
plt.figure(figsize=figsize)
FlowCal.plot.violin_dose_response(
data=d,
channel='FL1',
positions=iptg,
xlabel='IPTG (uM)',
xscale='log',
violin_width=0.5,
ylim=(1e0,1e4),
xlim=(1e1,1e4),
bin_edges=np.logspace(0,4,30))
plt.figure(figsize=figsize)
FlowCal.plot.violin_dose_response(
data=d,
channel='FL1',
positions=iptg,
xlabel='IPTG (uM)',
xscale='log',
violin_width=0.5,
ylim=(1e0,1e4),
xlim=(1e1,1e4),
bin_edges=np.logspace(0,4,30),
upper_trim_fraction=0.1,
lower_trim_fraction=0.05)
plt.figure(figsize=figsize)
FlowCal.plot.violin_dose_response(
data=d,
channel='FL1',
positions=iptg,
xlabel='IPTG (uM)',
xscale='log',
violin_width_to_span_fraction=0.025,
ylim=(1e0,1e4),
xlim=(1e1,1e4),
bin_edges=np.logspace(0,4,30),
upper_trim_fraction=0.1,
lower_trim_fraction=0.05)
plt.figure(figsize=figsize)
FlowCal.plot.violin_dose_response(
data=d,
channel='FL1',
positions=iptg,
xlabel='IPTG (uM)',
xscale='log',
violin_width=0.5,
ylim=(1e0,1e4),
xlim=(1e1,1e4),
bin_edges=np.logspace(0,4,30),
upper_trim_fraction=0.1,
lower_trim_fraction=0.05,
violin_kwargs={'facecolor':'red', 'edgecolor':'blue'})
plt.figure(figsize=figsize)
FlowCal.plot.violin_dose_response(
data=d,
channel='FL1',
positions=iptg,
xlabel='IPTG (uM)',
xscale='log',
violin_width=0.5,
ylim=(1e0,1e4),
xlim=(1e1,1e4),
bin_edges=np.logspace(0,4,30),
upper_trim_fraction=0.1,
lower_trim_fraction=0.05,
violin_kwargs={'facecolor':'red', 'edgecolor':'blue'},
draw_summary_stat=False)
plt.figure(figsize=figsize)
FlowCal.plot.violin_dose_response(
data=d,
channel='FL1',
positions=iptg,
xlabel='IPTG (uM)',
xscale='log',
violin_width=0.5,
ylim=(1e0,1e4),
xlim=(1e1,1e4),
bin_edges=np.logspace(0,4,30),
upper_trim_fraction=0.1,
lower_trim_fraction=0.05,
violin_kwargs={'facecolor':'red', 'edgecolor':'blue'},
draw_summary_stat_fxn=np.median,
draw_summary_stat_kwargs={'color':'green'})
plt.figure(figsize=figsize)
FlowCal.plot.violin_dose_response(
data=d,
channel='FL1',
positions=iptg,
xlabel='IPTG (uM)',
xscale='log',
violin_width=0.5,
ylim=(1e0,1e4),
xlim=(1e1,1e4),
bin_edges=np.logspace(0,4,30),
upper_trim_fraction=0.1,
lower_trim_fraction=0.05,
violin_kwargs={'facecolor':'red', 'edgecolor':'blue'},
draw_summary_stat_fxn=np.median,
draw_summary_stat_kwargs={'color':'green'},
log_zero_tick_label='test')
plt.figure(figsize=figsize)
FlowCal.plot.violin_dose_response(
data=d,
channel='FL1',
positions=iptg,
xlabel='IPTG (uM)',
xscale='log',
violin_width=0.5,
ylim=(1e0,1e4),
xlim=(1e1,1e4),
bin_edges=np.logspace(0,4,30),
upper_trim_fraction=0.1,
lower_trim_fraction=0.05,
violin_kwargs={'facecolor':'red', 'edgecolor':'blue'},
draw_summary_stat_fxn=np.median,
draw_summary_stat_kwargs={'color':'green'},
log_zero_tick_label='test',
draw_log_zero_divider_kwargs={'color':'purple'})
plt.figure(figsize=figsize)
FlowCal.plot.violin_dose_response(
data=d,
channel='FL1',
positions=iptg,
xlabel='IPTG (uM)',
xscale='log',
violin_width=0.5,
ylim=(1e0,1e4),
xlim=(1e1,1e4),
bin_edges=[np.logspace(0,4,30),
np.logspace(0,4,200),
np.logspace(0,4,20),
np.logspace(0,4,200),
np.logspace(0,4,30)],
upper_trim_fraction=[0.1, 0.25, 0.01, 0.1, 0.01],
lower_trim_fraction=[0.25, 0.01, 0.1, 0.05, 0.1],
violin_kwargs=[{'facecolor':'red', 'edgecolor':'purple'},
{'facecolor':'orange', 'edgecolor':'blue'},
{'facecolor':'yellow', 'edgecolor':'green'},
{'facecolor':'green', 'edgecolor':'yellow'},
{'facecolor':'blue', 'edgecolor':'orange'}],
draw_summary_stat_fxn=np.median,
draw_summary_stat_kwargs=[{'color':'blue'},
{'color':'black'},
{'color':'red'},
{'color':'blue'},
{'color':'white'},],
log_zero_tick_label='test',
draw_log_zero_divider_kwargs={'color':'purple'})
def iptg_hill_model(iptg_concentration):
mn = 20.
mx = 1700.
K = 300.
n = 1.5
if iptg_concentration <= 0:
return mn
else:
return mn + ((mx-mn)/(1+((K/iptg_concentration)**n)))
plt.figure(figsize=figsize)
FlowCal.plot.violin_dose_response(
data=d,
model_fxn=iptg_hill_model,
channel='FL1',
positions=iptg,
xlabel='IPTG (uM)',
xscale='log',
violin_width=0.5,
ylim=(1e0,1e4),
xlim=(1e1,1e4),
bin_edges=[np.logspace(0,4,30),
np.logspace(0,4,200),
np.logspace(0,4,20),
np.logspace(0,4,200),
np.logspace(0,4,30)],
upper_trim_fraction=[0.1, 0.25, 0.01, 0.1, 0.01],
lower_trim_fraction=[0.25, 0.01, 0.1, 0.05, 0.1],
violin_kwargs=[{'facecolor':'red', 'edgecolor':'purple'},
{'facecolor':'orange', 'edgecolor':'blue'},
{'facecolor':'yellow', 'edgecolor':'green'},
{'facecolor':'green', 'edgecolor':'yellow'},
{'facecolor':'blue', 'edgecolor':'orange'}],
draw_summary_stat_fxn=np.median,
draw_summary_stat_kwargs=[{'color':'blue'},
{'color':'black'},
{'color':'red'},
{'color':'blue'},
{'color':'white'},],
min_tick_label='jing',
max_tick_label='gle',
log_zero_tick_label='bells',
draw_log_zero_divider_kwargs={'color':'purple'},
min_bin_edges=np.logspace(0,4,200),
max_bin_edges=np.logspace(0,4,20),
min_upper_trim_fraction=0.2,
min_lower_trim_fraction=0,
max_upper_trim_fraction=0,
max_lower_trim_fraction=0.1,
min_violin_kwargs={'facecolor':'green', 'edgecolor':'purple'},
max_violin_kwargs={'facecolor':'blue', 'edgecolor':'orange'},
min_draw_summary_stat_kwargs={'color':'black'},
max_draw_summary_stat_kwargs={'color':'white'},
draw_min_line_kwargs={'color':'green'},
draw_max_line_kwargs={'color':'blue'},
draw_model_kwargs={'color':'red','linestyle':':'},
draw_minmax_divider_kwargs={'color':'blue','linestyle':'--'})
plt.figure(figsize=figsize)
FlowCal.plot.violin_dose_response(
data=d,
min_data=d[0],
model_fxn=iptg_hill_model,
channel='FL1',
positions=iptg,
xlabel='IPTG (uM)',
xscale='log',
violin_width=0.5,
ylim=(1e0,1e4),
xlim=(1e1,1e4),
bin_edges=[np.logspace(0,4,30),
np.logspace(0,4,200),
np.logspace(0,4,20),
np.logspace(0,4,200),
np.logspace(0,4,30)],
upper_trim_fraction=[0.1, 0.25, 0.01, 0.1, 0.01],
lower_trim_fraction=[0.25, 0.01, 0.1, 0.05, 0.1],
violin_kwargs=[{'facecolor':'red', 'edgecolor':'purple'},
{'facecolor':'orange', 'edgecolor':'blue'},
{'facecolor':'yellow', 'edgecolor':'green'},
{'facecolor':'green', 'edgecolor':'yellow'},
{'facecolor':'blue', 'edgecolor':'orange'}],
draw_summary_stat_fxn=np.median,
draw_summary_stat_kwargs=[{'color':'blue'},
{'color':'black'},
{'color':'red'},
{'color':'blue'},
{'color':'white'},],
min_tick_label='jing',
max_tick_label='gle',
log_zero_tick_label='bells',
draw_log_zero_divider_kwargs={'color':'purple'},
min_bin_edges=np.logspace(0,4,200),
max_bin_edges=np.logspace(0,4,20),
min_upper_trim_fraction=0.2,
min_lower_trim_fraction=0,
max_upper_trim_fraction=0,
max_lower_trim_fraction=0.1,
min_violin_kwargs={'facecolor':'green', 'edgecolor':'purple'},
max_violin_kwargs={'facecolor':'blue', 'edgecolor':'orange'},
min_draw_summary_stat_kwargs={'color':'black'},
max_draw_summary_stat_kwargs={'color':'white'},
draw_min_line_kwargs={'color':'green'},
draw_max_line_kwargs={'color':'blue'},
draw_model_kwargs={'color':'red','linestyle':':'},
draw_minmax_divider_kwargs={'color':'blue','linestyle':'--'})
plt.figure(figsize=figsize)
FlowCal.plot.violin_dose_response(
data=d,
max_data=d[-1],
model_fxn=iptg_hill_model,
channel='FL1',
positions=iptg,
xlabel='IPTG (uM)',
xscale='log',
violin_width=0.5,
ylim=(1e0,1e4),
xlim=(1e1,1e4),
bin_edges=[np.logspace(0,4,30),
np.logspace(0,4,200),
np.logspace(0,4,20),
np.logspace(0,4,200),
np.logspace(0,4,30)],
upper_trim_fraction=[0.1, 0.25, 0.01, 0.1, 0.01],
lower_trim_fraction=[0.25, 0.01, 0.1, 0.05, 0.1],
violin_kwargs=[{'facecolor':'red', 'edgecolor':'purple'},
{'facecolor':'orange', 'edgecolor':'blue'},
{'facecolor':'yellow', 'edgecolor':'green'},
{'facecolor':'green', 'edgecolor':'yellow'},
{'facecolor':'blue', 'edgecolor':'orange'}],
draw_summary_stat_fxn=np.median,
draw_summary_stat_kwargs=[{'color':'blue'},
{'color':'black'},
{'color':'red'},
{'color':'blue'},
{'color':'white'},],
min_tick_label='jing',
max_tick_label='gle',
log_zero_tick_label='bells',
draw_log_zero_divider_kwargs={'color':'purple'},
min_bin_edges=np.logspace(0,4,200),
max_bin_edges=np.logspace(0,4,20),
min_upper_trim_fraction=0.2,
min_lower_trim_fraction=0,
max_upper_trim_fraction=0,
max_lower_trim_fraction=0.1,
min_violin_kwargs={'facecolor':'green', 'edgecolor':'purple'},
max_violin_kwargs={'facecolor':'blue', 'edgecolor':'orange'},
min_draw_summary_stat_kwargs={'color':'black'},
max_draw_summary_stat_kwargs={'color':'white'},
draw_min_line_kwargs={'color':'green'},
draw_max_line_kwargs={'color':'blue'},
draw_model_kwargs={'color':'red','linestyle':':'},
draw_minmax_divider_kwargs={'color':'blue','linestyle':'--'})
plt.figure(figsize=figsize)
FlowCal.plot.violin_dose_response(
data=d,
min_data=d[0],
max_data=d[-1],
model_fxn=iptg_hill_model,
channel='FL1',
positions=iptg,
xlabel='IPTG (uM)',
xscale='log',
violin_width=0.5,
ylim=(1e0,1e4),
xlim=(1e1,1e4),
bin_edges=[np.logspace(0,4,30),
np.logspace(0,4,200),
np.logspace(0,4,20),
np.logspace(0,4,200),
np.logspace(0,4,30)],
upper_trim_fraction=[0.1, 0.25, 0.01, 0.1, 0.01],
lower_trim_fraction=[0.25, 0.01, 0.1, 0.05, 0.1],
violin_kwargs=[{'facecolor':'red', 'edgecolor':'purple'},
{'facecolor':'orange', 'edgecolor':'blue'},
{'facecolor':'yellow', 'edgecolor':'green'},
{'facecolor':'green', 'edgecolor':'yellow'},
{'facecolor':'blue', 'edgecolor':'orange'}],
draw_summary_stat_fxn=np.median,
draw_summary_stat_kwargs=[{'color':'blue'},
{'color':'black'},
{'color':'red'},
{'color':'blue'},
{'color':'white'},],
min_tick_label='jing',
max_tick_label='gle',
log_zero_tick_label='bells',
draw_log_zero_divider_kwargs={'color':'purple'},
min_bin_edges=np.logspace(0,4,200),
max_bin_edges=np.logspace(0,4,20),
min_upper_trim_fraction=0.2,
min_lower_trim_fraction=0,
max_upper_trim_fraction=0,
max_lower_trim_fraction=0.1,
min_violin_kwargs={'facecolor':'green', 'edgecolor':'purple'},
max_violin_kwargs={'facecolor':'blue', 'edgecolor':'orange'},
min_draw_summary_stat_kwargs={'color':'black'},
max_draw_summary_stat_kwargs={'color':'white'},
draw_min_line_kwargs={'color':'green'},
draw_max_line_kwargs={'color':'blue'},
draw_model_kwargs={'color':'red','linestyle':':'},
draw_minmax_divider_kwargs={'color':'blue','linestyle':'--'})
plt.figure(figsize=figsize)
FlowCal.plot.violin_dose_response(
data=d,
min_data=d[0],
max_data=d[-1],
model_fxn=iptg_hill_model,
channel='FL1',
positions=iptg,
xlabel='IPTG (uM)',
xscale='log',
violin_width=0.5,
ylim=(1e0,1e4),
xlim=(1e1,1e4),
bin_edges=[np.logspace(0,4,30),
np.logspace(0,4,200),
np.logspace(0,4,20),
np.logspace(0,4,200),
np.logspace(0,4,30)],
upper_trim_fraction=[0.1, 0.25, 0.01, 0.1, 0.01],
lower_trim_fraction=[0.25, 0.01, 0.1, 0.05, 0.1],
violin_kwargs=[{'facecolor':'red', 'edgecolor':'purple'},
{'facecolor':'orange', 'edgecolor':'blue'},
{'facecolor':'yellow', 'edgecolor':'green'},
{'facecolor':'green', 'edgecolor':'yellow'},
{'facecolor':'blue', 'edgecolor':'orange'}],
draw_summary_stat_fxn=np.median,
draw_summary_stat_kwargs=[{'color':'blue'},
{'color':'black'},
{'color':'red'},
{'color':'blue'},
{'color':'white'},],
min_tick_label='jing',
max_tick_label='gle',
log_zero_tick_label='bells',
draw_log_zero_divider_kwargs={'color':'purple'},
min_bin_edges=np.logspace(0,4,200),
max_bin_edges=np.logspace(0,4,20),
min_upper_trim_fraction=0.2,
min_lower_trim_fraction=0,
max_upper_trim_fraction=0,
max_lower_trim_fraction=0.1,
min_violin_kwargs={'facecolor':'green', 'edgecolor':'purple'},
max_violin_kwargs={'facecolor':'blue', 'edgecolor':'orange'},
min_draw_summary_stat_kwargs={'color':'black'},
max_draw_summary_stat_kwargs={'color':'white'},
draw_min_line_kwargs={'color':'green'},
draw_max_line_kwargs={'color':'blue'},
draw_model_kwargs={'color':'red','linestyle':':'},
draw_minmax_divider_kwargs={'color':'blue','linestyle':'--'},
density=True)
plt.show() These tests require the |
Add
plot.violin()
, which easily and flexibly illustrates violin plots from flow cytometry data.Closes #332.
Still TODO: create tutorial images and update image links in
/doc/python_tutorial/plot.rst
.Wishlist:
density
parameter? (likenormed_area
parameter ofplot.hist1d
)pd.Series
andpd.Dataframe
inputs? (probably better left to Add support for pandas DataFrames #76)Testing:
In both
Python 3.8 + Anaconda 2020.02
andPython 2.7 + Anaconda 4.4.0
:analyze_no_mef.py
,analyze_mef.py
, andanalyze_excel_ui.py
in/examples
)./doc/python_tutorial/plot.rst
).Thoughts on some failure modes:
Supporting the
channel
parameter, which allplot
functions offer, was a bit tricky given how flexible my original code was to different inputs. Ifplot.violin()
is used correctly, it works as described. There are some potentially common failure modes, though:plot.violin(fcs_data)
(withoutchannel
) will attempt to plot each row offcs_data
as a violin. This happens becauseplot.violin()
understandsfcs_data
to be a sequence of 1D sequences (which it technically is). This can be bad forfcs_data
with many rows.plot.violin([fcs_data1,fcs_data2,fcs_data3])
(again withoutchannel
) will concatenate all channels for eachfcs_data
and attempt to plot them, which usually fails trying to calculatelog(0)
. This happens because the input is understood to be a sequence of 1D arrays, and each 1D array is iterated over using the.flat
numpy iterator feature.I chose not to address these failure modes, but I still wanted to point them out.