Commit 04739dba authored by dmattek's avatar dmattek

Added: option to upload and display stimulation pattern

parent 9d1f5677
...@@ -97,7 +97,8 @@ help.text = c( ...@@ -97,7 +97,8 @@ help.text = c(
'Plotting and data processing requires a unique cell ID across entire dataset. A typical dataset from CellProfiler assigns unique cell ID (TrackLabel) within each field of view (Metadata_Site). 'Plotting and data processing requires a unique cell ID across entire dataset. A typical dataset from CellProfiler assigns unique cell ID (TrackLabel) within each field of view (Metadata_Site).
Therefore, a unique ID is created by concatenating these two columns. If the dataset already contains a unique ID, UNcheck this box and select a single column only.', Therefore, a unique ID is created by concatenating these two columns. If the dataset already contains a unique ID, UNcheck this box and select a single column only.',
'This option allows to interpolate NAs or missing data. Some rows in the input file might be missing because a particular time point might not had been acquired. 'This option allows to interpolate NAs or missing data. Some rows in the input file might be missing because a particular time point might not had been acquired.
This option, interpolates such missing points as well as points with NAs in the measurement column. When this option is checked, the interval of time column must be provided!' This option, interpolates such missing points as well as points with NAs in the measurement column. When this option is checked, the interval of time column must be provided!',
'Accepts CSV file with two columns: grouping, time points of stimulation.'
) )
...@@ -186,6 +187,7 @@ rotatedAxisElementText = function(angle, position='x', size = 12){ ...@@ -186,6 +187,7 @@ rotatedAxisElementText = function(angle, position='x', size = 12){
element_text(size = 12, angle = angle, vjust = vjust, hjust = hjust) element_text(size = 12, angle = angle, vjust = vjust, hjust = hjust)
} }
# default ggplot theme used in the app
myGgplotTheme = myGgplotTheme =
theme_bw(base_size = 8, base_family = "Helvetica") + theme_bw(base_size = 8, base_family = "Helvetica") +
theme( theme(
...@@ -206,7 +208,9 @@ myGgplotTheme = ...@@ -206,7 +208,9 @@ myGgplotTheme =
legend.position = "top" legend.position = "top"
) )
myGgplotTraj = function(dt.arg, # data table
# Plot individual time series
LOCplotTraj = function(dt.arg, # input data table
x.arg, # string with column name for x-axis x.arg, # string with column name for x-axis
y.arg, # string with column name for y-axis y.arg, # string with column name for y-axis
group.arg, # string with column name for grouping time series (typicaly cell ID) group.arg, # string with column name for grouping time series (typicaly cell ID)
...@@ -218,9 +222,10 @@ myGgplotTraj = function(dt.arg, # data table ...@@ -218,9 +222,10 @@ myGgplotTraj = function(dt.arg, # data table
ylab.arg = NULL, # string with y-axis label ylab.arg = NULL, # string with y-axis label
plotlab.arg = NULL, # string with plot label plotlab.arg = NULL, # string with plot label
dt.stim.arg = NULL, # plotting additional dataset; typically to indicate stimulations (not fully implemented yet, not tested!) dt.stim.arg = NULL, # plotting additional dataset; typically to indicate stimulations (not fully implemented yet, not tested!)
x.stim.arg = c('tstart', 'tend'), # column names in stimulation dt with x and xend parameters
y.stim.arg = c('ystart', 'yend'), # column names in stimulation dt with y and yend parameters
tfreq.arg = 1, tfreq.arg = 1,
ylim.arg = NULL, ylim.arg = NULL,
stim.bar.height.arg = 0.1,
stim.bar.width.arg = 0.5, stim.bar.width.arg = 0.5,
aux.label1 = NULL, # 1st point label; used for interactive plotting; displayed in the tooltip; typically used to display values of column holding x & y coordinates aux.label1 = NULL, # 1st point label; used for interactive plotting; displayed in the tooltip; typically used to display values of column holding x & y coordinates
aux.label2 = NULL, aux.label2 = NULL,
...@@ -313,16 +318,19 @@ myGgplotTraj = function(dt.arg, # data table ...@@ -313,16 +318,19 @@ myGgplotTraj = function(dt.arg, # data table
facet_wrap(as.formula(paste("~", facet.arg)), facet_wrap(as.formula(paste("~", facet.arg)),
ncol = facet.ncol.arg, ncol = facet.ncol.arg,
scales = "free_x") scales = "free_x")
# plot stimulation bars underneath time series
# dt.stim.arg is read separately and should contain 4 columns with
# xy positions of beginning and end of the bar
if(!is.null(dt.stim.arg)) { if(!is.null(dt.stim.arg)) {
p.tmp = p.tmp + geom_segment(data = dt.stim.arg, p.tmp = p.tmp + geom_segment(data = dt.stim.arg,
aes(x = Stimulation_time - tfreq.arg, aes_string(x = x.stim.arg[1],
xend = Stimulation_time - tfreq.arg, xend = x.stim.arg[2],
y = ylim.arg[1], y = y.stim.arg[1],
yend = ylim.arg[1] + abs(ylim.arg[2] - ylim.arg[1]) * stim.bar.height.arg), yend = y.stim.arg[2],
group = 'group'),
colour = rhg_cols[[3]], colour = rhg_cols[[3]],
size = stim.bar.width.arg, size = stim.bar.width.arg)
group = 1)
} }
if (!is.null(ylim.arg)) if (!is.null(ylim.arg))
...@@ -338,14 +346,65 @@ myGgplotTraj = function(dt.arg, # data table ...@@ -338,14 +346,65 @@ myGgplotTraj = function(dt.arg, # data table
return(p.tmp) return(p.tmp)
} }
# Plot average time series with CI together in one facet
LOCplotTrajRibbon = function(dt.arg, # input data table
x.arg, # string with column name for x-axis
y.arg, # string with column name for y-axis
group.arg = NULL, # string with column name for grouping time series (here, it's a column corresponding to grouping by condition)
col.arg = NULL, # colour pallette for individual time series
dt.stim.arg = NULL, # data table with stimulation pattern
x.stim.arg = c('tstart', 'tend'), # column names in stimulation dt with x and xend parameters
y.stim.arg = c('ystart', 'yend'), # column names in stimulation dt with y and yend parameters
stim.bar.width.arg = 0.5,
ribbon.lohi.arg = c('Lower', 'Upper'),
ribbon.fill.arg = 'grey50',
ribbon.alpha.arg = 0.5,
xlab.arg = NULL,
ylab.arg = NULL,
plotlab.arg = NULL) {
p.tmp = ggplot(dt.arg, aes_string(x = x.arg, group = group.arg)) +
geom_ribbon(aes_string(ymin = ribbon.lohi.arg[1], ymax = ribbon.lohi.arg[2]),
fill = ribbon.fill.arg,
alpha = ribbon.alpha.arg) +
geom_line(aes_string(y = y.arg, colour = group.arg))
# plot stimulation bars underneath time series
# dt.stim.arg is read separately and should contain 4 columns with
# xy positions of beginning and end of the bar
if(!is.null(dt.stim.arg)) {
p.tmp = p.tmp + geom_segment(data = dt.stim.arg,
aes_string(x = x.stim.arg[1],
xend = x.stim.arg[2],
y = y.stim.arg[1],
yend = y.stim.arg[2]),
colour = rhg_cols[[3]],
size = stim.bar.width.arg,
group = 1)
}
# Fast DTW computation
fastDTW <-function (x) if (is.null(col.arg)) {
{ p.tmp = p.tmp +
return(dtw(x, window.type = 'sakoechiba', distance.only = T)$normalizedDistance) scale_color_discrete(name = '')
} else {
p.tmp = p.tmp +
scale_colour_manual(values = col.arg, name = '')
}
if (!is.null(plotlab.arg))
p.tmp = p.tmp + ggtitle(plotlab.arg)
p.tmp = p.tmp +
xlab(xlab.arg) +
ylab(ylab.arg)
return(p.tmp)
} }
# Plots a scatter plot with marginal histograms # Plots a scatter plot with marginal histograms
# Points are connected by a line (grouping by cellID) # Points are connected by a line (grouping by cellID)
# #
......
...@@ -172,7 +172,7 @@ clustHierUI <- function(id, label = "Hierarchical CLustering") { ...@@ -172,7 +172,7 @@ clustHierUI <- function(id, label = "Hierarchical CLustering") {
} }
# SERVER # SERVER
clustHier <- function(input, output, session, in.data4clust, in.data4trajPlot) { clustHier <- function(input, output, session, in.data4clust, in.data4trajPlot, in.data4stimPlot) {
output$uiPlotHierClSel = renderUI({ output$uiPlotHierClSel = renderUI({
ns <- session$ns ns <- session$ns
...@@ -337,6 +337,20 @@ clustHier <- function(input, output, session, in.data4clust, in.data4trajPlot) { ...@@ -337,6 +337,20 @@ clustHier <- function(input, output, session, in.data4clust, in.data4trajPlot) {
return(loc.dt) return(loc.dt)
}) })
data4stimPlotCl <- reactive({
cat(file = stderr(), 'data4stimPlotCl: in\n')
loc.dt = in.data4stimPlot()
if (is.null(loc.dt)) {
cat(file = stderr(), 'data4stimPlotCl: dt is NULL\n')
return(NULL)
}
cat(file = stderr(), 'data4stimPlotCl: dt not NULL\n')
return(loc.dt)
})
# download a list of cellIDs with cluster assignments # download a list of cellIDs with cluster assignments
output$downCellCl <- downloadHandler( output$downCellCl <- downloadHandler(
filename = function() { filename = function() {
...@@ -495,19 +509,24 @@ clustHier <- function(input, output, session, in.data4clust, in.data4trajPlot) { ...@@ -495,19 +509,24 @@ clustHier <- function(input, output, session, in.data4clust, in.data4trajPlot) {
# Hierarchical - Heat Map - download pdf # Hierarchical - Heat Map - download pdf
callModule(downPlot, "downPlotHier", createFnameHeatMap, plotHier) callModule(downPlot, "downPlotHier", createFnameHeatMap, plotHier)
# plot individual trajectories withina cluster
callModule(modTrajPlot, 'modPlotHierTraj', callModule(modTrajPlot, 'modPlotHierTraj',
in.data = data4trajPlotCl, in.data = data4trajPlotCl,
in.data.stim = data4stimPlotCl,
in.facet = 'cl', in.facet = 'cl',
in.facet.color = getClColHier, in.facet.color = getClColHier,
in.fname = createFnameTrajPlot) in.fname = createFnameTrajPlot)
# plot cluster means
callModule(modTrajRibbonPlot, 'modPlotHierTrajRibbon', callModule(modTrajRibbonPlot, 'modPlotHierTrajRibbon',
in.data = data4trajPlotCl, in.data = data4trajPlotCl,
in.data.stim = data4stimPlotCl,
in.facet = 'cl', in.facet = 'cl',
in.facet.color = getClColHier, in.facet.color = getClColHier,
in.fname = createFnameRibbonPlot) in.fname = createFnameRibbonPlot)
# plot distribution barplot
callModule(modClDistPlot, 'hierClDistPlot', callModule(modClDistPlot, 'hierClDistPlot',
in.data = data4clDistPlot, in.data = data4clDistPlot,
in.cols = getClColHier, in.cols = getClColHier,
......
...@@ -184,7 +184,7 @@ clustHierSparUI <- function(id, label = "Sparse Hierarchical CLustering") { ...@@ -184,7 +184,7 @@ clustHierSparUI <- function(id, label = "Sparse Hierarchical CLustering") {
} }
# SERVER # SERVER
clustHierSpar <- function(input, output, session, in.data4clust, in.data4trajPlot) { clustHierSpar <- function(input, output, session, in.data4clust, in.data4trajPlot, in.data4stimPlot) {
# UI for advanced options # UI for advanced options
output$uiPlotHierSparNperms = renderUI({ output$uiPlotHierSparNperms = renderUI({
...@@ -391,6 +391,20 @@ clustHierSpar <- function(input, output, session, in.data4clust, in.data4trajPlo ...@@ -391,6 +391,20 @@ clustHierSpar <- function(input, output, session, in.data4clust, in.data4trajPlo
return(loc.dt) return(loc.dt)
}) })
data4stimPlotClSpar <- reactive({
cat(file = stderr(), 'data4stimPlotClSpar: in\n')
loc.dt = in.data4stimPlot()
if (is.null(loc.dt)) {
cat(file = stderr(), 'data4stimPlotClSpar: dt is NULL\n')
return(NULL)
}
cat(file = stderr(), 'data4stimPlotClSpar: dt not NULL\n')
return(loc.dt)
})
# download a list of cellIDs with cluster assignments # download a list of cellIDs with cluster assignments
output$downCellClSpar <- downloadHandler( output$downCellClSpar <- downloadHandler(
...@@ -541,22 +555,23 @@ clustHierSpar <- function(input, output, session, in.data4clust, in.data4trajPlo ...@@ -541,22 +555,23 @@ clustHierSpar <- function(input, output, session, in.data4clust, in.data4trajPlo
# Sparse Hierarchical - Heat Map - download pdf # Sparse Hierarchical - Heat Map - download pdf
callModule(downPlot, "downPlotHierSparHM", createFnameHeatMap, plotHierSpar) callModule(downPlot, "downPlotHierSparHM", createFnameHeatMap, plotHierSpar)
# plot individual trajectories withina cluster
callModule(modTrajPlot, 'modPlotHierSparTraj', callModule(modTrajPlot, 'modPlotHierSparTraj',
in.data = data4trajPlotClSpar, in.data = data4trajPlotClSpar,
in.data.stim = data4stimPlotClSpar,
in.facet = 'cl', in.facet = 'cl',
in.facet.color = getClColHierSpar, in.facet.color = getClColHierSpar,
in.fname = createFnameTrajPlot) in.fname = createFnameTrajPlot)
# plot cluster means
callModule(modTrajRibbonPlot, 'modPlotHierSparTrajRibbon', callModule(modTrajRibbonPlot, 'modPlotHierSparTrajRibbon',
in.data = data4trajPlotClSpar, in.data = data4trajPlotClSpar,
in.data.stim = data4stimPlotClSpar,
in.facet = 'cl', in.facet = 'cl',
in.facet.color = getClColHierSpar, in.facet.color = getClColHierSpar,
in.fname = createFnameRibbonPlot) in.fname = createFnameRibbonPlot)
# plot distribution barplot
callModule(modClDistPlot, 'hierClSparDistPlot', callModule(modClDistPlot, 'hierClSparDistPlot',
in.data = data4clSparDistPlot, in.data = data4clSparDistPlot,
in.cols = getClColHierSpar, in.cols = getClColHierSpar,
......
...@@ -69,6 +69,7 @@ modTrajPlotUI = function(id, label = "Plot Individual Time Series") { ...@@ -69,6 +69,7 @@ modTrajPlotUI = function(id, label = "Plot Individual Time Series") {
modTrajPlot = function(input, output, session, modTrajPlot = function(input, output, session,
in.data, in.data,
in.data.stim,
in.fname, in.fname,
in.facet = 'group', in.facet = 'group',
in.facet.color = NULL) { in.facet.color = NULL) {
...@@ -189,6 +190,7 @@ modTrajPlot = function(input, output, session, ...@@ -189,6 +190,7 @@ modTrajPlot = function(input, output, session,
return(NULL) return(NULL)
} }
# check main data exists
loc.dt = isolate(in.data()) loc.dt = isolate(in.data())
cat("plotTraj: on to plot\n\n") cat("plotTraj: on to plot\n\n")
...@@ -198,6 +200,17 @@ modTrajPlot = function(input, output, session, ...@@ -198,6 +200,17 @@ modTrajPlot = function(input, output, session,
} }
cat(file = stderr(), 'plotTraj: dt not NULL\n') cat(file = stderr(), 'plotTraj: dt not NULL\n')
# check if stim data exists
loc.dt.stim = isolate(in.data.stim())
if (is.null(loc.dt.stim)) {
cat(file = stderr(), 'plotTraj: dt.stim is NULL\n')
} else {
cat(file = stderr(), 'plotTraj: dt.stim not NULL\n')
}
# Future: change such that a column with colouring status is chosen by the user # Future: change such that a column with colouring status is chosen by the user
...@@ -247,14 +260,17 @@ modTrajPlot = function(input, output, session, ...@@ -247,14 +260,17 @@ modTrajPlot = function(input, output, session,
} }
p.out = myGgplotTraj( p.out = LOCplotTraj(
dt.arg = loc.dt, dt.arg = loc.dt,
x.arg = 'realtime', x.arg = 'realtime',
y.arg = 'y', y.arg = 'y',
group.arg = "id", group.arg = "id",
facet.arg = in.facet, facet.arg = in.facet,
facet.ncol.arg = input$inPlotTrajFacetNcol, facet.ncol.arg = input$inPlotTrajFacetNcol,
facet.color.arg = loc.facet.col, facet.color.arg = loc.facet.col,
dt.stim.arg = loc.dt.stim,
x.stim.arg = c('tstart', 'tend'),
y.stim.arg = c('ystart', 'yend'),
xlab.arg = 'Time (min)', xlab.arg = 'Time (min)',
line.col.arg = loc.line.col.arg, line.col.arg = loc.line.col.arg,
aux.label1 = if (locPos) 'pos.x' else NULL, aux.label1 = if (locPos) 'pos.x' else NULL,
......
...@@ -48,6 +48,7 @@ modTrajRibbonPlotUI = function(id, label = "Plot Individual Time Series") { ...@@ -48,6 +48,7 @@ modTrajRibbonPlotUI = function(id, label = "Plot Individual Time Series") {
modTrajRibbonPlot = function(input, output, session, modTrajRibbonPlot = function(input, output, session,
in.data, in.data,
in.data.stim,
in.facet = 'group', in.facet = 'group',
in.facet.color = NULL, in.facet.color = NULL,
in.fname) { in.fname) {
...@@ -107,24 +108,44 @@ modTrajRibbonPlot = function(input, output, session, ...@@ -107,24 +108,44 @@ modTrajRibbonPlot = function(input, output, session,
plotTraj, TRUE) plotTraj, TRUE)
plotTraj <- function() { plotTraj <- function() {
cat(file = stderr(), 'plotTraj: in\n') cat(file = stderr(), 'plotTrajRibbon: in\n')
locBut = input$butPlotTraj locBut = input$butPlotTraj
if (locBut == 0) { if (locBut == 0) {
cat(file = stderr(), 'plotTraj: Go button not pressed\n') cat(file = stderr(), 'plotTrajRibbon: Go button not pressed\n')
return(NULL) return(NULL)
} }
# check if main data exists
loc.dt = isolate(in.data()) loc.dt = isolate(in.data())
cat("plotTraj: on to plot\n\n") cat("plotTrajRibbon: on to plot\n\n")
if (is.null(loc.dt)) { if (is.null(loc.dt)) {
cat(file = stderr(), 'plotTraj: dt is NULL\n') cat(file = stderr(), 'plotTrajRibbon: dt is NULL\n')
return(NULL) return(NULL)
} }
cat(file = stderr(), 'plotTraj: dt not NULL\n') cat(file = stderr(), 'plotTrajRibbon: dt not NULL\n')
# check if stim data exists
loc.dt.stim = isolate(in.data.stim())
if (is.null(loc.dt.stim)) {
cat(file = stderr(), 'plotTrajRibbon: stim is NULL\n')
} else {
cat(file = stderr(), 'plotTrajRibbon: stim not NULL\n')
# choose only 1st group of stimulation pattern for ribbon plot
loc.groups = unique(loc.dt.stim[['group']])
if(length(loc.groups) > 1) {
cat(file = stderr(), 'plotTrajRibbon: more than 1 group in stim; choosing 1st\n')
loc.dt.stim = loc.dt.stim[group == loc.groups[1]]
}
}
# Future: change such that a column with colouring status is chosen by the user # Future: change such that a column with colouring status is chosen by the user
...@@ -180,11 +201,14 @@ modTrajRibbonPlot = function(input, output, session, ...@@ -180,11 +201,14 @@ modTrajRibbonPlot = function(input, output, session,
loc.dt.aggr[, (in.facet) := as.factor(get(in.facet))] loc.dt.aggr[, (in.facet) := as.factor(get(in.facet))]
p.out = tca::plotTrajRibbon(dt.arg = loc.dt.aggr, p.out = LOCplotTrajRibbon(dt.arg = loc.dt.aggr,
x.arg = 'realtime', x.arg = 'realtime',
y.arg = 'Mean', y.arg = 'Mean',
col.arg = loc.facet.col, col.arg = loc.facet.col,
group.arg = in.facet, group.arg = in.facet,
dt.stim.arg = loc.dt.stim,
x.stim.arg = c('tstart', 'tend'),
y.stim.arg = c('ystart', 'yend'),
xlab.arg = 'Time (min)', xlab.arg = 'Time (min)',
ylab.arg = '') + ylab.arg = '') +
ggplotTheme() + ggplotTheme() +
......
...@@ -37,8 +37,8 @@ shinyServer(function(input, output, session) { ...@@ -37,8 +37,8 @@ shinyServer(function(input, output, session) {
# The value of inDataGen1,2 actionButton is the number of times they were pressed # The value of inDataGen1,2 actionButton is the number of times they were pressed
dataGen1 = isolate(input$inDataGen1), dataGen1 = isolate(input$inDataGen1),
dataLoadNuc = isolate(input$inButLoadNuc), dataLoadNuc = isolate(input$inButLoadNuc),
dataLoadTrajRem = isolate(input$inButLoadTrajRem) dataLoadTrajRem = isolate(input$inButLoadTrajRem),
#dataLoadStim = isolate(input$inButLoadStim) dataLoadStim = isolate(input$inButLoadStim)
) )
#### ####
...@@ -78,7 +78,36 @@ shinyServer(function(input, output, session) { ...@@ -78,7 +78,36 @@ shinyServer(function(input, output, session) {
# reset("inFileStimLoad") # reset is a shinyjs function # reset("inFileStimLoad") # reset is a shinyjs function
}) })
# load data with trajectories to remove
dataLoadTrajRem <- eventReactive(input$inButLoadTrajRem, {
cat(file = stderr(), "dataLoadTrajRem\n")
locFilePath = input$inFileLoadTrajRem$datapath
counter$dataLoadTrajRem <- input$inButLoadTrajRem - 1
if (is.null(locFilePath) || locFilePath == '')
return(NULL)
else {
return(fread(locFilePath))
}
})
# load data with stimulation pattern
dataLoadStim <- eventReactive(input$inButLoadStim, {
cat(file = stderr(), "dataLoadStim\n")
locFilePath = input$inFileLoadStim$datapath
counter$dataLoadStim <- input$inButLoadStim - 1
if (is.null(locFilePath) || locFilePath == '')
return(NULL)
else {
return(fread(locFilePath))
}
})
# UI for loading csv with cell IDs for trajectory removal # UI for loading csv with cell IDs for trajectory removal
output$uiFileLoadTrajRem = renderUI({ output$uiFileLoadTrajRem = renderUI({
cat(file = stderr(), 'UI uiFileLoadTrajRem\n') cat(file = stderr(), 'UI uiFileLoadTrajRem\n')
...@@ -98,20 +127,26 @@ shinyServer(function(input, output, session) { ...@@ -98,20 +127,26 @@ shinyServer(function(input, output, session) {
actionButton("inButLoadTrajRem", "Load Data") actionButton("inButLoadTrajRem", "Load Data")
}) })
# load main data file # UI for loading csv with stimulation pattern
dataLoadTrajRem <- eventReactive(input$inButLoadTrajRem, { output$uiFileLoadStim = renderUI({
cat(file = stderr(), "dataLoadTrajRem\n") cat(file = stderr(), 'UI uiFileLoadStim\n')
locFilePath = input$inFileLoadTrajRem$datapath
counter$dataLoadTrajRem <- input$inButLoadTrajRem - 1 if(input$chBstim)
fileInput(
'inFileLoadStim',
'Select data file (e.g. stim.csv) and press "Load Data"',
accept = c('text/csv', 'text/comma-separated-values,text/plain')
)
})
output$uiButLoadStim = renderUI({
cat(file = stderr(), 'UI uiButLoadStim\n')
if (is.null(locFilePath) || locFilePath == '') if(input$chBstim)
return(NULL) actionButton("inButLoadStim", "Load Data")
else {
return(fread(locFilePath))
}
}) })
# COLUMN SELECTION # COLUMN SELECTION
output$varSelTrackLabel = renderUI({ output$varSelTrackLabel = renderUI({
...@@ -739,6 +774,22 @@ shinyServer(function(input, output, session) { ...@@ -739,6 +774,22 @@ shinyServer(function(input, output, session) {
}) })
# prepare data with stimulation pattern
# this dataset is displayed underneath of trajectory plot (modules/trajPlot.R) as geom_segment
data4stimPlot <- reactive({
cat(file = stderr(), 'data4stimPlot\n')
if (input$chBstim) {
cat(file = stderr(), 'data4stimPlot: stim not NULL\n')
loc.dt.stim = dataLoadStim()
return(loc.dt.stim)
} else {
cat(file = stderr(), 'data4stimPlot: stim is NULL\n')
return(NULL)
}
})