def draw(data, size=(400, 225), node_size=2.0, edge_size=0.25, default_node_color="0xaaaaaa", default_edge_color="0x777777", z=20): """Draws an interactive 3D visualization of the inputted graph. Args: data: Either an adjacency list of tuples (ie. [(1,2),...]) or json size: (Optional) Dimensions of visualization, in pixels node_size: (Optional) Defaults to 2.0 edge_size: (Optional) Defaults to 0.25 default_node_color: (Optional) If loading data without specified "color" properties, this will be used. Default is "0xaaaaaa" default_edge_color: (Optional) If loading data without specified "color" properties, this will be used. Default is "0x222222" z: (Optional) Starting z position of the camera. Default is 20 Inputting an adjacency list into `data` results in a "default" graph type. For more customization, generate a json file using other methods before running the drawer. """ # Guess the input format and handle accordingly if isinstance(data, list): graph = json_formatter.dumps(generate(data)) elif isinstance(data, dict): graph = json_formatter.dumps(data) else: # Support both files and strings try: with open(data) as in_file: graph = in_file.read() except: graph = data # This calls igraph and uses some IPython magic to get everything linked script = ("var $d = $('<div/>').attr('id', 'graph_' + utils.uuid());" "$d.width(%d); $d.height(%d);" "igraph.create($d, {nodeSize: %f, edgeSize: %f," " defaultNodeColor: '%s'," " defaultEdgeColor: '%s'});" "igraph.draw(%s);" "container.show();" "element.append($d);" % (size[0], size[1], node_size, edge_size, default_node_color, default_edge_color, graph)) # Execute js and display the results in a div (see script for more) display(Javascript(data=lib_script + script))
def to_json(data, compress=False): """Converts the output of `generate(...)` to formatted json. Floats are rounded to three decimals and positional vectors are printed on one line with some whitespace buffer. """ return json.compress(data) if compress else json.dumps(data)
def run(structure, input_type="cif", output_type="cif", l=1.2, h_i0=-2.0, charge_precision=3, method="ewald", m_r=2, m_k=2, eta=50.0, ionization_data_path=DEFAULT_IONIZATION_PATH, charge_data_path=DEFAULT_CHARGE_PATH): """Runs EQeq on the inputted structure, returning charge data. Args: structure: Either a filename or data encoding a chemical. input_type: (Optional) Specifies input type. Can be anything supported by openbabel, as well as "json" output_type: (Optional) Specifies the output type. Currently, options are "cif", "mol", "pdb", "car", "json", "list", and "files". The first four return modified chemical data formats, "list" returns a Python object, "json" is that object serialized, and "files" saves files of all possible output types. l: (Optional) Lambda, the dielectric screening parameter. h_i0: (Optional) The electron affinity of hydrogen. charge_precision: (Optional) Number of decimals to use for charges. method: (Optional) Method to use. Can be "direct" (default), "nonperiodic", or "ewald". m_r: (Optional) Number of unit cells to consider in "real space". This is measured radially, so m_r = 1 evaluates 27 unit cells. m_k: (Optional) Number of unit cells to consider in "frequency space". This is measured radially, so m_k = 1 evaluates 27 unit cells. eta: (Optional) Ewald splitting parameter ionization_data_path: (Optional) A path to the file containing ion- ization data. By default, assumes the data is in the EQeq folder and saved as "ionizationdata.dat". charge_data_path: (Optional) A path to the file containing charge- center data. By default, assumes the data is in the EQeq folder and saved as "chargecenters.dat". Returns: A string representing the charged crystal. Returns nothing if the output type is set to "files" """ # Error handling on string params. Should spare users some annoyance. o, m = output_type.lower(), method.lower() if o not in ["cif", "pdb", "car", "mol", "json", "list", "files"]: raise NotImplementedError("Output format '%s' is not supported!" % o) if m not in ["direct", "nonperiodic", "ewald"]: raise NotImplementedError("Method '%s' is not supported!" % m) # If linked to openbabel, use it to handle json interconversion externally if input_type != "cif": structure = format_converter.convert(structure, input_type, "cif") structure = structure.replace("\t", " ") # Calls libeqeq.so's run method, returning a string of data result = eqeq.run(structure, ("json" if output_type == "list" else output_type), l, h_i0, charge_precision, method, m_r, m_k, eta, ionization_data_path, charge_data_path) if output_type == "list": return json.loads(result) # This option appends atoms in json/object data with a "charge" attribute if output_type == "json": obj = format_converter.convert(structure, "cif", "object") result = json.loads(result) for atom, charge in zip(obj["atoms"], result): atom["charge"] = charge result = json.dumps(obj) return result
def to_json(data): """Converts the output of `generate(...)` to formatted json. Args: data: The data structure outputted by `generate()` Floats are rounded to three decimals and positional vectors are printed on one line with some whitespace buffer. """ return json_formatter.dumps(data)
def convert(data, in_format, out_format, pretty=False): """Converts between two inputted chemical formats. Args: data: A string representing the chemical file to be converted. If the `in_format` is "json", this can also be a Python object in_format: The format of the `data` string. Can be "json" or any format recognized by Open Babel out_format: The format to convert to. Can be "json" or any format recognized by Open Babel pretty: (Optional) If True and `out_format` is "json", will pretty- print the output for human readability Returns: A string representing the inputted `data` in the specified `out_format` """ # Decide on a json formatter depending on desired prettiness dumps = json.dumps if pretty else json.compress # If it's a json string, load it if in_format == "json" and isinstance(data, basestring): data = json.loads(data) # A little "hack" to format inputted json if in_format == "json" and out_format == "json": return json.dumps(data) # These are converted manually to retain crystallographic information if in_format == "json" and out_format == "cif": return json_to_cif(data) # These use the open babel library to interconvert, with additions for json mol = (json_to_pybel(data) if in_format == "json" else pybel.readstring(in_format.encode("ascii"), "".join(i for i in data if ord(i) < 128) .encode("ascii"))) # Infer structure in cases where the input format has no specification if not mol.OBMol.HasNonZeroCoords(): mol.make3D() mol.OBMol.Center() # EQeq takes a specific cif format that openbabel does not output. # This manually overrides that. if out_format == "cif": return json_to_cif(pybel_to_json(mol)) if out_format == "object": return pybel_to_json(mol) elif out_format == "json": return dumps(pybel_to_json(mol)) else: return mol.write(out_format)
def convert(data, in_format, out_format, pretty=False): """Converts between two inputted chemical formats. Args: data: A string representing the chemical file to be converted. If the `in_format` is "json", this can also be a Python object in_format: The format of the `data` string. Can be "json" or any format recognized by Open Babel out_format: The format to convert to. Can be "json" or any format recognized by Open Babel pretty: (Optional) If True and `out_format` is "json", will pretty- print the output for human readability Returns: A string representing the inputted `data` in the specified `out_format` """ # Decide on a json formatter depending on desired prettiness dumps = json.dumps if pretty else json.compress # If it's a json string, load it if in_format == "json" and isinstance(data, basestring): data = json.loads(data) # A little "hack" to format inputted json if in_format == "json" and out_format == "json": return json.dumps(data) # These are converted manually to retain crystallographic information if in_format == "json" and out_format == "cif": return json_to_cif(data) # These use the open babel library to interconvert, with additions for json mol = (json_to_pybel(data) if in_format == "json" else pybel.readstring( in_format.encode("ascii"), "".join(i for i in data if ord(i) < 128).encode("ascii"))) # Infer structure in cases where the input format has no specification if not mol.OBMol.HasNonZeroCoords(): mol.make3D() mol.OBMol.Center() # EQeq takes a specific cif format that openbabel does not output. # This manually overrides that. if out_format == "cif": return json_to_cif(pybel_to_json(mol)) if out_format == "object": return pybel_to_json(mol) elif out_format == "json": return dumps(pybel_to_json(mol)) else: return mol.write(out_format)
def convert(data, in_format, out_format, filename=None, pretty=False): """Converts between two inputted chemical formats. Args: data: A string representing the chemical file to be converted. If the `in_format` is "json", this can also be a Python object in_format: The format of the `data` string. Can be "json" or any format recognized by Open Babel out_format: The format to convert to. Can be "json" or any format recognized by Open Babel filename: (Optional) The name of the file containing `data`. This is used primarily to encode data saved in the file naming scheme of the old building-block format pretty: (Optional) If True and `out_format` is "json", will pretty- print the output for human readability Returns: A string representing the inputted `data` in the specified `out_format` """ # Decide on a json formatter depending on desired prettiness dumps = json.dumps if pretty else json.compress # If it's a json string, load it if in_format == "json" and isinstance(data, basestring): data = json.loads(data) # A little "hack" to format inputted json if in_format == "json" and out_format == "json": return json.dumps(data) # These use the open babel library to interconvert, with additions for json mol = (json_to_pybel(data) if in_format == "json" else pybel.readstring(in_format.encode("ascii"), "".join(i for i in data if ord(i) < 128) .encode("ascii"))) # Infer structure in cases where the input format has no specification if not mol.OBMol.HasNonZeroCoords(): mol.make3D() mol.OBMol.Center() return (dumps(pybel_to_json(mol, name=filename)) if out_format == "json" else mol.write(out_format.encode("ascii")))
if ind > 0: metInfo[row[1]] = {} metInfo[row[1]]['name'] = row[0] metInfo[row[1]]['KEGGID'] = row[2] metInfo[row[1]]['fullname'] = row[3] metInfo[row[1]]['centralcarbon'] = int(row[9]) metInfo[row[1]]['aminoacid'] = int(row[8]) metInfo[row[1]]['nucleotide'] = int(row[7]) metInfo[row[1]]['cofactor'] = int(row[6]) metInfo[row[1]]['fattyacid'] = int(row[5]) metInfo[row[1]]['other'] = int(row[4]) with open(sys.argv[-1]) as in_file: network = json.load(in_file) for key in network['nodes'].keys(): if metInfo[key]['centralcarbon']: network['nodes'][key]['color'] = 'red' elif metInfo[key]['aminoacid']: network['nodes'][key]['color'] = 'green' elif metInfo[key]['nucleotide']: network['nodes'][key]['color'] = 'blue' elif metInfo[key]['cofactor']: network['nodes'][key]['color'] = 'yellow' elif metInfo[key]['fattyacid']: network['nodes'][key]['color'] = 'purple' elif metInfo[key]['other']: network['nodes'][key]['color'] = 'gray' print(json_formatter.dumps(network))
# creates the initial arrangement for the nodes based on the starting node master_nodes = layer(edges, available_nodes, start_node=starting_node, depth=0) # get the range of depth and counts for each layer depth_count = {} for node in master_nodes.keys(): if master_nodes[node]["depth"] in depth_count.keys(): depth_count[master_nodes[node]["depth"]] = depth_count[ master_nodes[node]["depth"]] + 1 else: depth_count[master_nodes[node]["depth"]] = 1 # space out particular layers based on how many nodes are in a particular # layer for layer_of_interest, count in depth_count.items(): if count > threshold_for_spacing: nodes_of_interest = [] for node in master_nodes.keys(): if master_nodes[node]["depth"] == layer_of_interest: nodes_of_interest.append(node) master_nodes = space(master_nodes, nodes_of_interest, force_iter=10) # Convert to json and print print(json_formatter.dumps({"edges": edges, "nodes": master_nodes}))
if __name__ == '__main__': import sys import json import json_formatter # See if input is a file try: with open(sys.argv[-1]) as in_file: edges = json.load(in_file) except IOError: edges = json.loads(sys.argv[-1]) # Convert to internal representation edges = [{'source': str(s), 'target': str(t)} for s, t in edges] # Handle additional args kwargs = {'force_strength': 5.0, 'is_3d': True} for i, arg in enumerate(sys.argv): if arg == '--force-strength': kwargs['force_strength'] = float(sys.argv[i + 1]) elif arg == '--2D': kwargs['is_3d'] = False # Generate nodes nodes = run(edges, **kwargs) # Convert to json and print print(json_formatter.dumps({'edges': edges, 'nodes': nodes}))
available_nodes = set(e["source"] for e in edges) | set(e["target"] for e in edges) # creates the initial arrangement for the nodes based on the starting node master_nodes = layer(edges, available_nodes, start_node=starting_node, depth=0) # get the range of depth and counts for each layer depth_count = {} for node in master_nodes.keys(): if master_nodes[node]["depth"] in depth_count.keys(): depth_count[master_nodes[node]["depth"]] = depth_count[ master_nodes[node]["depth"]] + 1 else: depth_count[master_nodes[node]["depth"]] = 1 # space out particular layers based on how many nodes are in a particular # layer for layer_of_interest, count in depth_count.items(): if count > threshold_for_spacing: nodes_of_interest = [] for node in master_nodes.keys(): if master_nodes[node]["depth"] == layer_of_interest: nodes_of_interest.append(node) master_nodes = space( master_nodes, nodes_of_interest, force_iter=10) # Convert to json and print print(json_formatter.dumps({"edges": edges, "nodes": master_nodes}))
edges = json.loads(sys.argv[-1]) # Convert to internal representation edges = [{"source": str(s), "target": str(t)} for s, t in edges] # Handle additional args kwargs = { "edge_length": 20, "separation": 5, "density": 0, "is_concentric": False, "is_3d": True } for i, arg in enumerate(sys.argv): if arg == "--edge-length": kwargs["edge_length"] = float(sys.argv[i + 1]) elif arg == "--separation": kwargs["separation"] = float(sys.argv[i + 1]) elif arg == "--density": kwargs["density"] = float(sys.argv[i + 1]) elif arg == "--concentric": kwargs["is_concentric"] = True elif arg == "--2D": kwargs["is_3d"] = False # Generate nodes nodes = run(edges, **kwargs) # Convert to json and print print json_formatter.dumps({"edges": edges, "nodes": nodes})
# See if input is a file try: with open(sys.argv[-1]) as in_file: edges = json.load(in_file) except IOError: edges = json.loads(sys.argv[-1]) # Convert to internal representation edges = [{"source": str(s), "target": str(t)} for s, t in edges] # Handle additional args kwargs = {"edge_length": 20, "separation": 5, "density": 0, "is_concentric": False, "is_3d": True} for i, arg in enumerate(sys.argv): if arg == "--edge-length": kwargs["edge_length"] = float(sys.argv[i + 1]) elif arg == "--separation": kwargs["separation"] = float(sys.argv[i + 1]) elif arg == "--density": kwargs["density"] = float(sys.argv[i + 1]) elif arg == "--concentric": kwargs["is_concentric"] = True elif arg == "--2D": kwargs["is_3d"] = False # Generate nodes nodes = run(edges, **kwargs) # Convert to json and print print json_formatter.dumps({"edges": edges, "nodes": nodes})