• 0 Votes
    8 Posts
    575 Views

    Once you have whatever you need as a numpy array I suggest you use one of these functions to visualize it within Sim4Life

    import s4l_v1 as s4l import s4l_v1.document as document import s4l_v1.analysis as analysis import s4l_v1.model as model def visualizeArray(data, x=None,y=None,z=None, unit_name="", unit="", name="", scaling = 1.0, visualize_max = False, scalarrange = None, visualize_isosurface = False, debug = False): """ Create field in postpro to visualize data, if no axis provided then they are automatically assigned based on number of elements in data visualizeArray(data, x=None,y=None,z=None,unit_name="", unit="", name="", scaling = 0.001, goToMax = False) data - numpy array - 3D numpy array x - numpy array - 1D numpy array of x axis coordinates y - numpy array - 1D numpy array of y axis coordinates z - numpy array - 1D numpy array of z axis coordinates unit_name - string - unit name to be displayed unit - string - unit to be displayed name - string - name of field in postpro scaling - float - scaling factor for axes (default 0.001) goToMax - boolean - visualize slice field viewer of maximum in array visualize_slice scalarrange visualize_isosurface isosurface_value debug """ if x is None: x = np.arange(data.shape[0]+1)*.001 if y is None: y = np.arange(data.shape[1]+1)*.001 if z is None: z = np.arange(data.shape[2]+1)*.001 grid = analysis.core.RectilinearGrid() grid.XAxis = np.array(x)*scaling grid.YAxis = np.array(y)*scaling grid.ZAxis = np.array(z)*scaling field = analysis.core.DoubleFieldData() field.Grid = grid if data.size == (len(x) * len(y) * len(z)): field.ValueLocation = analysis.core.eValueLocation.kNode elif data.size == (len(x)-1) * (len(y)-1) * (len(z)-1): field.ValueLocation = analysis.core.eValueLocation.kCellCenter else: print "ERROR: Grid and Data don't match" return False field.NumberOfComponents = 1 field.NumberOfSnapshots = 1 field.Quantity.Unit = s4l.Unit(unit) field.Quantity.Name = unit_name # Note: memory layout is such that x is fastest, z slowest dimension values = data.ravel('F') values = values.astype(np.float64) field.SetField( 0, values ) assert field.Check() producer = analysis.core.TrivialProducer() if name != "": producer.Description = name producer.SetDataObject(field) if visualize_max: sfv = analysis.viewers.SliceFieldViewer() sfv.Inputs[0].Connect( producer.Outputs[0] ) sfv.Slice.Plane = sfv.Slice.Plane.enum.XY sfv.Update(0) sfv.GotoMaxSlice() sfv.Update(0) document.AllAlgorithms.Add(sfv) sfv = analysis.viewers.SliceFieldViewer() sfv.Inputs[0].Connect( producer.Outputs[0] ) sfv.Slice.Plane = sfv.Slice.Plane.enum.YZ sfv.Update(0) sfv.GotoMaxSlice() sfv.Update(0) document.AllAlgorithms.Add(sfv) sfv = analysis.viewers.SliceFieldViewer() sfv.Inputs[0].Connect( producer.Outputs[0] ) sfv.Slice.Plane = sfv.Slice.Plane.enum.XZ sfv.Update(0) sfv.GotoMaxSlice() sfv.Update(0) document.AllAlgorithms.Add(sfv) if visualize_isosurface: iso_surface_viewer = analysis.viewers.IsoSurfaceViewer() iso_surface_viewer.Inputs[0].Connect( producer.Outputs[0] ) iso_surface_viewer.Data.Mode = iso_surface_viewer.Data.Mode.enum.QuantityRealModulus #H CHECK - maybe should just use default (delete this line) iso_surface_viewer.Visualization.ScalarBarVisible = False iso_surface_viewer.UpdateAttributes() iso_surface_viewer.Update(0) document.AllAlgorithms.Add(iso_surface_viewer) document.AllAlgorithms.Add(producer) return producer def visualizeComplexArray(data, x=None,y=None,z=None, unit_name="", unit="", name="", scaling = 1.0, visualize_max = False, scalarrange = None, visualize_isosurface = False, debug = False): """ Create field in postpro to visualize data, if no axis provided then they are automatically assigned based on number of elements in data visualizeArray(data, x=None,y=None,z=None,unit_name="", unit="", name="", scaling = 0.001, goToMax = False) data - numpy array - 3D numpy array x - numpy array - 1D numpy array of x axis coordinates y - numpy array - 1D numpy array of y axis coordinates z - numpy array - 1D numpy array of z axis coordinates unit_name - string - unit name to be displayed unit - string - unit to be displayed name - string - name of field in postpro scaling - float - scaling factor for axes (default 0.001) goToMax - boolean - visualize slice field viewer of maximum in array visualize_slice scalarrange visualize_isosurface isosurface_value debug """ if x is None: x = np.arange(data.shape[0]+1)*.001 if y is None: y = np.arange(data.shape[1]+1)*.001 if z is None: z = np.arange(data.shape[2]+1)*.001 grid = analysis.core.RectilinearGrid() grid.XAxis = np.array(x)*scaling grid.YAxis = np.array(y)*scaling grid.ZAxis = np.array(z)*scaling field = analysis.core.ComplexDoubleFieldData() field.Grid = grid if data.size == (len(x) * len(y) * len(z)): field.ValueLocation = analysis.core.eValueLocation.kNode elif data.size == (len(x)-1) * (len(y)-1) * (len(z)-1): field.ValueLocation = analysis.core.eValueLocation.kCellCenter else: print "ERROR: Grid and Data don't match" return False field.NumberOfComponents = 1 field.NumberOfSnapshots = 1 field.Quantity.Unit = s4l.Unit(unit) field.Quantity.Name = unit_name # Note: memory layout is such that x is fastest, z slowest dimension values = data.ravel('F') #values = values.astype(np.complex64) field.SetField( 0, values ) assert field.Check() producer = analysis.core.TrivialProducer() if name != "": producer.Description = name producer.SetDataObject(field) if visualize_max: sfv = analysis.viewers.SliceFieldViewer() sfv.Inputs[0].Connect( producer.Outputs[0] ) sfv.Slice.Plane = sfv.Slice.Plane.enum.XY sfv.Update(0) sfv.GotoMaxSlice() sfv.Update(0) document.AllAlgorithms.Add(sfv) sfv = analysis.viewers.SliceFieldViewer() sfv.Inputs[0].Connect( producer.Outputs[0] ) sfv.Slice.Plane = sfv.Slice.Plane.enum.YZ sfv.Update(0) sfv.GotoMaxSlice() sfv.Update(0) document.AllAlgorithms.Add(sfv) sfv = analysis.viewers.SliceFieldViewer() sfv.Inputs[0].Connect( producer.Outputs[0] ) sfv.Slice.Plane = sfv.Slice.Plane.enum.XZ sfv.Update(0) sfv.GotoMaxSlice() sfv.Update(0) document.AllAlgorithms.Add(sfv) if visualize_isosurface: iso_surface_viewer = analysis.viewers.IsoSurfaceViewer() iso_surface_viewer.Inputs[0].Connect( producer.Outputs[0] ) iso_surface_viewer.Data.Mode = iso_surface_viewer.Data.Mode.enum.QuantityRealModulus #H CHECK - maybe should just use default (delete this line) iso_surface_viewer.Visualization.ScalarBarVisible = False iso_surface_viewer.UpdateAttributes() iso_surface_viewer.Update(0) document.AllAlgorithms.Add(iso_surface_viewer) document.AllAlgorithms.Add(producer) return producer def visualize2DArray(data, x=None,y=None,z=None, unit_name="", unit="", name="", scaling = 1., visualize_slice = False, scalarrange = None, visualize_isosurface = False, isosurface_value = None, debug = False): """ Create field in postpro to visualize data, if no axis provided then they are automatically assigned based on number of elements in data visualize2DArray(data, x=None,y=None,z=None, unit_name="", unit="", name="", scaling = 0.001, visualize = False, scalarrange = None) data - numpy array - 3D numpy array x - numpy array - 1D numpy array of x axis coordinates y - numpy array - 1D numpy array of y axis coordinates z - numpy array - 1D numpy array of z axis coordinates unit_name - string - unit name to be displayed unit - string - unit to be displayed name - string - name of field in postpro scaling - float - scaling factor for axes (default 0.001) visualize - bool - automatically extract field """ from numpy import newaxis # Deal with dimension of data if data.ndim == 2: data = data[:,:,newaxis] elif data.ndim < 2 or data.ndim > 3: print "Data Dimensions Error" return # Deal with scalar axis by turning into array if np.isscalar(x): x = [x] elif np.isscalar(y): y = [y] elif np.isscalar(z): z = [z] #If axes are not set, then make axes if x is None: x = np.arange(data.shape[0]+1)*.001 if y is None: y = np.arange(data.shape[1]+1)*.001 if z is None: z = np.arange(data.shape[2]+1)*.001 # Deal with monotonically decreasing axes if np.all(np.diff(x) < 0) and np.size(x) > 1: x = x[::-1] data = data[::-1] if debug == True: print "Warning: Monotonically decreasing x axes" if np.all(np.diff(y) < 0) and np.size(y) > 1: y = y[::-1] data = data[:,::-1] if debug == True: print "Warning: Monotonically decreasing y axes" if np.all(np.diff(z) < 0) and np.size(z) > 1: z = z[::-1] data = data[:,:,::-1] if debug == True: print "Warning: Monotonically decreasing z axes" grid = analysis.core.RectilinearGrid() grid.XAxis = np.array(x)*scaling grid.YAxis = np.array(y)*scaling grid.ZAxis = np.array(z)*scaling field = analysis.core.DoubleFieldData() field.Grid = grid if data.size == (len(x) * len(y) * len(z)): field.ValueLocation = analysis.core.eValueLocation.kNode elif data.size == (len(x)-1) * (len(y)-1) * (len(z)-1): field.ValueLocation = analysis.core.eValueLocation.kCellCenter else: print "ERROR: Grid and Data don't match" return field.NumberOfComponents = 1 field.NumberOfSnapshots = 1 field.Quantity.Unit = s4l.Unit(unit) field.Quantity.Name = unit_name # Note: memory layout is such that x is fastest, z slowest dimension values = data.ravel('F') values = values.astype(np.float64) field.SetField( 0, values ) assert field.Check() producer = analysis.core.TrivialProducer() if name != "": producer.Description = name producer.SetDataObject(field) # Adding a SliceSurfaceViewer if visualize_slice: sfv = analysis.viewers.SliceFieldViewer() sfv.Inputs[0].Connect( producer.Outputs[0] ) if len(x) == 1: sfv.Slice.Plane = sfv.Slice.Plane.enum.YZ elif len(y) == 1: sfv.Slice.Plane = sfv.Slice.Plane.enum.XZ elif len(z) == 1: sfv.Slice.Plane = sfv.Slice.Plane.enum.XY sfv.Visualization.ScalarBarVisible = False if scalarrange != None: sfv.ScalarRange = scalarrange sfv.Update(0) document.AllAlgorithms.Add(sfv) # Adding a IsoSurfaceViewer if visualize_isosurface: iso_surface_viewer = analysis.viewers.IsoSurfaceViewer() iso_surface_viewer.Inputs[0].Connect( producer.Outputs[0] ) if isosurface_value is not None: iso_surface_viewer.IsoValues = (isosurface_value,) iso_surface_viewer.Data.Mode = iso_surface_viewer.Data.Mode.enum.QuantityRealModulus #H CHECK - maybe should just use default (delete this line) iso_surface_viewer.Visualization.ScalarBarVisible = False iso_surface_viewer.UpdateAttributes() iso_surface_viewer.Update() if scalarrange != None: iso_surface_viewer.ScalarRange = scalarrange iso_surface_viewer.UpdateAttributes() iso_surface_viewer.Update() document.AllAlgorithms.Add(iso_surface_viewer) document.AllAlgorithms.Add(producer) return producer

    to use it then you would just need to do:

    visualize2DArray(my_data, x_axis, y_axis, z_coordinate)

    and then it should show up in the Postpro / Analysis tab for you to work this

  • 0 Votes
    2 Posts
    623 Views

    This looks quite good, thank you for providing your scripts.
    Note that, for the second method, you could create your cylinder directly at the desired position:

    cylinder2 = model.CreateSolidCylinder(Vec3(0,1,-15),Vec3(0,1,-15),0.5)

    There is also the XCoredModeling.CoverWires() function that allows you to make a surface (i.e. face) out of a circle entity.

    Last, but not least, note that the line model_to_grid_filter.MaximumEdgeLength is ultimately what determines the tradeoff between accuracy and computational cost of the interpolation (since it defines the resolution of the triangulated mesh on which the interpolation is done).