diff --git a/src/SimNDT/core/inspectionMethods.py b/src/SimNDT/core/inspectionMethods.py new file mode 100644 index 0000000..2beb5e2 --- /dev/null +++ b/src/SimNDT/core/inspectionMethods.py @@ -0,0 +1,303 @@ +#!/usr/bin/env python +# encoding: utf-8 +""" +inspectionMethods.py + +Created by Miguel Molero on 2013-09-26. +Copyright (c) 2013 MMolero. All rights reserved. +""" + +from math import sin, cos, sqrt, pi +import numpy as np + +import SimNDT.core.inspectionSetup as Inspection +import copy + +class Source: + def __init__(self): + self.Longitudinal = True + self.Shear = False + self.Pressure = True + self.Displacement = False + self.hideReceiver = False + + def __str__(self): + return ("Source: Longitudinal={}, Shear={}, Pressure={}, " + "Displacement={}, HideReceiver={}").format( + self.Longitudinal, self.Shear, self.Pressure, + self.Displacement, self.hideReceiver) + + def __repr__(self): + return ("Source(Longitudinal={}, Shear={}, Pressure={}, " + "Displacement={}, HideReceiver={})").format( + self.Longitudinal, self.Shear, self.Pressure, + self.Displacement, self.hideReceiver) + + + +class SingleLaunch: + + @classmethod + def view(cls, M, N, Pixel_mm, Theta, transducer): + x2 = np.zeros((2,),dtype=np.float32) + y2 = np.zeros((2,),dtype=np.float32) + + Ntheta = np.size(Theta,0) + D_T = np.around(M/2.) + + if transducer.PointSource: + SizePixel = 0.5 + else: + SizePixel = np.around( 0.5 * Pixel_mm * transducer.Size ) + + Location = transducer.Location + + if Location == "Top": + + x2 = M/2. + (D_T)*np.sin(Theta) + y2 = N/2. + (D_T)*np.cos(Theta) + + X0 = np.around(M/2.) + Y0 = np.around(N/2.) + + XL, YL = Inspection.setEmisor(Theta, SizePixel, x2, y2, X0, Y0) + YL += (np.around(transducer.CenterOffset * Pixel_mm )) + XL[:,0] += (np.around(transducer.BorderOffset * Pixel_mm )) + XL[:,1] -= (np.around(transducer.BorderOffset * Pixel_mm )) + XL = np.fliplr(XL) + + + elif Location == "Left": + + x2 = M/2. + (D_T)*np.sin(Theta) + y2 = N/2. + (D_T)*np.cos(Theta) + + X0 = np.around(M/2.) + Y0 = np.around(N/2.) + + XL, YL = Inspection.setEmisor(Theta, SizePixel, x2, y2, X0, Y0) + XL += (np.around(transducer.CenterOffset * Pixel_mm )) + + YL[:,0] += (np.around(transducer.BorderOffset * Pixel_mm )) + YL[:,1] -= (np.around(transducer.BorderOffset * Pixel_mm )) + YL = np.fliplr(YL) + + + return XL, YL + + + def setInspection(self, Scenario, Transducer, Simulation): + """ + set Inspection on numerical model + """ + MRI, NRI = Simulation.MRI, Simulation.NRI + TapGrid = Simulation.TapGrid + Rgrid = Simulation.Rgrid + M = np.shape(Scenario.Iabs)[0] *Rgrid + N = np.shape(Scenario.Iabs)[1] *Rgrid + M2 = M/ 2.0 + N2 = N/ 2.0 + + x2 = np.zeros((2,),dtype=np.float32) + y2 = np.zeros((2,),dtype=np.float32) + Ntheta = np.size(self.Theta,0) + + X0 = np.around((MRI)/2.0) + Y0 = np.around((NRI)/2.0) + x2[0] = X0 + (M2-TapGrid[0])*np.sin(self.Theta[0])+1 + + + if Transducer.Location == "Top": + + if self.Method == "PulseEcho" or self.hideReceiver == True: + x2[1] = x2[0] + else: + x2[1] = X0 + (M2-TapGrid[1])*np.sin(self.Theta[1])-1 + y2[:] = (NRI-TapGrid[2]-TapGrid[3])/2.0 + TapGrid[2] + + + elif Transducer.Location == "Left": + + if self.Method == "PulseEcho": + y2[1] = y2[0] + else: + y2[1] = Y0 + (M2-TapGrid[1])*np.sin(self.Theta[1])-1 + + x2[:] = (NRI-TapGrid[2]-TapGrid[3])/2.0 + TapGrid[2] + + + if Transducer.PointSource: + Transducer.SizePixel = 0.5 + else: + Transducer.SizePixel = np.around( 0.5 * Scenario.Pixel_mm * Transducer.Size * Rgrid ) + + XL, YL = Inspection.setEmisor(self.Theta, Transducer.SizePixel, x2, y2, X0, Y0) + XL, YL, IR = Inspection.centerOffset(XL, YL, self.Theta, Scenario, Transducer, Rgrid) + XL, YL = Inspection.borderOffset(XL, YL, Scenario, Transducer, Rgrid) + + self.XL = XL.copy() + self.YL = YL.copy() + self.IR = IR.copy() + + + def getReceivers(self, T): + return Inspection.getReceivers(self.XL, self.YL, self.IR, T, False) + + + +class Transmission(SingleLaunch): + + def __init__(self,Location="Top"): + self.Name = "Transmission" + self.Method = "Transmission" + self.Location = Location + self.hideReceiver = False + + + if Location=="Top": + self.Theta = [270.0*pi/180.0, 90.0*pi/180.0] + elif Location == "Left": + self.Theta = [180.0*pi/180.0, 0.0*pi/180.0] + + def __str__(self): + return ("Transmission: Method={}, Location={}, Theta={}, HideReceiver={}, " + "XL={}, YL={}, IR={}").format( + self.Method, self.Location, self.Theta, self.hideReceiver, + getattr(self, 'XL', 'Not set'), getattr(self, 'YL', 'Not set'), getattr(self, 'IR', 'Not set')) + + def __repr__(self): + return "Transmission(Location='{}')".format(self.Location) + + + +class PulseEcho(SingleLaunch): + + def __init__(self,Location="Top"): + self.Name = "PulseEcho" + self.Method = "PulseEcho" + self.Location = Location + self.hideReceiver = False + if Location=="Top": + self.Theta = [270.0*pi/180.0, 270*pi/180.0] + elif Location=="Left": + self.Theta = [180.0*pi/180.0, 0.0*pi/180.0] + + def __str__(self): + return ("PulseEcho: Method={}, Location={}, " + "Theta={}, HideReceiver={}").format( + self.Method, self.Location, self.Theta, self.hideReceiver) + + def __repr__(self): + return "PulseEcho(Location='{}')".format(self.Location) + + +class LinearScan(SingleLaunch): + + def __init__(self, ini=-10, end=10, step=1, + Location="Top", Method = "Transmission",Theta = [270.0*pi/180.0, 90.0*pi/180.0]): + + self.Name = "LinearScan" + self.Location = Location + Num = np.size( np.arange(ini,end,step)) + self.ScanVector = np.linspace(ini, end, Num+1, endpoint=True) + self.ScanVectorString = "(%g,%g,%g)"%(ini,end,step) + self.Method = Method + self.Theta = Theta + + def __str__(self): + return ("LinearScan: Method={}, Location={}, " + "ScanVector={}, Theta={}").format( + self.Method, self.Location, self.ScanVectorString, self.Theta) + + def __repr__(self): + return ("LinearScan(ini={}, end={}, " + "step={}, Location='{}', Method='{}')").format( + self.ScanVector[0], + self.ScanVector[-1], + (self.ScanVector[1] - self.ScanVector[0] if len(self.ScanVector) > 1 else 'N/A'), + self.Location, + self.Method) + + + + + +class Tomography: + + def __init__(self,ProjectionStep=45,DiameterRing=50,OneProjection=False): + + self.Name = "Tomography" + self.Method = "Transmission" + self.DiameterRing = DiameterRing + self.ProjectionStep = ProjectionStep + self.OneProjection = OneProjection + self.Theta = np.arange(270,-90.0, -self.ProjectionStep)*(pi/180.0) + + + @staticmethod + def view(M, N, DiameterRing, Pixel_mm, Theta, transducer): + + x2 = np.zeros((2,),dtype=np.float32) + y2 = np.zeros((2,),dtype=np.float32) + + Ntheta = np.size(Theta,0) + D_T = np.around(DiameterRing*Pixel_mm/2.) + + x2 = M/2. + (D_T)*np.sin(Theta) + y2 = N/2. + (D_T)*np.cos(Theta) + + X0 = np.around(M/2.) + Y0 = np.around(N/2.) + + if transducer.PointSource: + SizePixel = 0.5 + else: + SizePixel = np.around( 0.5 * Pixel_mm * transducer.Size ) + + XL, YL = Inspection.setEmisor(Theta, SizePixel, x2, y2, X0, Y0) + + return XL, YL + + + + def setInspection(self, Scenario, Transducer, Simulation): + """ + set Inspection on numerical model + """ + MRI, NRI = Simulation.MRI, Simulation.NRI + TapGrid = Simulation.TapGrid + Rgrid = Simulation.Rgrid + M = np.shape(Scenario.Iabs)[0] *Rgrid + N = np.shape(Scenario.Iabs)[1] *Rgrid + M2 = M/ 2.0 + N2 = N/ 2.0 + Pixel_mm = Scenario.Pixel_mm + + Ntheta = np.size(self.Theta,0) + DR = np.around(self.DiameterRing*Pixel_mm*Rgrid/2.) + + X0 = TapGrid[0] + (Scenario.M/2.0)*Rgrid + Y0 = TapGrid[2] + (Scenario.N/2.0)*Rgrid + x2 = X0 + (DR)*np.sin(self.Theta) + y2 = Y0 + (DR)*np.cos(self.Theta) + + if Transducer.PointSource: + Transducer.SizePixel = 0.5 + else: + Transducer.SizePixel = np.floor( 0.5 * Scenario.Pixel_mm * Transducer.Size * Rgrid ) + + XL, YL = Inspection.setEmisor(self.Theta, Transducer.SizePixel, x2, y2, X0, Y0) + XL, YL, IR = Inspection.centerOffset(XL, YL, self.Theta, Scenario, Transducer, Rgrid) + + + self.XL = XL.copy() + self.YL = YL.copy() + self.IR = IR.copy() + + + def getReceivers(self, T): + return Inspection.getReceivers(self.XL, self.YL, self.IR, T, False) + + + +