Exemplo n.º 1
0
def prof_view():
    """Called from a command line to generate an html viewer for profile data."""

    parser = argparse.ArgumentParser()
    parser.add_argument('--noshow', action='store_true', dest='noshow',
                        help="Don't pop up a browser to view the data.")
    parser.add_argument('-t', '--title', action='store', dest='title',
                        default='Profile of Method Calls by Instance',
                        help='Title to be displayed above profiling view.')
    parser.add_argument('rawfiles', metavar='rawfile', nargs='*',
                        help='File(s) containing raw profile data to be processed. Wildcards are allowed.')

    options = parser.parse_args()

    if not options.rawfiles:
        print("No files to process.")
        sys.exit(0)

    call_graph, totals = process_profile(options.rawfiles)

    viewer = "icicle.html"
    code_dir = os.path.dirname(os.path.abspath(__file__))

    with open(os.path.join(code_dir, viewer), "r") as f:
        template = f.read()

    graphjson = json.dumps(call_graph)

    outfile = 'profile_' + viewer
    with open(outfile, 'w') as f:
        f.write(Template(template).substitute(call_graph_data=graphjson,
                                              title=options.title))

    if not options.noshow:
        webview(outfile)
Exemplo n.º 2
0
def prof_view():
    """Called from a command line to generate an html viewer for profile data."""

    parser = argparse.ArgumentParser()
    parser.add_argument('--noshow',
                        action='store_true',
                        dest='noshow',
                        help="Don't pop up a browser to view the data.")
    parser.add_argument('-t',
                        '--title',
                        action='store',
                        dest='title',
                        default='Profile of Method Calls by Instance',
                        help='Title to be displayed above profiling view.')
    parser.add_argument(
        'rawfiles',
        metavar='rawfile',
        nargs='*',
        help=
        'File(s) containing raw profile data to be processed. Wildcards are allowed.'
    )

    options = parser.parse_args()

    if not options.rawfiles:
        print("No files to process.")
        sys.exit(0)

    call_graph, totals = process_profile(options.rawfiles)

    viewer = "icicle.html"
    code_dir = os.path.dirname(os.path.abspath(__file__))

    with open(os.path.join(code_dir, viewer), "r") as f:
        template = f.read()

    graphjson = json.dumps(call_graph)

    outfile = 'profile_' + viewer
    with open(outfile, 'w') as f:
        f.write(
            Template(template).substitute(call_graph_data=graphjson,
                                          title=options.title))

    if not options.noshow:
        webview(outfile)
Exemplo n.º 3
0
def view_model(problem_or_filename,
               outfile='visualization',
               show_browser=True):
    """
    Generates a directory containing a tree viewer Optionally pops up a web browser to
    view the file.

    Parameters
    ----------
    problem_or_filename : Either a Problem() or a string
        Problem() : The Problem (after problem.setup()) for the desired tree.
        string : The filename of the case recorder file containing the data required to build the tree.

    outfile : str, optional
        The path of the output folder.  Defaults to current directory + 'visualization'.

    show_browser : bool, optional
        If True, pop up the system default web browser to view the generated html file.
        Defaults to True.
    """
    cur_dir = os.getcwd()
    if outfile == 'visualization':
        outfile = os.path.join(cur_dir, outfile)

    model_data_filename = 'model_data.js'
    folder_name = outfile
    code_dir = os.path.dirname(os.path.abspath(__file__))
    model_viewer_data = _get_viewer_data(problem_or_filename)
    model_data = json.dumps(model_viewer_data)

    if os.path.isdir(folder_name):
        shutil.rmtree(folder_name)

    shutil.copytree(src=code_dir + '/visualization', dst=folder_name)

    model_data_dir = os.path.join(folder_name, model_data_filename)
    with open(model_data_dir, 'w') as f:
        f.write('var modelData = %s' % model_data)

    if show_browser:
        from openmdao.devtools.webview import webview
        view_path = os.path.join(cur_dir, folder_name)
        view_path = os.path.join(view_path, 'index.html')
        webview(view_path)
Exemplo n.º 4
0
def view_connections(root, outfile='connections.html', show_browser=True,
                     src_filter='', tgt_filter='', precision=6):
    """
    Generates a self-contained html file containing a detailed connection
    viewer.  Optionally pops up a web browser to view the file.

    Args
    ----
    root : system or Problem
        The root for the desired tree.

    outfile : str, optional
        The name of the output html file.  Defaults to 'connections.html'.

    show_browser : bool, optional
        If True, pop up a browser to view the generated html file.
        Defaults to True.

    src_filter : str, optional
        If defined, use this as the initial value for the source system filter.

    tgt_filter : str, optional
        If defined, use this as the initial value for the target system filter.

    precision : int, optional
        Sets the precision for displaying array values.
    """
    # since people will be used to passing the Problem as the first arg to
    # the N2 diagram funct, allow them to pass a Problem here as well.
    if isinstance(root, Problem):
        system = root.root
    else:
        system = root

    connections = system._probdata.connections
    to_prom = system._sysdata.to_prom_name
    src2tgts = {}
    units = {n: m.get('units','') for n,m in chain(iteritems(system._unknowns_dict),
                                                   iteritems(system._params_dict))}

    vals = {}

    with printoptions(precision=precision, suppress=True, threshold=10000):
        for t, tmeta in iteritems(system._params_dict):
            if t in connections:
                s, idxs = connections[t]
                if idxs is not None:
                    val = system.unknowns[to_prom[s]][idxs]
                else:
                    val = system.unknowns[to_prom[s]]

                # if there's a unit conversion, express the value in the
                # units of the target
                if 'unit_conv' in tmeta:
                    scale, offset = tmeta['unit_conv']
                    val = (val + offset) * scale

                if s not in src2tgts:
                    src2tgts[s] = [t]
                else:
                    src2tgts[s].append(t)
            else: # unconnected param
                val = system._params_dict[t]['val']

            if isinstance(val, numpy.ndarray):
                val = numpy.array2string(val)
            else:
                val = str(val)

            vals[t] = val

        noconn_srcs = sorted((n for n in system._unknowns_dict
                               if n not in src2tgts), reverse=True)
        for s in noconn_srcs:
            vals[s] = str(system.unknowns[to_prom[s]])

    vals['NO CONNECTION'] = ''

    src_systems = set()
    tgt_systems = set()
    for s in src2tgts:
        parts = s.split('.')
        for i in range(len(parts)):
            src_systems.add('.'.join(parts[:i]))

    for t in connections:
        parts = t.split('.')
        for i in range(len(parts)):
            tgt_systems.add('.'.join(parts[:i]))

    # reverse sort so that "NO CONNECTION" shows up at the bottom
    src2tgts['NO CONNECTION'] = sorted([t for t in to_prom
                                    if t not in system._unknowns_dict and
                                       t not in connections], reverse=True)

    src_systems = [{'name':n} for n in sorted(src_systems)]
    src_systems.insert(1, {'name': "NO CONNECTION"})
    tgt_systems = [{'name':n} for n in sorted(tgt_systems)]
    tgt_systems.insert(1, {'name': "NO CONNECTION"})

    data = {
        'src2tgts': [(s,ts) for s,ts in sorted(iteritems(src2tgts), reverse=True)],
        'proms': to_prom,
        'units': units,
        'vals': vals,
        'src_systems': src_systems,
        'tgt_systems': tgt_systems,
        'noconn_srcs': noconn_srcs,
        'src_filter': src_filter,
        'tgt_filter': tgt_filter,
    }

    viewer = 'connect_table.html'

    code_dir = os.path.dirname(os.path.abspath(__file__))

    with open(os.path.join(code_dir, viewer), "r") as f:
        template = f.read()

    graphjson = json.dumps(data)

    with open(outfile, 'w') as f:
        s = template.replace("<connection_data>", graphjson)
        f.write(s)

    if show_browser:
        webview(outfile)
Exemplo n.º 5
0
def view_connections(root, outfile='connections.html', show_browser=True):
    """
    Generates a self-contained html file containing a detailed connection
    viewer.  Optionally pops up a web browser to view the file.

    Args
    ----
    root : system or Problem
        The root for the desired tree.

    outfile : str, optional
        The name of the output html file.  Defaults to 'connections.html'.

    show_browser : bool, optional
        If True, pop up a browser to view the generated html file.
        Defaults to True.
    """
    # since people will be used to passing the Problem as the first arg to
    # the N2 diagram funct, allow them to pass a Problem here as well.
    if isinstance(root, Problem):
        system = root.root
    else:
        system = root

    connections = system._probdata.connections
    to_prom = system._sysdata.to_prom_name
    src2tgts = {}
    units = {
        n: m.get('units', '')
        for n, m in chain(iteritems(system._unknowns_dict),
                          iteritems(system._params_dict))
    }

    sizes = {}
    for t, (s, idxs) in iteritems(connections):
        if idxs is not None:
            sizes[t] = len(idxs)
        else:
            sizes[t] = system._params_dict[t]['size']
        if s not in src2tgts:
            src2tgts[s] = [t]
        else:
            src2tgts[s].append(t)

    src_systems = set()
    tgt_systems = set()
    for s in src2tgts:
        parts = s.split('.')
        for i in range(len(parts)):
            src_systems.add('.'.join(parts[:i]))

    for t in connections:
        parts = t.split('.')
        for i in range(len(parts)):
            tgt_systems.add('.'.join(parts[:i]))

    # reverse sort so that "NO CONNECTION" shows up at the bottom
    src2tgts['NO CONNECTION'] = sorted([
        t for t in to_prom
        if t not in system._unknowns_dict and t not in connections
    ],
                                       reverse=True)

    src_systems = [{'name': n} for n in sorted(src_systems)]
    src_systems.insert(1, {'name': "NO CONNECTION"})
    tgt_systems = [{'name': n} for n in sorted(tgt_systems)]
    tgt_systems.insert(1, {'name': "NO CONNECTION"})

    data = {
        'src2tgts':
        [(s, ts) for s, ts in sorted(iteritems(src2tgts), reverse=True)],
        'proms':
        to_prom,
        'units':
        units,
        'sizes':
        sizes,
        'src_systems':
        src_systems,
        'tgt_systems':
        tgt_systems,
        'noconn_srcs':
        sorted((n for n in system._unknowns_dict if n not in src2tgts),
               reverse=True),
    }

    viewer = 'connect_table.html'

    code_dir = os.path.dirname(os.path.abspath(__file__))

    with open(os.path.join(code_dir, viewer), "r") as f:
        template = f.read()

    graphjson = json.dumps(data)

    with open(outfile, 'w') as f:
        s = template.replace("<connection_data>", graphjson)
        f.write(s)

    if show_browser:
        webview(outfile)
Exemplo n.º 6
0
def view_connections(root, outfile='connections.html', show_browser=True,
                     src_filter='', tgt_filter='', precision=6):
    """
    Generates a self-contained html file containing a detailed connection
    viewer.  Optionally pops up a web browser to view the file.

    Parameters
    ----------
    root : system or Problem
        The root for the desired tree.

    outfile : str, optional
        The name of the output html file.  Defaults to 'connections.html'.

    show_browser : bool, optional
        If True, pop up a browser to view the generated html file.
        Defaults to True.

    src_filter : str, optional
        If defined, use this as the initial value for the source system filter.

    tgt_filter : str, optional
        If defined, use this as the initial value for the target system filter.

    precision : int, optional
        Sets the precision for displaying array values.
    """
    # since people will be used to passing the Problem as the first arg to
    # the N2 diagram funct, allow them to pass a Problem here as well.
    if isinstance(root, Problem):
        system = root.model
    else:
        system = root

    input_srcs = system._conn_global_abs_in2out

    connections = {
        tgt: src for tgt, src in iteritems(input_srcs) if src is not None
    }

    src2tgts = {}
    units = {n: data.get('units','')
                for n, data in iteritems(system._var_allprocs_abs2meta)}
    vals = {}

    with printoptions(precision=precision, suppress=True, threshold=10000):

        for t in system._var_abs_names['input']:
            tmeta = system._var_abs2meta[t]
            idxs = tmeta['src_indices']
            flat = tmeta['flat_src_indices']
            if idxs is None:
                idxs = np.arange(tmeta['size'], dtype=int)

            if t in connections:
                s = connections[t]
                val = system._outputs[s]
                if isinstance(val, np.ndarray):
                    val = system._outputs[s].flatten()[idxs]
                else:
                    val = system._outputs[s]

                # if there's a unit conversion, express the value in the
                # units of the target
                if units[t]:
                    val = convert_units(val, units[s], units[t])

                if s not in src2tgts:
                    src2tgts[s] = [t]
                else:
                    src2tgts[s].append(t)
            else: # unconnected param
                val = system._inputs[t]

            if isinstance(val, np.ndarray):
                val = np.array2string(val)
            else:
                val = str(val)

            vals[t] = val

        noconn_srcs = sorted((n for n in system._var_abs_names['output']
                                if n not in src2tgts), reverse=True)
        for s in noconn_srcs:
            vals[s] = str(system._outputs[s])

    vals['NO CONNECTION'] = ''

    src_systems = set()
    tgt_systems = set()
    for s in system._var_abs_names['output']:
        parts = s.split('.')
        for i in range(len(parts)):
            src_systems.add('.'.join(parts[:i]))

    for t in system._var_abs_names['input']:
        parts = t.split('.')
        for i in range(len(parts)):
            tgt_systems.add('.'.join(parts[:i]))

    # reverse sort so that "NO CONNECTION" shows up at the bottom
    src2tgts['NO CONNECTION'] = sorted([t for t in system._var_abs_names['input']
                                    if t not in connections], reverse=True)

    src_systems = [{'name':n} for n in sorted(src_systems)]
    src_systems.insert(1, {'name': "NO CONNECTION"})
    tgt_systems = [{'name':n} for n in sorted(tgt_systems)]
    tgt_systems.insert(1, {'name': "NO CONNECTION"})

    data = {
        'src2tgts': sorted(iteritems(src2tgts)),
        'proms': None,
        'units': units,
        'vals': vals,
        'src_systems': src_systems,
        'tgt_systems': tgt_systems,
        'noconn_srcs': noconn_srcs,
        'src_filter': src_filter,
        'tgt_filter': tgt_filter,
    }

    viewer = 'connect_table.html'

    code_dir = os.path.dirname(os.path.abspath(__file__))

    with open(os.path.join(code_dir, viewer), "r") as f:
        template = f.read()

    graphjson = json.dumps(data)

    with open(outfile, 'w') as f:
        s = template.replace("<connection_data>", graphjson)
        f.write(s)

    if show_browser:
        webview(outfile)
Exemplo n.º 7
0
def view_connections(root, outfile='connections.html', show_browser=True):
    """
    Generates a self-contained html file containing a detailed connection
    viewer.  Optionally pops up a web browser to view the file.

    Args
    ----
    root : system or Problem
        The root for the desired tree.

    outfile : str, optional
        The name of the output html file.  Defaults to 'connections.html'.

    show_browser : bool, optional
        If True, pop up a browser to view the generated html file.
        Defaults to True.
    """
    # since people will be used to passing the Problem as the first arg to
    # the N2 diagram funct, allow them to pass a Problem here as well.
    if isinstance(root, Problem):
        system = root.root
    else:
        system = root

    connections = system._probdata.connections
    to_prom = system._sysdata.to_prom_name
    src2tgts = {}
    units = {n: m.get('units','') for n,m in chain(iteritems(system._unknowns_dict),
                                                   iteritems(system._params_dict))}

    sizes = {}
    for t, (s, idxs) in iteritems(connections):
        if idxs is not None:
            sizes[t] = len(idxs)
        else:
            sizes[t] = system._params_dict[t]['size']
        if s not in src2tgts:
            src2tgts[s] = [t]
        else:
            src2tgts[s].append(t)

    src_systems = set()
    tgt_systems = set()
    for s in src2tgts:
        parts = s.split('.')
        for i in range(len(parts)):
            src_systems.add('.'.join(parts[:i]))

    for t in connections:
        parts = t.split('.')
        for i in range(len(parts)):
            tgt_systems.add('.'.join(parts[:i]))

    # reverse sort so that "NO CONNECTION" shows up at the bottom
    src2tgts['NO CONNECTION'] = sorted([t for t in to_prom
                                    if t not in system._unknowns_dict and
                                       t not in connections], reverse=True)

    src_systems = [{'name':n} for n in sorted(src_systems)]
    src_systems.insert(1, {'name': "NO CONNECTION"})
    tgt_systems = [{'name':n} for n in sorted(tgt_systems)]
    tgt_systems.insert(1, {'name': "NO CONNECTION"})

    data = {
        'src2tgts': [(s,ts) for s,ts in sorted(iteritems(src2tgts), reverse=True)],
        'proms': to_prom,
        'units': units,
        'sizes': sizes,
        'src_systems': src_systems,
        'tgt_systems': tgt_systems,
        'noconn_srcs': sorted((n for n in system._unknowns_dict
                               if n not in src2tgts), reverse=True),
    }

    viewer = 'connect_table.html'

    code_dir = os.path.dirname(os.path.abspath(__file__))

    with open(os.path.join(code_dir, viewer), "r") as f:
        template = f.read()

    graphjson = json.dumps(data)

    with open(outfile, 'w') as f:
        s = template.replace("<connection_data>", graphjson)
        f.write(s)

    if show_browser:
        webview(outfile)
Exemplo n.º 8
0
def view_tree(problem, outfile='partition_tree_n2.html', show_browser=True, offline=True, embed=False):
    """
    Generates a self-contained html file containing a tree viewer
    of the specified type.  Optionally pops up a web browser to
    view the file.

    Args
    ----
    problem : Problem()
        The Problem (after problem.setup()) for the desired tree.

    outfile : str, optional
        The name of the output html file.  Defaults to 'partition_tree_n2.html'.

    show_browser : bool, optional
        If True, pop up the system default web browser to view the generated html file.
        Defaults to True.

    offline : bool, optional
        If True, embed the javascript d3 library into the generated html file so that the tree can be viewed
        offline without an internet connection.  Otherwise if False, have the html request the latest d3 file
        from https://d3js.org/d3.v4.min.js when opening the html file.
        Defaults to True.

    embed : bool, optional
        If True, export only the innerHTML that is between the body tags, used for embedding the viewer into another html file.
        If False, create a standalone HTML file that has the DOCTYPE, html, head, meta, and body tags.
        Defaults to False.
    """
    component_execution_orders = {}
    component_execution_index = [0] #list so pass by ref
    tree = _system_tree_dict(problem.root, component_execution_orders, component_execution_index)
    viewer = 'partition_tree_n2.template'

    code_dir = os.path.dirname(os.path.abspath(__file__))

    with open(os.path.join(code_dir, viewer), "r") as f:
        template = f.read()

    html_begin_tags = ("<!DOCTYPE html>\n"
        "<html>\n"
        "<head>\n"
        "    <meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\">\n"
        "</head>\n"
        "<body>\n")

    html_end_tags = ("</body>\n"
        "</html>\n")

    if embed:
        html_begin_tags = html_end_tags = ""

    d3_library = "<script src=\"https://d3js.org/d3.v4.min.js\" charset=\"utf-8\"></script>"
    if offline:
        with open(os.path.join(code_dir, 'd3.v4.min.js'), "r") as f:
            d3_library = "<script type=\"text/javascript\"> %s </script>" % (f.read())

    treejson = json.dumps(tree)

    connections_list = []
    G = problem._probdata.relevance._sgraph
    scc = nx.strongly_connected_components(G)
    scc_list = [s for s in scc if len(s)>1] #list(scc)

    for tgt, (src, idxs) in iteritems(problem._probdata.connections):
        src_subsystem = src.rsplit('.', 1)[0]
        tgt_subsystem = tgt.rsplit('.', 1)[0]


        count = 0
        edges_list = []
        for li in scc_list:
            if src_subsystem in li and tgt_subsystem in li:
                count = count+1
                if(count > 1):
                    raise ValueError('Count greater than 1')

                exe_tgt = component_execution_orders[tgt_subsystem]
                exe_src = component_execution_orders[src_subsystem]
                exe_low = min(exe_tgt,exe_src)
                exe_high = max(exe_tgt,exe_src)
                subg = G.subgraph(li)
                for n in subg.nodes():
                    exe_order = component_execution_orders[n]
                    if(exe_order < exe_low or exe_order > exe_high):
                        subg.remove_node(n)


                src_to_tgt_str = src_subsystem + ' ' + tgt_subsystem
                for tup in subg.edges():
                    edge_str = tup[0] + ' ' + tup[1]
                    if edge_str != src_to_tgt_str:
                        edges_list.append(edge_str)


        if(len(edges_list) > 0):
            connections_list.append({'src':src, 'tgt':tgt, 'cycle_arrows': edges_list})
        else:
            connections_list.append({'src':src, 'tgt':tgt})

    connsjson = json.dumps(connections_list)

    with open(outfile, 'w') as f:
        f.write(template % (html_begin_tags, d3_library, treejson, connsjson, html_end_tags))

    if show_browser:
        from openmdao.devtools.webview import webview
        webview(outfile)
Exemplo n.º 9
0
def view_tree(problem,
              outfile='partition_tree_n2.html',
              show_browser=True,
              offline=True,
              embed=False):
    """
    Generates a self-contained html file containing a tree viewer
    of the specified type.  Optionally pops up a web browser to
    view the file.

    Args
    ----
    problem : Problem()
        The Problem (after problem.setup()) for the desired tree.

    outfile : str, optional
        The name of the output html file.  Defaults to 'partition_tree_n2.html'.

    show_browser : bool, optional
        If True, pop up the system default web browser to view the generated html file.
        Defaults to True.

    offline : bool, optional
        If True, embed the javascript d3 library into the generated html file so that the tree can be viewed
        offline without an internet connection.  Otherwise if False, have the html request the latest d3 file
        from https://d3js.org/d3.v4.min.js when opening the html file.
        Defaults to True.

    embed : bool, optional
        If True, export only the innerHTML that is between the body tags, used for embedding the viewer into another html file.
        If False, create a standalone HTML file that has the DOCTYPE, html, head, meta, and body tags.
        Defaults to False.
    """
    component_execution_orders = {}
    component_execution_index = [0]  #list so pass by ref
    tree = _system_tree_dict(problem.root, component_execution_orders,
                             component_execution_index)
    viewer = 'partition_tree_n2.template'

    code_dir = os.path.dirname(os.path.abspath(__file__))

    with open(os.path.join(code_dir, viewer), "r") as f:
        template = f.read()

    html_begin_tags = (
        "<!DOCTYPE html>\n"
        "<html>\n"
        "<head>\n"
        "    <meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\">\n"
        "</head>\n"
        "<body>\n")

    html_end_tags = ("</body>\n" "</html>\n")

    if embed:
        html_begin_tags = html_end_tags = ""

    d3_library = "<script src=\"https://d3js.org/d3.v4.min.js\" charset=\"utf-8\"></script>"
    if offline:
        with open(os.path.join(code_dir, 'd3.v4.min.js'), "r") as f:
            d3_library = "<script type=\"text/javascript\"> %s </script>" % (
                f.read())

    treejson = json.dumps(tree)

    connections_list = []
    G = problem._probdata.relevance._sgraph
    scc = nx.strongly_connected_components(G)
    scc_list = [s for s in scc if len(s) > 1]  #list(scc)

    for tgt, (src, idxs) in iteritems(problem._probdata.connections):
        src_subsystem = src.rsplit('.', 1)[0]
        tgt_subsystem = tgt.rsplit('.', 1)[0]

        count = 0
        edges_list = []
        for li in scc_list:
            if src_subsystem in li and tgt_subsystem in li:
                count = count + 1
                if (count > 1):
                    raise ValueError('Count greater than 1')

                exe_tgt = component_execution_orders[tgt_subsystem]
                exe_src = component_execution_orders[src_subsystem]
                exe_low = min(exe_tgt, exe_src)
                exe_high = max(exe_tgt, exe_src)
                subg = G.subgraph(li)
                for n in subg.nodes():
                    exe_order = component_execution_orders[n]
                    if (exe_order < exe_low or exe_order > exe_high):
                        subg.remove_node(n)

                src_to_tgt_str = src_subsystem + ' ' + tgt_subsystem
                for tup in subg.edges():
                    edge_str = tup[0] + ' ' + tup[1]
                    if edge_str != src_to_tgt_str:
                        edges_list.append(edge_str)

        if (len(edges_list) > 0):
            connections_list.append({
                'src': src,
                'tgt': tgt,
                'cycle_arrows': edges_list
            })
        else:
            connections_list.append({'src': src, 'tgt': tgt})

    connsjson = json.dumps(connections_list)

    with open(outfile, 'w') as f:
        f.write(
            template %
            (html_begin_tags, d3_library, treejson, connsjson, html_end_tags))

    if show_browser:
        from openmdao.devtools.webview import webview
        webview(outfile)
Exemplo n.º 10
0
def view_model(problem_or_filename, outfile='partition_tree_n2.html', show_browser=True, offline=True, embed=False):
    """
    Generates a self-contained html file containing a tree viewer
    of the specified type.  Optionally pops up a web browser to
    view the file.

    Args
    ----
    problem_or_filename : Either a Problem() or a string
        Problem() : The Problem (after problem.setup()) for the desired tree.
        string : The filename of the case recorder file containing the data required to build the tree.

    outfile : str, optional
        The name of the output html file.  Defaults to 'partition_tree_n2.html'.

    show_browser : bool, optional
        If True, pop up the system default web browser to view the generated html file.
        Defaults to True.

    offline : bool, optional
        If True, embed the javascript d3 library into the generated html file so that the tree can be viewed
        offline without an internet connection.  Otherwise if False, have the html request the latest d3 file
        from https://d3js.org/d3.v4.min.js when opening the html file.
        Defaults to True.

    embed : bool, optional
        If True, export only the innerHTML that is between the body tags, used for embedding the viewer into another html file.
        If False, create a standalone HTML file that has the DOCTYPE, html, head, meta, and body tags.
        Defaults to False.
    """
    viewer = 'partition_tree_n2.template'

    code_dir = os.path.dirname(os.path.abspath(__file__))

    with open(os.path.join(code_dir, viewer), "r") as f:
        template = f.read()

    html_begin_tags = ("<!DOCTYPE html>\n"
        "<html>\n"
        "<head>\n"
        "    <meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\">\n"
        "</head>\n"
        "<body>\n")

    html_end_tags = ("</body>\n"
        "</html>\n")

    display_none_attr = ""

    if embed:
        html_begin_tags = html_end_tags = ""
        display_none_attr = " style=\"display:none\""

    d3_library = "<script src=\"https://d3js.org/d3.v4.min.js\" charset=\"utf-8\"></script>"
    if offline:
        with open(os.path.join(code_dir, 'd3.v4.min.js'), "r") as f:
            d3_library = "<script type=\"text/javascript\"> %s </script>" % (f.read())

    if isinstance(problem_or_filename, Problem):
        required_data = get_required_data_from_problem(problem_or_filename)
    else:
        raise ValueError("Filenames not supported yet!")
    tree_json = json.dumps(required_data['tree'])
    conns_json = json.dumps(required_data['connections_list'])

    with open(outfile, 'w') as f:
        f.write(template % (html_begin_tags, display_none_attr, d3_library, tree_json, conns_json, html_end_tags))

    if show_browser:
        from openmdao.devtools.webview import webview
        webview(outfile)
Exemplo n.º 11
0
def view_model(problem_or_filename,
               outfile='partition_tree_n2.html',
               show_browser=True,
               offline=True,
               embed=False):
    """
    Generates a self-contained html file containing a tree viewer
    of the specified type.  Optionally pops up a web browser to
    view the file.

    Args
    ----
    problem_or_filename : Either a Problem() or a string
        Problem() : The Problem (after problem.setup()) for the desired tree.
        string : The filename of the case recorder file containing the data required to build the tree.

    outfile : str, optional
        The name of the output html file.  Defaults to 'partition_tree_n2.html'.

    show_browser : bool, optional
        If True, pop up the system default web browser to view the generated html file.
        Defaults to True.

    offline : bool, optional
        If True, embed the javascript d3 library into the generated html file so that the tree can be viewed
        offline without an internet connection.  Otherwise if False, have the html request the latest d3 file
        from https://d3js.org/d3.v4.min.js when opening the html file.
        Defaults to True.

    embed : bool, optional
        If True, export only the innerHTML that is between the body tags, used for embedding the viewer into another html file.
        If False, create a standalone HTML file that has the DOCTYPE, html, head, meta, and body tags.
        Defaults to False.
    """
    viewer = 'partition_tree_n2.template'

    code_dir = os.path.dirname(os.path.abspath(__file__))

    with open(os.path.join(code_dir, viewer), "r") as f:
        template = f.read()

    html_begin_tags = (
        "<!DOCTYPE html>\n"
        "<html>\n"
        "<head>\n"
        "    <meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\">\n"
        "</head>\n"
        "<body>\n")

    html_end_tags = ("</body>\n" "</html>\n")

    display_none_attr = ""

    if embed:
        html_begin_tags = html_end_tags = ""
        display_none_attr = " style=\"display:none\""

    d3_library = "<script src=\"https://d3js.org/d3.v4.min.js\" charset=\"utf-8\"></script>"
    if offline:
        with open(os.path.join(code_dir, 'd3.v4.min.js'), "r") as f:
            d3_library = "<script type=\"text/javascript\"> %s </script>" % (
                f.read())

    if isinstance(problem_or_filename, Problem):
        model_viewer_data = get_model_viewer_data(problem_or_filename)
    else:
        # Do not know file type. Try opening to see what works
        file_type = None
        if is_valid_sqlite3_db(problem_or_filename):
            db = SqliteDict(filename=problem_or_filename,
                            flag='r',
                            tablename='metadata')
            file_type = "sqlite"
        else:
            try:
                hdf = h5py.File(problem_or_filename, 'r')
                file_type = 'hdf5'
            except:
                raise ValueError(
                    "The given filename is not one of the supported file formats: sqlite or hdf5"
                )

        if file_type == "sqlite":
            model_viewer_data = db['model_viewer_data']
        elif file_type == "hdf5":
            metadata = hdf.get('metadata', None)
            model_viewer_data = pickle.loads(
                metadata.get('model_viewer_data').value)

    tree_json = json.dumps(model_viewer_data['tree'])
    conns_json = json.dumps(model_viewer_data['connections_list'])

    with open(outfile, 'w') as f:
        f.write(template % (html_begin_tags, display_none_attr, d3_library,
                            tree_json, conns_json, html_end_tags))

    if show_browser:
        from openmdao.devtools.webview import webview
        webview(outfile)
Exemplo n.º 12
0
def view_model(problem_or_filename, outfile='n2.html', show_browser=True, embeddable=False, draw_potential_connections=True):
    """
    Generates an HTML file containing a tree viewer. Optionally pops up a web browser to
    view the file.

    Parameters
    ----------
    problem_or_filename : Either a Problem() or a string
        Problem() : The Problem (after problem.setup()) for the desired tree.
        string : The filename of the case recorder file containing the data required to
         build the tree.

    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.
    """
    html_begin_tags = """
                      <html>
                      <head>
                        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
                      </head>
                      <body>\n
                      """
    html_end_tags = """
                    </body>
                    </html>
                    """

    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
    with open(os.path.join(libs_dir, "awesomplete.js"), "r") as f:
        awesomplete = f.read()
    with open(os.path.join(libs_dir, "d3.v4.min.js"), "r") as f:
        d3 = f.read()
    with open(os.path.join(libs_dir, "http.js"), "r") as f:
        http = f.read()
    with open(os.path.join(libs_dir, "jquery-3.2.1.min.js"), "r") as f:
        jquery = f.read()
    with open(os.path.join(libs_dir, "vkBeautify.js"), "r") as f:
        vk_beautify = f.read()

    #grab the src
    with open(os.path.join(src_dir, "constants.js"), "r") as f:
        constants = f.read()
    with open(os.path.join(src_dir, "draw.js"), "r") as f:
        draw = f.read()
    with open(os.path.join(src_dir, "legend.js"), "r") as f:
        legend = f.read()
    with open(os.path.join(src_dir, "modal.js"), "r") as f:
        modal = f.read()
    with open(os.path.join(src_dir, "ptN2.js"), "r") as f:
        pt_n2 = f.read()
    with open(os.path.join(src_dir, "search.js"), "r") as f:
        search = f.read()
    with open(os.path.join(src_dir, "svg.js"), "r") as f:
        svg = f.read()

    #grab the style
    with open(os.path.join(style_dir, "awesomplete.css"), "r") as f:
        awesomplete_style = f.read()
    with open(os.path.join(style_dir, "partition_tree.css"), "r") as f:
        partition_tree_style = f.read()
    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()

    #grab the model viewer data
    model_viewer_data = 'var modelData = %s' % json.dumps(_get_viewer_data(problem_or_filename))

    #add the necessary HTML tags if we aren't embedding
    if not embeddable:
        index = html_begin_tags + index + html_end_tags

    #put all style and JS into index
    index = index.replace('{{awesomplete_style}}', awesomplete_style)
    index = index.replace('{{partition_tree_style}}', partition_tree_style)
    index = index.replace('{{fontello}}', encoded_font)
    index = index.replace('{{d3_lib}}', d3)
    index = index.replace('{{awesomplete_lib}}', awesomplete)
    index = index.replace('{{vk_beautify_lib}}', vk_beautify)
    index = index.replace('{{model_data}}', model_viewer_data)
    index = index.replace('{{constants_lib}}', constants)
    index = index.replace('{{modal_lib}}', modal)
    index = index.replace('{{svg_lib}}', svg)
    index = index.replace('{{search_lib}}', search)
    index = index.replace('{{legend_lib}}', legend)
    index = index.replace('{{draw_lib}}', draw)
    index = index.replace('{{ptn2_lib}}', pt_n2)
    if draw_potential_connections:
        index = index.replace('{{draw_potential_connections}}', 'true')
    else:
        index = index.replace('{{draw_potential_connections}}', 'false')

    with open(outfile, 'w') as f:
        f.write(index)

    #open it up in the browser
    if show_browser:
        from openmdao.devtools.webview import webview
        webview(outfile)
Exemplo n.º 13
0
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)
Exemplo n.º 14
0
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)
Exemplo n.º 15
0
def _write_xdsm(filename,
                viewer_data,
                optimizer=None,
                include_solver=False,
                cleanup=True,
                design_vars=None,
                responses=None,
                residuals=None,
                model_path=None,
                recurse=True,
                include_external_outputs=True,
                subs=_CHAR_SUBS,
                writer='pyXDSM',
                show_browser=False,
                add_process_conns=True,
                quiet=False,
                **kwargs):
    """
    XDSM writer. Components are extracted from the connections of the problem.

    Parameters
    ----------
    filename : str
        Filename (absolute path without extension)
    connections : list[(str, str)]
        Connections list
    optimizer : str or None, optional
        Optimizer name
    include_solver:  bool, optional
        Defaults to False.
    cleanup : bool, optional
        Clean-up temporary files after making the diagram.
        Defaults to True.
    design_vars : OrderedDict or None
        Design variables
    responses : OrderedDict or None, , optional
        Responses
    model_path : str or None, optional
        Path to the subsystem to be transcribed to XDSM.  If None, use the model root.
    recurse : bool, optional
        If False, treat the top level of each name as the source/target component.
    include_external_outputs : bool, optional
        If True, show externally connected outputs when transcribing a subsystem.
        Defaults to True.
    subs : tuple, optional
       Character pairs to be substituted. Forbidden characters or just for the sake of nicer names.
    writer: str, optional
        Writer is pyXDSM or XDSMjs.
        Defaults to pyXDSM.
    show_browser : bool, optional
        If True, pop up a browser to view the generated html file.
        Defaults to False.
    add_process_conns: bool
        Add process connections (thin black lines)
        Defaults to True
    quiet : bool
        Set to True to suppress output from pdflatex

    kwargs : dict
        Keyword arguments

    Returns
    -------
        XDSM
    """
    # TODO implement residuals

    writer_name = writer.lower()  # making it case insensitive

    # Box appearance
    box_stacking = kwargs.pop('box_stacking', _DEFAULT_BOX_STACKING)
    box_width = kwargs.pop('box_width', _DEFAULT_BOX_WIDTH)
    box_lines = kwargs.pop('box_lines', _MAX_BOX_LINES)
    # In XDSMjs components are numbered by default, so only add for pyXDSM as an option
    add_component_indices = kwargs.pop('numbered_comps',
                                       True) and (writer_name == 'pyxdsm')
    number_alignment = kwargs.pop('number_alignment',
                                  'horizontal')  # nothing, space or new line

    def format_block(names, **kwargs):
        if writer == 'pyxdsm':
            return _format_block_string(var_names=names,
                                        stacking=box_stacking,
                                        box_width=box_width,
                                        box_lines=box_lines,
                                        **kwargs)
        else:
            return names

    def number_label(number, text, alignment):
        # Adds an index to the label either above or on the left side.
        number_str = '{}: '.format(number)
        if alignment == 'horizontal':
            txt = '{}{}'.format(number_str, text)
            if box_stacking == 'vertical':
                return _multiline_block(txt)
            else:
                return txt
        elif alignment == 'vertical':
            return _multiline_block(number_str, text)
        else:
            return text  # In case of a wrong setting

    connections = viewer_data['connections_list']
    tree = viewer_data['tree']

    # Get the top level system to be transcripted to XDSM
    comps = _get_comps(tree, model_path=model_path, recurse=recurse)
    solvers = []

    conns1, external_inputs1, external_outputs1 = _prune_connections(
        connections, model_path=model_path)

    conns2 = _process_connections(conns1, recurse=recurse, subs=subs)
    external_inputs2 = _process_connections(external_inputs1,
                                            recurse=recurse,
                                            subs=subs)
    external_outputs2 = _process_connections(external_outputs1,
                                             recurse=recurse,
                                             subs=subs)

    conns3 = _accumulate_connections(conns2)
    external_inputs3 = _accumulate_connections(external_inputs2)
    external_outputs3 = _accumulate_connections(external_outputs2)

    if writer_name == 'pyxdsm':  # pyXDSM
        x = XDSMWriter()
    elif writer_name == 'xdsmjs':  # XDSMjs
        x = XDSMjsWriter()
    else:
        msg = 'Undefined XDSM writer "{}"'
        raise ValueError(msg.format(writer_name))

    if optimizer is not None:
        label = optimizer
        if add_component_indices:
            opt_index = len(comps) + len(
                solvers) + 2  # index of last block + 1
            nr_comps = len(x.comps)
            index_str = '{}, {}$ \\rightarrow $ 2'.format(
                nr_comps + 1, opt_index, nr_comps + 2)
            label = number_label(index_str, label, number_alignment)
        x.add_optimizer(label=label)

    if include_solver:
        # Default "run once" solvers are ignored
        # Nonlinear solver has precedence
        msg = "Solvers in the XDSM diagram are not fully supported yet, and needs manual editing."
        warnings.warn(msg)

        solver_str = _format_solver_str(tree,
                                        stacking=box_stacking,
                                        add_indices=add_component_indices)

        if solver_str:  # At least one non-default solver
            if add_component_indices:
                i = len(x.comps) + 1
                solver_str = number_label(i, solver_str, number_alignment)
            solvers.append(solver_str)
            x.add_solver(solver_str)

    design_vars2 = _collect_connections(design_vars)
    responses2 = _collect_connections(responses)

    # Design variables
    for comp, conn_vars in iteritems(design_vars2):
        conn_vars = [_replace_chars(var, subs)
                     for var in conn_vars]  # Format var names
        opt_con_vars = [_opt_var_str(var)
                        for var in conn_vars]  # Optimal var names
        init_con_vars = [_init_var_str(var, writer_name)
                         for var in conn_vars]  # Optimal var names
        x.connect('opt', comp,
                  format_block(conn_vars))  # Connection from optimizer
        x.add_output(comp, format_block(opt_con_vars),
                     side='left')  # Optimal design variables
        x.add_output('opt', format_block(opt_con_vars),
                     side='left')  # Optimal design variables
        x.add_input('opt',
                    format_block(init_con_vars))  # Initial design variables

    # Responses
    for comp, conn_vars in iteritems(responses2):
        conn_vars = [_replace_chars(var, subs)
                     for var in conn_vars]  # Optimal var names
        opt_con_vars = [_opt_var_str(var) for var in conn_vars]
        x.connect(comp, 'opt', conn_vars)  # Connection to optimizer
        x.add_output(comp, format_block(opt_con_vars),
                     side='left')  # Optimal output

    # Add components
    for comp in comps:  # Driver is 1, so starting from 2
        i = len(x.comps) + 1
        label = _replace_chars(comp['name'], substitutes=subs)
        if add_component_indices:
            label = number_label(i, label, number_alignment)
        x.add_comp(name=comp['abs_name'], label=label)

    # Add the connections
    for src, dct in iteritems(conns3):
        for tgt, conn_vars in iteritems(dct):
            x.connect(src, tgt, format_block(conn_vars))

    # Add the externally sourced inputs
    for src, tgts in iteritems(external_inputs3):
        for tgt, conn_vars in iteritems(tgts):
            formatted_conn_vars = [
                _replace_chars(o, substitutes=subs) for o in conn_vars
            ]
            x.add_input(tgt, format_block(formatted_conn_vars))

    # Add the externally connected outputs
    if include_external_outputs:
        for src, tgts in iteritems(external_outputs3):
            output_vars = set()
            for tgt, conn_vars in iteritems(tgts):
                output_vars |= set(conn_vars)
                formatted_outputs = [
                    _replace_chars(o, subs) for o in output_vars
                ]
            x.add_output(src, formatted_outputs, side='right')

    if add_process_conns:
        x.add_workflow()
    x.write(filename, cleanup=cleanup, quiet=quiet, **kwargs)

    if show_browser:
        # path will be specified based on the "out_format", if all required inputs where
        # provided for showing the results.
        if writer_name == 'pyxdsm':  # pyXDSM
            ext = 'pdf'
        elif writer_name == 'xdsmjs':  # XDSMjs
            ext = 'html'
        else:
            err_msg = '"{}" is an invalid writer name.'
            raise ValueError(err_msg.format(writer))
        path = '.'.join([filename, ext])
        webview(path)  # Can open also PDFs

    return x
Exemplo n.º 16
0
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)
Exemplo n.º 17
0
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

    html_begin_tags = """
                      <html>
                      <head>
                        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
                      </head>
                      <body>\n
                      """
    html_end_tags = """
                    </body>
                    </html>
                    """

    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
    with open(os.path.join(libs_dir, "awesomplete.js"), "r") as f:
        awesomplete = f.read()
    with open(os.path.join(libs_dir, "d3.v4.min.js"), "r") as f:
        d3 = f.read()
    with open(os.path.join(libs_dir, "vkBeautify.js"), "r") as f:
        vk_beautify = f.read()

    # grab the src
    with open(os.path.join(src_dir, "constants.js"), "r") as f:
        constants = f.read()
    with open(os.path.join(src_dir, "draw.js"), "r") as f:
        draw = f.read()
    with open(os.path.join(src_dir, "legend.js"), "r") as f:
        legend = f.read()
    with open(os.path.join(src_dir, "modal.js"), "r") as f:
        modal = f.read()
    with open(os.path.join(src_dir, "ptN2.js"), "r") as f:
        pt_n2 = f.read()
    with open(os.path.join(src_dir, "search.js"), "r") as f:
        search = f.read()
    with open(os.path.join(src_dir, "svg.js"), "r") as f:
        svg = f.read()

    # grab the style
    with open(os.path.join(style_dir, "awesomplete.css"), "r") as f:
        awesomplete_style = f.read()
    with open(os.path.join(style_dir, "partition_tree.css"), "r") as f:
        partition_tree_style = f.read()
    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 not embeddable:
        index = html_begin_tags + index + html_end_tags

    # put all style and JS into index
    index = index.replace('{{awesomplete_style}}', awesomplete_style)
    index = index.replace('{{partition_tree_style}}', partition_tree_style)
    index = index.replace('{{fontello}}', encoded_font)
    index = index.replace('{{d3_lib}}', d3)
    index = index.replace('{{awesomplete_lib}}', awesomplete)
    index = index.replace('{{vk_beautify_lib}}', vk_beautify)
    index = index.replace('{{model_data}}', model_viewer_data)
    index = index.replace('{{constants_lib}}', constants)
    index = index.replace('{{modal_lib}}', modal)
    index = index.replace('{{svg_lib}}', svg)
    index = index.replace('{{search_lib}}', search)
    index = index.replace('{{legend_lib}}', legend)
    index = index.replace('{{draw_lib}}', draw)
    index = index.replace('{{ptn2_lib}}', pt_n2)
    if draw_potential_connections:
        index = index.replace('{{draw_potential_connections}}', 'true')
    else:
        index = index.replace('{{draw_potential_connections}}', 'false')

    with open(outfile, 'w') as f:
        f.write(index)

    # open it up in the browser
    if show_browser:
        from openmdao.devtools.webview import webview
        webview(outfile)
Exemplo n.º 18
0
def view_connections(root, outfile='connections.html', show_browser=True,
                     src_filter='', tgt_filter='', precision=6):
    """
    Generates a self-contained html file containing a detailed connection
    viewer.  Optionally pops up a web browser to view the file.

    Parameters
    ----------
    root : system or Problem
        The root for the desired tree.

    outfile : str, optional
        The name of the output html file.  Defaults to 'connections.html'.

    show_browser : bool, optional
        If True, pop up a browser to view the generated html file.
        Defaults to True.

    src_filter : str, optional
        If defined, use this as the initial value for the source system filter.

    tgt_filter : str, optional
        If defined, use this as the initial value for the target system filter.

    precision : int, optional
        Sets the precision for displaying array values.
    """
    if MPI and MPI.COMM_WORLD.rank != 0:
        return

    # since people will be used to passing the Problem as the first arg to
    # the N2 diagram funct, allow them to pass a Problem here as well.
    if isinstance(root, Problem):
        system = root.model
    else:
        system = root

    input_srcs = system._conn_global_abs_in2out

    connections = {
        tgt: src for tgt, src in iteritems(input_srcs) if src is not None
    }

    src2tgts = defaultdict(list)
    units = {n: data.get('units','')
                for n, data in iteritems(system._var_allprocs_abs2meta)}
    vals = {}

    with printoptions(precision=precision, suppress=True, threshold=10000):

        for t in system._var_abs_names['input']:
            tmeta = system._var_abs2meta[t]
            idxs = tmeta['src_indices']

            if t in connections:
                s = connections[t]
                val = _get_output(system, s, idxs)

                # if there's a unit conversion, express the value in the
                # units of the target
                if units[t] and val != "<on remote_proc>":
                    val = convert_units(val, units[s], units[t])

                src2tgts[s].append(t)
            else: # unconnected param
                val = _get_input(system, t, None)

            if isinstance(val, np.ndarray):
                val = np.array2string(val)
            else:
                val = str(val)

            vals[t] = val

        noconn_srcs = sorted((n for n in system._var_abs_names['output']
                                if n not in src2tgts), reverse=True)
        for s in noconn_srcs:
            vals[s] = str(system._outputs[s])

    vals['NO CONNECTION'] = ''

    src_systems = set()
    tgt_systems = set()
    for s in system._var_abs_names['output']:
        parts = s.split('.')
        for i in range(len(parts)):
            src_systems.add('.'.join(parts[:i]))

    for t in system._var_abs_names['input']:
        parts = t.split('.')
        for i in range(len(parts)):
            tgt_systems.add('.'.join(parts[:i]))

    # reverse sort so that "NO CONNECTION" shows up at the bottom
    src2tgts['NO CONNECTION'] = sorted([t for t in system._var_abs_names['input']
                                    if t not in connections], reverse=True)

    src_systems = [{'name':n} for n in sorted(src_systems)]
    src_systems.insert(1, {'name': "NO CONNECTION"})
    tgt_systems = [{'name':n} for n in sorted(tgt_systems)]
    tgt_systems.insert(1, {'name': "NO CONNECTION"})

    data = {
        'src2tgts': sorted(iteritems(src2tgts)),
        'proms': None,
        'units': units,
        'vals': vals,
        'src_systems': src_systems,
        'tgt_systems': tgt_systems,
        'noconn_srcs': noconn_srcs,
        'src_filter': src_filter,
        'tgt_filter': tgt_filter,
    }

    viewer = 'connect_table.html'

    code_dir = os.path.dirname(os.path.abspath(__file__))

    with open(os.path.join(code_dir, viewer), "r") as f:
        template = f.read()

    graphjson = json.dumps(data)

    with open(outfile, 'w') as f:
        s = template.replace("<connection_data>", graphjson)
        f.write(s)

    if show_browser:
        webview(outfile)
Exemplo n.º 19
0
def view_model(problem_or_filename,
               outfile='n2.html',
               show_browser=True,
               embeddable=False):
    """
    Generates an HTML file containing a tree viewer. Optionally pops up a web browser to
    view the file.

    Parameters
    ----------
    problem_or_filename : Either a Problem() or a string
        Problem() : The Problem (after problem.setup()) for the desired tree.
        string : The filename of the case recorder file containing the data required to build the tree.

    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.
    """
    html_begin_tags = """
                      <html>
                      <head>
                        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
                      </head>
                      <body>\n
                      """
    html_end_tags = """
                    </body>
                    </html>
                    """

    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
    with open(os.path.join(libs_dir, "awesomplete.js"), "r") as f:
        awesomplete = f.read()
    with open(os.path.join(libs_dir, "d3.v4.min.js"), "r") as f:
        d3 = f.read()
    with open(os.path.join(libs_dir, "http.js"), "r") as f:
        http = f.read()
    with open(os.path.join(libs_dir, "jquery-3.2.1.min.js"), "r") as f:
        jquery = f.read()
    with open(os.path.join(libs_dir, "vkBeautify.js"), "r") as f:
        vk_beautify = f.read()

    #grab the src
    with open(os.path.join(src_dir, "constants.js"), "r") as f:
        constants = f.read()
    with open(os.path.join(src_dir, "context-menu.js"), "r") as f:
        context_menu = f.read()
    with open(os.path.join(src_dir, "draw.js"), "r") as f:
        draw = f.read()
    with open(os.path.join(src_dir, "legend.js"), "r") as f:
        legend = f.read()
    with open(os.path.join(src_dir, "modal.js"), "r") as f:
        modal = f.read()
    with open(os.path.join(src_dir, "ptN2.js"), "r") as f:
        pt_n2 = f.read()
    with open(os.path.join(src_dir, "search.js"), "r") as f:
        search = f.read()
    with open(os.path.join(src_dir, "svg.js"), "r") as f:
        svg = f.read()

    #grab the style
    with open(os.path.join(style_dir, "awesomplete.css"), "r") as f:
        awesomplete_style = f.read()
    with open(os.path.join(style_dir, "partition_tree.css"), "r") as f:
        partition_tree_style = f.read()
    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()

    #grab the model viewer data
    model_viewer_data = 'var modelData = %s' % json.dumps(
        _get_viewer_data(problem_or_filename))

    #add the necessary HTML tags if we aren't embedding
    if not embeddable:
        index = html_begin_tags + index + html_end_tags

    #put all style and JS into index
    index = index.replace('{{awesomplete_style}}', awesomplete_style)
    index = index.replace('{{partition_tree_style}}', partition_tree_style)
    index = index.replace('{{fontello}}', encoded_font)
    index = index.replace('{{d3_lib}}', d3)
    index = index.replace('{{awesomplete_lib}}', awesomplete)
    index = index.replace('{{vk_beautify_lib}}', vk_beautify)
    index = index.replace('{{model_data}}', model_viewer_data)
    index = index.replace('{{constants_lib}}', constants)
    index = index.replace('{{modal_lib}}', modal)
    index = index.replace('{{svg_lib}}', svg)
    index = index.replace('{{search_lib}}', search)
    index = index.replace('{{legend_lib}}', legend)
    index = index.replace('{{draw_lib}}', draw)
    index = index.replace('{{context_menu_lib}}', context_menu)
    index = index.replace('{{ptn2_lib}}', pt_n2)

    with open(outfile, 'w') as f:
        f.write(index)

    #open it up in the browser
    if show_browser:
        from openmdao.devtools.webview import webview
        webview(outfile)
Exemplo n.º 20
0
def view_connections(root,
                     outfile='connections.html',
                     show_browser=True,
                     src_filter='',
                     tgt_filter='',
                     precision=6):
    """
    Generates a self-contained html file containing a detailed connection
    viewer.  Optionally pops up a web browser to view the file.

    Args
    ----
    root : system or Problem
        The root for the desired tree.

    outfile : str, optional
        The name of the output html file.  Defaults to 'connections.html'.

    show_browser : bool, optional
        If True, pop up a browser to view the generated html file.
        Defaults to True.

    src_filter : str, optional
        If defined, use this as the initial value for the source system filter.

    tgt_filter : str, optional
        If defined, use this as the initial value for the target system filter.

    precision : int, optional
        Sets the precision for displaying array values.
    """
    # since people will be used to passing the Problem as the first arg to
    # the N2 diagram funct, allow them to pass a Problem here as well.
    if isinstance(root, Problem):
        system = root.root
    else:
        system = root

    connections = system._probdata.connections
    to_prom = system._sysdata.to_prom_name
    src2tgts = {}
    units = {
        n: m.get('units', '')
        for n, m in chain(iteritems(system._unknowns_dict),
                          iteritems(system._params_dict))
    }

    vals = {}

    with printoptions(precision=precision, suppress=True, threshold=10000):
        for t, tmeta in iteritems(system._params_dict):
            if t in connections:
                s, idxs = connections[t]
                if idxs is not None:
                    val = system.unknowns[to_prom[s]][idxs]
                else:
                    val = system.unknowns[to_prom[s]]

                # if there's a unit conversion, express the value in the
                # units of the target
                if 'unit_conv' in tmeta:
                    scale, offset = tmeta['unit_conv']
                    val = (val + offset) * scale

                if s not in src2tgts:
                    src2tgts[s] = [t]
                else:
                    src2tgts[s].append(t)
            else:  # unconnected param
                val = system._params_dict[t]['val']

            if isinstance(val, numpy.ndarray):
                val = numpy.array2string(val)
            else:
                val = str(val)

            vals[t] = val

        noconn_srcs = sorted(
            (n for n in system._unknowns_dict if n not in src2tgts),
            reverse=True)
        for s in noconn_srcs:
            vals[s] = str(system.unknowns[to_prom[s]])

    vals['NO CONNECTION'] = ''

    src_systems = set()
    tgt_systems = set()
    for s in src2tgts:
        parts = s.split('.')
        for i in range(len(parts)):
            src_systems.add('.'.join(parts[:i]))

    for t in connections:
        parts = t.split('.')
        for i in range(len(parts)):
            tgt_systems.add('.'.join(parts[:i]))

    # reverse sort so that "NO CONNECTION" shows up at the bottom
    src2tgts['NO CONNECTION'] = sorted([
        t for t in to_prom
        if t not in system._unknowns_dict and t not in connections
    ],
                                       reverse=True)

    src_systems = [{'name': n} for n in sorted(src_systems)]
    src_systems.insert(1, {'name': "NO CONNECTION"})
    tgt_systems = [{'name': n} for n in sorted(tgt_systems)]
    tgt_systems.insert(1, {'name': "NO CONNECTION"})

    data = {
        'src2tgts':
        [(s, ts) for s, ts in sorted(iteritems(src2tgts), reverse=True)],
        'proms':
        to_prom,
        'units':
        units,
        'vals':
        vals,
        'src_systems':
        src_systems,
        'tgt_systems':
        tgt_systems,
        'noconn_srcs':
        noconn_srcs,
        'src_filter':
        src_filter,
        'tgt_filter':
        tgt_filter,
    }

    viewer = 'connect_table.html'

    code_dir = os.path.dirname(os.path.abspath(__file__))

    with open(os.path.join(code_dir, viewer), "r") as f:
        template = f.read()

    graphjson = json.dumps(data)

    with open(outfile, 'w') as f:
        s = template.replace("<connection_data>", graphjson)
        f.write(s)

    if show_browser:
        webview(outfile)
Exemplo n.º 21
0
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)
Exemplo n.º 22
0
def view_model(problem_or_filename, outfile='partition_tree_n2.html', show_browser=True, offline=True, embed=False):
    """
    Generates a self-contained html file containing a tree viewer
    of the specified type.  Optionally pops up a web browser to
    view the file.

    Args
    ----
    problem_or_filename : Either a Problem() or a string
        Problem() : The Problem (after problem.setup()) for the desired tree.
        string : The filename of the case recorder file containing the data required to build the tree.

    outfile : str, optional
        The name of the output html file.  Defaults to 'partition_tree_n2.html'.

    show_browser : bool, optional
        If True, pop up the system default web browser to view the generated html file.
        Defaults to True.

    offline : bool, optional
        If True, embed the javascript d3 library into the generated html file so that the tree can be viewed
        offline without an internet connection.  Otherwise if False, have the html request the latest d3 file
        from https://d3js.org/d3.v4.min.js when opening the html file.
        Defaults to True.

    embed : bool, optional
        If True, export only the innerHTML that is between the body tags, used for embedding the viewer into another html file.
        If False, create a standalone HTML file that has the DOCTYPE, html, head, meta, and body tags.
        Defaults to False.
    """
    viewer = 'partition_tree_n2.template'

    code_dir = os.path.dirname(os.path.abspath(__file__))

    with open(os.path.join(code_dir, viewer), "r") as f:
        template = f.read()

    html_begin_tags = ("<!DOCTYPE html>\n"
        "<html>\n"
        "<head>\n"
        "    <meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\">\n"
        "</head>\n"
        "<body>\n")

    html_end_tags = ("</body>\n"
        "</html>\n")

    display_none_attr = ""

    if embed:
        html_begin_tags = html_end_tags = ""
        display_none_attr = " style=\"display:none\""

    d3_library = "<script src=\"https://d3js.org/d3.v4.min.js\" charset=\"utf-8\"></script>"
    if offline:
        with open(os.path.join(code_dir, 'd3.v4.min.js'), "r") as f:
            d3_library = "<script type=\"text/javascript\"> %s </script>" % (f.read())

    with open(os.path.join(code_dir, "fontello.woff"), "rb") as f:
        encoded_font = str(base64.b64encode(f.read()).decode("ascii"))

    with open(os.path.join(code_dir, 'awesomplete.css'), "r") as f:
            awesomplete_css = "%s" % (f.read())

    with open(os.path.join(code_dir, 'awesomplete.js'), "r") as f:
            awesomplete_js = "%s" % (f.read())

    if isinstance(problem_or_filename, Problem):
        model_viewer_data = get_model_viewer_data(problem_or_filename)
    else:
        # Do not know file type. Try opening to see what works
        file_type = None
        if is_valid_sqlite3_db(problem_or_filename):
            db = SqliteDict(filename=problem_or_filename, flag='r', tablename='metadata')
            file_type = "sqlite"
        else:
            try:
                hdf = h5py.File(problem_or_filename, 'r')
                file_type = 'hdf5'
            except:
                raise ValueError("The given filename is not one of the supported file formats: sqlite or hdf5")

        if file_type == "sqlite":
            model_viewer_data = db['model_viewer_data']
        elif file_type == "hdf5":
            metadata = hdf.get('metadata', None)
            model_viewer_data = pickle.loads(metadata.get('model_viewer_data').value)


    tree_json = json.dumps(model_viewer_data['tree'])
    conns_json = json.dumps(model_viewer_data['connections_list'])

    with open(outfile, 'w') as f:
        f.write(template % (html_begin_tags, awesomplete_css, encoded_font, display_none_attr, d3_library, awesomplete_js, tree_json, conns_json, html_end_tags))

    if show_browser:
        from openmdao.devtools.webview import webview
        webview(outfile)