Skip to content
  • Search
Skins
  • Light
  • Cerulean
  • Cosmo
  • Flatly
  • Journal
  • Litera
  • Lumen
  • Lux
  • Materia
  • Minty
  • Morph
  • Pulse
  • Sandstone
  • Simplex
  • Sketchy
  • Spacelab
  • United
  • Yeti
  • Zephyr
  • Dark
  • Cyborg
  • Darkly
  • Quartz
  • Slate
  • Solar
  • Superhero
  • Vapor

  • Default (No Skin)
  • No Skin
Collapse

ZMT zurich med tech

  1. Home
  2. Sim4Life
  3. Python API
  4. Acoustic simulation - phase information needed (using Python)

Acoustic simulation - phase information needed (using Python)

Scheduled Pinned Locked Moved Python API
11 Posts 2 Posters 1.6k Views
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • A Offline
    A Offline
    Annalisa
    wrote on last edited by Annalisa
    #1

    Hi!
    How can I extract the phase value of the pressure p(f) on a sensor point directly by Python?
    I don' t know if that's possible ( to directly extract the phase).

    Alternatively, I can extract the real and imaginary part of the complex pressure on my n sensors and then derive the phase values. BUT I can do it, extracting in separate excel files each pressure value. Not easy to handle.
    I would need to allocate the n complex pressure values in a single array and then, calculate the phase from these values. I am moving my first steps in Python, so I really appreciate some helps.

    Thanks

    1 Reply Last reply
    1
    • M Offline
      M Offline
      montanaro
      wrote on last edited by
      #2

      Hi,

      For a point sensor p(f):

      Under properties you get the option for Complex component and can select Phase (deg).

      from Python:

      
      import numpy
      import s4l_v1.analysis as analysis
      import s4l_v1.document as document
      import s4l_v1.model as model
      import s4l_v1.units as units
      from s4l_v1 import ReleaseVersion
      from s4l_v1 import Unit
      
      # Adding a new SimulationExtractor
      simulation = document.AllSimulations["Single Element Focused Transducer"]
      simulation_extractor = simulation.Results()
      
      # Adding a new AcousticSensorExtractor
      acoustic_sensor_extractor = simulation_extractor["Focus  (SEFT)"]
      
      # Get Point Sensor 
      input = acoustic_sensor_extractor.Outputs["p(f)"]
      # Get Point Sensor data (output is complex pressure)
      output = input.Data.GetComponent(0)
      
      # Post Process: Angle
      output_angle = numpy.angle(output)
      
      1 Reply Last reply
      1
      • M Offline
        M Offline
        montanaro
        wrote on last edited by
        #3

        For Field sensor p(x,y,z,f):

        Easiest is to create a 'Calculator' and calculate it yourself, then right click field and select 'To Python..' to get the corresponding Python code

        Select overall field -> p(x,y,z,f) -> Field Data Tools -> Calculator -> Value Location: Cell Center -> Scalar Variables: F (Re{p}) -> Scalar Variables: G (Im{p}) -> Expression: atan(G/F) (change it to read this or whatever suitable formula you wish)

        Then you can use the viewers (note, careful with division by zero, you'll need to adjust the color bar accordingly, also you'll get 'wrapped' angles)

        (In the next reply I'll show you how you can extract the field, manipulate it, and plot it back ... Very useful to plot arbitrary numpy arrays in S4L)

        Python code:

        import numpy
        import s4l_v1.analysis as analysis
        import s4l_v1.document as document
        import s4l_v1.model as model
        import s4l_v1.units as units
        from s4l_v1 import ReleaseVersion
        from s4l_v1 import Unit
        
        # Creating the analysis pipeline
        # Adding a new SimulationExtractor
        simulation = document.AllSimulations["Single Element Focused Transducer"]
        simulation_extractor = simulation.Results()
        
        # Adding a new AcousticSensorExtractor
        acoustic_sensor_extractor = simulation_extractor["Overall Field"]
        
        # Adding a new FieldCalculator
        inputs = [acoustic_sensor_extractor.Outputs["p(x,y,z,f)"]]
        field_calculator = analysis.field.FieldCalculator(inputs=inputs)
        field_calculator.Expression = u"atan(G/F)"
        field_calculator.ValueLocation = field_calculator.ValueLocation.enum.CellCenter
        field_calculator.UpdateAttributes()
        document.AllAlgorithms.Add(field_calculator)
        
        # Adding a new SliceFieldViewer
        inputs = [field_calculator.Outputs["Result(x,y,z)"]]
        slice_field_viewer = analysis.viewers.SliceFieldViewer(inputs=inputs)
        slice_field_viewer.Data.Mode = slice_field_viewer.Data.Mode.enum.QuantityRealPart
        slice_field_viewer.Slice.Plane = slice_field_viewer.Slice.Plane.enum.XZ
        slice_field_viewer.Slice.Index = 155
        slice_field_viewer.UpdateAttributes()
        document.AllAlgorithms.Add(slice_field_viewer)
        
        1 Reply Last reply
        1
        • M Offline
          M Offline
          montanaro
          wrote on last edited by
          #4

          To get the field as a numpy array:

          import numpy
          import s4l_v1.analysis as analysis
          import s4l_v1.document as document
          import s4l_v1.model as model
          import s4l_v1.units as units
          from s4l_v1 import ReleaseVersion
          from s4l_v1 import Unit
          
          # Creating the analysis pipeline
          # Adding a new SimulationExtractor
          simulation = document.AllSimulations["Single Element Focused Transducer"]
          simulation_extractor = simulation.Results()
          
          # Adding a new AcousticSensorExtractor
          acoustic_sensor_extractor = simulation_extractor["Overall Field"]
          document.AllAlgorithms.Add(acoustic_sensor_extractor)
          
          # Adding a new SliceFieldViewer
          field = acoustic_sensor_extractor.Outputs["p(x,y,z,f)"]
          # Remember to update
          # Otherwise this script will fail unless you have already extracted results in the GUI
          field.Update()
          
          field_np = field.Data.Field(0) # Field as flattened 1D array
          # 3D Field dimensions (which might be different to grid dimensions)
          # Data is often times defined at cell centers, Grid at cell nodes
          dims = numpy.array(field.Data.Grid.Dimensions)
          if numpy.prod(dims) != len(field_np):
          	dims = dims-1
          field_np = field_np.reshape(dims, order='F') # Field as 3D array
          
          xaxis = field.Data.Grid.XAxis
          yaxis = field.Data.Grid.YAxis
          zaxis = field.Data.Grid.ZAxis
          
          # You can now manipulate field_np as you wish
          field_angle = numpy.unwrap(numpy.angle(field_np))
          

          To plot your numpy array back into sim4life you create what is known as a 'Trivial Producer' which holds your numpy array which can be manipulated in the analysis tab:

          data = field_angle
          
          grid = analysis.core.RectilinearGrid()
          grid.XAxis = xaxis
          grid.YAxis = yaxis
          grid.ZAxis = zaxis
          
          # Careful, the new field is a field of Doubles, changes to ComplexFieldData
          # if you need to work with complex numbers
          new_field = analysis.core.DoubleFieldData()  
          new_field.Grid = grid
          if data.size == (len(grid.XAxis) * len(grid.YAxis) * len(grid.ZAxis)):
          	new_field.ValueLocation = analysis.core.eValueLocation.kNode
          elif data.size == (len(grid.XAxis)-1) * (len(grid.YAxis)-1) * (len(grid.ZAxis)-1):
          	new_field.ValueLocation = analysis.core.eValueLocation.kCellCenter
          else:
          	print "ERROR: Grid and Data don't match"
          	assert False
          new_field.NumberOfComponents = 1
          new_field.NumberOfSnapshots = 1
          new_field.Quantity.Name = "My Field"
          
          # Note: memory layout is such that x is fastest, z slowest dimension
          values = data.ravel('F')	
          values = values.astype(numpy.float64) # Change if working with ComplexFieldData
          new_field.SetField( 0, values )
          assert new_field.Check()
          
          producer = analysis.core.TrivialProducer()
          producer.Description = "My Trivial Producer"
          producer.SetDataObject(new_field)
          
          document.AllAlgorithms.Add(producer)
          
          1 Reply Last reply
          1
          • A Offline
            A Offline
            Annalisa
            wrote on last edited by
            #5

            Thank you very much for the detailed instructions.
            I tried the first code you gave me and it works for a single sensor as expected.
            (just need to add input.Update()).
            In my case I have several sensors so I need to use a for loop in order to extract the phase value on each sensor.
            My code is:

            from future import absolute_import
            from future import print_function
            import sys, os, math
            import h5py
            import s4l_v1.model as model
            import s4l_v1.simulation.acoustic as acoustic
            import s4l_v1.analysis as analysis
            import s4l_v1.document as document
            import scipy.io

            import numpy
            import s4l_v1.document as document
            import s4l_v1.materials.database as database
            import s4l_v1.model as model
            import s4l_v1.simulation.acoustic as acoustic
            import s4l_v1.units as units
            from s4l_v1 import ReleaseVersion
            from s4l_v1 import Unit

            try:
            # Define the version to use for default values
            ReleaseVersion.set_active(ReleaseVersion.version5_2)

            # Creating the analysis pipeline
            # Adding a new SimulationExtractor
            simulation = document.AllSimulations["My simulation"]
            simulation_extractor = simulation.Results()
            
            
            for i in range(0,128):
            
            	# Adding a new AcousticSensorExtractor
            	acoustic_sensor_extractor = simulation_extractor["Sensor" + str(i)]
            	document.AllAlgorithms.Add(acoustic_sensor_extractor)
            	input = acoustic_sensor_extractor.Outputs["p(f)"]
            	input.Update()
            
            	# Get Point Sensor data (output is complex pressure)
            	output = input.Data.GetComponent(i)
            	
            	# Post Process: Angle
            	output_angle = numpy.angle(output)
            

            except Exception as exc:
            import traceback
            traceback.print_exc(exc)
            Reset active version to default
            ReleaseVersion.reset()
            raise(exc)

            When I run this code the console gives this message:
            File "C:\Users\PC\Documents\Sim4Life\5.2\Scripts\temp\BP p(f) extractor.py", line 58
            Reset active version to default
            ^
            SyntaxError: invalid syntax

            any idea?

            Thanks

            Annalisa

            1 Reply Last reply
            0
            • M Offline
              M Offline
              montanaro
              wrote on last edited by
              #6

              "input.Update()"

              • you're right. As a general rule, make sure to always have this (if results are extracted and updated in the GUI you might not get this error)

              Not sure why you get this error but this line seems wrong:
              GetComponent(i) ... Should probably be GetComponent(0)

              Components are typically useful when you have vector fields, In which case GetComponent(0) probably corresponds to E_x, GetComponent(1) to E_y, etc.. They should typically be set to 0 since most fields have only 1 'component'. (not to be confused with snapshots which typically refer to time snapshots or frequency snapshots, where 0 is the main harmonic)

              1 Reply Last reply
              0
              • A Offline
                A Offline
                Annalisa
                wrote on last edited by
                #7

                GetComponent(0), yes you are right. That was a typo.
                The problem still persists.
                How can I extract the phase on each sensors using a "for" loop?

                thanks again

                1 Reply Last reply
                0
                • M Offline
                  M Offline
                  montanaro
                  wrote on last edited by montanaro
                  #8

                  Just tried it on a simple example and seemed to work ... Maybe get rid of

                  try:
                  # Define the version to use for default values
                  ReleaseVersion.set_active(ReleaseVersion.version5_2)
                  

                  and

                  except Exception as exc:
                  import traceback
                  traceback.print_exc(exc)
                  Reset active version to default
                  ReleaseVersion.reset()
                  raise(exc)
                  

                  (seems that 'reset active version ...' line should be a comment)

                  This is what I tried:

                  # -*- coding: utf-8 -*-
                  # Creating the analysis pipeline
                  # Adding a new SimulationExtractor
                  simulation = document.AllSimulations["Single Element Focused Transducer - Copy"]
                  simulation_extractor = simulation.Results()
                  
                  for i in range(1,5):
                  
                  	# Adding a new AcousticSensorExtractor
                  	acoustic_sensor_extractor = simulation_extractor["Focus " + str(i)]
                  	document.AllAlgorithms.Add(acoustic_sensor_extractor)
                  	input = acoustic_sensor_extractor.Outputs["p(f)"]
                  	input.Update()
                  
                  	# Get Point Sensor data (output is complex pressure)
                  	output = input.Data.GetComponent(0)
                  	
                  	# Post Process: Angle
                  	output_angle = numpy.angle(output)
                  	print i, output_angle
                  

                  and this was my output:

                  1 [ 1.69136047]
                  2 [ 1.69136047]
                  3 [ 1.69136047]
                  4 [ 1.69136047]
                  

                  (my point sensors were all at the same location)

                  1 Reply Last reply
                  1
                  • A Offline
                    A Offline
                    Annalisa
                    wrote on last edited by
                    #9
                    This post is deleted!
                    1 Reply Last reply
                    0
                    • A Offline
                      A Offline
                      Annalisa
                      wrote on last edited by
                      #10

                      Now, I want assign each phase value to an element of my transducer.
                      But using my code:

                      for i in range(0,128):
                      	
                      	source_settings = acoustic.SourceSettings()
                      	source_settings.Name = "Source Settings" + str(i)
                      	source_settings.Amplitude = 100000.0, Unit("Pa")		
                      	source_settings.Phase = -output_angle[i], units.Degrees
                      	simulation.Add(source_settings, components[i])
                      

                      does not work because in output_angle (evaluated with the previous code) I have only the last value (corresponding to sensor#127).
                      I would need to allocate all the phase values in a callable list (?) in order to be able to use the for loop.
                      Thank for further helps

                      1 Reply Last reply
                      0
                      • M Offline
                        M Offline
                        montanaro
                        wrote on last edited by montanaro
                        #11

                        You need to make output_angle into an array and append the new values at the end every time (the i-th element will have the i-th phase you want)

                        output_angle = numpy.array([])
                        for i in range(0,128):
                        	# your code
                        	output_angle = numpy.append(output_angle, numpy.angle(output))
                        
                        1 Reply Last reply
                        1
                        Reply
                        • Reply as topic
                        Log in to reply
                        • Oldest to Newest
                        • Newest to Oldest
                        • Most Votes


                        • Login

                        • Don't have an account? Register

                        • Login or register to search.
                        • First post
                          Last post
                        0
                        • Search