Documentation for PhotonRegistry
Helper class to manage the PHOTONAI Element Register.
Use it to add and remove items into the register. You can also retrieve information about items and its hyperparameters.
Every item in the register is encoded by a string literal that points to a python class and its namespace. You can access the python class via the string literal. The class PhotonElement imports and instantiates the class for you.
Examples:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
|
__init__(self, custom_elements_folder=None)
special
Initialize the object.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
custom_elements_folder |
str |
Path to folder with custom element in it. |
None |
Source code in photonai/base/registry/registry.py
def __init__(self, custom_elements_folder: str = None):
"""
Initialize the object.
Parameters:
custom_elements_folder:
Path to folder with custom element in it.
"""
self.current_folder = os.path.dirname(os.path.abspath(inspect.getfile(inspect.currentframe())))
self.module_path = os.path.join(self.current_folder, "modules")
if not os.path.isdir(self.module_path):
os.mkdir(self.module_path)
# update list with available sub_elements
self._list_available_modules()
PhotonRegistry.CUSTOM_ELEMENTS_FOLDER = custom_elements_folder
self._load_custom_folder(custom_elements_folder)
if len(PhotonRegistry.ELEMENT_DICTIONARY) == 0 or \
PhotonRegistry.ELEMENT_DICTIONARY == PhotonRegistry.CUSTOM_ELEMENTS:
PhotonRegistry.ELEMENT_DICTIONARY.update(self.get_package_info())
delete(self, photon_name)
Delete Element from JSON file.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
photon_name |
str |
The string literal encoding the class. |
required |
Source code in photonai/base/registry/registry.py
def delete(self, photon_name: str):
"""
Delete Element from JSON file.
Parameters:
photon_name:
The string literal encoding the class.
"""
if photon_name in PhotonRegistry.CUSTOM_ELEMENTS:
del PhotonRegistry.CUSTOM_ELEMENTS[photon_name]
self._write_to_json(PhotonRegistry.CUSTOM_ELEMENTS)
logger.info('Removing the PipelineElement named "{0}" from CustomElements.json.'.format(photon_name))
else:
logger.info('Cannot remove "{0}" from CustomElements.json. Element has not been registered before.'.format(photon_name))
get_package_info(self, photon_package=['PhotonCore'])
Collect all registered elements from JSON file.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
photon_package |
list |
The names of the PHOTONAI submodules for which the elements should be retrieved. |
['PhotonCore'] |
Returns:
Type | Description |
---|---|
dict |
Dict of registered elements. |
Source code in photonai/base/registry/registry.py
def get_package_info(self, photon_package: list = PHOTON_REGISTRIES) -> dict:
"""
Collect all registered elements from JSON file.
Parameters:
photon_package:
The names of the PHOTONAI submodules for which
the elements should be retrieved.
Returns:
Dict of registered elements.
"""
class_info = dict()
for package in photon_package:
content = self._load_json(package)
for idx, key in enumerate(content):
class_path, class_name = os.path.splitext(content[key][0])
if idx == 0 and package not in ["PhotonCore", "CustomElements"]:
# try to import something from module.
# if that fails. drop this shit.
try:
imported_module = importlib.import_module(class_path)
desired_class = getattr(imported_module, class_name[1:])
custom_element = desired_class()
except (AttributeError, ModuleNotFoundError) as e:
logger.error(e)
logger.error("Could not import from package {}. Deleting json.".format(package))
self.delete_module(package)
class_info[key] = class_path, class_name[1:]
return class_info
info(self, photon_name)
Show information for object that is encoded by this name.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
photon_name |
str |
The string literal which accesses the class. |
required |
Source code in photonai/base/registry/registry.py
def info(self, photon_name: str):
"""
Show information for object that is encoded by this name.
Parameters:
photon_name:
The string literal which accesses the class.
"""
content = self.get_package_info() # load existing json
if photon_name in content:
element_namespace, element_name = content[photon_name]
print("----------------------------------")
print("Name: " + element_name)
print("Namespace: " + element_namespace)
print("----------------------------------")
try:
imported_module = __import__(element_namespace, globals(), locals(), element_name, 0)
desired_class = getattr(imported_module, element_name)
base_element = desired_class()
print("Possible Hyperparameters as derived from constructor:")
class_args = inspect.signature(base_element.__init__)
for item, more_info in class_args.parameters.items():
print("{:<35} {:<75}".format(item, str(more_info)))
print("----------------------------------")
except Exception as e:
logger.error(e)
logger.error("Could not instantiate class " + element_namespace + "." + element_name)
else:
logger.error("Could not find element " + photon_name)
list_available_elements(self, photon_package=['PhotonCore'])
Print info about all items that are registered for the PHOTONAI submodule to the console.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
photon_package |
list |
The names of the PHOTON submodules for which the elements should be retrieved. |
['PhotonCore'] |
Source code in photonai/base/registry/registry.py
def list_available_elements(self, photon_package: list = PHOTON_REGISTRIES):
"""
Print info about all items that are registered for the PHOTONAI
submodule to the console.
Parameters:
photon_package:
The names of the PHOTON submodules for which
the elements should be retrieved.
"""
if isinstance(photon_package, str):
photon_package = [photon_package]
for package in photon_package:
content = self._load_json(package)
if len(content) > 0:
print('\n' + package)
for k, v in sorted(content.items()):
class_info, package_type = v
print("{:<35} {:<75} {:<5}".format(k, class_info, package_type))
register(self, photon_name, class_str, element_type)
Save element information to the JSON file.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
photon_name |
str |
The string literal with which you want to access the class. |
required |
class_str |
str |
The namespace of the class, like in the import statement. |
required |
element_type |
str |
Can be 'Estimator' or 'Transformer' |
required |
Source code in photonai/base/registry/registry.py
def register(self, photon_name: str, class_str: str, element_type: str):
"""
Save element information to the JSON file.
Parameters:
photon_name:
The string literal with which you want to access the class.
class_str:
The namespace of the class, like in the import statement.
element_type:
Can be 'Estimator' or 'Transformer'
"""
# check if folder exists
if not PhotonRegistry.CUSTOM_ELEMENTS_FOLDER:
raise ValueError("To register an element, specify a custom elements folder when instantiating the registry "
"module. Example: registry = PhotonRegistry('/MY/CUSTOM/ELEMENTS/FOLDER)")
if not element_type == "Estimator" and not element_type == "Transformer":
raise ValueError("Variable element_type must be 'Estimator' or 'Transformer'")
duplicate = self._check_duplicate(photon_name=photon_name, class_str=class_str, content=PhotonRegistry.CUSTOM_ELEMENTS)
if not duplicate:
python_file = os.path.join(PhotonRegistry.CUSTOM_ELEMENTS_FOLDER, class_str.split('.')[0] + '.py')
if not os.path.isfile(python_file):
raise FileNotFoundError("Couldn't find python file {} in your custom elements folder. "
"Please copy your file into this folder first!".format(python_file))
# add new element
PhotonRegistry.CUSTOM_ELEMENTS[photon_name] = class_str, element_type
# write back to file
self._write_to_json(PhotonRegistry.CUSTOM_ELEMENTS)
logger.info('Adding PipelineElement ' + class_str + ' to CustomElements.json as "' + photon_name + '".')
# activate custom elements
self.activate()
# check custom element
logger.info("Running tests on custom element...")
return self._run_tests(photon_name, element_type)
else:
logger.error('Could not register element!')