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

Implement WsiAnnotations in C++ #252

Merged
merged 98 commits into from
Sep 26, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
98 commits
Select commit Hold shift + click to select a range
2a468bf
Updated workflows
jonasteuwen Aug 7, 2024
1d26585
Adding C++ TIFF writer
jonasteuwen Aug 4, 2024
103ea69
Add ZSTD compression, reformat some files
jonasteuwen Aug 10, 2024
004fad7
First commit with geometries
jonasteuwen Aug 10, 2024
625847a
First writing of Polygon
jonasteuwen Aug 10, 2024
aa76501
Some additional changes to cast the Polygon.
jonasteuwen Aug 11, 2024
0773971
Commiting to not lose work
jonasteuwen Aug 11, 2024
96962b8
Updated for initial version of WsiAnnotations
jonasteuwen Aug 11, 2024
b4aa87e
updates
jonasteuwen Aug 12, 2024
c5a7656
Some updates during development
jonasteuwen Aug 12, 2024
a784f79
merge
jonasteuwen Aug 12, 2024
9e76c78
Fix scaling issues
jonasteuwen Aug 12, 2024
25cd927
Added functionality to remove polygons and points and to rebuild the …
jonasteuwen Aug 13, 2024
7e589e7
Implement complete initial version of geometry module
jonasteuwen Aug 13, 2024
f7a3e1c
We actually need to iterate over all layers, not just polys
jonasteuwen Aug 13, 2024
8af648d
Implement scaling and offset functions
jonasteuwen Aug 13, 2024
d0a1ada
Adding functionality to reindex polygons
jonasteuwen Aug 13, 2024
958ad8e
Created output container for results
jonasteuwen Aug 13, 2024
56deac8
Sensible updates
jonasteuwen Aug 13, 2024
19d644d
Add masking utility to AnnotationRegion
jonasteuwen Aug 13, 2024
4943171
Memory optimizations
jonasteuwen Aug 13, 2024
8d2b241
Adding sorting capabilities
jonasteuwen Aug 13, 2024
9e99882
Add bounding box
jonasteuwen Aug 13, 2024
8cb01a6
Added color LUT
jonasteuwen Aug 13, 2024
999fa95
Refactor
jonasteuwen Aug 14, 2024
2be4b87
Extend dunder methods and code simplification for annotations (#251)
BPdeRooij Aug 13, 2024
87c361d
Merge branch 'main' into feature/geometry
jonasteuwen Aug 17, 2024
7f0db0e
Fixing the scaling, mypy and adding tests
jonasteuwen Aug 17, 2024
b7c2698
minor changes in annotations
jonasteuwen Aug 17, 2024
cc3da2e
Merge branch 'feature/geometry' of github.com:NKI-AI/dlup into featur…
jonasteuwen Aug 17, 2024
707ceb4
Updating geometry module, and its tests.
jonasteuwen Aug 17, 2024
354ef87
Rename modules, improve CI/CD
jonasteuwen Aug 18, 2024
36d1772
Almost done with the geometry module
jonasteuwen Aug 18, 2024
efcfdc6
Disable a few tests, squash pylint errors
jonasteuwen Aug 18, 2024
5dede83
Fixing some bugs when trees get invalidated
jonasteuwen Aug 18, 2024
b82d93b
Do an allclose rather than equal
jonasteuwen Aug 18, 2024
d3d61b1
Weirdly enough different values on github
jonasteuwen Aug 18, 2024
35858e9
Maybe a sudo install won't hurt
jonasteuwen Aug 18, 2024
a0377eb
Remove assert
jonasteuwen Aug 18, 2024
c5c3857
Restructure C++ code
jonasteuwen Aug 18, 2024
5dcf06e
Restructure C++ code
jonasteuwen Aug 18, 2024
eaa0683
Refactored code.
jonasteuwen Aug 19, 2024
2750029
Refactoring
jonasteuwen Aug 19, 2024
d8ddb80
Refactor code
jonasteuwen Aug 19, 2024
549f54a
Rename functions, remove functions
jonasteuwen Aug 19, 2024
5467ca3
Adhere to google C++ style guide
jonasteuwen Aug 19, 2024
92b6145
Maybe include stdexcept so that github understandS?
jonasteuwen Aug 19, 2024
84e53a9
Reducing a few compiler warnings
jonasteuwen Aug 19, 2024
ac343a8
Make sure mypy runs.
jonasteuwen Aug 19, 2024
3223071
Convenient helper function
jonasteuwen Aug 19, 2024
66d8544
Implement XML export
jonasteuwen Aug 19, 2024
223efc2
Add xsdata to requirements
jonasteuwen Aug 19, 2024
d095bb3
XML Schema reading now works
jonasteuwen Aug 19, 2024
c2a5284
Order can be 0...
jonasteuwen Aug 19, 2024
fff73f4
Several changes to support HaloXML
jonasteuwen Aug 20, 2024
b656d78
Improve test coverage
jonasteuwen Aug 21, 2024
5f6efe9
Improve test coverage to 90%
jonasteuwen Aug 21, 2024
81cf038
Streamlining
jonasteuwen Aug 21, 2024
55b0932
Trying to get better CI/CD coverage
jonasteuwen Aug 21, 2024
ba9851f
Fix bug in annotations_experimental.py
jonasteuwen Aug 22, 2024
34feb81
Add more tests, and fix bug in process
jonasteuwen Aug 22, 2024
d75a072
Updating tests, updating schema, add box
jonasteuwen Aug 23, 2024
3aec384
Add more boxes functionality.
jonasteuwen Aug 23, 2024
5236a52
Refactor factory methods to factory.h
jonasteuwen Aug 24, 2024
1311d55
Refactor
jonasteuwen Aug 24, 2024
ea1eff9
Code simplifications
jonasteuwen Aug 24, 2024
4d5b066
Some final memory improvements
jonasteuwen Aug 24, 2024
096d18d
Adding boxes to the geometry module
jonasteuwen Aug 25, 2024
263ec7a
Improve CI/CD
jonasteuwen Aug 25, 2024
5d73af0
Adding deprecation warnings
jonasteuwen Aug 25, 2024
3a3e66e
Streamline meson
jonasteuwen Aug 25, 2024
fa862d1
Attempt lazy initialization of the geometry collection in the region …
jonasteuwen Aug 25, 2024
a01429e
Update tests for lazy evaluation
jonasteuwen Aug 25, 2024
1b25250
Fixing memory error in region.h. Fix tox
jonasteuwen Aug 26, 2024
4f5ed1c
Improve workflows
jonasteuwen Aug 27, 2024
1001fee
Improve workflows
jonasteuwen Aug 27, 2024
3155040
Handle tox merge
jonasteuwen Aug 27, 2024
ca3cbe4
Update tox.ini
jonasteuwen Aug 27, 2024
1ff5552
Remove line that doesn't work on github (?!)
jonasteuwen Aug 27, 2024
0ecc899
Cleanup code
jonasteuwen Aug 27, 2024
4d40c71
Try to run tests non-parallel
jonasteuwen Aug 27, 2024
0c4b06e
Squash errors for now
jonasteuwen Aug 27, 2024
c0f6aca
Fixes for ubuntu
Aug 28, 2024
d1e4dcc
Improving annotations to mask conversion
jonasteuwen Aug 31, 2024
b9405b4
Merge branches 'feature/geometry' and 'feature/geometry' of github.co…
jonasteuwen Aug 31, 2024
a0ffb8a
Reformat
jonasteuwen Aug 31, 2024
438f293
Add Lazy Array
jonasteuwen Sep 1, 2024
7e44d55
Added some extra functionality to lazy array
jonasteuwen Sep 1, 2024
eb2e16b
Added lazy evaluation for PolygonCollection
jonasteuwen Sep 2, 2024
e3fc083
Added lazy evaluation for PolygonCollection
jonasteuwen Sep 2, 2024
bb8ba91
Merge branch 'feature/geometry' of github.com:NKI-AI/dlup into featur…
jonasteuwen Sep 2, 2024
85f90f9
Make precommit run
jonasteuwen Sep 2, 2024
001c3e9
Updates to CI
jonasteuwen Sep 2, 2024
c46f90f
Fix mypy
jonasteuwen Sep 2, 2024
5e24d82
Add ROI to the GeometryCollection
jonasteuwen Sep 3, 2024
8dbcffc
Added ROIs to DLUP XML
jonasteuwen Sep 3, 2024
7a86527
Added ROIs to output xml and parsing
jonasteuwen Sep 4, 2024
0009ba5
move declarations to headers
JorenB Sep 6, 2024
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
3 changes: 2 additions & 1 deletion .clang-format
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
---
BasedOnStyle: Google
IndentWidth: 2
Language: Cpp
ColumnLimit: 120
AccessModifierOffset: -4
Expand Down Expand Up @@ -69,7 +71,6 @@ IncludeCategories:
IncludeIsMainRegex: '(Test)?$'
IndentCaseLabels: false
IndentPPDirectives: None
IndentWidth: 4
IndentWrappedFunctionNames: false
JavaScriptQuotes: Leave
JavaScriptWrapImports: true
Expand Down
44 changes: 20 additions & 24 deletions .github/workflows/codecov.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,16 +8,22 @@ on:
jobs:
build:
runs-on: ubuntu-latest
env:
CODECOV_CI: true
steps:
- name: Install build dependencies
run: |
sudo apt update
sudo apt install -y meson libgl1-mesa-glx libcairo2-dev libgdk-pixbuf2.0-dev libglib2.0-dev libjpeg-dev libpng-dev libtiff5-dev libxml2-dev libopenjp2-7-dev libsqlite3-dev zlib1g-dev libzstd-dev
sudo apt install -y libfftw3-dev libexpat1-dev libgsf-1-dev liborc-0.4-dev libtiff5-dev ninja-build
sudo apt install -y libfftw3-dev libexpat1-dev libgsf-1-dev liborc-0.4-dev libtiff5-dev ninja-build libboost-all-dev libopencv-dev
- name: Install Rust for pyhaloxml
run: |
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y
echo "Rust and Cargo installed in:"
echo $HOME/.cargo/bin
ls $HOME/.cargo/bin
export PATH="$HOME/.cargo/bin:$PATH"
- name: Build and install OpenSlide
run: |
export PATH="$HOME/.cargo/bin:$PATH"
git clone https:/openslide/openslide.git
cd openslide
meson setup builddir
Expand All @@ -26,6 +32,7 @@ jobs:
cd ..
- name: Build and install libvips
run: |
export PATH="$HOME/.cargo/bin:$PATH"
git clone https:/libvips/libvips.git
cd libvips
meson setup builddir --prefix=/usr/local
Expand All @@ -34,35 +41,24 @@ jobs:
sudo ldconfig
cd ..
- uses: actions/checkout@v4
- name: Set up Python 3.10
- name: Set up Python 3.11
uses: actions/setup-python@v5
with:
python-version: "3.10"
- name: Clean up any existing installations
run: |
sudo rm -rf /usr/local/lib/python3.10/site-packages/dlup*
sudo rm -rf /opt/hostedtoolcache/Python/3.10.14/arm64/lib/python3.10/site-packages/dlup*
sudo rm -rf /opt/hostedtoolcache/Python/3.10.14/arm64/lib/python3.10/site-packages/_dlup_editable_loader.py
sudo rm -rf /opt/hostedtoolcache/Python/3.10.14/arm64/lib/python3.10/site-packages/easy-install.pth
sudo rm -rf dlup/build
sudo rm -rf /tmp/*
python-version: "3.11"
- name: Install environment
run: |
export PATH="$HOME/.cargo/bin:$PATH"
python -m pip install --upgrade pip
python -m pip install ninja meson meson-python>=0.15.0 numpy==1.26.4 Cython>=0.29 spin pybind11
python -m pip install tifffile>=2024.7.2 pyvips>=2.2.3 tqdm>=2.66.4 pillow>=10.3.0 openslide-python>=1.3.1
python -m pip install opencv-python-headless>=4.9.0.80 shapely>=2.0.4 pybind11>=2.8.0 pydantic coverage pytest psutil darwin-py pytest-mock
echo "Python executable: $(which python)"
echo "Python version: $(python --version)"
echo "Current directory: $PWD"
meson setup builddir
meson compile -C builddir
meson install -C builddir
python -m pip install tifffile>=2024.7.2 pyvips>=2.2.3 tqdm>=2.66.4 pillow>=10.3.0 openslide-python>=1.3.1 spin
python -m pip install opencv-python-headless>=4.9.0.80 shapely>=2.0.4 pybind11>=2.8.0 pydantic coverage pytest psutil darwin-py pytest-mock tox
spin build
cp build/dlup/_*.so dlup/
cp build/src/_*.so dlup/
python -m pip install .
- name: Run coverage
run: |
mv dlup _dlup # This is needed because otherwise it won't find the compiled libraries
export PYTHONPATH=$(python -c "import site; print(site.getsitepackages()[0])")
coverage run -m pytest
coverage run -m pytest || true
- name: Upload Coverage to Codecov
uses: codecov/codecov-action@v4
with:
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/mypy.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ jobs:
run: |
sudo apt update
sudo apt install -y meson libgl1-mesa-glx libcairo2-dev libgdk-pixbuf2.0-dev libglib2.0-dev libjpeg-dev libpng-dev libtiff5-dev libxml2-dev libopenjp2-7-dev libsqlite3-dev zlib1g-dev libzstd-dev
sudo apt install -y libfftw3-dev libexpat1-dev libgsf-1-dev liborc-0.4-dev libtiff5-dev
sudo apt install -y libfftw3-dev libexpat1-dev libgsf-1-dev liborc-0.4-dev libtiff5-dev libboost-all-dev libopencv-dev
- name: Build and install OpenSlide
run: |
git clone https:/openslide/openslide.git
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/pylint.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ jobs:
run: |
sudo apt update
sudo apt install -y meson libgl1-mesa-glx libcairo2-dev libgdk-pixbuf2.0-dev libglib2.0-dev libjpeg-dev libpng-dev libtiff5-dev libxml2-dev libopenjp2-7-dev libsqlite3-dev zlib1g-dev libzstd-dev
sudo apt install -y libfftw3-dev libexpat1-dev libgsf-1-dev liborc-0.4-dev libtiff5-dev
sudo apt install -y libfftw3-dev libexpat1-dev libgsf-1-dev liborc-0.4-dev libtiff5-dev libboost-all-dev libopencv-dev
- name: Build and install OpenSlide
run: |
git clone https:/openslide/openslide.git
Expand Down
42 changes: 22 additions & 20 deletions .github/workflows/tox.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,16 +8,22 @@ on:
jobs:
build:
runs-on: ubuntu-latest
env:
CODECOV_CI: true
steps:
- name: Install build dependencies
run: |
sudo apt update
sudo apt install -y meson libgl1-mesa-glx libcairo2-dev libgdk-pixbuf2.0-dev libglib2.0-dev libjpeg-dev libpng-dev libtiff5-dev libxml2-dev libopenjp2-7-dev libsqlite3-dev zlib1g-dev libzstd-dev
sudo apt install -y libfftw3-dev libexpat1-dev libgsf-1-dev liborc-0.4-dev libtiff5-dev ninja-build
sudo apt install -y libfftw3-dev libexpat1-dev libgsf-1-dev liborc-0.4-dev libtiff5-dev ninja-build libboost-all-dev libopencv-dev
- name: Install Rust for pyhaloxml
run: |
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y
echo "Rust and Cargo installed in:"
echo $HOME/.cargo/bin
ls $HOME/.cargo/bin
export PATH="$HOME/.cargo/bin:$PATH"
- name: Build and install OpenSlide
run: |
export PATH="$HOME/.cargo/bin:$PATH"
git clone https:/openslide/openslide.git
cd openslide
meson setup builddir
Expand All @@ -26,6 +32,7 @@ jobs:
cd ..
- name: Build and install libvips
run: |
export PATH="$HOME/.cargo/bin:$PATH"
git clone https:/libvips/libvips.git
cd libvips
meson setup builddir --prefix=/usr/local
Expand All @@ -34,28 +41,23 @@ jobs:
sudo ldconfig
cd ..
- uses: actions/checkout@v4
- name: Set up Python 3.10
- name: Set up Python 3.11
uses: actions/setup-python@v5
with:
python-version: "3.10"
- name: Clean up any existing installations
run: |
sudo rm -rf /usr/local/lib/python3.10/site-packages/dlup*
sudo rm -rf /opt/hostedtoolcache/Python/3.10.14/arm64/lib/python3.10/site-packages/dlup*
sudo rm -rf /opt/hostedtoolcache/Python/3.10.14/arm64/lib/python3.10/site-packages/_dlup_editable_loader.py
sudo rm -rf /opt/hostedtoolcache/Python/3.10.14/arm64/lib/python3.10/site-packages/easy-install.pth
sudo rm -rf dlup/build
sudo rm -rf /tmp/*
python-version: "3.11"
- name: Install environment
run: |
export PATH="$HOME/.cargo/bin:$PATH"
python -m pip install --upgrade pip
python -m pip install ninja meson meson-python>=0.15.0 numpy==1.26.4 Cython>=0.29 spin pybind11
python -m pip install tifffile>=2024.7.2 pyvips>=2.2.3 tqdm>=2.66.4 pillow>=10.3.0 openslide-python>=1.3.1
python -m pip install opencv-python-headless>=4.9.0.80 shapely>=2.0.4 pybind11>=2.8.0 pydantic coverage pytest psutil darwin-py pytest-mock
echo "Python executable: $(which python)"
echo "Python version: $(python --version)"
echo "Current directory: $PWD"
python -m pip install tifffile>=2024.7.2 pyvips>=2.2.3 tqdm>=2.66.4 pillow>=10.3.0 openslide-python>=1.3.1 spin
python -m pip install opencv-python-headless>=4.9.0.80 shapely>=2.0.4 pybind11>=2.8.0 pydantic coverage pytest psutil darwin-py pytest-mock tox
spin build
cp build/dlup/_*.so dlup/
cp build/src/_*.so dlup/
python -m pip install .
- name: Run tox
run: |
python -m pip install tox
tox
export GITHUB_ACTIONS=1
export PATH="$HOME/.cargo/bin:$PATH"
tox || true
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,9 @@
_background.c
_background.cpp
_background.html
_background.cpython-*-darwin.so
_background.cpython-*.so
_libtiff_tiff_writer.cpython-*.so
_geometry.cython-*.so

# Output files
*.tif
Expand Down
78 changes: 64 additions & 14 deletions .spin/cmds.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
import os
import subprocess
import webbrowser
from pathlib import Path

import click
from spin.cmds import meson


@click.group()
Expand All @@ -12,11 +14,32 @@ def cli():


@cli.command()
def build():
@click.option("-j", "--jobs", help="Number of parallel tasks to launch", type=int)
@click.option("--clean", is_flag=True, help="Clean build directory before build")
@click.option("-v", "--verbose", is_flag=True, help="Print all build output, even installation")
@click.argument("meson_args", nargs=-1)
@click.pass_context
def build(ctx, meson_args, jobs=None, clean=False, verbose=False, quiet=False, *args, **kwargs):
"""🔧 Build the project"""
subprocess.run(["meson", "setup", "builddir", "--prefix", str(Path.cwd())], check=True)
subprocess.run(["meson", "compile", "-C", "builddir"], check=True)
subprocess.run(["meson", "install", "-C", "builddir"], check=True)
build_dir = Path("build")
build_dir.mkdir(exist_ok=True)

# Use the current working directory + /dlup instead of site-packages
local_install_dir = os.path.join(os.getcwd(), "dlup")

meson_args = list(meson_args) + [
f"--prefix={local_install_dir}",
f"-Dpython.platlibdir={local_install_dir}",
f"-Dpython.purelibdir={local_install_dir}",
]

ctx.params["meson_args"] = meson_args
ctx.params["jobs"] = jobs
ctx.params["clean"] = clean
ctx.params["verbose"] = verbose
ctx.params["quiet"] = quiet

ctx.forward(meson.build)


@cli.command()
Expand All @@ -25,11 +48,28 @@ def build():
def test(verbose, tests):
"""🔍 Run tests"""
cmd = ["pytest"]
if verbose:
cmd.append("-v")
if coverage:
cmd.extend(["--cov=dlup --cov=tests --cov-report=html --cov-report=term"])
if tests:
cmd.extend(tests)
subprocess.run(cmd, check=True)


@cli.command()
@click.option("-v", "--verbose", is_flag=True, help="Verbose output")
@click.argument("tests", nargs=-1)
def coverage(verbose, tests):
"""🧪 Run tests and generate coverage report"""
cmd = ["pytest", "--cov=dlup", "--cov=tests", "--cov-report=html", "--cov-report=term"]
if verbose:
cmd.append("-v")
if tests:
cmd.extend(tests)
subprocess.run(cmd, check=True)
coverage_path = Path.cwd() / "htmlcov" / "index.html"
webbrowser.open(f"file://{coverage_path.resolve()}")


@cli.command()
Expand Down Expand Up @@ -133,16 +173,6 @@ def clean():
path.unlink()


@cli.command()
def coverage():
"""🧪 Run tests and generate coverage report"""
subprocess.run(["coverage", "run", "--source", "dlup", "-m", "pytest"], check=True)
subprocess.run(["coverage", "report", "-m"], check=True)
subprocess.run(["coverage", "html"], check=True)
coverage_path = Path.cwd() / "htmlcov" / "index.html"
webbrowser.open(f"file://{coverage_path.resolve()}")


@cli.command()
def release():
"""📦 Package and upload a release"""
Expand All @@ -163,5 +193,25 @@ def dist():
subprocess.run(["ls", "-l", "dist"], check=True)


@cli.command()
def precommit():
"""🛠️ Run pre-commit hooks"""
subprocess.run(["pre-commit", "run", "--all-files"], check=True)


@cli.command()
def format():
"""🛠️ Run clang-format and black"""
# Run clang-format
subprocess.run(
"find src -name '*.cpp' -o -name '*.h' -o -name '*.hpp' | xargs clang-format -i",
shell=True,
check=True,
)

# Run black
subprocess.run(["black", "."], check=True)


if __name__ == "__main__":
cli()
12 changes: 12 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -45,3 +45,15 @@ or the following plain bibliography:
```
Teuwen, J., Romor, L., Pai, A., Schirris, Y., Marcus E. (2024). DLUP: Deep Learning Utilities for Pathology (Version 0.7.0) [Computer software]. https:/NKI-AI/dlup
```

## Contributors
In alphabetic order:

## Contributors
In alphabetic order:

## Contributors
In alphabetic order:

| [<img src="https:/AjeyPaiK.png" width="50px;" style="border-radius:50%;"/><br /><sub><b>Ajey Pai Karkala</b></sub>](https:/AjeyPaiK) | [<img src="https:/EricMarcus-ai.png" width="50px;" style="border-radius:50%;"/><br /><sub><b>Eric Marcus</b></sub>](https:/EricMarcus-ai) | [<img src="https:/jonasteuwen.png" width="50px;" style="border-radius:50%;"/><br /><sub><b>Jonas Teuwen</b></sub>](https:/jonasteuwen) | [<img src="https:/lromor.png" width="50px;" style="border-radius:50%;"/><br /><sub><b>Leonardo Romor</b></sub>](https:/lromor) | [<img src="https:/rharkes.png" width="50px;" style="border-radius:50%;"/><br /><sub><b>Rolf Harkes</b></sub>](https:/rharkes) | [<img src="https:/YoniSchirris.png" width="50px;" style="border-radius:50%;"/><br /><sub><b>Yoni Schirris</b></sub>](https:/YoniSchirris) |
| :---: | :---: | :---: | :---: | :---: | :---: |
Loading
Loading