Skip to content
Snippets Groups Projects
Commit e41690b9 authored by Lukas Müller's avatar Lukas Müller
Browse files

Merge branch 'cmdows_dev_0.5'. Added further test cases

# Conflicts:
# pyKADMOS/scripts/WP6_TUDWingDesign_work.py


Former-commit-id: 7271871dae229b297c3166fac454e4931526a0ec
parents e3a044b7 bc7f0ca9
No related branches found
No related tags found
No related merge requests found
Pipeline #192595 canceled
Showing
with 6923 additions and 6312 deletions
......@@ -9,8 +9,8 @@ import sys
import itertools
import filecmp
import time
import ast
import copy
import ast
 
import shutil
import distutils.util
......@@ -38,7 +38,7 @@ from pyKADMOS.sample.rce import RceWorkflow
from pyKADMOS.sample.utilities import transform_data_into_strings, transform_string_into_format, extend_list_uniquely,\
export_as_json, move_and_open, make_camel_case, unmake_camel_case, get_list_entries, open_file, Child, ChildGroup,\
recursively_empty, format_string_for_d3js, get_unique_friendly_id, ChildSequence, remove_if_exists,\
recursively_stringify
recursively_stringify, make_plural, recursively_dictify
from pyKADMOS.sample.utilities import color_list, test_attr_cond, hex_to_rgb
 
from pyKADMOS.sample import prompt_utilities as PRO
......@@ -1924,6 +1924,7 @@ class KadmosGraph(nx.DiGraph):
for node, data in self.nodes_iter(data=True):
id = self.in_degree(node)
od = self.out_degree(node)
if data['category'] == 'variable':
if id == 0 and od == 0:
data['subcategory'] = 'hole'
......@@ -2994,13 +2995,13 @@ class KadmosGraph(nx.DiGraph):
modification = 'KADMOS export of a repository connectivity graph (RCG).'
if MPG:
MPG = None
warnings.warn('The RCG is given with an MPG. The MPG will be ignored.', Warning)
logger.warning('The RCG is given with an MPG. The MPG will be ignored.')
elif isinstance(self, FundamentalProblemGraph):
graph = FundamentalProblemGraph(self)
modification = 'KADMOS export of a fundamental problem graph (FPG).'
if MPG:
MPG = None
warnings.warn('The FPG is given with an MPG. The MPG will be ignored.', Warning)
logger.warning('The FPG is given with an MPG. The MPG will be ignored.')
elif isinstance(self, MdaoDataGraph):
graph = MdaoDataGraph(self)
modification = 'KADMOS Export of a mdao data graph (MDG) graph.'
......@@ -3010,12 +3011,16 @@ class KadmosGraph(nx.DiGraph):
 
# Check the graph validity
if isinstance(graph, FundamentalProblemGraph) or isinstance(graph, MdaoDataGraph):
if not graph.check():
try:
check = graph.check()
except:
check = False
if not check:
if kadmos_check_critical:
raise AssertionError('The graph is not valid according to KADMOS.')
raise IOError('The graph is not valid according to KADMOS.')
else:
warnings.warn('The graph is not valid according to KADMOS.'
'The validity of the CMDOWS output is not guaranteed.', Warning)
logger.warning('The graph is not valid according to KADMOS.'
'The validity of the CMDOWS output is not guaranteed.')
 
# Set basic variables and create CMDOWS element
cmdows_version = str(self.CMDOWS_VERSION)
......@@ -3144,7 +3149,7 @@ class KadmosGraph(nx.DiGraph):
Child(cmdows_problem_role, 'parameterUID', graph_problem_role)
for cmdows_problem_role_attr in cmdows_parameterDef[1]:
if cmdows_problem_role_attr == 'samples':
# TODO: Make more feneric for all lists
# TODO: Make more generic for all lists
# Create e.g. problemDefinition/problemRoles/parameters/designVariables/designVariable/samples
cmdows_samples = Child(cmdows_problem_role, 'samples')
if graph.node[graph_problem_role].get(cmdows_problem_role_attr) is not None:
......@@ -3212,7 +3217,7 @@ class KadmosGraph(nx.DiGraph):
# Create architectureElements/parameters/...
for architecture_roles_var in graph.ARCHITECTURE_ROLES_VARS:
cmdows_parameter = Child(cmdows_parameters,
make_camel_case(architecture_roles_var, make_plural=True))
make_camel_case(architecture_roles_var, make_plural_option=True))
graph_parameter_nodes = graph.find_all_nodes(attr_cond=['architecture_role', '==', architecture_roles_var])
for graph_parameter_node in graph_parameter_nodes:
cmdows_parameter_node = Child(cmdows_parameter, make_camel_case(architecture_roles_var))
......@@ -3250,7 +3255,7 @@ class KadmosGraph(nx.DiGraph):
for architecture_roles_fun in architecture_roles_funs:
nodes = graph.find_all_nodes(attr_cond=['architecture_role', '==', str(architecture_roles_fun)])
cmdows_analyses = Child(cmdows_executable_blocks, make_camel_case(architecture_roles_fun,
make_plural=True))
make_plural_option=True))
for node in nodes:
cmdows_analysis = Child(cmdows_analyses, make_camel_case(architecture_roles_fun))
Child(cmdows_analysis, 'relatedExecutableBlockUID', node)
......@@ -4133,10 +4138,31 @@ class KadmosGraph(nx.DiGraph):
if remove_after_compress:
shutil.rmtree(vispack_folder)
 
def expand_node(self, node_name, elements):
"""
Function to expand and clean-up a certain element of a specific node when a _ui_d is given
"""
# TODO: Edit docstring
# TODO: Add input assertions
for element in elements:
graph_element_name = make_plural(unmake_camel_case(element[0], '_'))
initial_element_data = self.node[node_name].get(graph_element_name)
if initial_element_data is not None:
for data_key, data_value in initial_element_data.iteritems():
for sub_data_key, sub_data_value in data_value.iteritems():
if sub_data_key.endswith('_ui_d'):
new_subelement_id = '/' + sub_data_value.split('/', 1)[1]
new_subelement_data = dict(zip(element[1], [self.node[new_subelement_id].get(e) for e in element[1]]))
self.node[node_name][graph_element_name][new_subelement_id] = new_subelement_data
del self.node[node_name][graph_element_name][data_key]
return self.node[node_name]
 
def load_from_cmdows(filename, source_folder=None, kadmos_check_critical=True):
"""
Method to load a KadmosGraph object from a CMDOWS file. Right now can handle RCG and FPG.
Method to load a KadmosGraph object from a CMDOWS file. Can handle RCGs and FPGs right now.
 
:param filename: name of the file to be opened
:type filename: basestring
......@@ -4192,14 +4218,15 @@ def load_from_cmdows(filename, source_folder=None, kadmos_check_critical=True):
schema = etree.XMLSchema(etree.XML(webcontent))
result = schema.validate(cmdows)
if not result:
warnings.warn('The CMDOWS file ' + filename +
' does not adhere to CMDOWS schema version ' + str(graph.CMDOWS_VERSION) + '.', Warning)
logger.warning('The CMDOWS file ' + filename +
' does not adhere to CMDOWS schema version ' + str(graph.CMDOWS_VERSION) + '.')
 
# TODO: Load header info?
 
# Set kb_path in order to have a valid graph
# TODO: Remove kb_path from validity check
graph.graph['kb_path'] = 'unknown'
kb_path = 'unknown'
graph.graph['kb_path'] = kb_path
 
# Create variable nodes
for variable in cmdows.findall('parameters/parameter'):
......@@ -4252,14 +4279,16 @@ def load_from_cmdows(filename, source_folder=None, kadmos_check_critical=True):
else:
arr = list()
for cmdows_block in list(cmdows_blocks):
# TODO: Check if selection of node is unambiguous
graph.node[cmdows_block.text]['problem_role'] = role[:-5]
if graph.node.get(cmdows_block.text) == None:
# Add note if it does not exist yet
# TODO: Maybe load architecture elements before problem definition
graph.add_node(cmdows_block.text, category='function')
graph.node[cmdows_block.text]['problem_role'] = role
arr.append(cmdows_block.text)
graph.graph['problem_formulation']['function_ordering'][role] = arr
 
# Add attributes to the variable nodes
# TODO: Get array from somewhere else
variable_types = ['designVariables', 'objectiveVariables', 'constraintVariables', 'stateVariables']
variable_types = [make_plural(role[0]) for role in graph.CMDOWS_ROLES_DEF]
for variable_type in variable_types:
cmdows_variables = cmdows_problem_roles.find('parameters/'+variable_type)
if cmdows_variables is not None:
......@@ -4279,43 +4308,97 @@ def load_from_cmdows(filename, source_folder=None, kadmos_check_critical=True):
cmdows_sample_data[int(cmdows_sample.get('position')) - 1] = float(cmdows_sample.text)
graph.node[cmdows_parameter_uid][
graph.CMDOWS_ATTRIBUTE_DICT_INV[attribute.tag]] = cmdows_sample_data
# The following nodes and edges are only generated for MDGs
if isinstance(graph, MdaoDataGraph):
 
# TODO: First set up architecture
#cmdows_architecture_parameters = cmdows.find('architectureElements/parameters')
#for cmdows_architecture_parameter in list(cmdows_architecture_parameters):
# for cmdows_single_architecture_parameter in list(cmdows_architecture_parameter):
# graph.node[cmdows_single_architecture_parameter.get('uID')]
# Create architecture element nodes
cmdows_architecture_parameters = cmdows.find('architectureElements/parameters')
for cmdows_architecture_parameter in list(cmdows_architecture_parameters):
for cmdows_single_architecture_parameter in list(cmdows_architecture_parameter):
cmdows_uid = cmdows_single_architecture_parameter.get('uID')
key_dict = {'relatedParameterUID': 'related_to_schema_node'}
attr_dict = recursively_dictify(cmdows_single_architecture_parameter, key_dict)
graph.add_node(cmdows_uid,
attr_dict,
category='variable',
architecture_role=unmake_camel_case(cmdows_single_architecture_parameter.tag, ' '))
cmdows_architecture_exe_blocks = cmdows.find('architectureElements/executableBlocks')
for cmdows_architecture_exe_block in list(cmdows_architecture_exe_blocks):
for cmdows_single_architecture_exe_block in list(cmdows_architecture_exe_block):
cmdows_uid = cmdows_single_architecture_exe_block.get('uID')
if cmdows_uid is not None:
attr_dict = recursively_dictify(cmdows_single_architecture_exe_block)
graph.add_node(cmdows_uid,
attr_dict,
category='function',
architecture_role=unmake_camel_case(cmdows_single_architecture_exe_block.tag, ' '))
# Copy node data from problem formulation to executableBlocks
graph.expand_node(cmdows_uid, graph.CMDOWS_ROLES_DEF)
else:
for role in graph.ARCHITECTURE_ROLES_FUNS:
cmdows_role_name = make_camel_case(role)
if cmdows_single_architecture_exe_block.tag == cmdows_role_name:
cmdows_uid = cmdows_single_architecture_exe_block.find('relatedExecutableBlockUID').text
graph.node[cmdows_uid]['architecture_role'] = role
 
# Create MDG edges
cmdows_data_graph = cmdows.find('workflow/dataGraph')
graph.graph['name'] = cmdows_data_graph.findtext('name')
cmdows_edges = cmdows_data_graph.find('edges/edge')
cmdows_edges = cmdows_data_graph.find('edges')
if cmdows_edges is not None:
for edge in list(cmdows_edges):
graph.add_edge(edge.findtext('fromUID'), edge.findtext('toUID'))
 
# TODO: Make process graph
# Create MPG
cmdows_process_graph = cmdows.find('workflow/processGraph')
mpg = MdaoProcessGraph(kb_path=kb_path, name=cmdows_process_graph.findtext('name'))
cmdows_nodes = cmdows_process_graph.find('nodes')
if cmdows_nodes is not None:#
for node in list(cmdows_nodes):
# Get new node info
key_dict = {'processStepNumber': 'process_step',
'convergerStepNumber': 'converger_step',
'referenceUID': 'uid'}
new_attr_dict = recursively_dictify(node, key_dict)
del new_attr_dict['uid']
# Copy other node info
attr_dict = graph.node[node.findtext('referenceUID')]
attr_dict.update(new_attr_dict)
mpg.add_node(node.findtext('referenceUID'), attr_dict = attr_dict)
cmdows_edges = cmdows_process_graph.find('edges')
if cmdows_edges is not None:
for edge in list(cmdows_edges):
mpg.add_edge(edge.findtext('fromUID'), edge.findtext('toUID'),
attr_dict = {'process_step': edge.findtext('processStepNumber')})
 
#print graph.graph
#nodes = graph.find_all_nodes(category='variable')
#for node in nodes:
# print node
# print graph.node[node]
# Remove None nodes
try:
graph.remove_node(None)
mpg.remove_node(None)
except nx.exception.NetworkXError:
pass
 
# Check of graph
# TODO: Add kadmos_check_critical check
if isinstance(graph, FundamentalProblemGraph) or isinstance(graph, MdaoDataGraph):
if not graph.check():
logger.warning('The graph created from the CMDOWS file is invalid.')
try:
check = graph.check()
except:
check = False
if not check:
if kadmos_check_critical:
raise IOError('The graph created from the CMDOWS file is invalid.')
else:
logger.warning('The graph created from the CMDOWS file is invalid.')
 
# Finish
logger.info('CMDOWS file ' + path + ' loaded.')
 
# Return graph
return graph
if isinstance(graph, MdaoDataGraph):
return graph, mpg
else:
return graph
 
def cmdows_integrity_check(graph, MPG=None):
"""
......@@ -4329,6 +4412,8 @@ def cmdows_integrity_check(graph, MPG=None):
:rtype: bool
"""
 
# TODO: Implement tempfiles instead of testfile
# Logging
logger.info('Performing CMDOWS integrity check...')
 
......@@ -4336,8 +4421,13 @@ def cmdows_integrity_check(graph, MPG=None):
timestamp = datetime.now()
graph.save_as_cmdows('testfile1', 'test description', 'test author', '1.1', timestamp=timestamp, MPG=MPG,
kadmos_check_critical=False, pretty_print=True)
check = load_from_cmdows('testfile1')
check.save_as_cmdows('testfile2', 'test description', 'test author', '1.1', timestamp=timestamp, kadmos_check_critical=False, pretty_print=True)
if MPG is not None:
check, check_mpg = load_from_cmdows('testfile1', kadmos_check_critical=False)
else:
check = load_from_cmdows('testfile1', kadmos_check_critical=False)
check_mpg = None
check.save_as_cmdows('testfile2', 'test description', 'test author', '1.1', timestamp=timestamp, MPG=check_mpg,
kadmos_check_critical=False, pretty_print=True)
# First try file wise comparison
if filecmp.cmp('testfile1.xml', 'testfile2.xml'):
result_a = True
......@@ -4353,6 +4443,7 @@ def cmdows_integrity_check(graph, MPG=None):
result_a = True
else:
result_a = False
logger.info('The following elements are not loaded: '+ str([x for x in list if x not in set(checklist)]))
 
# Check if the file adheres to the schema
try:
......@@ -4376,14 +4467,24 @@ def cmdows_integrity_check(graph, MPG=None):
logger.info('CMDOWS integrity check passed.')
else:
if not result_a:
logger.info('Not all information is written to/read from the CMDOWS file.')
logger.info('Not all elements are written to/read from the CMDOWS file.')
if not result_b:
logger.info('The CMDOWS file does not adhere to its schema.')
# TODO: Warning is not showing up always. Check!
warnings.warn('CMDOWS integrity check failed.')
logger.warning('CMDOWS integrity check failed.')
 
return result
 
def load_from_kdms(filename, source_folder=None, kadmos_check_critical=True):
# TODO: Make general open class that included assertions and kadmos_check_critical
return open_kdms(filename, source_folder)
def load_from_graphml(filename, source_folder=None, kadmos_check_critical=True):
return import_graphml(filename, source_folder)
def open_kdms(filename, source_folder=None):
"""
Method to open any KadmosGraph graph object using pickling.
......@@ -6937,7 +7038,7 @@ class MdaoDataGraph(KadmosGraph):
prob_var_nodes = self.find_all_nodes(category='variable', subcategory='all problematic variables')
prob_fun_nodes = self.find_all_nodes(category='function', subcategory='all problematic functions')
 
if prob_fun_nodes:
if prob_fun_nodes and print_in_log:
self.inspect_node(prob_fun_nodes[0])
 
if print_in_log:
......@@ -6958,11 +7059,11 @@ class MdaoDataGraph(KadmosGraph):
graph_check = False
if prob_var_nodes:
print 'WARNING A02: There are still problematic variable nodes in the graph, namely: ' + \
str(prob_var_nodes)
str(prob_var_nodes)
graph_check = False
if prob_fun_nodes:
print 'WARNING A03: There are still problematic function nodes in the graph, namely: ' + \
str(prob_fun_nodes)
str(prob_fun_nodes)
graph_check = False
for node in var_nodes:
if self.in_degree(node) == 0:
......
import logging
import tempfile
import os
import shutil
from flask import Flask, request, redirect, url_for, send_file, render_template, send_from_directory
from graph import *
# Initial settings
logger = logging.getLogger(__name__)
app = Flask(__name__)
app.debug = True
temp = os.path.join(os.path.dirname(os.path.realpath(__file__)), '../temp/')
tempfile.tempdir = temp
# Initial variables
file_types = ['cmdows', 'kdms', 'graphml']
file_extensions = ['xml', 'kdms', 'graphml']
# Index
@app.route("/")
def index(message=None):
# Check if message is send
if request.values.get('message', False) and message is None:
message = request.values['message']
# Render index
return render_template('index.html', types=file_types, message=message)
# Upload
@app.route("/", methods=['POST'])
def upload():
# Get file
file = request.files['file']
# Check file existence
if not file:
return index(message='Please upload a KADMOS graph file.')
# Get file type
if request.values.get('file_type', 'auto') != 'auto':
file_type = request.values.get('file_type')
elif file.filename.lower().endswith(tuple(file_extensions)):
file_type = file_types[file_extensions.index(os.path.splitext(file.filename)[1].lower()[1:])]
else:
return index(message='The file type could not be recognized. Please specify it under advanced options.')
# Create temporary directory
temp_dir = tempfile.mkdtemp()
# Move file in temporary directory
path = os.path.join(temp_dir, 'input.'+file_extensions[file_types.index(file_type)])
file.save(path)
# Get graph from file
# TODO Add exceptions and warnings if importing fails
if file_type == 'cmdows':
graph = load_from_cmdows(path)
elif file_type == 'kdms':
graph = load_from_kdms(path)
elif file_type == 'graphml':
graph = load_from_graphml(path)
# Save graph for further use
graph.save_as_kdms('graph.kdms', temp_dir)
# Send user to view page
return redirect(url_for('view', temp_id=os.path.basename(os.path.normpath(temp_dir))))
# View
@app.route('/<temp_id>')
@app.route('/<temp_id>/<action>')
def view(temp_id=None, action=None):
# Check if files exist
temp_dir = str(os.path.join(temp, temp_id))
if not os.path.exists(temp_dir):
return redirect(url_for('index', message='The requested graph not exist (anymore). Please upload a new file.'))
# Load graph
graph = load_from_kdms('graph.kdms', source_folder=temp_dir)
# Perform actions
if action == 'pdf':
graph.create_dsm(filename='graph',
destination_folder=temp_dir)
return send_file(os.path.join(temp_dir, 'graph.pdf'))
if action == 'cmdows':
graph.save_as_cmdows(filename='graph',
destination_folder=temp_dir,
description='CMDOWS file created with the KADMOS interface',
creator='KADMOS interface',
file_version='1.0')
return send_file(os.path.join(temp_dir, 'graph.xml'), as_attachment=True)
if action == 'vispack':
graph.create_visualization_package(os.path.join(temp_dir, 'graph.vispack'))
return send_file(os.path.join(temp_dir, 'graph.vispack'), as_attachment=True)
if action == 'delete':
shutil.rmtree(temp_dir)
return redirect(url_for('index', message='All files were deleted.'))
return render_template('view.html', temp_id=temp_id)
if __name__ == '__main__':
app.run()
input:checked + label + div { display: none; }
\ No newline at end of file
<!DOCTYPE html>
<html lang=en>
<head>
<meta charset=UTF-8>
{% if title %}
<title>{{ title }} - KADMOS interface</title>
{% else %}
<title>KADMOS interface</title>
{% endif %}
<link rel=stylesheet href="{{ url_for('static', filename='style.css') }}">
</head>
<body>
{% block content %}{% endblock %}
</body>
</html>
\ No newline at end of file
{% extends "base.html" %}
{% block content %}
<h1>Welcome to the KADMOS interface!</h1>
{% if message %}
<p><font color=red>{{ message }}</font></p>
{% endif %}
<p>Upload a KADMOS graph file to get started.<br>CMDOWS, KDMS and GRAPHML file types are supported.</p>
<form action="" method=post enctype=multipart/form-data>
<input type=file name=file>
<input type=submit value=Upload>
<br>
<input type=checkbox style="display: none" id=advanced checked>
<label for=advanced>Advanced Options</label>
<div id=advanced_options>
Filetype:
<select name=file_type>
<option value=auto selected>auto</option>
{% for type in types %}
<option value={{type}}>{{type.upper()}}</option>
{% endfor %}
</select>
</div>
</form>
{% endblock %}
\ No newline at end of file
{% extends "base.html" %}
{% block content %}
<h1>Welcome to the KADMOS interface!</h1>
{% if message %}
<p><font color=red>{{ message }}</font></p>
{% endif %}
<p>Here we go! You just uploaded a KADMOS graph file. The graph was imported successfully. What do you want to do with it?</p>
<ul>
<li><a href="{{ temp_id }}/pdf">Create a (X)DSM PDF file</a></li>
<li><a href="{{ temp_id }}/vispack">Create a dynamic (X)DSM HTML package</a></li>
<li><a href="{{ temp_id }}/cmdows">Create a CMDOWS XML file</a></li>
<li><a href="{{ temp_id }}/delete">Delete all files</a></li>
<li><a>Something else</a></li>
</ul>
{% endblock %}
\ No newline at end of file
......@@ -153,7 +153,7 @@ def get_mdao_setup(mdao_setup):
allow_unconverged_couplings = False
else:
raise IOError('Incorrect mdao_setup "%s" specified.' % mdao_setup)
return mdo_architecture,mda_type,allow_unconverged_couplings
return mdo_architecture, mda_type, allow_unconverged_couplings
def test_attr_cond(attr_value, operator, test_value):
......@@ -170,7 +170,7 @@ def test_attr_cond(attr_value, operator, test_value):
:rtype: bool
"""
# Assert inputs
pos_ops = ['<','<=','==','!=','>=','>', 'in']
pos_ops = ['<', '<=', '==', '!=', '>=', '>', 'in']
assert isinstance(operator,str)
assert set([operator]).intersection(set(pos_ops)), "'%s' is an invalid operator, possible operators are: %s." % \
(operator, pos_ops)
......@@ -246,8 +246,8 @@ def transform_data_into_strings(data, keys_to_be_removed=list()):
"""
# Input assertions
assert isinstance(data,dict)
assert isinstance(keys_to_be_removed,list)
assert isinstance(data, dict)
assert isinstance(keys_to_be_removed, list)
for key, item in data.iteritems():
if item is None:
......@@ -319,14 +319,34 @@ def extend_list_uniquely(original_list, extension_list):
return list(set(original_list))
def make_camel_case(string, make_plural=False):
def make_plural(string):
"""
Function to convert a string to its plural form.
:param string: initial string
:type string: str
:return: plural string
:rtype: str
"""
if string[-2:] == 'is':
# e.g. 'analysis' should become 'analyses'
string = string[:-2] + 'es'
else:
# e.g. 'variable' should become 'variables'
string += 's'
return string
def make_camel_case(string, make_plural_option=False):
"""
Function to make a string camelCase.
:param string: non-camelcase string
:type string: str
:param make_plural: pluralize camelcase string
:type make_plural: bool
:param make_plural_option: pluralize camelcase string
:type make_plural_option: bool
:return: camelcase string
:rtype: str
"""
......@@ -335,29 +355,26 @@ def make_camel_case(string, make_plural=False):
words = word_regex_pattern.split(string)
string = "".join(w.lower() if i is 0 else w.title() for i, w in enumerate(words))
if make_plural:
if string[-2:] == 'is':
# e.g. 'analysis' should become 'analyses'
string = string[:-2] + 'es'
else:
# e.g. 'variable' should become 'variables'
string = string + 's'
if make_plural_option:
string = make_plural(string)
return string
def unmake_camel_case(string):
def unmake_camel_case(string, separator='_'):
"""
Function to make camelCase a string with underscores.
Function to make camelCase a string with separator (e.g. underscores).
:param string: camelCase string
:type string: str
:return: string with underscores
:param separator: symbol/symbols used as separator
:type string: str
:return: string with separator
:rtype: str
"""
string = re.sub(r"(\w)([A-Z])", r"\1_\2", string) # Add underscores
string = string.lower() # Remove capitalization
string = re.sub(r"(\w)([A-Z])", r"\1"+separator+r"\2", string) # Add separator
string = string.lower() # Remove capitalization
return string
......@@ -461,7 +478,7 @@ def open_file(filename):
def Child(parent, tag, content='', attrib={}, **extra):
"""
Utility function extending the xml.etree.ElementTree.SubElement function
Utility function extending the xml.etree.ElementTree.SubElement function.
:param parent: The parent element
:param tag: The subelement name
......@@ -484,7 +501,7 @@ def Child(parent, tag, content='', attrib={}, **extra):
def ChildSequence(parent, data, data_keys=None, data_dict=None):
"""
Utility function extending the previously defined Child function such that sequences
can easily be created in an xml.etree.ElementTree
can easily be created in an xml.etree.ElementTree.
:param parent: The parent element
:param data: The list of data to be written to the sequence in the form [[key1, value1], [key2, value2]]
......@@ -535,7 +552,7 @@ def ChildGroup(graph, attr_name, attr_value, data_list):
assert isinstance(data_list, list)
# Element
element = Element(make_camel_case(attr_value, make_plural=True))
element = Element(make_camel_case(attr_value, make_plural_option=True))
# Nodes
nodes = graph.find_all_nodes(attr_cond=[attr_name, '==', attr_value])
......@@ -547,13 +564,11 @@ def ChildGroup(graph, attr_name, attr_value, data_list):
for index in range(len(data_list)):
data_key = data_list[index][0]
data_value = data_list[index][1]
# TODO: Remove if statement if all values from data_list need to be present
if graph.node[node].get(data_key) is not None:
if isinstance(data_value, list):
# For design variables and similar cases
subsubelement = Child(subelement, data_value[0])
# TODO: If KADMOS allows for more than one objectiveVariable at some point
# the fix below can be removed
# TODO: If KADMOS allows for more than one objectiveVariable at some point this fix can be removed
if data_value[0] == 'objectiveVariables':
graph.node[node][data_key] = {graph.node[node][data_key][0]: graph.node[node][data_key][0]}
for subdata_key, subdata_value in graph.node[node][data_key].iteritems():
......@@ -587,7 +602,7 @@ def recursively_empty(e):
def recursively_stringify(tree):
"""
Utility function to recursively stringify a ElementTree object (for file comparison)
Utility function to recursively stringify a ElementTree object (for file comparison).
:param tree: Input ElementTree object
:return: List of strings representing the ElementTree object
......@@ -605,4 +620,52 @@ def recursively_stringify(tree):
string_list.sort()
return string_list
\ No newline at end of file
return string_list
def recursively_dictify(element, key_dict={}):
"""
Utility function to recursively convert a ElementTree.Element object to a dictionary.
:param element: Input ElementTree.Element
:param element: Dictionary for translating keys
:return: dictionary representing the ElementTree.Element
"""
# Create dictionary
dictionary = {}
# Loop over element
for subelement in list(element):
# If subelement contains a string it is assumed that the final level of the dictionary is reached
if subelement.text.strip():
# Check if string is actually a list and convert to a list in this case
try:
subelement_value = ast.literal_eval(subelement.text)
if not isinstance(subelement_value, list):
raise ValueError
except (SyntaxError, ValueError):
subelement_value = subelement.text.strip()
# If subelement contains other elements start recursive loop
elif list(subelement) is not None:
subelement_value = recursively_dictify(subelement)
# Write value to dictionary
if subelement_value:
subelement_key = key_dict.get(subelement.tag, unmake_camel_case(subelement.tag, '_'))
# Check that this dictionary entry does not exits yet
# If so add identifier
if dictionary.get(subelement_key) is not None:
subelement_key = subelement_key + '_' + \
str(sum([key.startswith(subelement_key) for key in dictionary.keys()]))
dictionary[subelement_key] = subelement_value
# Temporary fix for objective variables
# TODO Change data structure in KADMOS graph and then remove this fix
if dictionary.get('objective_variables', False):
dictionary['objective_variable'] = [dictionary['objective_variables'].values()[0]['objective_variable_ui_d'][10:]]
del dictionary['objective_variables']
#print dictionary
# Return
return dictionary
......@@ -16,7 +16,7 @@ email: i.vangent@tudelft.nl
import os
import shutil
import logging
#logging.basicConfig(format='%(levelname)s: %(message)s', level=logging.DEBUG)
logging.basicConfig(format='%(levelname)s: %(message)s', level=logging.DEBUG)
from pprint import PrettyPrinter
from pyKADMOS.sample.graph import open_kdms, FundamentalProblemGraph, cmdows_integrity_check
......@@ -121,8 +121,8 @@ else:
shutil.copytree(subfolder + 'vispack_RCG', subfolder + 'vispack')
# Save CMDOWS file
#RCG.save_as_cmdows('RCG', 'WP6 TU Delft Wing Design RCG file', 'Lukas Mueller', '0.1',
# destination_folder=subfolder + 'CMDOWS', pretty_print=True)
RCG.save_as_cmdows('RCG', 'WP6 TU Delft Wing Design RCG file', 'Lukas Mueller', '0.1',
destination_folder=subfolder + 'CMDOWS', pretty_print=True)
#cmdows_integrity_check(RCG)
# On to the wrapping of the MDAO architectures
......@@ -323,9 +323,9 @@ for idx, item in enumerate(mdao_definitions):
vispack_version=vispack_version)
# Save CMDOWS file
# MDG.save_as_cmdows('MDAO_' + mdao_definition, 'WP6 TU Delft Wing Design MDAO file', 'Lukas Mueller', '0.1', MPG=MPG,
# destination_folder=subfolder+'CMDOWS', pretty_print=True)
# cmdows_integrity_check(MDG, MPG=MPG)
MDG.save_as_cmdows('MDAO_' + mdao_definition, 'WP6 TU Delft Wing Design MDAO file', 'Lukas Mueller', '0.1', MPG=MPG,
destination_folder=subfolder+'CMDOWS', pretty_print=True)
cmdows_integrity_check(MDG, MPG=MPG)
# Create RCE workflow
if create_rce_wf:
......
......@@ -3,14 +3,14 @@
<header>
<creator>Lukas Mueller</creator>
<description>WP6 TU Delft Wing Design FPG file</description>
<timestamp>2017-04-01T21:24:19.100000</timestamp>
<timestamp>2017-04-21T13:26:39.829000</timestamp>
<fileVersion>0.1</fileVersion>
<cmdowsVersion>0.4</cmdowsVersion>
<updates>
<update>
<modification>KADMOS export of a fundamental problem graph (FPG).</modification>
<creator>Lukas Mueller</creator>
<timestamp>2017-04-01T21:24:19.100000</timestamp>
<timestamp>2017-04-21T13:26:39.829000</timestamp>
<fileVersion>0.1</fileVersion>
<cmdowsVersion>0.4</cmdowsVersion>
</update>
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment