def view_model(data_source, outfile='n2.html', show_browser=True, embeddable=False, title=None, use_declare_partial_info=False): """ Generates an HTML file containing a tree viewer. Optionally opens a web browser to view the file. Parameters ---------- data_source : <Problem> or str The Problem or case recorder database containing the model or model data. outfile : str, optional The name of the final output file show_browser : bool, optional If True, pop up the system default web browser to view the generated html file. Defaults to True. embeddable : bool, optional If True, gives a single HTML file that doesn't have the <html>, <DOCTYPE>, <body> and <head> tags. If False, gives a single, standalone HTML file for viewing. title : str, optional The title for the diagram. Used in the HTML title and also shown on the page. use_declare_partial_info: bool, optional If True, in the N2 matrix, component internal connectivity computed using derivative declarations, otherwise, derivative declarations ignored, so dense component connectivity is assumed. """ # grab the model viewer data model_data = _get_viewer_data(data_source) options = {} options['use_declare_partial_info'] = use_declare_partial_info model_data['options'] = options model_data = 'var modelData = %s' % json.dumps(model_data, default=make_serializable) # if MPI is active only display one copy of the viewer if MPI and MPI.COMM_WORLD.rank != 0: return code_dir = os.path.dirname(os.path.abspath(__file__)) vis_dir = os.path.join(code_dir, "visualization") libs_dir = os.path.join(vis_dir, "libs") src_dir = os.path.join(vis_dir, "src") style_dir = os.path.join(vis_dir, "style") # grab the libraries, src and style lib_dct = { 'd3': 'd3.v4.min', 'awesomplete': 'awesomplete', 'vk_beautify': 'vkBeautify' } libs = read_files(itervalues(lib_dct), libs_dir, 'js') src_names = 'constants', 'draw', 'legend', 'modal', 'ptN2', 'search', 'svg' srcs = read_files(src_names, src_dir, 'js') styles = read_files(('awesomplete', 'partition_tree'), style_dir, 'css') with open(os.path.join(style_dir, "fontello.woff"), "rb") as f: encoded_font = str(base64.b64encode(f.read()).decode("ascii")) if title: title = "OpenMDAO Model Hierarchy and N2 diagram: %s" % title else: title = "OpenMDAO Model Hierarchy and N2 diagram" h = DiagramWriter(filename=os.path.join(vis_dir, "index.html"), title=title, styles=styles, embeddable=embeddable) # put all style and JS into index h.insert('{{fontello}}', encoded_font) for k, v in iteritems(lib_dct): h.insert('{{{}_lib}}'.format(k), write_script(libs[v], indent=_IND)) for name, code in iteritems(srcs): h.insert('{{{}_lib}}'.format(name.lower()), write_script(code, indent=_IND)) h.insert('{{model_data}}', write_script(model_data, indent=_IND)) # Toolbar toolbar = h.toolbar group1 = toolbar.add_button_group() group1.add_button("Return To Root", uid="returnToRootButtonId", disabled="disabled", content="icon-home") group1.add_button("Back", uid="backButtonId", disabled="disabled", content="icon-left-big") group1.add_button("Forward", uid="forwardButtonId", disabled="disabled", content="icon-right-big") group1.add_button("Up One Level", uid="upOneLevelButtonId", disabled="disabled", content="icon-up-big") group2 = toolbar.add_button_group() group2.add_button("Uncollapse In View Only", uid="uncollapseInViewButtonId", content="icon-resize-full") group2.add_button("Uncollapse All", uid="uncollapseAllButtonId", content="icon-resize-full bigger-font") group2.add_button("Collapse Outputs In View Only", uid="collapseInViewButtonId", content="icon-resize-small") group2.add_button("Collapse All Outputs", uid="collapseAllButtonId", content="icon-resize-small bigger-font") group2.add_dropdown("Collapse Depth", button_content="icon-sort-number-up", uid="idCollapseDepthDiv") group3 = toolbar.add_button_group() group3.add_button("Clear Arrows and Connections", uid="clearArrowsAndConnectsButtonId", content="icon-eraser") group3.add_button("Show Path", uid="showCurrentPathButtonId", content="icon-terminal") group3.add_button("Show Legend", uid="showLegendButtonId", content="icon-map-signs") group3.add_button("Toggle Solver Names", uid="toggleSolverNamesButtonId", content="icon-minus") group3.add_dropdown("Font Size", id_naming="idFontSize", options=_FONT_SIZES, option_formatter=lambda x: '{}px'.format(x), button_content="icon-text-height") group3.add_dropdown("Vertically Resize", id_naming="idVerticalResize", options=_MODEL_HEIGHTS, option_formatter=lambda x: '{}px'.format(x), button_content="icon-resize-vertical", header="Model Height") group4 = toolbar.add_button_group() group4.add_button("Save SVG", uid="saveSvgButtonId", content="icon-floppy") group5 = toolbar.add_button_group() group5.add_button("Help", uid="helpButtonId", content="icon-help") # Help help_txt = ( 'Left clicking on a node in the partition tree will navigate to that node. ' 'Right clicking on a node in the model hierarchy will collapse/uncollapse it. ' 'A click on any element in the N^2 diagram will allow those arrows to persist.' ) h.add_help(help_txt, footer="OpenMDAO Model Hierarchy and N^2 diagram") if use_declare_partial_info: h.insert( '{{component_connectivity}}', 'Note: Component internal connectivity computed using derivative declarations' ) else: h.insert( '{{component_connectivity}}', 'Note: Derivative declarations ignored, so dense component connectivity is assumed' ) # Write output file h.write(outfile) # open it up in the browser if show_browser: from openmdao.devtools.webview import webview webview(outfile)
def write_html(outfile, source_data=None, data_file=None, embeddable=False): """ Writes XDSMjs HTML output file, with style and script files embedded. The source data can be the name of a JSON file or a dictionary. If a JSON file name is provided, the file will be referenced in the HTML. If the input is a dictionary, it will be embedded. If both data file and source data are given, data file is Parameters ---------- outfile : str Output HTML file source_data : str or dict or None XDSM data in a dictionary or string data_file : str or None Output HTML file embeddable : bool, optional If True, gives a single HTML file that doesn't have the <html>, <DOCTYPE>, <body> and <head> tags. If False, gives a single, standalone HTML file for viewing. """ # directories main_dir = os.path.dirname(os.path.abspath(__file__)) code_dir = os.path.join(main_dir, 'XDSMjs') build_dir = os.path.join(code_dir, "build") style_dir = code_dir # CSS with open(os.path.join(build_dir, "xdsm.bundle.js"), "r") as f: code = f.read() xdsm_bundle = write_script(code, {'type': 'text/javascript'}) xdsm_attrs = {'class': 'xdsm'} # grab the data if data_file is not None: # Add name of the data file xdsm_attrs['data-mdo-file'] = data_file elif source_data is not None: if isinstance(source_data, (dict, str)): data_str = str(source_data) # dictionary converted to string else: msg = ( 'Invalid data type for source data: {} \n' 'The source data should be a JSON file name or a dictionary.') raise ValueError(msg.format(type(source_data))) # Replace quote marks for the HTML syntax for i in ('u"', "u'", '"', "'"): # quote marks and unicode prefixes data_str = data_str.replace(i, r'"') xdsm_attrs['data-mdo'] = data_str else: # both source data and data file name are None msg = 'Specify either "source_data" or "data_file".' raise ValueError(msg.format(type(source_data))) # grab the style styles = read_files(('fontello', 'xdsm'), style_dir, 'css') styles_elem = write_style(content='\n\n'.join(itervalues(styles))) # put all style and JS into index toolbar_div = write_div(attrs={'class': 'xdsm-toolbar'}) xdsm_div = write_div(attrs=xdsm_attrs) body = '\n\n'.join([toolbar_div, xdsm_div]) if embeddable: index = '\n\n'.join([styles_elem, xdsm_bundle, body]) else: meta = '<meta charset="{}">'.format(_CHAR_SET) head = '\n\n'.join([meta, styles_elem, xdsm_bundle]) index = head_and_body(head, body, attrs={'class': "js", 'lang': ""}) # Embed style, scripts and data to HTML with open(outfile, 'w') as f: f.write(index)
def view_model(data_source, outfile='n2.html', show_browser=True, embeddable=False, title=None): """ Generates an HTML file containing a tree viewer. Optionally opens a web browser to view the file. Parameters ---------- data_source : <Problem> or str The Problem or case recorder database containing the model or model data. outfile : str, optional The name of the final output file show_browser : bool, optional If True, pop up the system default web browser to view the generated html file. Defaults to True. embeddable : bool, optional If True, gives a single HTML file that doesn't have the <html>, <DOCTYPE>, <body> and <head> tags. If False, gives a single, standalone HTML file for viewing. title : str, optional The title for the diagram. Used in the HTML title and also shown on the page. """ # grab the model viewer data model_data = _get_viewer_data(data_source) model_data = 'var modelData = %s' % json.dumps(model_data, default=make_serializable) # if MPI is active only display one copy of the viewer if MPI and MPI.COMM_WORLD.rank != 0: return code_dir = os.path.dirname(os.path.abspath(__file__)) vis_dir = os.path.join(code_dir, "visualization") libs_dir = os.path.join(vis_dir, "libs") src_dir = os.path.join(vis_dir, "src") style_dir = os.path.join(vis_dir, "style") # grab the libraries, src and style lib_dct = {'d3': 'd3.v4.min', 'awesomplete': 'awesomplete', 'vk_beautify': 'vkBeautify'} libs = read_files(itervalues(lib_dct), libs_dir, 'js') src_names = 'constants', 'draw', 'legend', 'modal', 'ptN2', 'search', 'svg' srcs = read_files(src_names, src_dir, 'js') styles = read_files(('awesomplete', 'partition_tree'), style_dir, 'css') with open(os.path.join(style_dir, "fontello.woff"), "rb") as f: encoded_font = str(base64.b64encode(f.read()).decode("ascii")) if title: title = "OpenMDAO Model Hierarchy and N2 diagram: %s" % title else: title = "OpenMDAO Model Hierarchy and N2 diagram" h = DiagramWriter(filename=os.path.join(vis_dir, "index.html"), title=title, styles=styles, embeddable=embeddable) # put all style and JS into index h.insert('{{fontello}}', encoded_font) for k, v in iteritems(lib_dct): h.insert('{{{}_lib}}'.format(k), write_script(libs[v], indent=_IND)) for name, code in iteritems(srcs): h.insert('{{{}_lib}}'.format(name.lower()), write_script(code, indent=_IND)) h.insert('{{model_data}}', write_script(model_data, indent=_IND)) # Toolbar toolbar = h.toolbar group1 = toolbar.add_button_group() group1.add_button("Return To Root", uid="returnToRootButtonId", disabled="disabled", content="icon-home") group1.add_button("Back", uid="backButtonId", disabled="disabled", content="icon-left-big") group1.add_button("Forward", uid="forwardButtonId", disabled="disabled", content="icon-right-big") group1.add_button("Up One Level", uid="upOneLevelButtonId", disabled="disabled", content="icon-up-big") group2 = toolbar.add_button_group() group2.add_button("Uncollapse In View Only", uid="uncollapseInViewButtonId", content="icon-resize-full") group2.add_button("Uncollapse All", uid="uncollapseAllButtonId", content="icon-resize-full bigger-font") group2.add_button("Collapse Outputs In View Only", uid="collapseInViewButtonId", content="icon-resize-small") group2.add_button("Collapse All Outputs", uid="collapseAllButtonId", content="icon-resize-small bigger-font") group2.add_dropdown("Collapse Depth", button_content="icon-sort-number-up", uid="idCollapseDepthDiv") group3 = toolbar.add_button_group() group3.add_button("Clear Arrows and Connections", uid="clearArrowsAndConnectsButtonId", content="icon-eraser") group3.add_button("Show Path", uid="showCurrentPathButtonId", content="icon-terminal") group3.add_button("Show Legend", uid="showLegendButtonId", content="icon-map-signs") group3.add_button("Show Params", uid="showParamsButtonId", content="icon-exchange") group3.add_button("Toggle Solver Names", uid="toggleSolverNamesButtonId", content="icon-minus") group3.add_dropdown("Font Size", id_naming="idFontSize", options=_FONT_SIZES, option_formatter=lambda x: '{}px'.format(x), button_content="icon-text-height") group3.add_dropdown("Vertically Resize", id_naming="idVerticalResize", options=_MODEL_HEIGHTS, option_formatter=lambda x: '{}px'.format(x), button_content="icon-resize-vertical", header="Model Height") group4 = toolbar.add_button_group() group4.add_button("Save SVG", uid="saveSvgButtonId", content="icon-floppy") group5 = toolbar.add_button_group() group5.add_button("Help", uid="helpButtonId", content="icon-help") # Help help_txt = ('Left clicking on a node in the partition tree will navigate to that node. ' 'Right clicking on a node in the model hierarchy will collapse/uncollapse it. ' 'A click on any element in the N^2 diagram will allow those arrows to persist.') h.add_help(help_txt, footer="OpenMDAO Model Hierarchy and N^2 diagram") # Write output file h.write(outfile) # open it up in the browser if show_browser: from openmdao.devtools.webview import webview webview(outfile)
def write_html(outfile, source_data=None, data_file=None, embeddable=False): """ Writes XDSMjs HTML output file, with style and script files embedded. The source data can be the name of a JSON file or a dictionary. If a JSON file name is provided, the file will be referenced in the HTML. If the input is a dictionary, it will be embedded. If both data file and source data are given, data file is Parameters ---------- outfile : str Output HTML file source_data : str or dict or None XDSM data in a dictionary or string data_file : str or None Output HTML file embeddable : bool, optional If True, gives a single HTML file that doesn't have the <html>, <DOCTYPE>, <body> and <head> tags. If False, gives a single, standalone HTML file for viewing. """ # directories main_dir = os.path.dirname(os.path.abspath(__file__)) code_dir = os.path.join(main_dir, 'XDSMjs') build_dir = os.path.join(code_dir, "build") style_dir = code_dir # CSS with open(os.path.join(build_dir, "xdsm.bundle.js"), "r") as f: code = f.read() xdsm_bundle = write_script(code, {'type': 'text/javascript'}) xdsm_attrs = {'class': 'xdsm'} # grab the data if data_file is not None: # Add name of the data file xdsm_attrs['data-mdo-file'] = data_file elif source_data is not None: if isinstance(source_data, (dict, str)): data_str = str(source_data) # dictionary converted to string else: msg = ('Invalid data type for source data: {} \n' 'The source data should be a JSON file name or a dictionary.') raise ValueError(msg.format(type(source_data))) # Replace quote marks for the HTML syntax for i in ('u"', "u'", '"', "'"): # quote marks and unicode prefixes data_str = data_str.replace(i, r'"') xdsm_attrs['data-mdo'] = data_str else: # both source data and data file name are None msg = 'Specify either "source_data" or "data_file".' raise ValueError(msg.format(type(source_data))) # grab the style styles = read_files(('fontello', 'xdsm'), style_dir, 'css') styles_elem = write_style(content='\n\n'.join(itervalues(styles))) # put all style and JS into index toolbar_div = write_div(attrs={'class': 'xdsm-toolbar'}) xdsm_div = write_div(attrs=xdsm_attrs) body = '\n\n'.join([toolbar_div, xdsm_div]) if embeddable: index = '\n\n'.join([styles_elem, xdsm_bundle, body]) else: meta = '<meta charset="{}">'.format(_CHAR_SET) head = '\n\n'.join([meta, styles_elem, xdsm_bundle]) index = head_and_body(head, body, attrs={'class': "js", 'lang': ""}) # Embed style, scripts and data to HTML with open(outfile, 'w') as f: f.write(index)
def view_model(data_source, outfile='n2.html', show_browser=True, embeddable=False, draw_potential_connections=True): """ Generates an HTML file containing a tree viewer. Optionally opens a web browser to view the file. Parameters ---------- data_source : <Problem> or str The Problem or case recorder database containing the model or model data. outfile : str, optional The name of the final output file show_browser : bool, optional If True, pop up the system default web browser to view the generated html file. Defaults to True. embeddable : bool, optional If True, gives a single HTML file that doesn't have the <html>, <DOCTYPE>, <body> and <head> tags. If False, gives a single, standalone HTML file for viewing. draw_potential_connections : bool, optional If true, allows connections to be drawn on the N2 that do not currently exist in the model. Defaults to True. """ # grab the model viewer data model_viewer_data = _get_viewer_data(data_source) model_viewer_data = 'var modelData = %s' % json.dumps(model_viewer_data) # if MPI is active only display one copy of the viewer if MPI and MPI.COMM_WORLD.rank != 0: return code_dir = os.path.dirname(os.path.abspath(__file__)) vis_dir = os.path.join(code_dir, "visualization") libs_dir = os.path.join(vis_dir, "libs") src_dir = os.path.join(vis_dir, "src") style_dir = os.path.join(vis_dir, "style") # grab the libraries, src and style lib_dct = {'d3': 'd3.v4.min', 'awesomplete': 'awesomplete', 'vk_beautify': 'vkBeautify'} libs = read_files(itervalues(lib_dct), libs_dir, 'js') src_names = 'constants', 'draw', 'legend', 'modal', 'ptN2', 'search', 'svg' srcs = read_files(src_names, src_dir, 'js') styles = read_files(('awesomplete', 'partition_tree'), style_dir, 'css') style_elems = '\n\n'.join([write_style(content=s) for s in itervalues(styles)]) with open(os.path.join(style_dir, "fontello.woff"), "rb") as f: encoded_font = str(base64.b64encode(f.read()).decode("ascii")) # grab the index.html with open(os.path.join(vis_dir, "index.html"), "r") as f: index = f.read() # add the necessary HTML tags if we aren't embedding if embeddable: index = '\n\n'.join([style_elems, index]) else: meta = '<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">' head = '\n\n'.join([meta, style_elems]) # Write styles to head index = head_and_body(head=head, body=index) # put all style and JS into index index = index.replace('{{fontello}}', encoded_font) for k, v in iteritems(lib_dct): index = index.replace('{{{}_lib}}'.format(k), write_script(libs[v], indent=4)) for name, code in iteritems(srcs): index = index.replace('{{{}_lib}}'.format(name.lower()), write_script(code, indent=4)) index = index.replace('{{model_data}}', write_script(model_viewer_data, indent=4)) index = index.replace('{{draw_potential_connections}}', str(draw_potential_connections).lower()) with open(outfile, 'w') as f: # write output file f.write(index) # open it up in the browser if show_browser: from openmdao.devtools.webview import webview webview(outfile)
def view_model(data_source, outfile='n2.html', show_browser=True, embeddable=False, draw_potential_connections=True): """ Generates an HTML file containing a tree viewer. Optionally opens a web browser to view the file. Parameters ---------- data_source : <Problem> or str The Problem or case recorder database containing the model or model data. outfile : str, optional The name of the final output file show_browser : bool, optional If True, pop up the system default web browser to view the generated html file. Defaults to True. embeddable : bool, optional If True, gives a single HTML file that doesn't have the <html>, <DOCTYPE>, <body> and <head> tags. If False, gives a single, standalone HTML file for viewing. draw_potential_connections : bool, optional If true, allows connections to be drawn on the N2 that do not currently exist in the model. Defaults to True. """ # grab the model viewer data model_viewer_data = _get_viewer_data(data_source) model_viewer_data = 'var modelData = %s' % json.dumps(model_viewer_data) # if MPI is active only display one copy of the viewer if MPI and MPI.COMM_WORLD.rank != 0: return code_dir = os.path.dirname(os.path.abspath(__file__)) vis_dir = os.path.join(code_dir, "visualization") libs_dir = os.path.join(vis_dir, "libs") src_dir = os.path.join(vis_dir, "src") style_dir = os.path.join(vis_dir, "style") # grab the libraries, src and style lib_dct = { 'd3': 'd3.v4.min', 'awesomplete': 'awesomplete', 'vk_beautify': 'vkBeautify' } libs = read_files(itervalues(lib_dct), libs_dir, 'js') src_names = 'constants', 'draw', 'legend', 'modal', 'ptN2', 'search', 'svg' srcs = read_files(src_names, src_dir, 'js') styles = read_files(('awesomplete', 'partition_tree'), style_dir, 'css') style_elems = '\n\n'.join( [write_style(content=s) for s in itervalues(styles)]) with open(os.path.join(style_dir, "fontello.woff"), "rb") as f: encoded_font = str(base64.b64encode(f.read()).decode("ascii")) # grab the index.html with open(os.path.join(vis_dir, "index.html"), "r") as f: index = f.read() # add the necessary HTML tags if we aren't embedding if embeddable: index = '\n\n'.join([style_elems, index]) else: meta = '<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">' head = '\n\n'.join([meta, style_elems]) # Write styles to head index = head_and_body(head=head, body=index) # put all style and JS into index index = index.replace('{{fontello}}', encoded_font) for k, v in iteritems(lib_dct): index = index.replace('{{{}_lib}}'.format(k), write_script(libs[v], indent=4)) for name, code in iteritems(srcs): index = index.replace('{{{}_lib}}'.format(name.lower()), write_script(code, indent=4)) index = index.replace('{{model_data}}', write_script(model_viewer_data, indent=4)) index = index.replace('{{draw_potential_connections}}', str(draw_potential_connections).lower()) with open(outfile, 'w') as f: # write output file f.write(index) # open it up in the browser if show_browser: from openmdao.devtools.webview import webview webview(outfile)