[docs]defproject_to_vtk(project,filename="",fill_nans=None,fill_infs=None):r""" Save network and phase data to a single vtp file for visualizing in Paraview. Parameters ---------- network : Network The Network containing the data to be written phases : list, optional A list containing Phase(s) containing data to be written filename : str, optional Filename to write data. If no name is given the file is named after the network fill_nans : scalar The value to use to replace NaNs with. The VTK file format does not work with NaNs, so they must be dealt with. The default is `None` which means property arrays with NaNs are not written to the file. Other useful options might be 0 or -1, but the user must be aware that these are not real values, only place holders. fill_infs : scalar The value to use to replace infs with. The default is ``None`` which means that property arrays containing ``None`` will *not* be written to the file, and a warning will be issued. A useful value is """network=project.networkalgs=project.algorithms# Check if any of the phases has time seriestransient=is_transient(algs)iftransient:logger.warning("vtp format does not support transient data, "+"use xdmf instead")iffilename=="":filename=project.namefilename=_parse_filename(filename=filename,ext="vtp")am=project_to_dict(project=project,categorize_by=["object","data"])am=pd.json_normalize(am,sep='.').to_dict(orient='records')[0]forkinlist(am.keys()):am[k.replace('.',' | ')]=am.pop(k)key_list=list(sorted(am.keys()))points=network["pore.coords"]pairs=network["throat.conns"]num_points=np.shape(points)[0]num_throats=np.shape(pairs)[0]root=ET.fromstring(_TEMPLATE)piece_node=root.find("PolyData").find("Piece")piece_node.set("NumberOfPoints",str(num_points))piece_node.set("NumberOfLines",str(num_throats))points_node=piece_node.find("Points")coords=_array_to_element("coords",points.T.ravel("F"),n=3)points_node.append(coords)lines_node=piece_node.find("Lines")connectivity=_array_to_element("connectivity",pairs)lines_node.append(connectivity)offsets=_array_to_element("offsets",2*np.arange(len(pairs))+2)lines_node.append(offsets)point_data_node=piece_node.find("PointData")cell_data_node=piece_node.find("CellData")forkeyinkey_list:array=am[key]ifarray.dtype=="O":logger.warning(key+" has dtype object,"+" will not write to file")else:ifarray.dtype==bool:array=array.astype(int)ifnp.any(np.isnan(array)):iffill_nansisNone:logger.warning(key+" has nans,"+" will not write to file")continueelse:array[np.isnan(array)]=fill_nansifnp.any(np.isinf(array)):iffill_infsisNone:logger.warning(key+" has infs,"+" will not write to file")continueelse:array[np.isinf(array)]=fill_infselement=_array_to_element(key,array)ifarray.size==num_points:point_data_node.append(element)elifarray.size==num_throats:cell_data_node.append(element)tree=ET.ElementTree(root)tree.write(filename)withopen(filename,"r+")asf:string=f.read()string=string.replace("</DataArray>","</DataArray>\n\t\t\t")f.seek(0)# consider adding header: '<?xml version="1.0"?>\n'+f.write(string)