Beispiel #1
0
def kinematics_remove_outliers( positions, displacements, filter_size, threshold=2, absolut_threshold=False, filter_high=True, filter_base_field=0 ):

  number_of_nodes = positions.shape[0]
  number_of_displacements = displacements.shape[1]

  if positions.shape[1] != 3:
      try: logging.info.warn("kinematics_remove_outliers(): Not given three positions. Stopping.")
      except: print "kinematics_remove_outliers(): Not given three positions. Stopping."
      return -1

  if number_of_nodes != displacements.shape[0]:
      try: logging.info.warn("kinematics_remove_outliers(): Not given the same amout of positions and displacements. Stopping.")
      except: print "kinematics_remove_outliers(): Not given the same amout of positions and displacements. Stopping."
      return -1

  nodes_z, nodes_y, nodes_x = calculate_node_spacing( positions )
   
  # Initialize output matrix
  result = numpy.zeros( ( number_of_nodes, number_of_displacements ) )

  #-----------------------------------------------------------------------
  #-  Reshape the displacements so that we easily have the neighbours   --
  #-----------------------------------------------------------------------
  # This is a 4D array of z, y, x positions + component...
  displacements = numpy.array( displacements.reshape( ( len( nodes_z ), len( nodes_y ), len( nodes_x ), number_of_displacements ) ) )
  
  mask = spot_outliers(  displacements[ :, :, :, filter_base_field ], filter_size, threshold, absolut_threshold, filter_high )

  for i in range( number_of_displacements ):
    result[ :, i ] = remove_outliers(  displacements[ :, :, :, i ], filter_size, mask ).reshape( ( number_of_nodes ) )

  return result, mask.reshape( ( number_of_nodes ) )
Beispiel #2
0
def kinematics_median_filter_fnc( positions, displacements, filter_size ):
  # 2014-07-23 Eddy (on holiday in Greece...)
  # The median filter above seems both unnecessarily complicated and
  #   not general enough to deserve to name median_filter.
  # => Renaming it kinematics_median_filter.
  
  number_of_nodes = positions.shape[0]
  number_of_displacements = displacements.shape[1]

  if positions.shape[1] != 3:
      try: logging.info.warn("kinematics_median_filter_fnc(): Not given three positions. Stopping.")
      except: print "kinematics_median_filter_fnc(): Not given three positions. Stopping."
      return -1

  if number_of_nodes != displacements.shape[0]:
      try: logging.info.warn("kinematics_median_filter_fnc(): Not given the same amout of positions and displacements. Stopping.")
      except: print "kinematics_median_filter_fnc(): Not given the same amout of positions and displacements. Stopping."
      return -1

  nodes_z, nodes_y, nodes_x = calculate_node_spacing( positions )
   

  try:
      # Figure out spacing from first two nodes positions
      y_spacing = nodes_y[1] - nodes_y[0]
      x_spacing = nodes_x[1] - nodes_x[0]
      if len(nodes_z) == 1:
        #we are working with 2D images
        z_spacing = y_spacing
      else:
        z_spacing = nodes_z[1] - nodes_z[0]
  except IndexError:
      try: logging.info.warn("kinematics_median_filter_fnc(): Not enough nodes to calculate median filter")
      except: print "kinematics_median_filter_fnc(): Not enough nodes to calculate median filter"
      return -1

  # If the node spacing is not the same in every direction, we're not sure that this
  #   can work.
  if z_spacing != y_spacing or z_spacing != x_spacing:
      try: logging.info.warn("kinematics_median_filter_fnc(): The spacing is different, and I'm not sure I can handle this. Stopping.")
      except: "kinematics_median_filter_fnc(): The spacing is different, and I'm not sure I can handle this. Stopping."
      return -1

  # Define output matrix
  result = numpy.zeros( ( number_of_nodes, number_of_displacements ) )

  #-----------------------------------------------------------------------
  #-  Reshape the displacements so that we easily have the neighbours   --
  #-----------------------------------------------------------------------
  # This is a 4D array of z, y, x positions + component...
  displacements = numpy.array( displacements.reshape( ( len( nodes_z ), len( nodes_y ), len( nodes_x ), number_of_displacements ) ) )

  for i in range( number_of_displacements ):
    result[ :, i ] = median_filter_nans( numpy.squeeze(displacements[ :, :, :, i ]), filter_size ).reshape( ( number_of_nodes ) )

  return result
def kinematics_median_filter_fnc( positions, displacements, filter_size ):
  # The median filter above seems both unnecessarily complicated and
  #   not general enough to deserve to name median_filter.
  # Making a new stub (above) to warn users.

  #-----------------------------------------------------------------------
  #-  Calculate nodal spacing                                           --
  #-      (this comes from regular_prior_interpolator.py)               --
  #-----------------------------------------------------------------------
  number_of_nodes = positions.shape[0]
  number_of_displacements = displacements.shape[1]

  if positions.shape[1] != 3:
      print "  -> kinematics_median_filter(): Not given three positions. Stopping."
      return -1

  if number_of_nodes != displacements.shape[0]:
      print "  -> kinematics_median_filter(): Not given the same amout of positions and displacements. Stopping."
      return -1

  nodes_z, nodes_y, nodes_x = calculate_node_spacing( positions )
   

  try:
      # Figure out spacing from first two nodes positions
      y_spacing = nodes_y[1] - nodes_y[0]
      x_spacing = nodes_x[1] - nodes_x[0]
      if len(nodes_z) == 1:
        #we are working with 2D images
        z_spacing = y_spacing
      else:
        z_spacing = nodes_z[1] - nodes_z[0]
  except IndexError:
      raise Exception('Warning: Not enough nodes to calculate median filter')

  # If the node spacing is not the same in every direction, we're not sure that this
  #   can work.
  if z_spacing != y_spacing or z_spacing != x_spacing:
    raise Exception("kinematics_median_filter_fnc(): the spacing is different, and I'm not sure I can handle this. Stopping.")

  # Define output matrix
  result = numpy.zeros( ( number_of_nodes, number_of_displacements ) )

  #-----------------------------------------------------------------------
  #-  Reshape the displacements so that we easily have the neighbours   --
  #-----------------------------------------------------------------------
  # This is a 4D array of z, y, x positions + component...
  displacements = numpy.array( displacements.reshape( ( len( nodes_z ), len( nodes_y ), len( nodes_x ), number_of_displacements ) ) )

  for i in range( number_of_displacements ):
    result[ :, i ] = median_filter_nans( numpy.squeeze(displacements[ :, :, :, i ]), filter_size ).reshape( ( number_of_nodes ) )

  return result
Beispiel #4
0
    def show_displacements(self):
        # This function create a new window to show the output displacements

        # load the kinematic file if different from the last loaded
        self.get_kinematics()

        number_of_nodes = self.kinematics.shape[0]
        nodes_z, nodes_y, nodes_x = calculate_node_spacing(
            self.kinematics[:, 1:4])
        displacements = self.kinematics[:, 4:7]
        displacements = numpy.array(
            displacements.reshape(
                (len(nodes_z), len(nodes_y), len(nodes_x), 3)))

        self.win_plots = Toplevel(self.master)

        currentRow = 0
        currentCol = 0

        ### PLOT IMAGES ###
        # function in show_image.py that plot the displacements and command button for zoom, slice setting, and histograms plotting
        plot_matrix(self.win_plots, displacements,
                    self.variables['images_2D'].get()).grid(row=currentRow,
                                                            column=currentCol,
                                                            sticky=W + E,
                                                            padx=5,
                                                            pady=(0, 10),
                                                            columnspan=5)
        currentRow += 1

        ### FILTERS ###
        # create a frame to control the filters paramenters
        self.filter_control = filterFrame(self.win_plots,
                                          self.variables['images_2D'].get())
        self.filter_control.grid(row=currentRow,
                                 column=currentCol,
                                 sticky=W + E,
                                 padx=5,
                                 pady=(0, 10),
                                 columnspan=5)
        currentRow += 1

        ### COMMAND BUTTONS ###
        filterBut = Button(self.win_plots,
                           text="Apply Filters",
                           command=self.apply_filters)
        filterBut.grid(row=currentRow,
                       column=currentCol,
                       sticky=W + E,
                       padx=5,
                       pady=(0, 10))
        saveBut = Button(self.win_plots,
                         text="Save Kinematics",
                         command=self.save_kinematics)
        saveBut.grid(row=currentRow,
                     column=currentCol + 1,
                     sticky=W + E,
                     padx=5,
                     pady=(0, 10))
        saveBut = Button(self.win_plots,
                         text="Close",
                         command=self.win_plots.destroy)
        saveBut.grid(row=currentRow,
                     column=currentCol + 4,
                     sticky=W + E,
                     padx=5,
                     pady=(0, 10))
        currentRow += 1

        # centre the window on the main one
        self.win_plots.update_idletasks()
        width = self.win_plots.winfo_width()
        height = self.win_plots.winfo_height()
        self.win_plots.geometry(
            "%dx%d%+d%+d" %
            (width, height, self.master.master.winfo_x() +
             self.master.master.winfo_width() / 2 - width / 2,
             self.master.master.winfo_y() +
             self.master.master.winfo_height() / 2 - height / 2))
        self.win_plots.geometry('')
Beispiel #5
0
def regular_strain_large_strain_centred(positions,
                                        displacements,
                                        neighbourhoodDistance,
                                        calculateConnectivity=False):

    pos = positions.copy()
    # neighbourhoodDistance can take positive integer values
    # if =1 we include (2*neighbourhoodDistance+1)^3-1
    numberOfNeighbours = (2 * neighbourhoodDistance + 1)**3 - 1

    try:
        logging.log.info(
            "regular_strain_large_strain_centered(): Calculating strains in Large Deformations framework \
        \n (Geers et al., 1996, Computing strain felds from discrete displacement fields in 2D-solids ) taking neighbours plus or minus {:d}"
            .format(neighbourhoodDistance))
    except:
        print "regular_strain_large_strain_centered(): Calculating strains in Large Deformations framework \
        \n (Geers et al., 1996, Computing strain felds from discrete displacement fields in 2D-solids ) taking neighbours plus or minus {:d}".format(
            neighbourhoodDistance)

    nodalRealtivePositionsRef = numpy.zeros(
        (numberOfNeighbours, 3))  # Delta_X_0 in document
    nodalRealtivePositionsDef = numpy.zeros(
        (numberOfNeighbours, 3))  # Delta_X_t in document
    I = numpy.eye(3)  # identity matrix
    ########################################################################
    ##  Relative nodal positions                                          ##
    ########################################################################
    #-----------------------------------------------------------------------
    #-  Calculate nodal spacing                                           --
    #-      (this comes from regular_prior_interpolator.py)               --
    #-----------------------------------------------------------------------

    number_of_nodes = positions.shape[0]

    connectivity = numpy.zeros((0, 1))

    nodes_z, nodes_y, nodes_x = calculate_node_spacing(positions)

    try:
        # Figure out spacing from first two nodes positions
        z_spacing = nodes_z[1] - nodes_z[0]
        y_spacing = nodes_y[1] - nodes_y[0]
        x_spacing = nodes_x[1] - nodes_x[0]
    except IndexError:
        raise Exception('Warning: Not enough nodes to calculate strain')

    ## Define strain matrix
    ##  2014-11-12 PB and EA: changing strain 6-component vector to a full 3x3 strain tensor
    strain = numpy.zeros((len(nodes_z), len(nodes_y), len(nodes_x), 3, 3))
    rot = numpy.zeros((len(nodes_z), len(nodes_y), len(nodes_x), 3, 3))
    volStrain = numpy.zeros(
        (len(nodes_z) - 1, len(nodes_y) - 1, len(nodes_x) - 1, 1))

    ########################################################################
    ##  Getting the displacements around each node                        ##
    ########################################################################
    #-----------------------------------------------------------------------
    #-  Reshape the displacements so that we easily have the neighbours   --
    #-----------------------------------------------------------------------
    #displacements_x = displacements[ :, 2 ].reshape( ( len( nodes_z ), len( nodes_y ), len( nodes_x ) ) )
    #displacements_y = displacements[ :, 1 ].reshape( ( len( nodes_z ), len( nodes_y ), len( nodes_x ) ) )
    #displacements_z = displacements[ :, 0 ].reshape( ( len( nodes_z ), len( nodes_y ), len( nodes_x ) ) )

    # This is a 4D array of x, y, z positions + component...
    displacements = displacements.reshape(
        (len(nodes_z), len(nodes_y), len(nodes_x), 3))
    positions = positions.reshape(
        (len(nodes_z), len(nodes_y), len(nodes_x), 3))

    #-----------------------------------------------------------------------
    #-  Fetch neighbourhood displacements from x y z displacements        --
    #-    i.e., fill in the nodalDisplacements matrix  numpy.zeros( ( 8, 3 ) )            --
    #-----------------------------------------------------------------------
    for z in range(neighbourhoodDistance,
                   len(nodes_z) - neighbourhoodDistance):
        print "\tregular_strain_large_strain_centred: Working on z=%04i/%04i\r" % (
            z, len(nodes_z) - 1),
        for y in range(neighbourhoodDistance,
                       len(nodes_y) - neighbourhoodDistance):
            for x in range(neighbourhoodDistance,
                           len(nodes_x) - neighbourhoodDistance):
                sX0X0 = numpy.zeros((3, 3))
                sX0Xt = numpy.zeros((3, 3))
                m0 = numpy.zeros((3))
                mt = numpy.zeros((3))

                neighbourCount = 0
                centralNodePosition = positions[z, y, x, :]
                centralNodeDisplacement = displacements[z, y, x, :]
                for nZ in range(-neighbourhoodDistance,
                                neighbourhoodDistance + 1):
                    for nY in range(-neighbourhoodDistance,
                                    neighbourhoodDistance + 1):
                        for nX in range(-neighbourhoodDistance,
                                        neighbourhoodDistance + 1):
                            if nZ == 0 and nY == 0 and nX == 0:
                                # we're actually on the node we're studying, skipping this point
                                pass
                            else:
                                # In the reference case this is just the node spacing
                                #                                                 absolute position of this neighbour node
                                #                                                                                         minus abs position of central node
                                nodalRealtivePositionsRef[
                                    neighbourCount, :] = positions[
                                        z + nZ, y + nY,
                                        x + nX, :] - centralNodePosition

                                #                                                absolute position of this neighbour node
                                #                                                                                         plus displacement of this neighbour node
                                #                                                                                                                                      minus abs position of central node
                                #                                                                                                                                                            minus displacement of central node
                                nodalRealtivePositionsDef[
                                    neighbourCount, :] = positions[
                                        z + nZ, y + nY,
                                        x + nX, :] + displacements[
                                            z + nZ, y + nY, x +
                                            nX, :] - centralNodePosition - centralNodeDisplacement
                                for u in range(3):
                                    for v in range(3):
                                        sX0X0[
                                            u, v] += nodalRealtivePositionsRef[
                                                neighbourCount,
                                                u] * nodalRealtivePositionsRef[
                                                    neighbourCount, v]
                                        sX0Xt[
                                            u, v] += nodalRealtivePositionsRef[
                                                neighbourCount,
                                                u] * nodalRealtivePositionsDef[
                                                    neighbourCount, v]

                                m0 += nodalRealtivePositionsRef[
                                    neighbourCount, :]
                                mt += nodalRealtivePositionsDef[
                                    neighbourCount, :]
                                neighbourCount += 1
                if numpy.all(
                        numpy.isfinite(nodalRealtivePositionsDef)) == False:
                    strain[z, y, x, :, :] = numpy.zeros((3, 3)) * numpy.nan
                    rot[z, y, x, :, :] = numpy.zeros((3, 3)) * numpy.nan
                    volStrain[z, y, x] = numpy.nan

                else:
                    # multiply the sums sX0X0, sX0Xt by numberOfNeighbours
                    sX0X0 = numberOfNeighbours * sX0X0
                    sX0Xt = numberOfNeighbours * sX0Xt

                    A = sX0X0 - numpy.dot(m0, m0)
                    C = sX0Xt - numpy.dot(m0, mt)

                    try:
                        F = numpy.dot(numpy.linalg.inv(A), C)
                        # Right Cauchy-Green tensor (as opposed to left)
                        rot[z, y, x, :, :] = 0.5 * numpy.dot(F.T, -F)

                        # Green-Lagrange tensors
                        E = 0.5 * (numpy.dot(F.T, F) - I)

                        # Call our strain "E"
                        strain[z, y, x, :, :] = E
                        volStrain[z, y, x] = numpy.linalg.det(F) - 1
                        #print "\tregular_strain_large_strain_centred: success!!!"

                        # 2017-03-09 EA and JD: If VTK set calculate this -- excluding by default because the .append is crazy slow
                        if calculateConnectivity:
                            #Adding a point cell to connectivity only if strain is non nans
                            connectivity = numpy.append(connectivity, [[
                                x + len(nodes_x) * y +
                                len(nodes_x) * len(nodes_y) * z
                            ]],
                                                        axis=0)

                    except numpy.linalg.linalg.LinAlgError:
                        print "\tLinAlgError: A", A
                        strain[z, y, x, :, :] = numpy.zeros((3, 3)) * numpy.nan
                        rot[z, y, x, :, :] = numpy.zeros((3, 3)) * numpy.nan
                        volStrain[z, y, x] = numpy.nan

    try:
        logging.log.info(
            "regular_strain_large_strain_centered(): strain calculation done.")
    except:
        print "regular_strain_large_strain_centered(): strain calculation done."

    return [strain, rot, connectivity, volStrain]
Beispiel #6
0
def process_results(  kinematics, data ):
    
    interpolate_strain = False
  
    # 2015-04-14 EA: Adding default option to save output files as tiff, which requires tifffile.py
    if data.saveTIFF:
      # tools already added to path
      from tools.tifffile import imsave

    # Generate a mask for the output of the files.
    #   1. All nodes which have reported an error need to be masked.
    #   2. All nodes which have low CC can also be optionally masked.

    # Generate all fields replacing error Nodes with NaNs -- to read from kinematics array...
    # 2013-08-22 - Calculation of node spacing moved to ./tools/calculate_node_spacing.py
    nodes_z, nodes_y, nodes_x = calculate_node_spacing( kinematics[ :, 1:4 ] )

    cc_field = numpy.array( kinematics[ :, 10 ] ).astype( '<f4' )

    mask = construct_mask( kinematics, data.cc_threshold )

    #-----------------------------------------------------------------------
    #-  Done generating the mask...                                       --
    #-----------------------------------------------------------------------
    # Clean up the kinematics with the mask
    for i in [ 4,5,6,7,8,9 ]: kinematics[ :, i ] += mask

    # Remove outliers
    if data.remove_outliers_filter_size != None:
      if data.remove_outliers_filter_size > 0:
          try: logging.log.info("process_results(): Removing outliers") 
          except: print "process_results(): Removing outliers"
          try:
            #kinematics[ :, 4:10 ] = data.kinematics_median_filter_fnc( kinematics[ :, 1:4 ], kinematics[ :, 4:10 ], data.kinematics_median_filter )
            [ kinematics[ :, 4:10 ], mask_outliers ] = kinematics_remove_outliers( kinematics[ :, 1:4 ], kinematics[ :, 4:10 ], \
                data.remove_outliers_filter_size, data.remove_outliers_threshold, data.remove_outliers_absolut_threshold, data.remove_outliers_filter_high, data.filter_base_field )
            #mask[ numpy.where(mask_outliers==1) ] = 0
            mask[ numpy.isfinite(kinematics[:,4]) ] = 0
          except Exception as exc:
            try: logging.log.warn(exc.message)
            except: print exc.message
            pass

    # filter kinematics...
    if data.kinematics_median_filter != None:
      if data.kinematics_median_filter > 0:
          try: logging.log.info("process_results(): Applying a Kinematics Median filter of {:0.1f} (3 means ±1)".format( data.kinematics_median_filter ))
          except: print "process_results(): Applying a Kinematics Median filter of {:0.1f} (3 means ±1)".format( data.kinematics_median_filter )
          try:
            kinematics[ :, 4:10 ] = kinematics_median_filter_fnc( kinematics[ :, 1:4 ], kinematics[ :, 4:10 ], data.kinematics_median_filter )
            mask[ numpy.isfinite(kinematics[:,4]) ] = 0
          except Exception as exc:
            try: logging.log.warn(exc.message)
            except: print exc.message

    if data.pixel_size_ratio != 1:
      if data.image_centre is not None:
          kinematics = correct_pixel_size_changing( kinematics, data.pixel_size_ratio, data.image_centre )
      else:
          raise Exception('Image centre needed to correct pixel size ratio')

    try: logging.log.info( "Writing output files to {}/{}".format( data.DIR_out, data.output_name ) )
    except: print "Writing output files to {}/{}".format( data.DIR_out, data.output_name )

    if data.saveTIFF:
      if data.saveError: imsave( data.DIR_out + "/%s-error-field-%04ix%04ix%04i.tif"%( data.output_name, len(nodes_x), len(nodes_y), len(nodes_z) ), kinematics[ :, 11 ].reshape( ( len(nodes_z), len(nodes_y), len(nodes_x) ) ).astype( '<f4' ) )
      if data.saveCC:    imsave( data.DIR_out +    "/%s-cc-field-%04ix%04ix%04i.tif"%( data.output_name, len(nodes_x), len(nodes_y), len(nodes_z) ),            cc_field.reshape( ( len(nodes_z), len(nodes_y), len(nodes_x) ) ).astype( '<f4' ) )
      if data.saveMask:  imsave( data.DIR_out +        "/%s-mask-%04ix%04ix%04i.tif"%( data.output_name, len(nodes_x), len(nodes_y), len(nodes_z) ),                mask.reshape( ( len(nodes_z), len(nodes_y), len(nodes_x) ) ).astype( '<f4' ) )
    if data.saveRAW:
      if data.saveError: kinematics[ :, 11 ].astype( '<f4' ).tofile( data.DIR_out + "/%s-error-field-%04ix%04ix%04i.raw"%( data.output_name, len(nodes_x), len(nodes_y), len(nodes_z)) )
      if data.saveCC:    cc_field.astype( '<f4' ).tofile(           data.DIR_out + "/%s-cc-field-%04ix%04ix%04i.raw"%( data.output_name, len(nodes_x), len(nodes_y), len(nodes_z)) )
      if data.saveMask:   mask.astype( '<f4' ).tofile(               data.DIR_out + "/%s-mask-%04ix%04ix%04i.raw"%( data.output_name, len(nodes_x), len(nodes_y), len(nodes_z)) )
    if data.saveVTK:
      headersEndPosition = WriteVTK_headers( data.DIR_out + "/%s.vtk"%( data.output_name ), kinematics[ :, 1:4 ], mask )
      if data.saveCC or data.saveDispl or data.saveRot: WriteVTK_data( data.DIR_out + "/%s.vtk"%( data.output_name ), '', [], data_type = 'POINT_DATA', nPoints = numpy.where(numpy.isfinite(mask))[0].shape[0] )
      if data.saveCC: WriteVTK_data( data.DIR_out + "/%s.vtk"%( data.output_name ), 'correlation_coefficient', cc_field, mask )
      if data.saveError:
        WriteVTK_headers( data.DIR_out + "/%s_errors.vtk"%( data.output_name ), kinematics[ :, 1:4 ] )
        WriteVTK_data( data.DIR_out + "/%s_errors.vtk"%( data.output_name ), 'error'                  , kinematics[ :, 11 ], [], 'POINT_DATA')

    if data.saveDispl:
      if data.saveTIFF:
        if not data.images_2D: imsave( data.DIR_out + "/%s-z-field-%04ix%04ix%04i.tif"%(  data.output_name, len(nodes_x), len(nodes_y), len(nodes_z)),     kinematics[ :, 4 ].reshape( ( len(nodes_z), len(nodes_y), len(nodes_x) ) ).astype( '<f4' ) )
        imsave( data.DIR_out + "/%s-y-field-%04ix%04ix%04i.tif"%(  data.output_name, len(nodes_x), len(nodes_y), len(nodes_z)),     kinematics[ :, 5 ].reshape( ( len(nodes_z), len(nodes_y), len(nodes_x) ) ).astype( '<f4' ) )
        imsave( data.DIR_out + "/%s-x-field-%04ix%04ix%04i.tif"%(  data.output_name, len(nodes_x), len(nodes_y), len(nodes_z)),     kinematics[ :, 6 ].reshape( ( len(nodes_z), len(nodes_y), len(nodes_x) ) ).astype( '<f4' ) )
      if data.saveRAW:
        if not data.images_2D: kinematics[ :, 4 ].astype( '<f4' ).tofile( data.DIR_out + "/%s-z-field-%04ix%04ix%04i.raw"%(  data.output_name, len(nodes_x), len(nodes_y), len(nodes_z)) )
        kinematics[ :, 5 ].astype( '<f4' ).tofile( data.DIR_out + "/%s-y-field-%04ix%04ix%04i.raw"%(  data.output_name, len(nodes_x), len(nodes_y), len(nodes_z)) )
        kinematics[ :, 6 ].astype( '<f4' ).tofile( data.DIR_out + "/%s-x-field-%04ix%04ix%04i.raw"%(  data.output_name, len(nodes_x), len(nodes_y), len(nodes_z)) )
      if data.saveVTK:
        WriteVTK_data( data.DIR_out + "/%s.vtk"%( data.output_name ), 'Displacements', kinematics[ :, 4:7 ], mask)

    if data.saveRot:
      if data.saveTIFF:
        if not data.images_2D: imsave( data.DIR_out + "/%s-z-rotvect-%04ix%04ix%04i.tif"%(  data.output_name, len(nodes_x), len(nodes_y), len(nodes_z)),     kinematics[ :, 7 ].reshape( ( len(nodes_z), len(nodes_y), len(nodes_x) ) ).astype( '<f4' ) )
        imsave( data.DIR_out + "/%s-y-rotvect-%04ix%04ix%04i.tif"%(  data.output_name, len(nodes_x), len(nodes_y), len(nodes_z)),     kinematics[ :, 8 ].reshape( ( len(nodes_z), len(nodes_y), len(nodes_x) ) ).astype( '<f4' ) )
        imsave( data.DIR_out + "/%s-x-rotvect-%04ix%04ix%04i.tif"%(  data.output_name, len(nodes_x), len(nodes_y), len(nodes_z)),     kinematics[ :, 9 ].reshape( ( len(nodes_z), len(nodes_y), len(nodes_x) ) ).astype( '<f4' ) )
      if data.saveRAW:
        if not data.images_2D: kinematics[ :, 7 ].astype( '<f4' ).tofile( data.DIR_out + "/%s-z-rotvect-%04ix%04ix%04i.raw"%(  data.output_name, len(nodes_x), len(nodes_y), len(nodes_z)) )
        kinematics[ :, 8 ].astype( '<f4' ).tofile( data.DIR_out + "/%s-y-rotvect-%04ix%04ix%04i.raw"%(  data.output_name, len(nodes_x), len(nodes_y), len(nodes_z)) )
        kinematics[ :, 9 ].astype( '<f4' ).tofile( data.DIR_out + "/%s-x-rotvect-%04ix%04ix%04i.raw"%(  data.output_name, len(nodes_x), len(nodes_y), len(nodes_z)) )
      if data.saveVTK:
        WriteVTK_data( data.DIR_out + "/%s.vtk"%( data.output_name ), 'Rotations', kinematics[ :, 7:10 ], mask)

    try:
      if data.calculate_strain:
        if    data.strain_mode == "smallStrains":
            [ strain, rot, connectivity, cellIndex ] = regular_strain_small_strain( kinematics[:,1:4], kinematics[:,4:7] )
          
            if data.saveVTK:
              connectivity = numpy.searchsorted(numpy.where(numpy.isfinite(mask))[0],connectivity)
              cellType = 12

        elif  data.strain_mode == "largeStrains":
            [ strain, rot, connectivity, cellIndex, volStrain ] = regular_strain_large_strain( kinematics[:,1:4], kinematics[:,4:7], data.saveVTK )
            
            if data.saveVTK:
              connectivity = numpy.searchsorted(numpy.where(numpy.isfinite(mask))[0],connectivity)
              cellType = 12

        elif  data.strain_mode == "largeStrainsCentred":
            neighbourhoodDistance = 1
            [ strain, rot, connectivity, volStrain ] = regular_strain_large_strain_centred( kinematics[:,1:4], kinematics[:,4:7], neighbourhoodDistance )
            if data.saveVTK:
              cellIndex = numpy.squeeze(connectivity).astype( 'i' )
              connectivity = numpy.searchsorted(numpy.where(numpy.isfinite(mask))[0],connectivity)
              cellType = 1

        elif  data.strain_mode == "tetrahedralStrains":
            [ strain, rot, connectivity, coordinates ] = tetrahedral_elements_strain( kinematics[:,1:4], kinematics[:,4:7], mask = mask )
            cellIndex = range(connectivity.shape[0])
            connectivity = numpy.searchsorted(numpy.where(numpy.isfinite(mask))[0],connectivity)
            cellType = 10   
            
            if data.saveTIFF or data.saveRAW:
              interpolate_strain = True


        strain = strain.astype( '<f4' )
        rot    = rot.astype(    '<f4' )
        strain_components = {}              
        strain_components_int = {}

        # 0S: 17-10-18 Catch 2D case
        if len(nodes_z)==1:
            twoD = True
        else:
            twoD = False

        ## Extract strain tensor components
        if len(strain.shape) == 5 :
            strain_components['zz'] = numpy.array( strain[ :, :, :, 0, 0 ] )
            strain_components['zz'] = numpy.array( strain[ :, :, :, 0, 0 ] )
            strain_components['zy'] = numpy.array( strain[ :, :, :, 0, 1 ] )
            strain_components['zx'] = numpy.array( strain[ :, :, :, 0, 2 ] )
            strain_components['yy'] = numpy.array( strain[ :, :, :, 1, 1 ] )
            strain_components['yx'] = numpy.array( strain[ :, :, :, 1, 2 ] )
            strain_components['xx'] = numpy.array( strain[ :, :, :, 2, 2 ] )
        elif len(strain.shape) == 3 :
            strain_components['zz'] = numpy.array( strain[ :, 0, 0 ] )
            strain_components['zy'] = numpy.array( strain[ :, 0, 1 ] )
            strain_components['zx'] = numpy.array( strain[ :, 0, 2 ] )
            strain_components['yy'] = numpy.array( strain[ :, 1, 1 ] )
            strain_components['yx'] = numpy.array( strain[ :, 1, 2 ] )
            strain_components['xx'] = numpy.array( strain[ :, 2, 2 ] )

        # Volumetric Strain is the trace only in the case of small strains...
        if data.strain_mode == "smallStrains":
            strain_components['volumetric']     = strain_components['zz'] + strain_components['yy'] + strain_components['xx']
        
        # "Real" volumetric strain from: https://en.wikipedia.org/wiki/Infinitesimal_strain_theory#Volumetric_strain taking a=1
        elif data.strain_mode == "largeStrains" or data.strain_mode == "largeStrainsCentred" or data.strain_mode == "tetrahedralStrains":
            # 0S: 17-10-18 volumetric strain in large strains is given from the determinant of the transformation gradient tensor F
            strain_components['volumetric']  =  volStrain
        
        # Steve's Maximum Shear Strain, see: Ando (2013) Phd, and Hall et al. 2009
        # 0S: 17-10-18
        #   see Wood: Soil Behaviour and Critical State Soil Mechanics (p. 21)
        #   this definition comes from work-conjugate pairs expressed in terms of the engineering strain γ (γ=0.5*ε)
        #   so the coefficient 3 becomes 12
        #   NOTE #1: this definition is only valid for small strains, for the moment we keep it for large strains too
        #   NOTE #2: in large strains: a decomposition of the stretch tensor U=Uiso*Udev should give us the deviatoric strain --> TODO soon.
        #   NOTE #3: you need to catch a 2D case, otherwise you're subtracting 'yy' and 'xx' from 'zz'(which is 0) and that gives you a huge difference
        if not twoD:
            strain_components['maximum_shear']  = ( 1/3.0 ) * numpy.sqrt( 2*( strain_components['xx']-strain_components['yy'] )**2  +  \
                                                                        2*( strain_components['xx']-strain_components['zz'] )**2  +  \
                                                                        2*( strain_components['yy']-strain_components['zz'] )**2  +  \
                                                                            #3*strain_components['yx']**2 + 3*strain_components['zx']**2 + 3*strain_components['zy']**2 )
                                                                            12*strain_components['yx']**2 + 12*strain_components['zx']**2 + 12*strain_components['zy']**2 )
        else:
            #OS: 17-10-18 no idea for the coefficients in 2D, sorry
            strain_components['maximum_shear']  = ( 1/3.0 ) * numpy.sqrt( 2*(strain_components['xx']-strain_components['yy'] )**2  +  \
                                                                            #3*strain_components['yx']**2 + 3*strain_components['zx']**2 + 3*strain_components['zy']**2 )
                                                                            12*strain_components['yx']**2 )

        ############################################
        # 0S: 17-10-18:
        # tests for:
        #   1: isotropic compression and
        #   2: simple shear
        # passed for 3D and 2D.
        ############################################

        if data.saveVTK:
          WriteVTK_maesh( data.DIR_out + "/%s.vtk"%( data.output_name ), connectivity, headersEndPosition, cellType )
          WriteVTK_data( data.DIR_out + "/%s.vtk"%( data.output_name ), '', [], data_type = 'CELL_DATA', nPoints = len( connectivity ) )
          
        for component in enumerate([ 'zz', 'zy', 'zx', 'yy', 'yx', 'xx', 'volumetric', 'maximum_shear' ]):
            
            if data.saveStrain[ component[0] ]:
              
              if data.saveVTK: WriteVTK_data( data.DIR_out + "/%s.vtk"%( data.output_name ), '%s_strain'%( component[1]), strain_components[ component[1] ].flat[cellIndex] )
              
              try:
                if interpolate_strain:
                    try: logging.log.info("Interpolation of %s into a regular grid to save TIF/RAW. This can take some time..."%(component[1]))
                    except: print "Interpolation of %s into a regular grid to save TIF/RAW. This can take some time..."%(component[1])
                    strain_components_int[ component[1] ] = numpy.ones_like( mask )*numpy.nan  
                    strain_components_int[ component[1] ][ numpy.where( ~numpy.isnan(mask) ) ] = griddata( coordinates, strain_components[ component[1] ], kinematics[ numpy.where( ~numpy.isnan( mask ) ), 1:4 ] )
                    strain_components[     component[1] ] = strain_components_int[ component[1] ].reshape( ( len( nodes_z ), len( nodes_y ), len( nodes_x ) ) )
                    try: logging.log.info("Interpolation done!")
                    except: print "Interpolation done!"
                  
                if data.saveTIFF or data.saveRAW:
                  dimZ = strain_components[ component[1] ].shape[0]
                  dimY = strain_components[ component[1] ].shape[1]
                  dimX = strain_components[ component[1] ].shape[2]
                  
                if data.saveTIFF: imsave( data.DIR_out + "/%s-%s_strain-field-%04ix%04ix%04i.tif"%( data.output_name, component[1], dimX, dimY, dimZ), strain_components[ component[1] ].astype( '<f4' ) )
                if data.saveRAW:  strain_components[ component[1] ].astype( '<f4' ).tofile( data.DIR_out + "/%s-%s_strain-field-%04ix%04ix%04i.raw"%( data.output_name, component[1], dimX, dimY, dimZ) )
              
              except:
                try: logging.log.warn("Warning: it was not possible to interpolate %s strain"%(component[1]))
                except: print "Warning: it was not possible to interpolate %s strain"%(component[1])
                      
        if data.saveRotFromStrain:
          # 2014-10-13 EA: calculation of rotation
          if len(strain.shape) == 5 :
              R33 = numpy.array( rot[ :, :, :, 0, 0 ] )
              R32 = numpy.array( rot[ :, :, :, 0, 1 ] )
              R31 = numpy.array( rot[ :, :, :, 0, 2 ] )
              R22 = numpy.array( rot[ :, :, :, 1, 1 ] )
              R21 = numpy.array( rot[ :, :, :, 1, 2 ] )
              R11 = numpy.array( rot[ :, :, :, 2, 2 ] )
          elif len(strain.shape) == 3 :
              R33 = numpy.array( rot[ :, 0, 0 ] )
              R32 = numpy.array( rot[ :, 0, 1 ] )
              R31 = numpy.array( rot[ :, 0, 2 ] )
              R22 = numpy.array( rot[ :, 1, 1 ] )
              R21 = numpy.array( rot[ :, 1, 2 ] )
              R11 = numpy.array( rot[ :, 2, 2 ] )

          RotAngle = numpy.sqrt( R32**2 + R31**2 + R21**2 )

          if data.saveTIFF:
              if len(strain.shape) == 5 :
                  imsave( data.DIR_out + "/%s-rot_angle-%04ix%04ix%04i.tif"%( data.output_name, dimX, dimY, dimZ), RotAngle.astype( '<f4' ) )
              else:
                  try: logging.log.warn("Warning: Strain not in a regular grid. Can not write TIFF")
                  except: print "Warning: Strain not in a regular grid. Can not write TIFF"
          if data.saveRAW:
              if len(strain.shape) == 5 :
                  RotAngle.astype( '<f4' ).tofile( data.DIR_out + "/%s-rot_angle-%04ix%04ix%04i.raw"%( data.output_name, dimX, dimY, dimZ) )
              else:
                  try: logging.log.warn("Warning: Strain not in a regular grid. Can not write RAW")
                  except: print "Warning: Strain not in a regular grid. Can not write RAW"
          if data.saveVTK:
              #WriteVTK_data( data.DIR_out + "/%s.vtk"%( data.output_name ), 'rot_angle', RotAngle )
              pass

    except Exception as exc:
      raise Exception(exc)          
Beispiel #7
0
def process_results(kinematics, data):

    interpolate_strain = False

    # 2015-04-14 EA: Adding default option to save output files as tiff, which requires tifffile.py
    if data.saveTIFF:
        # tools already added to path
        from tools.tifffile import imsave

    # Generate a mask for the output of the files.
    #   1. All nodes which have reported an error need to be masked.
    #   2. All nodes which have low CC can also be optionally masked.

    # Generate all fields replacing error Nodes with NaNs -- to read from kinematics array...
    # 2013-08-22 - Calculation of node spacing moved to ./tools/calculate_node_spacing.py
    nodes_z, nodes_y, nodes_x = calculate_node_spacing(kinematics[:, 1:4])

    cc_field = numpy.array(kinematics[:, 10]).astype('<f4')

    #-----------------------------------------------------------------------
    #-  Generate a NaN mask to add to other fields                        --
    #-----------------------------------------------------------------------
    mask = numpy.zeros(cc_field.shape, dtype='<f4')

    # add the nodes which are error nodes to the mask
    mask[numpy.where(kinematics[:, 11] != 0)] = numpy.nan

    if data.cc_threshold == "auto":
        # if we have a data.cc_threshold set, add this to the mask
        data.cc_threshold = cc_autothreshold(cc_field)

    if data.cc_threshold == None:
        data.cc_threshold = -1.0  #why do we need this?

    else:
        # if data.cc_threshold != None, calculate and apply mask
        data.cc_threshold = float(data.cc_threshold)
        # ...and mask with data.cc_threshold
        mask[numpy.where(cc_field < data.cc_threshold)] = numpy.nan

    #-----------------------------------------------------------------------
    #-  Done generating the mask...                                       --
    #-----------------------------------------------------------------------
    # Clean up the kinematics with the mask
    for i in [4, 5, 6, 7, 8, 9]:
        kinematics[:, i] += mask

    # Remove outliers
    if data.remove_outliers_filter_size != None:
        if data.remove_outliers_filter_size > 0:
            print "\tprocess_results: Removing outliers"  #%0.1f (3 means ±1)"%( data.kinematics_median_filter )
            try:
                #kinematics[ :, 4:10 ] = data.kinematics_median_filter_fnc( kinematics[ :, 1:4 ], kinematics[ :, 4:10 ], data.kinematics_median_filter )
                [ kinematics[ :, 4:10 ], mask_outliers ] = kinematics_remove_outliers( kinematics[ :, 1:4 ], kinematics[ :, 4:10 ], \
                    data.remove_outliers_filter_size, data.remove_outliers_threshold, data.remove_outliers_absolut_threshold, data.remove_outliers_filter_high, data.filter_base_field )
                #mask[ numpy.where(mask_outliers==1) ] = 0
            except Exception as exc:
                print exc.message
                pass

    # filter kinematics...
    if data.kinematics_median_filter != None:
        if data.kinematics_median_filter > 0:
            print "\tprocess_results: Applying a Kinematics Median filter of %0.1f (3 means ±1)" % (
                data.kinematics_median_filter)
            try:
                kinematics[:, 4:10] = kinematics_median_filter_fnc(
                    kinematics[:, 1:4], kinematics[:, 4:10],
                    data.kinematics_median_filter)
            except Exception as exc:
                print exc.message
                pass

    if data.pixel_size_ratio != 1:
        if data.image_centre is not None:
            kinematics = correct_pixel_size_changing(kinematics,
                                                     data.pixel_size_ratio,
                                                     data.image_centre)
        else:
            raise Exception('Image centre needed to correct pixel size ratio')

    print "  -> Writing output files to %s/%s..." % (data.DIR_out,
                                                     data.output_name)

    # 2015-01-27 EA and ET: TODO: These could be optional one day...
    if data.saveTIFF:
        if data.saveError:
            imsave(
                data.DIR_out + "/%s-error-field-%04ix%04ix%04i.tif" %
                (data.output_name, len(nodes_x), len(nodes_y), len(nodes_z)),
                kinematics[:, 11].reshape(
                    (len(nodes_z), len(nodes_y), len(nodes_x))).astype('<f4'))
        if data.saveCC:
            imsave(
                data.DIR_out + "/%s-cc-field-%04ix%04ix%04i.tif" %
                (data.output_name, len(nodes_x), len(nodes_y), len(nodes_z)),
                cc_field.reshape(
                    (len(nodes_z), len(nodes_y), len(nodes_x))).astype('<f4'))
        if data.saveMask:
            imsave(
                data.DIR_out + "/%s-mask-%04ix%04ix%04i.tif" %
                (data.output_name, len(nodes_x), len(nodes_y), len(nodes_z)),
                mask.reshape(
                    (len(nodes_z), len(nodes_y), len(nodes_x))).astype('<f4'))
    if data.saveRAW:
        # Save RAW Files
        if data.saveError:
            kinematics[:, 11].astype('<f4').tofile(
                data.DIR_out + "/%s-error-field-%04ix%04ix%04i.raw" %
                (data.output_name, len(nodes_x), len(nodes_y), len(nodes_z)))
        if data.saveCC:
            cc_field.astype('<f4').tofile(
                data.DIR_out + "/%s-cc-field-%04ix%04ix%04i.raw" %
                (data.output_name, len(nodes_x), len(nodes_y), len(nodes_z)))
        if data.saveMask:
            mask.astype('<f4').tofile(
                data.DIR_out + "/%s-mask-%04ix%04ix%04i.raw" %
                (data.output_name, len(nodes_x), len(nodes_y), len(nodes_z)))
    if data.saveVTK:
        #print "\tprocess_results:VTK output not implemented yet"
        headersEndPosition = WriteVTK_headers(
            data.DIR_out + "/%s.vtk" % (data.output_name), kinematics[:, 1:4],
            mask)
        if data.saveCC:
            WriteVTK_data(data.DIR_out + "/%s.vtk" % (data.output_name),
                          'correlation_coefficient', cc_field, mask,
                          'POINT_DATA')
        if data.saveError:
            WriteVTK_headers(
                data.DIR_out + "/%s_errors.vtk" % (data.output_name),
                kinematics[:, 1:4])
            WriteVTK_data(data.DIR_out + "/%s_errors.vtk" % (data.output_name),
                          'error', kinematics[:, 11], [], 'POINT_DATA')

    if data.saveDispl:
        if data.saveTIFF:
            if not data.images_2D:
                imsave(
                    data.DIR_out + "/%s-z-field-%04ix%04ix%04i.tif" %
                    (data.output_name, len(nodes_x), len(nodes_y),
                     len(nodes_z)),
                    kinematics[:, 4].reshape((len(nodes_z), len(nodes_y),
                                              len(nodes_x))).astype('<f4'))
            imsave(
                data.DIR_out + "/%s-y-field-%04ix%04ix%04i.tif" %
                (data.output_name, len(nodes_x), len(nodes_y), len(nodes_z)),
                kinematics[:, 5].reshape(
                    (len(nodes_z), len(nodes_y), len(nodes_x))).astype('<f4'))
            imsave(
                data.DIR_out + "/%s-x-field-%04ix%04ix%04i.tif" %
                (data.output_name, len(nodes_x), len(nodes_y), len(nodes_z)),
                kinematics[:, 6].reshape(
                    (len(nodes_z), len(nodes_y), len(nodes_x))).astype('<f4'))
        if data.saveRAW:
            # Save RAW Files
            if not data.images_2D:
                kinematics[:, 4].astype('<f4').tofile(
                    data.DIR_out + "/%s-z-field-%04ix%04ix%04i.raw" %
                    (data.output_name, len(nodes_x), len(nodes_y),
                     len(nodes_z)))
            kinematics[:, 5].astype('<f4').tofile(
                data.DIR_out + "/%s-y-field-%04ix%04ix%04i.raw" %
                (data.output_name, len(nodes_x), len(nodes_y), len(nodes_z)))
            kinematics[:, 6].astype('<f4').tofile(
                data.DIR_out + "/%s-x-field-%04ix%04ix%04i.raw" %
                (data.output_name, len(nodes_x), len(nodes_y), len(nodes_z)))
        if data.saveVTK:
            #print "\tprocess_results:VTK output not implemented yet"
            WriteVTK_data(data.DIR_out + "/%s.vtk" % (data.output_name),
                          'Displacements', kinematics[:, 4:7], mask)

    if data.saveRot:
        if data.saveTIFF:
            if not data.images_2D:
                imsave(
                    data.DIR_out + "/%s-z-rotvect-%04ix%04ix%04i.tif" %
                    (data.output_name, len(nodes_x), len(nodes_y),
                     len(nodes_z)),
                    kinematics[:, 7].reshape((len(nodes_z), len(nodes_y),
                                              len(nodes_x))).astype('<f4'))
            imsave(
                data.DIR_out + "/%s-y-rotvect-%04ix%04ix%04i.tif" %
                (data.output_name, len(nodes_x), len(nodes_y), len(nodes_z)),
                kinematics[:, 8].reshape(
                    (len(nodes_z), len(nodes_y), len(nodes_x))).astype('<f4'))
            imsave(
                data.DIR_out + "/%s-x-rotvect-%04ix%04ix%04i.tif" %
                (data.output_name, len(nodes_x), len(nodes_y), len(nodes_z)),
                kinematics[:, 9].reshape(
                    (len(nodes_z), len(nodes_y), len(nodes_x))).astype('<f4'))
        if data.saveRAW:
            if not data.images_2D:
                kinematics[:, 7].astype('<f4').tofile(
                    data.DIR_out + "/%s-z-rotvect-%04ix%04ix%04i.raw" %
                    (data.output_name, len(nodes_x), len(nodes_y),
                     len(nodes_z)))
            kinematics[:, 8].astype('<f4').tofile(
                data.DIR_out + "/%s-y-rotvect-%04ix%04ix%04i.raw" %
                (data.output_name, len(nodes_x), len(nodes_y), len(nodes_z)))
            kinematics[:, 9].astype('<f4').tofile(
                data.DIR_out + "/%s-x-rotvect-%04ix%04ix%04i.raw" %
                (data.output_name, len(nodes_x), len(nodes_y), len(nodes_z)))
        if data.saveVTK:
            WriteVTK_data(data.DIR_out + "/%s.vtk" % (data.output_name),
                          'Rotations', kinematics[:, 7:10], mask)

    if data.calculate_strain:
        #try:
        if data.strain_mode == "smallStrains":
            [strain,
             rot] = regular_strain_small_strain(kinematics[:, 1:4],
                                                kinematics[:, 4:7])
            if data.saveVTK:
                # resample strain in a regular grid - not implemented yet
                print "WARNING: saving VTK with mode smallStrains is not implemented yet"
                data.saveVTK = False

        elif data.strain_mode == "largeStrains":
            [strain,
             rot] = regular_strain_large_strain(kinematics[:, 1:4],
                                                kinematics[:, 4:7])
            if data.saveVTK:
                # resample strain in a regular grid - not implemented yet
                print "WARNING: saving VTK with mode largeStrains is not implemented yet"
                data.saveVTK = False
        elif data.strain_mode == "largeStrainsCentred":
            [strain, rot
             ] = regular_strain_large_strain_centred(kinematics[:, 1:4],
                                                     kinematics[:, 4:7], 1)
            if data.saveVTK:
                # resample strain in a regular grid - not implemented yet
                print "WARNING: saving VTK with mode largeStrains is not implemented yet"
                data.saveVTK = False

        elif data.strain_mode == "tetrahedralStrains":
            [strain, rot, connectivity,
             coordinates] = tetrahedral_elements_strain(kinematics[:, 1:4],
                                                        kinematics[:, 4:7],
                                                        mask=mask)

            print "max strain = ", strain.max()
            print "coordinates.shape = ", coordinates.shape
            if data.saveTIFF or data.saveRAW:
                ## resample strain in a regular grid - not implemented yet
                #print "WARNING: saving TIFF or RAW with mode tetrahedralStrains is not implemented yet"
                #data.saveTIFF = False
                #data.saveRAW = False

                interpolate_strain = True

        strain = strain.astype('<f4')
        rot = rot.astype('<f4')

        ## Extract strain tensor components
        if len(strain.shape) == 5:
            zz = numpy.array(strain[:, :, :, 0, 0])
            zy = numpy.array(strain[:, :, :, 0, 1])
            zx = numpy.array(strain[:, :, :, 0, 2])
            yy = numpy.array(strain[:, :, :, 1, 1])
            yx = numpy.array(strain[:, :, :, 1, 2])
            xx = numpy.array(strain[:, :, :, 2, 2])
            dimZ = strain.shape[0]
            dimY = strain.shape[1]
            dimX = strain.shape[2]
        elif len(strain.shape) == 3:
            zz = numpy.array(strain[:, 0, 0])
            zy = numpy.array(strain[:, 0, 1])
            zx = numpy.array(strain[:, 0, 2])
            yy = numpy.array(strain[:, 1, 1])
            yx = numpy.array(strain[:, 1, 2])
            xx = numpy.array(strain[:, 2, 2])

        if data.saveVTK:
            #print "\tprocess_results:VTK output not implemented yet"
            WriteVTK_maesh(data.DIR_out + "/%s.vtk" % (data.output_name),
                           connectivity, headersEndPosition)
            WriteVTK_data(data.DIR_out + "/%s.vtk" % (data.output_name),
                          '', [],
                          data_type='CELL_DATA',
                          nPoints=len(connectivity))
            if data.saveStrain[0]:
                WriteVTK_data(data.DIR_out + "/%s.vtk" % (data.output_name),
                              'strain_zz', zz)
            if data.saveStrain[1]:
                WriteVTK_data(data.DIR_out + "/%s.vtk" % (data.output_name),
                              'strain_zy', zy)
            if data.saveStrain[2]:
                WriteVTK_data(data.DIR_out + "/%s.vtk" % (data.output_name),
                              'strain_zx', zx)
            if data.saveStrain[3]:
                WriteVTK_data(data.DIR_out + "/%s.vtk" % (data.output_name),
                              'strain_yy', yy)
            if data.saveStrain[4]:
                WriteVTK_data(data.DIR_out + "/%s.vtk" % (data.output_name),
                              'strain_yx', yx)
            if data.saveStrain[5]:
                WriteVTK_data(data.DIR_out + "/%s.vtk" % (data.output_name),
                              'strain_xx', xx)
            if data.saveStrain[6]:
                # Volumetric Strain is the trace
                volumetric_strain = zz + yy + xx
                WriteVTK_data(data.DIR_out + "/%s.vtk" % (data.output_name),
                              'vol_strain', volumetric_strain)
            if data.saveStrain[7]:
                # Steve's Maximum Shear Strain, see: Ando (2013) Phd, and Hall et al. 2009
                maximum_shear_strain  = ( 1/3.0 ) * numpy.sqrt( 2*( xx-yy )**2  +  2*(xx-zz)**2  +  2*(yy-zz)**2 + \
                                                                3*yx**2         +  3*zx**2       +  3*zy**2 )
                WriteVTK_data(data.DIR_out + "/%s.vtk" % (data.output_name),
                              'max_shear', maximum_shear_strain)

        if interpolate_strain:
            print "Interpolation strain data into a regular grid to save TIF/RAW (This can take some time...)",
            zz_int = numpy.ones_like(mask) * numpy.nan
            zy_int = numpy.ones_like(mask) * numpy.nan
            zx_int = numpy.ones_like(mask) * numpy.nan
            yy_int = numpy.ones_like(mask) * numpy.nan
            yx_int = numpy.ones_like(mask) * numpy.nan
            xx_int = numpy.ones_like(mask) * numpy.nan
            zz_int[numpy.where(~numpy.isnan(mask))] = griddata(
                coordinates, zz, kinematics[numpy.where(~numpy.isnan(mask)),
                                            1:4])
            zy_int[numpy.where(~numpy.isnan(mask))] = griddata(
                coordinates, zy, kinematics[numpy.where(~numpy.isnan(mask)),
                                            1:4])
            zx_int[numpy.where(~numpy.isnan(mask))] = griddata(
                coordinates, zx, kinematics[numpy.where(~numpy.isnan(mask)),
                                            1:4])
            yy_int[numpy.where(~numpy.isnan(mask))] = griddata(
                coordinates, yy, kinematics[numpy.where(~numpy.isnan(mask)),
                                            1:4])
            yx_int[numpy.where(~numpy.isnan(mask))] = griddata(
                coordinates, yx, kinematics[numpy.where(~numpy.isnan(mask)),
                                            1:4])
            xx_int[numpy.where(~numpy.isnan(mask))] = griddata(
                coordinates, xx, kinematics[numpy.where(~numpy.isnan(mask)),
                                            1:4])
            zz = zz_int.reshape((len(nodes_z), len(nodes_y), len(nodes_x)))
            zy = zy_int.reshape((len(nodes_z), len(nodes_y), len(nodes_x)))
            zx = zx_int.reshape((len(nodes_z), len(nodes_y), len(nodes_x)))
            yy = yy_int.reshape((len(nodes_z), len(nodes_y), len(nodes_x)))
            yx = yx_int.reshape((len(nodes_z), len(nodes_y), len(nodes_x)))
            xx = xx_int.reshape((len(nodes_z), len(nodes_y), len(nodes_x)))
            #zz = re_intsampling_irregular_grid( zz, coordinates )
            #zy = resampling_irregular_grid( zy, coordinates )
            #zx = resampling_irregular_grid( zx, coordinates )
            #yy = resampling_irregular_grid( yy, coordinates )
            #yx = resampling_irregular_grid( yx, coordinates )
            #xx = resampling_irregular_grid( xx, coordinates )
            dimZ = zz.shape[0]
            dimY = zz.shape[1]
            dimX = zz.shape[2]
            #print "Warning: Strain not in a regular grid. Can not write TIFF"

        if data.saveTIFF:
            if data.saveStrain[0]:
                imsave(
                    data.DIR_out + "/%s-strain_zz-field-%04ix%04ix%04i.tif" %
                    (data.output_name, dimX, dimY, dimZ), zz.astype('<f4'))
            if data.saveStrain[1]:
                imsave(
                    data.DIR_out + "/%s-strain_zy-field-%04ix%04ix%04i.tif" %
                    (data.output_name, dimX, dimY, dimZ), zy.astype('<f4'))
            if data.saveStrain[2]:
                imsave(
                    data.DIR_out + "/%s-strain_zx-field-%04ix%04ix%04i.tif" %
                    (data.output_name, dimX, dimY, dimZ), zx.astype('<f4'))
            if data.saveStrain[3]:
                imsave(
                    data.DIR_out + "/%s-strain_yy-field-%04ix%04ix%04i.tif" %
                    (data.output_name, dimX, dimY, dimZ), yy.astype('<f4'))
            if data.saveStrain[4]:
                imsave(
                    data.DIR_out + "/%s-strain_yx-field-%04ix%04ix%04i.tif" %
                    (data.output_name, dimX, dimY, dimZ), yx.astype('<f4'))
            if data.saveStrain[5]:
                imsave(
                    data.DIR_out + "/%s-strain_xx-field-%04ix%04ix%04i.tif" %
                    (data.output_name, dimX, dimY, dimZ), xx.astype('<f4'))
            if data.saveStrain[6]:
                volumetric_strain = zz + yy + xx
                imsave(
                    data.DIR_out + "/%s-vol_strain-field-%04ix%04ix%04i.tif" %
                    (data.output_name, dimX, dimY, dimZ),
                    volumetric_strain.astype('<f4'))
            if data.saveStrain[7]:
                # Steve's Maximum Shear Strain, see: Ando (2013) Phd, and Hall et al. 2009
                maximum_shear_strain  = ( 1/3.0 ) * numpy.sqrt( 2*( xx-yy )**2  +  2*(xx-zz)**2  +  2*(yy-zz)**2 + \
                                                                3*yx**2         +  3*zx**2       +  3*zy**2 )
                imsave(
                    data.DIR_out +
                    "/%s-maximum_shear_strain-field-%04ix%04ix%04i.tif" %
                    (data.output_name, dimX, dimY, dimZ),
                    maximum_shear_strain.astype('<f4'))

        if data.saveRAW:
            # Save RAW Files
            if data.saveStrain[0]:
                zz.astype('<f4').tofile(
                    data.DIR_out + "/%s-strain_zz-field-%04ix%04ix%04i.raw" %
                    (data.output_name, dimX, dimY, dimZ))
            if data.saveStrain[1]:
                zy.astype('<f4').tofile(
                    data.DIR_out + "/%s-strain_zy-field-%04ix%04ix%04i.raw" %
                    (data.output_name, dimX, dimY, dimZ))
            if data.saveStrain[2]:
                zx.astype('<f4').tofile(
                    data.DIR_out + "/%s-strain_zx-field-%04ix%04ix%04i.raw" %
                    (data.output_name, dimX, dimY, dimZ))
            if data.saveStrain[3]:
                yy.astype('<f4').tofile(
                    data.DIR_out + "/%s-strain_yy-field-%04ix%04ix%04i.raw" %
                    (data.output_name, dimX, dimY, dimZ))
            if data.saveStrain[4]:
                yx.astype('<f4').tofile(
                    data.DIR_out + "/%s-strain_yx-field-%04ix%04ix%04i.raw" %
                    (data.output_name, dimX, dimY, dimZ))
            if data.saveStrain[5]:
                xx.astype('<f4').tofile(
                    data.DIR_out + "/%s-strain_xx-field-%04ix%04ix%04i.raw" %
                    (data.output_name, dimX, dimY, dimZ))
            if data.saveStrain[6]:
                volumetric_strain = zz + yy + xx
                volumetric_strain.astype('<f4').tofile(
                    data.DIR_out + "/%s-vol_strain-field-%04ix%04ix%04i.raw" %
                    (data.output_name, dimX, dimY, dimZ))
            if data.saveStrain[7]:
                # Steve's Maximum Shear Strain, see: Ando (2013) Phd, and Hall et al. 2009
                maximum_shear_strain  = ( 1/3.0 ) * numpy.sqrt( 2*( xx-yy )**2  +  2*(xx-zz)**2  +  2*(yy-zz)**2 + \
                                                                3*yx**2         +  3*zx**2       +  3*zy**2 )
                maximum_shear_strain.astype('<f4').tofile(
                    data.DIR_out + "/%s-max_shear-field-%04ix%04ix%04i.raw" %
                    (data.output_name, dimX, dimY, dimZ))

        if data.saveRotFromStrain:
            # 2014-10-13 EA: calc     ulation of rotation
            if len(strain.shape) == 5:
                R33 = numpy.array(rot[:, :, :, 0, 0])
                R32 = numpy.array(rot[:, :, :, 0, 1])
                R31 = numpy.array(rot[:, :, :, 0, 2])
                R22 = numpy.array(rot[:, :, :, 1, 1])
                R21 = numpy.array(rot[:, :, :, 1, 2])
                R11 = numpy.array(rot[:, :, :, 2, 2])
            elif len(strain.shape) == 3:
                R33 = numpy.array(rot[:, 0, 0])
                R32 = numpy.array(rot[:, 0, 1])
                R31 = numpy.array(rot[:, 0, 2])
                R22 = numpy.array(rot[:, 1, 1])
                R21 = numpy.array(rot[:, 1, 2])
                R11 = numpy.array(rot[:, 2, 2])

            RotAngle = numpy.sqrt(R32**2 + R31**2 + R21**2)

            if data.saveTIFF:
                if len(strain.shape) == 5:
                    imsave(
                        data.DIR_out + "/%s-rot_angle-%04ix%04ix%04i.tif" %
                        (data.output_name, dimX, dimY, dimZ),
                        RotAngle.astype('<f4'))
                else:
                    print "Warning: Strain not in a regular grid. Can not write TIFF"
            if data.saveRAW:
                # Save RAW Files
                if len(strain.shape) == 5:
                    RotAngle.astype('<f4').tofile(
                        data.DIR_out + "/%s-rot_angle-%04ix%04ix%04i.raw" %
                        (data.output_name, dimX, dimY, dimZ))
                else:
                    print "Warning: Strain not in a regular grid. Can not write RAW"
            if data.saveVTK:
                #print "\tprocess_results:VTK output not implemented yet"
                #WriteVTK_data( data.DIR_out + "/%s.vtk"%( data.output_name ), 'rot_angle', RotAngle )
                pass
Beispiel #8
0
def regular_strain_large_strain( positions, displacements, calculateConnectivity=False ):

  try: logging.log.info("regular_strain_large_strain: Calculating strains in Large Deformations framework...")
  except: print "regular_strain_large_strain: Calculating strains in Large Deformations framework..."

  SFderivative        = numpy.zeros( ( 3, 8 ) ) # Derivative of shape functions from F.E.
  relNodePos          = numpy.zeros( ( 8, 3 ) ) # RELATIVE Node positions
  nodalDisplacements  = numpy.zeros( ( 8, 3 ) ) # Nodal displacements
  dsdx                = numpy.zeros( ( 3, 3 ) ) #
  dxds                = numpy.zeros( ( 3, 3 ) )
  Bn                  = numpy.zeros( ( 3, 8 ) ) # D/dx with shape function
  I                   = numpy.eye( 3 ) # identity matrix

  # N.B. x is in the real coordiantes of the image
  #      s is in the Shape Function coordinates.


  ########################################################################
  ##   Derivative of shape function nodal weights from F.E.             ##
  ########################################################################
  # Derivatives of the 8-node shape function wrt X
  SFderivative[0,0]=-0.125; SFderivative[0,1]=0.125; SFderivative[0,2]=0.125; SFderivative[0,3]=-0.125; SFderivative[0,4]=-0.125; SFderivative[0,5]=0.125; SFderivative[0,6]=0.125; SFderivative[0,7]=-0.125;

  # Derivatives of the 8-node shape function wrt Y
  SFderivative[1,0]=-0.125; SFderivative[1,1]=-0.125; SFderivative[1,2]=0.125; SFderivative[1,3]=0.125; SFderivative[1,4]=-0.125; SFderivative[1,5]=-0.125; SFderivative[1,6]=0.125; SFderivative[1,7]=0.125;

  # Derivatives of the 8-node shape function wrt Z
  SFderivative[2,0]=-0.125; SFderivative[2,1]=-0.125; SFderivative[2,2]=-0.125; SFderivative[2,3]=-0.125; SFderivative[2,4]=0.125;  SFderivative[2,5]=0.125;  SFderivative[2,6]=0.125;  SFderivative[2,7]=0.125;


  ########################################################################
  ##  Relative nodal positions                                          ##
  ########################################################################
  #-----------------------------------------------------------------------
  #-  Calculate nodal spacing                                           --
  #-      (this comes from regular_prior_interpolator.py)               --
  #-----------------------------------------------------------------------

  number_of_nodes = positions.shape[0]
  connectivity = numpy.zeros((0,8))
  cellIndex = numpy.zeros((0,)).astype( 'i' )

  nodes_z, nodes_y, nodes_x = calculate_node_spacing( positions )
  
  if len(nodes_z)==1:
    
    # To make the strain calculation work in 2D a fictitious second layer of equal displacements is added 
    #   so that the strain in z is null
    positions_fictitious = numpy.copy( positions )
    positions_fictitious[:,0]+=1
    
    positions      = numpy.concatenate( ( positions, positions_fictitious ) )
    displacements  = numpy.concatenate( ( displacements, displacements ) )
    nodes_z = nodes_z + [1]

    nodes_z, nodes_y, nodes_x = calculate_node_spacing( positions )
  
  try:
      # Figure out spacing from first two nodes positions
      z_spacing = nodes_z[1] - nodes_z[0]
      y_spacing = nodes_y[1] - nodes_y[0]
      x_spacing = nodes_x[1] - nodes_x[0]
  except IndexError:
      raise Exception('Warning: Not enough nodes to calculate strain')

  # Define strain matrix
  #  2014-11-12 PB and EA: changing strain 6-component vector to a full 3x3 strain tensor
  #  2016-04-28 ET: strain tensor is filled up to len( nodes_# )-1, changing the declaration to fit this size 
  strain = numpy.zeros( ( len( nodes_z ) - 1, len( nodes_y ) - 1, len( nodes_x ) - 1, 3, 3 ) )
  rot    = numpy.zeros( ( len( nodes_z ) - 1, len( nodes_y ) - 1, len( nodes_x ) - 1, 3, 3 ) )


  #-----------------------------------------------------------------------
  #-  Definition of elements                                            --
  #-----------------------------------------------------------------------
  # 2014-11-12 PB and EA: This is the RELATIVE position of the nodes WRT node 1, which is at 0,0,0
  # 2014-11-12 PB and EA: We're going to read in the displacements z-first so we'll put z-spacing first here.
  relNodePos[0,0]=0.0; relNodePos[1,0]=z_spacing; relNodePos[2,0]=z_spacing; relNodePos[3,0]=0.0;       relNodePos[4,0]=0.0;        relNodePos[5,0]=z_spacing;  relNodePos[6,0]=z_spacing; relNodePos[7,0]=0.0;
  relNodePos[0,1]=0.0; relNodePos[1,1]=0.0;       relNodePos[2,1]=y_spacing; relNodePos[3,1]=y_spacing; relNodePos[4,1]=0.0;        relNodePos[5,1]=0.0;        relNodePos[6,1]=y_spacing; relNodePos[7,1]=y_spacing;
  relNodePos[0,2]=0.0; relNodePos[1,2]=0.0;       relNodePos[2,2]=0.0;       relNodePos[3,2]=0.0;       relNodePos[4,2]=x_spacing;  relNodePos[5,2]=x_spacing;  relNodePos[6,2]=x_spacing; relNodePos[7,2]=x_spacing;

  # Original Comment: /* Calculate dxds = SFderivative*relNodePos and so dsdx=inv(dxds) */
  for i in range(3):
    for j in range(3):
      for nodeNumber in range(8):
        # 2014-11-12 PB and EA: loop over each of the 8 nodes, summing the 8 derivatives
        dxds[ i, j ] = dxds[ i, j ] +      SFderivative[ i, nodeNumber ] * relNodePos[ nodeNumber, j ]

  # 2014-11-12 PB and EA: Replaing above commented calculations with a numpy inverse
  dsdx =  numpy.linalg.inv( dxds )

  #-----------------------------------------------------------------------
  #-  Operator which describes weighting of nodal coordinates by shape  --
  #-    function (see Hall et al. 2006)                                 --
  #-----------------------------------------------------------------------
  for ii in range(3):
    for nodeNumber in range(8):
      for kk in range(3):
        Bn[ ii, nodeNumber ] = Bn[ ii, nodeNumber ] + dsdx[ ii, kk ] * SFderivative[ kk, nodeNumber ]


  ########################################################################
  ##  Getting the displacements around each node                        ##
  ########################################################################
  #-----------------------------------------------------------------------
  #-  Reshape the displacements so that we easily have the neighbours   --
  #-----------------------------------------------------------------------
  #displacements_x = displacements[ :, 2 ].reshape( ( len( nodes_z ), len( nodes_y ), len( nodes_x ) ) )
  #displacements_y = displacements[ :, 1 ].reshape( ( len( nodes_z ), len( nodes_y ), len( nodes_x ) ) )
  #displacements_z = displacements[ :, 0 ].reshape( ( len( nodes_z ), len( nodes_y ), len( nodes_x ) ) )

  # This is a 4D array of x, y, z positions + component...
  displacements = displacements.reshape( ( len( nodes_z ), len( nodes_y ), len( nodes_x ), 3 ) )

  #-----------------------------------------------------------------------
  #-  Fetch neighbourhood displacements from x y z displacements        --
  #-    i.e., fill in the nodalDisplacements matrix  numpy.zeros( ( 8, 3 ) )            --
  #-----------------------------------------------------------------------
  for z in range( len(nodes_z) - 1 ):
    print "\tregular_strain_large_strain: Working on z=%04i/%04i\r"%( z, len(nodes_z)-1 ),

    for y in range( len(nodes_y) - 1 ):
      for x in range( len(nodes_x) - 1 ):

        # All the displacements (x,y,z) for the node
        # 2014-11-12 PB and EA: Going to read in the displacements z,y,x even though the rest of the code is nominally x,y,z
        #    so that our resulting strain tensor is the right way around (that is to say z-first)
        nodalDisplacements[ 0, : ] = displacements[ z  , y  , x  , : ]
        nodalDisplacements[ 1, : ] = displacements[ z+1, y  , x  , : ]
        nodalDisplacements[ 2, : ] = displacements[ z+1, y+1, x  , : ]
        nodalDisplacements[ 3, : ] = displacements[ z  , y+1, x  , : ]
        nodalDisplacements[ 4, : ] = displacements[ z  , y  , x+1, : ]
        nodalDisplacements[ 5, : ] = displacements[ z+1, y  , x+1, : ]
        nodalDisplacements[ 6, : ] = displacements[ z+1, y+1, x+1, : ]
        nodalDisplacements[ 7, : ] = displacements[ z  , y+1, x+1, : ]
        
        if numpy.all( numpy.isfinite( nodalDisplacements ) ) == False:
            strain[ z, y, x, :, : ] = numpy.zeros( (3,3) ) * numpy.nan
            rot[ z, y, x, :, : ]    = numpy.zeros( (3,3) ) * numpy.nan

        else:
            # This is our temporary variable for the calculation of the gradient of displacement
            dudx = numpy.zeros( ( 3, 3 ) )

            #-----------------------------------------------------------------------
            #-  Calculate du/dx --  2014-11-12 PB and EA: removing (du/dx).T since we're going for a green-lagrange tensor... see above
            #-----------------------------------------------------------------------
            for i in range(3):
              for j in range( i, 3 ):  # N.B. this does: i,j = 0,0; 0,1; 0,2; 1,1; 1,2; 2,2
                for nodeNumber in range(8):
                  # Original Comment: /* strain=dsdx*SFderivative*nodalDisplacements; */
                  dudx[i,j] = dudx[i,j] + ( Bn[i,nodeNumber] * nodalDisplacements[nodeNumber,j] )

                  # 2014-10-13 adding rotation matrix calculation
                  rot[   z,y,x,i,j] = rot[   z,y,x,i,j] + \
                                      0.5*(Bn[i,nodeNumber]*nodalDisplacements[nodeNumber,j] - Bn[j,nodeNumber]*nodalDisplacements[nodeNumber,i])

            # 2014-11-12 PB and EA: completing the diagonal terms of the dudx and rotation tensors
            dudx[ 1, 0 ] = dudx[ 0, 1 ]
            dudx[ 2, 0 ] = dudx[ 0, 2 ]
            dudx[ 2, 1 ] = dudx[ 1, 2 ]

            rot[ z,y,x,1,0 ]    = rot[ z,y,x,0,1]
            rot[ z,y,x,2,0 ]    = rot[ z,y,x,0,2]
            rot[ z,y,x,2,1 ]    = rot[ z,y,x,1,2]

            # Strain Gradient tensor
            F = I + dudx

            # Right Cauchy-Green tensor (as opposed to left)
            C = numpy.dot( F.T, F )

            # Green-Lagrange tensors
            E = 0.5*( C - I )

            # Call our strain "E"
            strain[ z, y, x, :, : ] = E

            # 2017-03-09 EA and JD: If VTK set calculate this -- excluding by default because the .append is crazy slow
            if calculateConnectivity:
                firstCorner = x + y*len(nodes_x) + z*len(nodes_x)*len(nodes_y)
                connectivity = numpy.append( connectivity, [ [ firstCorner,                                          firstCorner+1, 
                                                                firstCorner+len(nodes_x)+1,                           firstCorner+len(nodes_x),
                                                                firstCorner+len(nodes_x)*len(nodes_y),                firstCorner+len(nodes_x)*len(nodes_y)+1, 
                                                                firstCorner+len(nodes_x)*len(nodes_y)+len(nodes_x)+1, firstCorner+len(nodes_x)*len(nodes_y)+len(nodes_x) ] ], axis=0 )
                cellIndex = numpy.append( cellIndex, x + y*(len(nodes_x)-1) + z*(len(nodes_x)-1)*(len(nodes_y)-1) )

  try: logging.log.info("regular_strain_large_strain: strain calculation done.")
  except: print "regular_strain_large_strain: strain calculation done."
                
  return [ strain, rot, connectivity, cellIndex ]
def regular_strain_small_strain(positions,
                                displacements,
                                calculateConnectivity=False):

    try:
        logging.log.info(
            "regular_strain_small_strain: Calculating strains in Small Strain framework..."
        )
    except:
        print "regular_strain_small_strain: Calculating strains in Small Strain framework..."

    SFderivative = numpy.zeros(
        (3, 8))  # Derivative of shape functions from F.E.
    relNodePos = numpy.zeros((8, 3))  # RELATIVE Node positions
    nodalDisplacements = numpy.zeros((8, 3))  # Nodal displacements
    dsdx = numpy.zeros((3, 3))  #
    dxds = numpy.zeros((3, 3))
    Bn = numpy.zeros((3, 8))  # D/dx with shape function

    # N.B. x is in the real coordiantes of the image
    #      s is in the Shape Function coordinates.

    ########################################################################
    ##   Derivative of shape function nodal weights from F.E.             ##
    ########################################################################
    # Derivatives of the 8-node shape function wrt X
    SFderivative[0, 0] = -0.125
    SFderivative[0, 1] = 0.125
    SFderivative[0, 2] = 0.125
    SFderivative[0, 3] = -0.125
    SFderivative[0, 4] = -0.125
    SFderivative[0, 5] = 0.125
    SFderivative[0, 6] = 0.125
    SFderivative[0, 7] = -0.125

    # Derivatives of the 8-node shape function wrt Y
    SFderivative[1, 0] = -0.125
    SFderivative[1, 1] = -0.125
    SFderivative[1, 2] = 0.125
    SFderivative[1, 3] = 0.125
    SFderivative[1, 4] = -0.125
    SFderivative[1, 5] = -0.125
    SFderivative[1, 6] = 0.125
    SFderivative[1, 7] = 0.125

    # Derivatives of the 8-node shape function wrt Z
    SFderivative[2, 0] = -0.125
    SFderivative[2, 1] = -0.125
    SFderivative[2, 2] = -0.125
    SFderivative[2, 3] = -0.125
    SFderivative[2, 4] = 0.125
    SFderivative[2, 5] = 0.125
    SFderivative[2, 6] = 0.125
    SFderivative[2, 7] = 0.125

    ########################################################################
    ##  Relative nodal positions                                          ##
    ########################################################################
    #-----------------------------------------------------------------------
    #-  Calculate nodal spacing                                           --
    #-      (this comes from regular_prior_interpolator.py)               --
    #-----------------------------------------------------------------------

    number_of_nodes = positions.shape[0]
    connectivity = numpy.zeros((0, 8))
    cellIndex = numpy.zeros((0, )).astype('i')

    nodes_z, nodes_y, nodes_x = calculate_node_spacing(positions)

    try:
        # Figure out spacing from first two nodes positions
        z_spacing = nodes_z[1] - nodes_z[0]
        y_spacing = nodes_y[1] - nodes_y[0]
        x_spacing = nodes_x[1] - nodes_x[0]
    except IndexError:
        raise Exception('Warning: Not enough nodes to calculate strain')

    # Define strain matrix
    #  2014-11-12 PB and EA: changing strain 6-component vector to a full 3x3 strain tensor
    strain = numpy.zeros(
        (len(nodes_z) - 1, len(nodes_y) - 1, len(nodes_x) - 1, 3, 3))
    rot = numpy.zeros(
        (len(nodes_z) - 1, len(nodes_y) - 1, len(nodes_x) - 1, 3, 3))

    #-----------------------------------------------------------------------
    #-  Definition of elements                                            --
    #-----------------------------------------------------------------------
    # 2014-11-12 PB and EA: This is the RELATIVE position of the nodes WRT node 1, which is at 0,0,0
    relNodePos[0, 0] = 0.0
    relNodePos[1, 0] = z_spacing
    relNodePos[2, 0] = z_spacing
    relNodePos[3, 0] = 0.0
    relNodePos[4, 0] = 0.0
    relNodePos[5, 0] = z_spacing
    relNodePos[6, 0] = z_spacing
    relNodePos[7, 0] = 0.0
    relNodePos[0, 1] = 0.0
    relNodePos[1, 1] = 0.0
    relNodePos[2, 1] = y_spacing
    relNodePos[3, 1] = y_spacing
    relNodePos[4, 1] = 0.0
    relNodePos[5, 1] = 0.0
    relNodePos[6, 1] = y_spacing
    relNodePos[7, 1] = y_spacing
    relNodePos[0, 2] = 0.0
    relNodePos[1, 2] = 0.0
    relNodePos[2, 2] = 0.0
    relNodePos[3, 2] = 0.0
    relNodePos[4, 2] = x_spacing
    relNodePos[5, 2] = x_spacing
    relNodePos[6, 2] = x_spacing
    relNodePos[7, 2] = z_spacing

    # Original Comment: /* Calculate dxds = SFderivative*relNodePos and so dsdx=inv(dxds) */
    for i in range(3):
        for j in range(3):
            for nodeNumber in range(8):
                # 2014-11-12 PB and EA: loop over each of the 8 nodes, summing the 8 derivatives
                dxds[i, j] = dxds[i, j] + SFderivative[
                    i, nodeNumber] * relNodePos[nodeNumber, j]

    # 2014-11-12 PB and EA: Replaing above commented calculations with a numpy inverse
    dsdx = numpy.linalg.inv(dxds)

    #-----------------------------------------------------------------------
    #-  Operator which describes weighting of nodal coordinates by shape  --
    #-    function (see Hall et al. 2006)                                 --
    #-----------------------------------------------------------------------
    for ii in range(3):
        for nodeNumber in range(8):
            for kk in range(3):
                Bn[ii, nodeNumber] = Bn[
                    ii,
                    nodeNumber] + dsdx[ii, kk] * SFderivative[kk, nodeNumber]

    ########################################################################
    ##  Getting the displacements around each node                        ##
    ########################################################################
    #-----------------------------------------------------------------------
    #-  Reshape the displacements so that we easily have the neighbours   --
    #-----------------------------------------------------------------------
    displacements_x = displacements[:, 2].reshape(
        (len(nodes_z), len(nodes_y), len(nodes_x)))
    displacements_y = displacements[:, 1].reshape(
        (len(nodes_z), len(nodes_y), len(nodes_x)))
    displacements_z = displacements[:, 0].reshape(
        (len(nodes_z), len(nodes_y), len(nodes_x)))

    # This is a 4D array of x, y, z positions + component...
    displacements = displacements.reshape(
        (len(nodes_z), len(nodes_y), len(nodes_x), 3))

    #-----------------------------------------------------------------------
    #-  Fetch neighbourhood displacements from x y z displacements        --
    #-    i.e., fill in the nodalDisplacements matrix  numpy.zeros( ( 8, 3 ) )            --
    #-----------------------------------------------------------------------
    for z in range(len(nodes_z) - 1):
        print "\tregular_strain_small_strain: Working on z=%04i/%04i\r" % (
            z, len(nodes_z) - 1),

        for y in range(len(nodes_y) - 1):
            for x in range(len(nodes_x) - 1):

                # All the displacements (x,y,z) for the node
                # This at the end of the matrix makes it backwards -> [::-1],
                #   this puts us back into x,y,z like the rest of this strain code.
                nodalDisplacements[0, :] = displacements[z, y, x, :]
                nodalDisplacements[1, :] = displacements[z + 1, y, x, :]
                nodalDisplacements[2, :] = displacements[z + 1, y + 1, x, :]
                nodalDisplacements[3, :] = displacements[z, y + 1, x, :]
                nodalDisplacements[4, :] = displacements[z, y, x + 1, :]
                nodalDisplacements[5, :] = displacements[z + 1, y, x + 1, :]
                nodalDisplacements[6, :] = displacements[z + 1, y + 1,
                                                         x + 1, :]
                nodalDisplacements[7, :] = displacements[z, y + 1, x + 1, :]

                if numpy.all(numpy.isfinite(nodalDisplacements)) == False:
                    strain[z, y, x, :, :] = numpy.zeros((3, 3)) * numpy.nan
                    rot[z, y, x, :, :] = numpy.zeros((3, 3)) * numpy.nan

                else:
                    #-----------------------------------------------------------------------
                    #-  Calculate Strain                                                  --
                    #-----------------------------------------------------------------------
                    for i in range(3):
                        for j in range(
                                i, 3
                        ):  # N.B. this does: i,j = 0,0; 0,1; 0,2; 1,1; 1,2; 2,2
                            for nodeNumber in range(8):
                                # Original Comment: /* strain=dsdx*SFderivative*nodalDisplacements; */
                                strain[z,y,x,i,j] = strain[z,y,x,i,j] + \
                                                    0.5 * ( Bn[i,nodeNumber] * nodalDisplacements[nodeNumber,j] + Bn[j,nodeNumber] * nodalDisplacements[nodeNumber,i] )

                                # 2014-10-13 adding rotation matrix calculation
                                rot[   z,y,x,i,j] = rot[   z,y,x,i,j] + \
                                                    0.5*(Bn[i,nodeNumber]*nodalDisplacements[nodeNumber,j] - Bn[j,nodeNumber]*nodalDisplacements[nodeNumber,i])

                    # 2014-11-12 PB and EA: completing the diagonal terms of the strain and rotation tensors
                    strain[z, y, x, 1, 0] = strain[z, y, x, 0, 1]
                    strain[z, y, x, 2, 0] = strain[z, y, x, 0, 2]
                    strain[z, y, x, 2, 1] = strain[z, y, x, 1, 2]

                    rot[z, y, x, 1, 0] = rot[z, y, x, 0, 1]
                    rot[z, y, x, 2, 0] = rot[z, y, x, 0, 2]
                    rot[z, y, x, 2, 1] = rot[z, y, x, 1, 2]

                    # 2017-03-09 EA and JD: If VTK set calculate this -- excluding by default because the .append is crazy slow
                    if calculateConnectivity:
                        firstCorner = x + y * len(nodes_x) + z * len(
                            nodes_x) * len(nodes_y)
                        connectivity = numpy.append(connectivity, [[
                            firstCorner, firstCorner + 1, firstCorner +
                            len(nodes_x) + 1, firstCorner + len(nodes_x),
                            firstCorner + len(nodes_x) * len(nodes_y),
                            firstCorner + len(nodes_x) * len(nodes_y) + 1,
                            firstCorner + len(nodes_x) * len(nodes_y) +
                            len(nodes_x) + 1, firstCorner +
                            len(nodes_x) * len(nodes_y) + len(nodes_x)
                        ]],
                                                    axis=0)
                        cellIndex = numpy.append(
                            cellIndex, x + y * (len(nodes_x) - 1) + z *
                            (len(nodes_x) - 1) * (len(nodes_y) - 1))

    try:
        logging.log.info(
            "regular_strain_small_strain(): strain calculation done.")
    except:
        print "regular_strain_small_strain(): strain calculation done."

    return [strain, rot, connectivity, cellIndex]
Beispiel #10
0
def regular_prior_interpolator(old_prior, new_prior, filter_size=None):

    old_nodes_z, old_nodes_y, old_nodes_x = calculate_node_spacing(
        old_prior[:, 1:4])

    # Figure out spacing from first two nodes positions
    if len(old_nodes_z) == 1:
        old_z_spacing = 1
    else:
        old_z_spacing = old_nodes_z[1] - old_nodes_z[0]
    old_y_spacing = old_nodes_y[1] - old_nodes_y[0]
    old_x_spacing = old_nodes_x[1] - old_nodes_x[0]
    try:
        logging.log.info(
            "regular_prior_interpolator: Prior node spacing (z,y,x) is:\t{:.0f} {:.0f} {:.0f}"
            .format(old_z_spacing, old_y_spacing, old_x_spacing))
    except:
        print "regular_prior_interpolator: Prior node spacing (z,y,x) is:\t{:.0f} {:.0f} {:.0f}".format(
            old_z_spacing, old_y_spacing, old_x_spacing)

    # Reshape prior field to a three dimensional arrays
    z_field = old_prior[:, 4].reshape(
        (len(old_nodes_z), len(old_nodes_y), len(old_nodes_x)))
    y_field = old_prior[:, 5].reshape(
        (len(old_nodes_z), len(old_nodes_y), len(old_nodes_x)))
    x_field = old_prior[:, 6].reshape(
        (len(old_nodes_z), len(old_nodes_y), len(old_nodes_x)))
    z_rot = old_prior[:, 7].reshape(
        (len(old_nodes_z), len(old_nodes_y), len(old_nodes_x)))
    y_rot = old_prior[:, 8].reshape(
        (len(old_nodes_z), len(old_nodes_y), len(old_nodes_x)))
    x_rot = old_prior[:, 9].reshape(
        (len(old_nodes_z), len(old_nodes_y), len(old_nodes_x)))

    #Replacing the Inf in the prior with the median of finte values around (in None replace with zero)
    inf_positions = numpy.where(numpy.isinf(x_field))

    for inf_number in range(len(inf_positions[0])):
        z = inf_positions[0][inf_number]
        y = inf_positions[1][inf_number]
        x = inf_positions[2][inf_number]

        try:
            z_field[z, y, x] = numpy.media(z_field[where(
                numpy.isfinite(z_filed[z - 1:z + 2, y - 1:y + 2,
                                       z - 1:x + 2]))])
            y_field[z, y, x] = numpy.media(y_field[where(
                numpy.isfinite(y_filed[z - 1:z + 2, y - 1:y + 2,
                                       z - 1:x + 2]))])
            x_field[z, y, x] = numpy.media(x_field[where(
                numpy.isfinite(x_filed[z - 1:z + 2, y - 1:y + 2,
                                       z - 1:x + 2]))])
        except:
            pass

    z_field[numpy.where(numpy.isinf(z_field))] = 0
    y_field[numpy.where(numpy.isinf(y_field))] = 0
    x_field[numpy.where(numpy.isinf(x_field))] = 0

    if filter_size is not None and filter_size > 0:
        try:
            logging.log.info(
                "regular_prior_interpolator: Smoothing kinematics field")
        except:
            print "regular_prior_interpolator: Smoothing kinematics field"
        # 2014-07-18 -- Edward Ando
        # Changing the median filter for the field from scipy.ndimage.filters.median_filter
        #   (which seems to propagate NaNs) to our own, home-developed median filter:
        z_field = median_filter_nans(numpy.squeeze(z_field),
                                     filter_size).reshape(
                                         (len(old_nodes_z), len(old_nodes_y),
                                          len(old_nodes_x)))
        y_field = median_filter_nans(numpy.squeeze(y_field),
                                     filter_size).reshape(
                                         (len(old_nodes_z), len(old_nodes_y),
                                          len(old_nodes_x)))
        x_field = median_filter_nans(numpy.squeeze(x_field),
                                     filter_size).reshape(
                                         (len(old_nodes_z), len(old_nodes_y),
                                          len(old_nodes_x)))
        z_rot = median_filter_nans(numpy.squeeze(z_rot), filter_size).reshape(
            (len(old_nodes_z), len(old_nodes_y), len(old_nodes_x)))
        y_rot = median_filter_nans(numpy.squeeze(y_rot), filter_size).reshape(
            (len(old_nodes_z), len(old_nodes_y), len(old_nodes_x)))
        x_rot = median_filter_nans(numpy.squeeze(x_rot), filter_size).reshape(
            (len(old_nodes_z), len(old_nodes_y), len(old_nodes_x)))

    # Normalise coordinates of new prior nodes positions
    #   (subtract position of old top corner and divide by old node spacing), to get into the SHAPE => SIZE
    #   of the old prior for interpolation.
    new_prior_normalised = numpy.zeros((new_prior.shape[0], 3),
                                       dtype=numpy.float32)
    new_prior_normalised[:, 0] = (new_prior[:, 1] -
                                  old_nodes_z[0]) / old_z_spacing
    new_prior_normalised[:, 1] = (new_prior[:, 2] -
                                  old_nodes_y[0]) / old_y_spacing
    new_prior_normalised[:, 2] = (new_prior[:, 3] -
                                  old_nodes_x[0]) / old_x_spacing

    # Interpolate each prior field for each new node
    # 2014-07-23 Edward Andò:
    #   map_coordinates does not handle NaNs, and cannot handle masked arrays for the moment,
    #   ...so we will seek and destroy the NaNs in the displacement fields before doing a map_coordinates
    # This means for each NaN position, we will grow a window until we get a real value,
    #   and then we'll use that window do make a median to fill in our NaN measurement.

    # Figure out NaN positions... (they will be in the same place for every field)
    nan_positions = numpy.where(numpy.isnan(x_field))

    # A mask of ones and zeros in order to quickly work out the smallest window size for the filter
    mask = numpy.ones((len(old_nodes_z), len(old_nodes_y), len(old_nodes_x)),
                      dtype='bool')
    mask[nan_positions] = False

    number_of_nans = len(nan_positions[0])

    if number_of_nans > 0:
        try:
            logging.log.warn(
                "regular_prior_interpolator(): {:.0f} NaNs detected, replacing them with a median value of the smallest window that touches real data"
                .format(number_of_nans))
        except:
            print "regular_prior_interpolator(): {:.0f} NaNs detected, replacing them with a median value of the smallest window that touches real data".format(
                number_of_nans)

    for nan_number in range(number_of_nans):
        z = nan_positions[0][nan_number]
        y = nan_positions[1][nan_number]
        x = nan_positions[2][nan_number]

        z_top = z
        y_top = y
        x_top = x

        z_bot = z
        y_bot = y
        x_bot = x

        window_sum = 0
        step = 0

        while window_sum == 0:
            step += 1
            #print "step = ", step
            if z_top >= 0: z_top -= step
            if y_top >= 0: y_top -= step
            if x_top >= 0: x_top -= step

            if z_bot <= len(old_nodes_z): z_bot += step
            if y_bot <= len(old_nodes_y): y_bot += step
            if x_bot <= len(old_nodes_x): x_bot += step

            window_sum = numpy.sum(   mask[ z_top:z_bot+1,\
                                            y_top:y_bot+1,\
                                            x_top:x_bot+1   ] )

            local_mask = numpy.where( mask[ z_top:z_bot+1,\
                                            y_top:y_bot+1,\
                                            x_top:x_bot+1   ] )

        z_field[ z, y, x ] = numpy.median( z_field[ z_top:z_bot+1,\
                                                    y_top:y_bot+1,\
                                                    x_top:x_bot+1   ][local_mask] )
        y_field[ z, y, x ] = numpy.median( y_field[ z_top:z_bot+1,\
                                                    y_top:y_bot+1,\
                                                    x_top:x_bot+1   ][local_mask] )
        x_field[ z, y, x ] = numpy.median( x_field[ z_top:z_bot+1,\
                                                    y_top:y_bot+1,\
                                                    x_top:x_bot+1   ][local_mask] )

        z_rot[ z, y, x ] = numpy.median( z_rot[ z_top:z_bot+1,\
                                                    y_top:y_bot+1,\
                                                    x_top:x_bot+1   ][local_mask] )
        y_rot[ z, y, x ] = numpy.median( y_rot[ z_top:z_bot+1,\
                                                    y_top:y_bot+1,\
                                                    x_top:x_bot+1   ][local_mask] )
        x_rot[ z, y, x ] = numpy.median( x_rot[ z_top:z_bot+1,\
                                                    y_top:y_bot+1,\
                                                    x_top:x_bot+1   ][local_mask] )

    new_z_field = ndimage.map_coordinates(z_field,
                                          new_prior_normalised.T,
                                          order=1,
                                          mode='nearest',
                                          prefilter=False).T
    new_y_field = ndimage.map_coordinates(y_field,
                                          new_prior_normalised.T,
                                          order=1,
                                          mode='nearest').T
    new_x_field = ndimage.map_coordinates(x_field,
                                          new_prior_normalised.T,
                                          order=1,
                                          mode='nearest').T

    new_z_rot = ndimage.map_coordinates(z_rot,
                                        new_prior_normalised.T,
                                        order=1,
                                        mode='nearest',
                                        prefilter=False).T
    new_y_rot = ndimage.map_coordinates(y_rot,
                                        new_prior_normalised.T,
                                        order=1,
                                        mode='nearest').T
    new_x_rot = ndimage.map_coordinates(x_rot,
                                        new_prior_normalised.T,
                                        order=1,
                                        mode='nearest').T

    # Update and return new prior guesses array
    new_prior[:, 4] = new_z_field
    new_prior[:, 5] = new_y_field
    new_prior[:, 6] = new_x_field
    new_prior[:, 7] = new_z_rot
    new_prior[:, 8] = new_y_rot
    new_prior[:, 9] = new_x_rot

    return new_prior