Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Convert this into a standalone library. #2

Merged
merged 4 commits into from
Jul 16, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 36 additions & 0 deletions .github/workflows/check-install.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
on:
push:
branches:
- master
pull_request:

name: Check CMake install

jobs:
install:
runs-on: ubuntu-latest

steps:
- uses: actions/checkout@v4

- name: Get latest CMake
uses: lukka/get-cmake@latest

- name: Configure the build
run: cmake -S . -B build -DSCRAN_PCA_TESTS=OFF

- name: Install the library
run: sudo cmake --install build

- name: Test downstream usage
run: |
mkdir _downstream
touch _downstream/source.cpp
cat << EOF > _downstream/CMakeLists.txt
cmake_minimum_required(VERSION 3.24)
project(test_install)
add_executable(whee source.cpp)
find_package(libscran_scran_pca)
target_link_libraries(whee libscran::scran_pca)
EOF
cd _downstream && cmake -S . -B build
71 changes: 64 additions & 7 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,20 +1,77 @@
cmake_minimum_required(VERSION 3.14)

project(scran_principal_component_analysis
project(scran_pca
VERSION 1.0.0
DESCRIPTION "Principal components analysis for single-cell data"
LANGUAGES CXX)

add_library(scran_principal_component_analysis INTERFACE)
target_compile_features(scran_principal_component_analysis INTERFACE cxx_std_17)
target_include_directories(scran_principal_component_analysis INTERFACE include/scran)
include(GNUInstallDirs)
include(CMakePackageConfigHelpers)

add_subdirectory(extern)
target_link_libraries(scran_principal_component_analysis INTERFACE scran_core_utils tatami::tatami tatami::tatami_stats ltla::irlba Eigen3::Eigen)
# Library
add_library(scran_pca INTERFACE)
add_library(libscran::scran_pca ALIAS scran_pca)

target_include_directories(scran_pca INTERFACE
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}/scran_pca>)
target_compile_features(scran_pca INTERFACE cxx_std_17)

# Dependencies
option(SCRAN_PCA_FETCH_EXTERN "Automatically fetch scran_pca's external dependencies." ON)
if(SCRAN_PCA_FETCH_EXTERN)
add_subdirectory(extern)
else()
find_package(tatami_tatami 3.0.0 CONFIG REQUIRED)
find_package(tatami_tatami_stats 1.0.0 CONFIG REQUIRED)
find_package(libscran_scran_blocks 1.0.0 CONFIG REQUIRED)
find_package(ltla_irlba 2.0.0 CONFIG REQUIRED)
find_package(Eigen3 3.4.0 REQUIRED NO_MODULE)
endif()

target_link_libraries(
scran_pca INTERFACE
tatami::tatami
tatami::tatami_stats
libscran::scran_blocks
ltla::irlba
Eigen3::Eigen
)

# Tests
if(CMAKE_PROJECT_NAME STREQUAL PROJECT_NAME)
option(SCRAN_PCA_TESTS "Build scran_pca's test suite." ON)
else()
option(SCRAN_PCA_TESTS "Build scran_pca's test suite." OFF)
endif()

if(SCRAN_PCA_TESTS)
include(CTest)
if(BUILD_TESTING)
add_subdirectory(tests)
endif()
endif()
endif()

# Install
install(DIRECTORY include/
DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/scran_pca)

install(TARGETS scran_pca
EXPORT scran_pcaTargets)

install(EXPORT scran_pcaTargets
FILE libscran_scran_pcaTargets.cmake
NAMESPACE libscran::
DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/libscran_scran_pca)

configure_package_config_file(${CMAKE_CURRENT_SOURCE_DIR}/cmake/Config.cmake.in
"${CMAKE_CURRENT_BINARY_DIR}/libscran_scran_pcaConfig.cmake"
INSTALL_DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/libscran_scran_pca)

write_basic_package_version_file(
"${CMAKE_CURRENT_BINARY_DIR}/libscran_scran_pcaConfigVersion.cmake"
COMPATIBILITY SameMajorVersion)

install(FILES "${CMAKE_CURRENT_BINARY_DIR}/libscran_scran_pcaConfig.cmake"
"${CMAKE_CURRENT_BINARY_DIR}/libscran_scran_pcaConfigVersion.cmake"
DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/libscran_scran_pca)
66 changes: 47 additions & 19 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
# Principal components analysis, duh

![Unit tests](https://github.com/libscran/principal_component_analysis/actions/workflows/run-tests.yaml/badge.svg)
![Documentation](https://github.com/libscran/principal_component_analysis/actions/workflows/doxygenate.yaml/badge.svg)
[![Codecov](https://codecov.io/gh/libscran/principal_component_analysis/graph/badge.svg?token=qklLZtJSE9)](https://codecov.io/gh/libscran/principal_component_analysis)
![Unit tests](https://github.com/libscran/scran_pca/actions/workflows/run-tests.yaml/badge.svg)
![Documentation](https://github.com/libscran/scran_pca/actions/workflows/doxygenate.yaml/badge.svg)
[![Codecov](https://codecov.io/gh/libscran/scran_pca/graph/badge.svg?token=qklLZtJSE9)](https://codecov.io/gh/libscran/scran_pca)

## Overview

Expand All @@ -16,13 +16,13 @@ factored out into a separate C++ library for easier re-use.
Given a [`tatami::Matrix`](https://github.com/tatami-inc/tatami), the `simple_pca::compute()` function will compute the PCA to obtain a low-dimensional representation of the cells:

```cpp
#include "scran/simple_pca.hpp"
#include "scran_pca/scran_pca.hpp"

tatami::Matrix<double, int>* ptr = some_data_source();
const tatami::Matrix<double, int>& mat = some_data_source();

// Take the top 20 PCs:
scran::simple_pca::Options opt;
auto res = scran::simple_pca::compute(ptr, 20, opt);
scran_pca::SimplePcaOptions opt;
auto res = scran_pca::simple_pca(mat, 20, opt);

res.components; // rows are PCs, columns are cells.
res.rotation; // rows are genes, columns correspond to PCs.
Expand All @@ -45,8 +45,8 @@ This ensures that the inter-block differences do not contribute to the first few
```cpp
std::vector<int> blocks = some_blocks();

scran::blocked_pca::Options bopt;
auto bres = scran::blocked_pca::compute(ptr, blocks.data(), 20, bopt);
scran_pca::BlockedPcaOptions bopt;
auto bres = scran_pca::blocked_pca(mat, blocks.data(), 20, bopt);

bres.components; // rows are PCs, columns are cells.
bres.center; // rows are blocks, columns are genes.
Expand All @@ -59,31 +59,59 @@ we can use `blocked_pca::compute()` to obtain an appropriate matrix that focuses

```cpp
bopt.components_from_residuals = false;
auto bres2 = scran::blocked_pca::compute(ptr, blocks.data(), 20, bopt);
auto bres2 = scran_pca::blocked_pca(mat, blocks.data(), 20, bopt);
```

Check out the [reference documentation](https://libscran.github.io/principal_component_analysis) for more details.
Check out the [reference documentation](https://libscran.github.io/scran_pca) for more details.

## Building projects

This repository is part of the broader [**libscran**](https://github.com/libscran/libscran) library,
so users are recommended to use the latter in their projects.
**libscran** developers should just use CMake with `FetchContent`:
### CMake with `FetchContent`

If you're using CMake, you just need to add something like this to your `CMakeLists.txt`:

```cmake
include(FetchContent)

FetchContent_Declare(
scran_principal_component_analysis
GIT_REPOSITORY https://github.com/libscran/principal_component_analysis
scran_pca
GIT_REPOSITORY https://github.com/libscran/scran_pca
GIT_TAG master # or any version of interest
)

FetchContent_MakeAvailable(scran_principal_component_analysis)
FetchContent_MakeAvailable(scran_pca)
```

Then you can link to **scran_pca** to make the headers available during compilation:

```cmake
# For executables:
target_link_libraries(myexe scran_principal_component_analysis)
target_link_libraries(myexe libscran::scran_pca)

# For libaries
target_link_libraries(mylib INTERFACE scran_principal_component_analysis)
target_link_libraries(mylib INTERFACE libscran::scran_pca)
```

### CMake with `find_package()`

```cmake
find_package(libscran_scran_pca CONFIG REQUIRED)
target_link_libraries(mylib INTERFACE libscran::scran_pca)
```

To install the library, use:

```sh
mkdir build && cd build
cmake .. -DSCRAN_PCA_TESTS=OFF
cmake --build . --target install
```

By default, this will use `FetchContent` to fetch all external dependencies.
If you want to install them manually, use `-DSCRAN_PCA_FETCH_EXTERN=OFF`.
See the tags in [`extern/CMakeLists.txt`](extern/CMakeLists.txt) to find compatible versions of each dependency.

### Manual

If you're not using CMake, the simple approach is to just copy the files in `include/` - either directly or with Git submodules - and include their path during compilation with, e.g., GCC's `-I`.
This requires the external dependencies listed in [`extern/CMakeLists.txt`](extern/CMakeLists.txt), which also need to be made available during compilation.
10 changes: 10 additions & 0 deletions cmake/Config.cmake.in
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
@PACKAGE_INIT@

include(CMakeFindDependencyMacro)
find_dependency(tatami_tatami 3.0.0 CONFIG REQUIRED)
find_dependency(tatami_tatami_stats 1.0.0 CONFIG REQUIRED)
find_dependency(libscran_scran_blocks 1.0.0 CONFIG REQUIRED)
find_dependency(ltla_irlba 2.0.0 CONFIG REQUIRED)
find_dependency(Eigen3 3.4.0 REQUIRED NO_MODULE)

include("${CMAKE_CURRENT_LIST_DIR}/libscran_scran_pcaTargets.cmake")
8 changes: 4 additions & 4 deletions extern/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -25,13 +25,13 @@ FetchContent_Declare(
)

FetchContent_Declare(
scran_core_utils
GIT_REPOSITORY https://github.com/libscran/core_utils
GIT_TAG master
scran_blocks
GIT_REPOSITORY https://github.com/libscran/scran_blocks
GIT_TAG master # ^1.0.0
)

FetchContent_MakeAvailable(tatami)
FetchContent_MakeAvailable(tatami_stats)
FetchContent_MakeAvailable(irlba)
FetchContent_MakeAvailable(eigen)
FetchContent_MakeAvailable(scran_core_utils)
FetchContent_MakeAvailable(scran_blocks)
15 changes: 0 additions & 15 deletions include/scran/scran.hpp

This file was deleted.

Loading