Source code for optimeed.core.tools

from optimeed.core.commonImport import *
import os
import numpy as np
import sys
import ast
import re
import operator
import inspect


[docs]class text_format:
[docs] PURPLE = '\033[95m'
[docs] CYAN = '\033[96m'
[docs] DARKCYAN = '\033[36m'
[docs] BLUE = '\033[94m'
[docs] GREEN = '\033[92m'
[docs] YELLOW = '\033[93m'
[docs] WHITE = '\033[30m'
[docs] RED = '\033[91m'
[docs] BOLD = '\033[1m'
[docs] UNDERLINE = '\033[4m'
[docs] END = '\033[0m'
[docs]def software_version(): MAJOR = 1.0 MINOR = 0.0 return MAJOR*10 + MINOR
# # Find an expression delimited by begin_char and end_char in theStr, and apply transformation replace_function # ex: find_and_replace('{', '}', 2*{x}, lambda str_in: str_in + "*2") returns 2*x*2
[docs]def find_and_replace(begin_char, end_char, theStr, replace_function): regex = '\\' + begin_char + '([^}]+)' + '\\' + end_char split_str = re.split(regex, theStr) # Replace chars are even new_str = '' for i in range(len(split_str)): if i % 2: new_str += str(replace_function(split_str[i])) else: new_str += str(split_str[i]) return new_str
[docs]def create_unique_dirname(dirname): base_dir = dirname index = 0 while os.path.isdir(dirname): dirname = base_dir + "_" + str(index) index += 1 os.makedirs(os.path.abspath(dirname)) return dirname
[docs]def applyEquation(objectIn, s): """ Apply literal expression based on an object :param objectIn: Object :param s: literal expression. Float variables taken from the object are written between {}, int between []. Example: s="{x}+{y}*2" if x and y are attributes of objectIn. :return: value (float) """ str_eq = find_and_replace("{", "}", s, lambda attr_in: "({})".format(float(rgetattr(objectIn, attr_in)))) str_eq = find_and_replace("[", "]", str_eq, lambda attr_in: "({})".format(int(rgetattr(objectIn, attr_in)))) return eval(str_eq)
[docs]def arithmeticEval(s): node = ast.parse(s, mode='eval') binOps = { ast.Add: operator.add, ast.Sub: operator.sub, ast.Mult: operator.mul, ast.Div: operator.truediv, ast.Mod: operator.mod, ast.USub: operator.neg } def _eval(in_node): if isinstance(in_node, ast.Expression): return _eval(in_node.body) elif isinstance(in_node, ast.Str): return in_node.s elif isinstance(in_node, ast.Num): return in_node.n elif isinstance(in_node, ast.BinOp): return binOps[type(in_node.op)](_eval(in_node.left), _eval(in_node.right)) elif isinstance(in_node, ast.Name): return float('inf') elif isinstance(in_node, ast.UnaryOp): return binOps[type(in_node.op)](_eval(in_node.operand)) else: raise TypeError('Unsupported type {}'.format(in_node)) return _eval(node.body)
[docs]def isNonePrintMessage(theObject, theMessage, show_type=SHOW_INFO): if theObject is None: printIfShown(theMessage, show_type) return True return False
[docs]def getPath_workspace(): thePath = os.path.abspath(os.getcwd() + '/Workspace') if not os.path.exists(thePath): os.makedirs(thePath) return thePath
[docs]def getLineInfo(lvl=1): filename = os.path.relpath(inspect.stack()[lvl][1], os.getcwd()) line = inspect.stack()[lvl][2] method = inspect.stack()[lvl][3] return filename, method, line
[docs]def printIfShown(theStr, show_type=SHOW_DEBUG, isToPrint=True, appendTypeName=True): if isToPrint: try: sys.stdout.isatty() if show_type == SHOW_WARNING: colourBegin = text_format.YELLOW # yellow if appendTypeName: colourBegin += 'Warning: ' elif show_type == SHOW_ERROR: colourBegin = text_format.RED if appendTypeName: colourBegin += 'ERROR: ' elif show_type == SHOW_INFO: colourBegin = text_format.BLUE if appendTypeName: colourBegin += 'Info: ' elif show_type == SHOW_DEBUG: colourBegin = text_format.WHITE if appendTypeName: colourBegin += 'Debug: ' else: colourBegin = '' colourEnd = '' if colourBegin is '' else '\033[0m' except AttributeError: # Not the original stdout that has not implemented that function :) :) :) colourBegin = '' colourEnd = '' if show_type in SHOW_CURRENT: file, method, line = getLineInfo(2) logstr = "\t[File: {}, Line: {}, Method: {}]".format(file, line, method) print(colourBegin + str(theStr) + colourEnd + logstr) return
[docs]def universalPath(thePath): return os.path.abspath(thePath)
[docs]def add_suffix_to_path(thePath, suffix): head, tail = os.path.split(thePath) base_name, extension = os.path.splitext(tail) newPath = head + '/' + base_name + suffix + extension return newPath
[docs]def get_object_attrs(obj): try: return obj.__dict__ except AttributeError: dico = {} try: for attr in obj.__slots__: dico[attr] = getattr(obj, attr) except AttributeError: pass # return {attr: getattr(obj, attr) for attr in obj.__slots__} return dico
[docs]def rsetattr(obj, attr, val): pre, _, post = attr.rpartition('.') # ex: "a.b.c" -> pre = a.b, ; post = c if pre: obj_returned = rgetattr(obj, pre) # , checkIndices=False) else: obj_returned = obj splitted = post.split('[') index_end_list = [] char_begin = attr if len(splitted) > 1: char_begin = splitted[0] for i in range(1, len(splitted)): index_end_list.append(splitted[i].replace(']', '').replace("'", '')) if len(index_end_list): curr_nested_obj = obj_returned for index in range(len(index_end_list)-1): try: curr_nested_obj = curr_nested_obj[index_end_list[index]] except (KeyError, TypeError, IndexError): curr_nested_obj = curr_nested_obj[int(index_end_list[index])] try: getattr(curr_nested_obj, char_begin)[index_end_list[-1]] = val except (KeyError, TypeError, IndexError): getattr(curr_nested_obj, char_begin)[int(index_end_list[-1])] = val else: setattr(obj_returned, post, val)
[docs]def rgetattr(obj, attr): """ Recursively get an attribute from object. Extends getattr method :param obj: object :param attr: attribute to get :return: """ attributes = attr.split('.') curr_object = obj for attribute in attributes: # Get end parentheses list_indices = [] splitted = attribute.split('[') if not splitted: splitted = [attribute] curr_object = getattr(curr_object, splitted[0]) if len(splitted) > 1: for i in range(1, len(splitted)): list_indices.append(splitted[i].replace(']', '').replace("'", '')) for item in list_indices: try: curr_object = curr_object[item] except (KeyError, TypeError, IndexError): curr_object = curr_object[int(item)] return curr_object
[docs]def indentParagraph(text_in, indent_level=1): rowsP = text_in.split("\n") if rowsP[-1] == '': rowsP = rowsP[0:-1] Pout = '' space = '' for i in range(indent_level): space += '\t' for element in rowsP: Pout += space + element + '\n' return Pout
# def from_scattered_to_surf(dataX, dataY, dataZ, nPoints): # X = np.arange(min(dataX), max(dataX), (max(dataX)-min(dataX))/nPoints) # Y = np.arange(min(dataY), max(dataY), (max(dataY)-min(dataY))/nPoints) # X, Y = np.meshgrid(X, Y) # Z = griddata((dataX, dataY), dataZ, (X, Y), method='linear') # return X, Y, Z
[docs]def truncate(theStr, truncsize): return theStr[:truncsize] + (theStr[truncsize:] and '..')
[docs]def str_all_attr(theObject, max_recursion_level): def set_attribute_color(strAttribute, level): if level == 0: color = text_format.GREEN + text_format.BOLD elif level == 1: color = text_format.DARKCYAN else: color = text_format.BLUE return color + strAttribute + text_format.END def _str_all_attr(_theObject, _max_recursion_level, curr_level): temp = vars(_theObject) theStr = '' object_keys = list() variable_keys = list() list_keys = list() truncsize = 99999999999999999999 for key in temp: _theObject = temp[key] if getattr(_theObject, '__dict__', None) is not None: object_keys.append(key) else: if isinstance(_theObject, list): list_keys.append(key) else: variable_keys.append(key) for key in variable_keys: theVariable = temp[key] theStr += set_attribute_color(key, curr_level) + '\t:\t' + truncate(str(theVariable), truncsize) + '\n' for key in list_keys: theList = temp[key] theStr += set_attribute_color(key, curr_level) + '\t:\t' for index, item in enumerate(theList): if getattr(item, '__dict__', None) is not None: if index == 0: theStr += '\n' theStr += indentParagraph("Item " + str(index) + " -", 1) theStr += indentParagraph(_str_all_attr(item, _max_recursion_level, curr_level+1), 2) else: theStr += truncate(str(item), truncsize) + ', ' if theStr.endswith('.., '): break theStr += '\n' if curr_level >= _max_recursion_level: return theStr else: for key in object_keys: _theObject = temp[key] theStr += set_attribute_color(key, curr_level) + ":\n" theStr += indentParagraph(_str_all_attr(_theObject, _max_recursion_level, curr_level+1), 1) return theStr return _str_all_attr(theObject, max_recursion_level, 0)
[docs]def get_2D_pareto(xList, yList, max_X=True, max_Y=True): coef_x = 1 coef_y = 1 if max_X: coef_x = -1 if max_Y: coef_y = -1 # assign all in new array and ignore values mapping = [] coords = [] for i in range(len(xList)): if not np.isnan(xList[i]) and not np.isnan(yList[i]): coords.append([coef_x * xList[i], coef_y * yList[i]]) mapping.append(i) costs = np.array(coords) is_efficient = np.ones(costs.shape[0], dtype=bool) for i, c in enumerate(costs): if is_efficient[i]: is_efficient[is_efficient] = np.any(costs[is_efficient] < c, axis=1) # Keep any point with a lower cost is_efficient[i] = True # And keep self # Create new array newx = [] newy = [] indices = [] for index, isPareto in enumerate(is_efficient): if isPareto: goodIndex = mapping[index] newx.append(xList[goodIndex]) newy.append(yList[goodIndex]) indices.append(goodIndex) return newx, newy, indices
[docs]def get_ND_pareto(objectives_list, are_maxobjectives_list=None): """ Return the N-D pareto front :param objectives_list: list of list of objectives: example [[0,1], [1,1], [2,2]] :param are_maxobjectives_list: for each objective, tells if they are to be maximized or not: example [True, False]. Default: False :return: extracted_pareto, indices: list of [x, y, ...] points forming the pareto front, and list of the indices of these points from the base list. """ numberOfObjectives = len(objectives_list[0]) if are_maxobjectives_list is None: are_maxobjectives_list = [False]*numberOfObjectives coef_list = [-1 if isMaxObjective else 1 for isMaxObjective in are_maxobjectives_list] # assign all in new array and ignore values mapping = [] coords = [] for index_objective, objectives in enumerate(objectives_list): mustAdd = True for objective in objectives: if np.isnan(objective): mustAdd = False if mustAdd: coords.append([coef_list[i]*objectives[i] for i in range(numberOfObjectives)]) mapping.append(index_objective) costs = np.array(coords) is_efficient = np.ones(costs.shape[0], dtype=bool) for i, c in enumerate(costs): if is_efficient[i]: is_efficient[is_efficient] = np.any(costs[is_efficient] < c, axis=1) # Keep any point with a lower cost is_efficient[i] = True # And keep self # Create new array extracted_pareto = list() indices = [] for index, isPareto in enumerate(is_efficient): if isPareto: goodIndex = mapping[index] extracted_pareto.append(objectives_list[goodIndex]) indices.append(goodIndex) return extracted_pareto, indices
[docs]def delete_indices_from_list(indices, theList): """ Delete elements from list at indices :param indices: list :param theList: list """ sorted_indices = list(dict.fromkeys(list(np.sort(indices)))) sorted_indices.reverse() for index in sorted_indices: del theList[index]