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 ) )
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
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('')
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]
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)
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
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]
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