Source code for model.algorithms._alg

# -*- coding: utf-8 -*-
"""
This is Algorithm master class and all algorithms must inherit from it.
"""
import collections
from PyQt5.QtCore import QObject, pyqtSlot

__authors__ = {"Dennis Groß": "gdennis91@googlemail.com",
               "Pavel Shkadzko": "p.shkadzko@gmail.com",
               "Philipp Reichert": "prei@me.com"}


[docs]class Algorithm: def __init__(self): """ Public Attributes: | *modified*: True if Algorithm settings were modified, true by default | *belongs*: A step name to which current algorithm belongs | *float_sliders*: a list containing all FloatSlider created by the user | *integer_sliders*: a list containing all InterSlider created by the user | *checkboxes*: a list containing all Checkboxes created by the user | *drop_downs*: a list containing all DropDowns created by the user | *result*: a tuple containing all resulting data produced or modified by the algorithm | *store_image*: this flag is per default false and indicates if the calculated image from this algorithm should be stores at the default location after processing. | *icon* (str): Path to custom icon to be used for this algorithm. Returns: | *object*: instance of the algorithm object """ # QObject.__init__(self) self.modified = True self.integer_sliders = [] self.float_sliders = [] self.checkboxes = [] self.drop_downs = [] self.name = "" self.icon = "./assets/images/missing.png" self.parent = "" self.result = {"img": None, "graph": None} self.store_image = False
[docs] def belongs(self): """ Identifies the category to which this algorithm implementation is assoc iated with. Therefore you the contributor returns a string yielding the name of the associated category. E.g. we have an algorithm "blur" which is created through implementing the abstract class Algorithm. In "blur" we override the belongs method to return "preprocessing" to associate the "blur" algorithm instance with the category "preprocessing". Returns: | *self.parent*: The string identifier to which category this algorithm belongs to """ return self.parent
[docs] def process(self, input_data): """ Contains the logic of the implemented algorithm. While computing the pipeline each algorithm will be called with its process method giving the output image from the previous algorithm processed in the pipeline The images are used to draw the result of each algorithm in the left section of the UI. Therefore the contributor should return an image itself at the end of this method. By default this method raises an error if the user is not overriding his own process method. Args: | *input_data*: a tuple which contains all relevant arguments found in the results of the previous processed algorithm. As common in the pipeline pattern, the successors always get called with the information the predecessor created. The first element in input_data should always be image array, the second element is reserved for graph. This is why algorithm process methods operate on args indeces (args[0] or args[1]). Please consider this in case you decide to add an algorithm which produces something different than an image array or networkx graph object. """ raise NotImplementedError
[docs] def get_name(self): """ This method returns the name of the implemented algorithm. E.g. int case the contributor is implementing a "watershed" algorithm, his get_name method should return "watershed". By default this method raises an error if the user is not overriding his own get_name method. Returns: | *self.name*: The name of the algorithm specified in this implementation. """ if self.name: return self.name else: raise NotImplementedError
[docs] def set_icon(self, icon_path): """ Args: | *icon_path*: The path to the icon to be used """ self.icon = icon_path
[docs] def get_icon(self): """ Returns: | *icon_path*: The path to the icon to be used """ return self.icon
[docs] def report_pip(self): """ This method returns a dictionary which contains all relevant algorithm information and returns it to the pipeline along with the algorithm name. The pipeline needs this information to create a json representation of the algorithm. It will encode the dic as following: E.g. blur : {"type" : "preprocessing", "kernelsize" : 2.5} The encoding of the dic to json will be done by the pipeline which collects the dictionary of each algorithm in the processing list. Returns: | *self.name, collections.OrderedDict* (list): A tuple consisting of the name of the algorithm and the dic containing all relevant information about the algorithm which need to be stored on the filesystem for the pipeline.json. """ list = [["type", self.parent], ["store_image", self.store_image]] for int_slider in self.integer_sliders: list.append([int_slider.name, int_slider.value]) for float_slider in self.float_sliders: list.append([float_slider.name, float_slider.value]) for checkbox in self.checkboxes: list.append([checkbox.name, checkbox.value]) for dropdown in self.drop_downs: list.append([dropdown.name, dropdown.value]) return self.name, collections.OrderedDict(list)
[docs] def unset_modified(self): """ Set modified to False """ self.modified = False
[docs] def set_modified(self): """ Set modified to True """ self.modified = True
@pyqtSlot(bool)
[docs] def set_store_image(self, state): self.store_image = state
[docs] def find_ui_element(self, name): """ This method helps the json parser to find the ui elements with the given name Args: |name: name of the ui element we are looking for Returns: """ for int_slider in self.integer_sliders: if int_slider.name == name: return int_slider for float_slider in self.float_sliders: if float_slider.name == name: return float_slider # checkboxes are optional if self.checkboxes: for checkbox in self.checkboxes: if checkbox.name == name: return checkbox else: return None for dropdown in self.drop_downs: if dropdown.name == name: return dropdown raise FileNotFoundError("could not find ui element: " + name)
[docs]class IntegerSlider: """ A class defining a slider of type int to display in the algorithm detail section of the UI. After calling the IntegerSlider constructor, the program automatically creates ui widgets as wellas qt slots and signals to connect this slider with the UI. """ def __init__(self, name, lower, upper, step_size, default): """ Args: | *name*: The name to be displayed in the UI - label of the slider | *lower*: The lower bound of the slider in the UI | *upper*: The upper bound of the slider in the UI | *step_size*: The amount of a slider step in the UI | *default*: The default value for the slider in the UI Returns: instance of an IntegerSlider object """ self.step_size = step_size self.default = default self.value = default self.lower = lower self.upper = upper self.name = name @pyqtSlot(int)
[docs] def set_value(self, arg1): """ The set_value method is used by the UI and the batch-mode of NEFI as an input source of selected values for this particular slider instance. The @pyqtSlot(int) decoration declares this method as as QT-Slot. To get more information about Slots and Signals in QT read about it in the official QT documentation. Args: | *arg1*: the integer value selected in the ui or the pipeline in batch-mode """ if arg1 > self.upper or arg1 < self.lower: raise AssertionError("Given parameter " + str(arg1) +" for " + str(self.name) + " setting is outside range. [" + str(self.lower) + ", " + str(self.upper) + "]") self.value = arg1
[docs]class FloatSlider: """ A class defining a slider of type float to display in the algorithm detail section of the UI. After calling the FloatSlider constructor, the program automatically creates ui widgets as well as qt slots and signals to connect this slider with the UI. """ def __init__(self, name, lower, upper, step_size, default): """ Args: | *name*: The name to be displayed in the UI - label of the slider | *lower*: The lower bound of the slider in the UI | *upper*: The upper bound of the slider in the UI | *step_size*: The amount of a slider step in the UI | *default*: The default value for the slider in the UI Returns: instance of an IntegerSlider object """ self.step_size = step_size self.default = default self.value = default self.lower = lower self.upper = upper self.name = name @pyqtSlot(float)
[docs] def set_value(self, arg1): """ The set_value method is used by the UI and the batch-mode of NEFI as an input source of selected values for this particular slider instance. The @pyqtSlot(int) decoration declares this method as as QT-Slot. To get more information about Slots and Signals in QT read about it in the official QT documentation. Args: | *arg1*: the integer value selected in the ui or the pipeline in batch-mode """ if arg1 > self.upper or arg1 < self.lower: raise AssertionError("Given parameter " + str(arg1) +" for " + str(self.name) + " setting is outside range. [" + str(self.lower) + ", " + str(self.upper) + "]") self.value = arg1
[docs]class CheckBox: """ A class defining a Checkbox of type boolean to display in the algorithm detail section of the UI. After calling the CheckBox constructor, the program automatically creates ui widgets as well as qt slots and signals to connect this checkbox with the UI. """ def __init__(self, name, default): """ Args: | *name*: The name of the checkbox to be displayed in the ui | *default*: The default value of the checkbox """ self.default = default self.value = default self.name = name @pyqtSlot(bool)
[docs] def set_value(self, arg1): """ The set_value method is used by the UI and the batch-mode of NEFI as an input source of selected values for this particular checkbox instance. The @pyqtSlot(bool) decoration declares this method as as QT-Slot. To get more information about Slots and Signals in QT read about it in the official QT documentation. Args: | *arg1*: the boolean value selected in the ui or the pipeline in batch-mode """ self.value = arg1