Skip to content

Commit

Permalink
Merge pull request #193 from Artur-man/main
Browse files Browse the repository at this point in the history
push to dev
  • Loading branch information
Artur-man authored Jan 20, 2025
2 parents ae1d88d + 573d1de commit 99ae8b7
Show file tree
Hide file tree
Showing 10 changed files with 191 additions and 127 deletions.
4 changes: 3 additions & 1 deletion .Rbuildignore
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,6 @@ git
dev
^.github$
^index\.md$
^LICENSE\.md$
^LICENSE\.md$
Dockerfile
environment.yml
8 changes: 6 additions & 2 deletions .github/workflows/check.yml
Original file line number Diff line number Diff line change
Expand Up @@ -148,8 +148,6 @@ jobs:
# All Other dependencies
- name: Install Suggested dependencies
run: |
install.packages(c('reticulate'))
BiocManager::install(c('basilisk'))
BiocManager::install(c('DelayedArray'))
BiocManager::install(c('HDF5Array'))
remotes::install_github('bnprks/BPCells/[email protected]')
Expand Down Expand Up @@ -183,3 +181,9 @@ jobs:
check_dir = "check"
)
shell: Rscript {0}

# All Other dependencies
- name: Install other Suggested dependencies
run: |
install.packages(c('reticulate'))
BiocManager::install(c('basilisk'))
3 changes: 2 additions & 1 deletion .github/workflows/docker.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ on:
push:
branches:
- main
- dev

jobs:
push_to_registry:
Expand Down Expand Up @@ -38,7 +39,7 @@ jobs:
uses: docker/build-push-action@3b5e8027fcad23fda98b2e3ac259d8d67585f671
with:
context: .
file: ./inst/extdata/Dockerfile
file: Dockerfile
push: true
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
23 changes: 19 additions & 4 deletions inst/extdata/Dockerfile → Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,28 @@ RUN apt-get update
RUN apt-get install -y libgdal-dev libfftw3-dev libmagick++-dev cmake libhdf5-dev git libopencv-dev libopencv-features2d-dev
RUN apt-get install -y libssl-dev libcurl4-openssl-dev libgit2-dev libxml2-dev libfontconfig1-dev libharfbuzz-dev libfribidi-dev libfreetype6-dev libpng-dev libtiff5-dev libjpeg-dev libz-dev

# build conda
RUN ls
RUN wget https://github.com/conda-forge/miniforge/releases/download/24.11.2-1/Miniforge3-Linux-aarch64.sh
RUN bash Miniforge3-Linux-aarch64.sh -b
SHELL ["/bin/bash", "-c"]
RUN /root/miniforge3/bin/conda init
RUN source /root/.bashrc

# build voltron env
ADD environment.yml environment.yml
RUN /root/miniforge3/bin/conda env create -f environment.yml

# OpenCV
RUN git clone https://github.com/opencv/opencv.git
RUN git clone https://github.com/opencv/opencv_contrib.git
RUN wget https://github.com/opencv/opencv/archive/refs/tags/4.8.1.zip
RUN unzip 4.8.1.zip
RUN rm 4.8.1.zip
RUN wget https://github.com/opencv/opencv_contrib/archive/refs/tags/4.8.1.zip
RUN unzip 4.8.1.zip
RUN rm 4.8.1.zip
RUN mkdir build
WORKDIR "build"
RUN cmake -D CMAKE_BUILD_TYPE=RELEASE -D CMAKE_INSTALL_PREFIX=/usr/local -D INSTALL_C_EXAMPLES=ON -D INSTALL_PYTHON_EXAMPLES=ON -D OPENCV_GENERATE_PKGCONFIG=ON -D OPENCV_EXTRA_MODULES_PATH=../opencv_contrib/modules/ -D BUILD_opencv_xfeatures2d=ON ../opencv/
RUN cmake -D CMAKE_BUILD_TYPE=RELEASE -D CMAKE_INSTALL_PREFIX=/usr/local -D INSTALL_C_EXAMPLES=ON -D INSTALL_PYTHON_EXAMPLES=ON -D OPENCV_GENERATE_PKGCONFIG=ON -D OPENCV_EXTRA_MODULES_PATH=../opencv_contrib-4.8.1/modules/ -D BUILD_opencv_xfeatures2d=ON ../opencv-4.8.1/
RUN make -j5
RUN make install
RUN sh -c 'echo "/usr/local/lib" > /etc/ld.so.conf.d/opencv.conf'
Expand All @@ -27,7 +43,6 @@ RUN R -e "BiocManager::install(c('EBImage', 'S4Arrays'))"

# Install Suggested dependencies
RUN R -e "install.packages(c('reticulate'))"
RUN R -e "BiocManager::install(c('basilisk'))"
RUN R -e "BiocManager::install(c('DelayedArray'))"
RUN R -e "BiocManager::install(c('HDF5Array'))"
RUN R -e "remotes::install_github('bnprks/BPCells/[email protected]')"
Expand Down
1 change: 0 additions & 1 deletion NAMESPACE
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,6 @@ S3method(addFeature,vrAssayV2)
S3method(as.VoltRon,Seurat)
S3method(as.VoltRon,SpatialExperiment)
S3method(as.Zarr,"magick-image")
S3method(as.Zarr,VoltRon)
S3method(combineChannels,VoltRon)
S3method(combineChannels,vrAssay)
S3method(combineChannels,vrAssayV2)
Expand Down
172 changes: 87 additions & 85 deletions R/conversion.R
Original file line number Diff line number Diff line change
Expand Up @@ -248,6 +248,7 @@ convertAnnDataToVoltRon <- function(file, AssayID = NULL, ...){
#' @param flip_coordinates if TRUE, the spatial coordinates (including segments) will be flipped.
#' @param method the package to use for conversion: "anndataR" or "anndata".
#' @param create.ometiff should an ometiff file be generated of default image of the object
#' @param python.path the path to the python binary, otherwise \code{basilisk} package is used.
#' @param ... additional parameters passed to \link{vrImages}.
#'
#' @details
Expand All @@ -267,6 +268,7 @@ as.AnnData <- function(object,
flip_coordinates = FALSE,
method = "anndata",
create.ometiff = FALSE,
python.path = NULL,
...) {

# Check the number of assays
Expand Down Expand Up @@ -361,32 +363,61 @@ as.AnnData <- function(object,
stop("Please install DelayedArray package for using DelayedArray functions")

# run basilisk to call zarr methods
py_env <- getBasilisk()
proc <- basilisk::basiliskStart(py_env)
on.exit(basilisk::basiliskStop(proc))
success <- basilisk::basiliskRun(proc, function(data, metadata, obsm, coords, segments, image_list, file) {
zarr <- reticulate::import("zarr")
anndata <- reticulate::import("anndata")
make_numpy_friendly <- function(x) {
if (DelayedArray::is_sparse(x)) {
methods::as(x, "dgCMatrix")
if(is.null(python.path)){
py_env <- getBasilisk()
proc <- basilisk::basiliskStart(py_env)
on.exit(basilisk::basiliskStop(proc))
success <- basilisk::basiliskRun(proc, function(data, metadata, obsm, coords, segments, image_list, file) {
zarr <- reticulate::import("zarr")
anndata <- reticulate::import("anndata")
make_numpy_friendly <- function(x) {
if (DelayedArray::is_sparse(x)) {
methods::as(x, "dgCMatrix")
}
else {
as.matrix(x)
}
}
else {
as.matrix(x)
X <- make_numpy_friendly(t(data))
obsm <- list(spatial = coords,
spatial_AssayID = coords,
segmentation = segmentations_array)
adata <- anndata$AnnData(X = X,
obs = metadata,
obsm = obsm,
uns = list(spatial = image_list))
adata <- reticulate::r_to_py(adata)
adata$write_zarr(file)
return(TRUE)
}, data = data, metadata = metadata, obsm = obsm, coords = coords, segments = segmentations_array, image_list = image_list, file = file)
} else {
if(file.exists(python.path)){
reticulate::use_python(python = python.path)
zarr <- reticulate::import("zarr")
anndata <- reticulate::import("anndata")
make_numpy_friendly <- function(x) {
if (DelayedArray::is_sparse(x)) {
methods::as(x, "dgCMatrix")
}
else {
as.matrix(x)
}
}
X <- make_numpy_friendly(t(data))
obsm <- list(spatial = coords,
spatial_AssayID = coords,
segmentation = segmentations_array)
adata <- anndata$AnnData(X = X,
obs = metadata,
obsm = obsm,
uns = list(spatial = image_list))
adata <- reticulate::r_to_py(adata)
adata$write_zarr(file)
} else {
stop("The python path '", python.path, "' doesn't exist!")
}
X <- make_numpy_friendly(t(data))
obsm <- list(spatial = coords,
spatial_AssayID = coords,
segmentation = segmentations_array)
adata <- anndata$AnnData(X = X,
obs = metadata,
obsm = obsm,
uns = list(spatial = image_list))
adata <- reticulate::r_to_py(adata)
adata$write_zarr(file)
return(TRUE)
}, data = data, metadata = metadata, obsm = obsm, coords = coords, segments = segmentations_array, image_list = image_list, file = file)
}

if(create.ometiff){
success2 <- as.OmeTiff(images_mgk[[1]], out_path = gsub("zarr[/]?$", "ome.tiff", file))
success <- success & success2
Expand Down Expand Up @@ -421,6 +452,15 @@ as.AnnData <- function(object,
stop("The anndata package is not installed. Please install it or choose the 'anndataR' method.")
}

# check reticulate
if(!is.null(python.path)){
if(file.exists(python.path)){
print(reticulate::py_config())
} else {
stop("The python path '", python.path, "' doesn't exist!")
}
}

# Create anndata using anndata
adata <- anndata::AnnData(X = t(data),
obs = metadata,
Expand All @@ -442,71 +482,33 @@ as.AnnData <- function(object,
}
}

# write_anndata_zarr <- function(data, metadata, obsm, coords, segments, image_list, file){
# zarr <- reticulate::import("zarr")
# anndata <- reticulate::import("anndata")
# make_numpy_friendly <- function(x) {
# if (DelayedArray::is_sparse(x)) {
# methods::as(x, "dgCMatrix")
# }
# else {
# as.matrix(x)
# }
# }
# X <- make_numpy_friendly(t(data))
# obsm <- list(spatial = coords,
# spatial_AssayID = coords,
# segmentation = segmentations_array)
# adata <- anndata$AnnData(X = X,
# obs = metadata,
# obsm = obsm,
# uns = list(spatial = image_list))
# adata <- reticulate::r_to_py(adata)
# adata$write_zarr(file)
# }

####
# AnnData (Zarr) ####
# Zarr ####
####

#' @rdname as.Zarr
#'
#' @importFrom magick image_raster
#' @importFrom grDevices col2rgb
#'
#' @export
as.Zarr.VoltRon <- function (object, out_path, image_id = "image_1")
{

# check packages
if(!requireNamespace('basilisk'))
stop("Please install basilisk package!: BiocManager::install('basilisk')")
if(!requireNamespace('reticulate'))
stop("Please install reticulate package!: install.packages('reticulate')")
if(!requireNamespace('DelayedArray'))
stop("Please install DelayedArray package for using DelayedArray functions")

# object data
datax <- vrData(object, norm = FALSE)
metadata <- Metadata(object)

# obsm
obsm <- list()
coords <- vrCoordinates(object)
obsm[["spatial"]] <- t(as.matrix(coords))
if (length(vrEmbeddingNames(object)) > 0) {
for (embed_name in vrEmbeddingNames(object)) {
embedding <- vrEmbeddings(object, type = embed_name)
obsm[[embed_name]] <- t(as.matrix(embedding))
}
}

py_env <- getBasilisk()
proc <- basilisk::basiliskStart(py_env)
on.exit(basilisk::basiliskStop(proc))
success <- basilisk::basiliskRun(proc, function(datax, metadata, obsm, out_path) {
anndata <- reticulate::import("anndata")
zarr <- reticulate::import("zarr")
make_numpy_friendly <- function(x, transpose = TRUE) {
if (transpose) {
x <- Matrix::t(x)
}
if (DelayedArray::is_sparse(x)) {
methods::as(x, "dgCMatrix")
}
else {
as.matrix(x)
}
}
X <- make_numpy_friendly(datax)
adata <- anndata$AnnData(X = X, obs = metadata)
if (length(obsm) > 0) {
obsm <- lapply(obsm, make_numpy_friendly)
adata$obsm <- obsm
}
adata$write_zarr(out_path)
return(TRUE)
}, datax = datax, metadata = metadata, obsm = obsm, out_path = out_path)
return(success)
}

#' @rdname as.Zarr
#'
#' @importFrom magick image_raster
Expand Down
22 changes: 22 additions & 0 deletions environment.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
name: voltron
channels:
- bioconda
- conda-forge
dependencies:
- python==3.10.14
- numpy==1.*
- pandas==1.*
- anndata==0.8.*
#- anndata==0.7.*
- h5py==3.*
- hdf5==1.*
- natsort==7.*
- packaging==20.*
- scipy==1.*
- sqlite==3.*
- zarr==2.*
- numcodecs==0.*
- tifffile==2024.2.12
- pip
- pip:
- ome-zarr==0.2.1
3 changes: 3 additions & 0 deletions man/as.AnnData.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 0 additions & 3 deletions man/as.Zarr.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading

0 comments on commit 99ae8b7

Please sign in to comment.