├── .gitattributes ├── .idea ├── .gitignore ├── PVBM.iml ├── inspectionProfiles │ ├── Project_Default.xml │ └── profiles_settings.xml ├── misc.xml ├── modules.xml └── vcs.xml ├── .readthedocs.yaml ├── LICENSE ├── MANIFEST.in ├── PVBM ├── CentralRetinalAnalysis.py ├── Datasets.py ├── DiscSegmenter.py ├── FractalAnalysis.py ├── GeometricalAnalysis.py ├── GeometryAnalysis.py ├── GraphCRE │ ├── GraphCentralRetinalEquivalent.py │ ├── __init__.py │ └── __pycache__ │ │ ├── GraphCentralRetinalEquivalent.cpython-311.pyc │ │ └── __init__.cpython-311.pyc ├── GraphRegularisation │ ├── GraphRegularisation.py │ ├── __init__.py │ └── __pycache__ │ │ ├── GraphRegularisation.cpython-311.pyc │ │ └── __init__.cpython-311.pyc ├── LesionSegmenter.py ├── __init__.py ├── __pycache__ │ ├── CentralRetinalAnalysis.cpython-311.pyc │ ├── Datasets.cpython-311.pyc │ ├── DiscSegmenter.cpython-311.pyc │ ├── FractalAnalysis.cpython-310.pyc │ ├── FractalAnalysis.cpython-311.pyc │ ├── GeometricalAnalysis.cpython-310.pyc │ ├── GeometricalAnalysis.cpython-311.pyc │ ├── GeometryAnalysis.cpython-311.pyc │ ├── LesionSegmenter.cpython-311.pyc │ ├── __init__.cpython-310.pyc │ └── __init__.cpython-311.pyc ├── debug.py └── helpers │ ├── __init__.py │ ├── __pycache__ │ ├── __init__.cpython-310.pyc │ ├── __init__.cpython-311.pyc │ ├── branching2.cpython-310.pyc │ ├── branching2.cpython-311.pyc │ ├── branching_angle.cpython-310.pyc │ ├── branching_angle.cpython-311.pyc │ ├── far.cpython-310.pyc │ ├── perimeter.cpython-310.pyc │ ├── perimeter.cpython-311.pyc │ ├── tortuosity.cpython-310.pyc │ └── tortuosity.cpython-311.pyc │ ├── branching2.py │ ├── branching_angle.py │ ├── perimeter.py │ └── tortuosity.py ├── README.md ├── docs ├── CentralRetinalAnalysis.rst ├── Datasets.rst ├── DiscSegmenter.rst ├── FractalAnalysis.rst ├── GeometricalAnalysis.rst ├── GeometryAnalysis.rst ├── LesionSegmenter.rst ├── Makefile ├── VBMsumary.jpg ├── _build │ ├── doctrees │ │ ├── CentralRetinalAnalysis.doctree │ │ ├── Datasets.doctree │ │ ├── DiscSegmenter.doctree │ │ ├── FractalAnalysis.doctree │ │ ├── GeometricalAnalysis.doctree │ │ ├── GeometryAnalysis.doctree │ │ ├── LesionSegmenter.doctree │ │ ├── environment.pickle │ │ ├── index.doctree │ │ ├── nbsphinx │ │ │ ├── pvbmtutorial.ipynb │ │ │ ├── pvbmtutorial_14_0.png │ │ │ ├── pvbmtutorial_15_0.png │ │ │ ├── pvbmtutorial_17_0.png │ │ │ ├── pvbmtutorial_21_0.png │ │ │ ├── pvbmtutorial_21_1.png │ │ │ ├── pvbmtutorial_25_0.png │ │ │ ├── pvbmtutorial_26_0.png │ │ │ ├── pvbmtutorial_30_0.png │ │ │ ├── pvbmtutorial_31_0.png │ │ │ ├── pvbmtutorial_36_0.png │ │ │ ├── pvbmtutorial_38_0.png │ │ │ ├── pvbmtutorial_39_0.png │ │ │ ├── pvbmtutorial_40_0.png │ │ │ ├── pvbmtutorial_42_0.png │ │ │ ├── pvbmtutorial_50_0.png │ │ │ └── pvbmtutorial_55_0.png │ │ └── pvbmtutorial.doctree │ └── html │ │ ├── .buildinfo │ │ ├── CentralRetinalAnalysis.html │ │ ├── Datasets.html │ │ ├── DiscSegmenter.html │ │ ├── FractalAnalysis.html │ │ ├── GeometricalAnalysis.html │ │ ├── GeometryAnalysis.html │ │ ├── LesionSegmenter.html │ │ ├── _images │ │ ├── pipeline.png │ │ ├── pvbmtutorial_14_0.png │ │ ├── pvbmtutorial_15_0.png │ │ ├── pvbmtutorial_17_0.png │ │ ├── pvbmtutorial_21_0.png │ │ ├── pvbmtutorial_21_1.png │ │ ├── pvbmtutorial_25_0.png │ │ ├── pvbmtutorial_26_0.png │ │ ├── pvbmtutorial_30_0.png │ │ ├── pvbmtutorial_31_0.png │ │ ├── pvbmtutorial_36_0.png │ │ ├── pvbmtutorial_38_0.png │ │ ├── pvbmtutorial_39_0.png │ │ ├── pvbmtutorial_40_0.png │ │ ├── pvbmtutorial_42_0.png │ │ ├── pvbmtutorial_50_0.png │ │ └── pvbmtutorial_55_0.png │ │ ├── _modules │ │ ├── PVBM │ │ │ ├── CentralRetinalAnalysis.html │ │ │ ├── Datasets.html │ │ │ ├── DiscSegmenter.html │ │ │ ├── FractalAnalysis.html │ │ │ ├── GeometricalAnalysis.html │ │ │ ├── GeometryAnalysis.html │ │ │ └── LesionSegmenter.html │ │ └── index.html │ │ ├── _sources │ │ ├── CentralRetinalAnalysis.rst.txt │ │ ├── Datasets.rst.txt │ │ ├── DiscSegmenter.rst.txt │ │ ├── FractalAnalysis.rst.txt │ │ ├── GeometricalAnalysis.rst.txt │ │ ├── GeometryAnalysis.rst.txt │ │ ├── LesionSegmenter.rst.txt │ │ ├── index.rst.txt │ │ └── pvbmtutorial.ipynb.txt │ │ ├── _static │ │ ├── basic.css │ │ ├── css │ │ │ ├── badge_only.css │ │ │ ├── fonts │ │ │ │ ├── Roboto-Slab-Bold.woff │ │ │ │ ├── Roboto-Slab-Bold.woff2 │ │ │ │ ├── Roboto-Slab-Regular.woff │ │ │ │ ├── Roboto-Slab-Regular.woff2 │ │ │ │ ├── fontawesome-webfont.eot │ │ │ │ ├── fontawesome-webfont.svg │ │ │ │ ├── fontawesome-webfont.ttf │ │ │ │ ├── fontawesome-webfont.woff │ │ │ │ ├── fontawesome-webfont.woff2 │ │ │ │ ├── lato-bold-italic.woff │ │ │ │ ├── lato-bold-italic.woff2 │ │ │ │ ├── lato-bold.woff │ │ │ │ ├── lato-bold.woff2 │ │ │ │ ├── lato-normal-italic.woff │ │ │ │ ├── lato-normal-italic.woff2 │ │ │ │ ├── lato-normal.woff │ │ │ │ └── lato-normal.woff2 │ │ │ └── theme.css │ │ ├── doctools.js │ │ ├── documentation_options.js │ │ ├── file.png │ │ ├── js │ │ │ ├── badge_only.js │ │ │ ├── html5shiv-printshiv.min.js │ │ │ ├── html5shiv.min.js │ │ │ └── theme.js │ │ ├── language_data.js │ │ ├── minus.png │ │ ├── nbsphinx-broken-thumbnail.svg │ │ ├── nbsphinx-code-cells.css │ │ ├── nbsphinx-gallery.css │ │ ├── nbsphinx-no-thumbnail.svg │ │ ├── plus.png │ │ ├── pygments.css │ │ ├── searchtools.js │ │ └── sphinx_highlight.js │ │ ├── genindex.html │ │ ├── index.html │ │ ├── objects.inv │ │ ├── pvbmtutorial.html │ │ ├── pvbmtutorial.ipynb │ │ ├── py-modindex.html │ │ ├── search.html │ │ └── searchindex.js ├── conf.py ├── docs_requirements.txt ├── figures │ └── pipeline.png ├── index.rst ├── make.bat ├── pvbmtutorial.ipynb ├── requirements.txt └── untitled ├── figures └── pipeline.png ├── images ├── 117-793-749-000036_RR_43001_04734_F_48.png ├── 117-793-749-000036_RR_43001_04734_F_48.png.1 ├── 117-793-749-000036_RR_43001_04734_F_48.png.2 ├── 117-793-749-000036_RR_43001_04734_F_48.png.3 ├── 117-793-749-000036_RR_43001_04734_F_48.png.4 ├── 121-691-760-V721942_RR_63739_04251_M_74.png ├── 121-691-760-V721942_RR_63739_04251_M_74.png.1 ├── 121-691-760-V721942_RR_63739_04251_M_74.png.2 ├── 121-691-760-V721942_RR_63739_04251_M_74.png.3 └── 121-691-760-V721942_RR_63739_04251_M_74.png.4 ├── pvbm.egg-info ├── PKG-INFO ├── SOURCES.txt ├── dependency_links.txt ├── requires.txt └── top_level.txt ├── pvbmtutorial.ipynb └── setup.py /.gitattributes: -------------------------------------------------------------------------------- 1 | *.onnx filter=lfs diff=lfs merge=lfs -text 2 | -------------------------------------------------------------------------------- /.idea/.gitignore: -------------------------------------------------------------------------------- 1 | # Default ignored files 2 | /shelf/ 3 | /workspace.xml 4 | # Editor-based HTTP Client requests 5 | /httpRequests/ 6 | # Datasource local storage ignored files 7 | /dataSources/ 8 | /dataSources.local.xml 9 | -------------------------------------------------------------------------------- /.idea/PVBM.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 12 | -------------------------------------------------------------------------------- /.idea/inspectionProfiles/Project_Default.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 15 | -------------------------------------------------------------------------------- /.idea/inspectionProfiles/profiles_settings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 6 | -------------------------------------------------------------------------------- /.idea/misc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | 7 | -------------------------------------------------------------------------------- /.idea/modules.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /.idea/vcs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /.readthedocs.yaml: -------------------------------------------------------------------------------- 1 | version: 2 2 | 3 | build: 4 | os: ubuntu-22.04 5 | tools: 6 | python: "3.9" 7 | 8 | python: 9 | install: 10 | - method: pip 11 | path: . 12 | - requirements: docs/requirements.txt 13 | 14 | sphinx: 15 | configuration: docs/conf.py 16 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2023 AIMLab. 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /MANIFEST.in: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aim-lab/PVBM/71c9077164098f85c928a09be719468e0a5896e4/MANIFEST.in -------------------------------------------------------------------------------- /PVBM/Datasets.py: -------------------------------------------------------------------------------- 1 | import gdown 2 | import os 3 | import zipfile 4 | 5 | 6 | class PVBMDataDownloader: 7 | """A class that downloads the PVBM datasets.""" 8 | def __init__(self): 9 | self.file_ids = { 10 | "UNAF": "1IM5qUEARNp2RFpzKmILbdgasjLuJEIcX", 11 | "INSPIRE": "18TcmkuN_eZgM2Ph5XiX8x7_ejtKhA3qb", 12 | "Crop_HRF": "1QcozuK5yDyXbBkHqkbM5bxEkTGzkPDl3" 13 | } 14 | 15 | def download_dataset_from_google_drive(self, file_id, save_path): 16 | url = f'https://drive.google.com/uc?id={file_id}' 17 | gdown.download(url, save_path, quiet=False) 18 | print(f"Dataset downloaded and saved to {save_path}") 19 | 20 | def unzip_file(self, zip_file_path, extract_to_dir): 21 | """ 22 | Unzip a file to the specified directory and delete the zip file after extraction. 23 | 24 | :param zip_file_path: Path to the zip file. 25 | :type zip_file_path: String 26 | 27 | :param extract_to_dir: Directory where the contents will be extracted. 28 | """ 29 | with zipfile.ZipFile(zip_file_path, 'r') as zip_ref: 30 | zip_ref.extractall(extract_to_dir) 31 | print(f"Files extracted to {extract_to_dir}") 32 | 33 | os.remove(zip_file_path) 34 | print(f"Deleted the zip file: {zip_file_path}") 35 | 36 | def download_dataset(self, name, save_folder_path): 37 | """ 38 | Download the PVBM datasets 39 | 40 | :param name: Name of the dataset to download. Need to be within {"UNAF", "INSPIRE", "Crop_HRF"} 41 | :param save_folder_path: Path to the folder where to store the downloaded datasets 42 | """ 43 | if name in list(self.file_ids.keys()): 44 | zip_save_path = f"{name}.zip" 45 | os.makedirs(save_folder_path, exist_ok=True) 46 | # Call the function to download the dataset 47 | self.download_dataset_from_google_drive(self.file_ids[name], zip_save_path) 48 | # Call the function to unzip the file and delete the zip file 49 | self.unzip_file(zip_save_path, save_folder_path) 50 | else: 51 | print("Name should be within the following:", list(self.file_ids.keys())) -------------------------------------------------------------------------------- /PVBM/DiscSegmenter.py: -------------------------------------------------------------------------------- 1 | import os 2 | import requests 3 | import onnxruntime as ort 4 | import numpy as np 5 | import PIL 6 | from PIL import Image 7 | from torchvision import transforms 8 | import cv2 9 | 10 | class DiscSegmenter: 11 | """A class that performs optic disc segmentation.""" 12 | 13 | def __init__(self): 14 | """Initialize the DiscSegmenter class with image size and model path.""" 15 | self.img_size = 512 16 | script_dir = os.path.dirname(os.path.abspath(__file__)) 17 | self.model_path = os.path.join(script_dir, "lunetv2_odc.onnx") 18 | self.download_model() 19 | 20 | def download_model(self): 21 | """Download the ONNX model if it does not exist.""" 22 | model_url = 'https://github.com/aim-lab/PVBM/raw/main/PVBM/lunetv2_odc.onnx' 23 | print(f"Model path: {self.model_path}") 24 | if not os.path.exists(self.model_path): 25 | print(f"Downloading model from {model_url}...") 26 | response = requests.get(model_url, stream=True) 27 | response.raise_for_status() 28 | with open(self.model_path, 'wb') as f: 29 | for chunk in response.iter_content(chunk_size=8192): 30 | f.write(chunk) 31 | print(f'Model downloaded to {self.model_path}') 32 | else: 33 | print("Model already exists, skipping download.") 34 | 35 | def find_biggest_contour(self, contours): 36 | """ 37 | Find the biggest contour in the provided list of contours. 38 | 39 | :param contours: List of contours. 40 | :type contours: list of numpy arrays 41 | :return: The center, radius, and the biggest contour. 42 | :rtype: tuple 43 | """ 44 | radius = -1 45 | final_contour = contours[0] 46 | (x, y), radius = cv2.minEnclosingCircle(final_contour) 47 | center = (int(x), int(y)) 48 | radius = int(radius) 49 | for contour in contours: 50 | (x, y), radius_ = cv2.minEnclosingCircle(contour) 51 | if radius_ > radius: 52 | center = (int(x), int(y)) 53 | radius = int(radius_) 54 | final_contour = contour 55 | return center, radius, final_contour 56 | 57 | def post_processing(self, segmentation, max_roi_size): 58 | """ 59 | Post-process the segmentation result to extract relevant zones. 60 | 61 | :param segmentation: Segmentation result as a numpy array. 62 | :type segmentation: numpy array 63 | :param max_roi_size: Maximum size of the region of interest. 64 | :type max_roi_size: int 65 | :return: The center, radius, region of interest, and zones ABC. 66 | :rtype: tuple 67 | """ 68 | segmentation = np.array(segmentation, dtype=np.uint8) 69 | try: 70 | contours, hierarchy = cv2.findContours(segmentation, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE) 71 | center, radius, contour = self.find_biggest_contour(contours) 72 | 73 | one_radius = np.zeros((segmentation.shape[0], segmentation.shape[1], 3), dtype=np.uint8) 74 | cv2.circle(one_radius, center, radius, (0, 255, 0), -1) 75 | 76 | two_radius = np.zeros((segmentation.shape[0], segmentation.shape[1], 3), dtype=np.uint8) 77 | cv2.circle(two_radius, center, int(radius * 2), (0, 255, 0), -1) 78 | 79 | three_radius = np.zeros((segmentation.shape[0], segmentation.shape[1], 3), dtype=np.uint8) 80 | cv2.circle(three_radius, center, radius * 3, (0, 255, 0), -1) 81 | 82 | roi = np.zeros((segmentation.shape[0], segmentation.shape[1], 3), dtype=np.uint8) 83 | cv2.circle(roi, center, max_roi_size, (0, 255, 0), -1) 84 | 85 | except: 86 | one_radius = np.zeros((segmentation.shape[0], segmentation.shape[1], 3), dtype=np.uint8) 87 | two_radius = np.zeros((segmentation.shape[0], segmentation.shape[1], 3), dtype=np.uint8) 88 | three_radius = np.zeros((segmentation.shape[0], segmentation.shape[1], 3), dtype=np.uint8) 89 | roi = np.zeros((segmentation.shape[0], segmentation.shape[1], 3), dtype=np.uint8) 90 | center = (segmentation.shape[0] // 2, segmentation.shape[1] // 2) 91 | radius = 0 92 | 93 | zones_ABC = np.zeros((segmentation.shape[0], segmentation.shape[1], 4)) 94 | zones_ABC[:, :, :3] = one_radius 95 | zones_ABC[:, :, 0] = two_radius[:, :, 1] 96 | zones_ABC[:, :, 2] = three_radius[:, :, 1] 97 | zones_ABC[:, :, 3] = np.maximum(one_radius[:, :, 1], three_radius[:, :, 1]) / 2 98 | 99 | return center, radius, roi, zones_ABC 100 | 101 | def segment(self, image_path): 102 | """ 103 | Perform the optic disc segmentation given an image path. 104 | 105 | :param image_path: Path to the image. 106 | :type image_path: str 107 | :return: A PIL Image containing the Optic Disc segmentation. 108 | :rtype: PIL.Image 109 | """ 110 | session = ort.InferenceSession(self.model_path) 111 | input_name = session.get_inputs()[0].name 112 | 113 | img_orig = PIL.Image.open(image_path) 114 | original_size = img_orig.size 115 | image = img_orig.resize((self.img_size, self.img_size)) 116 | image = transforms.ToTensor()(image) 117 | normalize = transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225]) 118 | image = normalize(image) 119 | 120 | image_np = image.numpy() 121 | image_np = np.expand_dims(image_np, axis=0) 122 | 123 | outputs = session.run(None, {input_name: image_np}) 124 | od = outputs[0][0, 0] > 0 125 | 126 | return PIL.Image.fromarray(np.array(od, dtype=np.uint8) * 255).resize(original_size, PIL.Image.Resampling.NEAREST) 127 | -------------------------------------------------------------------------------- /PVBM/GeometricalAnalysis.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | from skimage.morphology import skeletonize 3 | from scipy.signal import convolve2d 4 | from PVBM.helpers.tortuosity import compute_tortuosity 5 | from PVBM.helpers.perimeter import compute_perimeter_ 6 | from PVBM.helpers.branching_angle import compute_angles_dictionary 7 | import warnings 8 | 9 | class GeometricalVBMs: 10 | """ 11 | A class that can perform geometrical biomarker computation for a fundus image. 12 | 13 | .. deprecated:: 2.9.0 14 | This class will be removed in version 3.0. Use `GeometryAnalysis.GeometricalVBMs` instead. 15 | """ 16 | 17 | def __init__(self): 18 | super(GeometricalVBMs, self).__init__() 19 | 20 | warnings.warn( 21 | "The GeometricalVBMs class is deprecated and will be removed in version 3.0. " 22 | "Use GeometryAnalysis.GeometricalVBMs instead.", 23 | DeprecationWarning, 24 | stacklevel=2 25 | ) 26 | 27 | 28 | 29 | def area(self,segmentation): 30 | """ 31 | Computes the area of the blood vessels calculated as the total number of pixels in the segmentation, 32 | and is expressed in pixels^2 (squared pixels). 33 | 34 | :param segmentation: The segmentation is a two-dimensional array (HxW) with binary values (0 or 1). 35 | :type segmentation: array 36 | :return: The area of the segmentation. 37 | :rtype: float 38 | """ 39 | return np.sum(segmentation) 40 | 41 | def compute_particular_points(self,segmentation_skeleton): 42 | """ 43 | The particular point is the union between the endpoints and the intersection points. 44 | This function computes the number of endpoints and intersection points of the fundus image vasculature segmentation. 45 | 46 | :param segmentation_skeleton: The skeleton of the segmentation is a two-dimensional array (HxW) with binary values (0 or 1). 47 | :type segmentation_skeleton: np.ndarray 48 | :return: 49 | - The number of endpoints 50 | - The number of intersection points, 51 | - An array with endpoint pixel positions 52 | - An array with intersection point pixel positions. 53 | 54 | :rtype: (int, int, np.ndarray, np.ndarray) 55 | """ 56 | filter_ = np.array([[1, 1, 1], [1, 10, 1], [1, 1, 1]]) 57 | neighbours = convolve2d(segmentation_skeleton, filter_, mode="same") 58 | 59 | end_points = neighbours == 11 60 | inter_points = neighbours >= 13 61 | 62 | end_points_count = np.sum(end_points) 63 | inter_points_count = np.sum(inter_points) 64 | 65 | return end_points_count, inter_points_count, end_points, inter_points 66 | 67 | def compute_tortuosity_length(self,segmentation_skeleton): 68 | """ 69 | Computes the median tortuosity and the length of the fundus image vasculature segmentation. 70 | 71 | :param segmentation_skeleton: The skeleton of the segmentation is a two-dimensional array (HxW) with binary values (0 or 1). 72 | :type segmentation_skeleton: np.ndarray 73 | :return: 74 | - The median tortuosity 75 | - The overall length (in pixel) 76 | - A list of chord distance of each blood vessel (in pixel) 77 | - A list of lengths distance (arc) of each blood vessel (in pixel) 78 | - A dictionary with connection information. 79 | 80 | :rtype: (float, float, list, list, dict) 81 | """ 82 | median_tor,length,arc,chord,connection_dico = compute_tortuosity(segmentation_skeleton) 83 | return median_tor,length ,chord, arc,connection_dico 84 | 85 | def compute_perimeter(self,segmentation): 86 | """ 87 | Computes the perimeter and the border of the fundus image vasculature segmentation. 88 | 89 | :param segmentation: The segmentation is a two-dimensional array (HxW) with binary value (0 or 1). 90 | :type segmentation: np.ndarray 91 | :return: 92 | - The perimeter (in pixel) 93 | - A matrix containing the edges of the segmentation. 94 | 95 | :rtype: (float, np.ndarray) 96 | """ 97 | segmentation = segmentation 98 | filter_ = np.array([[-1, -1, -1], [-1, 8, -1], [-1, -1, -1]]) 99 | derivative = convolve2d(segmentation,filter_, mode="same") 100 | border = derivative>0 101 | segmentation_skeleton = skeletonize(np.ascontiguousarray(border)) 102 | perim,_ = compute_perimeter_(segmentation_skeleton.copy()) 103 | return perim,segmentation_skeleton 104 | 105 | def compute_branching_angles(self,segmentation_skeleton): 106 | """ 107 | Computes the mean, standard deviation, and median branching angle of the fundus image vasculature segmentation. 108 | 109 | :param segmentation_skeleton: The skeleton of the segmentation is a two-dimensional array (HxW) with binary values (0 or 1). 110 | :type segmentation_skeleton: np.ndarray 111 | :return: 112 | - The mean of the branching angles (in degrees) 113 | - The standard deviation of the branching angles (in degrees) 114 | - The median of the branching angles (in degrees) 115 | - A dictionary containing all the branching angles with their respective indices in the array as keys 116 | - A two-dimensional numpy array representing the visualization of the computed centroid of the segmentation skeleton. 117 | 118 | :rtype: (float, float, float, dict, np.ndarray) 119 | """ 120 | img= segmentation_skeleton 121 | #return compute_angles_dictionary(img) 122 | angle_dico,centroid = compute_angles_dictionary(img) 123 | mean_ba = np.mean(list(angle_dico.values())) 124 | std_ba = np.std(list(angle_dico.values())) 125 | median_ba = np.median(list(angle_dico.values())) 126 | return mean_ba, std_ba, median_ba,angle_dico,centroid 127 | -------------------------------------------------------------------------------- /PVBM/GraphCRE/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aim-lab/PVBM/71c9077164098f85c928a09be719468e0a5896e4/PVBM/GraphCRE/__init__.py -------------------------------------------------------------------------------- /PVBM/GraphCRE/__pycache__/GraphCentralRetinalEquivalent.cpython-311.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aim-lab/PVBM/71c9077164098f85c928a09be719468e0a5896e4/PVBM/GraphCRE/__pycache__/GraphCentralRetinalEquivalent.cpython-311.pyc -------------------------------------------------------------------------------- /PVBM/GraphCRE/__pycache__/__init__.cpython-311.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aim-lab/PVBM/71c9077164098f85c928a09be719468e0a5896e4/PVBM/GraphCRE/__pycache__/__init__.cpython-311.pyc -------------------------------------------------------------------------------- /PVBM/GraphRegularisation/GraphRegularisation.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | class TreeReg: 3 | """A class that store the topology information of a graph in order to remove irregularities""" 4 | def __init__(self, i, j): 5 | """ 6 | Initialise a tree node with the root of the tree node coordinate and an empty children node list 7 | 8 | :param i: X axis coodinates of the current tree node 9 | :type i: int 10 | :param j: Y axis coodinates of the current tree node 11 | :type j: int 12 | """ 13 | self.plot = (i, j) 14 | self.children = [] 15 | 16 | def add_children(self, i, j): 17 | """ 18 | Instantiate a children node and add it to the list of the children nodes 19 | 20 | :param i: X axis coodinates of the root of the children node 21 | :type i: int 22 | :param j: Y axis coodinates of the root of the children node 23 | :type j: int 24 | """ 25 | next_tree = TreeReg(i, j) 26 | self.children.append(next_tree) 27 | return next_tree 28 | 29 | def recursive_reg(self,A, i, j, n, tree, plot): 30 | """ 31 | A recursive function that iterate through the continuous graph and store the children of each node as well as its number of ancestor 32 | 33 | :param A: skeleton of the segmentation 34 | :type A: np.float 35 | :param i: X axis coodinates of the current node 36 | :type i: int 37 | :param j: Y axis coodinates of the current node 38 | :type j: int 39 | :param n: number of ancestor of the current node 40 | :type n: int 41 | :param tree: current tree node 42 | :type tree: PVBM.GraphRegularisation.GraphRegularisation.TreeReg 43 | :param plot: A numpy array where the continuous navigated graph is saved 44 | :type plot: np.array 45 | 46 | """ 47 | up = (i - 1, j) 48 | down = (i + 1, j) 49 | left = (i, j - 1) 50 | right = (i, j + 1) 51 | 52 | up_left = (i - 1, j - 1) 53 | up_right = (i - 1, j + 1) 54 | down_left = (i + 1, j - 1) 55 | down_right = (i + 1, j + 1) 56 | points = [up, down, left, right, up_left, up_right, down_left, down_right] 57 | children = np.sum([A[point] for point in points if 58 | (point[0] >= 0 and point[1] >= 0 and point[0] < A.shape[0] and point[1] < A.shape[1])]) 59 | if children >= 1: 60 | plot[i, j] = 1 61 | 62 | for point in points: 63 | if point[0] >= 0 and point[0] < A.shape[0] and point[1] < A.shape[1] and point[1] >= 0: 64 | if A[point] == 1: 65 | tree__ = tree.add_children(point[0], point[1]) 66 | A[point] = 0 67 | self.recursive_reg(A, point[0], point[1], n + 1, tree__, plot) 68 | 69 | def print_reg(self,tree, plot): 70 | """ 71 | A recursive function that correct graphs irregularities by removing children branch which contains less than 10 pixels 72 | 73 | :type tree: PVBM.GraphRegularisation.GraphRegularisation.TreeReg 74 | :param plot: A numpy array where the corrected graph is saved 75 | :type plot: np.array 76 | 77 | """ 78 | if len(tree.children) == 0: 79 | return 1 80 | else: 81 | n = 1 + sum([self.print_reg(child, plot) for child in tree.children]) 82 | if n >= 10: 83 | plot[tree.plot] = 1 84 | return n -------------------------------------------------------------------------------- /PVBM/GraphRegularisation/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aim-lab/PVBM/71c9077164098f85c928a09be719468e0a5896e4/PVBM/GraphRegularisation/__init__.py -------------------------------------------------------------------------------- /PVBM/GraphRegularisation/__pycache__/GraphRegularisation.cpython-311.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aim-lab/PVBM/71c9077164098f85c928a09be719468e0a5896e4/PVBM/GraphRegularisation/__pycache__/GraphRegularisation.cpython-311.pyc -------------------------------------------------------------------------------- /PVBM/GraphRegularisation/__pycache__/__init__.cpython-311.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aim-lab/PVBM/71c9077164098f85c928a09be719468e0a5896e4/PVBM/GraphRegularisation/__pycache__/__init__.cpython-311.pyc -------------------------------------------------------------------------------- /PVBM/LesionSegmenter.py: -------------------------------------------------------------------------------- 1 | import os 2 | import requests 3 | import onnxruntime as ort 4 | import numpy as np 5 | import PIL 6 | from PIL import Image 7 | from torchvision import transforms 8 | import cv2 9 | 10 | class LesionSegmenter: 11 | """A class that performs lesion segmentation.""" 12 | 13 | def __init__(self, model_path): 14 | """Initialize the LesionSegmenter class with image size and model path. 15 | Download the model from: https://drive.google.com/file/d/1pOhp506d0jiUzOWJBLoH6yXagkMLb8-t/view?usp=sharing 16 | """ 17 | self.img_size = 512 18 | script_dir = os.path.dirname(os.path.abspath(__file__)) 19 | #self.model_path = os.path.join(script_dir, "lesion.onnx") 20 | self.model_path = model_path 21 | 22 | 23 | def segment(self, image_path): 24 | """ 25 | Perform the lesion segmentation given an image path. 26 | 27 | :param image_path: Path to the image. 28 | :type image_path: str 29 | :return: A PIL Image containing the Lesion segmentation. 30 | :rtype: PIL.Image 31 | """ 32 | session = ort.InferenceSession(self.model_path) 33 | input_name = session.get_inputs()[0].name 34 | 35 | img_orig = PIL.Image.open(image_path) 36 | original_size = img_orig.size 37 | image = img_orig.resize((self.img_size, self.img_size)) 38 | image = transforms.ToTensor()(image) 39 | normalize = transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225]) 40 | image = normalize(image) 41 | 42 | image_np = image.numpy() 43 | image_np = np.expand_dims(image_np, axis=0) 44 | 45 | outputs = session.run(None, {input_name: image_np}) 46 | lesion = self.visualize_lesion(outputs[0]) 47 | 48 | return PIL.Image.fromarray(lesion).resize(original_size, PIL.Image.Resampling.NEAREST) 49 | 50 | def visualize_lesion(self,pred): 51 | # Initialize an empty RGBA image 52 | visualisation = np.zeros((pred.shape[-2], pred.shape[-1], 4), dtype=np.uint8) 53 | 54 | # Create masks for each variable where the pixel values are greater than zero 55 | ex_mask = pred[0, 0] > 0 56 | se_mask = pred[0, 1] > 0 57 | he_mask = pred[0, 2] > 0 58 | ma_mask = pred[0, 3] > 0 59 | 60 | # Assign colors to each variable 61 | # Pink color for 'se' (RGB: 255, 192, 203) 62 | visualisation[se_mask, 0] = 255 # Red channel 63 | visualisation[se_mask, 1] = 192 # Green channel 64 | visualisation[se_mask, 2] = 203 # Blue channel 65 | 66 | # White color for 'he' (RGB: 255, 255, 255) 67 | visualisation[he_mask, 0] = 255 # Red channel 68 | visualisation[he_mask, 1] = 255 # Green channel 69 | visualisation[he_mask, 2] = 255 # Blue channel 70 | 71 | # Cyan color for 'ma' (RGB: 0, 255, 255) 72 | visualisation[ma_mask, 0] = 0 # Red channel 73 | visualisation[ma_mask, 1] = 255 # Green channel 74 | visualisation[ma_mask, 2] = 255 # Blue channel 75 | 76 | # Orange color for 'ex' (RGB: 255, 165, 0) 77 | visualisation[ex_mask, 0] = 255 # Red channel 78 | visualisation[ex_mask, 1] = 165 # Green channel 79 | visualisation[ex_mask, 2] = 0 # Blue channel 80 | 81 | # Set the alpha channel to make the colors visible where any variable is present 82 | alpha_mask = se_mask | he_mask | ma_mask | ex_mask 83 | visualisation[alpha_mask, 3] = 255 # Alpha channel 84 | return visualisation 85 | -------------------------------------------------------------------------------- /PVBM/__init__.py: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /PVBM/__pycache__/CentralRetinalAnalysis.cpython-311.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aim-lab/PVBM/71c9077164098f85c928a09be719468e0a5896e4/PVBM/__pycache__/CentralRetinalAnalysis.cpython-311.pyc -------------------------------------------------------------------------------- /PVBM/__pycache__/Datasets.cpython-311.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aim-lab/PVBM/71c9077164098f85c928a09be719468e0a5896e4/PVBM/__pycache__/Datasets.cpython-311.pyc -------------------------------------------------------------------------------- /PVBM/__pycache__/DiscSegmenter.cpython-311.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aim-lab/PVBM/71c9077164098f85c928a09be719468e0a5896e4/PVBM/__pycache__/DiscSegmenter.cpython-311.pyc -------------------------------------------------------------------------------- /PVBM/__pycache__/FractalAnalysis.cpython-310.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aim-lab/PVBM/71c9077164098f85c928a09be719468e0a5896e4/PVBM/__pycache__/FractalAnalysis.cpython-310.pyc -------------------------------------------------------------------------------- /PVBM/__pycache__/FractalAnalysis.cpython-311.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aim-lab/PVBM/71c9077164098f85c928a09be719468e0a5896e4/PVBM/__pycache__/FractalAnalysis.cpython-311.pyc -------------------------------------------------------------------------------- /PVBM/__pycache__/GeometricalAnalysis.cpython-310.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aim-lab/PVBM/71c9077164098f85c928a09be719468e0a5896e4/PVBM/__pycache__/GeometricalAnalysis.cpython-310.pyc -------------------------------------------------------------------------------- /PVBM/__pycache__/GeometricalAnalysis.cpython-311.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aim-lab/PVBM/71c9077164098f85c928a09be719468e0a5896e4/PVBM/__pycache__/GeometricalAnalysis.cpython-311.pyc -------------------------------------------------------------------------------- /PVBM/__pycache__/GeometryAnalysis.cpython-311.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aim-lab/PVBM/71c9077164098f85c928a09be719468e0a5896e4/PVBM/__pycache__/GeometryAnalysis.cpython-311.pyc -------------------------------------------------------------------------------- /PVBM/__pycache__/LesionSegmenter.cpython-311.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aim-lab/PVBM/71c9077164098f85c928a09be719468e0a5896e4/PVBM/__pycache__/LesionSegmenter.cpython-311.pyc -------------------------------------------------------------------------------- /PVBM/__pycache__/__init__.cpython-310.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aim-lab/PVBM/71c9077164098f85c928a09be719468e0a5896e4/PVBM/__pycache__/__init__.cpython-310.pyc -------------------------------------------------------------------------------- /PVBM/__pycache__/__init__.cpython-311.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aim-lab/PVBM/71c9077164098f85c928a09be719468e0a5896e4/PVBM/__pycache__/__init__.cpython-311.pyc -------------------------------------------------------------------------------- /PVBM/debug.py: -------------------------------------------------------------------------------- 1 | from PIL import Image,ImageFilter #Import Pillow library to load the images 2 | import numpy as np #Import numpy 3 | from skimage.morphology import skeletonize,square,dilation #Import functions to compute morphological operations 4 | import os 5 | import pathlib 6 | path_to_save_datasets = "../PVBM_datasets" 7 | from PVBM.Datasets import PVBM_Datasets 8 | import sys 9 | sys.setrecursionlimit(100000) 10 | 11 | # dataset_downloader = PVBM_Datasets() 12 | # dataset_downloader.download_dataset("Crop_HRF", path_to_save_datasets) 13 | # dataset_downloader.download_dataset("INSPIRE", path_to_save_datasets) 14 | # dataset_downloader.download_dataset("UNAF", path_to_save_datasets) 15 | # print("Images downloaded successfully") 16 | segmentation_path = list(pathlib.Path(path_to_save_datasets).glob("*/artery/*"))[10] 17 | segmentation = Image.open(segmentation_path) #Open the segmentation 18 | image_path = str(segmentation_path).replace("artery","images").replace("veins", "images") 19 | image = Image.open(image_path) 20 | # Depending on the quality of the segmentation, you would need to regularize (smooth) it more or less 21 | #before computing the skeleton for instance by uncomment the following command 22 | #segmentation = segmentation.filter(ImageFilter.ModeFilter(size=3)) 23 | 24 | segmentation = np.array(segmentation)/255 #Convert the segmentation to a numpy array with value 0 and 1 25 | skeleton = skeletonize(segmentation)*1 # Compute the skeleton of the segmentation 26 | 27 | from PVBM.DiscSegmenter import DiscSegmenter 28 | segmenter = DiscSegmenter() 29 | optic_disc = segmenter.segment(str(segmentation_path).replace("artery","images").replace("veins", "images")) 30 | center, radius, roi, zones_ABC = segmenter.post_processing(optic_disc, max_roi_size = 600) 31 | from PVBM.CentralRetinalAnalysis import CREVBMs 32 | creVBMs = CREVBMs() 33 | zone_A_ = zones_ABC[:,:,1]/255 34 | zone_B_ = zones_ABC[:,:,0]/255 35 | zone_C_ = zones_ABC[:,:,2]/255 36 | outsideB = (zone_C_ - zone_B_) 37 | segmentation_roi = (segmentation * outsideB) 38 | skeleton_roi = (skeleton * outsideB) 39 | out = creVBMs.compute_central_retinal_equivalents(segmentation_roi.copy(), skeleton_roi.copy(),center[0],center[1], radius, artery = True, Toplot = False ) 40 | 1 41 | -------------------------------------------------------------------------------- /PVBM/helpers/__init__.py: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /PVBM/helpers/__pycache__/__init__.cpython-310.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aim-lab/PVBM/71c9077164098f85c928a09be719468e0a5896e4/PVBM/helpers/__pycache__/__init__.cpython-310.pyc -------------------------------------------------------------------------------- /PVBM/helpers/__pycache__/__init__.cpython-311.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aim-lab/PVBM/71c9077164098f85c928a09be719468e0a5896e4/PVBM/helpers/__pycache__/__init__.cpython-311.pyc -------------------------------------------------------------------------------- /PVBM/helpers/__pycache__/branching2.cpython-310.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aim-lab/PVBM/71c9077164098f85c928a09be719468e0a5896e4/PVBM/helpers/__pycache__/branching2.cpython-310.pyc -------------------------------------------------------------------------------- /PVBM/helpers/__pycache__/branching2.cpython-311.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aim-lab/PVBM/71c9077164098f85c928a09be719468e0a5896e4/PVBM/helpers/__pycache__/branching2.cpython-311.pyc -------------------------------------------------------------------------------- /PVBM/helpers/__pycache__/branching_angle.cpython-310.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aim-lab/PVBM/71c9077164098f85c928a09be719468e0a5896e4/PVBM/helpers/__pycache__/branching_angle.cpython-310.pyc -------------------------------------------------------------------------------- /PVBM/helpers/__pycache__/branching_angle.cpython-311.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aim-lab/PVBM/71c9077164098f85c928a09be719468e0a5896e4/PVBM/helpers/__pycache__/branching_angle.cpython-311.pyc -------------------------------------------------------------------------------- /PVBM/helpers/__pycache__/far.cpython-310.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aim-lab/PVBM/71c9077164098f85c928a09be719468e0a5896e4/PVBM/helpers/__pycache__/far.cpython-310.pyc -------------------------------------------------------------------------------- /PVBM/helpers/__pycache__/perimeter.cpython-310.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aim-lab/PVBM/71c9077164098f85c928a09be719468e0a5896e4/PVBM/helpers/__pycache__/perimeter.cpython-310.pyc -------------------------------------------------------------------------------- /PVBM/helpers/__pycache__/perimeter.cpython-311.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aim-lab/PVBM/71c9077164098f85c928a09be719468e0a5896e4/PVBM/helpers/__pycache__/perimeter.cpython-311.pyc -------------------------------------------------------------------------------- /PVBM/helpers/__pycache__/tortuosity.cpython-310.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aim-lab/PVBM/71c9077164098f85c928a09be719468e0a5896e4/PVBM/helpers/__pycache__/tortuosity.cpython-310.pyc -------------------------------------------------------------------------------- /PVBM/helpers/__pycache__/tortuosity.cpython-311.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aim-lab/PVBM/71c9077164098f85c928a09be719468e0a5896e4/PVBM/helpers/__pycache__/tortuosity.cpython-311.pyc -------------------------------------------------------------------------------- /PVBM/helpers/branching2.py: -------------------------------------------------------------------------------- 1 | import PIL 2 | import numpy as np 3 | from skimage.morphology import skeletonize 4 | #import matplotlib.pyplot as plt 5 | import scipy.misc 6 | import numpy as np 7 | from skimage.draw import line_aa 8 | from skimage.morphology import (erosion, dilation, closing, opening, 9 | area_closing, area_opening,disk) 10 | #from tqdm.notebook import tqdm 11 | from scipy.signal import convolve2d 12 | filter_ = np.ones((3,3)) 13 | filter_[1,1] = 10 14 | filter_ 15 | 16 | max_size = 20 17 | 18 | 19 | def recursive(i_or,j_or,skeleton,i,j,visited,all_important_index,connected,dist,plot = True,zoom = True,size = 10,verbose = 0): 20 | if verbose: 21 | print('current :', i,j) 22 | tmp = np.zeros_like(skeleton) 23 | up = (i-1,j) 24 | down = (i+1,j) 25 | left = (i,j-1) 26 | right = (i,j+1) 27 | 28 | up_left = (i-1,j-1) 29 | up_right = (i-1,j+1) 30 | down_left = (i+1,j-1) 31 | down_right = (i+1,j+1) 32 | if up[0] >=0 and visited[up] == 0: 33 | visited[up] = 1 34 | if skeleton[up[0]][up[1]] ==1: 35 | if dist == max_size: 36 | connected[(i_or,j_or)] = connected.get((i_or,j_or),[]) + [up] 37 | 38 | else : 39 | recursive(i_or,j_or,skeleton,up[0],up[1],visited,all_important_index,connected,dist +1 , plot = plot) 40 | 41 | if down[0] < len(skeleton) and visited[down] == 0: 42 | visited[down] = 1 43 | if skeleton[down[0]][down[1]] ==1: 44 | if dist == max_size: 45 | connected[(i_or,j_or)] = connected.get((i_or,j_or),[]) + [down] 46 | 47 | else : 48 | recursive(i_or,j_or,skeleton,down[0],down[1],visited,all_important_index,connected,dist +1, plot = plot) 49 | 50 | if left[1] >= 0 and visited[left] == 0: 51 | visited[left] = 1 52 | if skeleton[left[0]][left[1]] ==1: 53 | if dist == max_size : 54 | connected[(i_or,j_or)] = connected.get((i_or,j_or),[]) + [left] 55 | 56 | else : 57 | recursive(i_or,j_or,skeleton,left[0],left[1],visited,all_important_index,connected,dist+1, plot = plot) 58 | 59 | if right[1] =0 and up_left[1] >=0 and visited[up_left] == 0: 69 | visited[up_left] = 1 70 | if skeleton[up_left[0]][up_left[1]] ==1 : 71 | if dist == max_size: 72 | connected[(i_or,j_or)] = connected.get((i_or,j_or),[]) + [up_left] 73 | 74 | else : 75 | recursive(i_or,j_or,skeleton,up_left[0],up_left[1],visited,all_important_index,connected,dist +1, plot = plot) 76 | 77 | if up_right[0] >=0 and up_right[1] < len(skeleton) and visited[up_right] ==0: 78 | visited[up_right] = 1 79 | if skeleton[up_right[0]][up_right[1]] ==1: 80 | if dist == max_size: 81 | connected[(i_or,j_or)] = connected.get((i_or,j_or),[]) + [up_right] 82 | 83 | else : 84 | recursive(i_or,j_or,skeleton,up_right[0],up_right[1],visited,all_important_index,connected,dist+1, plot = plot) 85 | 86 | if down_left[0] < len(skeleton) and down_left[1] >=0 and visited[down_left] ==0: 87 | visited[down_left] = 1 88 | if skeleton[down_left[0]][down_left[1]] ==1: 89 | if down_left in all_important_index or dist == max_size: 90 | connected[(i_or,j_or)] = connected.get((i_or,j_or),[]) + [down_left] 91 | 92 | else : 93 | recursive(i_or,j_or,skeleton,down_left[0],down_left[1],visited,all_important_index,connected,dist+1 , plot = plot) 94 | 95 | if down_right[0] < len(skeleton) and down_right[1] < len(skeleton) and visited[down_right] ==0: 96 | visited[down_right] = 1 97 | if skeleton[down_right[0]][down_right[1]] ==1: 98 | if dist == max_size: 99 | connected[(i_or,j_or)] = connected.get((i_or,j_or),[]) + [down_right] 100 | 101 | else : 102 | recursive(i_or,j_or,skeleton,down_right[0],down_right[1],visited,all_important_index,connected,dist+1, plot = plot) 103 | 104 | 105 | def connected_pixels(skeleton,all_important_index,verbose = 0): 106 | connected = {} 107 | for i,j in all_important_index: 108 | visited = np.zeros((skeleton.shape[0],skeleton.shape[1])) 109 | if verbose : 110 | print('starting point : ',i,j) 111 | if skeleton[i][j] ==1 and (i,j) in all_important_index : 112 | recursive(i,j,skeleton,i,j,visited,all_important_index,connected,0,zoom = False,plot = False,verbose = verbose) 113 | return connected 114 | 115 | def compute_tortuosity(skeleton): 116 | tmp = convolve2d(skeleton,filter_,mode = "same") 117 | endpoints = tmp == 11 118 | intersection = tmp >= 13 119 | final_eroded = intersection 120 | origin_points = [] 121 | for i in range(final_eroded.shape[0]): 122 | for j in range(final_eroded.shape[1]): 123 | if final_eroded[i,j] == True: 124 | origin_points.append((i,j)) 125 | 126 | connection_dico = connected_pixels(skeleton,origin_points,verbose = 0) 127 | return connection_dico 128 | 129 | 130 | -------------------------------------------------------------------------------- /PVBM/helpers/branching_angle.py: -------------------------------------------------------------------------------- 1 | import PIL 2 | import numpy as np 3 | from skimage.morphology import skeletonize 4 | #import matplotlib.pyplot as plt 5 | import scipy.misc 6 | import numpy as np 7 | from skimage.draw import line_aa 8 | from skimage.morphology import (erosion, dilation, closing, opening, 9 | area_closing, area_opening,disk) 10 | #from tqdm.notebook import tqdm 11 | from PVBM.helpers.branching2 import compute_tortuosity 12 | 13 | from scipy.signal import convolve2d 14 | from queue import PriorityQueue 15 | 16 | filter_ = np.ones((3,3)) 17 | filter_[1,1] = 10 18 | filter_ 19 | 20 | def preprocess(skeleton): 21 | tmp = convolve2d(skeleton,filter_,mode = "same") 22 | endpoints = tmp == 11 23 | intersection = tmp >= 13 24 | final_eroded = endpoints + intersection 25 | origin_points = [] 26 | for i in range(final_eroded.shape[0]): 27 | for j in range(final_eroded.shape[1]): 28 | if final_eroded[i,j] == True: 29 | origin_points.append((i,j)) 30 | return origin_points 31 | 32 | def iterative(i,j,skeleton,origin_points,visited,dist,distance_dictionnary): 33 | pq = PriorityQueue() 34 | pq.put((0, i, j, i, j,0)) 35 | priotities = [0,1,2,3,4,5,6,7] 36 | while not pq.empty(): 37 | _, i_or, j_or, i, j,dist = pq.get() 38 | directions = [(i-1,j),(i+1,j),(i,j-1),(i,j+1),(i-1,j-1),(i-1,j+1),(i+1,j-1),(i+1,j+1)] 39 | for direction,priority in zip(directions,priotities): 40 | x,y = direction 41 | if x >= 0 and x < skeleton.shape[0] and y >= 0 and y < skeleton.shape[1] and visited[direction] == 0: 42 | visited[direction] = 1 43 | if skeleton[x][y] == 1: 44 | point = direction 45 | distance_dictionnary[(point[0],point[1])] = max(distance_dictionnary[point[0],point[1]],dist +1) 46 | pq.put((priority, i_or, j_or, x, y,dist+1)) 47 | 48 | 49 | def distance(skeleton,origin_points): 50 | distance_dictionnary = np.zeros((skeleton.shape[0],skeleton.shape[1])) -1 51 | for i,j in origin_points: 52 | visited = np.zeros((skeleton.shape[0],skeleton.shape[1])) 53 | if visited[i,j] == 0: 54 | visited[i,j] = 1 55 | if skeleton[i][j] ==1 and (i,j) in origin_points : 56 | iterative(i,j,skeleton,origin_points,visited,0,distance_dictionnary) 57 | return distance_dictionnary 58 | 59 | def compute_distances(skeleton,origin_points): 60 | distance_dictionnary = distance(skeleton,origin_points) 61 | 62 | return distance_dictionnary 63 | 64 | def isdouble(key,v1,v2,dico_angle): 65 | for k in dico_angle.keys(): 66 | if set(key) == set(k): 67 | return True 68 | return False 69 | 70 | def isdouble2(key,v1,v2,last_dico_angle): 71 | for k in last_dico_angle.keys(): 72 | if set(key) == set(k): 73 | return True 74 | return False 75 | 76 | def is_in(a,dico): 77 | for element in dico.keys(): 78 | if set(element) == a: 79 | return True 80 | return False 81 | def crop(angle): 82 | if angle >1 : 83 | return 1 84 | if angle <-1: 85 | return -1 86 | return angle 87 | def compute_angles_dictionary(skeleton): 88 | origin_points = preprocess(skeleton) 89 | distances_dico = compute_distances(skeleton,origin_points) ##plotable centroid 90 | centroid = distances_dico.copy() 91 | distance_dico_tmp = distances_dico.copy() 92 | distances_dico = {} 93 | for i in range(distance_dico_tmp.shape[0]): 94 | for j in range(distance_dico_tmp.shape[1]): 95 | if distance_dico_tmp[i,j] != -1 : 96 | distances_dico[i,j] = distance_dico_tmp[i,j] 97 | connection_dico = compute_tortuosity(skeleton) 98 | #return connection_dico 99 | dico_angle = {} 100 | for key,values in connection_dico.items(): 101 | for v1 in values: 102 | for v2 in values: 103 | if v2 != v1 and not isdouble(key,v1,v2,dico_angle) and not isdouble(key,v2,v1,dico_angle) : 104 | b = np.array(key) 105 | a = np.array(v1) 106 | c = np.array(v2) 107 | ba = a - b 108 | bc = c - b 109 | if np.isnan(ba).any() or np.isnan(bc).any() or np.isinf(ba).any() or np.isinf(bc).any() or np.linalg.norm(ba) == 0 or np.linalg.norm(bc) == 0: 110 | continue 111 | 112 | cosine_angle = np.dot(ba, bc) / (np.linalg.norm(ba) * np.linalg.norm(bc)) 113 | angle = np.arccos(crop(cosine_angle)) 114 | 115 | if np.mean(np.abs(b-a)) > 5 and np.mean(np.abs(b-c))>5 : 116 | dico_angle[(key,v1,v2)] = np.degrees(angle) 117 | final_connection_dico = {} 118 | for key in dico_angle.keys(): 119 | get = final_connection_dico.get(key[0],[]) 120 | for element in key[1:]: 121 | if element not in get: 122 | get.append(element) 123 | 124 | final_connection_dico[key[0]] = get 125 | 126 | last_connection_dico = {} 127 | for key,value in final_connection_dico.items(): 128 | if len(value) > 2: 129 | min_idx = 0 130 | min_point = value[0] 131 | min_dist = distances_dico.get(min_point,1444) 132 | for i in range(len(value)): 133 | point = value[i] 134 | dist = distances_dico.get(point,1444) 135 | if dist < min_dist: 136 | min_idx = i 137 | min_point = point 138 | min_dist = dist 139 | final_tuple = [] 140 | for val in value: 141 | if val != min_point: 142 | final_tuple.append(val) 143 | last_connection_dico[key] = final_tuple 144 | last_dico_angle = {} 145 | for key,values in last_connection_dico.items(): 146 | for v1 in values: 147 | for v2 in values: 148 | if v2 != v1 and not isdouble2(key,v1,v2,last_dico_angle) and not isdouble2(key,v2,v1,last_dico_angle): 149 | b = np.array(key) 150 | a = np.array(v1) 151 | c = np.array(v2) 152 | ba = a - b 153 | bc = c - b 154 | 155 | cosine_angle = np.dot(ba, bc) / (np.linalg.norm(ba) * np.linalg.norm(bc)) 156 | angle = np.arccos(crop(cosine_angle)) 157 | 158 | if np.mean(np.abs(b-a)) > 5 and np.mean(np.abs(b-c))>5 : 159 | last_dico_angle[(key,v1,v2)] = np.degrees(angle) 160 | 161 | final_angle_dico = {} 162 | for key,value in last_dico_angle.items(): 163 | if not is_in(set(key),final_angle_dico): 164 | final_angle_dico[key] = value 165 | 166 | return final_angle_dico,centroid 167 | 168 | 169 | 170 | 171 | 172 | -------------------------------------------------------------------------------- /PVBM/helpers/perimeter.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | from scipy.signal import convolve2d 3 | 4 | from queue import PriorityQueue 5 | 6 | 7 | def iterative(i,j, skeleton, distances_matrix): 8 | pq = PriorityQueue() 9 | pq.put((0, i, j)) 10 | priotities = [0,1,2,3,4,5,6,7] 11 | distances = [1, 1, 1, 1, 2**0.5, 2**0.5, 2**0.5, 2**0.5] 12 | while not pq.empty(): 13 | _, i, j = pq.get() 14 | directions = [(i-1,j),(i+1,j),(i,j-1),(i,j+1),(i-1,j-1),(i-1,j+1),(i+1,j-1),(i+1,j+1)] 15 | for direction, distance,priority in zip(directions,distances,priotities): 16 | x,y = direction 17 | if x >= 0 and x < skeleton.shape[0] and y >= 0 and y < skeleton.shape[1] and skeleton[direction] == 1: 18 | distances_matrix[direction] = distance 19 | skeleton[direction] = 0 20 | pq.put((priority, direction[0],direction[1])) 21 | 22 | 23 | 24 | 25 | def extract_subgraphs(skeleton): 26 | distances = np.zeros((skeleton.shape[0],skeleton.shape[1]),dtype = float) 27 | for i in range(distances.shape[0]): 28 | for j in range(distances.shape[1]): 29 | if distances[i,j] == 0 and skeleton[i,j] == 1: 30 | iterative(i,j,skeleton,distances) 31 | return distances 32 | 33 | 34 | def compute_perimeter_(skeleton): 35 | distances = extract_subgraphs(skeleton) 36 | return np.sum(distances),distances 37 | -------------------------------------------------------------------------------- /PVBM/helpers/tortuosity.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | from scipy.signal import convolve2d 3 | 4 | from queue import PriorityQueue 5 | 6 | def iterative(i_or, j_or, skeleton, all_important_index, visited, connected): 7 | pq = PriorityQueue() 8 | pq.put((0, i_or, j_or, i_or, j_or,0)) 9 | priotities = [0,1,2,3,4,5,6,7] 10 | distances = [1, 1, 1, 1, 2**0.5, 2**0.5, 2**0.5, 2**0.5] 11 | while not pq.empty(): 12 | _, i_or, j_or, i, j,d = pq.get() 13 | directions = [(i-1,j),(i+1,j),(i,j-1),(i,j+1),(i-1,j-1),(i-1,j+1),(i+1,j-1),(i+1,j+1)] 14 | for direction, distance,priority in zip(directions,distances,priotities): 15 | x,y = direction 16 | if x >= 0 and x < skeleton.shape[0] and y >= 0 and y < skeleton.shape[1] and visited[direction] == 0: 17 | if direction not in all_important_index: 18 | visited[direction] = 1 19 | if skeleton[x][y] == 1: 20 | point = direction 21 | if direction in all_important_index: 22 | connected[(i_or,j_or)] = connected.get((i_or,j_or),[]) + [(direction,d + distance)] 23 | else : 24 | pq.put((priority, i_or, j_or, x, y,d + distance )) 25 | 26 | 27 | 28 | 29 | 30 | def connected_pixels(skeleton, all_important_index): 31 | connected = {} 32 | visited = np.zeros_like(skeleton) 33 | for i, j in all_important_index: 34 | if skeleton[i][j] == 1 and not visited[i][j]: 35 | iterative(i, j, skeleton, all_important_index,visited,connected) 36 | #recursive(i, j, skeleton, i, j, visited, all_important_index, connected) 37 | return connected 38 | 39 | from scipy.signal import convolve2d 40 | filter_ = np.ones((3,3)) 41 | filter_[1,1] = 10 42 | filter_ 43 | 44 | 45 | 46 | def compute_tortuosity(skeleton): 47 | tmp = convolve2d(skeleton, filter_, mode="same") 48 | endpoints = tmp == 11 49 | intersection = tmp >= 13 50 | particular = endpoints + intersection 51 | origin_points = [(i, j) for i in range(particular.shape[0]) for j in range(particular.shape[1]) if particular[i, j]] 52 | connection_dico = connected_pixels(skeleton, origin_points) 53 | tor = [] 54 | chord = [] 55 | arc = [] 56 | for key, value in connection_dico.items(): 57 | x, y = key 58 | for p, d in value: 59 | if d > 10: 60 | arc.append(d) 61 | x2, y2 = p 62 | real_d = ((x - x2) ** 2 + (y - y2) ** 2) ** 0.5 63 | tor.append(d/real_d) 64 | chord.append(real_d) 65 | return np.median(tor), np.sum(chord), arc, chord, connection_dico 66 | 67 | 68 | 69 | -------------------------------------------------------------------------------- /docs/CentralRetinalAnalysis.rst: -------------------------------------------------------------------------------- 1 | CentralRetinalAnalysis 2 | =============== 3 | 4 | .. automodule:: PVBM.CentralRetinalAnalysis 5 | 6 | .. autoclass:: CREVBMs 7 | :members: None 8 | 9 | .. automethod:: compute_central_retinal_equivalents 10 | .. automethod:: apply_roi 11 | 12 | -------------------------------------------------------------------------------- /docs/Datasets.rst: -------------------------------------------------------------------------------- 1 | Datasets 2 | =================== 3 | 4 | .. automodule:: PVBM.Datasets 5 | 6 | .. autoclass:: PVBMDataDownloader 7 | :members: None 8 | 9 | .. automethod:: download_dataset 10 | -------------------------------------------------------------------------------- /docs/DiscSegmenter.rst: -------------------------------------------------------------------------------- 1 | DiscSegmenter 2 | =================== 3 | 4 | .. automodule:: PVBM.DiscSegmenter 5 | 6 | .. autoclass:: DiscSegmenter 7 | :members: None 8 | 9 | .. automethod:: segment 10 | .. automethod:: post_processing 11 | -------------------------------------------------------------------------------- /docs/FractalAnalysis.rst: -------------------------------------------------------------------------------- 1 | FractalAnalysis 2 | =============== 3 | 4 | .. automodule:: PVBM.FractalAnalysis 5 | 6 | .. autoclass:: MultifractalVBMs 7 | :members: None 8 | 9 | .. automethod:: compute_multifractals 10 | -------------------------------------------------------------------------------- /docs/GeometricalAnalysis.rst: -------------------------------------------------------------------------------- 1 | GeometricalAnalysis 2 | =================== 3 | 4 | .. automodule:: PVBM.GeometricalAnalysis 5 | :members: 6 | -------------------------------------------------------------------------------- /docs/GeometryAnalysis.rst: -------------------------------------------------------------------------------- 1 | GeometryAnalysis 2 | =================== 3 | 4 | .. automodule:: PVBM.GeometryAnalysis 5 | 6 | .. autoclass:: GeometricalVBMs 7 | :members: None 8 | 9 | .. automethod:: compute_geomVBMs 10 | .. automethod:: apply_roi 11 | -------------------------------------------------------------------------------- /docs/LesionSegmenter.rst: -------------------------------------------------------------------------------- 1 | LesionSegmenter 2 | =================== 3 | 4 | .. automodule:: PVBM.LesionSegmenter 5 | 6 | .. autoclass:: LesionSegmenter 7 | :members: None 8 | 9 | .. automethod:: __init__ 10 | 11 | .. automethod:: segment 12 | -------------------------------------------------------------------------------- /docs/Makefile: -------------------------------------------------------------------------------- 1 | # Minimal makefile for Sphinx documentation 2 | # 3 | 4 | # You can set these variables from the command line, and also 5 | # from the environment for the first two. 6 | SPHINXOPTS ?= 7 | SPHINXBUILD ?= sphinx-build 8 | SOURCEDIR = . 9 | BUILDDIR = _build 10 | 11 | # Put it first so that "make" without argument is like "make help". 12 | help: 13 | @$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) 14 | 15 | .PHONY: help Makefile 16 | 17 | # Catch-all target: route all unknown targets to Sphinx using the new 18 | # "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS). 19 | %: Makefile 20 | @$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) 21 | -------------------------------------------------------------------------------- /docs/VBMsumary.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aim-lab/PVBM/71c9077164098f85c928a09be719468e0a5896e4/docs/VBMsumary.jpg -------------------------------------------------------------------------------- /docs/_build/doctrees/CentralRetinalAnalysis.doctree: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aim-lab/PVBM/71c9077164098f85c928a09be719468e0a5896e4/docs/_build/doctrees/CentralRetinalAnalysis.doctree -------------------------------------------------------------------------------- /docs/_build/doctrees/Datasets.doctree: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aim-lab/PVBM/71c9077164098f85c928a09be719468e0a5896e4/docs/_build/doctrees/Datasets.doctree -------------------------------------------------------------------------------- /docs/_build/doctrees/DiscSegmenter.doctree: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aim-lab/PVBM/71c9077164098f85c928a09be719468e0a5896e4/docs/_build/doctrees/DiscSegmenter.doctree -------------------------------------------------------------------------------- /docs/_build/doctrees/FractalAnalysis.doctree: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aim-lab/PVBM/71c9077164098f85c928a09be719468e0a5896e4/docs/_build/doctrees/FractalAnalysis.doctree -------------------------------------------------------------------------------- /docs/_build/doctrees/GeometricalAnalysis.doctree: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aim-lab/PVBM/71c9077164098f85c928a09be719468e0a5896e4/docs/_build/doctrees/GeometricalAnalysis.doctree -------------------------------------------------------------------------------- /docs/_build/doctrees/GeometryAnalysis.doctree: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aim-lab/PVBM/71c9077164098f85c928a09be719468e0a5896e4/docs/_build/doctrees/GeometryAnalysis.doctree -------------------------------------------------------------------------------- /docs/_build/doctrees/LesionSegmenter.doctree: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aim-lab/PVBM/71c9077164098f85c928a09be719468e0a5896e4/docs/_build/doctrees/LesionSegmenter.doctree -------------------------------------------------------------------------------- /docs/_build/doctrees/environment.pickle: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aim-lab/PVBM/71c9077164098f85c928a09be719468e0a5896e4/docs/_build/doctrees/environment.pickle -------------------------------------------------------------------------------- /docs/_build/doctrees/index.doctree: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aim-lab/PVBM/71c9077164098f85c928a09be719468e0a5896e4/docs/_build/doctrees/index.doctree -------------------------------------------------------------------------------- /docs/_build/doctrees/nbsphinx/pvbmtutorial_14_0.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aim-lab/PVBM/71c9077164098f85c928a09be719468e0a5896e4/docs/_build/doctrees/nbsphinx/pvbmtutorial_14_0.png -------------------------------------------------------------------------------- /docs/_build/doctrees/nbsphinx/pvbmtutorial_15_0.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aim-lab/PVBM/71c9077164098f85c928a09be719468e0a5896e4/docs/_build/doctrees/nbsphinx/pvbmtutorial_15_0.png -------------------------------------------------------------------------------- /docs/_build/doctrees/nbsphinx/pvbmtutorial_17_0.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aim-lab/PVBM/71c9077164098f85c928a09be719468e0a5896e4/docs/_build/doctrees/nbsphinx/pvbmtutorial_17_0.png -------------------------------------------------------------------------------- /docs/_build/doctrees/nbsphinx/pvbmtutorial_21_0.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aim-lab/PVBM/71c9077164098f85c928a09be719468e0a5896e4/docs/_build/doctrees/nbsphinx/pvbmtutorial_21_0.png -------------------------------------------------------------------------------- /docs/_build/doctrees/nbsphinx/pvbmtutorial_21_1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aim-lab/PVBM/71c9077164098f85c928a09be719468e0a5896e4/docs/_build/doctrees/nbsphinx/pvbmtutorial_21_1.png -------------------------------------------------------------------------------- /docs/_build/doctrees/nbsphinx/pvbmtutorial_25_0.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aim-lab/PVBM/71c9077164098f85c928a09be719468e0a5896e4/docs/_build/doctrees/nbsphinx/pvbmtutorial_25_0.png -------------------------------------------------------------------------------- /docs/_build/doctrees/nbsphinx/pvbmtutorial_26_0.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aim-lab/PVBM/71c9077164098f85c928a09be719468e0a5896e4/docs/_build/doctrees/nbsphinx/pvbmtutorial_26_0.png -------------------------------------------------------------------------------- /docs/_build/doctrees/nbsphinx/pvbmtutorial_30_0.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aim-lab/PVBM/71c9077164098f85c928a09be719468e0a5896e4/docs/_build/doctrees/nbsphinx/pvbmtutorial_30_0.png -------------------------------------------------------------------------------- /docs/_build/doctrees/nbsphinx/pvbmtutorial_31_0.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aim-lab/PVBM/71c9077164098f85c928a09be719468e0a5896e4/docs/_build/doctrees/nbsphinx/pvbmtutorial_31_0.png -------------------------------------------------------------------------------- /docs/_build/doctrees/nbsphinx/pvbmtutorial_36_0.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aim-lab/PVBM/71c9077164098f85c928a09be719468e0a5896e4/docs/_build/doctrees/nbsphinx/pvbmtutorial_36_0.png -------------------------------------------------------------------------------- /docs/_build/doctrees/nbsphinx/pvbmtutorial_38_0.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aim-lab/PVBM/71c9077164098f85c928a09be719468e0a5896e4/docs/_build/doctrees/nbsphinx/pvbmtutorial_38_0.png -------------------------------------------------------------------------------- /docs/_build/doctrees/nbsphinx/pvbmtutorial_39_0.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aim-lab/PVBM/71c9077164098f85c928a09be719468e0a5896e4/docs/_build/doctrees/nbsphinx/pvbmtutorial_39_0.png -------------------------------------------------------------------------------- /docs/_build/doctrees/nbsphinx/pvbmtutorial_40_0.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aim-lab/PVBM/71c9077164098f85c928a09be719468e0a5896e4/docs/_build/doctrees/nbsphinx/pvbmtutorial_40_0.png -------------------------------------------------------------------------------- /docs/_build/doctrees/nbsphinx/pvbmtutorial_42_0.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aim-lab/PVBM/71c9077164098f85c928a09be719468e0a5896e4/docs/_build/doctrees/nbsphinx/pvbmtutorial_42_0.png -------------------------------------------------------------------------------- /docs/_build/doctrees/nbsphinx/pvbmtutorial_50_0.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aim-lab/PVBM/71c9077164098f85c928a09be719468e0a5896e4/docs/_build/doctrees/nbsphinx/pvbmtutorial_50_0.png -------------------------------------------------------------------------------- /docs/_build/doctrees/nbsphinx/pvbmtutorial_55_0.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aim-lab/PVBM/71c9077164098f85c928a09be719468e0a5896e4/docs/_build/doctrees/nbsphinx/pvbmtutorial_55_0.png -------------------------------------------------------------------------------- /docs/_build/doctrees/pvbmtutorial.doctree: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aim-lab/PVBM/71c9077164098f85c928a09be719468e0a5896e4/docs/_build/doctrees/pvbmtutorial.doctree -------------------------------------------------------------------------------- /docs/_build/html/.buildinfo: -------------------------------------------------------------------------------- 1 | # Sphinx build info version 1 2 | # This file hashes the configuration used when building these files. When it is not found, a full rebuild will be done. 3 | config: c451f562f0347dd4d97ecb138de3b220 4 | tags: 645f666f9bcd5a90fca523b33c5a78b7 5 | -------------------------------------------------------------------------------- /docs/_build/html/CentralRetinalAnalysis.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | CentralRetinalAnalysis — PVBM 3.0.0.0 documentation 8 | 9 | 10 | 11 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 |
28 | 66 | 67 |
71 | 72 |
73 |
74 |
75 | 82 |
83 |
84 |
85 |
86 | 87 |
88 |

CentralRetinalAnalysis

89 |
90 |
91 | class PVBM.CentralRetinalAnalysis.CREVBMs[source]
92 |

A class that can perform geometrical biomarker computation for a fundus image.

93 |
94 |
95 | compute_central_retinal_equivalents(blood_vessel, skeleton, xc, yc, radius, artery=True, Toplot=False)[source]
96 |

Compute the CRAE or CRVE equivalent for a given blood vessel graph.

97 |
98 |
Parameters:
99 |
    100 |
  • blood_vessel (np.array) – blood_vessel segmentation containing binary values within {0,1}

  • 101 |
  • skeleton (np.array) – blood_vessel segmentation skeleton containing binary values within {0,1}

  • 102 |
  • xc (int) – x axis of the optic disc center

  • 103 |
  • yc (int) – y axis of the optic disc center

  • 104 |
  • radius (int) – radius in pixel of the optic disc

  • 105 |
  • artery (Bool) – Flag to decide if to use CRAE or CRVE formulas (artery to True means CRAE, and to False means CRVE)

  • 106 |
  • Toplot (Bool) – Flag to decide if to store the visualisation element. (Setting it to true use more RAM)

  • 107 |
108 |
109 |
Returns:
110 |

A tuple containing: 111 | - A result dictionnary (Dict): Dictionnary containing the computer CRE (-1 if it has failed) 112 | - plotable_list (List): A summary that contains the topology information required to plot the visualisation (really useful when Toplot is True). Return None if the computation has failed.

113 |
114 |
Return type:
115 |

Tuple[Dict, List]

116 |
117 |
118 |
119 | 120 |
121 |
122 | apply_roi(segmentation, skeleton, zones_ABC)[source]
123 |

Apply a region of interest (ROI) mask to the segmentation and skeleton images.

124 |
125 |
Parameters:
126 |
    127 |
  • segmentation (np.array) – The segmentation image containing binary values within {0, 1}.

  • 128 |
  • skeleton (np.array) – The skeleton image containing binary values within {0, 1}.

  • 129 |
  • zones_ABC (np.array) – A mask image used to exclude specific zones, where the second channel defines the exclusion areas.

  • 130 |
131 |
132 |
Returns:
133 |

A tuple containing: 134 | - The modified segmentation image with the ROI applied. 135 | - The modified skeleton image with the ROI applied.

136 |
137 |
Return type:
138 |

Tuple[np.array, np.array]

139 |
140 |
141 |
142 | 143 |
144 | 145 |
146 | 147 | 148 |
149 |
150 |
154 | 155 |
156 | 157 |
158 |

© Copyright 2023, JF.

159 |
160 | 161 | Built with Sphinx using a 162 | theme 163 | provided by Read the Docs. 164 | 165 | 166 |
167 |
168 |
169 |
170 |
171 | 176 | 177 | 178 | -------------------------------------------------------------------------------- /docs/_build/html/Datasets.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Datasets — PVBM 3.0.0.0 documentation 8 | 9 | 10 | 11 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 |
28 | 65 | 66 |
70 | 71 |
72 |
73 |
74 | 81 |
82 |
83 |
84 |
85 | 86 |
87 |

Datasets

88 |
89 |
90 | class PVBM.Datasets.PVBMDataDownloader[source]
91 |

A class that downloads the PVBM datasets.

92 |
93 |
94 | download_dataset(name, save_folder_path)[source]
95 |

Download the PVBM datasets

96 |
97 |
Parameters:
98 |
    99 |
  • name – Name of the dataset to download. Need to be within {“UNAF”, “INSPIRE”, “Crop_HRF”}

  • 100 |
  • save_folder_path – Path to the folder where to store the downloaded datasets

  • 101 |
102 |
103 |
104 |
105 | 106 |
107 | 108 |
109 | 110 | 111 |
112 |
113 |
117 | 118 |
119 | 120 |
121 |

© Copyright 2023, JF.

122 |
123 | 124 | Built with Sphinx using a 125 | theme 126 | provided by Read the Docs. 127 | 128 | 129 |
130 |
131 |
132 |
133 |
134 | 139 | 140 | 141 | -------------------------------------------------------------------------------- /docs/_build/html/DiscSegmenter.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | DiscSegmenter — PVBM 3.0.0.0 documentation 8 | 9 | 10 | 11 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 |
28 | 66 | 67 |
71 | 72 |
73 |
74 |
75 | 82 |
83 |
84 |
85 |
86 | 87 |
88 |

DiscSegmenter

89 |
90 |
91 | class PVBM.DiscSegmenter.DiscSegmenter[source]
92 |

A class that performs optic disc segmentation.

93 |
94 |
95 |
96 | segment(image_path)[source]
97 |

Perform the optic disc segmentation given an image path.

98 |
99 |
Parameters:
100 |

image_path (str) – Path to the image.

101 |
102 |
Returns:
103 |

A PIL Image containing the Optic Disc segmentation.

104 |
105 |
Return type:
106 |

PIL.Image

107 |
108 |
109 |
110 | 111 |
112 |
113 | post_processing(segmentation, max_roi_size)[source]
114 |

Post-process the segmentation result to extract relevant zones.

115 |
116 |
Parameters:
117 |
    118 |
  • segmentation (numpy array) – Segmentation result as a numpy array.

  • 119 |
  • max_roi_size (int) – Maximum size of the region of interest.

  • 120 |
121 |
122 |
Returns:
123 |

The center, radius, region of interest, and zones ABC.

124 |
125 |
Return type:
126 |

tuple

127 |
128 |
129 |
130 | 131 |
132 |
133 | 134 |
135 | 136 | 137 |
138 |
139 |
143 | 144 |
145 | 146 |
147 |

© Copyright 2023, JF.

148 |
149 | 150 | Built with Sphinx using a 151 | theme 152 | provided by Read the Docs. 153 | 154 | 155 |
156 |
157 |
158 |
159 |
160 | 165 | 166 | 167 | -------------------------------------------------------------------------------- /docs/_build/html/FractalAnalysis.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | FractalAnalysis — PVBM 3.0.0.0 documentation 8 | 9 | 10 | 11 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 |
28 | 65 | 66 |
70 | 71 |
72 |
73 |
74 | 81 |
82 |
83 |
84 |
85 | 86 |
87 |

FractalAnalysis

88 |
89 |
90 | class PVBM.FractalAnalysis.MultifractalVBMs(n_dim=10, n_rotations=25, optimize=True, min_proba=0.01, maxproba=0.98)[source]
91 |

A class that can perform multifractal biomarker computation for a fundus vasculature segmentation.

92 |
93 |
Parameters:
94 |
    95 |
  • n_dim (int) – Maximum dimension used to calculate Singularity Length.

  • 96 |
  • n_rotations (int) – Number of rotations performed on the given segmentation from which the optimal run will be chosen.

  • 97 |
  • optimize (bool) – A boolean value that specify if the computation will be made using several rotated version of the segmentation.

  • 98 |
  • min_proba (float) – A minimum probability for the occupancy of calculated boxes (boxes with smaller probability will be ignored).

  • 99 |
  • max_proba (float) – A maximum probability for the occupancy of calculated boxes (boxes with higher probability will be ignored).

  • 100 |
101 |
102 |
103 |
104 |
105 | compute_multifractals(segmentation)[source]
106 |

Computes the multifractal biomarkers of a given retinal vasculature segmentation, specifically the dimensions D0, D1, D2, and the singularity length.

107 |
108 |
Parameters:
109 |

segmentation (np.ndarray) – An (N,N) binary numpy array representing the segmentation to be analyzed.

110 |
111 |
Returns:
112 |

A numpy array containing the computed biomarkers [D0, D1, D2, Singularity Length].

113 |
114 |
Return type:
115 |

np.ndarray

116 |
117 |
118 |
119 | 120 |
121 | 122 |
123 | 124 | 125 |
126 |
127 |
131 | 132 |
133 | 134 |
135 |

© Copyright 2023, JF.

136 |
137 | 138 | Built with Sphinx using a 139 | theme 140 | provided by Read the Docs. 141 | 142 | 143 |
144 |
145 |
146 |
147 |
148 | 153 | 154 | 155 | -------------------------------------------------------------------------------- /docs/_build/html/GeometryAnalysis.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | GeometryAnalysis — PVBM 3.0.0.0 documentation 8 | 9 | 10 | 11 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 |
28 | 66 | 67 |
71 | 72 |
73 |
74 |
75 | 82 |
83 |
84 |
85 |
86 | 87 |
88 |

GeometryAnalysis

89 |
90 |
91 | class PVBM.GeometryAnalysis.GeometricalVBMs[source]
92 |

A class that can perform geometrical biomarker computation for a fundus image.

93 |
94 |
95 | compute_geomVBMs(blood_vessel, skeleton, xc, yc, radius)[source]
96 |

Compute various geometrical vascular biomarkers (VBMs) for a given blood vessel graph.

97 |

This function analyzes the blood vessel segmentation and skeleton to extract several biomarkers such as area, 98 | tortuosity index, median tortuosity, overall length, median branching angle, and counts of start, end, and 99 | intersection points. It also provides visualizations of specific points on the graph.

100 |
101 |
Parameters:
102 |
    103 |
  • blood_vessel (np.array) – Blood vessel segmentation containing binary values within {0,1}.

  • 104 |
  • skeleton (np.array) – Blood vessel segmentation skeleton containing binary values within {0,1}.

  • 105 |
  • xc (int) – X-axis coordinate of the optic disc center.

  • 106 |
  • yc (int) – Y-axis coordinate of the optic disc center.

  • 107 |
  • radius (int) – Radius in pixels of the optic disc.

  • 108 |
109 |
110 |
Returns:
111 |

A tuple containing: 112 | - A list of biomarkers [area, tortuosity index, median tortuosity, overall length, median branching angle, number of start points, number of end points, number of intersection points]. 113 | - A tuple of visualizations (endpoints, interpoints, startpoints, angles_dico, dico).

114 |
115 |
Return type:
116 |

Tuple[list, tuple]

117 |
118 |
119 |
120 | 121 |
122 |
123 | apply_roi(segmentation, skeleton, zones_ABC, roi)[source]
124 |

Apply a region of interest (ROI) mask to the segmentation and skeleton images.

125 |
126 |
Parameters:
127 |
    128 |
  • segmentation (np.array) – The segmentation image containing binary values within {0, 1}.

  • 129 |
  • skeleton (np.array) – The skeleton image containing binary values within {0, 1}.

  • 130 |
  • zones_ABC (np.array) – A mask image used to exclude specific zones, where the second channel defines the exclusion areas.

  • 131 |
  • roi (np.array) – The region of interest mask, where the second channel defines the ROI areas.

  • 132 |
133 |
134 |
Returns:
135 |

A tuple containing: 136 | - The modified segmentation image with the ROI applied. 137 | - The modified skeleton image with the ROI applied.

138 |
139 |
Return type:
140 |

Tuple[np.array, np.array]

141 |
142 |
143 |
144 | 145 |
146 | 147 |
148 | 149 | 150 |
151 |
152 |
156 | 157 |
158 | 159 |
160 |

© Copyright 2023, JF.

161 |
162 | 163 | Built with Sphinx using a 164 | theme 165 | provided by Read the Docs. 166 | 167 | 168 |
169 |
170 |
171 |
172 |
173 | 178 | 179 | 180 | -------------------------------------------------------------------------------- /docs/_build/html/LesionSegmenter.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | LesionSegmenter — PVBM 3.0.0.0 documentation 8 | 9 | 10 | 11 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 |
28 | 66 | 67 |
71 | 72 |
73 |
74 |
75 | 82 |
83 |
84 |
85 |
86 | 87 |
88 |

LesionSegmenter

89 |
90 |
91 | class PVBM.LesionSegmenter.LesionSegmenter(model_path)[source]
92 |

A class that performs lesion segmentation.

93 |
94 |
95 |
96 | __init__(model_path)[source]
97 |

Initialize the LesionSegmenter class with image size and model path. 98 | Download the model from: https://drive.google.com/file/d/1pOhp506d0jiUzOWJBLoH6yXagkMLb8-t/view?usp=sharing

99 |
100 | 101 |
102 |
103 | segment(image_path)[source]
104 |

Perform the lesion segmentation given an image path.

105 |
106 |
Parameters:
107 |

image_path (str) – Path to the image.

108 |
109 |
Returns:
110 |

A PIL Image containing the Lesion segmentation.

111 |
112 |
Return type:
113 |

PIL.Image

114 |
115 |
116 |
117 | 118 |
119 |
120 | 121 |
122 | 123 | 124 |
125 |
126 |
130 | 131 |
132 | 133 |
134 |

© Copyright 2023, JF.

135 |
136 | 137 | Built with Sphinx using a 138 | theme 139 | provided by Read the Docs. 140 | 141 | 142 |
143 |
144 |
145 |
146 |
147 | 152 | 153 | 154 | -------------------------------------------------------------------------------- /docs/_build/html/_images/pipeline.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aim-lab/PVBM/71c9077164098f85c928a09be719468e0a5896e4/docs/_build/html/_images/pipeline.png -------------------------------------------------------------------------------- /docs/_build/html/_images/pvbmtutorial_14_0.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aim-lab/PVBM/71c9077164098f85c928a09be719468e0a5896e4/docs/_build/html/_images/pvbmtutorial_14_0.png -------------------------------------------------------------------------------- /docs/_build/html/_images/pvbmtutorial_15_0.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aim-lab/PVBM/71c9077164098f85c928a09be719468e0a5896e4/docs/_build/html/_images/pvbmtutorial_15_0.png -------------------------------------------------------------------------------- /docs/_build/html/_images/pvbmtutorial_17_0.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aim-lab/PVBM/71c9077164098f85c928a09be719468e0a5896e4/docs/_build/html/_images/pvbmtutorial_17_0.png -------------------------------------------------------------------------------- /docs/_build/html/_images/pvbmtutorial_21_0.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aim-lab/PVBM/71c9077164098f85c928a09be719468e0a5896e4/docs/_build/html/_images/pvbmtutorial_21_0.png -------------------------------------------------------------------------------- /docs/_build/html/_images/pvbmtutorial_21_1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aim-lab/PVBM/71c9077164098f85c928a09be719468e0a5896e4/docs/_build/html/_images/pvbmtutorial_21_1.png -------------------------------------------------------------------------------- /docs/_build/html/_images/pvbmtutorial_25_0.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aim-lab/PVBM/71c9077164098f85c928a09be719468e0a5896e4/docs/_build/html/_images/pvbmtutorial_25_0.png -------------------------------------------------------------------------------- /docs/_build/html/_images/pvbmtutorial_26_0.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aim-lab/PVBM/71c9077164098f85c928a09be719468e0a5896e4/docs/_build/html/_images/pvbmtutorial_26_0.png -------------------------------------------------------------------------------- /docs/_build/html/_images/pvbmtutorial_30_0.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aim-lab/PVBM/71c9077164098f85c928a09be719468e0a5896e4/docs/_build/html/_images/pvbmtutorial_30_0.png -------------------------------------------------------------------------------- /docs/_build/html/_images/pvbmtutorial_31_0.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aim-lab/PVBM/71c9077164098f85c928a09be719468e0a5896e4/docs/_build/html/_images/pvbmtutorial_31_0.png -------------------------------------------------------------------------------- /docs/_build/html/_images/pvbmtutorial_36_0.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aim-lab/PVBM/71c9077164098f85c928a09be719468e0a5896e4/docs/_build/html/_images/pvbmtutorial_36_0.png -------------------------------------------------------------------------------- /docs/_build/html/_images/pvbmtutorial_38_0.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aim-lab/PVBM/71c9077164098f85c928a09be719468e0a5896e4/docs/_build/html/_images/pvbmtutorial_38_0.png -------------------------------------------------------------------------------- /docs/_build/html/_images/pvbmtutorial_39_0.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aim-lab/PVBM/71c9077164098f85c928a09be719468e0a5896e4/docs/_build/html/_images/pvbmtutorial_39_0.png -------------------------------------------------------------------------------- /docs/_build/html/_images/pvbmtutorial_40_0.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aim-lab/PVBM/71c9077164098f85c928a09be719468e0a5896e4/docs/_build/html/_images/pvbmtutorial_40_0.png -------------------------------------------------------------------------------- /docs/_build/html/_images/pvbmtutorial_42_0.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aim-lab/PVBM/71c9077164098f85c928a09be719468e0a5896e4/docs/_build/html/_images/pvbmtutorial_42_0.png -------------------------------------------------------------------------------- /docs/_build/html/_images/pvbmtutorial_50_0.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aim-lab/PVBM/71c9077164098f85c928a09be719468e0a5896e4/docs/_build/html/_images/pvbmtutorial_50_0.png -------------------------------------------------------------------------------- /docs/_build/html/_images/pvbmtutorial_55_0.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aim-lab/PVBM/71c9077164098f85c928a09be719468e0a5896e4/docs/_build/html/_images/pvbmtutorial_55_0.png -------------------------------------------------------------------------------- /docs/_build/html/_modules/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Overview: module code — PVBM 3.0.0.0 documentation 7 | 8 | 9 | 10 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 |
25 | 56 | 57 |
61 | 62 |
63 |
64 |
65 |
    66 |
  • 67 | 68 |
  • 69 |
  • 70 |
71 |
72 |
73 |
74 |
75 | 76 |

All modules for which code is available

77 | 85 | 86 |
87 |
88 |
89 | 90 |
91 | 92 |
93 |

© Copyright 2023, JF.

94 |
95 | 96 | Built with Sphinx using a 97 | theme 98 | provided by Read the Docs. 99 | 100 | 101 |
102 |
103 |
104 |
105 |
106 | 111 | 112 | 113 | -------------------------------------------------------------------------------- /docs/_build/html/_sources/CentralRetinalAnalysis.rst.txt: -------------------------------------------------------------------------------- 1 | CentralRetinalAnalysis 2 | =============== 3 | 4 | .. automodule:: PVBM.CentralRetinalAnalysis 5 | 6 | .. autoclass:: CREVBMs 7 | :members: None 8 | 9 | .. automethod:: compute_central_retinal_equivalents 10 | .. automethod:: apply_roi 11 | 12 | -------------------------------------------------------------------------------- /docs/_build/html/_sources/Datasets.rst.txt: -------------------------------------------------------------------------------- 1 | Datasets 2 | =================== 3 | 4 | .. automodule:: PVBM.Datasets 5 | 6 | .. autoclass:: PVBMDataDownloader 7 | :members: None 8 | 9 | .. automethod:: download_dataset 10 | -------------------------------------------------------------------------------- /docs/_build/html/_sources/DiscSegmenter.rst.txt: -------------------------------------------------------------------------------- 1 | DiscSegmenter 2 | =================== 3 | 4 | .. automodule:: PVBM.DiscSegmenter 5 | 6 | .. autoclass:: DiscSegmenter 7 | :members: None 8 | 9 | .. automethod:: segment 10 | .. automethod:: post_processing 11 | -------------------------------------------------------------------------------- /docs/_build/html/_sources/FractalAnalysis.rst.txt: -------------------------------------------------------------------------------- 1 | FractalAnalysis 2 | =============== 3 | 4 | .. automodule:: PVBM.FractalAnalysis 5 | 6 | .. autoclass:: MultifractalVBMs 7 | :members: None 8 | 9 | .. automethod:: compute_multifractals 10 | -------------------------------------------------------------------------------- /docs/_build/html/_sources/GeometricalAnalysis.rst.txt: -------------------------------------------------------------------------------- 1 | GeometricalAnalysis 2 | =================== 3 | 4 | .. automodule:: PVBM.GeometricalAnalysis 5 | :members: 6 | -------------------------------------------------------------------------------- /docs/_build/html/_sources/GeometryAnalysis.rst.txt: -------------------------------------------------------------------------------- 1 | GeometryAnalysis 2 | =================== 3 | 4 | .. automodule:: PVBM.GeometryAnalysis 5 | 6 | .. autoclass:: GeometricalVBMs 7 | :members: None 8 | 9 | .. automethod:: compute_geomVBMs 10 | .. automethod:: apply_roi 11 | -------------------------------------------------------------------------------- /docs/_build/html/_sources/LesionSegmenter.rst.txt: -------------------------------------------------------------------------------- 1 | LesionSegmenter 2 | =================== 3 | 4 | .. automodule:: PVBM.LesionSegmenter 5 | 6 | .. autoclass:: LesionSegmenter 7 | :members: None 8 | 9 | .. automethod:: __init__ 10 | 11 | .. automethod:: segment 12 | -------------------------------------------------------------------------------- /docs/_build/html/_static/css/badge_only.css: -------------------------------------------------------------------------------- 1 | .clearfix{*zoom:1}.clearfix:after,.clearfix:before{display:table;content:""}.clearfix:after{clear:both}@font-face{font-family:FontAwesome;font-style:normal;font-weight:400;src:url(fonts/fontawesome-webfont.eot?674f50d287a8c48dc19ba404d20fe713?#iefix) format("embedded-opentype"),url(fonts/fontawesome-webfont.woff2?af7ae505a9eed503f8b8e6982036873e) format("woff2"),url(fonts/fontawesome-webfont.woff?fee66e712a8a08eef5805a46892932ad) format("woff"),url(fonts/fontawesome-webfont.ttf?b06871f281fee6b241d60582ae9369b9) format("truetype"),url(fonts/fontawesome-webfont.svg?912ec66d7572ff821749319396470bde#FontAwesome) format("svg")}.fa:before{font-family:FontAwesome;font-style:normal;font-weight:400;line-height:1}.fa:before,a .fa{text-decoration:inherit}.fa:before,a .fa,li .fa{display:inline-block}li .fa-large:before{width:1.875em}ul.fas{list-style-type:none;margin-left:2em;text-indent:-.8em}ul.fas li .fa{width:.8em}ul.fas li .fa-large:before{vertical-align:baseline}.fa-book:before,.icon-book:before{content:"\f02d"}.fa-caret-down:before,.icon-caret-down:before{content:"\f0d7"}.fa-caret-up:before,.icon-caret-up:before{content:"\f0d8"}.fa-caret-left:before,.icon-caret-left:before{content:"\f0d9"}.fa-caret-right:before,.icon-caret-right:before{content:"\f0da"}.rst-versions{position:fixed;bottom:0;left:0;width:300px;color:#fcfcfc;background:#1f1d1d;font-family:Lato,proxima-nova,Helvetica Neue,Arial,sans-serif;z-index:400}.rst-versions a{color:#2980b9;text-decoration:none}.rst-versions .rst-badge-small{display:none}.rst-versions .rst-current-version{padding:12px;background-color:#272525;display:block;text-align:right;font-size:90%;cursor:pointer;color:#27ae60}.rst-versions .rst-current-version:after{clear:both;content:"";display:block}.rst-versions .rst-current-version .fa{color:#fcfcfc}.rst-versions .rst-current-version .fa-book,.rst-versions .rst-current-version .icon-book{float:left}.rst-versions .rst-current-version.rst-out-of-date{background-color:#e74c3c;color:#fff}.rst-versions .rst-current-version.rst-active-old-version{background-color:#f1c40f;color:#000}.rst-versions.shift-up{height:auto;max-height:100%;overflow-y:scroll}.rst-versions.shift-up .rst-other-versions{display:block}.rst-versions .rst-other-versions{font-size:90%;padding:12px;color:grey;display:none}.rst-versions .rst-other-versions hr{display:block;height:1px;border:0;margin:20px 0;padding:0;border-top:1px solid #413d3d}.rst-versions .rst-other-versions dd{display:inline-block;margin:0}.rst-versions .rst-other-versions dd a{display:inline-block;padding:6px;color:#fcfcfc}.rst-versions.rst-badge{width:auto;bottom:20px;right:20px;left:auto;border:none;max-width:300px;max-height:90%}.rst-versions.rst-badge .fa-book,.rst-versions.rst-badge .icon-book{float:none;line-height:30px}.rst-versions.rst-badge.shift-up .rst-current-version{text-align:right}.rst-versions.rst-badge.shift-up .rst-current-version .fa-book,.rst-versions.rst-badge.shift-up .rst-current-version .icon-book{float:left}.rst-versions.rst-badge>.rst-current-version{width:auto;height:30px;line-height:30px;padding:0 6px;display:block;text-align:center}@media screen and (max-width:768px){.rst-versions{width:85%;display:none}.rst-versions.shift{display:block}} -------------------------------------------------------------------------------- /docs/_build/html/_static/css/fonts/Roboto-Slab-Bold.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aim-lab/PVBM/71c9077164098f85c928a09be719468e0a5896e4/docs/_build/html/_static/css/fonts/Roboto-Slab-Bold.woff -------------------------------------------------------------------------------- /docs/_build/html/_static/css/fonts/Roboto-Slab-Bold.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aim-lab/PVBM/71c9077164098f85c928a09be719468e0a5896e4/docs/_build/html/_static/css/fonts/Roboto-Slab-Bold.woff2 -------------------------------------------------------------------------------- /docs/_build/html/_static/css/fonts/Roboto-Slab-Regular.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aim-lab/PVBM/71c9077164098f85c928a09be719468e0a5896e4/docs/_build/html/_static/css/fonts/Roboto-Slab-Regular.woff -------------------------------------------------------------------------------- /docs/_build/html/_static/css/fonts/Roboto-Slab-Regular.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aim-lab/PVBM/71c9077164098f85c928a09be719468e0a5896e4/docs/_build/html/_static/css/fonts/Roboto-Slab-Regular.woff2 -------------------------------------------------------------------------------- /docs/_build/html/_static/css/fonts/fontawesome-webfont.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aim-lab/PVBM/71c9077164098f85c928a09be719468e0a5896e4/docs/_build/html/_static/css/fonts/fontawesome-webfont.eot -------------------------------------------------------------------------------- /docs/_build/html/_static/css/fonts/fontawesome-webfont.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aim-lab/PVBM/71c9077164098f85c928a09be719468e0a5896e4/docs/_build/html/_static/css/fonts/fontawesome-webfont.ttf -------------------------------------------------------------------------------- /docs/_build/html/_static/css/fonts/fontawesome-webfont.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aim-lab/PVBM/71c9077164098f85c928a09be719468e0a5896e4/docs/_build/html/_static/css/fonts/fontawesome-webfont.woff -------------------------------------------------------------------------------- /docs/_build/html/_static/css/fonts/fontawesome-webfont.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aim-lab/PVBM/71c9077164098f85c928a09be719468e0a5896e4/docs/_build/html/_static/css/fonts/fontawesome-webfont.woff2 -------------------------------------------------------------------------------- /docs/_build/html/_static/css/fonts/lato-bold-italic.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aim-lab/PVBM/71c9077164098f85c928a09be719468e0a5896e4/docs/_build/html/_static/css/fonts/lato-bold-italic.woff -------------------------------------------------------------------------------- /docs/_build/html/_static/css/fonts/lato-bold-italic.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aim-lab/PVBM/71c9077164098f85c928a09be719468e0a5896e4/docs/_build/html/_static/css/fonts/lato-bold-italic.woff2 -------------------------------------------------------------------------------- /docs/_build/html/_static/css/fonts/lato-bold.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aim-lab/PVBM/71c9077164098f85c928a09be719468e0a5896e4/docs/_build/html/_static/css/fonts/lato-bold.woff -------------------------------------------------------------------------------- /docs/_build/html/_static/css/fonts/lato-bold.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aim-lab/PVBM/71c9077164098f85c928a09be719468e0a5896e4/docs/_build/html/_static/css/fonts/lato-bold.woff2 -------------------------------------------------------------------------------- /docs/_build/html/_static/css/fonts/lato-normal-italic.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aim-lab/PVBM/71c9077164098f85c928a09be719468e0a5896e4/docs/_build/html/_static/css/fonts/lato-normal-italic.woff -------------------------------------------------------------------------------- /docs/_build/html/_static/css/fonts/lato-normal-italic.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aim-lab/PVBM/71c9077164098f85c928a09be719468e0a5896e4/docs/_build/html/_static/css/fonts/lato-normal-italic.woff2 -------------------------------------------------------------------------------- /docs/_build/html/_static/css/fonts/lato-normal.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aim-lab/PVBM/71c9077164098f85c928a09be719468e0a5896e4/docs/_build/html/_static/css/fonts/lato-normal.woff -------------------------------------------------------------------------------- /docs/_build/html/_static/css/fonts/lato-normal.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aim-lab/PVBM/71c9077164098f85c928a09be719468e0a5896e4/docs/_build/html/_static/css/fonts/lato-normal.woff2 -------------------------------------------------------------------------------- /docs/_build/html/_static/doctools.js: -------------------------------------------------------------------------------- 1 | /* 2 | * doctools.js 3 | * ~~~~~~~~~~~ 4 | * 5 | * Base JavaScript utilities for all Sphinx HTML documentation. 6 | * 7 | * :copyright: Copyright 2007-2023 by the Sphinx team, see AUTHORS. 8 | * :license: BSD, see LICENSE for details. 9 | * 10 | */ 11 | "use strict"; 12 | 13 | const BLACKLISTED_KEY_CONTROL_ELEMENTS = new Set([ 14 | "TEXTAREA", 15 | "INPUT", 16 | "SELECT", 17 | "BUTTON", 18 | ]); 19 | 20 | const _ready = (callback) => { 21 | if (document.readyState !== "loading") { 22 | callback(); 23 | } else { 24 | document.addEventListener("DOMContentLoaded", callback); 25 | } 26 | }; 27 | 28 | /** 29 | * Small JavaScript module for the documentation. 30 | */ 31 | const Documentation = { 32 | init: () => { 33 | Documentation.initDomainIndexTable(); 34 | Documentation.initOnKeyListeners(); 35 | }, 36 | 37 | /** 38 | * i18n support 39 | */ 40 | TRANSLATIONS: {}, 41 | PLURAL_EXPR: (n) => (n === 1 ? 0 : 1), 42 | LOCALE: "unknown", 43 | 44 | // gettext and ngettext don't access this so that the functions 45 | // can safely bound to a different name (_ = Documentation.gettext) 46 | gettext: (string) => { 47 | const translated = Documentation.TRANSLATIONS[string]; 48 | switch (typeof translated) { 49 | case "undefined": 50 | return string; // no translation 51 | case "string": 52 | return translated; // translation exists 53 | default: 54 | return translated[0]; // (singular, plural) translation tuple exists 55 | } 56 | }, 57 | 58 | ngettext: (singular, plural, n) => { 59 | const translated = Documentation.TRANSLATIONS[singular]; 60 | if (typeof translated !== "undefined") 61 | return translated[Documentation.PLURAL_EXPR(n)]; 62 | return n === 1 ? singular : plural; 63 | }, 64 | 65 | addTranslations: (catalog) => { 66 | Object.assign(Documentation.TRANSLATIONS, catalog.messages); 67 | Documentation.PLURAL_EXPR = new Function( 68 | "n", 69 | `return (${catalog.plural_expr})` 70 | ); 71 | Documentation.LOCALE = catalog.locale; 72 | }, 73 | 74 | /** 75 | * helper function to focus on search bar 76 | */ 77 | focusSearchBar: () => { 78 | document.querySelectorAll("input[name=q]")[0]?.focus(); 79 | }, 80 | 81 | /** 82 | * Initialise the domain index toggle buttons 83 | */ 84 | initDomainIndexTable: () => { 85 | const toggler = (el) => { 86 | const idNumber = el.id.substr(7); 87 | const toggledRows = document.querySelectorAll(`tr.cg-${idNumber}`); 88 | if (el.src.substr(-9) === "minus.png") { 89 | el.src = `${el.src.substr(0, el.src.length - 9)}plus.png`; 90 | toggledRows.forEach((el) => (el.style.display = "none")); 91 | } else { 92 | el.src = `${el.src.substr(0, el.src.length - 8)}minus.png`; 93 | toggledRows.forEach((el) => (el.style.display = "")); 94 | } 95 | }; 96 | 97 | const togglerElements = document.querySelectorAll("img.toggler"); 98 | togglerElements.forEach((el) => 99 | el.addEventListener("click", (event) => toggler(event.currentTarget)) 100 | ); 101 | togglerElements.forEach((el) => (el.style.display = "")); 102 | if (DOCUMENTATION_OPTIONS.COLLAPSE_INDEX) togglerElements.forEach(toggler); 103 | }, 104 | 105 | initOnKeyListeners: () => { 106 | // only install a listener if it is really needed 107 | if ( 108 | !DOCUMENTATION_OPTIONS.NAVIGATION_WITH_KEYS && 109 | !DOCUMENTATION_OPTIONS.ENABLE_SEARCH_SHORTCUTS 110 | ) 111 | return; 112 | 113 | document.addEventListener("keydown", (event) => { 114 | // bail for input elements 115 | if (BLACKLISTED_KEY_CONTROL_ELEMENTS.has(document.activeElement.tagName)) return; 116 | // bail with special keys 117 | if (event.altKey || event.ctrlKey || event.metaKey) return; 118 | 119 | if (!event.shiftKey) { 120 | switch (event.key) { 121 | case "ArrowLeft": 122 | if (!DOCUMENTATION_OPTIONS.NAVIGATION_WITH_KEYS) break; 123 | 124 | const prevLink = document.querySelector('link[rel="prev"]'); 125 | if (prevLink && prevLink.href) { 126 | window.location.href = prevLink.href; 127 | event.preventDefault(); 128 | } 129 | break; 130 | case "ArrowRight": 131 | if (!DOCUMENTATION_OPTIONS.NAVIGATION_WITH_KEYS) break; 132 | 133 | const nextLink = document.querySelector('link[rel="next"]'); 134 | if (nextLink && nextLink.href) { 135 | window.location.href = nextLink.href; 136 | event.preventDefault(); 137 | } 138 | break; 139 | } 140 | } 141 | 142 | // some keyboard layouts may need Shift to get / 143 | switch (event.key) { 144 | case "/": 145 | if (!DOCUMENTATION_OPTIONS.ENABLE_SEARCH_SHORTCUTS) break; 146 | Documentation.focusSearchBar(); 147 | event.preventDefault(); 148 | } 149 | }); 150 | }, 151 | }; 152 | 153 | // quick alias for translations 154 | const _ = Documentation.gettext; 155 | 156 | _ready(Documentation.init); 157 | -------------------------------------------------------------------------------- /docs/_build/html/_static/documentation_options.js: -------------------------------------------------------------------------------- 1 | var DOCUMENTATION_OPTIONS = { 2 | URL_ROOT: document.getElementById("documentation_options").getAttribute('data-url_root'), 3 | VERSION: '3.0.0.0', 4 | LANGUAGE: 'en', 5 | COLLAPSE_INDEX: false, 6 | BUILDER: 'html', 7 | FILE_SUFFIX: '.html', 8 | LINK_SUFFIX: '.html', 9 | HAS_SOURCE: true, 10 | SOURCELINK_SUFFIX: '.txt', 11 | NAVIGATION_WITH_KEYS: false, 12 | SHOW_SEARCH_SUMMARY: true, 13 | ENABLE_SEARCH_SHORTCUTS: true, 14 | }; -------------------------------------------------------------------------------- /docs/_build/html/_static/file.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aim-lab/PVBM/71c9077164098f85c928a09be719468e0a5896e4/docs/_build/html/_static/file.png -------------------------------------------------------------------------------- /docs/_build/html/_static/js/badge_only.js: -------------------------------------------------------------------------------- 1 | !function(e){var t={};function r(n){if(t[n])return t[n].exports;var o=t[n]={i:n,l:!1,exports:{}};return e[n].call(o.exports,o,o.exports,r),o.l=!0,o.exports}r.m=e,r.c=t,r.d=function(e,t,n){r.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:n})},r.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},r.t=function(e,t){if(1&t&&(e=r(e)),8&t)return e;if(4&t&&"object"==typeof e&&e&&e.__esModule)return e;var n=Object.create(null);if(r.r(n),Object.defineProperty(n,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var o in e)r.d(n,o,function(t){return e[t]}.bind(null,o));return n},r.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return r.d(t,"a",t),t},r.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},r.p="",r(r.s=4)}({4:function(e,t,r){}}); -------------------------------------------------------------------------------- /docs/_build/html/_static/js/html5shiv-printshiv.min.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @preserve HTML5 Shiv 3.7.3-pre | @afarkas @jdalton @jon_neal @rem | MIT/GPL2 Licensed 3 | */ 4 | !function(a,b){function c(a,b){var c=a.createElement("p"),d=a.getElementsByTagName("head")[0]||a.documentElement;return c.innerHTML="x",d.insertBefore(c.lastChild,d.firstChild)}function d(){var a=y.elements;return"string"==typeof a?a.split(" "):a}function e(a,b){var c=y.elements;"string"!=typeof c&&(c=c.join(" ")),"string"!=typeof a&&(a=a.join(" ")),y.elements=c+" "+a,j(b)}function f(a){var b=x[a[v]];return b||(b={},w++,a[v]=w,x[w]=b),b}function g(a,c,d){if(c||(c=b),q)return c.createElement(a);d||(d=f(c));var e;return e=d.cache[a]?d.cache[a].cloneNode():u.test(a)?(d.cache[a]=d.createElem(a)).cloneNode():d.createElem(a),!e.canHaveChildren||t.test(a)||e.tagUrn?e:d.frag.appendChild(e)}function h(a,c){if(a||(a=b),q)return a.createDocumentFragment();c=c||f(a);for(var e=c.frag.cloneNode(),g=0,h=d(),i=h.length;i>g;g++)e.createElement(h[g]);return e}function i(a,b){b.cache||(b.cache={},b.createElem=a.createElement,b.createFrag=a.createDocumentFragment,b.frag=b.createFrag()),a.createElement=function(c){return y.shivMethods?g(c,a,b):b.createElem(c)},a.createDocumentFragment=Function("h,f","return function(){var n=f.cloneNode(),c=n.createElement;h.shivMethods&&("+d().join().replace(/[\w\-:]+/g,function(a){return b.createElem(a),b.frag.createElement(a),'c("'+a+'")'})+");return n}")(y,b.frag)}function j(a){a||(a=b);var d=f(a);return!y.shivCSS||p||d.hasCSS||(d.hasCSS=!!c(a,"article,aside,dialog,figcaption,figure,footer,header,hgroup,main,nav,section{display:block}mark{background:#FF0;color:#000}template{display:none}")),q||i(a,d),a}function k(a){for(var b,c=a.getElementsByTagName("*"),e=c.length,f=RegExp("^(?:"+d().join("|")+")$","i"),g=[];e--;)b=c[e],f.test(b.nodeName)&&g.push(b.applyElement(l(b)));return g}function l(a){for(var b,c=a.attributes,d=c.length,e=a.ownerDocument.createElement(A+":"+a.nodeName);d--;)b=c[d],b.specified&&e.setAttribute(b.nodeName,b.nodeValue);return e.style.cssText=a.style.cssText,e}function m(a){for(var b,c=a.split("{"),e=c.length,f=RegExp("(^|[\\s,>+~])("+d().join("|")+")(?=[[\\s,>+~#.:]|$)","gi"),g="$1"+A+"\\:$2";e--;)b=c[e]=c[e].split("}"),b[b.length-1]=b[b.length-1].replace(f,g),c[e]=b.join("}");return c.join("{")}function n(a){for(var b=a.length;b--;)a[b].removeNode()}function o(a){function b(){clearTimeout(g._removeSheetTimer),d&&d.removeNode(!0),d=null}var d,e,g=f(a),h=a.namespaces,i=a.parentWindow;return!B||a.printShived?a:("undefined"==typeof h[A]&&h.add(A),i.attachEvent("onbeforeprint",function(){b();for(var f,g,h,i=a.styleSheets,j=[],l=i.length,n=Array(l);l--;)n[l]=i[l];for(;h=n.pop();)if(!h.disabled&&z.test(h.media)){try{f=h.imports,g=f.length}catch(o){g=0}for(l=0;g>l;l++)n.push(f[l]);try{j.push(h.cssText)}catch(o){}}j=m(j.reverse().join("")),e=k(a),d=c(a,j)}),i.attachEvent("onafterprint",function(){n(e),clearTimeout(g._removeSheetTimer),g._removeSheetTimer=setTimeout(b,500)}),a.printShived=!0,a)}var p,q,r="3.7.3",s=a.html5||{},t=/^<|^(?:button|map|select|textarea|object|iframe|option|optgroup)$/i,u=/^(?:a|b|code|div|fieldset|h1|h2|h3|h4|h5|h6|i|label|li|ol|p|q|span|strong|style|table|tbody|td|th|tr|ul)$/i,v="_html5shiv",w=0,x={};!function(){try{var a=b.createElement("a");a.innerHTML="",p="hidden"in a,q=1==a.childNodes.length||function(){b.createElement("a");var a=b.createDocumentFragment();return"undefined"==typeof a.cloneNode||"undefined"==typeof a.createDocumentFragment||"undefined"==typeof a.createElement}()}catch(c){p=!0,q=!0}}();var y={elements:s.elements||"abbr article aside audio bdi canvas data datalist details dialog figcaption figure footer header hgroup main mark meter nav output picture progress section summary template time video",version:r,shivCSS:s.shivCSS!==!1,supportsUnknownElements:q,shivMethods:s.shivMethods!==!1,type:"default",shivDocument:j,createElement:g,createDocumentFragment:h,addElements:e};a.html5=y,j(b);var z=/^$|\b(?:all|print)\b/,A="html5shiv",B=!q&&function(){var c=b.documentElement;return!("undefined"==typeof b.namespaces||"undefined"==typeof b.parentWindow||"undefined"==typeof c.applyElement||"undefined"==typeof c.removeNode||"undefined"==typeof a.attachEvent)}();y.type+=" print",y.shivPrint=o,o(b),"object"==typeof module&&module.exports&&(module.exports=y)}("undefined"!=typeof window?window:this,document); -------------------------------------------------------------------------------- /docs/_build/html/_static/js/html5shiv.min.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @preserve HTML5 Shiv 3.7.3 | @afarkas @jdalton @jon_neal @rem | MIT/GPL2 Licensed 3 | */ 4 | !function(a,b){function c(a,b){var c=a.createElement("p"),d=a.getElementsByTagName("head")[0]||a.documentElement;return c.innerHTML="x",d.insertBefore(c.lastChild,d.firstChild)}function d(){var a=t.elements;return"string"==typeof a?a.split(" "):a}function e(a,b){var c=t.elements;"string"!=typeof c&&(c=c.join(" ")),"string"!=typeof a&&(a=a.join(" ")),t.elements=c+" "+a,j(b)}function f(a){var b=s[a[q]];return b||(b={},r++,a[q]=r,s[r]=b),b}function g(a,c,d){if(c||(c=b),l)return c.createElement(a);d||(d=f(c));var e;return e=d.cache[a]?d.cache[a].cloneNode():p.test(a)?(d.cache[a]=d.createElem(a)).cloneNode():d.createElem(a),!e.canHaveChildren||o.test(a)||e.tagUrn?e:d.frag.appendChild(e)}function h(a,c){if(a||(a=b),l)return a.createDocumentFragment();c=c||f(a);for(var e=c.frag.cloneNode(),g=0,h=d(),i=h.length;i>g;g++)e.createElement(h[g]);return e}function i(a,b){b.cache||(b.cache={},b.createElem=a.createElement,b.createFrag=a.createDocumentFragment,b.frag=b.createFrag()),a.createElement=function(c){return t.shivMethods?g(c,a,b):b.createElem(c)},a.createDocumentFragment=Function("h,f","return function(){var n=f.cloneNode(),c=n.createElement;h.shivMethods&&("+d().join().replace(/[\w\-:]+/g,function(a){return b.createElem(a),b.frag.createElement(a),'c("'+a+'")'})+");return n}")(t,b.frag)}function j(a){a||(a=b);var d=f(a);return!t.shivCSS||k||d.hasCSS||(d.hasCSS=!!c(a,"article,aside,dialog,figcaption,figure,footer,header,hgroup,main,nav,section{display:block}mark{background:#FF0;color:#000}template{display:none}")),l||i(a,d),a}var k,l,m="3.7.3-pre",n=a.html5||{},o=/^<|^(?:button|map|select|textarea|object|iframe|option|optgroup)$/i,p=/^(?:a|b|code|div|fieldset|h1|h2|h3|h4|h5|h6|i|label|li|ol|p|q|span|strong|style|table|tbody|td|th|tr|ul)$/i,q="_html5shiv",r=0,s={};!function(){try{var a=b.createElement("a");a.innerHTML="",k="hidden"in a,l=1==a.childNodes.length||function(){b.createElement("a");var a=b.createDocumentFragment();return"undefined"==typeof a.cloneNode||"undefined"==typeof a.createDocumentFragment||"undefined"==typeof a.createElement}()}catch(c){k=!0,l=!0}}();var t={elements:n.elements||"abbr article aside audio bdi canvas data datalist details dialog figcaption figure footer header hgroup main mark meter nav output picture progress section summary template time video",version:m,shivCSS:n.shivCSS!==!1,supportsUnknownElements:l,shivMethods:n.shivMethods!==!1,type:"default",shivDocument:j,createElement:g,createDocumentFragment:h,addElements:e};a.html5=t,j(b),"object"==typeof module&&module.exports&&(module.exports=t)}("undefined"!=typeof window?window:this,document); -------------------------------------------------------------------------------- /docs/_build/html/_static/js/theme.js: -------------------------------------------------------------------------------- 1 | !function(n){var e={};function t(i){if(e[i])return e[i].exports;var o=e[i]={i:i,l:!1,exports:{}};return n[i].call(o.exports,o,o.exports,t),o.l=!0,o.exports}t.m=n,t.c=e,t.d=function(n,e,i){t.o(n,e)||Object.defineProperty(n,e,{enumerable:!0,get:i})},t.r=function(n){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(n,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(n,"__esModule",{value:!0})},t.t=function(n,e){if(1&e&&(n=t(n)),8&e)return n;if(4&e&&"object"==typeof n&&n&&n.__esModule)return n;var i=Object.create(null);if(t.r(i),Object.defineProperty(i,"default",{enumerable:!0,value:n}),2&e&&"string"!=typeof n)for(var o in n)t.d(i,o,function(e){return n[e]}.bind(null,o));return i},t.n=function(n){var e=n&&n.__esModule?function(){return n.default}:function(){return n};return t.d(e,"a",e),e},t.o=function(n,e){return Object.prototype.hasOwnProperty.call(n,e)},t.p="",t(t.s=0)}([function(n,e,t){t(1),n.exports=t(3)},function(n,e,t){(function(){var e="undefined"!=typeof window?window.jQuery:t(2);n.exports.ThemeNav={navBar:null,win:null,winScroll:!1,winResize:!1,linkScroll:!1,winPosition:0,winHeight:null,docHeight:null,isRunning:!1,enable:function(n){var t=this;void 0===n&&(n=!0),t.isRunning||(t.isRunning=!0,e((function(e){t.init(e),t.reset(),t.win.on("hashchange",t.reset),n&&t.win.on("scroll",(function(){t.linkScroll||t.winScroll||(t.winScroll=!0,requestAnimationFrame((function(){t.onScroll()})))})),t.win.on("resize",(function(){t.winResize||(t.winResize=!0,requestAnimationFrame((function(){t.onResize()})))})),t.onResize()})))},enableSticky:function(){this.enable(!0)},init:function(n){n(document);var e=this;this.navBar=n("div.wy-side-scroll:first"),this.win=n(window),n(document).on("click","[data-toggle='wy-nav-top']",(function(){n("[data-toggle='wy-nav-shift']").toggleClass("shift"),n("[data-toggle='rst-versions']").toggleClass("shift")})).on("click",".wy-menu-vertical .current ul li a",(function(){var t=n(this);n("[data-toggle='wy-nav-shift']").removeClass("shift"),n("[data-toggle='rst-versions']").toggleClass("shift"),e.toggleCurrent(t),e.hashChange()})).on("click","[data-toggle='rst-current-version']",(function(){n("[data-toggle='rst-versions']").toggleClass("shift-up")})),n("table.docutils:not(.field-list,.footnote,.citation)").wrap("
"),n("table.docutils.footnote").wrap("
"),n("table.docutils.citation").wrap("
"),n(".wy-menu-vertical ul").not(".simple").siblings("a").each((function(){var t=n(this);expand=n(''),expand.on("click",(function(n){return e.toggleCurrent(t),n.stopPropagation(),!1})),t.prepend(expand)}))},reset:function(){var n=encodeURI(window.location.hash)||"#";try{var e=$(".wy-menu-vertical"),t=e.find('[href="'+n+'"]');if(0===t.length){var i=$('.document [id="'+n.substring(1)+'"]').closest("div.section");0===(t=e.find('[href="#'+i.attr("id")+'"]')).length&&(t=e.find('[href="#"]'))}if(t.length>0){$(".wy-menu-vertical .current").removeClass("current").attr("aria-expanded","false"),t.addClass("current").attr("aria-expanded","true"),t.closest("li.toctree-l1").parent().addClass("current").attr("aria-expanded","true");for(let n=1;n<=10;n++)t.closest("li.toctree-l"+n).addClass("current").attr("aria-expanded","true");t[0].scrollIntoView()}}catch(n){console.log("Error expanding nav for anchor",n)}},onScroll:function(){this.winScroll=!1;var n=this.win.scrollTop(),e=n+this.winHeight,t=this.navBar.scrollTop()+(n-this.winPosition);n<0||e>this.docHeight||(this.navBar.scrollTop(t),this.winPosition=n)},onResize:function(){this.winResize=!1,this.winHeight=this.win.height(),this.docHeight=$(document).height()},hashChange:function(){this.linkScroll=!0,this.win.one("hashchange",(function(){this.linkScroll=!1}))},toggleCurrent:function(n){var e=n.closest("li");e.siblings("li.current").removeClass("current").attr("aria-expanded","false"),e.siblings().find("li.current").removeClass("current").attr("aria-expanded","false");var t=e.find("> ul li");t.length&&(t.removeClass("current").attr("aria-expanded","false"),e.toggleClass("current").attr("aria-expanded",(function(n,e){return"true"==e?"false":"true"})))}},"undefined"!=typeof window&&(window.SphinxRtdTheme={Navigation:n.exports.ThemeNav,StickyNav:n.exports.ThemeNav}),function(){for(var n=0,e=["ms","moz","webkit","o"],t=0;t0 63 | var meq1 = "^(" + C + ")?" + V + C + "(" + V + ")?$"; // [C]VC[V] is m=1 64 | var mgr1 = "^(" + C + ")?" + V + C + V + C; // [C]VCVC... is m>1 65 | var s_v = "^(" + C + ")?" + v; // vowel in stem 66 | 67 | this.stemWord = function (w) { 68 | var stem; 69 | var suffix; 70 | var firstch; 71 | var origword = w; 72 | 73 | if (w.length < 3) 74 | return w; 75 | 76 | var re; 77 | var re2; 78 | var re3; 79 | var re4; 80 | 81 | firstch = w.substr(0,1); 82 | if (firstch == "y") 83 | w = firstch.toUpperCase() + w.substr(1); 84 | 85 | // Step 1a 86 | re = /^(.+?)(ss|i)es$/; 87 | re2 = /^(.+?)([^s])s$/; 88 | 89 | if (re.test(w)) 90 | w = w.replace(re,"$1$2"); 91 | else if (re2.test(w)) 92 | w = w.replace(re2,"$1$2"); 93 | 94 | // Step 1b 95 | re = /^(.+?)eed$/; 96 | re2 = /^(.+?)(ed|ing)$/; 97 | if (re.test(w)) { 98 | var fp = re.exec(w); 99 | re = new RegExp(mgr0); 100 | if (re.test(fp[1])) { 101 | re = /.$/; 102 | w = w.replace(re,""); 103 | } 104 | } 105 | else if (re2.test(w)) { 106 | var fp = re2.exec(w); 107 | stem = fp[1]; 108 | re2 = new RegExp(s_v); 109 | if (re2.test(stem)) { 110 | w = stem; 111 | re2 = /(at|bl|iz)$/; 112 | re3 = new RegExp("([^aeiouylsz])\\1$"); 113 | re4 = new RegExp("^" + C + v + "[^aeiouwxy]$"); 114 | if (re2.test(w)) 115 | w = w + "e"; 116 | else if (re3.test(w)) { 117 | re = /.$/; 118 | w = w.replace(re,""); 119 | } 120 | else if (re4.test(w)) 121 | w = w + "e"; 122 | } 123 | } 124 | 125 | // Step 1c 126 | re = /^(.+?)y$/; 127 | if (re.test(w)) { 128 | var fp = re.exec(w); 129 | stem = fp[1]; 130 | re = new RegExp(s_v); 131 | if (re.test(stem)) 132 | w = stem + "i"; 133 | } 134 | 135 | // Step 2 136 | re = /^(.+?)(ational|tional|enci|anci|izer|bli|alli|entli|eli|ousli|ization|ation|ator|alism|iveness|fulness|ousness|aliti|iviti|biliti|logi)$/; 137 | if (re.test(w)) { 138 | var fp = re.exec(w); 139 | stem = fp[1]; 140 | suffix = fp[2]; 141 | re = new RegExp(mgr0); 142 | if (re.test(stem)) 143 | w = stem + step2list[suffix]; 144 | } 145 | 146 | // Step 3 147 | re = /^(.+?)(icate|ative|alize|iciti|ical|ful|ness)$/; 148 | if (re.test(w)) { 149 | var fp = re.exec(w); 150 | stem = fp[1]; 151 | suffix = fp[2]; 152 | re = new RegExp(mgr0); 153 | if (re.test(stem)) 154 | w = stem + step3list[suffix]; 155 | } 156 | 157 | // Step 4 158 | re = /^(.+?)(al|ance|ence|er|ic|able|ible|ant|ement|ment|ent|ou|ism|ate|iti|ous|ive|ize)$/; 159 | re2 = /^(.+?)(s|t)(ion)$/; 160 | if (re.test(w)) { 161 | var fp = re.exec(w); 162 | stem = fp[1]; 163 | re = new RegExp(mgr1); 164 | if (re.test(stem)) 165 | w = stem; 166 | } 167 | else if (re2.test(w)) { 168 | var fp = re2.exec(w); 169 | stem = fp[1] + fp[2]; 170 | re2 = new RegExp(mgr1); 171 | if (re2.test(stem)) 172 | w = stem; 173 | } 174 | 175 | // Step 5 176 | re = /^(.+?)e$/; 177 | if (re.test(w)) { 178 | var fp = re.exec(w); 179 | stem = fp[1]; 180 | re = new RegExp(mgr1); 181 | re2 = new RegExp(meq1); 182 | re3 = new RegExp("^" + C + v + "[^aeiouwxy]$"); 183 | if (re.test(stem) || (re2.test(stem) && !(re3.test(stem)))) 184 | w = stem; 185 | } 186 | re = /ll$/; 187 | re2 = new RegExp(mgr1); 188 | if (re.test(w) && re2.test(w)) { 189 | re = /.$/; 190 | w = w.replace(re,""); 191 | } 192 | 193 | // and turn initial Y back to y 194 | if (firstch == "y") 195 | w = firstch.toLowerCase() + w.substr(1); 196 | return w; 197 | } 198 | } 199 | 200 | -------------------------------------------------------------------------------- /docs/_build/html/_static/minus.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aim-lab/PVBM/71c9077164098f85c928a09be719468e0a5896e4/docs/_build/html/_static/minus.png -------------------------------------------------------------------------------- /docs/_build/html/_static/nbsphinx-broken-thumbnail.svg: -------------------------------------------------------------------------------- 1 | 2 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /docs/_build/html/_static/nbsphinx-code-cells.css: -------------------------------------------------------------------------------- 1 | /* remove conflicting styling from Sphinx themes */ 2 | div.nbinput.container div.prompt *, 3 | div.nboutput.container div.prompt *, 4 | div.nbinput.container div.input_area pre, 5 | div.nboutput.container div.output_area pre, 6 | div.nbinput.container div.input_area .highlight, 7 | div.nboutput.container div.output_area .highlight { 8 | border: none; 9 | padding: 0; 10 | margin: 0; 11 | box-shadow: none; 12 | } 13 | 14 | div.nbinput.container > div[class*=highlight], 15 | div.nboutput.container > div[class*=highlight] { 16 | margin: 0; 17 | } 18 | 19 | div.nbinput.container div.prompt *, 20 | div.nboutput.container div.prompt * { 21 | background: none; 22 | } 23 | 24 | div.nboutput.container div.output_area .highlight, 25 | div.nboutput.container div.output_area pre { 26 | background: unset; 27 | } 28 | 29 | div.nboutput.container div.output_area div.highlight { 30 | color: unset; /* override Pygments text color */ 31 | } 32 | 33 | /* avoid gaps between output lines */ 34 | div.nboutput.container div[class*=highlight] pre { 35 | line-height: normal; 36 | } 37 | 38 | /* input/output containers */ 39 | div.nbinput.container, 40 | div.nboutput.container { 41 | display: -webkit-flex; 42 | display: flex; 43 | align-items: flex-start; 44 | margin: 0; 45 | width: 100%; 46 | } 47 | @media (max-width: 540px) { 48 | div.nbinput.container, 49 | div.nboutput.container { 50 | flex-direction: column; 51 | } 52 | } 53 | 54 | /* input container */ 55 | div.nbinput.container { 56 | padding-top: 5px; 57 | } 58 | 59 | /* last container */ 60 | div.nblast.container { 61 | padding-bottom: 5px; 62 | } 63 | 64 | /* input prompt */ 65 | div.nbinput.container div.prompt pre { 66 | color: #307FC1; 67 | } 68 | 69 | /* output prompt */ 70 | div.nboutput.container div.prompt pre { 71 | color: #BF5B3D; 72 | } 73 | 74 | /* all prompts */ 75 | div.nbinput.container div.prompt, 76 | div.nboutput.container div.prompt { 77 | width: 4.5ex; 78 | padding-top: 5px; 79 | position: relative; 80 | user-select: none; 81 | } 82 | 83 | div.nbinput.container div.prompt > div, 84 | div.nboutput.container div.prompt > div { 85 | position: absolute; 86 | right: 0; 87 | margin-right: 0.3ex; 88 | } 89 | 90 | @media (max-width: 540px) { 91 | div.nbinput.container div.prompt, 92 | div.nboutput.container div.prompt { 93 | width: unset; 94 | text-align: left; 95 | padding: 0.4em; 96 | } 97 | div.nboutput.container div.prompt.empty { 98 | padding: 0; 99 | } 100 | 101 | div.nbinput.container div.prompt > div, 102 | div.nboutput.container div.prompt > div { 103 | position: unset; 104 | } 105 | } 106 | 107 | /* disable scrollbars and line breaks on prompts */ 108 | div.nbinput.container div.prompt pre, 109 | div.nboutput.container div.prompt pre { 110 | overflow: hidden; 111 | white-space: pre; 112 | } 113 | 114 | /* input/output area */ 115 | div.nbinput.container div.input_area, 116 | div.nboutput.container div.output_area { 117 | -webkit-flex: 1; 118 | flex: 1; 119 | overflow: auto; 120 | } 121 | @media (max-width: 540px) { 122 | div.nbinput.container div.input_area, 123 | div.nboutput.container div.output_area { 124 | width: 100%; 125 | } 126 | } 127 | 128 | /* input area */ 129 | div.nbinput.container div.input_area { 130 | border: 1px solid #e0e0e0; 131 | border-radius: 2px; 132 | /*background: #f5f5f5;*/ 133 | } 134 | 135 | /* override MathJax center alignment in output cells */ 136 | div.nboutput.container div[class*=MathJax] { 137 | text-align: left !important; 138 | } 139 | 140 | /* override sphinx.ext.imgmath center alignment in output cells */ 141 | div.nboutput.container div.math p { 142 | text-align: left; 143 | } 144 | 145 | /* standard error */ 146 | div.nboutput.container div.output_area.stderr { 147 | background: #fdd; 148 | } 149 | 150 | /* ANSI colors */ 151 | .ansi-black-fg { color: #3E424D; } 152 | .ansi-black-bg { background-color: #3E424D; } 153 | .ansi-black-intense-fg { color: #282C36; } 154 | .ansi-black-intense-bg { background-color: #282C36; } 155 | .ansi-red-fg { color: #E75C58; } 156 | .ansi-red-bg { background-color: #E75C58; } 157 | .ansi-red-intense-fg { color: #B22B31; } 158 | .ansi-red-intense-bg { background-color: #B22B31; } 159 | .ansi-green-fg { color: #00A250; } 160 | .ansi-green-bg { background-color: #00A250; } 161 | .ansi-green-intense-fg { color: #007427; } 162 | .ansi-green-intense-bg { background-color: #007427; } 163 | .ansi-yellow-fg { color: #DDB62B; } 164 | .ansi-yellow-bg { background-color: #DDB62B; } 165 | .ansi-yellow-intense-fg { color: #B27D12; } 166 | .ansi-yellow-intense-bg { background-color: #B27D12; } 167 | .ansi-blue-fg { color: #208FFB; } 168 | .ansi-blue-bg { background-color: #208FFB; } 169 | .ansi-blue-intense-fg { color: #0065CA; } 170 | .ansi-blue-intense-bg { background-color: #0065CA; } 171 | .ansi-magenta-fg { color: #D160C4; } 172 | .ansi-magenta-bg { background-color: #D160C4; } 173 | .ansi-magenta-intense-fg { color: #A03196; } 174 | .ansi-magenta-intense-bg { background-color: #A03196; } 175 | .ansi-cyan-fg { color: #60C6C8; } 176 | .ansi-cyan-bg { background-color: #60C6C8; } 177 | .ansi-cyan-intense-fg { color: #258F8F; } 178 | .ansi-cyan-intense-bg { background-color: #258F8F; } 179 | .ansi-white-fg { color: #C5C1B4; } 180 | .ansi-white-bg { background-color: #C5C1B4; } 181 | .ansi-white-intense-fg { color: #A1A6B2; } 182 | .ansi-white-intense-bg { background-color: #A1A6B2; } 183 | 184 | .ansi-default-inverse-fg { color: #FFFFFF; } 185 | .ansi-default-inverse-bg { background-color: #000000; } 186 | 187 | .ansi-bold { font-weight: bold; } 188 | .ansi-underline { text-decoration: underline; } 189 | 190 | 191 | div.nbinput.container div.input_area div[class*=highlight] > pre, 192 | div.nboutput.container div.output_area div[class*=highlight] > pre, 193 | div.nboutput.container div.output_area div[class*=highlight].math, 194 | div.nboutput.container div.output_area.rendered_html, 195 | div.nboutput.container div.output_area > div.output_javascript, 196 | div.nboutput.container div.output_area:not(.rendered_html) > img{ 197 | padding: 5px; 198 | margin: 0; 199 | } 200 | 201 | /* fix copybtn overflow problem in chromium (needed for 'sphinx_copybutton') */ 202 | div.nbinput.container div.input_area > div[class^='highlight'], 203 | div.nboutput.container div.output_area > div[class^='highlight']{ 204 | overflow-y: hidden; 205 | } 206 | 207 | /* hide copybtn icon on prompts (needed for 'sphinx_copybutton') */ 208 | .prompt .copybtn { 209 | display: none; 210 | } 211 | 212 | /* Some additional styling taken form the Jupyter notebook CSS */ 213 | .jp-RenderedHTMLCommon table, 214 | div.rendered_html table { 215 | border: none; 216 | border-collapse: collapse; 217 | border-spacing: 0; 218 | color: black; 219 | font-size: 12px; 220 | table-layout: fixed; 221 | } 222 | .jp-RenderedHTMLCommon thead, 223 | div.rendered_html thead { 224 | border-bottom: 1px solid black; 225 | vertical-align: bottom; 226 | } 227 | .jp-RenderedHTMLCommon tr, 228 | .jp-RenderedHTMLCommon th, 229 | .jp-RenderedHTMLCommon td, 230 | div.rendered_html tr, 231 | div.rendered_html th, 232 | div.rendered_html td { 233 | text-align: right; 234 | vertical-align: middle; 235 | padding: 0.5em 0.5em; 236 | line-height: normal; 237 | white-space: normal; 238 | max-width: none; 239 | border: none; 240 | } 241 | .jp-RenderedHTMLCommon th, 242 | div.rendered_html th { 243 | font-weight: bold; 244 | } 245 | .jp-RenderedHTMLCommon tbody tr:nth-child(odd), 246 | div.rendered_html tbody tr:nth-child(odd) { 247 | background: #f5f5f5; 248 | } 249 | .jp-RenderedHTMLCommon tbody tr:hover, 250 | div.rendered_html tbody tr:hover { 251 | background: rgba(66, 165, 245, 0.2); 252 | } 253 | 254 | -------------------------------------------------------------------------------- /docs/_build/html/_static/nbsphinx-gallery.css: -------------------------------------------------------------------------------- 1 | .nbsphinx-gallery { 2 | display: grid; 3 | grid-template-columns: repeat(auto-fill, minmax(160px, 1fr)); 4 | gap: 5px; 5 | margin-top: 1em; 6 | margin-bottom: 1em; 7 | } 8 | 9 | .nbsphinx-gallery > a { 10 | padding: 5px; 11 | border: 1px dotted currentColor; 12 | border-radius: 2px; 13 | text-align: center; 14 | } 15 | 16 | .nbsphinx-gallery > a:hover { 17 | border-style: solid; 18 | } 19 | 20 | .nbsphinx-gallery img { 21 | max-width: 100%; 22 | max-height: 100%; 23 | } 24 | 25 | .nbsphinx-gallery > a > div:first-child { 26 | display: flex; 27 | align-items: start; 28 | justify-content: center; 29 | height: 120px; 30 | margin-bottom: 5px; 31 | } 32 | -------------------------------------------------------------------------------- /docs/_build/html/_static/nbsphinx-no-thumbnail.svg: -------------------------------------------------------------------------------- 1 | 2 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /docs/_build/html/_static/plus.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aim-lab/PVBM/71c9077164098f85c928a09be719468e0a5896e4/docs/_build/html/_static/plus.png -------------------------------------------------------------------------------- /docs/_build/html/_static/pygments.css: -------------------------------------------------------------------------------- 1 | pre { line-height: 125%; } 2 | td.linenos .normal { color: inherit; background-color: transparent; padding-left: 5px; padding-right: 5px; } 3 | span.linenos { color: inherit; background-color: transparent; padding-left: 5px; padding-right: 5px; } 4 | td.linenos .special { color: #000000; background-color: #ffffc0; padding-left: 5px; padding-right: 5px; } 5 | span.linenos.special { color: #000000; background-color: #ffffc0; padding-left: 5px; padding-right: 5px; } 6 | .highlight .hll { background-color: #ffffcc } 7 | .highlight { background: #f8f8f8; } 8 | .highlight .c { color: #3D7B7B; font-style: italic } /* Comment */ 9 | .highlight .err { border: 1px solid #FF0000 } /* Error */ 10 | .highlight .k { color: #008000; font-weight: bold } /* Keyword */ 11 | .highlight .o { color: #666666 } /* Operator */ 12 | .highlight .ch { color: #3D7B7B; font-style: italic } /* Comment.Hashbang */ 13 | .highlight .cm { color: #3D7B7B; font-style: italic } /* Comment.Multiline */ 14 | .highlight .cp { color: #9C6500 } /* Comment.Preproc */ 15 | .highlight .cpf { color: #3D7B7B; font-style: italic } /* Comment.PreprocFile */ 16 | .highlight .c1 { color: #3D7B7B; font-style: italic } /* Comment.Single */ 17 | .highlight .cs { color: #3D7B7B; font-style: italic } /* Comment.Special */ 18 | .highlight .gd { color: #A00000 } /* Generic.Deleted */ 19 | .highlight .ge { font-style: italic } /* Generic.Emph */ 20 | .highlight .gr { color: #E40000 } /* Generic.Error */ 21 | .highlight .gh { color: #000080; font-weight: bold } /* Generic.Heading */ 22 | .highlight .gi { color: #008400 } /* Generic.Inserted */ 23 | .highlight .go { color: #717171 } /* Generic.Output */ 24 | .highlight .gp { color: #000080; font-weight: bold } /* Generic.Prompt */ 25 | .highlight .gs { font-weight: bold } /* Generic.Strong */ 26 | .highlight .gu { color: #800080; font-weight: bold } /* Generic.Subheading */ 27 | .highlight .gt { color: #0044DD } /* Generic.Traceback */ 28 | .highlight .kc { color: #008000; font-weight: bold } /* Keyword.Constant */ 29 | .highlight .kd { color: #008000; font-weight: bold } /* Keyword.Declaration */ 30 | .highlight .kn { color: #008000; font-weight: bold } /* Keyword.Namespace */ 31 | .highlight .kp { color: #008000 } /* Keyword.Pseudo */ 32 | .highlight .kr { color: #008000; font-weight: bold } /* Keyword.Reserved */ 33 | .highlight .kt { color: #B00040 } /* Keyword.Type */ 34 | .highlight .m { color: #666666 } /* Literal.Number */ 35 | .highlight .s { color: #BA2121 } /* Literal.String */ 36 | .highlight .na { color: #687822 } /* Name.Attribute */ 37 | .highlight .nb { color: #008000 } /* Name.Builtin */ 38 | .highlight .nc { color: #0000FF; font-weight: bold } /* Name.Class */ 39 | .highlight .no { color: #880000 } /* Name.Constant */ 40 | .highlight .nd { color: #AA22FF } /* Name.Decorator */ 41 | .highlight .ni { color: #717171; font-weight: bold } /* Name.Entity */ 42 | .highlight .ne { color: #CB3F38; font-weight: bold } /* Name.Exception */ 43 | .highlight .nf { color: #0000FF } /* Name.Function */ 44 | .highlight .nl { color: #767600 } /* Name.Label */ 45 | .highlight .nn { color: #0000FF; font-weight: bold } /* Name.Namespace */ 46 | .highlight .nt { color: #008000; font-weight: bold } /* Name.Tag */ 47 | .highlight .nv { color: #19177C } /* Name.Variable */ 48 | .highlight .ow { color: #AA22FF; font-weight: bold } /* Operator.Word */ 49 | .highlight .w { color: #bbbbbb } /* Text.Whitespace */ 50 | .highlight .mb { color: #666666 } /* Literal.Number.Bin */ 51 | .highlight .mf { color: #666666 } /* Literal.Number.Float */ 52 | .highlight .mh { color: #666666 } /* Literal.Number.Hex */ 53 | .highlight .mi { color: #666666 } /* Literal.Number.Integer */ 54 | .highlight .mo { color: #666666 } /* Literal.Number.Oct */ 55 | .highlight .sa { color: #BA2121 } /* Literal.String.Affix */ 56 | .highlight .sb { color: #BA2121 } /* Literal.String.Backtick */ 57 | .highlight .sc { color: #BA2121 } /* Literal.String.Char */ 58 | .highlight .dl { color: #BA2121 } /* Literal.String.Delimiter */ 59 | .highlight .sd { color: #BA2121; font-style: italic } /* Literal.String.Doc */ 60 | .highlight .s2 { color: #BA2121 } /* Literal.String.Double */ 61 | .highlight .se { color: #AA5D1F; font-weight: bold } /* Literal.String.Escape */ 62 | .highlight .sh { color: #BA2121 } /* Literal.String.Heredoc */ 63 | .highlight .si { color: #A45A77; font-weight: bold } /* Literal.String.Interpol */ 64 | .highlight .sx { color: #008000 } /* Literal.String.Other */ 65 | .highlight .sr { color: #A45A77 } /* Literal.String.Regex */ 66 | .highlight .s1 { color: #BA2121 } /* Literal.String.Single */ 67 | .highlight .ss { color: #19177C } /* Literal.String.Symbol */ 68 | .highlight .bp { color: #008000 } /* Name.Builtin.Pseudo */ 69 | .highlight .fm { color: #0000FF } /* Name.Function.Magic */ 70 | .highlight .vc { color: #19177C } /* Name.Variable.Class */ 71 | .highlight .vg { color: #19177C } /* Name.Variable.Global */ 72 | .highlight .vi { color: #19177C } /* Name.Variable.Instance */ 73 | .highlight .vm { color: #19177C } /* Name.Variable.Magic */ 74 | .highlight .il { color: #666666 } /* Literal.Number.Integer.Long */ -------------------------------------------------------------------------------- /docs/_build/html/_static/sphinx_highlight.js: -------------------------------------------------------------------------------- 1 | /* Highlighting utilities for Sphinx HTML documentation. */ 2 | "use strict"; 3 | 4 | const SPHINX_HIGHLIGHT_ENABLED = true 5 | 6 | /** 7 | * highlight a given string on a node by wrapping it in 8 | * span elements with the given class name. 9 | */ 10 | const _highlight = (node, addItems, text, className) => { 11 | if (node.nodeType === Node.TEXT_NODE) { 12 | const val = node.nodeValue; 13 | const parent = node.parentNode; 14 | const pos = val.toLowerCase().indexOf(text); 15 | if ( 16 | pos >= 0 && 17 | !parent.classList.contains(className) && 18 | !parent.classList.contains("nohighlight") 19 | ) { 20 | let span; 21 | 22 | const closestNode = parent.closest("body, svg, foreignObject"); 23 | const isInSVG = closestNode && closestNode.matches("svg"); 24 | if (isInSVG) { 25 | span = document.createElementNS("http://www.w3.org/2000/svg", "tspan"); 26 | } else { 27 | span = document.createElement("span"); 28 | span.classList.add(className); 29 | } 30 | 31 | span.appendChild(document.createTextNode(val.substr(pos, text.length))); 32 | parent.insertBefore( 33 | span, 34 | parent.insertBefore( 35 | document.createTextNode(val.substr(pos + text.length)), 36 | node.nextSibling 37 | ) 38 | ); 39 | node.nodeValue = val.substr(0, pos); 40 | 41 | if (isInSVG) { 42 | const rect = document.createElementNS( 43 | "http://www.w3.org/2000/svg", 44 | "rect" 45 | ); 46 | const bbox = parent.getBBox(); 47 | rect.x.baseVal.value = bbox.x; 48 | rect.y.baseVal.value = bbox.y; 49 | rect.width.baseVal.value = bbox.width; 50 | rect.height.baseVal.value = bbox.height; 51 | rect.setAttribute("class", className); 52 | addItems.push({ parent: parent, target: rect }); 53 | } 54 | } 55 | } else if (node.matches && !node.matches("button, select, textarea")) { 56 | node.childNodes.forEach((el) => _highlight(el, addItems, text, className)); 57 | } 58 | }; 59 | const _highlightText = (thisNode, text, className) => { 60 | let addItems = []; 61 | _highlight(thisNode, addItems, text, className); 62 | addItems.forEach((obj) => 63 | obj.parent.insertAdjacentElement("beforebegin", obj.target) 64 | ); 65 | }; 66 | 67 | /** 68 | * Small JavaScript module for the documentation. 69 | */ 70 | const SphinxHighlight = { 71 | 72 | /** 73 | * highlight the search words provided in localstorage in the text 74 | */ 75 | highlightSearchWords: () => { 76 | if (!SPHINX_HIGHLIGHT_ENABLED) return; // bail if no highlight 77 | 78 | // get and clear terms from localstorage 79 | const url = new URL(window.location); 80 | const highlight = 81 | localStorage.getItem("sphinx_highlight_terms") 82 | || url.searchParams.get("highlight") 83 | || ""; 84 | localStorage.removeItem("sphinx_highlight_terms") 85 | url.searchParams.delete("highlight"); 86 | window.history.replaceState({}, "", url); 87 | 88 | // get individual terms from highlight string 89 | const terms = highlight.toLowerCase().split(/\s+/).filter(x => x); 90 | if (terms.length === 0) return; // nothing to do 91 | 92 | // There should never be more than one element matching "div.body" 93 | const divBody = document.querySelectorAll("div.body"); 94 | const body = divBody.length ? divBody[0] : document.querySelector("body"); 95 | window.setTimeout(() => { 96 | terms.forEach((term) => _highlightText(body, term, "highlighted")); 97 | }, 10); 98 | 99 | const searchBox = document.getElementById("searchbox"); 100 | if (searchBox === null) return; 101 | searchBox.appendChild( 102 | document 103 | .createRange() 104 | .createContextualFragment( 105 | '" 109 | ) 110 | ); 111 | }, 112 | 113 | /** 114 | * helper function to hide the search marks again 115 | */ 116 | hideSearchWords: () => { 117 | document 118 | .querySelectorAll("#searchbox .highlight-link") 119 | .forEach((el) => el.remove()); 120 | document 121 | .querySelectorAll("span.highlighted") 122 | .forEach((el) => el.classList.remove("highlighted")); 123 | localStorage.removeItem("sphinx_highlight_terms") 124 | }, 125 | 126 | initEscapeListener: () => { 127 | // only install a listener if it is really needed 128 | if (!DOCUMENTATION_OPTIONS.ENABLE_SEARCH_SHORTCUTS) return; 129 | 130 | document.addEventListener("keydown", (event) => { 131 | // bail for input elements 132 | if (BLACKLISTED_KEY_CONTROL_ELEMENTS.has(document.activeElement.tagName)) return; 133 | // bail with special keys 134 | if (event.shiftKey || event.altKey || event.ctrlKey || event.metaKey) return; 135 | if (DOCUMENTATION_OPTIONS.ENABLE_SEARCH_SHORTCUTS && (event.key === "Escape")) { 136 | SphinxHighlight.hideSearchWords(); 137 | event.preventDefault(); 138 | } 139 | }); 140 | }, 141 | }; 142 | 143 | _ready(SphinxHighlight.highlightSearchWords); 144 | _ready(SphinxHighlight.initEscapeListener); 145 | -------------------------------------------------------------------------------- /docs/_build/html/objects.inv: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aim-lab/PVBM/71c9077164098f85c928a09be719468e0a5896e4/docs/_build/html/objects.inv -------------------------------------------------------------------------------- /docs/_build/html/py-modindex.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Python Module Index — PVBM 3.0.0.0 documentation 7 | 8 | 9 | 10 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 |
28 | 59 | 60 |
64 | 65 |
66 |
67 |
68 |
    69 |
  • 70 | 71 |
  • 72 |
  • 73 |
74 |
75 |
76 |
77 |
78 | 79 | 80 |

Python Module Index

81 | 82 |
83 | p 84 |
85 | 86 | 87 | 88 | 90 | 91 | 93 | 96 | 97 | 98 | 101 | 102 | 103 | 106 | 107 | 108 | 111 | 112 | 113 | 116 | 117 | 118 | 121 | 122 | 123 | 126 | 127 | 128 | 131 |
 
89 | p
94 | PVBM 95 |
    99 | PVBM.CentralRetinalAnalysis 100 |
    104 | PVBM.Datasets 105 |
    109 | PVBM.DiscSegmenter 110 |
    114 | PVBM.FractalAnalysis 115 |
    119 | PVBM.GeometricalAnalysis 120 |
    124 | PVBM.GeometryAnalysis 125 |
    129 | PVBM.LesionSegmenter 130 |
132 | 133 | 134 |
135 |
136 |
137 | 138 |
139 | 140 |
141 |

© Copyright 2023, JF.

142 |
143 | 144 | Built with Sphinx using a 145 | theme 146 | provided by Read the Docs. 147 | 148 | 149 |
150 |
151 |
152 |
153 |
154 | 159 | 160 | 161 | -------------------------------------------------------------------------------- /docs/_build/html/search.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Search — PVBM 3.0.0.0 documentation 7 | 8 | 9 | 10 | 11 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 |
28 | 59 | 60 |
64 | 65 |
66 |
67 |
68 |
    69 |
  • 70 | 71 |
  • 72 |
  • 73 |
74 |
75 |
76 |
77 |
78 | 79 | 86 | 87 | 88 |
89 | 90 |
91 | 92 |
93 |
94 |
95 | 96 |
97 | 98 |
99 |

© Copyright 2023, JF.

100 |
101 | 102 | Built with Sphinx using a 103 | theme 104 | provided by Read the Docs. 105 | 106 | 107 |
108 |
109 |
110 |
111 |
112 | 117 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | -------------------------------------------------------------------------------- /docs/conf.py: -------------------------------------------------------------------------------- 1 | # Configuration file for the Sphinx documentation builder. 2 | # 3 | # For the full list of built-in configuration values, see the documentation: 4 | # https://www.sphinx-doc.org/en/master/usage/configuration.html 5 | 6 | # -- Project information ----------------------------------------------------- 7 | # https://www.sphinx-doc.org/en/master/usage/configuration.html#project-information 8 | import os 9 | import sys 10 | import jupyter_core.paths 11 | 12 | sys.path.insert(0, os.path.abspath('..')) 13 | 14 | project = 'PVBM' 15 | copyright = '2023, JF' 16 | author = 'JF' 17 | release = '3.0.0.0' 18 | 19 | # -- General configuration --------------------------------------------------- 20 | # https://www.sphinx-doc.org/en/master/usage/configuration.html#general-configuration 21 | 22 | extensions = [ 23 | 'sphinx.ext.autodoc', 24 | 'sphinx.ext.viewcode', 25 | 'sphinx.ext.napoleon', 26 | 'nbsphinx', 27 | 'sphinx.ext.mathjax', 28 | ] 29 | 30 | nbsphinx_execute = 'never' 31 | source_dir = 'docs' 32 | 33 | # Add Jupyter's default template path 34 | template_paths = jupyter_core.paths.jupyter_path('nbconvert/templates') 35 | 36 | if not any('rst' in os.listdir(path) for path in template_paths if os.path.exists(path)): 37 | raise ValueError("No template sub-directory with name 'rst' found in Jupyter's template paths.") 38 | 39 | # Now add these template paths to Sphinx 40 | templates_path = ['_templates'] + template_paths 41 | 42 | exclude_patterns = ['_build', 'Thumbs.db', '.DS_Store'] 43 | modindex_common_prefix = [] 44 | 45 | # -- Options for HTML output ------------------------------------------------- 46 | # https://www.sphinx-doc.org/en/master/usage/configuration.html#options-for-html-output 47 | 48 | html_theme = 'sphinx_rtd_theme' 49 | html_static_path = ['_static'] 50 | html_css_files = ['custom.css'] 51 | -------------------------------------------------------------------------------- /docs/docs_requirements.txt: -------------------------------------------------------------------------------- 1 | nbsphinx 2 | numpy 3 | scipy 4 | scikit-image 5 | pillow 6 | -------------------------------------------------------------------------------- /docs/figures/pipeline.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aim-lab/PVBM/71c9077164098f85c928a09be719468e0a5896e4/docs/figures/pipeline.png -------------------------------------------------------------------------------- /docs/make.bat: -------------------------------------------------------------------------------- 1 | @ECHO OFF 2 | 3 | pushd %~dp0 4 | 5 | REM Command file for Sphinx documentation 6 | 7 | if "%SPHINXBUILD%" == "" ( 8 | set SPHINXBUILD=sphinx-build 9 | ) 10 | set SOURCEDIR=. 11 | set BUILDDIR=_build 12 | 13 | %SPHINXBUILD% >NUL 2>NUL 14 | if errorlevel 9009 ( 15 | echo. 16 | echo.The 'sphinx-build' command was not found. Make sure you have Sphinx 17 | echo.installed, then set the SPHINXBUILD environment variable to point 18 | echo.to the full path of the 'sphinx-build' executable. Alternatively you 19 | echo.may add the Sphinx directory to PATH. 20 | echo. 21 | echo.If you don't have Sphinx installed, grab it from 22 | echo.https://www.sphinx-doc.org/ 23 | exit /b 1 24 | ) 25 | 26 | if "%1" == "" goto help 27 | 28 | %SPHINXBUILD% -M %1 %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O% 29 | goto end 30 | 31 | :help 32 | %SPHINXBUILD% -M help %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O% 33 | 34 | :end 35 | popd 36 | -------------------------------------------------------------------------------- /docs/requirements.txt: -------------------------------------------------------------------------------- 1 | sphinx 2 | sphinx-rtd-theme 3 | nbsphinx 4 | jupyter 5 | -------------------------------------------------------------------------------- /docs/untitled: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | #PBS -N install_python_lib 3 | #PBS -l nodes=1:ppn=1 4 | #PBS -l walltime=00:10:00 5 | #PBS -j oe 6 | #PBS -q gpu_v100_q 7 | 8 | cd $PBS_O_WORKDIR 9 | 10 | # Activate the virtual environment (if applicable) 11 | source myenv/bin/activate 12 | 13 | # Install the Python library 14 | pip install library_name 15 | 16 | # Deactivate the virtual environment (if applicable) 17 | deactivate 18 | -------------------------------------------------------------------------------- /figures/pipeline.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aim-lab/PVBM/71c9077164098f85c928a09be719468e0a5896e4/figures/pipeline.png -------------------------------------------------------------------------------- /images/117-793-749-000036_RR_43001_04734_F_48.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aim-lab/PVBM/71c9077164098f85c928a09be719468e0a5896e4/images/117-793-749-000036_RR_43001_04734_F_48.png -------------------------------------------------------------------------------- /images/117-793-749-000036_RR_43001_04734_F_48.png.1: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aim-lab/PVBM/71c9077164098f85c928a09be719468e0a5896e4/images/117-793-749-000036_RR_43001_04734_F_48.png.1 -------------------------------------------------------------------------------- /images/117-793-749-000036_RR_43001_04734_F_48.png.2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aim-lab/PVBM/71c9077164098f85c928a09be719468e0a5896e4/images/117-793-749-000036_RR_43001_04734_F_48.png.2 -------------------------------------------------------------------------------- /images/117-793-749-000036_RR_43001_04734_F_48.png.3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aim-lab/PVBM/71c9077164098f85c928a09be719468e0a5896e4/images/117-793-749-000036_RR_43001_04734_F_48.png.3 -------------------------------------------------------------------------------- /images/117-793-749-000036_RR_43001_04734_F_48.png.4: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aim-lab/PVBM/71c9077164098f85c928a09be719468e0a5896e4/images/117-793-749-000036_RR_43001_04734_F_48.png.4 -------------------------------------------------------------------------------- /images/121-691-760-V721942_RR_63739_04251_M_74.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aim-lab/PVBM/71c9077164098f85c928a09be719468e0a5896e4/images/121-691-760-V721942_RR_63739_04251_M_74.png -------------------------------------------------------------------------------- /images/121-691-760-V721942_RR_63739_04251_M_74.png.1: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aim-lab/PVBM/71c9077164098f85c928a09be719468e0a5896e4/images/121-691-760-V721942_RR_63739_04251_M_74.png.1 -------------------------------------------------------------------------------- /images/121-691-760-V721942_RR_63739_04251_M_74.png.2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aim-lab/PVBM/71c9077164098f85c928a09be719468e0a5896e4/images/121-691-760-V721942_RR_63739_04251_M_74.png.2 -------------------------------------------------------------------------------- /images/121-691-760-V721942_RR_63739_04251_M_74.png.3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aim-lab/PVBM/71c9077164098f85c928a09be719468e0a5896e4/images/121-691-760-V721942_RR_63739_04251_M_74.png.3 -------------------------------------------------------------------------------- /images/121-691-760-V721942_RR_63739_04251_M_74.png.4: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aim-lab/PVBM/71c9077164098f85c928a09be719468e0a5896e4/images/121-691-760-V721942_RR_63739_04251_M_74.png.4 -------------------------------------------------------------------------------- /pvbm.egg-info/SOURCES.txt: -------------------------------------------------------------------------------- 1 | LICENSE 2 | MANIFEST.in 3 | README.md 4 | setup.py 5 | PVBM/CentralRetinalAnalysis.py 6 | PVBM/Datasets.py 7 | PVBM/DiscSegmenter.py 8 | PVBM/FractalAnalysis.py 9 | PVBM/GeometricalAnalysis.py 10 | PVBM/GeometryAnalysis.py 11 | PVBM/LesionSegmenter.py 12 | PVBM/__init__.py 13 | PVBM/debug.py 14 | PVBM/lunetv2_odc.onnx 15 | PVBM/GraphCRE/GraphCentralRetinalEquivalent.py 16 | PVBM/GraphCRE/__init__.py 17 | PVBM/GraphRegularisation/GraphRegularisation.py 18 | PVBM/GraphRegularisation/__init__.py 19 | PVBM/helpers/__init__.py 20 | PVBM/helpers/branching2.py 21 | PVBM/helpers/branching_angle.py 22 | PVBM/helpers/perimeter.py 23 | PVBM/helpers/tortuosity.py 24 | pvbm.egg-info/PKG-INFO 25 | pvbm.egg-info/SOURCES.txt 26 | pvbm.egg-info/dependency_links.txt 27 | pvbm.egg-info/requires.txt 28 | pvbm.egg-info/top_level.txt -------------------------------------------------------------------------------- /pvbm.egg-info/dependency_links.txt: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /pvbm.egg-info/requires.txt: -------------------------------------------------------------------------------- 1 | numpy 2 | scipy 3 | scikit-image 4 | pillow 5 | gdown 6 | onnxruntime 7 | torchvision 8 | opencv-python 9 | matplotlib 10 | -------------------------------------------------------------------------------- /pvbm.egg-info/top_level.txt: -------------------------------------------------------------------------------- 1 | PVBM 2 | -------------------------------------------------------------------------------- /setup.py: -------------------------------------------------------------------------------- 1 | from setuptools import setup, find_packages 2 | 3 | 4 | def read_readme(file_name): 5 | with open(file_name, "r", encoding="utf-8") as file: 6 | return file.read() 7 | 8 | 9 | long_description = read_readme("README.md") 10 | 11 | setup( 12 | name='pvbm', 13 | version='3.0.0.0', 14 | packages=find_packages(), 15 | include_package_data=True, # Ensure non-Python files are included 16 | package_data={ 17 | "": ["*.onnx"], # Include all .onnx files in all subdirectories 18 | }, 19 | install_requires=[ 20 | "numpy", 21 | "scipy", 22 | "scikit-image", 23 | "pillow", 24 | "gdown", 25 | "onnxruntime", 26 | "torchvision", 27 | "opencv-python", 28 | "matplotlib" 29 | ], 30 | author='Jonathan Fhima, Yevgeniy Men', 31 | author_email='jonathanfh@campus.technion.ac.il', 32 | description="Python Vasculature Biomarker toolbox", 33 | long_description=long_description, 34 | long_description_content_type="text/markdown", 35 | url='https://github.com/aim-lab/PVBM', 36 | ) 37 | --------------------------------------------------------------------------------