2017-10-16 90 views
1

我正在使用R和EBImage包编程一个用于图像分析的闪亮应用程序。 经过一些困难,我有一些不错的成绩,但在时间绘制computeFeatures的结果,我有一些奇怪的行为:DataTableOutput中的混沌顺序和多帧图像中的奇怪computeFeature图

  • 我不得不明令“细胞”栏才能正常目前datatableoutput数据。
  • 图形具有“帧”因子的倒序。
  • 分布图显示帧不共享图像的通用像素尺寸。看到帧之间没有坐标x和坐标y的重叠。这意味着像框架不在同一个位置。

下面是一个例子:

library(EBImage) 
library(shiny) 
library(tidyverse) 
library(DT) 

ui <- basicPage(
    column(
    width = 3, 
    h3("Images"), 
    displayOutput("nuc"), 
    displayOutput("nucbw") 
    ), 
    column(
    width = 9, 
    h3("Cell Features"), 
    DT::dataTableOutput("basicfeatures"), 
    hr(), 
    fluidRow(
     column(
     width = 4, 
     plotOutput("plot1") 
     ), 
     column(
     width = 8, 
     plotOutput("plot2") 
     ) 
    ) 
    ) 
) 

server <- function(input, output) { 

    # Load Image 
    nuc <- readImage(system.file("images", "nuclei.tif", package="EBImage")) 
    # Segmented Image 
    nucbw <- bwlabel(nuc > 0.5) 

    # Display Original Image 
    output$nuc <- renderDisplay(display(nuc)) 

    # Display Segmented Image 
    output$nucbw <- renderDisplay(display(nucbw)) 

    # Compute Features 
    features <- reactive({ 
    # Create empty dataframe 
    data <- data.frame() 
    # Obect to save total cell number 
    ntotal <- 0L 
    # Compute for each frame 
    for (i in 1:numberOfFrames(nuc)){ 
     nobjects <- max(nucbw[,,i]) 
     cell <- seq.int(from = ntotal + 1L, length.out = nobjects) 
     ntotal <- ntotal + nobjects 
     # Create frame column to know the frame where each cell belongs 
     frame <- rep(paste("Frame", i, sep = " "), nobjects) 
     # Create features dataframe 
     x1 <- computeFeatures.basic(nucbw[,,i], nuc[,,i]) 
     x2 <- computeFeatures.shape(nucbw[,,i], nuc[,,i]) 
     x3 <- computeFeatures.moment(nucbw[,,i], nuc[,,i]) 
     # Binding dataframe for each frame 
     bind <- cbind(cell, frame, x1, x2, x3) 
     # Binding dataframe different frame 
     data <- rbind(bind, data) 
    } 

# Convert "cell" to numeric 
    cell <- as.numeric(as.character(data$cell)) 
# "frame" remains untouched 
    frame <- data$frame 
# Convert computeFeatures to numeric 
    temp <- as.data.frame(data.matrix(data[,-c(1,2)])) 
# Binding to a unique data frame 
    data <- cbind(cell, frame, temp) 

    data 
    }) 


    # Render Features Table 
    output$basicfeatures <- DT::renderDataTable(
    features(), 
    rownames = FALSE, 
    caption = "Cell Features", 
    extensions = list(
     "ColReorder" = NULL, 
     "FixedHeader" = NULL 
    ), 
    options = list(
     pageLength = 10, 
     colReorder = TRUE, 
     fixedHeader = TRUE, 
     scrollX = TRUE, 
     order = list(0, 'asc') 
    ) 
    ) 

    data2 <- reactive({ 
    features() %>% 
     group_by(frame) %>% 
     summarise(n = n()) 
    }) 

    output$plot1<- renderPlot({ 
    g <- ggplot(data2(), aes(x = frame, y = n)) + 
     geom_col(aes(fill = frame), color = "black") + 
     labs(title = "NUMBER OF CELLS PER FRAME", x = "FRAME", y = "NUMBER OF CELLS") + 
     theme_bw(base_size = 16) + 
     theme(legend.position = "none") + 
     theme(axis.text = element_text(size = 14)) 
    g 
    }) 

    output$plot2<- renderPlot({ 
    g <- ggplot(features(), aes(x = m.cx, y = m.cy, fill = frame, color = frame)) + 
     geom_point(shape = 21, size = 4, alpha = 0.2) + 
     labs(title = "DISTRIBUTION OF CELLS", x = "COORDINATE X", y = "COORDINATE Y") + 
     theme_bw(base_size = 16) + 
     theme(
     rect = element_rect(colour = "red"), 
     strip.background = element_rect(colour = "black", fill = "white"), 
     strip.text.x = element_text(colour = "black"), 
     strip.text.y = element_text(colour = "black") 
     ) + 
     facet_wrap(~ frame, nrow = 1) 
    g 
    }) 

} 

shinyApp(ui, server) 
+0

执行'data < - rbind(data,bind)'而不是'data < - rbind(bind,data)'应该可以解决与订单相关的问题。 – SBista

+0

你说得对。它解决了我的问题的前两点。谢谢 – Archymedes

回答

0

的问题是由您的中间字符数据表示使用因子存储的事实引起的,并且该呼叫到data.matrix可以通过内部码替换因素,而不是他们代表的数字。最简单的方法是在library调用后设置options(stringsAsFactors = FALSE)

但是,您应该避免首先转换为字符。当数字特征矩阵x1,x2,是cbindframe字符向量时,会发生此强制。发生这种情况是因为character是这些不同数据类型的共同点。但是,您可以通过在此处创建data.frame来避免此问题:bind <- data.frame(cell, frame, x1, x2, x3)。然后在for循环之后的所有数据转换步骤都不再需要了。

+0

完美,它工作正常,但只是一个细节:绘制“分布图”时,我仍然需要将“m.cx”和“m.cy”转换为数字变量,以正确绘制为连续变量。谢谢你的帮助。我看到你正在开发EBImage和RBioFormats软件包,这真是太棒了,祝贺你。我用它们很多。 – Archymedes

+0

对,如果你决定去选择'stringsAsFactors = FALSE',你仍然需要这样做。然而,正如我所指出的那样,这是对后者的一种较差的解决方案,它不包括对“人物”的强制。您应该避免任何不必要的数据转换,特别是在Shiny应用程序的代码中,因为这会影响应用程序的响应性。如果我的答案解决了您的问题,您可以考虑接受和/或对其进行投票。 – aoles

+0

感谢您的建议。我没有正确地将“绑定< - data.frame(cell,frame,x1,x2,x3)”data.frame包含到循环中。它必须位于“bind < - cbind(cell,frame,x1,x2,x3)”之后。非常感谢 – Archymedes