R/method-accessor.R

Defines functions modify_AsIs_list .internal_extract_sample .internal_tax_table .internal_extract_taxonomy_ .internal_taxonomy mp_extract_otutree mp_extract_taxatree .internal_extract_abundance `[.tbl_mpse` head.alphasample head.diffAnalysisClass tail.diffAnalysisClass dim.diffAnalysisClass `$.diffAnalysisClass` `[[.diffAnalysisClass` `[.diffAnalysisClass`

Documented in mp_extract_otutree mp_extract_taxatree

##' @method [ diffAnalysisClass
##' @export
`[.diffAnalysisClass` <- function(x, i, j, asis = FALSE, ...) {
    result <- x@result
    y <- result[i, j, ...]
    if (!asis)
        return(y)
    x@result <- y
    return(x)
}

##' @method [[ diffAnalysisClass
##' @export
`[[.diffAnalysisClass` <- function(x, i) {
    result <- x@result
    if (!i %in% names(result))
        stop("input term not found...")
    result[[i]]
}

##' @method $ diffAnalysisClass
##' @export
`$.diffAnalysisClass` <-  function(x, name) {
    x <- x@result
    x[, name]
}

##' @method dim diffAnalysisClass
##' @export
dim.diffAnalysisClass <- function(x) {
    dim(x@result)
}

##' @importFrom utils tail
##' @method tail diffAnalysisClass
##' @export
tail.diffAnalysisClass <- function(x, n=6L, ...) {
    tail(x@result, n, ...)
}

#' @importFrom utils head
#' @method head diffAnalysisClass
#' @export
head.diffAnalysisClass <- function(x, n=6L, ...){
    head(as.data.frame(x), n=n, ...)
}

#' @method head alphasample
#' @export
head.alphasample <- function(x, n=6L, ...){
    head(as.data.frame(x), n=n, ...)
}

#' MPSE accessors
#' @param x R object, MPSE class in here
#' @param i,j,... Indices specifying elements to extract or replace.
#' Indices are 'numeric' or 'character' vectors or empty (missing) or
#' NULL.  Numeric values are coerced to integer as by 'as.integer' 
#' (and hence truncated towards zero).  Character vectors will be matched 
#' to the 'names' of the object (or for matrices/arrays, the 'dimnames')
#' @param drop logical If 'TRUE' the result is coerced to the lowest 
#' possible dimension (see the examples).  This only works for extracting 
#' elements, not for the replacement.
#' @param value character vector, Either ‘NULL’ or a character vector equal 
#' of length equal to the appropriate dimension.
#' @param object parameter of tax_table, R object, MPSE class in here.
#' @name MPSE-accessors
NULL

#' @rdname MPSE-accessors
#' @export
setMethod("[", signature(x="MPSE"),
          function(x, i, j, ..., drop=TRUE){

    otutree <- x@otutree
    refseq <- x@refseq
    taxatree <- x@taxatree
    nx <- methods::callNextMethod()
    newotus <- rownames(nx)
    rowda <- SummarizedExperiment::rowData(nx)

    otutree <- .internal_drop.tip(tree=otutree, newnm=newotus)
 
    if (length(newotus) == 1){
        if (!is.null(taxatree)){
            taxatb <- taxatree %>% 
                      taxatree_to_tb() %>% 
                      tibble::as_tibble(rownames="OTU") %>%
                      dplyr::filter(.data$OTU==newotus)
            rowda <- rowda %>% 
                     tibble::as_tibble(rownames="OTU") %>% 
                     dplyr::filter(.data$OTU==newotus) %>%
                     dplyr::left_join(taxatb, by="OTU") %>%
                     tibble::column_to_rownames(var="OTU") %>%
                     S4Vectors::DataFrame(check.names=FALSE)
            taxatree <- NULL
        }
    }else{
        taxatree <- .internal_drop.tip(
                                       tree=taxatree, 
                                       newnm=newotus, 
                                       collapse.singles=FALSE
                                )
    }

    if (!is.null(refseq)){
        refseq <- refseq[newotus]
    }
 
    nx@taxatree <- taxatree
    nx@otutree <- otutree
    nx@refseq <- refseq
    SummarizedExperiment::rowData(nx) <- rowda
    methods::validObject(nx)
    return(nx)
})

#' @method [ tbl_mpse
#' @export
`[.tbl_mpse` <- function(x, i, j, ..., drop=TRUE){
    res <- NextMethod()
    if (valid_names(res, type="tbl_mpse")){
        res <- add_attr.tbl_mpse(x1=res, x2=x)
    }else{
        res <- drop_class(res, class="tbl_mpse")
    }
    return (res)
}

#' @rdname MPSE-accessors
#' @export
setReplaceMethod("colData", c("MPSE", "DataFrame"), function(x, ..., value){
    res <- methods::callNextMethod()
})

#' @rdname MPSE-accessors
#' @export
setReplaceMethod("colData", c("MPSE", "NULL"), function(x, ..., value){
    res <- methods::callNextMethod()
})

#' extract the abundance matrix from MPSE object or tbl_mpse object
#' @rdname mp_extract_assays-methods
#' @param x MPSE or tbl_mpse object
#' @param .abundance the name of abundance to be extracted.
#' @param byRow logical if it is set TRUE, 'otu X sample' shape will return,
#' else 'sample X otu' will return.
#' @return otu abundance a data.frame object
#' @param ... additional parameters.
#' @export
setGeneric("mp_extract_assays", function(x, .abundance, byRow=TRUE, ...)standardGeneric("mp_extract_assays"))

#' @importFrom methods as
#' @rdname mp_extract_assays-methods
#' @aliases mp_extract_assays,MPSE
#' @exportMethod mp_extract_assays
setMethod("mp_extract_assays", signature(x="MPSE"), function(x, .abundance, byRow=TRUE, ...){
    .abundance <- rlang::enquo(.abundance)
    if (rlang::quo_is_missing(.abundance)){
        rlang::abort("The abundance name is required !")
    }

    assaysvar <- SummarizedExperiment::assayNames(x)
    if (!rlang::as_name(.abundance) %in% assaysvar){
        message_wrap(paste0("The assays slot of object does not contain ", 
                            rlang::as_name(.abundance)))
        return(NULL)
    }

    dat <- SummarizedExperiment::assay(x, rlang::as_name(.abundance))

    if (byRow){
        dat %<>% as('matrix') %>% as.data.frame(check.names=FALSE)
    }else{
        dat %<>% t() %>% as('matrix') %>% as.data.frame(check.names=FALSE)
    }
    return(dat)
})

.internal_extract_abundance <- function(x, .abundance, byRow=TRUE, ...){
    
    .abundance <- rlang::enquo(.abundance)

    if (rlang::quo_is_missing(.abundance)){
        rlang::abort("The abundance name is required !")
    }

    assaysvar <- x %>% attr("assaysvar")

    if (!rlang::as_name(.abundance) %in% assaysvar){
        rlang::abort("The abundance is not in the object!")
    }

    dat <- x %>% 
        ungroup() %>%
        select(c("OTU", "Sample", rlang::as_name(.abundance))) 

    if (byRow){
        dat %<>%
            tidyr::pivot_wider(id_cols="OTU", 
                               names_from="Sample", 
                               values_from=rlang::as_name(.abundance)) %>%
            tibble::column_to_rownames(var="OTU")
    }else{
        dat %<>%
            tidyr::pivot_wider(id_cols="Sample",
                               names_from="OTU",
                               values_from=rlang::as_name(.abundance)) %>%
            tibble::column_to_rownames(var="Sample")   
    }
    
    return(dat)
}

#' @rdname mp_extract_assays-methods
#' @aliases mp_extract_assays,tbl_mpse
#' @exportMethod mp_extract_assays
setMethod("mp_extract_assays", signature(x="tbl_mpse"), .internal_extract_abundance)

#' @rdname mp_extract_assays-methods
#' @aliases mp_extract_assays,grouped_df_mpse
#' @exportMethod mp_extract_assays
setMethod("mp_extract_assays", signature(x="grouped_df_mpse"), .internal_extract_abundance)


#' @title extract the taxonomy tree in MPSE object
#' @docType methods
#' @rdname mp_extract_tree-methods
#' @param x MPSE object
#' @param type character taxatree or otutree
#' @param tip.level character This argument will keep the nodes 
#' belong to the tip.level as tip nodes when type is taxatree, default is OTU, 
#' which will return the taxa tree with OTU level as tips.
#' @param ... additional arguments
#' @return taxatree treedata object
#' @export
setGeneric("mp_extract_tree", function(x, type="taxatree", tip.level="OTU", ...){standardGeneric("mp_extract_tree")})


#' @rdname mp_extract_tree-methods
#' @aliases mp_extract_tree,MPSE
#' @exportMethod mp_extract_tree
setMethod("mp_extract_tree", signature(x="MPSE"), function(x, type="taxatree", tip.level="OTU", ...){
    type %<>% match.arg(c("taxatree", "otutree"))
    tree <- methods::slot(x, type)
    tip.level <- rlang::enquo(tip.level)
    if (!is.null(tree)){
        if (type == "taxatree"){
            tree <- .extract_tree_at_tiplevel(tree, tip.level=!!tip.level)
        }
        return(tree)
    }else{
        message(tree_empty(type=type))
    }
})

#' @rdname mp_extract_tree-methods
#' @aliases mp_extract_tree,tbl_mpse
#' @exportMethod mp_extract_tree
setMethod("mp_extract_tree", signature(x="tbl_mpse"),function(x, type="taxatree", tip.level="OTU", ...){
    tip.level <- rlang::enquo(tip.level)
    .internal_tree(x = x, type = type, tip.level = !!tip.level)
})

#' @rdname mp_extract_tree-methods
#' @aliases mp_extract_tree,grouped_df_mpse
#' @exportMethod mp_extract_tree
setMethod("mp_extract_tree", signature(x="grouped_df_mpse"),function(x, type="taxatree", tip.level="OTU", ...){
    tip.level <- rlang::enquo(tip.level)
    .internal_tree(x=x, type=type, tip.level=!!tip.level)
})

#' @rdname mp_extract_tree-methods
#' @export
mp_extract_taxatree <- function(x, tip.level = "OTU", ...){
    tip.level <- rlang::enquo(tip.level)
    x <- mp_extract_tree(x = x, type="taxatree", tip.level = !!tip.level, ...)
    return(x)
}

#' @rdname mp_extract_tree-methods
#' @export
mp_extract_otutree <- function(x, ...){
    x <- mp_extract_tree(x = x, type = 'otutree', ...)
    return(x)
}

#' @rdname mp_extract_taxonomy-methods
#' @param x MPSE object
#' @param ... additional parameters, now is meaningless.
#' @return data.frame contained taxonomy information
#' @export
setGeneric("taxonomy", function(x, ...){standardGeneric("taxonomy")})

.internal_taxonomy <- function(x, ...){
    x <- x %>% mp_extract_taxonomy(...) %>%
         tibble::column_to_rownames(var="OTU")
    return(x)
}

#' @rdname mp_extract_taxonomy-methods
#' @aliases taxonomy,MPSE
#' @exportMethod taxonomy
setMethod("taxonomy", signature(x = "MPSE"), .internal_taxonomy)

#' @rdname mp_extract_taxonomy-methods
#' @aliases taxonomy,tbl_mpse
#' @exportMethod taxonomy
setMethod("taxonomy", signature(x = "tbl_mpse"), .internal_taxonomy)

#' @rdname mp_extract_taxonomy-methods
#' @aliases taxonomy,grouped_df_mpse
#' @export
setMethod("taxonomy", signature(x = "grouped_df_mpse"), .internal_taxonomy)



#' @title extract the taxonomy annotation in MPSE object
#' @docType methods
#' @rdname mp_extract_taxonomy-methods
#' @param x MPSE object
#' @param ... additional arguments
#' @return data.frame contained taxonomy annotation.
#' @export
setGeneric("mp_extract_taxonomy", function(x, ...)standardGeneric("mp_extract_taxonomy"))

#' @rdname mp_extract_taxonomy-methods
#' @aliases mp_extract_taxonomy,MPSE
#' @exportMethod mp_extract_taxonomy
setMethod("mp_extract_taxonomy", signature(x="MPSE"), function(x, ...){
    da <- .internal_extract_taxonomy(taxatree=x@taxatree, classnm=class(x)[1])
    return(da)
})

.internal_extract_taxonomy_ <- function(x, ...){
    taxatree <- x %>% attr("taxatree")
    classnm <- class(x)[1]
    da <- .internal_extract_taxonomy(taxatree = taxatree,
                                     classnm = classnm)
    return(da)
}

#' @rdname mp_extract_taxonomy-methods
#' @aliases mp_extract_taxonomy,tbl_mpse
#' @exportMethod mp_extract_taxonomy
setMethod("mp_extract_taxonomy", signature(x="tbl_mpse"), .internal_extract_taxonomy_)

#' @rdname mp_extract_taxonomy-methods
#' @aliases mp_extract_taxonomy,grouped_df_mpse
#' @exportMethod mp_extract_taxonomy
setMethod("mp_extract_taxonomy", signature(x="grouped_df_mpse"), .internal_extract_taxonomy_)

#' @rdname MPSE-accessors
#' @return taxonomyTable class
#' @export
setGeneric("tax_table", function(object)standardGeneric("tax_table"))

.internal_tax_table <- function(object){
    da <- mp_extract_taxonomy(object) %>%
          tibble::column_to_rownames(var="OTU") %>% 
          as.matrix()
    phyloseq::tax_table(da)
}

#' @rdname MPSE-accessors
#' @aliases tax_table,MPSE
#' @exportMethod tax_table
setMethod("tax_table", signature(object = "MPSE"), .internal_tax_table)

#' @rdname MPSE-accessors
#' @aliases tax_table,tbl_mpse
#' @exportMethod tax_table
setMethod("tax_table", signature(object = "tbl_mpse"), .internal_tax_table)

#' @rdname MPSE-accessors
#' @aliases tax_table,grouped_df_mpse 
#' @exportMethod tax_table
setMethod("tax_table", signature(object = "grouped_df_mpse"), .internal_tax_table)

#' @title extract the sample information in MPSE object
#' @docType methods
#' @rdname mp_extract_sample-methods
#' @param x MPSE object
#' @param ... additional arguments
#' @return tbl_df contained sample information.
#' @export
setGeneric("mp_extract_sample", function(x, ...)standardGeneric("mp_extract_sample"))

#' @rdname mp_extract_sample-methods
#' @aliases mp_extract_sample,MPSE
#' @exportMethod mp_extract_sample
setMethod("mp_extract_sample", signature(x="MPSE"), function(x, ...){
 da <- x@colData %>%
       data.frame(check.names=FALSE) %>%
       avoid_conflict_names() %>%
       tibble::as_tibble(rownames="Sample") %>%
       modify_AsIs_list()
 return(da)
})

.internal_extract_sample <- function(x, ...){
samplevar <- x %>% attr("samplevar")
da <- x %>%
    dplyr::ungroup() %>%
    select(samplevar) %>%
    distinct()
return(da)
}

modify_AsIs_list <- function(x, ...){
nms <- lapply(x, function(x)inherits(x, "AsIs") && typeof(x)=="list")
nms <- names(nms[unlist(nms)])
x %<>% dplyr::mutate_at(dplyr::vars(nms), ~unclass(.))
x
}

#' @rdname mp_extract_sample-methods
#' @aliases mp_extract_sample,tbl_mpse
#' @exportMethod mp_extract_sample
setMethod("mp_extract_sample", signature(x="tbl_mpse"), .internal_extract_sample)

#' @rdname mp_extract_sample-methods
#' @aliases mp_extract_sample,grouped_df_mpse
#' @exportMethod mp_extract_sample
setMethod("mp_extract_sample", signature(x="grouped_df_mpse"), .internal_extract_sample)

#' @title extract the feature (OTU) information in MPSE object
#' @docType methods
#' @rdname mp_extract_feature-methods
#' @param x MPSE object
#' @param addtaxa logical whether adding the taxonomy information
#' default is FALSE.
#' @param ... additional arguments
#' @return tbl_df contained feature (OTU) information.
#' @export
setGeneric("mp_extract_feature", function(x, addtaxa=FALSE, ...)standardGeneric("mp_extract_feature"))

#' @rdname mp_extract_feature-methods
#' @aliases mp_extract_feature,MPSE
#' @exportMethod mp_extract_feature
setMethod("mp_extract_feature", signature(x="MPSE"), function(x, addtaxa=FALSE, ...){
    da <- SummarizedExperiment::rowData(x) %>%
          avoid_conflict_names() %>%
          tibble::as_tibble(rownames="OTU")
    if (!is.null(x@taxatree)){
        tip.level <- x@taxatree %>% 
                     dplyr::filter(.data$isTip, keep.td=FALSE) %>% 
                     pull(.data$nodeClass) %>% 
                     unique()
        taxanm <- x@taxatree %>%
                  dplyr::filter(!.data$nodeClass %in% c(tip.level, "Root"), keep.td=FALSE) %>%
                  dplyr::pull(.data$nodeClass) %>% unique()
        trda <- x@taxatree %>%
                taxatree_to_tb() #%>%
                #tibble::as_tibble(rownames=tip.level)
        if (!addtaxa){
            trda %<>% dplyr::select(-taxanm)
        }
        trda %<>% dplyr::select(setdiff(colnames(trda), colnames(da))) %>%
            tibble::as_tibble(rownames=tip.level)
        da %<>% dplyr::left_join(trda, by=c("OTU"=tip.level)) 
                
    }
    da %<>% modify_AsIs_list()
    return(da)
})

.internal_extract_feature <- function(x, addtaxa=FALSE, ...){
    otumetavar <- x %>% attr("otumetavar")
    taxatree <- x %>% attr("taxatree")
    da <- x %>%
        dplyr::ungroup() %>%
        select(c("OTU", otumetavar)) %>%
        distinct()
    if (!is.null(taxatree)){
        tip.level <- taxatree %>%
                     dplyr::filter(.data$isTip, keep.td=FALSE) %>%
                     pull(.data$nodeClass) %>%
                     unique()        
        taxanm <- taxatree %>%
                  dplyr::filter(!.data$nodeClass %in% c(tip.level, "Root"), 
                                keep.td = FALSE) %>%
                  dplyr::pull(.data$nodeClass) %>% unique
        trda <- taxatree %>%
                taxatree_to_tb() %>%
                tibble::as_tibble(rownames = tip.level)
        if (!addtaxa){
            trda %<>% dplyr::select(-taxanm)
        }
        da %<>% dplyr::left_join(trda, by=c("OTU"= tip.level))
    }
    return(da)
}

#' @rdname mp_extract_feature-methods
#' @aliases mp_extract_feature,tbl_mpse
#' @exportMethod mp_extract_feature
setMethod("mp_extract_feature", signature(x="tbl_mpse"), .internal_extract_feature)

#' @rdname mp_extract_feature-methods
#' @aliases mp_extract_feature,grouped_df_mpse
#' @exportMethod mp_extract_feature
setMethod("mp_extract_feature", signature(x="grouped_df_mpse"), .internal_extract_feature)

#' Extract the result of mp_cal_rarecurve with action="add" from MPSE or tbl_mpse object
#' @rdname mp_extract_rarecurve-methods
#' @param x MPSE object or tbl_mpse object
#' @param .rarecurve the column name of rarecurve after run mp_cal_rarecurve with action="add".
#' @param ... additional parameter
#' @return rarecurve object that be be visualized by ggrarecurve
#' @export
setGeneric("mp_extract_rarecurve", function(x, .rarecurve, ...)standardGeneric("mp_extract_rarecurve"))

.internal_extract_rarecurve <- function(x, .rarecurve, ...){
.rarecurve <- rlang::enquo(.rarecurve)
if (rlang::quo_is_missing(.rarecurve)){
    .rarecurve <- as.symbol("RareAbundanceRarecurve")
}
dat <- x %>% 
    mp_extract_sample() %>%
    dplyr::select("Sample", !!.rarecurve) %>% 
    dplyr::rename(sample="Sample") %>%
    tidyr::unnest() %>% 
    suppressWarnings()
return(structure(list(data=dat), class="rarecurve"))
}

#' @rdname mp_extract_rarecurve-methods
#' @aliases mp_extract_rarecurve,MPSE
#' @exportMethod mp_extract_rarecurve
setMethod("mp_extract_rarecurve", signature(x="MPSE"), .internal_extract_rarecurve)

#' @rdname mp_extract_rarecurve-methods
#' @aliases mp_extract_rarecurve,tbl_mpse
#' @exportMethod mp_extract_rarecurve
setMethod("mp_extract_rarecurve", signature(x="tbl_mpse"), .internal_extract_rarecurve)

#' @rdname mp_extract_rarecurve-methods
#' @aliases mp_extract_rarecurve,grouped_df_mpse
#' @exportMethod mp_extract_rarecurve
setMethod("mp_extract_rarecurve", signature(x="grouped_df_mpse"), .internal_extract_rarecurve)

#' Extracting the abundance metric from MPSE or tbl_mpse object
#' @description 
#' Extracting the abundance metric from the MPSE or tbl_mpse,
#' the 'mp_cal_abundance' must have been run with action='add'.
#' @rdname mp_extract_abundance-methods
#' @param x MPSE or tbl_mpse object
#' @param taxa.class character the name of taxonomy 
#' class level what you want to extract
#' @param topn integer the number of the top most abundant, default
#' is NULL.
#' @param rmun logical whether to remove the unknown taxa, such as "g__un_xxx",
#' default is FALSE (the unknown taxa class will be considered as 'Others').
#' @param ... additional parameters
#' @author Shuangbin Xu
#' @export
setGeneric("mp_extract_abundance", function(x, taxa.class="all", topn=NULL, rmun=FALSE, ...)standardGeneric("mp_extract_abundance"))

#' @importFrom dplyr all_of
.internal_extract_abundance <- function(x, taxa.class="all", topn = NULL, rmun = FALSE, ...){
    taxa.class <- rlang::enquo(taxa.class)
    
    taxatree <-  x %>% 
                 mp_extract_tree()
    if (inherits(x, "MPSE")){
        assaysvar <- x %>% SummarizedExperiment::assayNames()
    }else{
        assaysvar <- x %>% attr("assaysvar")
    }
    
    if (is.null(taxatree)){
        taxa.class <- rlang::sym("OTU")
        da <- x %>% mp_extract_feature() %>% 
              dplyr::rename(label="OTU") %>% 
              dplyr::mutate(nodeClass="OTU") 
        if (ncol(da)==1){
            message_wrap("Please make sure the mp_cal_abundance(..., action='add') has been run.
                          Or you can extract the assay via mp_extract_assays since the taxonomy is NULL")
            return(NULL)
        }
        #return(da)
    }else{
        flag <-c(colnames(taxatree@data), colnames(taxatree@extraInfo)) %>% 
               unique() %in% c("node", "nodeClass", "nodeDepth")
        if (length(flag)==3 && all(flag)){
            message("Please make sure the mp_cal_abundance(..., action='add') has been run.")
            return(NULL)        
        }
        da <- taxatree %>% 
              as_tibble %>%    
              dplyr::select(-c("parent", "node", "nodeDepth")) %>%
              dplyr::filter(.data$nodeClass != "Root")
        taxa.class <- rlang::as_name(taxa.class)
        if (taxa.class!="all"){
            da <- da %>% 
                  dplyr::filter(.data$nodeClass == taxa.class)
        }
    }
    
    if (taxa.class!="all"){
        AbundBy <- colnames(da)[vapply(da, is.list, logical(1))]
        AbundBy <- AbundBy[grepl(paste0(assaysvar, collapse = "|"), AbundBy)]
        dat <- da %>% tidyr::unnest(cols=AbundBy[1])
        clnm <- colnames(dat)[vapply(dat, is.numeric, logical(1))]
        if (rmun){
            dat %<>% dplyr::mutate(label=ifelse(grepl("__un_", .data$label), "Others", .data$label))
        }
        totallabel <- dat %>%
              dplyr::group_by(.data$label) %>%
              dplyr::summarize(TotalByLabel=sum(!!as.symbol(clnm[1]))) %>%
              dplyr::arrange(dplyr::desc(.data$TotalByLabel)) %>% 
              dplyr::filter(.data$label != "Others") %>%
              dplyr::pull(.data$label)
        if (is.null(topn)){topn <- length(totallabel)}
        keepn <- min(topn, length(totallabel))
        if (keepn < length(totallabel)){
            keeplabel <- totallabel[seq_len(keepn)]
        }else{
            keeplabel <- totallabel
        }
        dtf <- list()
        for (i in AbundBy){
            df <- da %>% 
                  select(c("label", "nodeClass", i)) %>%
                  tidyr::unnest(cols=i)
            nms <- colnames(df)
            abunnm <- nms[vapply(df, is.numeric, logical(1))]
            gpnm <- nms[!nms %in% c("label", "nodeClass", abunnm)]
            if (gpnm[1]=="Sample"){
                gpnm <- "Sample"
            }else{
                gpnm <- gpnm
            }
            df1 <- df %>% 
                   dplyr::filter(.data$label %in% keeplabel)
            df2 <- df %>%
                   dplyr::filter(!.data$label %in% keeplabel) %>%
                   dplyr::mutate(label="Others") %>% 
                   dplyr::group_by(across(all_of(gpnm))) %>%
                   dplyr::mutate(across(all_of(abunnm), sum)) %>%
                   dplyr::ungroup() %>%
                   distinct() 
            dtf[[i]] <- dplyr::bind_rows(df1, df2) %>%
                  dplyr::mutate(label=factor(.data$label, levels=c(keeplabel, "Others"))) %>%
                  tidyr::nest(!!i:=nms[!nms %in% c("label", "nodeClass")])
    
        }
        da <- dtf %>% purrr::reduce(left_join, by=c("label", "nodeClass"))
    }
    return(da)
}

#' @rdname mp_extract_abundance-methods
#' @aliases mp_extract_abundance,MPSE
#' @export mp_extract_abundance
setMethod("mp_extract_abundance", signature(x="MPSE"), .internal_extract_abundance)

#' @rdname mp_extract_abundance-methods
#' @aliases mp_extract_abundance,tbl_mpse
#' @export mp_extract_abundance
setMethod("mp_extract_abundance", signature(x="tbl_mpse"), .internal_extract_abundance)

#' @rdname mp_extract_abundance-methods
#' @aliases mp_extract_abundance,grouped_df_mpse
#' @export mp_extract_abundance
setMethod("mp_extract_abundance", signature(x="grouped_df_mpse"), .internal_extract_abundance)


.internal_extract_taxonomy <- function(taxatree, classnm){
    if (is.null(taxatree)){
        message(paste0("The taxonomy annotation is empty in the ", classnm," object"))
        return(NULL)
    }
    tip.level <- taxatree %>% 
                 dplyr::filter(.data$isTip, keep.td = FALSE) %>% 
                 pull(.data$nodeClass) %>% 
                 unique()
    taxanm <- taxatree@data %>%
              dplyr::filter(!.data$nodeClass %in% c(tip.level, "Root")) %>%
              dplyr::pull(.data$nodeClass) %>% unique
    taxada <- taxatree_to_tb(taxatree) %>%
              tibble::as_tibble(rownames = "OTU") %>%
              dplyr::select(c("OTU", taxanm)) #%>%
              #tibble::column_to_rownames(var="OTU")
    return(taxada)

}

#' Extracting the PCA, PCoA, etc results from MPSE or tbl_mpse object
#' @rdname mp_extract_internal_attr-methods
#' @param x MPSE or tbl_mpse object
#' @param name character 'PCA' or 'PCoA'
#' @param ... additional parameters
#' @return prcomp or pcoa etc object
#' @export
setGeneric("mp_extract_internal_attr", function(x, name, ...)standardGeneric("mp_extract_internal_attr"))

.internal_extract_internal_attr <- function(x, name, ...){
    name <- rlang::enquo(name) %>% rlang::as_name()
    dat <- x %>% attr("internal_attr")
    message(paste0("The object contained internal attribute: ",paste0(names(dat), collapse=" ")))
    indx <- grep(paste0(name, "$"), names(dat), ignore.case=TRUE)
    if (length(indx)==0){
        return(NULL)
    }
    return(dat[[indx]])
}

#' @rdname mp_extract_internal_attr-methods
#' @aliases mp_extract_internal_attr,MPSE
#' @exportMethod mp_extract_internal_attr
setMethod("mp_extract_internal_attr", signature(x="MPSE"), .internal_extract_internal_attr)

#' @rdname mp_extract_internal_attr-methods
#' @aliases mp_extract_internal_attr,tbl_mpse
#' @exportMethod mp_extract_internal_attr
setMethod("mp_extract_internal_attr", signature(x="tbl_mpse"), .internal_extract_internal_attr)

#' @rdname mp_extract_internal_attr-methods
#' @aliases mp_extract_internal_attr,grouped_df_mpse
#' @exportMethod mp_extract_internal_attr
setMethod("mp_extract_internal_attr", signature(x="grouped_df_mpse"), .internal_extract_internal_attr)

#' @title extract the dist object from MPSE or tbl_mpse object
#' @docType methods
#' @rdname mp_extract_dist-methods
#' @param x MPSE object or tbl_mpse object
#' @param distmethod character the method of calculated distance.
#' @param type character, which type distance to be extracted, 'sample' represents
#' the distance between the samples based on feature abundance matrix, 'feature' represents 
#' the distance between the features based on feature abundance matrix, 'env' represents the
#' the distance between the samples based on continuous environment factors, default is 'sample'.
#' @param .group the column name of sample information, which only work with type='sample' or 
#' type='env', default is NULL, when it is provided, a tibble that can be visualized via ggplot2 
#' will return.
#' @param ... additional parameters
#' @return dist object or tbl_df object when .group is provided.
#' @export
setGeneric("mp_extract_dist", function(x, distmethod, type='sample', .group=NULL, ...)standardGeneric("mp_extract_dist"))

.internal_extract_dist <- function(x, distmethod, type='sample', .group=NULL, ...){
    .group <- rlang::enquo(.group)
    dots <- list(...)
    type %<>% match.arg(c('sample', 'feature', 'env'))

    if ('env.flag' %in% names(dots)){
        if (dots$env.flag){
            type <- 'env'
        }else{
            type <- 'sample'
        }
    }

    if(type == 'feature'){
        data <- x %>% mp_extract_feature(addtaxa = TRUE)
        distname <- paste0(distmethod, 'Featurey') %>% as.symbol()
        distmethod <- paste0('Feature_', distmethod)
        .group <- rlang::quo(NULL)
        prefix <- 'OTU'
    }else{
        data <- x %>% mp_extract_sample()
        if (type == 'env'){
           distmethod <- paste0('Env_', distmethod) 
        }
        distname <- paste0(distmethod, "Sampley") %>% as.symbol()
        prefix <- 'Sample'
    }
           
    #data <- x %>% mp_extract_sample()
    #distmethod <- switch(as.character(type),
    #                     "TRUE" = paste0("Env_", distmethod),
    #                     "FALSE" = distmethod)
    
    if (!distmethod %in% colnames(data)){
        rlang::abort(paste0("There is not ", distmethod, 
                            " distance in the object, please check whether the mp_cal_dist has been performed!"))
    }
    
    #distname <- paste0(distmethod, "Sampley") %>% as.symbol()
    
    if (rlang::quo_is_null(.group)){
        distobj <- data %>%
                select(c(prefix, distmethod)) %>%
                distinct() %>%
                tidyr::unnest() %>%
                suppressWarnings() %>%
                rename(x=prefix, y=distname, d=distmethod) %>%
                .df_to_dist() %>%
                add_attr(distmethod, 'method')
        return(distobj)
    }else{
        group.y <- paste0(rlang::as_name(.group), ".tmp") %>% as.symbol()
        dist.tb <- data %>%
                   dplyr::select(c(prefix, distmethod, !!.group)) %>%
                   tidyr::unnest(cols=distmethod) %>%
                   dplyr::mutate(dplyr::across(!!.group, 
                                               ~.x[match(!!as.symbol(distname), !!as.symbol(prefix))], 
                                               .names=rlang::as_name(group.y))) %>% 
                   dplyr::rowwise() %>% 
                   dplyr::mutate(GroupsComparison=paste0(sort(c(!!.group, !!group.y)),collapse="-vs-")) %>%
                   dplyr::filter(!!rlang::sym(prefix) != !!as.symbol(distname)) %>%
                   dplyr::select(c(prefix, distmethod, "GroupsComparison", distname))
        return(dist.tb)
    }
}

#' @rdname mp_extract_dist-methods
#' @aliases mp_extract_dist,MPSE
#' @exportMethod mp_extract_dist
setMethod("mp_extract_dist", signature(x="MPSE"), .internal_extract_dist)

#' @rdname mp_extract_dist-methods
#' @aliases mp_extract_dist,tbl_mpse
#' @exportMethod mp_extract_dist
setMethod("mp_extract_dist", signature(x="tbl_mpse"), .internal_extract_dist)

#' @rdname mp_extract_dist-methods
#' @aliases mp_extract_dist,grouped_df_mpse
#' @exportMethod mp_extract_dist
setMethod("mp_extract_dist", signature(x="grouped_df_mpse"), .internal_extract_dist)


.internal_tree <- function(x, type, tip.level){
    tip.level <- rlang::enquo(tip.level)
    type %<>% match.arg(c("taxatree", "otutree"))
    tree <- x %>% attr(type)
    if (!is.null(tree)){
        if (type == "taxatree"){
            tree <- .extract_tree_at_tiplevel(tree, tip.level=!!tip.level)
        }
        return(tree)
    }else{
        message(tree_empty(type=type))
    }
}

#' @importFrom treeio drop.tip
.extract_tree_at_tiplevel <- function(tree, tip.level){
    tip.level <- rlang::enquo(tip.level) %>% rlang::as_name()
    if (tip.level == "OTU"){
        return(tree)
    }
    rmnms <- tree %>% as_tibble %>% 
             dplyr::filter(.data$nodeDepth > .data$nodeDepth[match(tip.level, .data$nodeClass)]) %>%
             select(.data$label, .data$nodeDepth) %>% 
             group_by(.data$nodeDepth) %>% 
             dplyr::summarize(label=list(.data$label)) %>% 
             arrange(dplyr::desc(.data$nodeDepth)) %>% 
             pull(.data$label) 
    if (length(rmnms) > 0){
        for ( i in rmnms){
            tree <- drop.tip(tree, tip=i, collapse.singles=FALSE, trim.internal=FALSE)
        }
    }
    return(tree)
}

tree_empty <- function(type){
    x <- paste0("The ", type," is empty in the MPSE object!")
    return(x)
}

#' @rdname MPSE-accessors
#' @param x MPSE object
#' @export
setGeneric("otutree", function(x, ...)standardGeneric("otutree"))

#' @rdname MPSE-accessors
#' @aliases otutree,MPSE
#' @export
setMethod("otutree", signature(x="MPSE"), function(x,...){
    tree <- x %>% mp_extract_otutree(...)
    return(tree)
})


#' @rdname MPSE-accessors
#' @aliases otutree,tbl_mpse
#' @export
setMethod("otutree", signature(x="tbl_mpse"), function(x,...){
    tree <- x %>% mp_extract_otutree(...)
    return(tree)
})

#' @rdname MPSE-accessors
#' @aliases otutree,group_df_mpse
#' @export
setMethod("otutree", signature(x="MPSE"), function(x,...){
    tree <- x %>% mp_extract_otutree(...)
    return(tree)
})

#' @rdname MPSE-accessors 
#' @param x MPSE object
#' @param value treedata class, phylo class or NULL
#' @export
setGeneric("otutree<-", function(x, ..., value)standardGeneric("otutree<-"))

.internal_otutree_replace <- function(x, ..., value){
    if (inherits(value, "treedata")){
        newnms <- intersect(rownames(x), value@phylo$tip.label)
    }else if(inherits(value, "phylo")){
        newnms <- intersect(rownames(x), value$tip.label)
    }
    if (length(newnms)==0){
        stop_wrap("There are not the same labels between tip labels of the tree 
                   and the rownames of mpse, please check the tree is correct")
    }
    if (length(newnms) != nrow(x)){
        dropnms <- setdiff(rownames(x), newnms)
        message_wrap("droping rows without the input tree matches:")
        message_wrap(paste0(dropnms, collapse="\n"))
        x <- x[rownames(x) %in% newnms,]
    }
    x@otutree <- .internal_drop.tip(tree=value, newnm=rownames(x), collapse.singles=FALSE) %>%
                 as.treedata() 
    methods::validObject(x)
    return(x)
}

#' @rdname MPSE-accessors
#' @aliases otutree<-,MPSE
#' @export
setReplaceMethod("otutree", signature(x="MPSE", value="treedata"), .internal_otutree_replace)

#' @rdname MPSE-accessors
#' @aliases otutree<-,MPSE
#' @export
setReplaceMethod("otutree", signature(x="MPSE", value="phylo"), .internal_otutree_replace)

#' @rdname MPSE-accessors
#' @aliases otutree<-,MPSE
#' @export
setReplaceMethod("otutree", signature(x="MPSE", value="NULL"), function(x, ..., value){
    x@otutree <- NULL
    methods::validObject(x)
    return(x)
})

.internal_replace_otutree2 <- function(x, ..., value){
    nms <- x %>% dplyr::pull(.data$OTU) %>% unique()
    value <- .internal_drop.tip(tree = value, newnm = nms, collapse.singles = FALSE)
    x %<>%
          add_attr(value, name="otutree")
    return(x)
}

#' @rdname MPSE-accessors
#' @aliases otutree<-,tbl_mpse
#' @export
setReplaceMethod("otutree", signature(x="tbl_mpse", value="treedata"), .internal_replace_otutree2)

#' @rdname MPSE-accessors
#' @aliases otutree<-,grouped_df_mpse
#' @export
setReplaceMethod("otutree", signature(x="grouped_df_mpse", value="treedata"), .internal_replace_otutree2)

#' @rdname MPSE-accessors
#' @aliases otutree<-,tbl_mpse
#' @export
setReplaceMethod("otutree", signature(x="tbl_mpse", value="NULL"), .internal_replace_otutree2)

#' @rdname MPSE-accessors
#' @aliases otutree<-,grouped_df_mpse
#' @export
setReplaceMethod("otutree", signature(x="grouped_df_mpse", value="NULL"), .internal_replace_otutree2)

#' @rdname MPSE-accessors
#' @param x MPSE object
#' @export
setGeneric("taxatree", function(x, ...)standardGeneric("taxatree"))

#' @rdname MPSE-accessors
#' @aliases taxatree,MPSE
#' @export
setMethod("taxatree", signature(x="MPSE"),function(x, ...){
    tree <- x %>% mp_extract_taxatree(...)
    return(tree)
})

#' @rdname MPSE-accessors
#' @aliases taxatree,tbl_mpse
#' @export
setMethod("taxatree", signature(x = 'tbl_mpse'), function(x, ...){
    x %>% mp_extract_taxatree(...)
})

#' @rdname MPSE-accessors
#' @aliases taxatree,grouped_df_mpse
#' @export
setMethod('taxatree', signature(x = 'grouped_df_mpse'), function(x, ...){
    x %>% mp_extract_taxatree(...)
})

#' @rdname MPSE-accessors
#' @param x MPSE object
#' @param value  treedata object or NULL
#' @export
setGeneric("taxatree<-", function(x, ..., value)standardGeneric("taxatree<-"))

#' @rdname MPSE-accessors
#' @aliases taxatree<-,MPSE
#' @export
setReplaceMethod("taxatree", signature(x="MPSE", value="treedata"), function(x, ..., value){
    newnms <- intersect(rownames(x), value@phylo$tip.label)
    if (length(newnms) != nrow(x)){
        dropnms <- setdiff(rownames(x), newnms)
        message_wrap("droping rows without the input taxonomy matches:")
        message_wrap(paste0(dropnms, collapse="\n"))
        x <- x[rownames(x) %in% newnms,]
    }
    if (length(newnms)==0){
        stop_wrap("There are not the same labels between rownames of the taxonomy information 
                   and the rownames of mpse, please check the taxonomy is correct.")
    }
    x@taxatree <- .internal_drop.tip(tree=value, newnm=rownames(x), collapse.singles=FALSE)
    methods::validObject(x)
    return(x)
})

#' @rdname MPSE-accessors
#' @aliases taxatree<-,MPSE
#' @export
setReplaceMethod("taxatree", signature(x="MPSE", value="NULL"), function(x, ..., value){
    x@taxatree <- NULL
    methods::validObject(x)
    return(x)
})

.internal_replace_taxatree <- function(x, ..., value){
    attr(x, 'taxatree') <- value
    return(x)
}

#' @rdname MPSE-accessors
#' @aliases taxatree<-,tbl_mpse
#' @export
setReplaceMethod('taxatree', signature(x = 'tbl_mpse', value = 'treedata'), .internal_replace_taxatree)

#' @rdname MPSE-accessors
#' @aliases taxatree<-,tbl_mpse
#' @export
setReplaceMethod('taxatree', signature(x = 'tbl_mpse', value = 'NULL'), .internal_replace_taxatree)

#' @rdname MPSE-accessors
#' @aliases taxatree<-,grouped_df_mpse
#' @export
setReplaceMethod('taxatree', signature(x = 'grouped_df_mpse', value = 'treedata'), .internal_replace_taxatree)

#' @rdname MPSE-accessors
#' @aliases taxatree<-,grouped_df_mpse
#' @export 
setReplaceMethod('taxatree', signature(x = 'grouped_df_mpse', value = 'NULL'), .internal_replace_taxatree)


#' @rdname MPSE-accessors
#' @param x MPSE object
#' @param value data.frame, matrix, taxonomyTable or NULL
#' @export
setGeneric("taxonomy<-", function(x, ..., value)standardGeneric("taxonomy<-"))

.internal_taxonomy_replace <- function(x, ..., value){
    if (is.null(value)){
        taxa.tree <- NULL
    }else{
        taxa.tree <- value %>% convert_to_treedata(include.rownames = TRUE, ...)
    }
    taxatree(x) <- taxa.tree
    return(x)
}

#' @rdname MPSE-accessors
#' @aliases taxonomy<-,MPSE
#' @export
setReplaceMethod("taxonomy", signature(x = "MPSE", value = "data.frame"), .internal_taxonomy_replace)

#' @rdname MPSE-accessors
#' @aliases taxonomy<-,MPSE
#' @export
setReplaceMethod("taxonomy", signature(x = "MPSE", value = "matrix"), .internal_taxonomy_replace)

#' @rdname MPSE-accessors
#' @aliases taxonomy<-,MPSE
#' @export
setReplaceMethod("taxonomy", signature(x = "MPSE", value = "taxonomyTable"), .internal_taxonomy_replace)

#' @rdname MPSE-accessors
#' @aliases taxonomy<-,MPSE
#' @export
setReplaceMethod("taxonomy", signature(x = "MPSE", value = "NULL"), .internal_taxonomy_replace)

#' @rdname MPSE-accessors
#' @param x MPSE object
#' @export
setGeneric("refsequence", function(x, ...)standardGeneric("refsequence"))

#' @rdname MPSE-accessors
#' @aliases refsequence,MPSE
#' @export
setMethod("refsequence", signature(x="MPSE"), function(x, ...){
    refseq <- x@refseq
    if (is.null(refseq)){
        message("The representative sequence is empty")
    }
    return(refseq)
})

#' @rdname MPSE-accessors
#' @param x MPSE object
#' @param value XStringSet object or NULL
#' @export
setGeneric("refsequence<-", function(x, ..., value)standardGeneric("refsequence<-"))

#' @rdname MPSE-accessors
#' @aliases refsequence<-,MPSE
#' @export
setReplaceMethod("refsequence", signature(x="MPSE", value="XStringSet"), function(x, ..., value){
    x@refseq <- value[rownames(x)]
    methods::validObject(x)
    return(x)
})

#' @rdname MPSE-accessors
#' @aliases refsequence<-,MPSE
#' @export
setReplaceMethod("refsequence", signature(x="MPSE", value="NULL"), function(x, ..., value){
    x@refseq <- NULL
    methods::validObject(x)
    return(x)
})

#' Extract the representative sequences from MPSE object
#' @param x MPSE object
#' @param ... additional parameters, meaningless now.
#' @rdname mp_extract_refseq-methods
#' @export
setGeneric("mp_extract_refseq", function(x, ...)standardGeneric("mp_extract_refseq"))

.internal_extract_refseq <- function(x, ...){
    if (inherits(x, "MPSE")){
        ref.seq <- x@refseq
    }else{
        ref.seq <- x %>% attr("refseq")
    }
    return(ref.seq)
}

#' @rdname mp_extract_refseq-methods
#' @aliases mp_extract_refseq,MPSE
#' @export mp_extract_refseq
setMethod("mp_extract_refseq", signature(x="MPSE"), .internal_extract_refseq)

#' @rdname mp_extract_refseq-methods
#' @aliases mp_extract_refseq,tbl_mpse
#' @export mp_extract_refseq
setMethod("mp_extract_refseq", signature(x="tbl_mpse"), .internal_extract_refseq)

#' @rdname mp_extract_refseq-methods
#' @aliases mp_extract_refseq,grouped_df_mpse
#' @export mp_extract_refseq
setMethod("mp_extract_refseq", signature(x="grouped_df_mpse"), .internal_extract_refseq)


#' @rdname MPSE-accessors
#' @aliases rownames<-,MPSE
#' @export
setReplaceMethod("rownames", signature(x="MPSE"), function(x, value){
    nx <- methods::callNextMethod()
    oldnm <- rownames(x)
    if (!is.null(x@otutree)){
        nx@otutree <- rename_tiplab(x@otutree, oldname=oldnm, newname=value)
    }
    if (!is.null(x@taxatree)){
        nx@taxatree <- rename_tiplab(x@taxatree, oldname=oldnm, newname=value)
    }
    if (!is.null(x@refseq)){
        if (is.null(value)){
            nx@refseq <- NULL
        }else{
            names(nx@refseq) <- value[match(names(x@refseq), oldnm)]
        }
    }

    if (!is.null(value) && !is.null(oldnm)){
        old2new <- data.frame(.NEW=value, .OLDROWNAMES=oldnm) 
        old2new %<>% dplyr::left_join(x %>% mp_extract_feature(), by=c(.OLDROWNAMES="OTU")) %>%
                   tibble::column_to_rownames(var=".NEW")
        
        SummarizedExperiment::rowData(nx) <- old2new
    }
    methods::validObject(nx)
    return(nx)
})

#' select specific taxa level as rownames of MPSE
#' @param x MPSE object
#' @param tip.level the taxonomy level, default is 'OTU'.
#' @rdname mp_select_as_tip-methods
#' @export
#' @examples
#' \dontrun{
#' data(mouse.time.mpse)
#' newmpse <- mouse.time.mpse %>%
#'            mp_select_as_tip(tip.level = Species)
#' newmpse
#' }
setGeneric("mp_select_as_tip", function(x, tip.level = 'OTU')standardGeneric("mp_select_as_tip"))

.mp_select_tip <- function(x, tip.level="OTU"){
    tip.level <- rlang::enquo(tip.level)
    if (rlang::as_name(tip.level) == "OTU" || is.null(taxatree(x))){
        return(x)
    }
    newassay <- x %>% mp_cal_abundance(
       .abundance = "Abundance", 
       force = TRUE, 
       relative = FALSE,
       action = 'only'
    ) %>%
    suppressMessages() %>%
    dplyr::filter(.data$nodeClass == rlang::as_name(tip.level)) %>%
    tidyr::unnest(cols = "AbundanceBySample") %>%
    select("label", "Sample", "Abundance") %>%
    tidyr::pivot_wider(
       id_cols = "label", 
       names_from = "Sample", 
       values_from = "Abundance"
    ) %>%
    tibble::column_to_rownames(var = 'label')

    abund <- x %>% mp_extract_assays(.abundance="Abundance")
    if (is.null(x %>% mp_extract_assays(.abundance="RareAbundance")) %>% suppressMessages() &&
        identical(all.equal(abund, round(abund)), TRUE)
        ){
        message_wrap("
           The assays slot of original MPSE does not contain RareAbundance,
           The mp_rrarefy() will be run before selecting the specific tip level automatically.
                     ")
        x %<>% mp_rrarefy()
    }

    if ("RareAbundance" %in% SummarizedExperiment::assayNames(x)){
        newassay <- list(
          Abundance = newassay, 
          RareAbundance = x %>% mp_cal_abundance(
                .abundance = "RareAbundance",
                force = TRUE,
                relative = FALSE,
                action = "only"
            ) %>%
            suppressMessages() %>%
            dplyr::filter(.data$nodeClass == rlang::as_name(tip.level)) %>%
            tidyr::unnest(cols = "RareAbundanceBySample") %>%
            select("label", "Sample", "RareAbundance") %>%
            tidyr::pivot_wider(
               id_cols = "label",
               names_from = "Sample",
               values_from = "RareAbundance"
            ) %>%
            tibble::column_to_rownames(var = 'label') 
        )
    }

    taxa.tree <- x %>% mp_extract_taxatree(tip.level = !!tip.level)
    mpse <- MPSE(assays = newassay, taxatree = taxa.tree)
    if (inherits(x, "MPSE")){
        colData(mpse) <- SummarizedExperiment::colData(x)
    }else{
        mpse <- as_tibble(mpse) %>% 
                dplyr::left_join(x %>% mp_extract_sample, by="Sample")
    }
    return(mpse)
}

#' @rdname mp_select_as_tip-methods
#' @aliases mp_select_as_tip,MPSE
#' @export mp_select_as_tip
setMethod("mp_select_as_tip", signature(x = "MPSE"), .mp_select_tip)

#' @rdname mp_select_as_tip-methods
#' @aliases mp_select_as_tip,tbl_mpse
#' @export mp_select_as_tip
setMethod("mp_select_as_tip", signature(x = "tbl_mpse"), .mp_select_tip)

#' @rdname mp_select_as_tip-methods
#' @aliases mp_select_as_tip,grouped_df_mpse
#' @export mp_select_as_tip
setMethod("mp_select_as_tip", signature(x = "grouped_df_mpse"), .mp_select_tip)

rename_tiplab <- function(treedata, oldname, newname){
    if (is.null(newname)){
        return(NULL)
    }
    tip.label <- treedata@phylo$tip.label
    treedata@phylo$tip.label <- newname[match(tip.label, oldname)]
    return(treedata)
}

.internal_drop.tip <- function(tree, newnm=NULL, collapse.singles=TRUE, rmotus=NULL){
    if (is.null(tree)){
        return (NULL)
    }
    if (is.null(rmotus)){
        if (inherits(tree, "treedata")){
            rmotus <- setdiff(tree@phylo$tip.label, newnm)
        }else if (inherits(tree, "phylo")){
            rmotus <- setdiff(tree$tip.label, newnm)
        }
    }
    if (length(rmotus) > 0 && length(rmotus) != treeio::Ntip(tree)){
        otutree <- treeio::drop.tip(tree, tip=rmotus, collapse.singles=collapse.singles) %>%
            suppressMessages() %>%
            suppressWarnings()
    }else{
        otutree <- tree
    }
    return (otutree)
}

.dist2tbl <- function(x, y){
    distmethod <- 'DistFromOutSide'
    if (inherits(x, 'list')){
        if (!is.null(names(x))){
            distmethod <- names(x)
        }
        x <- x[[1]]
    }
    x1 <- as.matrix(x)
    flag <- match(unique(dim(x1)), dim(y))
    if (is.na(flag)){
        stop_wrap('The y is a dist object, but the dimension is different with the x (mpse).')
    }
    if (flag == 1){
        x.name <- 'OTU'
    }else{
        x.name <- 'Sample'
    }
    distsampley <- paste0(distmethod, x.name, 'y')
    x <- x %>%
        .dist_to_df() %>%
        dplyr::rename(!!distmethod:="d", !!distsampley:="y", !!x.name:='x') %>%
        tidyr::nest(!!distmethod:=c(!!as.symbol(distsampley), !!as.symbol(distmethod)))
    return(x)
}
xiangpin/MicrobitaProcess documentation built on April 12, 2024, 9:03 p.m.