From 05c66854c94e913326853b0d0b580c8d0adef64d Mon Sep 17 00:00:00 2001
From: jawi Violin plots are generated with the vioplot package. Bean plots are generated with the beanplot package. Using the beeswarm package. Tukey - whiskers extend to data points that are less than 1.5 x IQR away from 1st/3rd quartile;
+ HTML(' Tukey - whiskers extend to data points that are less than 1.5 x IQR away from 1st/3rd quartile;
Spear - whiskers extend to minimum and maximum values;
Altman - whiskers extend to 5th and 95th percentile (use only if n>40) +/-1.58*IQR/sqrt(n) - gives roughly 95% confidence that two medians differ (Chambers et al., 1983) +/-1.58*IQR/sqrt(n) - gives roughly 95% confidence that two medians differ (Chambers et al., 1983) The notches are defined as +/-1.58*IQR/sqrt(n) and represent the 95% confidence interval for each median.
Non-overlapping notches give roughly 95% confidence that two medians differ, ie, in 19 out of 20 cases the population
@@ -129,6 +135,7 @@ shinyUI(pageWithSidebar(
h5("X-axis range (eg., '0,10'):"),
textInput("xlimit", "", value="")
),
+ checkboxInput("logScale", "Change to log scale (only for data >0)", FALSE),
h5("Add grid: "),
radioButtons("addGrid", "", list("None" = 0, "X & Y"= 1, "X only" = 2, "Y only" = 3))
# numericInput("boxWidth", "Width of boxes:", value=1),
@@ -139,13 +146,24 @@ shinyUI(pageWithSidebar(
tabsetPanel(
# Welcome tab
tabPanel("About",
- HTML(' This application allows users to generate customized box plots in a number of variants based on their data. A data matrix
- can be uploaded as a file or pasted into the application. Basic box plots are generated based on the data and can be modified to include
- additional information. Additional features become available when checking that option. Information about sample sizes can be represented
- by the width of each box where the widths are proportional to the square roots of the number of observations n. Notches can be added to the
- boxes. These are defined as +/-1.58*IQR/sqrt(n) which gives roughly 95% confidence that two medians are different. It is also possible to define
- the whiskers based on the ideas of Spear and Tukey. Additional options of data visualization (violin and bean plots) reveal more information
- about the underlying data distribution. Plots can be labeled, customized (colors, dimensions, orientation) and exported as eps, pdf and svg files. This application was developed with Nature Methods and you can find the publication here.
+ The BoxPlotR has also been mentioned in this editorial and this
+ blog entry. Nature methods also dedicated a
+ Points of View and a Points of Significance
+ column to box plots. We hope that you find the BoxPlotR useful and we welcome suggestions
+ for additional features by our users. We would like to thank everyone who has made constructive suggestions so far. We will document the addition of new features in the News tab. This application allows users to generate customized box plots in a number of variants based on their data. A data matrix
+ can be uploaded as a file or pasted into the application. Basic box plots are generated based on the data and can be modified to include
+ additional information. Additional features become available when checking that option. Information about sample sizes can be represented
+ by the width of each box where the widths are proportional to the square roots of the number of observations n. Notches can be added to the
+ boxes. These are defined as +/-1.58*IQR/sqrt(n) which gives roughly 95% confidence that two medians are different. It is also possible to define
+ the whiskers based on the ideas of Spear and Tukey. Additional options of data visualization (violin and bean plots) reveal more information
+ about the underlying data distribution. Plots can be labeled, customized (colors, dimensions, orientation) and exported as eps, pdf and svg files. BoxPlotR code can be run locally via GitHub. You can also download and install it as a virtual machine (see GitHub and FAQs for details). R Development Core Team. R: A Language and Environment for Statistical Computing. R Foundation for Statistical Computing, Vienna (2013) Hadley Wickham and Lisa Stryjewski: 40 years of boxplots Kristin Potter: Methods for Presenting Statistical Information: The Box Plot Kristin Potter: Methods for Presenting Statistical Information: The Box Plot There are several recent updates. The jitter of points is now consistent for all samples. When
+ data points are added to the plot, the size and transparence of the points can now be modified with
+ sliders. The link to one of the boxplot references has been updated. The sample names are now displayed as they are in the input, ie., spaces and special characters
+ are not replaced with underscores. If you experience problems with this boxplot server, there is an alternative BoxPlotR mirror
+ available at boxplot.bio.ed.ac.uk. A: Please download the virtual machine from http://tyerslab.bio.ed.ac.uk/download/shiny.boxplot.7z (1.1GB).
+ Unzip the file using 7zip or equivalent. The virtual machine is available in the open
+ virtualization format (OVF) and you can use this file with vbox and
+ vmware player.
+ One easy way to use the server is to set the virtual host network environment to NAT. After importing the virtual machine you can
+ start the server and login as user shiny with password pk635153Y6jx89r. On the command line use the command ifconfg and record the
+ IP address of the virtual server. Now going back to the virtual host network environment change the advanced settings of the NAT and
+ activate port forwarding for the guest network ip address (shiny server) using port 80 to the host ip address using for example port 8080.
+ Now you should be able to access the shiny server in a browser on port 127.0.0.1:8080 or your localhost:8080.
+ If you are not familiar with the software packages there are detailed examples for
+ vbox and
+ vmware.
+
+
RStudio and Inc. shiny: Web Application Framework for R. R package version 0.5.0 (2013)
@@ -155,15 +173,15 @@ shinyUI(pageWithSidebar(
Neuwirth, E. RColorBrewer: ColorBrewer palettes. R package version 1.0-5. (2011)
BoxPlotR code can be run locally via GitHub. You can also download and install it as a virtual machine (see GitHub and FAQs for details).
'), +BoxPlotR code can be run locally via GitHub. You can also download and install it as a virtual machine (see GitHub and FAQs for details).
'), h5("Software references"), HTML('R Development Core Team. R: A Language and Environment for Statistical Computing. R Foundation for Statistical Computing, Vienna (2013)
@@ -189,11 +228,20 @@ shinyUI(fluidPage(
a("shiny package from RStudio", href="http://www.rstudio.com/shiny/"), ".")
),
# Boxplot tab
- tabPanel("Data visualization", downloadButton("downloadPlotEPS", "Download eps-file"),
- downloadButton("downloadPlotPDF", "Download pdf-file"),
- downloadButton("downloadPlotSVG", "Download svg-file"),
- plotOutput("boxPlot", height='100%', width='100%'),
- h4("Box plot statistics"), tableOutput("boxplotStatsTable"),
+ tabPanel("Data visualization",
+ div(class="controls-row",
+ downloadButton("downloadPlotEPS", "Download eps-file"),
+ downloadButton("downloadPlotPDF", "Download pdf-file"),
+ downloadButton("downloadPlotSVG", "Download svg-file")
+ ),
+ div(class="plot-card",
+ plotOutput("boxPlot", height='100%', width='100%')
+ ),
+ div(class="table-card",
+ h4("Box plot statistics"),
+ tableOutput("boxplotStatsTable")
+ ),
+ br(),
h6("This application was created by the ", a("Tyers", href="http://tyers.iric.ca/"), " and ", a("Rappsilber", href="http://rappsilberlab.org/"),
" labs. Please send bugs and feature requests to Michaela Spitzer (michaela.spitzer(at)gmail.com) and Jan Wildenhain (jan.wildenhain(at)gmail.com). This application uses the ",
a("shiny package from RStudio", href="http://www.rstudio.com/shiny/"), ".")
@@ -208,6 +256,8 @@ shinyUI(fluidPage(
),
# News
tabPanel("News",
+ h5("April 8, 2026"),
+ HTML('
The shiny server backend has been updated. The number of concurrent sessions has been limited to 15 and the session idle timeout set to 10 minutes. We are currently reworking the code to support the latest R and shiny versions, plus preparing a system upgrade of the server.
'), h5("January 17, 2021"), HTML('There are several recent updates. The jitter of points is now consistent for all samples. When data points are added to the plot, the size and transparence of the points can now be modified with @@ -232,19 +282,8 @@ shinyUI(fluidPage( In Adobe Illustrator you will also need to use the 'release compound path' command. For PDF files you should 'release clipping mask'. SVG import appears to have problems in Adobe Illustrator and Corel Draw and should be avoided. EPS, PDF and SVG import all work with Inkscape http://www.inkscape.org/."), - h5("Q: I would like to install BoxPlotR as a virtual machine."), - HTML('
A: Please download the virtual machine from http://tyerslab.bio.ed.ac.uk/download/shiny.boxplot.7z (1.1GB). - Unzip the file using 7zip or equivalent. The virtual machine is available in the open - virtualization format (OVF) and you can use this file with vbox and - vmware player. - One easy way to use the server is to set the virtual host network environment to NAT. After importing the virtual machine you can - start the server and login as user shiny with password pk635153Y6jx89r. On the command line use the command ifconfg and record the - IP address of the virtual server. Now going back to the virtual host network environment change the advanced settings of the NAT and - activate port forwarding for the guest network ip address (shiny server) using port 80 to the host ip address using for example port 8080. - Now you should be able to access the shiny server in a browser on port 127.0.0.1:8080 or your localhost:8080. - If you are not familiar with the software packages there are detailed examples for - vbox and - vmware.
') + h5("Q: I would like to run BoxPlotR locally in an isolated environment."), + HTML('A: We provide a pre-configured Docker image that automatically installs and configures the environment. First, ensure you have Docker installed. Then, clone the repository and run the following terminal commands inside the repository directory:
docker build -t boxplotr .
docker run -d -p 3838:3838 boxplotr
You can then access the application by navigating your web browser to http://localhost:3838.
Data in delimited text files can be separated by comma, tab or semicolon. + ), + sidebarLayout( + sidebarPanel( + conditionalPanel( + condition = "input.tabs1=='About'", + h4("Introduction") + ), + conditionalPanel( + condition = "input.tabs1=='Data upload'", + h4("Enter data"), + radioButtons("dataInput", "", list("Load sample data" = 1, "Upload file" = 2, "Paste data" = 3)), + conditionalPanel( + condition = "input.dataInput=='1'", + h5("Load sample data:"), + radioButtons("sampleData", "Load sample data", list("Example 1 (100,76,16,76,41 data points)" = 1, "Example 2 (3 columns with 100 data points)" = 2)) + ), + conditionalPanel( + condition = "input.dataInput=='2'", + h5("Upload delimited text file: "), + fileInput("upload", "", multiple = FALSE), + radioButtons("fileSepDF", "Delimiter:", list("Comma" = 1, "Tab" = 2, "Semicolon" = 3)), # , "Space"=4)) + HTML('
Data in delimited text files can be separated by comma, tab or semicolon. For example, Excel data can be exported in .csv (comma separated) or .tab (tab separated) format.
') - ), - conditionalPanel(condition="input.dataInput=='3'", - h5("Paste data below:"), - tags$textarea(id="myData", rows=10, cols=5, ""), - actionButton('clearText_button','Clear data'), - radioButtons("fileSepP", "Separator:", list("Comma"=1,"Tab"=2,"Semicolon"=3)) - ) - ), - conditionalPanel(condition="input.tabs1=='Data visualization'", - - radioButtons("plotType", "", list("Boxplot"=0, "Other"=1)), - conditionalPanel(condition="input.plotType=='1'", - radioButtons("otherPlotType", "", list("Violin plot"=0, "Bean plot"=1)), - HTML('Violin plots are generated with the vioplot package. Bean plots are generated with the beanplot package.
'), - textInput("myOtherPlotColours", "Colour(s):", value=c("light grey, white")), - conditionalPanel(condition="input.otherPlotType=='0'", - helpText("Colour of the 'violin area'"), - textInput("violinBorder", "Border colour:", value=c("grey")) - ), - conditionalPanel(condition="input.otherPlotType=='1'", - helpText("up to 4 colours can be specified: area of the beans, lines inside the bean, lines outside the bean, and average line per bean"), - textInput("beanBorder", "Border colour:", value=c("grey")), - radioButtons("beanPlotMedianMean", "Display: ", list("Median"=0, "Mean"=1)) - ) - ), - - h4("Plot options"), - checkboxInput("plotDataPoints", "Minimum number of data points", FALSE), - conditionalPanel(condition="input.plotDataPoints", - numericInput("nrOfDataPoints", "Data point limit: ", value=5, min=5) - ), - - conditionalPanel(condition="input.plotType=='0'", - checkboxInput("showDataPoints", "Add data points", FALSE), - conditionalPanel(condition="input.showDataPoints", - radioButtons("datapointType", "", list("Default"=0, "Bee swarm"=1, "Jittered"=2)), - sliderInput("pointTransparency", "Transparency of data points", min=0, max=99, value=50), - sliderInput("pointSize", "Size of data points", min=1, max=20, value=10), - HTML('Using the beeswarm package.
'), - textInput("pointColors", "Colour(s):", value=c("black")) - ), - checkboxInput("whiskerDefinition", "Definition of whisker extent", FALSE), - conditionalPanel(condition="input.whiskerDefinition", - radioButtons("whiskerType", "", list("Tukey"=0, "Spear"=1, "Altman"=2)), -# conditionalPanel(condition="input.whiskerType=='0'", -# numericInput("TukeyRange", "Define whisker extent (x IQR):", min=0, step=0.5, value=1.5) -# ), -# conditionalPanel(condition="input.whiskerType=='1'", -# HTML('Spear - Whiskers extend to minimum and maximum values.
') -# ), -# conditionalPanel(condition="input.whiskerType=='2'", -# numericInput("AltmanRange", "Define whisker extent in percentiles (ie, '5' means that whiskers extend to 5th and 95th percentile):", min=0, step=0.5, value=5) -# ), - HTML('Tukey - whiskers extend to data points that are less than 1.5 x IQR away from 1st/3rd quartile; - Spear - whiskers extend to minimum and maximum values; + ), + conditionalPanel( + condition = "input.dataInput=='3'", + h5("Paste data below:"), + tags$textarea(id = "myData", rows = 10, cols = 5, ""), + actionButton("clearText_button", "Clear data"), + radioButtons("fileSepP", "Separator:", list("Comma" = 1, "Tab" = 2, "Semicolon" = 3)) + ) + ), + conditionalPanel( + condition = "input.tabs1=='Data visualization'", + radioButtons("plotType", "", list("Boxplot" = 0, "Other" = 1)), + conditionalPanel( + condition = "input.plotType=='1'", + radioButtons("otherPlotType", "", list("Violin plot" = 0, "Bean plot" = 1)), + HTML('
Violin plots are generated with the vioplot package. Bean plots are generated with the beanplot package.
'), + textInput("myOtherPlotColours", "Colour(s):", value = c("light grey, white")), + conditionalPanel( + condition = "input.otherPlotType=='0'", + helpText("Colour of the 'violin area'"), + textInput("violinBorder", "Border colour:", value = c("grey")) + ), + conditionalPanel( + condition = "input.otherPlotType=='1'", + helpText("up to 4 colours can be specified: area of the beans, lines inside the bean, lines outside the bean, and average line per bean"), + textInput("beanBorder", "Border colour:", value = c("grey")), + radioButtons("beanPlotMedianMean", "Display: ", list("Median" = 0, "Mean" = 1)) + ) + ), + h4("Plot options"), + checkboxInput("plotDataPoints", "Minimum number of data points", FALSE), + conditionalPanel( + condition = "input.plotDataPoints", + numericInput("nrOfDataPoints", "Data point limit: ", value = 5, min = 5) + ), + conditionalPanel( + condition = "input.plotType=='0'", + checkboxInput("showDataPoints", "Add data points", FALSE), + conditionalPanel( + condition = "input.showDataPoints", + radioButtons("datapointType", "", list("Default" = 0, "Bee swarm" = 1, "Jittered" = 2)), + sliderInput("pointTransparency", "Transparency of data points", min = 0, max = 99, value = 50), + sliderInput("pointSize", "Size of data points", min = 1, max = 20, value = 10), + HTML('Using the beeswarm package.
'), + textInput("pointColors", "Colour(s):", value = c("black")) + ), + checkboxInput("whiskerDefinition", "Definition of whisker extent", FALSE), + conditionalPanel( + condition = "input.whiskerDefinition", + radioButtons("whiskerType", "", list("Tukey" = 0, "Spear" = 1, "Altman" = 2)), + # conditionalPanel(condition="input.whiskerType=='0'", + # numericInput("TukeyRange", "Define whisker extent (x IQR):", min=0, step=0.5, value=1.5) + # ), + # conditionalPanel(condition="input.whiskerType=='1'", + # HTML('Spear - Whiskers extend to minimum and maximum values.
') + # ), + # conditionalPanel(condition="input.whiskerType=='2'", + # numericInput("AltmanRange", "Define whisker extent in percentiles (ie, '5' means that whiskers extend to 5th and 95th percentile):", min=0, step=0.5, value=5) + # ), + HTML('Tukey - whiskers extend to data points that are less than 1.5 x IQR away from 1st/3rd quartile; + Spear - whiskers extend to minimum and maximum values; Altman - whiskers extend to 5th and 95th percentile (use only if n>40)
') - ), - checkboxInput("showNrOfPoints", "Display number of data points", FALSE), - checkboxInput("addMeans", "Add sample means", FALSE), - conditionalPanel(condition="input.addMeans", - checkboxInput("addMeanCI", "Add confidence intervals of means", FALSE), - conditionalPanel(condition="input.addMeanCI", - radioButtons("meanCI", "Define confidence interval of means:", list("83%"=83, "90%"=90, "95%"=95)) - ) - ), - - checkboxInput("myVarwidth", "Variable width boxes", FALSE), - helpText("Widths of boxes are proportional to square-roots of the number of observations."), - checkboxInput("myNotch", "Add notches", FALSE), - HTML('+/-1.58*IQR/sqrt(n) - gives roughly 95% confidence that two medians differ (Chambers et al., 1983)
'), - conditionalPanel(condition="input.myNotch", - HTML('The notches are defined as +/-1.58*IQR/sqrt(n) and represent the 95% confidence interval for each median. - Non-overlapping notches give roughly 95% confidence that two medians differ, ie, in 19 out of 20 cases the population + ), + checkboxInput("showNrOfPoints", "Display number of data points", FALSE), + checkboxInput("addMeans", "Add sample means", FALSE), + conditionalPanel( + condition = "input.addMeans", + checkboxInput("addMeanCI", "Add confidence intervals of means", FALSE), + conditionalPanel( + condition = "input.addMeanCI", + radioButtons("meanCI", "Define confidence interval of means:", list("83%" = 83, "90%" = 90, "95%" = 95)) + ) + ), + checkboxInput("myVarwidth", "Variable width boxes", FALSE), + helpText("Widths of boxes are proportional to square-roots of the number of observations."), + checkboxInput("myNotch", "Add notches", FALSE), + HTML('
+/-1.58*IQR/sqrt(n) - gives roughly 95% confidence that two medians differ (Chambers et al., 1983)
'), + conditionalPanel( + condition = "input.myNotch", + HTML('The notches are defined as +/-1.58*IQR/sqrt(n) and represent the 95% confidence interval for each median. + Non-overlapping notches give roughly 95% confidence that two medians differ, ie, in 19 out of 20 cases the population medians (estimated based on the samples) are in fact different (Chambers et al., 1983).
') - ), - textInput("myColours", "Colour(s):", value=c("light grey, white")), - helpText("Colours in HEX format can be chosen on http://colorbrewer2.org/") - ), - - checkboxInput("labelsTitle", "Modify labels and title", FALSE), - conditionalPanel(condition="input.labelsTitle", - checkboxInput("xaxisLabelAngle", "Rotate sample names", FALSE), - textInput("myXlab", "X-axis label:", value=c("")), - textInput("myYlab", "Y-axis label:", value=c("")), - textInput("myTitle", "Boxplot title:", value=c("")), - textInput("mySubtitle", "Boxplot subtitle:", value=c("")) - ), - checkboxInput("plotSize", "Adjust plot size", FALSE), - conditionalPanel(condition="input.plotSize", - numericInput("myHeight", "Plot height:", value=550), - numericInput("myWidth", "Plot width:", value=750) - ), - checkboxInput("fontSizes", "Change font sizes", FALSE), - conditionalPanel(condition="input.fontSizes", - numericInput("cexTitle", "Title font size:", value=14), - numericInput("cexAxislabel", "Axis label size:", value=14), - numericInput("cexAxis", "Axis font size:", value=12) - ), - h5("Orientation of box plots:"), - radioButtons("myOrientation", "", list("Vertical"=0, "Horizontal"=1)), - conditionalPanel(condition="input.myOrientation=='0'", - h5("Y-axis range (eg., '0,10'):"), - textInput("ylimit", "", value="") - ), - conditionalPanel(condition="input.myOrientation=='1'", - h5("X-axis range (eg., '0,10'):"), - textInput("xlimit", "", value="") - ), - checkboxInput("logScale", "Change to log scale (only for data >0)", FALSE), - h5("Add grid: "), - radioButtons("addGrid", "", list("None" = 0, "X & Y"= 1, "X only" = 2, "Y only" = 3)) -# numericInput("boxWidth", "Width of boxes:", value=1), - ) - ), - - mainPanel( - tabsetPanel( - # Welcome tab - tabPanel("About", - HTML(' + ), + textInput("myColours", "Colour(s):", value = c("light grey, white")), + helpText("Colours in HEX format can be chosen on http://colorbrewer2.org/") + ), + checkboxInput("labelsTitle", "Modify labels and title", FALSE), + conditionalPanel( + condition = "input.labelsTitle", + checkboxInput("xaxisLabelAngle", "Rotate sample names", FALSE), + textInput("myXlab", "X-axis label:", value = c("")), + textInput("myYlab", "Y-axis label:", value = c("")), + textInput("myTitle", "Boxplot title:", value = c("")), + textInput("mySubtitle", "Boxplot subtitle:", value = c("")) + ), + checkboxInput("plotSize", "Adjust plot size", FALSE), + conditionalPanel( + condition = "input.plotSize", + numericInput("myHeight", "Plot height:", value = 550), + numericInput("myWidth", "Plot width:", value = 750) + ), + checkboxInput("fontSizes", "Change font sizes", FALSE), + conditionalPanel( + condition = "input.fontSizes", + numericInput("cexTitle", "Title font size:", value = 14), + numericInput("cexAxislabel", "Axis label size:", value = 14), + numericInput("cexAxis", "Axis font size:", value = 12) + ), + h5("Orientation of box plots:"), + radioButtons("myOrientation", "", list("Vertical" = 0, "Horizontal" = 1)), + conditionalPanel( + condition = "input.myOrientation=='0'", + h5("Y-axis range (eg., '0,10'):"), + textInput("ylimit", "", value = "") + ), + conditionalPanel( + condition = "input.myOrientation=='1'", + h5("X-axis range (eg., '0,10'):"), + textInput("xlimit", "", value = "") + ), + checkboxInput("logScale", "Change to log scale (only for data >0)", FALSE), + h5("Add grid: "), + radioButtons("addGrid", "", list("None" = 0, "X & Y" = 1, "X only" = 2, "Y only" = 3)) + # numericInput("boxWidth", "Width of boxes:", value=1), + ) + ), + mainPanel( + tabsetPanel( + # Welcome tab + tabPanel( + "About", + HTML('This application was developed with Nature Methods and you can find the publication here. The BoxPlotR has also been mentioned in this editorial and this blog entry. Nature methods also dedicated a @@ -206,96 +221,108 @@ shinyUI(fluidPage( the whiskers based on the ideas of Spear and Tukey. Additional options of data visualization (violin and bean plots) reveal more information about the underlying data distribution. Plots can be labeled, customized (colors, dimensions, orientation) and exported as eps, pdf and svg files.
BoxPlotR code can be run locally via GitHub. You can also download and install it as a virtual machine (see GitHub and FAQs for details).
'), - - h5("Software references"), - HTML('R Development Core Team. R: A Language and Environment for Statistical Computing. R Foundation for Statistical Computing, Vienna (2013)
+ h5("Support BoxPlotR"),
+ HTML('
Please consider supporting the development and maintenance of BoxPlotR with a donation.
'), + h5("Software references"), + HTML('R Development Core Team. R: A Language and Environment for Statistical Computing. R Foundation for Statistical Computing, Vienna (2013)
RStudio and Inc. shiny: Web Application Framework for R. R package version 0.5.0 (2013)
Adler, D. vioplot: Violin plot. R package version 0.2 (2005)
Eklund, A. beeswarm: The bee swarm plot, an alternative to stripchart. R package version 0.1.5 (2012)
Kampstra, P. Beanplot: A Boxplot Alternative for Visual Comparison of Distributions. Journal of Statistical Software, Code Snippets 28(1). 1-9 (2008)
Neuwirth, E. RColorBrewer: ColorBrewer palettes. R package version 1.0-5. (2011)
Hadley Wickham and Lisa Stryjewski: 40 years of boxplots
'), - HTML('Kristin Potter: Methods for Presenting Statistical Information: The Box Plot
'), - h6("This application was created by the ", a("Tyers", href="http://tyers.iric.ca/"), " and ", a("Rappsilber", href="http://rappsilberlab.org/"), - " labs. Please send bugs and feature requests to Michaela Spitzer (michaela.spitzer(at)gmail.com) and Jan Wildenhain (jan.wildenhain(at)gmail.com). This application uses the ", - a("shiny package from RStudio", href="http://www.rstudio.com/shiny/"), ".") - ), - # Data upload tab - tabPanel("Data upload", tableOutput("filetable"), - h6("This application was created by the ", a("Tyers", href="http://tyers.iric.ca/"), " and ", a("Rappsilber", href="http://rappsilberlab.org/"), - " labs. Please send bugs and feature requests to Michaela Spitzer (michaela.spitzer(at)gmail.com) and Jan Wildenhain (jan.wildenhain(at)gmail.com). This application uses the ", - a("shiny package from RStudio", href="http://www.rstudio.com/shiny/"), ".") - ), - # Boxplot tab - tabPanel("Data visualization", - div(class="controls-row", - downloadButton("downloadPlotEPS", "Download eps-file"), - downloadButton("downloadPlotPDF", "Download pdf-file"), - downloadButton("downloadPlotSVG", "Download svg-file") - ), - div(class="plot-card", - plotOutput("boxPlot", height='100%', width='100%') - ), - div(class="table-card", - h4("Box plot statistics"), - tableOutput("boxplotStatsTable") - ), - br(), - h6("This application was created by the ", a("Tyers", href="http://tyers.iric.ca/"), " and ", a("Rappsilber", href="http://rappsilberlab.org/"), - " labs. Please send bugs and feature requests to Michaela Spitzer (michaela.spitzer(at)gmail.com) and Jan Wildenhain (jan.wildenhain(at)gmail.com). This application uses the ", - a("shiny package from RStudio", href="http://www.rstudio.com/shiny/"), ".") - ), - # Figure legend - tabPanel("Figure legend template", h5("Box plot description for figure legend:"), textOutput("FigureLegend"), - h5("Further information to be added to the figure legend:"), p("What do the box plots show, explain colours if used."), - downloadButton("downloadBoxplotData", "Download box plot data as .CSV file"), - h6("This application was created by the ", a("Tyers", href="http://tyers.iric.ca/"), " and ", a("Rappsilber", href="http://rappsilberlab.org/"), - " labs. Please send bugs and feature requests to Michaela Spitzer (michaela.spitzer(at)gmail.com) and Jan Wildenhain (jan.wildenhain(at)gmail.com). This application uses the ", - a("shiny package from RStudio", href="http://www.rstudio.com/shiny/"), ".") - ), - # News - tabPanel("News", - h5("April 8, 2026"), - HTML('The shiny server backend has been updated. The number of concurrent sessions has been limited to 15 and the session idle timeout set to 10 minutes. We are currently reworking the code to support the latest R and shiny versions, plus preparing a system upgrade of the server.
'), - h5("January 17, 2021"), - HTML('There are several recent updates. The jitter of points is now consistent for all samples. When + h5("Further references"), + HTML('
Hadley Wickham and Lisa Stryjewski: 40 years of boxplots
'), + HTML('Kristin Potter: Methods for Presenting Statistical Information: The Box Plot
'), + h6( + "This application was created by the ", a("Tyers", href = "http://tyers.iric.ca/"), " and ", a("Rappsilber", href = "http://rappsilberlab.org/"), + " labs. Please send bugs and feature requests to Michaela Spitzer (michaela.spitzer(at)gmail.com) and Jan Wildenhain (jan.wildenhain(at)gmail.com). This application uses the ", + a("shiny package from RStudio", href = "http://www.rstudio.com/shiny/"), "." + ) + ), + # Data upload tab + tabPanel( + "Data upload", tableOutput("filetable"), + h6( + "This application was created by the ", a("Tyers", href = "http://tyers.iric.ca/"), " and ", a("Rappsilber", href = "http://rappsilberlab.org/"), + " labs. Please send bugs and feature requests to Michaela Spitzer (michaela.spitzer(at)gmail.com) and Jan Wildenhain (jan.wildenhain(at)gmail.com). This application uses the ", + a("shiny package from RStudio", href = "http://www.rstudio.com/shiny/"), "." + ) + ), + # Boxplot tab + tabPanel( + "Data visualization", + div( + class = "controls-row", + downloadButton("downloadPlotEPS", "Download eps-file"), + downloadButton("downloadPlotPDF", "Download pdf-file"), + downloadButton("downloadPlotSVG", "Download svg-file") + ), + div( + class = "plot-card", + plotOutput("boxPlot", height = "100%", width = "100%") + ), + div( + class = "table-card", + h4("Box plot statistics"), + tableOutput("boxplotStatsTable") + ), + br(), + h6( + "This application was created by the ", a("Tyers", href = "http://tyers.iric.ca/"), " and ", a("Rappsilber", href = "http://rappsilberlab.org/"), + " labs. Please send bugs and feature requests to Michaela Spitzer (michaela.spitzer(at)gmail.com) and Jan Wildenhain (jan.wildenhain(at)gmail.com). This application uses the ", + a("shiny package from RStudio", href = "http://www.rstudio.com/shiny/"), "." + ) + ), + # Figure legend + tabPanel( + "Figure legend template", h5("Box plot description for figure legend:"), textOutput("FigureLegend"), + h5("Further information to be added to the figure legend:"), p("What do the box plots show, explain colours if used."), + downloadButton("downloadBoxplotData", "Download box plot data as .CSV file"), + h6( + "This application was created by the ", a("Tyers", href = "http://tyers.iric.ca/"), " and ", a("Rappsilber", href = "http://rappsilberlab.org/"), + " labs. Please send bugs and feature requests to Michaela Spitzer (michaela.spitzer(at)gmail.com) and Jan Wildenhain (jan.wildenhain(at)gmail.com). This application uses the ", + a("shiny package from RStudio", href = "http://www.rstudio.com/shiny/"), "." + ) + ), + # News + tabPanel( + "News", + h5("April 16, 2026"), + HTML("The number of concurrent sessions has been increased to 50.
"), + h5("April 8, 2026"), + HTML("The shiny server backend has been updated. The number of concurrent sessions has been limited to 15 and the session idle timeout set to 10 minutes. We are currently reworking the code to support the latest R and shiny versions, plus preparing a system upgrade of the server.
"), + h5("January 17, 2021"), + HTML("There are several recent updates. The jitter of points is now consistent for all samples. When data points are added to the plot, the size and transparence of the points can now be modified with - sliders. The link to one of the boxplot references has been updated.
'), - h5("June 11, 2020"), - HTML('The sample names are now displayed as they are in the input, ie., spaces and special characters - are not replaced with underscores.
'), - h5("January 11, 2017"), - HTML('If you experience problems with this boxplot server, there is an alternative BoxPlotR mirror + sliders. The link to one of the boxplot references has been updated.
"), + h5("June 11, 2020"), + HTML("The sample names are now displayed as they are in the input, ie., spaces and special characters + are not replaced with underscores.
"), + h5("January 11, 2017"), + HTML('If you experience problems with this boxplot server, there is an alternative BoxPlotR mirror available at boxplot.bio.ed.ac.uk.
'), - h5("July 23, 2014"), - p("Upgrade to R version 3.1 and shiny-server 1.2"), - h5("March 18, 2014"), - p("The user can now choose the color of the data points. There is also an additional option for data + h5("July 23, 2014"), + p("Upgrade to R version 3.1 and shiny-server 1.2"), + h5("March 18, 2014"), + p("The user can now choose the color of the data points. There is also an additional option for data point display: data points can now be randomly jittered. A small bug in label display was fixed. Log scales can now be used.") - ), - # FAQ - tabPanel("FAQ", - h5("Q: I have trouble editing the graphic files."), - p("A: For EPS files make sure to 'ungroup' all objects so they can be edited independently. - In Adobe Illustrator you will also need to use the 'release compound path' command. For PDF - files you should 'release clipping mask'. SVG import appears to have problems in Adobe Illustrator + ), + # FAQ + tabPanel( + "FAQ", + h5("Q: I have trouble editing the graphic files."), + p("A: For EPS files make sure to 'ungroup' all objects so they can be edited independently. + In Adobe Illustrator you will also need to use the 'release compound path' command. For PDF + files you should 'release clipping mask'. SVG import appears to have problems in Adobe Illustrator and Corel Draw and should be avoided. EPS, PDF and SVG import all work with Inkscape http://www.inkscape.org/."), - h5("Q: I would like to run BoxPlotR locally in an isolated environment."), - HTML('A: We provide a pre-configured Docker image that automatically installs and configures the environment. First, ensure you have Docker installed. Then, clone the repository and run the following terminal commands inside the repository directory:
docker build -t boxplotr .
docker run -d -p 3838:3838 boxplotr
You can then access the application by navigating your web browser to http://localhost:3838.
A: We provide a pre-configured Docker image that automatically installs and configures the environment. First, ensure you have Docker installed. Then, clone the repository and run the following terminal commands inside the repository directory:
docker build -t boxplotr .
docker run -d -p 3838:3838 boxplotr
You can then access the application by navigating your web browser to http://localhost:3838.
Supports .csv, .tab, .txt, .xls, and .xlsx. ", + "Data in delimited text files can be ", + "separated by comma, tab or semicolon. Excel files will be read ", + "automatically from the first sheet.
", + sep = "" + )) + ), + conditionalPanel( + condition = "input.dataInput=='3'", + h5("Paste data below:"), + tags$textarea(id = "myData", rows = 10, cols = 5, ""), + actionButton("clearText_button", "Clear data"), + radioButtons( + "fileSepP", "Separator:", + list("Comma" = 1, "Tab" = 2, "Semicolon" = 3) + ) + ) + ), + conditionalPanel( + condition = "input.tabs1=='Data visualization'", + radioButtons("plotType", "", list("Boxplot" = 0, "Other" = 1)), + conditionalPanel( + condition = "input.plotType=='1'", + radioButtons( + "otherPlotType", "", + list("Violin plot" = 0, "Bean plot" = 1) + ), + HTML(paste( + "Violin plots are generated with the ", + "vioplot package. Bean plots are generated ", + "with the beanplot package.
", + sep = "" + )), + textInput( + "myOtherPlotColours", "Colour(s):", + value = c("light grey, white") + ), + conditionalPanel( + condition = "input.otherPlotType=='0'", + helpText("Colour of the 'violin area'"), + textInput("violinBorder", "Border colour:", value = c("grey")) + ), + conditionalPanel( + condition = "input.otherPlotType=='1'", + helpText(paste( + "up to 4 colours can be specified: area of the beans, lines ", + "inside the bean, lines outside the bean, and average line ", + "per bean", + sep = "" + )), + textInput("beanBorder", "Border colour:", value = c("grey")), + radioButtons( + "beanPlotMedianMean", "Display: ", + list("Median" = 0, "Mean" = 1) + ) + ) + ), + h4("Plot options"), + checkboxInput("plotDataPoints", "Minimum number of data points", FALSE), + conditionalPanel( + condition = "input.plotDataPoints", + numericInput( + "nrOfDataPoints", "Data point limit: ", + value = 5, min = 5 + ) + ), + checkboxInput("showDataPoints", "Add data points", FALSE), + conditionalPanel( + condition = "input.showDataPoints", + radioButtons( + "datapointType", "", + list("Default" = 0, "Bee swarm" = 1, "Jittered" = 2) + ), + sliderInput( + "pointTransparency", "Transparency of data points", + min = 0, max = 99, value = 50 + ), + sliderInput( + "pointSize", "Size of data points", + min = 1, max = 20, value = 10 + ), + HTML(paste( + "Using the beeswarm package.
", + sep = "" + )), + textInput("pointColors", "Colour(s):", value = c("black")) + ), + checkboxInput("showNrOfPoints", "Display number of data points", FALSE), + conditionalPanel( + condition = "input.plotType=='0'", + checkboxInput( + "whiskerDefinition", "Definition of whisker extent", FALSE + ), + conditionalPanel( + condition = "input.whiskerDefinition", + radioButtons( + "whiskerType", "", + list("Tukey" = 0, "Spear" = 1, "Altman" = 2) ), - conditionalPanel( - condition = "input.tabs1=='Data upload'", - h4("Enter data"), - radioButtons("dataInput", "", list("Load sample data" = 1, "Upload file" = 2, "Paste data" = 3)), - conditionalPanel( - condition = "input.dataInput=='1'", - h5("Load sample data:"), - radioButtons("sampleData", "Load sample data", list("Example 1 (100,76,16,76,41 data points)" = 1, "Example 2 (3 columns with 100 data points)" = 2)) - ), - conditionalPanel( - condition = "input.dataInput=='2'", - h5("Upload delimited text file: "), - fileInput("upload", "", multiple = FALSE), - radioButtons("fileSepDF", "Delimiter:", list("Comma" = 1, "Tab" = 2, "Semicolon" = 3)), # , "Space"=4)) - HTML('Data in delimited text files can be separated by comma, tab or semicolon. - For example, Excel data can be exported in .csv (comma separated) or .tab (tab separated) format.
') - ), - conditionalPanel( - condition = "input.dataInput=='3'", - h5("Paste data below:"), - tags$textarea(id = "myData", rows = 10, cols = 5, ""), - actionButton("clearText_button", "Clear data"), - radioButtons("fileSepP", "Separator:", list("Comma" = 1, "Tab" = 2, "Semicolon" = 3)) - ) + HTML(paste( + "Tukey - whiskers extend to data ", + "points that are less than 1.5 x IQR away from 1st/3rd ", + "quartile", + "; Spear - whiskers extend to minimum and maximum values; ", + "Altman - whiskers extend to 5th and 95th percentile ", + "(use only if n>40)
", + sep = "" + )) + ), + checkboxInput("addMeans", "Add sample means", FALSE), + conditionalPanel( + condition = "input.addMeans", + checkboxInput( + "addMeanCI", "Add confidence intervals of means", FALSE ), conditionalPanel( - condition = "input.tabs1=='Data visualization'", - radioButtons("plotType", "", list("Boxplot" = 0, "Other" = 1)), - conditionalPanel( - condition = "input.plotType=='1'", - radioButtons("otherPlotType", "", list("Violin plot" = 0, "Bean plot" = 1)), - HTML('Violin plots are generated with the vioplot package. Bean plots are generated with the beanplot package.
'), - textInput("myOtherPlotColours", "Colour(s):", value = c("light grey, white")), - conditionalPanel( - condition = "input.otherPlotType=='0'", - helpText("Colour of the 'violin area'"), - textInput("violinBorder", "Border colour:", value = c("grey")) - ), - conditionalPanel( - condition = "input.otherPlotType=='1'", - helpText("up to 4 colours can be specified: area of the beans, lines inside the bean, lines outside the bean, and average line per bean"), - textInput("beanBorder", "Border colour:", value = c("grey")), - radioButtons("beanPlotMedianMean", "Display: ", list("Median" = 0, "Mean" = 1)) - ) - ), - h4("Plot options"), - checkboxInput("plotDataPoints", "Minimum number of data points", FALSE), - conditionalPanel( - condition = "input.plotDataPoints", - numericInput("nrOfDataPoints", "Data point limit: ", value = 5, min = 5) - ), - conditionalPanel( - condition = "input.plotType=='0'", - checkboxInput("showDataPoints", "Add data points", FALSE), - conditionalPanel( - condition = "input.showDataPoints", - radioButtons("datapointType", "", list("Default" = 0, "Bee swarm" = 1, "Jittered" = 2)), - sliderInput("pointTransparency", "Transparency of data points", min = 0, max = 99, value = 50), - sliderInput("pointSize", "Size of data points", min = 1, max = 20, value = 10), - HTML('Using the beeswarm package.
'), - textInput("pointColors", "Colour(s):", value = c("black")) - ), - checkboxInput("whiskerDefinition", "Definition of whisker extent", FALSE), - conditionalPanel( - condition = "input.whiskerDefinition", - radioButtons("whiskerType", "", list("Tukey" = 0, "Spear" = 1, "Altman" = 2)), - # conditionalPanel(condition="input.whiskerType=='0'", - # numericInput("TukeyRange", "Define whisker extent (x IQR):", min=0, step=0.5, value=1.5) - # ), - # conditionalPanel(condition="input.whiskerType=='1'", - # HTML('Spear - Whiskers extend to minimum and maximum values.
') - # ), - # conditionalPanel(condition="input.whiskerType=='2'", - # numericInput("AltmanRange", "Define whisker extent in percentiles (ie, '5' means that whiskers extend to 5th and 95th percentile):", min=0, step=0.5, value=5) - # ), - HTML('Tukey - whiskers extend to data points that are less than 1.5 x IQR away from 1st/3rd quartile; - Spear - whiskers extend to minimum and maximum values; - Altman - whiskers extend to 5th and 95th percentile (use only if n>40)
') - ), - checkboxInput("showNrOfPoints", "Display number of data points", FALSE), - checkboxInput("addMeans", "Add sample means", FALSE), - conditionalPanel( - condition = "input.addMeans", - checkboxInput("addMeanCI", "Add confidence intervals of means", FALSE), - conditionalPanel( - condition = "input.addMeanCI", - radioButtons("meanCI", "Define confidence interval of means:", list("83%" = 83, "90%" = 90, "95%" = 95)) - ) - ), - checkboxInput("myVarwidth", "Variable width boxes", FALSE), - helpText("Widths of boxes are proportional to square-roots of the number of observations."), - checkboxInput("myNotch", "Add notches", FALSE), - HTML('+/-1.58*IQR/sqrt(n) - gives roughly 95% confidence that two medians differ (Chambers et al., 1983)
'), - conditionalPanel( - condition = "input.myNotch", - HTML('The notches are defined as +/-1.58*IQR/sqrt(n) and represent the 95% confidence interval for each median. - Non-overlapping notches give roughly 95% confidence that two medians differ, ie, in 19 out of 20 cases the population - medians (estimated based on the samples) are in fact different (Chambers et al., 1983).
') - ), - textInput("myColours", "Colour(s):", value = c("light grey, white")), - helpText("Colours in HEX format can be chosen on http://colorbrewer2.org/") - ), - checkboxInput("labelsTitle", "Modify labels and title", FALSE), - conditionalPanel( - condition = "input.labelsTitle", - checkboxInput("xaxisLabelAngle", "Rotate sample names", FALSE), - textInput("myXlab", "X-axis label:", value = c("")), - textInput("myYlab", "Y-axis label:", value = c("")), - textInput("myTitle", "Boxplot title:", value = c("")), - textInput("mySubtitle", "Boxplot subtitle:", value = c("")) - ), - checkboxInput("plotSize", "Adjust plot size", FALSE), - conditionalPanel( - condition = "input.plotSize", - numericInput("myHeight", "Plot height:", value = 550), - numericInput("myWidth", "Plot width:", value = 750) - ), - checkboxInput("fontSizes", "Change font sizes", FALSE), - conditionalPanel( - condition = "input.fontSizes", - numericInput("cexTitle", "Title font size:", value = 14), - numericInput("cexAxislabel", "Axis label size:", value = 14), - numericInput("cexAxis", "Axis font size:", value = 12) - ), - h5("Orientation of box plots:"), - radioButtons("myOrientation", "", list("Vertical" = 0, "Horizontal" = 1)), - conditionalPanel( - condition = "input.myOrientation=='0'", - h5("Y-axis range (eg., '0,10'):"), - textInput("ylimit", "", value = "") - ), - conditionalPanel( - condition = "input.myOrientation=='1'", - h5("X-axis range (eg., '0,10'):"), - textInput("xlimit", "", value = "") - ), - checkboxInput("logScale", "Change to log scale (only for data >0)", FALSE), - h5("Add grid: "), - radioButtons("addGrid", "", list("None" = 0, "X & Y" = 1, "X only" = 2, "Y only" = 3)) - # numericInput("boxWidth", "Width of boxes:", value=1), + condition = "input.addMeanCI", + radioButtons( + "meanCI", "Define confidence interval of means:", + list("83%" = 83, "90%" = 90, "95%" = 95) + ) ) + ), + checkboxInput("myVarwidth", "Variable width boxes", FALSE), + helpText(paste( + "Widths of boxes are proportional to square-roots of the ", + "number of observations.", + sep = "" + )), + checkboxInput("myNotch", "Add notches", FALSE), + HTML(paste( + "+/-1.58*IQR/sqrt(n) - gives roughly ", + "95% confidence that two medians differ (Chambers et al., 1983)", + "
", + sep = "" + )), + conditionalPanel( + condition = "input.myNotch", + HTML(paste( + "The notches are defined as +/-1.58*IQR/sqrt(n) and ", + "represent the 95% confidence interval for each median. ", + "Non-overlapping notches give roughly 95% confidence that two ", + "medians differ, ie, in 19 out of 20 cases the population ", + "medians (estimated based on the samples) are in fact ", + "different (Chambers et al., 1983).
", + sep = "" + )) + ), + textInput("myColours", "Colour(s):", value = c("light grey, white")), + helpText(paste( + "Colours in HEX format can be chosen on ", + "http://colorbrewer2.org/", + sep = "" + )) ), - mainPanel( - tabsetPanel( - # Welcome tab - tabPanel( - "About", - HTML(' -This application was developed with Nature Methods and you can find the publication here. - The BoxPlotR has also been mentioned in this editorial and this - blog entry. Nature methods also dedicated a - Points of View and a Points of Significance - column to box plots. We hope that you find the BoxPlotR useful and we welcome suggestions - for additional features by our users. We would like to thank everyone who has made constructive suggestions so far. We will document the addition of new features in the News tab.
-This application allows users to generate customized box plots in a number of variants based on their data. A data matrix - can be uploaded as a file or pasted into the application. Basic box plots are generated based on the data and can be modified to include - additional information. Additional features become available when checking that option. Information about sample sizes can be represented - by the width of each box where the widths are proportional to the square roots of the number of observations n. Notches can be added to the - boxes. These are defined as +/-1.58*IQR/sqrt(n) which gives roughly 95% confidence that two medians are different. It is also possible to define - the whiskers based on the ideas of Spear and Tukey. Additional options of data visualization (violin and bean plots) reveal more information - about the underlying data distribution. Plots can be labeled, customized (colors, dimensions, orientation) and exported as eps, pdf and svg files.
-BoxPlotR code can be run locally via GitHub. You can also download and install it as a virtual machine (see GitHub and FAQs for details).
'), - h5("Support BoxPlotR"), - HTML('Please consider supporting the development and maintenance of BoxPlotR with a donation.
'), - h5("Software references"), - HTML('R Development Core Team. R: A Language and Environment for Statistical Computing. R Foundation for Statistical Computing, Vienna (2013)
- RStudio and Inc. shiny: Web Application Framework for R. R package version 0.5.0 (2013)
- Adler, D. vioplot: Violin plot. R package version 0.2 (2005)
- Eklund, A. beeswarm: The bee swarm plot, an alternative to stripchart. R package version 0.1.5 (2012)
- Kampstra, P. Beanplot: A Boxplot Alternative for Visual Comparison of Distributions. Journal of Statistical Software, Code Snippets 28(1). 1-9 (2008)
- Neuwirth, E. RColorBrewer: ColorBrewer palettes. R package version 1.0-5. (2011)
Hadley Wickham and Lisa Stryjewski: 40 years of boxplots
'), - HTML('Kristin Potter: Methods for Presenting Statistical Information: The Box Plot
'), - h6( - "This application was created by the ", a("Tyers", href = "http://tyers.iric.ca/"), " and ", a("Rappsilber", href = "http://rappsilberlab.org/"), - " labs. Please send bugs and feature requests to Michaela Spitzer (michaela.spitzer(at)gmail.com) and Jan Wildenhain (jan.wildenhain(at)gmail.com). This application uses the ", - a("shiny package from RStudio", href = "http://www.rstudio.com/shiny/"), "." - ) - ), - # Data upload tab - tabPanel( - "Data upload", tableOutput("filetable"), - h6( - "This application was created by the ", a("Tyers", href = "http://tyers.iric.ca/"), " and ", a("Rappsilber", href = "http://rappsilberlab.org/"), - " labs. Please send bugs and feature requests to Michaela Spitzer (michaela.spitzer(at)gmail.com) and Jan Wildenhain (jan.wildenhain(at)gmail.com). This application uses the ", - a("shiny package from RStudio", href = "http://www.rstudio.com/shiny/"), "." - ) - ), - # Boxplot tab - tabPanel( - "Data visualization", - div( - class = "controls-row", - downloadButton("downloadPlotEPS", "Download eps-file"), - downloadButton("downloadPlotPDF", "Download pdf-file"), - downloadButton("downloadPlotSVG", "Download svg-file") - ), - div( - class = "plot-card", - plotOutput("boxPlot", height = "100%", width = "100%") - ), - div( - class = "table-card", - h4("Box plot statistics"), - tableOutput("boxplotStatsTable") - ), - br(), - h6( - "This application was created by the ", a("Tyers", href = "http://tyers.iric.ca/"), " and ", a("Rappsilber", href = "http://rappsilberlab.org/"), - " labs. Please send bugs and feature requests to Michaela Spitzer (michaela.spitzer(at)gmail.com) and Jan Wildenhain (jan.wildenhain(at)gmail.com). This application uses the ", - a("shiny package from RStudio", href = "http://www.rstudio.com/shiny/"), "." - ) - ), - # Figure legend - tabPanel( - "Figure legend template", h5("Box plot description for figure legend:"), textOutput("FigureLegend"), - h5("Further information to be added to the figure legend:"), p("What do the box plots show, explain colours if used."), - downloadButton("downloadBoxplotData", "Download box plot data as .CSV file"), - h6( - "This application was created by the ", a("Tyers", href = "http://tyers.iric.ca/"), " and ", a("Rappsilber", href = "http://rappsilberlab.org/"), - " labs. Please send bugs and feature requests to Michaela Spitzer (michaela.spitzer(at)gmail.com) and Jan Wildenhain (jan.wildenhain(at)gmail.com). This application uses the ", - a("shiny package from RStudio", href = "http://www.rstudio.com/shiny/"), "." - ) - ), - # News - tabPanel( - "News", - h5("April 16, 2026"), - HTML("The number of concurrent sessions has been increased to 50.
"), - h5("April 8, 2026"), - HTML("The shiny server backend has been updated. The number of concurrent sessions has been limited to 15 and the session idle timeout set to 10 minutes. We are currently reworking the code to support the latest R and shiny versions, plus preparing a system upgrade of the server.
"), - h5("January 17, 2021"), - HTML("There are several recent updates. The jitter of points is now consistent for all samples. When - data points are added to the plot, the size and transparence of the points can now be modified with - sliders. The link to one of the boxplot references has been updated.
"), - h5("June 11, 2020"), - HTML("The sample names are now displayed as they are in the input, ie., spaces and special characters - are not replaced with underscores.
"), - h5("January 11, 2017"), - HTML('If you experience problems with this boxplot server, there is an alternative BoxPlotR mirror - available at boxplot.bio.ed.ac.uk.
'), - h5("July 23, 2014"), - p("Upgrade to R version 3.1 and shiny-server 1.2"), - h5("March 18, 2014"), - p("The user can now choose the color of the data points. There is also an additional option for data - point display: data points can now be randomly jittered. - A small bug in label display was fixed. Log scales can now be used.") - ), - # FAQ - tabPanel( - "FAQ", - h5("Q: I have trouble editing the graphic files."), - p("A: For EPS files make sure to 'ungroup' all objects so they can be edited independently. - In Adobe Illustrator you will also need to use the 'release compound path' command. For PDF - files you should 'release clipping mask'. SVG import appears to have problems in Adobe Illustrator - and Corel Draw and should be avoided. EPS, PDF and SVG import all work with Inkscape http://www.inkscape.org/."), - h5("Q: I would like to run BoxPlotR locally in an isolated environment."), - HTML('A: We provide a pre-configured Docker image that automatically installs and configures the environment. First, ensure you have Docker installed. Then, clone the repository and run the following terminal commands inside the repository directory:
docker build -t boxplotr .
docker run -d -p 3838:3838 boxplotr
You can then access the application by navigating your web browser to http://localhost:3838.
This application was developed with Nature Methods and ", + "you can find the publication here. ", + "The BoxPlotR has also been mentioned in this ", + "editorial and this ", + "blog entry. Nature methods also dedicated a Points of View and a Points of Significance", + " column to box plots. We hope that you find the BoxPlotR useful and we welcome suggestions for ", + "additional features by our users.
", + sep = "" + )), + h5("Support BoxPlotR"), + HTML(paste( + "Please consider supporting the development and maintenance ", + "of BoxPlotR with a donation.
", + sep = "" + )), + h5("Software references"), + HTML(paste( + "R Development Core Team. R: A Language and Environment for Statistical ",
+ "Computing. R Foundation for Statistical Computing, Vienna ",
+ "(2013)
RStudio and Inc. shiny: Web Application Framework for R. R ",
+ "package version 0.5.0 (2013)
Adler, D. vioplot",
+ ": Violin plot. R package version 0.2 (2005)
Eklund, ",
+ "A. beeswarm: The bee swarm plot, an alternative ",
+ "to stripchart. R package version 0.1.5 (2012)
Kampstra, ",
+ "P. Beanplot: A Boxplot Alternative for Visual ",
+ "Comparison of Distributions. Journal of Statistical ",
+ "Software, Code Snippets 28(1). 1-9 (2008)
Neuwirth, E. ",
+ "RColorBrewer: ColorBrewer palettes. R ",
+ "package version 1.0-5. (2011)
Number of sessions increased to 50.
"), + h5("April 8, 2026"), + HTML(paste( + "The shiny server backend has been updated. The number of ", + "concurrent sessions has been limited to 15 and the session ", + "idle timeout set to 10 minutes. We are currently reworking ", + "the code to support the latest R and shiny versions.
", + sep = "" + )), + h5("January 17, 2021"), + HTML(paste( + "There are several recent updates. The jitter of points is ", + "now consistent for all samples. When data points are added to ", + "the plot, the size can now be modified with sliders.
", + sep = "" + )) + ), + tabPanel( + "FAQ", + h5("Q: I have trouble editing the graphic files."), + p(paste( + "A: For EPS files make sure to 'ungroup' all objects so they ", + "can be edited independently. In Adobe Illustrator you will ", + "also need to use the 'release compound path' command.", + sep = "" + )), + h5("Q: I would like to run BoxPlotR locally."), + HTML(paste( + "A: We provide a pre-configured Docker image. First, ensure ",
+ "you have ",
+ "Docker installed. Then, run:
",
+ "docker build -t boxplotr .
",
+ "docker run -d -p 3838:3838 boxplotr
mrMlGmCy9*WT)s)V2^WMIsQHm_!YcVMB^$hl;UroP7rxx|+f>r^Hw`p@DpL-;^ z!;KNhY6*!oCFWAB9KM2dj`BtcZ)cG@Y3~be$?M9zp5N+l&h|z@N!ybQ^8L)N-&S(r z#+a^&MBlYqmDn?=NLIHDes9X2=sF}s)JG@7Ogk~5wW=`$e4|Yd)it~K;VXv}Y{?hb zB$s@y#y>pBeM{Vr(~}jm;vcv!$)tcMjAXjuNP)?&rG(~z9*a?#8-Z$Q)5&AUOuXP+kdrcP?n1$yhii$T@?B_ z4zt&BxI56?nepcGFLcXC-=iA3WC0J6%Qp+$X<_x>gHvqZy?8(U{q0*H9!9*#=7mzm zr25;nwvNBS7G%^fo~%lxtrX`I?cNwyXO80fvB(^E{fDUtPtGMcwcL2bZx#+){*3|3 zr}mh0BK+0B&kZV@Y_ERGUTQYkSHB@!I7ZV9yfoZ>of2W{j)SVkG98knk1J@Q3QmI} zq!Vwm;X*wVZ$z8_LBF@uCWGn)qG!Q0OL}Mq+K3xw<#jxrmJ!1#wqd$K z0Pe_yV!sxxW{PL??rlAWV*@tDc-KMtZ!O9n)eTnL52f+)f;PFavdEkQQ~U&sDCBkh z+1}5{toJ YavqnLH#0j62j)+rfy$*Dv9e%j@2QIZwf$;V97$p z{vohT2 C^V zra1##_cB7o&61=b>OIxY5UTm1WPONR?iYm~))?~F(p{HT+?*-<+rd+>BgjF^Fc?9T zT9 -*>R;$UnFgEl(sT%dE!o~@39qxzmcL0qqkoAx$j}#@ jJ!gOY<@i(*wiy7)R%yyR(~;G>=*?gxInTc z)P>o&$%sYH9@OuVEU&(MGi5t_$3TU%S+Phg4TuqZLB*SS;b}@TYtOBQd2s+9)Xn)t ziGhedRWD^p?l80%$@!%9Gt(R5c}X@a|5c1eeU%Hlzjgnl)j;!^FKgftn0)U_ m-|P(jD- zzHQUSy{+?lxM#Dwyz67WO9!l*jf|!c8+>V&qEhT4WF`bVpLN0|s9$r^3&WlF$6E?t zZ0!<9G=YZBd;4G0qm9zVA4L5S^goI(U~C`d!Yp0 qv@txmU#1_FJjb-6eVG&IJjsG1a7Rx8$l0M{|9DA25%kLq=v5u~+> z=u ->;p#%n`RfySg{o(GD4&LIBL($3M6rKr0kQiJj@9wk)<>E^oa* z&f#ph>JTYUY+p@}J{t;~@wZxKZtDZaTx@;)>aKg@0F+MY3UnKn)@y0nh>|HgZ)Bap zbw*Kbm+xpRw-S<+m1OwAb6N{t2i!}i+sjD9-Vw}B4BTM+;vj7MVdb15OzvaH09p@P z?61dGy~`4%2O(8TQ8>!F5stJJ6p!~Sk|IFPHX_KaY>97L?3F8c<^1J6Lw*jot~N$K zKeY+4U3 `0Pv$q!+p9La;$-eG{;8v9fQZr~drV4X@A zZWoO~pydOPi+b7EobpiRQr<*P{t u$#fu({5SC&WuzO#y$le9+@9+E!2gmUDF2Hx#MX5!)cXqK7faxSz3MQBXJ>uB zCEH$8?`KPY0om{h&2jkNntLOG6^0KLt@5(;by|daJZ5&es+(hPcYKStlzc$kZ<&f} zMg;VN9OMJ`NB5lb1>5#wHckCKmLu7arH(2%8MaDP1s_`P;$-f6a% Oh61x0fG)>v~^*K!gve+(wiV zkQ0CpQl6`f$keu`E#+Z>Qt|ixuMvCYB}JUjfVXUUFvg#|fs$(TiV0T&5 S4LIRSRFc0%1R2H&?OdyMNd^78wrznX<{ls*y7xct=Q3edy? zB>G$Fom}@fD1-c9C`&mOSFN>V6{gk;*^@oA^1&%U&o}tm@ugNlMH)4*)xVn2mSuEY zUq$K6P~*RUy;&iD{Nl`!Y?l>VJ>j*m-@2d`aePyZotu-z H0;3p b_ zuS5gJ#x&ynz;QY3L*V(K0n*>o+4FbPOkM=2{ud69%K2m33^`THx=Q zNo{JAiPn;FTMM h!LNK=v$~ohlXgo32SMUYsQ+nwCHf zY9l?OnOYBhd0FLMLp)*VY7O1 #>}ssp3J{ox1lD zpAq=6GY7H=IY~rM6R=`Yi4-absk55Uej1mBlXBAo;MQlF(0x&-zqHxLg%|^fzL~U7 zpf>FYWa~KVG*mAz(8p%8b<;Cz;#|O97JI6{cCJtvF&`L0mq|!59-J+>4fD~gK)$v1 zV|m}6*k-oXc<$HPRy}hDYpvSJNp1h=NC; ^tV^J&V 8Jgjh zdRJj1d5L?qSBjnmJL_0bCJFyeJLwDq+7mm>99SjnggAx3#scdAYLhyP#)norJDwf) zKGynO1ZNYpTCbu=TB&%v0u*Naj@=*uJtDQ >?bhyLqbFn!(fSGb7|qpJUx@O7`FM37aK1 z()uH+`y$4uZ5aFnGuY^V(6$r=m=Bzw>6IgNZSWSf#7>;`G<(jl*1F*$uWJN*i;T3M z`IQ|C=~oomd#-#Ttd%$q8MJJS26|;+FwqF-R><<2m65ZUD>k!^m5eA5MvMyD@9{p8 V>76+e{VdaUl z6C&l8X9MdGycezANfwZcZHV#mJtm7_O%N`fzZuzf5o_eE(ySYBkqZ+xt(7i)^~F;q zhA>15I1RswHEhfGnx&&Kxj;B0n@)M^m$6^6JMDI61LIi9_Y-Tfz|BBVz@*L_TsNTQ zx23Vwyu_o7b<0h{l+{ct3R9}R-g8ik9cGC!#{SkT=)0lp)OKFUo8{~3`P-6Q;APZo z@_69ZoC$b!_?y4p9~wWk(7@&s)U27F-dl_PQoM1}nJPTDwzc;bzQ%0pRtlMYSAu z*8Jpej)?3jVG}Dm wT-vdO@svNOHMD-<(fO&d)`&Le3JOS%+nHSpmDhdPI? z69qVNBdhr}etBm2m;uTpwY8QFKG?YGwW0GzASiQdLn2ej3vLgD-R?{Hx=q5H4(L$< zk10c1yziIc`)xq@oz?TWTsb)GEWe4-IY99?NXta-)9m5-KHEmcCn65kIzO_y4Zk2H zD=@qtt|;TVI3xv1*wUdzJ$5PFbthOcv!2OnMjg4naNGoqvAv&u7Dyhmfi9t-U2x2n z3z20Ulp$efgiMzL*R%nK-evJ3ax%Wh&1hmEJQ2+(n9;DVB^s6TNsqOJXXJy&j%ZjG zc#)&iPuIk^b4g@a|BeP40b3T|to5FrH|tmi%-f((dxZnhweBKqiNMfyrO*~bmP3Iy z<^A7!a4-hPm`ua$x*q``{SEVCY5TZbPeK9y#Q{eF9McV77(}Eht*c*V!_An!6~-~e zhq9i2KTxn;mT*5Ux4gmHwmRw*w|u;;E^j3DF@z%->~pe#vzI^pLvRwQORV{$migx4 zr>N!QLv=V47N_ u9%P4vnX@KQa!GG{P6aO2+i5 BYP RC{tpx|t zfcb$$G*Uw+tLe<*X<%Bcr5jz|!qLI~cY+ob(XWcF!VBkjrt^bhU~Au+4wh=!DzBTZ z=5kxALdBd0KiLLRQyVq!-@PHWceqQAOGdJ% D5;IodQk16^^)NtV4a52ONSyRowJ zfy4w2h!-)XHsrcT+rcq58GZ(pVZ-g}4Ie>-ji)?^dE=HK$!19iBjhl?6YkWq_Jab9 zi>YS*QDK5*3&eLD4CtAhL*UGleI~=QC_;?4yw_47DBE-Jvcp8NJ;e9$XYAknY6XnB z#iv*1I>&?AX-`W^&gTJHz;K=U5YX#3)UYb_e8k-b;sGITM{^tNfw2v>s?<>jvVmLY z8uvw5rNM-_5t*+Q%cmEn1kdiY-{3lMR-6KQJYa_~bKOQyAZUqHcg_a8XtzQ79-dzH zo?Rq0R!Q#&@KPwk ? z#?bknE9jk!zEc4I$y#vgk0V|{!N(Wf13)&wOJ3u-+C3Nq+@~?|f{JTp!dfU{W_8f8 z*V9yiOLnN4tr-)qCx0IQCsg8B33$^$wOlM M=DLhE{7dc zdx^ q`6eqr`xnFEJ{&@pBV^hfRHk;LE0Iu)Qr{GT0xA>UEOZn;8*eQfR?n1kT7{ z+YD%j^$!;=0+xTBaHW^)D1y4~3_QgTgSSy!DV`zfKo)JB)it3PJzB-GnH!=V9qeM} z(X>%?OY{>~Md+hcPrG&_gs8|99e^g8Gd;xj=!Z&%vT9BIB|PXC@5FOin#U$4o`YSd z%Rl}Y>V4n#x;?BR^D`ER7}uS8Q}AQAh_LgrD?=@PpReb6e3#GK?lwGK)QF~iz2{o> zoSZimjSg_p4a*C{`-F+#Sn^m16ll^#ZPg*!WJ*4g(VvThZqf!0SwB;5iXZGN$Yc }y9Bv9s0g3i=JihOvMNqX`?i A$X%@ZY*6_Hp!`V-(2NAq7caG9Q4Lzw5qb?1_L36S`Krm_wvXW-iWi z8qxQ?JUz<{Ce{Iv(_)EA@n#3uR3=sdwIe3t+>E**msLMfZbZJ^P|bo^>D$z9jfKoH z_mMdqiy!yr6^K)tKD|;%s_bptfbL;!$XUXl`{_ 2tM*V;A~ig1leiBmIj0&8qmZWpu#Ze%S`r1O;a3R$e?>%q5FDns?+Y~ tIT(M6w! >6AV#s2eu$y_%$&0wfZ zV5@4bz0WsC j)7blB{l`LT#QtZJPG Z-FnvquEfu<=0H)U&+fgVBz9JsSM*R)Ro7l|bbCLA(SxJka=A|=9!Ub3)pUGM^f zf leMp%-g>G z$};eM-Js?Z9JkMB1I9A8gk4|&z-+fc#SjVu<@@R6T1bJMyyRLL8#&aq56d{{Ac|l| zD_JMEuQY0y!PpwG6wRS?$ut;ZI?$3j0bftk!Dc zSig8L`h=j0{rHpg+uBFoDY)+VS8wszRmT9s-+#K)pP-w29 Fe^;_F-tV=Ffte?&pAlfO|LSBW&o7&wR)%i|5@emxid>$F9i|hHU z&ix~>>@dQ0_yev)&zoXF7TUb^!2R~%--h>RF^qN!D1qO6*ijB8Z~(Eu#NP&E90y7z z4xjYV4z<`HFOZ~33{&cLu7AkPpd80ha(94C-~`7gO#@`DUs<&mpK0L#qM2E&V_W>$ z3g>vfWxqB!PGtP?MJ7DwraX4^3hrvTk7f5gXF=XQbNU??4Zj{^qVULSXuaOz(ey2F zsfLMxU*CX6qr4R{P3$n0L0~B3UM*Bs94Rn9e=@MmC>nA*mC(L7fy{_`t$nnSQ7#Gr z$Nc4+RUR3H?d;-Y)6bWU
zDH-$=g4y_x%O;N_0H%^;jh|Y7>Q$9AHFCOS8^lkOQ%@hsbw7$P-|AI^gTrSvi%J~> z*Fv=yX<8O7pI)*)l9q|md==q@XUdPa&fB 6fPl4+$fkMEKuRp4E!uQ;}>Ts04vvngCXxk4T7pI_G&ZaU!K4W|fl?a!=TGfsK0}+|bOis!7Q-|^!s2ZF zp1{Rx6MuWWnkg|p`zYQXQjb$%`6Bg>USK-s99f5!WGHB1D;>?Kcj>d5fd?M$0=Vw` z9R3FWDBqDreCKL3M~oE|kS# fhdy2#;7Qa=Jo%`EM4A&S_4W*e2foGKAG{eiT7 z!!pFv3lVE_et_LZHZNe-r)hL^gg> Dq&=$Meo^q^j$Q3~rh$8)n7XROlY|z0PqT!&S7uG4^@Mnx?ZS}u4cir| z7CEu3PT>WoX|vwSUorw4eaQux;2pO1pvQp+L%Rfg+=JFS=iU!37Ms1a^O^O(>zC6n z2n+7h06DuPYMmd?G^%j<2pDlW!&4QCt_-Z(ez1I&T>xA#%fQcuNGI3BGbbimt)p1$ zn~!Qb3EAi^5loDQcsvKO4}@NtbLT8jGn;Xg l~$Wl zJv%_$ 5PI$+bXio_IV zohD9UZQa*M+q97L5$smr6C2wZ6-0ynIa$ULNH-K{O%@{TWZz-1sS}R)lWIhLz9~Sk zH(UMo!s=$uw}N8@dRBi<>6l#$i?pMcT#s$;6+Z3>la9%!L{rf7ea{~hm3w_PZCpKx z$3d^@`1wf-r&M@Cp!IfTMtIp F!DN2A0A#@>l1fvPYot8Mao!5XK z7FBT=v~>HpykJ| @$|QEe$8^tJwsgZCbL81BO_$r7@#qVqv@r)3Q6r?O!Ya=yy;{ zzCSTG3}^z`uNG;+KcuRJdXnbI6u>K!{pC~shfGX$UJK@k-Yj2VPmp8w(#yy7VhX5u z9GVe~$kmVs&k~KC#EGWBWf|wOs@2XgH1zfDgMC78j5jD-%I1yDcH&4&gHQLK7)WmZ zeetSN7+xg-STK@`pN@`TfkFn&&zA#cxJ=LIep4W8Eob`6w|QVsovlV}Rrig`bkFjk z#QiEI%zRFX{gnF%>?yRwYku|oubthc_|B!cfYaOo+Bx@gc6WuasgsjVj5^$PK?sNe zIUb&)!5FL&=-H>Z^uqw3x&EY 3;@&ssSi3YT+#q@BhW%90l%l@y&(N;$R@u9 z6h>HkzB_QgjBiwTQZ=}k*zXLL^GGgh(k%}-Ol5@gc0z&}nbJ!9JKIm}Va>!sxq9PD zi|+3>rfEwPxYpLXBwu;_roy7jjuykkTRGAR6;f{+-%VWbDl-g3k^M|(#CFy!F{!A- zP*T(Gva>1b4`4)!GZkHNt8uNzAHHCD-hR(#FT#d#s@R5&-e9 Ca+E@ak$#@|^URRY7TkP|48X641-KdoSi(*LmknB6 z)M%-Vy!Gpx8~@R>)m% EMV*;s-N%EWB1Fwccbq9$>WXRoc%{Hr!29#CWd%F z!ceTH^qWn(;OBQywbLw%oXW2+eNs)C-U)KH|3~L3_eE1`_}gpkKZd-UcM_H3dU&X~ zzlED8^qhUsdOV+;E3OF{q<7?cxOv5)fq13~Os#-tHG>H|O2D)VutRbnW^uFKh~&C{ zfL-$1zKR@5YYo8l$4JhbCA0Em`tDUG*3Ez5KHomAhduLTo&jBSX&X7R`85P=4`es4 zE5x~pWSJ6HoqHd8{W0W1pM@3<)0gB^vP3uUCS=1&v(+R#w$*tkMZ%ewd)gZ}M^4^A z7qjLR$Yy)Dit|Oj-e}fVOcJRLyOc`Ctr}+GZDuHX&zlUl7wrq=>frd)WcU%nadq4( z`GbG&jDkC-?H5{P^MHVJ%Q=}b2_Yb8qVzltS`l8(ul@D>zmqu;5Es?$L0pu4Gw6<@ z136V>n$*sef}oNybQ}vj4$lrXY}l~dkY)T47f9h%UzN@h#eTg2xz `P?-T2mJz8BYm&p{7IFid0a99fWGtk?h(rpUD7Kn*g%`Wn- zp(=(Dh*F)Q*PK*Qnn|$=U?e)=ou4OP#Y0`v_LvQu?}n{HSW;3uq-7=AT!}g51%Fb% z_lV5Fh~ARadL|Z3!Zb(u|6N{iB<>G5AD4yg*V}_Y7v&UL4a86xJ2nHI-Df1RUJz3= zhD=-1d~o~0)16?nJPwxp0qEF2K!jT@eZ0^F;#Un+i?8i{Ao$6fk(K~phvV9r<)#)D z$vMBZer}DkiandEkt~_Sf+cT1ox9`$+9*EX6^!yGvS}Ec$Oq+{|MG(T|ha!!oY3 zE5kmAX{J@V9S`Mix-r!a17IF6Qk3|2nh<4rrl{GgaYDb6%zyO~HoD?U>oHGKx0w}2 zQ~@c7?Z$wv6a_HqnZgL%1bm*WBbO~tEId`AF>>B^WP@OmiY5w-&nLHdk*zv{+q-g^ zs!kQd?s4*Mk-FwxhP-UGaE=AXyBg@PAU1TbfHMR;rN;)2DLvswI5i%C (aZL9@$lL|s=4{Anh>pjR%^YV zIh#ttSgO(&e_kv7ktAZZe#u|_?I>pkzRFST*;!Tore)c5oTxq&lpC`+eFv1dhWov* z6Vo~vE=9wCO}U&ietd7@`LE+|=B!7ZS0y*6sK%ke&0#OMzV7U8T>8mvN*Biy?gQ+u z=QNmpA!S6a9p8GSttcj|i1taZ>xr-O-T1;D68*%V+|+M4_`NxGtLRcu0(;%-q_3@% zVBM=rA}Z_xd0Z)9k5xMFvRBc>-%3jVxDZnKD+ z4B0Mz`Ym;MT#r|d(r!*`l-&|v?OTt0!ylvfrfTq7(%iT7!^c5P)7rSs_;jR%`4{Jl zolAvJ-BooSNMHJ%6f!EP@#79bR=0HTHiSRq(n$3cx&eC8>#mUn``EXZf<{C6y`K*euwR4K5J6rBC`+bMfke)rw= zZBC)8uAgDH&rdg9g3`$HTY&CEr?;)Yl V_16+qT1XpzrQbre~tvYzwB>Q>tkEdO7D5GH?BVutYsyBSB+=f>i*>WigbYCPhy zB^bY!kbK{3{Y1P 8K z2PEzLC$pEf_2{!^J)2y3^JUS37MGYuT`^QRMc@63C#E?9@FyL-*g;Lr-4q+?8ofcN zwT4}##L~Oy&%;N-KDonGHKN@q#A?<{ zGkXK=dR>$LunJb_U-uHNWr}^Z@ckBd=st( %W)^a4(O?HpKB*5F|6g%VPT)$` zAo-zi e!)dp!Cn=I<_4I9A^ 5PTTX;M!Hs z L8# OV)SP9=7CC<&uP=E&n m|=8b@HB`Z!io!I$t;i1(VFC$aY3@H}yWe-A^SO4S!q-x~1`>Sca}l z^V#M##jY#vOhzJnLKc@~N9C^ToaSAlxGSHmho$@}g?wPv-+Vc{*!`-K{C@ ?WZB97^`cfPvC|LC >zyYw6r|h`FAm|*EFHFxRiqbh;@Q#*MsjD0 zPb;@GRQBZFdp^eZHhh;5o Ip}YL_MoR3vM|-}X#v^?yz1sD3d>q!4_5jqUBg>1P(TEB?Q#0$eAU7WxCa!qe7D z?j_dzG#^8A5;dOL=|2rlA#XPSjM1E*i77$fLFWhm;FkpP(TJ@2SiXEsE=|>EF>XIC z yPY82KTh@itq=te+ha$+cB#f$@DM} z_S0&t-q4ROB=UqJYIpIN+cFY00Q%;%HZV?}m#qRt-P0~O)+wLJuhtCAq8*R33ehqC zk=l*dqzZ4EXVHg>v-6vzG *@;)ZpJ2JY}H^KiwgH2getZm9>~TN6Gs~BjAZA4e|}oWr8xF)P$>r zFwR8Wl HZuU{>iA}hkUb8|X13K?Eh2vh&;kh*bBQ1(gau$eBp?p)T} z(o_>b#xJyaI5~>Kw(inva1A$c`AsR-rc`izmDc(dUs+b!U~Jf0_&v)C#biE~V(PbC zI-sK86dRNLYE4{CzNuChTV%ax{x24A^F0^YuIK+8IU~W4lGw)}Zqc}~(c7Fp#Vs}+ zYOV9?H_EH^8y2Ix4sMSFZ<05XO*0b!R6bD?^~qBGCc;2UoRlzXyngfXV`m
HhE% ztxwEk^D@D+&^EJOBX{3O#c_5eGU7s4C>Aa{FD{xo7_^tNF-=II&yCVlxdVFrpWwP! zFi=Rrl}V9fs-F^y3*{>c= s&@XSjM4fKFOD`1v zLT4^&8Jai>jOM$FNq5i&NZD$9pRj$S*q^jct)u13ZO}D4-)CrS{1p5VMfHt^`KRL@ z^OTLPOHYmt^2vr`2OlT?(Ko+&fBt?_D3XuoX$K1CL*Jr EwYIQ@gpc ziW4ryPqs+hca3II?kxFShw;g44!gbQGHmgGy;LqJ>{z+uwP%$kn7&XR)ze4JOMas> ztSuyTGwJBv5eo}CmgVo|RQah}ATbiP@x#4Gi{^T6UDFfFEpmZ98C*ZAR*Ym)%bV1A zwU _3ZtW@^|9 Z u+8NKlLU5Ge)_*a@~`sk^YgCv?BCP^vbd@ z3)#me2O8wrS81=t?$=om@x!9{{NwG{p;X+zj9djPOvcqLjqg68vlsNsy_ 3OCr`(U?uyTOB2IvK~_S`IdbAFfk zK=~o(^AfJ#_1cZK8{2hF&APm7>@c33FsdF0?l_72s8r^g36Ff~;l)l}9Er-neS6k- zuhUi1zO#?Bca**KGjz55AfB)Psqmg~jCi>_mo0Md&1X>J=qo+#&KD;0E6>$Zmy_-7 zPH%lSdb#_*T=LO?1`1*FpxtNRl2F+w9c^cJNX=vF*zD+YqrKGL(U;}dO0Qo%Yd-t` z7< VMUl;@TdG595Jmy?;9lscZ0(Vnf$Hmfl4Oixe<`=4h>wV)uINYQB1;`7U z7QigWiwI{UFb`z_tu2f%JK-{qTA8W}=XE3xa8*1YI}PyKc(%1^vJ9kd2#ySky$*x7 z^AQias eagpA&Ff`1_MaG OOMG5jK*GXpaaP`c zea6`#u7MRPD9cfUQ3+hE`s=6>+<6N>`JAFD9c{;gq>Ldv?2_11e)6X;X3-7N&D6o| z^7ZoWf0n(|5_tyj?Omf+?A#-N0t|rQ%fY-$I-c(f>T`gbHuwI^S!UQ54gkqS992({ zP|lnbh+(hF0->PE7pSu}I45|xynoULLL`Z!K1FdQB93wP6o%5SApogZnDgkDU{BWf z;zEs&ooE@>&<7*^*b71#Df;0osT<@FX)gw2=J8QKjBVQ;hJTyVl(mV71B?IEspbu+ z5v%D7ygDF|(RnsQR$*@K8Tq$Sj$G^pO 0Ag`fAuGiYM#hUEEeK2T}2FJmdB sr)Af z{pVj3sm-m*>>Pt)7jg&OC~`TP?OF}bAb2c=uAl_9JUqZApfn1QX@%r+$VrRuE4?dX zB8RGwxJ2I9d7?y3#!JE-+SzKDz#+rgfpSc&ibj~TeX{R^ =_8!<%sDNOMq6H|RFkZ_}7J+_v~vv7Y+DZZ5F1G+)PlL8=MG0BQd% zz9>m&Ikp#v4i@Vw|LQpeIDQAe*OgX@bISSX7nP?b$f@0ysjkuD&UC5*V1J$65*lwC ziQyjPh!{UYR;-uBY)*DEn@>%ONzWBS842K#6h=vayb*u+1~?G)pa@FZn!coJER=XE zs_5lAVC zHT+Bj$p6Iv{s~g@VIehYHr +$z+VF9VD5-WkhV!_{E z*;(_oT!ZNg%VM20t6mR6UW|Q7MdSb`smxS<9rh_O$BHA=&y|FRybWLcLET@@Gn?8Q zQn pg)*B%?v~36O4-N@$-aG zkcr8iY=;mVs9)9qPvKC8B_| ^B#Q 8zIqQ?X7S8J%qz+ioU$pH` $%L7*OIkCFwWm-<_JA2z-aAx$^e*_gX>(aqYUGvJA~Q(oAQE*S@?8+U)Krk zqhlQY(0lfg#-Gn0zw{peAEJwa T25#0WwicCSx6c38sU&P~s@XIfpe z2yV0NUNlYROQr1(L&@PQZx5@L5Hk{BsRO4;$~a>FzZuq(E12L6TBhd(i#a?&NL*j= z@;RtUu&<(f6$>tX0t#Pj(>K4(*83z|I-F%Pmp%d-1boop0>Eck-_MzoOTXG2QMnWU zv|KJ1tE^{MHG&d?clVkQaQOBMguJv2nhJLIL-i)w!;SWDVt4v(AMM}&AHQIg&O>hT zB#*i<&cmc+Ma7D6=vlAOugL$hK*xh0nSWVk1uU6eg8?GpBSPTt&9U}Na4-E9FI{{m z?_~S~CmE-kMRR=1S;$cw6hwZL3^+t0)d3TFAt1OqKnaos$N&tTA{}`xZ(|L0Qne9; zv|ke|C!px29u~5Qz|u7`RYM}a!4YV q_G145|CiKQ#?lc<^}sG_iWEE;Lu_=&WSMk7Z6*`ZQ}w23E>o|10f9S#EG%4+2> zJf8XA43J0v_Pt*-Jki;*e}bb!9#a%W1HeDni228Omu^1oAY<037$zI0Q1{|0Gk^O{ zVRfW0wg7DuZ5Rtqh5aJO*oP5QVkoFd$rcLgrvgld5k$5a*Fiy*3S7o!y;{9Dc `EC@hn%Fv?=WR8}!D&MmHiS zoM;ykSbT&RND0yg=3G5vxBrx*CWDd=ML5|47Q8#8-;V2J5;CYC@Z$y87NiUY>UZKc zc*A7QPq#Qb6i~$-Vl5FOOsDnCC(R43M1<9&7E#O 3%pzcW_=zxx(8H zxSF1JZZP9`7tPyHp 9v$IZ% zSO3~Xo jYC=l*&yN7Q&a@2xuq;QtPco|>@)Z|=Dx(7a zzDH}(fP{3tGARcISu1m9qljrLaB^PJuwaxWs9g=KQi*i*ZabRVDH-SR_TUJ859e~$fAGz!p^B05K9|C7wdaS}^^way*r}F$x-7EqC^yATO z`95ITA EN=*X#-~VDPI?pbgxb3QQ=s|S#0RU(|~)>C((~U zhPzOeRbziY-nTaN{D0VkKN|IeK*r1epK0-^Ec1U)i~g?gp%b-m9;5aZo?Eo29+8@A zZDi3=&rPS$A|Y>g>%tETrB7KCd$?QM=>*8D>FAu66XE=>+_BQKB*e_J^S6L|QB|8I2(kiP~fm zmyxuW25=y28AP@m8M}%B&P&N3jwF{dJKF!|5n@vHAc%Gw51mJ8>bd#nW{%{jH(+LK zYQ7_T!9&W|vC0z?3kKZ9Cl9 Pvigzk;Ddg=TEGua)!%i zIDsR3t0Vg#sTtl97C-7;wC3LtLQRouhx=^V>ED5uXY`LLQ?VS=&+z~4A`Kz7e37JX z7M~jdJ%&>W!QN`g(C!%ADo2^c@qBb%rygHi3(5<8%3kgmw3GmvR4=#y1#$X*6g~Ry zaBnSlViEbTXb(^?3`@RGx8KUiN~neRJ*<+lzy(VxML%VlAJkp~94Uprk=bCBTY;!O z7n&e^>eiE7o-Aw<_b)?nCx0$K*i-oJh+T;1#H{6)bhpz2?RnWy$?p+Aon7P%-Y) z5n MSux;*k5;)PAMJ<(THd2)r2}qy z8<4WP)wV_s{EdDNoAM0vAWJ Pq7PjNaIpC;3oPYOTe*tCi