def evaluate(input_rows, data, aggregate): quantities = [ QuantityFactory.create_quantity( symbol_type=ROW_IDX_TO_SYMBOL_NAME[idx], value=ureg.parse_expression(row['Editable Value'])) for idx, row in enumerate(input_rows) if row['Editable Value'] ] if data and len(data) > 0: quantities += json.loads(data, cls=MontyDecoder).values() if not quantities: raise PreventUpdate material = Material() for quantity in quantities: material.add_quantity(quantity) graph = Graph() output_material = graph.evaluate(material) if aggregate: output_quantities = output_material.get_aggregated_quantities( ).values() else: output_quantities = output_material.get_quantities() output_rows = [{ 'Property': quantity.symbol.display_names[0], 'Value': quantity.pretty_string(sigfigs=3) } for quantity in output_quantities] output_table = dt.DataTable(id='output-table', rows=output_rows, editable=False) # TODO: clean up input_quantity_names = [q.symbol.name for q in quantities] derived_quantity_names = set( [q.symbol.name for q in output_quantities]) - \ set(input_quantity_names) material_graph_data = graph_conversion( graph.get_networkx_graph(), nodes_to_highlight_green=input_quantity_names, nodes_to_highlight_yellow=list(derived_quantity_names)) options = AESTHETICS['global_options'] options['edges']['color'] = '#000000' output_graph = html.Div(GraphComponent(id='material-graph', graph=material_graph_data, options=options), style={ 'width': '100%', 'height': '400px' }) return [output_graph, html.Br(), output_table]
def test_graph_conversion(self): graph = Graph() converted = graph_conversion(graph.get_networkx_graph()) serialized = json.dumps(converted) self.assertIsNotNone(serialized) # Ensure that there are both nodes and proper edges self.assertIn('Band gap', [n['label'] for n in converted['nodes']]) self.assertIn({'from': 'band_gap', "to": "Is Metallic"}, converted['edges'])
def test_graph_conversion(self): graph = Graph() converted = graph_conversion(graph.get_networkx_graph()) serialized = json.dumps(converted) self.assertIsNotNone(serialized) # Ensure that there are both nodes and proper edges self.assertIn('Band gap', [n['data']['label'] for n in converted if n['group'] == 'nodes']) self.assertIn({'source': 'band_gap', "target": "Is Metallic"}, [n['data'] for n in converted if n['group'] == 'edges'])
def model_layout(model_name): """Create a Dash layout for a provided model. Args: model_name: an instance of an AbstractModel subclass Returns: Dash layout """ # dict to hold layouts for each section layouts = OrderedDict() # instantiate model from name model = DEFAULT_MODEL_DICT[model_name] model_title = html.Div(className='row', children=[ html.H3(model.title), ]) # TODO: costly, should just construct subgraph directly? g = Graph() subgraph = nx.ego_graph(g.get_networkx_graph(), model, undirected=True) options = AESTHETICS['global_options'] if "arrows" in options["edges"]: options["edges"]["arrows"] = "to" layouts['Graph'] = html.Div(GraphComponent( id="model_graph", graph=graph_conversion(subgraph), options=AESTHETICS['global_options']), style={ 'width': '100%', 'height': '300px' }) if model.categories: tags = html.Ul(className="tags", children=[ html.Li(tag, className="tag") for tag in model.categories ]) layouts['Tags'] = tags if model.references: references = html.Div([ dcc.Markdown(references_to_markdown(ref)) for ref in model.references ]) layouts['References'] = references symbols = html.Div(children=[ html.Div(className='row', children=[ html.Div(className='two columns', children=[str(symbol)]), html.Div( className='ten columns', children=[ dcc.Link( DEFAULT_SYMBOLS[prop_name].display_names[0], href='/property/{}'.format(prop_name)) ]) ]) for symbol, prop_name in model.symbol_property_map.items() ]) layouts['Symbols'] = symbols layouts['Description'] = dcc.Markdown(model.description) if model.validate_from_preset_test(): sample_data_header = html.Div( className='row', children=[ html.Div(className='five columns', style={'text-align': 'center'}, children=[html.H4('Input(s)')]), html.Div(className='two columns', style={'text-align': 'center'}, children=[html.H4('->')]), html.Div(className='five columns', style={'text-align': 'center'}, children=[html.H4('Output(s)')]) ]) layouts['Sample Code'] = html.Div([ dcc.Markdown( "Propnet models can be called directly, with propnet acting " "as a library of tested materials science models. Sample code for this " "model is as follows:"), dcc.SyntaxHighlighter(model.example_code) ]) sublayouts = [] for title, layout in layouts.items(): sublayouts.append(html.H6(title)) sublayouts.append(layout) return html.Div([ model_title, html.Br(), *sublayouts, html.Br(), #dcc.Link('< Back to Models', href='/model'), #html.Br(), dcc.Link('< Back', href='/explore') ])
def symbol_layout(symbol_name, aesthetics=None): """Create a Dash layout for a provided symbol. Args: symbol_name (str): a symbol name aesthetics (dict): an aesthetics configuration dictionary Returns: Dash layout """ aesthetics = aesthetics or AESTHETICS.copy() # list to hold layouts for each section layouts = [] symbol = DEFAULT_SYMBOLS[symbol_name] main_name = symbol.display_names[0] layouts.append(html.H6('Graph')) # TODO: costly, should just construct subgraph directly? g = Graph() subgraph = nx.ego_graph(g.get_networkx_graph(), symbol, undirected=True, radius=2) options=AESTHETICS['global_options'] if "arrows" in options["edges"]: options["edges"]["arrows"] = "to" set_(aesthetics, "node_options.show_model_labels", True) layouts.append(html.Div( GraphComponent( id="model_graph", graph=graph_conversion(subgraph, aesthetics=AESTHETICS), options=AESTHETICS['global_options'] ), style={'width': '100%', 'height': '300px'} )) if len(symbol.display_names) > 1: display_names = ", ".join(symbol.display_names[1:]) other_names = dcc.Markdown("Also known as: {}".format(display_names)) layouts.append(other_names) if len(symbol.display_symbols) > 1: symbols = " ".join(symbol.display_symbols) symbols = dcc.Markdown("Common symbols: {}".format(symbols)) layouts.append(symbols) if symbol.category in ('property', 'condition'): units = dcc.Markdown("Canonical units: **{}**".format(symbol.unit_as_string)) dimension = dcc.Markdown("**{}**".format(symbol.dimension_as_string)) layouts.append(units) layouts.append(dimension) if symbol.comment: layouts.append(dcc.Markdown(symbol.comment)) return html.Div([ main_name, html.Br(), html.Div(layouts), html.Br(), #dcc.Link('< Back to Properties', href='/property'), #html.Br(), dcc.Link('< Back', href='/explore') ])