For a simple install using the release version of mpld3 you can either install from the Python Package Index (PyPI)
pip3 install survivalvolume
or from the github repository
pip3 install git+https://github.com/genomematt/survivalvolume.git
To run the tests use
python3 -m survivalvolume.tests.test_all
It is also recommended to run the user_guide.ipynb file and visually compare it to the html version
In [1]:
from survivalvolume.parse import studylog_prism_to_tv_tables
tvts = studylog_prism_to_tv_tables('survivalvolume/tests/data/Studylogish.xlsx')
In [2]:
tvts['Treat']
Out[2]:
In [3]:
import pandas
import pathlib
p = pathlib.Path('survivalvolume/tests/data').glob('*.tsv')
parsed_data = {filename.stem:pandas.read_table(filename.as_posix(), sep='\t',index_col=0) for filename in p}
parsed_data['good_treatment']
Out[3]:
If you have parsed data from a clumsy or proprietary format you may wish to export your data to tab separated value files as a clean and future proof backup option
In [4]:
from survivalvolume.tests.test_data import test_data
def save_dict_of_dataframes(dodf, dir_name='.'):
for key in dodf:
dodf[key].to_csv('{0}/{1}.tsv'.format(dir_name,key),sep='\t')
pass
save_dict_of_dataframes(test_data, 'survivalvolume/tests/data')
In [5]:
from survivalvolume.tests.test_data import test_data
test_data['vehicle']
Out[5]:
In [6]:
test_data['vehicle'].to_csv()
Out[6]:
Biweekly measurement can sometimes result in inconsistent data due to the alternating offset of days. There is a convenience function in survivalvolume.parse standardise_days that allows easy renumbering to an alternating pattern
In [7]:
from survivalvolume.parse import standardise_days
standardise_days(test_data['vehicle'])
Out[7]:
In [8]:
help(standardise_days)
In [9]:
standardise_days(test_data['vehicle'],first_interval=4,second_interval=3)
Out[9]:
In [10]:
# Tell the drawing package we want to see the output in the notebook
import matplotlib
%matplotlib inline
# Lots of warnings are being generated which gets a bit distracting so we will turn them off
import warnings
warnings.filterwarnings('ignore')
In [11]:
from survivalvolume.tests.test_data import test_data
test_data['vehicle']
Out[11]:
Our line plots are based around a TumourVolumePlot object that we will progressively update with data and plotting instructions
In [12]:
from survivalvolume.plot import TumourVolumePlot
tvp = TumourVolumePlot(figsize=(12,10))
There are three data types for a TumourVolumePlot, and you can build up a plot by adding instances of any combination of these data types. Each time you add data the plot will update, and you can display each step as you build up to your final figure.
In [13]:
tvp.add_mean('Vehicle',test_data['vehicle'],color='blue')
tvp.display()
Out[13]:
In [14]:
tvp.add_individuals('Vehicle',test_data['vehicle'],color='blue')
tvp.display()
Out[14]:
Note that this plot is interactive. When you hover your cursor over the lines for each individual you will see the line highlighted and additional information (the name of the individual). You can also use the magnifying glass to zoom in on a section, the arrow tool to move the canvas, and the home button to return to the original view.
In [15]:
tvp.add_interval('Vehicle',test_data['vehicle'],color='blue')
tvp.display()
Out[15]:
The interval that is plotted is the 95% confidence interval of the mean. This is interpreted as the range in which the observed mean would lie 95% of the time with a random sample from the underlying normally distributed population that is estimated from the observed data. It is not the same thing as the 95% confidence interval based on standard deviation - this shows the range in which 95% of the observations would lie given the estimate from the observed data.
When interpreting these graphs the spread of the individual observations provides the information on the range of observed values you would expect to see, and the interval the region in which we are confident the mean line would lie if we repeated the experiment.
Tests of differences in means are likely to be significant if the 95% confidence intervals of the means do not overlap, while significantly different means may overlap a two standard deviation range of observations.
If you add additional data the plot will automatically rescale
In [16]:
tvp.add_mean('A treatment',test_data['other_treatment'],color='orange')
tvp.add_interval('A treatment',test_data['other_treatment'],color='orange')
tvp.add_individuals('A treatment',test_data['other_treatment'],color='orange')
tvp.display()
Out[16]:
In [17]:
tvp.add_mean('Good treatment',test_data['good_treatment'],color='green')
tvp.add_interval('Good treatment',test_data['good_treatment'],color='green',alpha=0.1)
tvp.add_individuals('Good treatment',test_data['good_treatment'],color='green',dashes=[3,2,1,2])
tvp.display()
Out[17]:
You can set the tite and axis labels on the TumourVolumePlot object
In [18]:
tvp.title = 'My Great Experiment'
You can work directly on the underlying matplotlib axis object if you need to adjust styles or set display limits
In [19]:
tvp.ax.set_xlim([0,100])
tvp.ax.set_ylim([0,1000])
tvp.ax.set_autoscaley_on(False)
tvp.display()
Out[19]:
If you have multiple plots with the same legend you may wish to turn it off, which is simply achieved with an argument to display
In [20]:
tvp.display(legend=False)
Out[20]:
In [21]:
tvp.xlim = [0,120]
tvp.display(legend=False)
Out[21]:
You can save your output as interactive html, or as static pdf files
In [22]:
tvp.save_html('my great experiment.html')
tvp.save_pdf('my great experiment.pdf')
The confidence interval based on the standard error of the mean is only defined when there is more than one individual. The mean of n=1 is valid; however, graphing a single individual as the mean can be visually misleading. We set the threshold of display for the mean so that it is only displayed when n > 2. When n is small the range of the confidence interval will also increase dramatically, and be default it is also only displayed when n > 2. Both the mean and interval can be altered by setting a threshold value, however a minimum of 2 data points is required to display the confidence interval.
In [23]:
from survivalvolume.plot import TumourVolumePlot
tvp = TumourVolumePlot(figsize=(12,10))
tvp.add_mean('A treatment',test_data['other_treatment'],color='orange',threshold=0)
tvp.add_interval('A treatment',test_data['other_treatment'],color='orange',threshold=0)
tvp.add_individuals('A treatment',test_data['other_treatment'],color='orange')
tvp.display()
Out[23]:
In [24]:
tvp = TumourVolumePlot(figsize=(12,10))
tvp.add_mean('A treatment',test_data['other_treatment'],color='orange')
tvp.add_individuals('A treatment',test_data['other_treatment'],color='orange', dashes = [1,1])
tvp.add_interval('A treatment',test_data['other_treatment'],color='orange')
tvp.add_mean('Vehicle',test_data['vehicle'],color='blue')
tvp.add_individuals('Vehicle',test_data['vehicle'],color='blue', dashes = [3,3])
tvp.add_interval('Vehicle',test_data['vehicle'],color='blue')
tvp.add_mean('Good Treatment',test_data['good_treatment'],color='green')
tvp.add_individuals('Good Treatment',test_data['good_treatment'],color='green', dashes = [1,2,3,2])
tvp.add_interval('Good Treatment',test_data['good_treatment'],color='green')
tvp.add_mean('Good Treatment',test_data['good_treatment'],color='green')
tvp.add_individuals('Good Treatment',test_data['good_treatment'],color='green', dashes = [1,2,3,2])
tvp.add_interval('Good Treatment',test_data['good_treatment'],color='green')
tvp.xlim = [0,100]
tvp.title = 'My Great Treatment Model'
tvp.ylabel = 'TV mm$^{3}$'
tvp.km_ylabel = 'Survival Probability'
tvp.display()
Out[24]:
In [25]:
# Lifelines uses matplotlib and to get it to show in a notebook we need to use the following commands
import matplotlib
%matplotlib inline
In [26]:
from survivalvolume.plot import make_km
kmfs = {}
for name in test_data:
kmfs[name] = make_km(test_data[name], label=name)
print(kmfs.keys())
In [27]:
kmfs['other_treatment'].plot(color='orange')
Out[27]:
In [28]:
ax = matplotlib.pyplot.subplot(111)
ax.spines['right'].set_visible(False)
ax.spines['top'].set_visible(False)
ax.xaxis.set_ticks_position('bottom')
ax.yaxis.set_ticks_position('left')
kmfs['other_treatment'].plot(show_censors=True,ax=ax,color='orange')
kmfs['vehicle'].plot(show_censors=True,ax=ax,color='blue')
kmfs['good_treatment'].plot(show_censors=True,ax=ax,color='green')
Out[28]:
The lifelines package has two built in statistical tests, the log rank test and a multivariate log rank test. The log rank test assesses the probability of observing two data sets (or more extremely different data) if all data is drawn from populations with the same endpoint generation process. The multivariate test assess the probability of the observed or more extreme data if all observations are from the same endpoint generation process.
We need to convert the tumour volume data into a table of last observed time and whether the endpoint has been observed. In the example above this was done 'under the hood' by the survivalvolume.plot.make_km function.
In [29]:
import pandas
from survivalvolume.plot import volume_to_survival
volume_to_survival(test_data['vehicle'],endpoint=700)
Out[29]:
In [30]:
from lifelines.statistics import logrank_test, pairwise_logrank_test, multivariate_logrank_test
vehicle_survival = volume_to_survival(test_data['vehicle'],endpoint=700)
good_treatment_survival = volume_to_survival(test_data['good_treatment'],endpoint=700)
other_treatment_survival = volume_to_survival(test_data['other_treatment'],endpoint=700)
result = logrank_test(list(vehicle_survival['Time']),
list(other_treatment_survival['Time']),
list(vehicle_survival['Observed']),
list(other_treatment_survival['Observed']),
alpha=0.95)
result.print_summary()
Note that drawstyle steps required for correct rendering of the Kaplan-Meier chart was not implemented until mpld3/mpld3#350 in mpld3 0.3git (August 2016). Full support will not be available until mpld3 v0.3 is released in late 2016. Until this time only static matplotlib plots will render correctly.
In [31]:
from survivalvolume.plot import VolumeSurvivalPlot
dual = VolumeSurvivalPlot(figsize=(12,5))
dual.add_mean('A treatment',test_data['other_treatment'],color='orange')
dual.add_individuals('A treatment',test_data['other_treatment'],color='orange', dashes = [1,1])
dual.add_interval('A treatment',test_data['other_treatment'],color='orange')
dual.add_mean('Vehicle',test_data['vehicle'],color='blue')
dual.add_individuals('Vehicle',test_data['vehicle'],color='blue', dashes = [3,3])
dual.add_interval('Vehicle',test_data['vehicle'],color='blue')
dual.add_mean('Good Treatment',test_data['good_treatment'],color='green')
dual.add_individuals('Good Treatment',test_data['good_treatment'],color='green', dashes = [1,2,3,2])
dual.add_interval('Good Treatment',test_data['good_treatment'],color='green')
dual.display(use_mpld3=False)
Using the matplotlib display back end you can't re-display a figure so the following constructs the whole plot again rather than adding to the plot like we did in previous examples. Saving the figure as a pdf will also hide the figure, so you can display html then save a pdf, but not the reverse.
In [32]:
dual = VolumeSurvivalPlot(figsize=(15,5),vertical=False)
dual.add_mean('A treatment',test_data['other_treatment'],color='orange')
dual.add_individuals('A treatment',test_data['other_treatment'],color='orange', dashes = [1,1])
dual.add_interval('A treatment',test_data['other_treatment'],color='orange')
dual.add_mean('Vehicle',test_data['vehicle'],color='blue')
dual.add_individuals('Vehicle',test_data['vehicle'],color='blue', dashes = [3,3])
dual.add_interval('Vehicle',test_data['vehicle'],color='blue')
dual.add_mean('Good Treatment',test_data['good_treatment'],color='green')
dual.add_individuals('Good Treatment',test_data['good_treatment'],color='green', dashes = [1,2,3,2])
dual.add_interval('Good Treatment',test_data['good_treatment'],color='green')
dual.xlim = [0,100]
dual.display(legend=False,use_mpld3=False)
In [33]:
dual = VolumeSurvivalPlot(figsize=(15,10), km_size=0.5)
dual.add_mean('A treatment',test_data['other_treatment'],color='orange')
dual.add_individuals('A treatment',test_data['other_treatment'],color='orange', dashes = [1,1])
dual.add_interval('A treatment',test_data['other_treatment'],color='orange')
dual.add_mean('Vehicle',test_data['vehicle'],color='blue')
dual.add_individuals('Vehicle',test_data['vehicle'],color='blue', dashes = [3,3])
dual.add_interval('Vehicle',test_data['vehicle'],color='blue')
dual.add_mean('Good Treatment',test_data['good_treatment'],color='green')
dual.add_individuals('Good Treatment',test_data['good_treatment'],color='green', dashes = [1,2,3,2])
dual.add_interval('Good Treatment',test_data['good_treatment'],color='green')
dual.add_mean('Good Treatment',test_data['good_treatment'],color='green')
dual.add_individuals('Good Treatment',test_data['good_treatment'],color='green', dashes = [1,2,3,2])
dual.add_interval('Good Treatment',test_data['good_treatment'],color='green')
dual.xlim = [0,100]
dual.title = 'My Great Treatment Model'
dual.ylabel = 'TV mm'
dual.km_ylabel = 'Survival Probability'
dual.display(legend=False)
Out[33]:
In [34]:
dual.save_pdf('dual_plot.pdf')
In [35]:
dual = VolumeSurvivalPlot(figsize=(15,10), km_size=0.5)
dual.add_mean('A treatment',test_data['other_treatment'],color='orange')
dual.add_individuals('A treatment',test_data['other_treatment'],color='orange', dashes = [1,1])
dual.add_interval('A treatment',test_data['other_treatment'],color='orange')
dual.add_mean('Vehicle',test_data['vehicle'],color='blue')
dual.add_individuals('Vehicle',test_data['vehicle'],color='blue', dashes = [3,3])
dual.add_interval('Vehicle',test_data['vehicle'],color='blue')
dual.add_mean('Good Treatment',test_data['good_treatment'],color='green')
dual.add_individuals('Good Treatment',test_data['good_treatment'],color='green', dashes = [1,2,3,2])
dual.add_interval('Good Treatment',test_data['good_treatment'],color='green')
dual.add_mean('Good Treatment',test_data['good_treatment'],color='green')
dual.add_individuals('Good Treatment',test_data['good_treatment'],color='green', dashes = [1,2,3,2])
dual.add_interval('Good Treatment',test_data['good_treatment'],color='green')
dual.xlim = [0,100]
dual.title = 'My Great Treatment Model'
dual.ylabel = 'TV mm3'
dual.km_ylabel = 'Survival Probability'
dual.display(use_mpld3=True)
Out[35]:
In [36]:
dual.save_html('dual_plot.html')
In the vertically stacked plot we usually hide the x axis tick labels on the volume plot to get a cleaner plot. You can toggle this behaviour with the hide_volume_labels display option
In [37]:
dual = VolumeSurvivalPlot(figsize=(15,8))
dual.add_mean('A treatment',test_data['other_treatment'],color='orange')
dual.add_individuals('A treatment',test_data['other_treatment'],color='orange', dashes = [1,1])
dual.add_interval('A treatment',test_data['other_treatment'],color='orange')
dual.add_mean('Vehicle',test_data['vehicle'],color='blue')
dual.add_individuals('Vehicle',test_data['vehicle'],color='blue', dashes = [3,3])
dual.add_interval('Vehicle',test_data['vehicle'],color='blue')
dual.add_mean('Good Treatment',test_data['good_treatment'],color='green')
dual.add_individuals('Good Treatment',test_data['good_treatment'],color='green', dashes = [1,2,3,2])
dual.add_interval('Good Treatment',test_data['good_treatment'],color='green')
dual.title = 'My Great Experiment'
dual.xlim = [0,100]
dual.display(legend=False, hide_volume_labels = False, use_mpld3=False)
km_ci_show, the flag for displaying confidence intervals in the Kaplan-Meier plot, and km_show_censors, the flag for displaying censored individuals, both need to be set prior to the addition of data. Data is plotted in the order it is added, which will determine which line overplots at the top of the Kaplan-Meier plot.
In [38]:
dual = VolumeSurvivalPlot(figsize=(15,8))
dual.km_show_censors = False
dual.km_ci_show = False
dual.add_mean('A treatment',test_data['other_treatment'],color='orange')
dual.add_individuals('A treatment',test_data['other_treatment'],color='orange', dashes = [1,1])
dual.add_interval('A treatment',test_data['other_treatment'],color='orange')
dual.add_mean('Vehicle',test_data['vehicle'],color='blue')
dual.add_individuals('Vehicle',test_data['vehicle'],color='blue', dashes = [3,3])
dual.add_interval('Vehicle',test_data['vehicle'],color='blue')
dual.add_mean('Good Treatment',test_data['good_treatment'],color='green')
dual.add_individuals('Good Treatment',test_data['good_treatment'],color='green', dashes = [1,2,3,2])
dual.add_interval('Good Treatment',test_data['good_treatment'],color='green')
dual.title = 'My Great Experiment'
dual.xlim = [0,100]
dual.display(legend=False, hide_volume_labels = False)
Out[38]:
You can do a pairwise log rank test on the dual plot object referencing the name given to the mean. We do not do all possible pairwise as this would incur a greater multiple testing penalty. The results of selected tests are calculated manually and then subsequently will need to be corrected for multiple testing
In [39]:
print('Available to test are:', dual.volume_data.keys())
a = dual.logrank_test('Vehicle', 'Good Treatment')
In [40]:
#You can change these definitions here and all the following plots will update in style
other_treatment_mean = {'color':'red','lw':3}
other_treatment_interval = {'color':'red', 'alpha':0.1}
other_treatment_individuals = {'color':'red','lw':1,'dashes':[2,1,1,1,5,1,1,1]}
dual = VolumeSurvivalPlot(figsize=(15,8))
dual.add_mean('A treatment',test_data['other_treatment'], **other_treatment_mean)
dual.add_individuals('A treatment',test_data['other_treatment'], **other_treatment_individuals)
dual.add_interval('A treatment',test_data['other_treatment'], **other_treatment_interval)
dual.display(legend=False, use_mpld3=False)
In [41]:
dual = VolumeSurvivalPlot(figsize=(15,8))
dual.add_mean('A treatment',test_data['other_treatment'], **other_treatment_mean)
dual.add_individuals('A treatment',test_data['other_treatment'], **other_treatment_individuals)
dual.add_interval('A treatment',test_data['other_treatment'], **other_treatment_interval)
dual.display(legend=False)
dual.ax.annotate("Look Here!",
xy=(25, 540), xycoords='data',
xytext=(22, 900), textcoords='data',
arrowprops=dict(arrowstyle="->",color='green'),
color='blue')
#arrows are not supported by mpld3 v0.3git
dual.display(use_mpld3=False)
In [42]:
dual = VolumeSurvivalPlot(figsize=(15,8))
dual.add_mean('A treatment',test_data['other_treatment'], **other_treatment_mean)
dual.add_individuals('A treatment',test_data['other_treatment'], **other_treatment_individuals)
dual.add_interval('A treatment',test_data['other_treatment'], **other_treatment_interval)
dual.ylim = [0,1000]
dual.ax.annotate("Look Here!",
xy=(25, 540), xycoords='data',
xytext=(22, 900), textcoords='data',
arrowprops=dict(arrowstyle="->",color='green'),
color='blue')
dual.ax.annotate('',
xy=(22, 140), xycoords='data',
xytext=(22, 40), textcoords='data',
arrowprops=dict(arrowstyle="fancy",color='orange'),
color='blue')
dual.ax.text(0, 700, "Threshold", ha="right", va="center", rotation=0,
size=6,
bbox=dict(boxstyle="rarrow,pad=0.3", fc="cyan", ec="b", lw=2))
#arrows are not supported by mpld3 v0.3git
dual.display(legend=False, use_mpld3=False)
In [43]:
from matplotlib.patches import Rectangle
from matplotlib.collections import PatchCollection
dual = VolumeSurvivalPlot(figsize=(15,8))
dual.add_mean('A treatment',test_data['other_treatment'], **other_treatment_mean)
dual.add_individuals('A treatment',test_data['other_treatment'], **other_treatment_individuals)
dual.add_interval('A treatment',test_data['other_treatment'], **other_treatment_interval)
dual.ylim = [0,1000]
dual.xlim = [0,100]
dual.ax.add_patch(Rectangle((0, 0), 21, 20, facecolor="lightgrey",lw=0))
dual.display(legend=False, use_mpld3=False)
In [44]:
from matplotlib.patches import Rectangle
from matplotlib.collections import PatchCollection
dual = VolumeSurvivalPlot(figsize=(15,8))
dual.add_mean('A treatment',test_data['other_treatment'], **other_treatment_mean)
dual.add_individuals('A treatment',test_data['other_treatment'], **other_treatment_individuals)
dual.add_interval('A treatment',test_data['other_treatment'], **other_treatment_interval)
dual.ylim = [0,1000]
dual.xlim = [0,100]
dual.shade_interval(0,25)
dual.display(legend=False, use_mpld3=False)
In [45]:
dual = VolumeSurvivalPlot(figsize=(15,8))
dual.add_mean('A treatment',test_data['other_treatment'], **other_treatment_mean)
dual.add_individuals('A treatment',test_data['other_treatment'], **other_treatment_individuals)
dual.add_interval('A treatment',test_data['other_treatment'], **other_treatment_interval)
dual.ylim = [0,1000]
dual.xlim = [0,100]
dual.show_treatment_days([1,3,5,8,10,12,], facecolor="lightgrey")
dual.show_treatment_days([15,17,19], facecolor="lightblue")
dual.display(legend=False, use_mpld3=False)
In [46]:
dual = VolumeSurvivalPlot(figsize=(15,8))
dual.add_mean('A treatment',test_data['other_treatment'], **other_treatment_mean)
dual.add_individuals('A treatment',test_data['other_treatment'], **other_treatment_individuals)
dual.add_interval('A treatment',test_data['other_treatment'], **other_treatment_interval)
dual.ylim = [0,1000]
dual.xlim = [0,100]
dual.ax.axhline(700,color='lightgrey',lw=1,alpha=0.3,dashes=[5,5])
dual.ax.axhline(200,color='lightgrey',lw=1,alpha=0.3)
dual.ax.axvline(21,color='lightgrey',lw=1,alpha=0.3)
dual.show_treatment_days([1,3,5,8,10,12,], facecolor="lightgrey")
dual.show_treatment_days([15,17,19], facecolor="lightblue")
dual.display(legend=False, use_mpld3=False)
In [47]:
def cm2inch(cm):
return cm/2.54
dual = VolumeSurvivalPlot(figsize=(cm2inch(9),cm2inch(8)))
dual.add_mean('A treatment',test_data['other_treatment'], **other_treatment_mean)
dual.add_individuals('A treatment',test_data['other_treatment'], **other_treatment_individuals)
dual.add_interval('A treatment',test_data['other_treatment'], **other_treatment_interval)
dual.ylim = [0,1000]
dual.xlim = [0,100]
dual.fontsize = 8
dual.title = 'Sized for 6 per page'
#save as an adobe illustrator compatible pdf and open in Illustrator
dual.save_pdf('sized6perpage.ai', legend=False)
#!open sized6perpage.ai
Legend placement can be manually controlled by calling the add legend method of the plot and providing the legend='custom' argument when calling display to prevent deletion of the existing legend.
The most common use for this function is to over ride the default 'best' placement. Additional arguments such as bbox_to_anchor will be passed to matplotlib's legend function. For PDF output this can be used to move the legend outside the plot area; however, this currently will result in unpredicatable results when using the mpld3 html output.
In [48]:
dual = VolumeSurvivalPlot(figsize=(15,8))
dual.km_show_censors = False
dual.km_ci_show = False
dual.add_mean('A treatment',test_data['other_treatment'],color='orange')
dual.add_individuals('A treatment',test_data['other_treatment'],color='orange', dashes = [1,1])
dual.add_interval('A treatment',test_data['other_treatment'],color='orange',alpha=0.05)
dual.add_mean('Vehicle',test_data['vehicle'],color='blue')
dual.add_individuals('Vehicle',test_data['vehicle'],color='blue', dashes = [3,3])
dual.add_interval('Vehicle',test_data['vehicle'],color='blue',alpha=0.05)
dual.add_mean('Good Treatment',test_data['good_treatment'],color='green')
dual.add_individuals('Good Treatment',test_data['good_treatment'],color='green', dashes = [1,2,3,2])
dual.add_interval('Good Treatment',test_data['good_treatment'],color='green',alpha=0.05)
dual.title = 'My Great Experiment'
dual.xlim = [0,100]
#set the legend location to 1.01 plot widths right, and 1.0 up from the bottom left of the plot.
dual.add_legend(loc='lower left',bbox_to_anchor=(1.01,1.0))
dual.display(legend='custom', hide_volume_labels = False, use_mpld3=False)
A frequent requirement of plots comparing groups is to be able to rapidly asses the number of individual that are included in a group. Although this information is visually presented as lines on the volume plot and steps in the Kaplain-Meier plot it is often useful to annotate the legend with the number of individual in each group.
In [49]:
dual = VolumeSurvivalPlot(figsize=(15,8))
#Display the number of individuals in the legend
dual.n_in_legend = True
dual.km_show_censors = False
dual.km_ci_show = False
dual.add_mean('A treatment',test_data['other_treatment'],color='orange')
dual.add_individuals('A treatment',test_data['other_treatment'],color='orange', dashes = [1,1])
dual.add_interval('A treatment',test_data['other_treatment'],color='orange',alpha=0.05)
dual.add_mean('Vehicle',test_data['vehicle'],color='blue')
dual.add_individuals('Vehicle',test_data['vehicle'],color='blue', dashes = [3,3])
dual.add_interval('Vehicle',test_data['vehicle'],color='blue',alpha=0.05)
dual.add_mean('Good Treatment',test_data['good_treatment'],color='green')
dual.add_individuals('Good Treatment',test_data['good_treatment'],color='green', dashes = [1,2,3,2])
dual.add_interval('Good Treatment',test_data['good_treatment'],color='green',alpha=0.05)
dual.title = 'My Great Experiment'
dual.xlim = [0,100]
#set the legend location to 1.01 plot widths right, and 1.0 up from the bottom left of the plot.
dual.add_legend(loc='lower left',bbox_to_anchor=(1.01,1.0))
dual.display(legend=True, use_mpld3=True)
Out[49]: