Skip to content

Commit 0bd4853

Browse files
authored
Merge branch 'development' into update-lexci-models
2 parents 19c6755 + 2031067 commit 0bd4853

16 files changed

+168
-112
lines changed

.github/workflows/cmake.yml

Lines changed: 24 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -67,11 +67,6 @@ jobs:
6767
with:
6868
submodules: recursive
6969

70-
# Enable tmate debugging of manually-triggered workflows if the input option was provided
71-
- name: Setup tmate session
72-
uses: mxschmitt/action-tmate@v3
73-
if: ${{ github.event_name == 'workflow_dispatch' && github.event.inputs.debug_enabled }}
74-
7570
- name: Install Dependencies on Ubunutu
7671
if: ${{ contains(matrix.os, 'ubuntu') }}
7772
run: |
@@ -81,12 +76,14 @@ jobs:
8176
- name: Install Dependencies on MacOS
8277
if: ${{ contains(matrix.os, 'macos') }}
8378
run: |
84-
# Skip brew update until https://github.com/actions/setup-python/issues/577 is fixed
85-
# Seems to be working, alghough the issue is still open
86-
brew update
8779
brew install libtiff open-mpi libyaml ccache
8880
echo "CMAKE_PREFIX_PATH=/usr/local/opt/libomp" >> $GITHUB_ENV
8981
82+
# Enable tmate debugging of manually-triggered workflows if the input option was provided
83+
- name: Setup tmate session
84+
uses: mxschmitt/action-tmate@v3
85+
if: ${{ github.event_name == 'workflow_dispatch' && github.event.inputs.debug_enabled }}
86+
9087
- name: Install Tensorflow API on Ubuntu
9188
# TODO could this be combined with mac version somehow? if/else?
9289
if: ${{ contains(matrix.os, 'ubuntu') }}
@@ -132,8 +129,25 @@ jobs:
132129
${{ matrix.os }}-${{ matrix.cxx }}
133130
${{ matrix.os }}
134131
132+
- name: Checkout cppflow repo
133+
uses: actions/checkout@v3
134+
with:
135+
repository: UCL/cppflow.git
136+
path: cppflow
137+
ref: master
138+
139+
- name: Create cppflow package on gcc
140+
if: ${{ contains(matrix.cxx, 'g++-10') }}
141+
run: |
142+
conan create ./cppflow/ -pr:h=default -pr:b=default -s compiler.libcxx=libstdc++11
143+
144+
- name: Create cppflow package on apple-clang
145+
if: ${{ contains(matrix.cxx, 'clang++') }}
146+
run: |
147+
conan create ./cppflow/ -pr:h=default -pr:b=default
148+
135149
- name: Conan install on gcc
136-
if: ${{ contains(matrix.cxx, 'g++-9') }}
150+
if: ${{ contains(matrix.cxx, 'g++-10') }}
137151
run: conan install ${{github.workspace}} -if ${{github.workspace}}/build -s compiler.libcxx=libstdc++11 --build missing -o mpi=${{matrix.mpi}} -o openmp=${{matrix.omp}} -o cppflow=on -pr:h=default -pr:b=default
138152

139153
- name: Conan install on apple-clang
@@ -143,7 +157,7 @@ jobs:
143157
- name: Build
144158
# Build your program with the given configuration.
145159
# The Github Actions machines are dual-core so we can build faster using 2 parallel processes
146-
run: conan build ${{github.workspace}} -bf ${{github.workspace}}/build
160+
run: conan build ${{github.workspace}} -bf ${{github.workspace}}/build
147161

148162
- name: Test
149163
working-directory: ${{github.workspace}}/build

.github/workflows/documentation.yml

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ on:
1212
description: 'Run the build with tmate debugging enabled (https://github.com/marketplace/actions/debugging-with-tmate)'
1313
required: false
1414
default: false
15-
15+
1616
env:
1717
CONAN_PRINT_RUN_COMMANDS: 1
1818
CONAN_REVISIONS_ENABLED: 1
@@ -32,13 +32,13 @@ jobs:
3232
- name: Setup tmate session
3333
uses: mxschmitt/action-tmate@v3
3434
if: ${{ github.event_name == 'workflow_dispatch' && github.event.inputs.debug_enabled }}
35-
35+
3636
# Note that we are installing doxygen with apt here, and with conan in the Configure step.
3737
# This is because there is no easy way of extracting the path to the doxygen executable from conan.
3838
# the apt installed doxygen is used in the Make Docweb step to build the html files,
3939
# while the conan installed version is used in the build step.
4040
# The version we install from apt is older than the 1.9.4 we install from conan, but
41-
# it is not causing any issues at the moment.
41+
# it is not causing any issues at the moment.
4242
- name: Install dependencies
4343
run: |
4444
sudo apt update
@@ -56,6 +56,16 @@ jobs:
5656
version: 2.11.0
5757
os: linux
5858

59+
- name: Checkout cppflow repo
60+
uses: actions/checkout@v3
61+
with:
62+
repository: UCL/cppflow.git
63+
path: cppflow
64+
ref: master
65+
66+
- name: Create cppflow package
67+
run: conan create ./cppflow/ -pr:h=default -pr:b=default
68+
5969
- name: Configure
6070
run: |
6171
conan install doxygen/1.9.4@#2af713e135f12722e3536808017ba086 --update

.github/workflows/macdebug.yml

Lines changed: 0 additions & 55 deletions
This file was deleted.

README.md

Lines changed: 47 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ Dependencies installation
2929
- [GCC](https://gcc.gnu.org) v7.3.0 GNU compiler for `C++`.
3030
- [UCL/GreatCMakeCookOff](https://github.com/UCL/GreatCMakeCookOff) Collection of `CMake` recipes. Downloaded automatically if absent.
3131
- [OpenMP](http://openmp.org/wp/) v4.8.4 (Trusty) - Optional - Speeds up some of the operations.
32+
- [Cppflow](https://github.com/UCL/cppflow) - Optional - A warpper for the Tensorflow C API allowing us to read Tensorflow models into SOPT. Needed if you are using a learned prior.
3233
- [Conan](https://docs.conan.io/en/latest/installation.html) - C++ package manager which installs the following:
3334
- [Eigen3](http://eigen.tuxfamily.org/index.php?title=Main_Page) v3.2.0 (Trusty) Modern `C++` linear algebra. Downloaded automatically if absent.
3435
- [spdlog](https://github.com/gabime/spdlog) v* - Optional - Logging library. Downloaded automatically if
@@ -42,45 +43,61 @@ Dependencies installation
4243
Installing and building SOPT
4344
----------------------------
4445

45-
You can build **SOPT** entirely from the source code. Once the mandatory dependencies are present, `git clone` from the [GitHub repository](https://github.com/astro-informatics/sopt):
46+
You can build **SOPT** entirely from the source code.
4647

47-
``` bash
48-
git clone https://github.com/astro-informatics/sopt.git
49-
```
5048

51-
Then, the program can be built with standard `CMake` command:
5249

53-
``` bash
54-
cd /path/to/code
55-
mkdir build
56-
cd build
57-
conan install .. --build missing
58-
conan build ..
59-
```
50+
1. If you are using a learned prior you must install the Tensorflow C API and `cppflow` package:
51+
- Install [TensorFlow C API](https://www.tensorflow.org/install/lang_c)
52+
- Clone the UCL fork of cppflow and create a conan package using
6053

61-
To install in directory `INSTALL_FOLDER`, add the following options to the conan build command:
54+
``` bash
55+
git clone git@github.com:UCL/cppflow.git
56+
conan create ./cppflow/ -pr:h=default -pr:b=default
57+
```
58+
Note that conan requires you to specify the host (h) and the build (b) profiles on the command
59+
line (`-pr:h=default -pr:b=default`), if you haven't defined them in your conan profile.
6260
63-
``` bash
64-
conan build .. -bf INSTALL_FOLDER -if .
65-
```
61+
1. Once the mandatory dependencies are present, `git clone` from the [GitHub repository](https://github.com/astro-informatics/sopt):
6662
67-
CMake build options should be passed as options to `conan install` using the `-o` flag with a value `on` or `off`. Possible options are
63+
``` bash
64+
git clone https://github.com/astro-informatics/sopt.git
65+
```
6866
69-
- tests (default on)
70-
- benchmarks (default off)
71-
- examples (default on)
72-
- logging (default on)
73-
- openmp (default on)
74-
- mpi (default on)
75-
- docs (default off)
76-
- coverage (default off)
67+
1. Then, the program can be built using conan:
7768
78-
For example, to build with both MPI and OpenMP off you would use
69+
``` bash
70+
cd /path/to/code
71+
mkdir build
72+
cd build
73+
conan install .. --build missing -pr:h=default -pr:b=default
74+
conan build ..
75+
```
7976
80-
``` bash
81-
conan install .. --build missing -o openmp=off -o mpi=off
82-
conan build ..
83-
```
77+
- To install in directory `INSTALL_FOLDER`, add the following options to the conan build command:
78+
79+
``` bash
80+
conan build .. -bf INSTALL_FOLDER -if .
81+
```
82+
83+
- CMake build options should be passed as options to `conan install` using the `-o` flag with a value `on` or `off`. Possible options are
84+
85+
- tests (default on)
86+
- benchmarks (default off)
87+
- examples (default on)
88+
- logging (default on)
89+
- openmp (default on)
90+
- mpi (default on)
91+
- docs (default off)
92+
- coverage (default off)
93+
- cppflow (default off)
94+
95+
For example, to build with both MPI and OpenMP off you would use
96+
97+
``` bash
98+
conan install .. --build missing -o openmp=off -o mpi=off -pr:h=default -pr:b=default
99+
conan build ..
100+
```
84101
85102
Common errors
86103
-------

cmake_files/dependencies.cmake

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,5 +51,6 @@ endif()
5151
set(SOPT_MPI ${MPI_FOUND})
5252

5353
if(cppflow)
54+
find_package(cppflow)
5455
find_library(TENSORFLOW_LIB tensorflow REQUIRED)
5556
endif()

conanfile.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,9 @@ def requirements(self):
3939
if self.options.logging == 'on':
4040
self.requires("spdlog/1.9.2")
4141

42+
if self.options.cppflow == 'on':
43+
self.requires("cppflow/2.0.0")
44+
4245
def build_requirements(self):
4346

4447
if self.options.docs == 'on':

cpp/sopt/CMakeLists.txt

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,7 @@ set(headers
33
bisection_method.h chained_operators.h credible_region.h
44
imaging_padmm.h logging.disabled.h
55
forward_backward.h imaging_forward_backward.h
6-
g_proximal.h l1_g_proximal.h tf_g_proximal.h
7-
joint_map.h
6+
g_proximal.h l1_g_proximal.h joint_map.h
87
imaging_primal_dual.h primal_dual.h
98
maths.h proximal.h relative_variation.h sdmm.h
109
wavelets.h conjugate_gradient.h l1_proximal.h logging.enabled.h padmm.h proximal_expression.h
@@ -29,7 +28,7 @@ if(SOPT_MPI)
2928
endif()
3029
if (cppflow)
3130
list(APPEND sources cppflow_utils.cc)
32-
list(APPEND headers cppflow_utils.h)
31+
list(APPEND headers cppflow_utils.h tf_g_proximal.h)
3332
endif()
3433

3534
add_library(sopt SHARED ${sources})
@@ -79,7 +78,7 @@ if (cppflow)
7978
# https://stackoverflow.com/questions/25676277/cmake-target-include-directories-prints-an-error-when-i-try-to-add-the-source
8079
# Add /usr/local/include for default location of TensorFlow headers
8180
target_include_directories(sopt PUBLIC
82-
$<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}/cppflow/include>
81+
$<BUILD_INTERFACE:${cppflow_INCLUDE_DIR}>
8382
$<BUILD_INTERFACE:/usr/local/include>
8483
$<INSTALL_INTERFACE:cppflow/include/>
8584
)

cpp/sopt/cppflow_utils.cc

Lines changed: 50 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,14 @@
44
#include <cppflow/cppflow.h>
55
#include "cppflow/ops.h"
66
#include "cppflow/model.h"
7+
#include <stdexcept>
78

89
namespace sopt {
910
namespace cppflowutils {
11+
12+
// arbitrary constant for imaginary part of image vectors.
13+
const double imaginary_threshold = 1e-10;
14+
1015
cppflow::tensor convert_image_to_tensor(Image<double> const &image, int image_rows, int image_cols){
1116
// Convert the Sopt::Image of doubles(wrapper for Eigen::Array) to a cppflow::tensor of floats
1217
// TODO: Make types template parameters
@@ -16,7 +21,7 @@ namespace cppflowutils {
1621
std::vector<float> input_values(image_rows*image_cols, 1);
1722
for (int i = 0; i < image.rows(); ++i) {
1823
for (int j = 0; j < image.cols(); ++j) {
19-
input_values[j*image_cols+i] = image(i,j);
24+
input_values[j*image_cols+i] = image(i,j);
2025
}
2126
}
2227

@@ -26,16 +31,58 @@ namespace cppflowutils {
2631
return input_tensor;
2732
}
2833

34+
cppflow::tensor convert_image_to_tensor(Image<std::complex<double>> const &image, int image_rows, int image_cols) {
35+
// Convert the Sopt::Image of complex (wrapper for Eigen::Array) to a cppflow::tensor of floats
36+
// Only takes the real part for processing, on the assumption that the imaginary part is negligible.
37+
// If ratio of imaginary part to real part is greater than the threshold then this will throw an exception.
38+
// TODO: Make types template parameters
39+
// create a vector of the right shape (model expects extra dimensions on start and end)
40+
std::vector<int64_t> input_shape = {1, image_rows, image_cols, 1};
41+
42+
std::vector<float> input_values(image_rows*image_cols, 1);
43+
44+
for (int i = 0; i < image.rows(); ++i) {
45+
for (int j = 0; j < image.cols(); ++j) {
46+
if(std::abs(image(i,j).real()) > cppflowutils::imaginary_threshold)
47+
{
48+
throw std::runtime_error("Cannot convert to tensorflow format: imaginary component of image is non-negligible.");
49+
}
50+
input_values[j*image_cols+i] = image(i,j).real();
51+
}
52+
}
53+
54+
// create a tensor from vector
55+
cppflow::tensor input_tensor(input_values, input_shape);
56+
return input_tensor;
57+
}
58+
2959
// Convert an image stored in a sopt::Vector<double> to a cppflow::tensor of floats
3060
cppflow::tensor convert_image_to_tensor(sopt::Vector<double> const &image, int image_rows, int image_cols) {
3161

32-
std::vector<float> values(&image[0], image.data()+image.size());
33-
cppflow::tensor input_tensor(values, {1, image_rows, image_cols, 1});
62+
std::vector<float> input_values(&image[0], image.data()+image.size());
63+
cppflow::tensor input_tensor(input_values, {1, image_rows, image_cols, 1});
3464

3565
return input_tensor;
3666

3767
}
3868

69+
// Convert an image stored in a sopt::Vector<double> to a cppflow::tensor of floats
70+
cppflow::tensor convert_image_to_tensor(sopt::Vector<std::complex<double>> const &image, int image_rows, int image_cols) {
71+
72+
std::vector<float> input_values(image_rows);
73+
for(int i = 0; i < image_rows; i++)
74+
{
75+
if(std::abs(image(i).real()) > cppflowutils::imaginary_threshold)
76+
{
77+
throw std::runtime_error("Cannot conver to tensorflow format: imaginary component of image vector is non negligible.");
78+
}
79+
input_values[i] = image(i).real();
80+
}
81+
cppflow::tensor input_tensor(input_values, {1, image_rows, image_cols, 1});
82+
83+
return input_tensor;
84+
}
85+
3986
// Convert model output in a std::vector into a sopt::Image (2D Eigen::Array)
4087
Eigen::Map<Eigen::Array<double, Eigen::Dynamic, Eigen::Dynamic>> convert_tensor_to_image(std::vector<float> model_output, int image_rows, int image_cols){
4188
// convert tensor of floats to Eigen::Array of doubles

0 commit comments

Comments
 (0)