retuve.keyphrases.config

The parent class for for Retuve configs

  1# Copyright 2024 Adam McArthur
  2#
  3# Licensed under the Apache License, Version 2.0 (the "License");
  4# you may not use this file except in compliance with the License.
  5# You may obtain a copy of the License at
  6#
  7#     http://www.apache.org/licenses/LICENSE-2.0
  8#
  9# Unless required by applicable law or agreed to in writing, software
 10# distributed under the License is distributed on an "AS IS" BASIS,
 11# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 12# See the License for the specific language governing permissions and
 13# limitations under the License.
 14
 15"""
 16The parent class for for Retuve configs
 17"""
 18
 19import copy
 20from typing import List, Tuple
 21
 22from PIL import ImageFont
 23from radstract.data.dicom import DicomTypes
 24from torch.types import Device
 25
 26from retuve.keyphrases.enums import OperationType
 27from retuve.keyphrases.subconfig import (
 28    APIConfig,
 29    BatchConfig,
 30    HipConfig,
 31    TrakConfig,
 32    VisualsConfig,
 33)
 34from retuve.logs import ulogger
 35from retuve.utils import RETUVE_DIR, register_config_dirs
 36
 37
 38class GlobalConfig:
 39    def __init__(self, username: str, password: str):
 40        self.username = username
 41        self.password = password
 42
 43
 44class Config:
 45    """Configuration class."""
 46
 47    configs = {}
 48    live_config = None
 49
 50    def __init__(
 51        self,
 52        dicom_type: DicomTypes,
 53        crop_coordinates: Tuple[float],
 54        template: bool,
 55        min_seg_confidence: float,
 56        device: Device,
 57        operation_type: OperationType,
 58        dev: bool,
 59        replace_old: bool,
 60        seg_export: bool,
 61        test_data_passthrough: bool,
 62        subconfig_hip: HipConfig,
 63        subconfig_trak: TrakConfig,
 64        subconfig_visuals: VisualsConfig,
 65        subconfig_api: APIConfig,
 66        subconfig_batch: BatchConfig,
 67        name=None,
 68    ):
 69        """
 70        Initialize Config.
 71
 72        :param dicom_type (DicomTypes): The type of dicom to use.
 73        :param crop_coordinates (Tuple[float]): The crop coordinates.
 74        :param template (bool): Whether this is a template config.
 75        :param min_seg_confidence (float): The minimum segmentation confidence.
 76        :param device (Device): The device to use.
 77        :param operation_type (OperationType): The operation type.
 78        :param dev (bool): Whether to use dev mode.
 79        :param replace_old (bool): Whether to replace old files.
 80        :param seg_export (bool): Whether to export segmentation.
 81        :param test_data_passthrough (bool): Whether to pass through test data.
 82        :param subconfig_hip (HipConfig): The hip subconfig.
 83        :param subconfig_trak (TrakConfig): The trak subconfig.
 84        :param subconfig_visuals (VisualsConfig): The visuals subconfig.
 85        :param subconfig_api (APIConfig): The api subconfig.
 86        :param subconfig_batch (BatchConfig): The batch subconfig.
 87        :param name (str): The name (keyphrase) of the config.
 88        """
 89        self.name = name
 90
 91        if not (template or name):
 92            raise ValueError("Template configs must have a name specified.")
 93
 94        if not template and (name):
 95            self.register(name)
 96
 97        self.dicom_type = dicom_type
 98        self.crop_coordinates = crop_coordinates
 99        self.min_seg_confidence = min_seg_confidence
100
101        self.device = device
102        self.replace_old = replace_old
103        self.operation_type = operation_type
104        self.dev = dev
105
106        self.seg_export = seg_export
107
108        self.hip: HipConfig = subconfig_hip
109        self.trak: TrakConfig = subconfig_trak
110        self.visuals: VisualsConfig = subconfig_visuals
111        self.api: APIConfig = subconfig_api
112        self.batch: BatchConfig = subconfig_batch
113
114        self.test_data_passthrough = test_data_passthrough
115
116        if operation_type not in [
117            OperationType.SEG,
118            OperationType.LANDMARK,
119        ]:
120            raise ValueError(f"Invalid operation type: {operation_type}")
121
122    def register(
123        self,
124        name: str,
125        store: bool = True,
126        silent: bool = False,
127        live: bool = False,
128    ):
129        """
130        Register the config.
131
132        :param name (str): The name of the config.
133        :param store (bool): Whether to store the config
134                             for later retrieval.
135
136        """
137        self.name = name
138
139        # check if config already exists
140        if self.configs.get(name):
141            raise ValueError(f"Config {name} already exists.")
142
143        if not self.configs.get(name) and store:
144            self.configs[name] = {}
145
146        if store:
147            self.configs[name] = self
148
149        if live:
150            Config.live_config = self
151
152        # defaults need registering
153        if self.visuals.default_font_size:
154            self.visuals.font_h1 = ImageFont.truetype(
155                f"{RETUVE_DIR}/files/RobotoMono-Regular.ttf",
156                self.visuals.default_font_size,
157            )
158
159            self.visuals.font_h2 = ImageFont.truetype(
160                f"{RETUVE_DIR}/files/RobotoMono-Regular.ttf",
161                self.visuals.default_font_size,
162            )
163
164        self.batch.register()
165
166        register_config_dirs(self)
167
168        if not self.api.api_token:
169            ValueError("API token must be set.")
170
171        if not silent:
172            ulogger.info(f"Registered config for {name}")
173
174    def unregister(self, silent: bool = False):
175        """
176        Unregister the config.
177        """
178        if self.name in self.configs:
179            del self.configs[self.name]
180
181        if not silent:
182            ulogger.info(f"Unregistered config for {self.name}")
183
184    def get_copy(self) -> "Config":
185        """
186        Get a copy of the config.
187
188        :return: A copy of the config.
189        """
190        return copy.deepcopy(self)
191
192    def inject_global_config(self, username, password):
193        """
194        Inject the global config into the config.
195
196        :param username (str): The username.
197        :param password (str): The password.
198        """
199        Config.global_config = GlobalConfig(username, password)
200
201    @classmethod
202    def get_configs(self) -> List[Tuple[str, "Config"]]:
203        """
204        Get all registered/stored configs.
205
206        :return: A list of tuples of name and config.
207        """
208        return [(name, config) for name, config, in self.configs.items()]
209
210    @classmethod
211    def get_config(cls, name: str) -> "Config":
212        """
213        Get a config by name.
214
215        :param name (str): The name of the config.
216
217        :return: The config.
218        """
219        # check if name is of type Config
220        if isinstance(name, Config):
221            return name
222
223        if not cls.configs.get(name):
224            raise ValueError(f"Config {name} does not exist.")
225
226        return cls.configs[name]
227
228    @classmethod
229    def keyphrase_exists(cls, name: str) -> bool:
230        """
231        Check if a keyphrase exists in the configs.
232
233        :param name (str): The name of the keyphrase.
234
235        :return: Whether the keyphrase exists.
236        """
237        lower_keys = [key.lower() for key in cls.configs.keys()]
238        return name.lower() in lower_keys
class GlobalConfig:
39class GlobalConfig:
40    def __init__(self, username: str, password: str):
41        self.username = username
42        self.password = password
GlobalConfig(username: str, password: str)
40    def __init__(self, username: str, password: str):
41        self.username = username
42        self.password = password
username
password
class Config:
 45class Config:
 46    """Configuration class."""
 47
 48    configs = {}
 49    live_config = None
 50
 51    def __init__(
 52        self,
 53        dicom_type: DicomTypes,
 54        crop_coordinates: Tuple[float],
 55        template: bool,
 56        min_seg_confidence: float,
 57        device: Device,
 58        operation_type: OperationType,
 59        dev: bool,
 60        replace_old: bool,
 61        seg_export: bool,
 62        test_data_passthrough: bool,
 63        subconfig_hip: HipConfig,
 64        subconfig_trak: TrakConfig,
 65        subconfig_visuals: VisualsConfig,
 66        subconfig_api: APIConfig,
 67        subconfig_batch: BatchConfig,
 68        name=None,
 69    ):
 70        """
 71        Initialize Config.
 72
 73        :param dicom_type (DicomTypes): The type of dicom to use.
 74        :param crop_coordinates (Tuple[float]): The crop coordinates.
 75        :param template (bool): Whether this is a template config.
 76        :param min_seg_confidence (float): The minimum segmentation confidence.
 77        :param device (Device): The device to use.
 78        :param operation_type (OperationType): The operation type.
 79        :param dev (bool): Whether to use dev mode.
 80        :param replace_old (bool): Whether to replace old files.
 81        :param seg_export (bool): Whether to export segmentation.
 82        :param test_data_passthrough (bool): Whether to pass through test data.
 83        :param subconfig_hip (HipConfig): The hip subconfig.
 84        :param subconfig_trak (TrakConfig): The trak subconfig.
 85        :param subconfig_visuals (VisualsConfig): The visuals subconfig.
 86        :param subconfig_api (APIConfig): The api subconfig.
 87        :param subconfig_batch (BatchConfig): The batch subconfig.
 88        :param name (str): The name (keyphrase) of the config.
 89        """
 90        self.name = name
 91
 92        if not (template or name):
 93            raise ValueError("Template configs must have a name specified.")
 94
 95        if not template and (name):
 96            self.register(name)
 97
 98        self.dicom_type = dicom_type
 99        self.crop_coordinates = crop_coordinates
100        self.min_seg_confidence = min_seg_confidence
101
102        self.device = device
103        self.replace_old = replace_old
104        self.operation_type = operation_type
105        self.dev = dev
106
107        self.seg_export = seg_export
108
109        self.hip: HipConfig = subconfig_hip
110        self.trak: TrakConfig = subconfig_trak
111        self.visuals: VisualsConfig = subconfig_visuals
112        self.api: APIConfig = subconfig_api
113        self.batch: BatchConfig = subconfig_batch
114
115        self.test_data_passthrough = test_data_passthrough
116
117        if operation_type not in [
118            OperationType.SEG,
119            OperationType.LANDMARK,
120        ]:
121            raise ValueError(f"Invalid operation type: {operation_type}")
122
123    def register(
124        self,
125        name: str,
126        store: bool = True,
127        silent: bool = False,
128        live: bool = False,
129    ):
130        """
131        Register the config.
132
133        :param name (str): The name of the config.
134        :param store (bool): Whether to store the config
135                             for later retrieval.
136
137        """
138        self.name = name
139
140        # check if config already exists
141        if self.configs.get(name):
142            raise ValueError(f"Config {name} already exists.")
143
144        if not self.configs.get(name) and store:
145            self.configs[name] = {}
146
147        if store:
148            self.configs[name] = self
149
150        if live:
151            Config.live_config = self
152
153        # defaults need registering
154        if self.visuals.default_font_size:
155            self.visuals.font_h1 = ImageFont.truetype(
156                f"{RETUVE_DIR}/files/RobotoMono-Regular.ttf",
157                self.visuals.default_font_size,
158            )
159
160            self.visuals.font_h2 = ImageFont.truetype(
161                f"{RETUVE_DIR}/files/RobotoMono-Regular.ttf",
162                self.visuals.default_font_size,
163            )
164
165        self.batch.register()
166
167        register_config_dirs(self)
168
169        if not self.api.api_token:
170            ValueError("API token must be set.")
171
172        if not silent:
173            ulogger.info(f"Registered config for {name}")
174
175    def unregister(self, silent: bool = False):
176        """
177        Unregister the config.
178        """
179        if self.name in self.configs:
180            del self.configs[self.name]
181
182        if not silent:
183            ulogger.info(f"Unregistered config for {self.name}")
184
185    def get_copy(self) -> "Config":
186        """
187        Get a copy of the config.
188
189        :return: A copy of the config.
190        """
191        return copy.deepcopy(self)
192
193    def inject_global_config(self, username, password):
194        """
195        Inject the global config into the config.
196
197        :param username (str): The username.
198        :param password (str): The password.
199        """
200        Config.global_config = GlobalConfig(username, password)
201
202    @classmethod
203    def get_configs(self) -> List[Tuple[str, "Config"]]:
204        """
205        Get all registered/stored configs.
206
207        :return: A list of tuples of name and config.
208        """
209        return [(name, config) for name, config, in self.configs.items()]
210
211    @classmethod
212    def get_config(cls, name: str) -> "Config":
213        """
214        Get a config by name.
215
216        :param name (str): The name of the config.
217
218        :return: The config.
219        """
220        # check if name is of type Config
221        if isinstance(name, Config):
222            return name
223
224        if not cls.configs.get(name):
225            raise ValueError(f"Config {name} does not exist.")
226
227        return cls.configs[name]
228
229    @classmethod
230    def keyphrase_exists(cls, name: str) -> bool:
231        """
232        Check if a keyphrase exists in the configs.
233
234        :param name (str): The name of the keyphrase.
235
236        :return: Whether the keyphrase exists.
237        """
238        lower_keys = [key.lower() for key in cls.configs.keys()]
239        return name.lower() in lower_keys

Configuration class.

Config( dicom_type: radstract.data.dicom.utils.DicomTypes, crop_coordinates: Tuple[float], template: bool, min_seg_confidence: float, device: Union[torch.device, str, int, NoneType], operation_type: retuve.keyphrases.enums.OperationType, dev: bool, replace_old: bool, seg_export: bool, test_data_passthrough: bool, subconfig_hip: retuve.keyphrases.subconfig.HipConfig, subconfig_trak: retuve.keyphrases.subconfig.TrakConfig, subconfig_visuals: retuve.keyphrases.subconfig.VisualsConfig, subconfig_api: retuve.keyphrases.subconfig.APIConfig, subconfig_batch: retuve.keyphrases.subconfig.BatchConfig, name=None)
 51    def __init__(
 52        self,
 53        dicom_type: DicomTypes,
 54        crop_coordinates: Tuple[float],
 55        template: bool,
 56        min_seg_confidence: float,
 57        device: Device,
 58        operation_type: OperationType,
 59        dev: bool,
 60        replace_old: bool,
 61        seg_export: bool,
 62        test_data_passthrough: bool,
 63        subconfig_hip: HipConfig,
 64        subconfig_trak: TrakConfig,
 65        subconfig_visuals: VisualsConfig,
 66        subconfig_api: APIConfig,
 67        subconfig_batch: BatchConfig,
 68        name=None,
 69    ):
 70        """
 71        Initialize Config.
 72
 73        :param dicom_type (DicomTypes): The type of dicom to use.
 74        :param crop_coordinates (Tuple[float]): The crop coordinates.
 75        :param template (bool): Whether this is a template config.
 76        :param min_seg_confidence (float): The minimum segmentation confidence.
 77        :param device (Device): The device to use.
 78        :param operation_type (OperationType): The operation type.
 79        :param dev (bool): Whether to use dev mode.
 80        :param replace_old (bool): Whether to replace old files.
 81        :param seg_export (bool): Whether to export segmentation.
 82        :param test_data_passthrough (bool): Whether to pass through test data.
 83        :param subconfig_hip (HipConfig): The hip subconfig.
 84        :param subconfig_trak (TrakConfig): The trak subconfig.
 85        :param subconfig_visuals (VisualsConfig): The visuals subconfig.
 86        :param subconfig_api (APIConfig): The api subconfig.
 87        :param subconfig_batch (BatchConfig): The batch subconfig.
 88        :param name (str): The name (keyphrase) of the config.
 89        """
 90        self.name = name
 91
 92        if not (template or name):
 93            raise ValueError("Template configs must have a name specified.")
 94
 95        if not template and (name):
 96            self.register(name)
 97
 98        self.dicom_type = dicom_type
 99        self.crop_coordinates = crop_coordinates
100        self.min_seg_confidence = min_seg_confidence
101
102        self.device = device
103        self.replace_old = replace_old
104        self.operation_type = operation_type
105        self.dev = dev
106
107        self.seg_export = seg_export
108
109        self.hip: HipConfig = subconfig_hip
110        self.trak: TrakConfig = subconfig_trak
111        self.visuals: VisualsConfig = subconfig_visuals
112        self.api: APIConfig = subconfig_api
113        self.batch: BatchConfig = subconfig_batch
114
115        self.test_data_passthrough = test_data_passthrough
116
117        if operation_type not in [
118            OperationType.SEG,
119            OperationType.LANDMARK,
120        ]:
121            raise ValueError(f"Invalid operation type: {operation_type}")

Initialize Config.

Parameters
  • dicom_type (DicomTypes): The type of dicom to use.
  • crop_coordinates (Tuple[float]): The crop coordinates.
  • template (bool): Whether this is a template config.
  • min_seg_confidence (float): The minimum segmentation confidence.
  • device (Device): The device to use.
  • operation_type (OperationType): The operation type.
  • dev (bool): Whether to use dev mode.
  • replace_old (bool): Whether to replace old files.
  • seg_export (bool): Whether to export segmentation.
  • test_data_passthrough (bool): Whether to pass through test data.
  • subconfig_hip (HipConfig): The hip subconfig.
  • subconfig_trak (TrakConfig): The trak subconfig.
  • subconfig_visuals (VisualsConfig): The visuals subconfig.
  • subconfig_api (APIConfig): The api subconfig.
  • subconfig_batch (BatchConfig): The batch subconfig.
  • name (str): The name (keyphrase) of the config.
configs = {}
live_config = None
name
dicom_type
crop_coordinates
min_seg_confidence
device
replace_old
operation_type
dev
seg_export
test_data_passthrough
def register( self, name: str, store: bool = True, silent: bool = False, live: bool = False):
123    def register(
124        self,
125        name: str,
126        store: bool = True,
127        silent: bool = False,
128        live: bool = False,
129    ):
130        """
131        Register the config.
132
133        :param name (str): The name of the config.
134        :param store (bool): Whether to store the config
135                             for later retrieval.
136
137        """
138        self.name = name
139
140        # check if config already exists
141        if self.configs.get(name):
142            raise ValueError(f"Config {name} already exists.")
143
144        if not self.configs.get(name) and store:
145            self.configs[name] = {}
146
147        if store:
148            self.configs[name] = self
149
150        if live:
151            Config.live_config = self
152
153        # defaults need registering
154        if self.visuals.default_font_size:
155            self.visuals.font_h1 = ImageFont.truetype(
156                f"{RETUVE_DIR}/files/RobotoMono-Regular.ttf",
157                self.visuals.default_font_size,
158            )
159
160            self.visuals.font_h2 = ImageFont.truetype(
161                f"{RETUVE_DIR}/files/RobotoMono-Regular.ttf",
162                self.visuals.default_font_size,
163            )
164
165        self.batch.register()
166
167        register_config_dirs(self)
168
169        if not self.api.api_token:
170            ValueError("API token must be set.")
171
172        if not silent:
173            ulogger.info(f"Registered config for {name}")

Register the config.

Parameters
  • name (str): The name of the config.
  • store (bool): Whether to store the config for later retrieval.
def unregister(self, silent: bool = False):
175    def unregister(self, silent: bool = False):
176        """
177        Unregister the config.
178        """
179        if self.name in self.configs:
180            del self.configs[self.name]
181
182        if not silent:
183            ulogger.info(f"Unregistered config for {self.name}")

Unregister the config.

def get_copy(self) -> Config:
185    def get_copy(self) -> "Config":
186        """
187        Get a copy of the config.
188
189        :return: A copy of the config.
190        """
191        return copy.deepcopy(self)

Get a copy of the config.

Returns

A copy of the config.

def inject_global_config(self, username, password):
193    def inject_global_config(self, username, password):
194        """
195        Inject the global config into the config.
196
197        :param username (str): The username.
198        :param password (str): The password.
199        """
200        Config.global_config = GlobalConfig(username, password)

Inject the global config into the config.

Parameters
  • username (str): The username.
  • password (str): The password.
@classmethod
def get_configs(self) -> List[Tuple[str, Config]]:
202    @classmethod
203    def get_configs(self) -> List[Tuple[str, "Config"]]:
204        """
205        Get all registered/stored configs.
206
207        :return: A list of tuples of name and config.
208        """
209        return [(name, config) for name, config, in self.configs.items()]

Get all registered/stored configs.

Returns

A list of tuples of name and config.

@classmethod
def get_config(cls, name: str) -> Config:
211    @classmethod
212    def get_config(cls, name: str) -> "Config":
213        """
214        Get a config by name.
215
216        :param name (str): The name of the config.
217
218        :return: The config.
219        """
220        # check if name is of type Config
221        if isinstance(name, Config):
222            return name
223
224        if not cls.configs.get(name):
225            raise ValueError(f"Config {name} does not exist.")
226
227        return cls.configs[name]

Get a config by name.

Parameters
  • name (str): The name of the config.
Returns

The config.

@classmethod
def keyphrase_exists(cls, name: str) -> bool:
229    @classmethod
230    def keyphrase_exists(cls, name: str) -> bool:
231        """
232        Check if a keyphrase exists in the configs.
233
234        :param name (str): The name of the keyphrase.
235
236        :return: Whether the keyphrase exists.
237        """
238        lower_keys = [key.lower() for key in cls.configs.keys()]
239        return name.lower() in lower_keys

Check if a keyphrase exists in the configs.

Parameters
  • name (str): The name of the keyphrase.
Returns

Whether the keyphrase exists.