#pragma rtGlobals=1 // Use modern global access method. #pragma version = 1.1 #pragma ModuleName= bentSi Menu "Macros" "Pick angle axis",bentSi#PickAngles(Rodriques,$"") "X rotation between cursors",/Q,yAngleBetweenCursors() End Function GetStrains(fileRoot,i0,i1) String fileRoot // e.g. "ws7_1_" Variable i0,i1 // Variable i, i0=142, i1=188 // Variable i, i0=151, i1=188 if (!strlen(fileRoot)) DoAlert 0, "you must give the file root" return 1 endif String str = StrVarOrDefault("strainPath","") if (strlen(str)<1) Abort "no path string found" endif printf "using path '%s'\r",str Variable N = i1-i0+1 // Make/N=(N)/O ezz=NaN,eyy=NaN,exx=NaN Make/N=(N)/O exx=NaN, exy=NaN, exz=NaN Make/N=(N)/O eyx=NaN, eyy=NaN, eyz=NaN Make/N=(N)/O ezx=NaN, ezy=NaN, ezz=NaN Make/N=(N,2)/O int=NaN // will be redimensioned later // SetScale/P x i0,1,"µm", exx,eyy,ezz,int SetScale/P x i0,1,"µm", exx,exy,exz,eyx,eyy,eyz,ezx,ezy,ezz,int Make/N=(3,3)/O/D rot // a single rotation matrix Make/N=(N,3)/O/D Rodriques Rodriques = NaN Variable i,j,nn, angle String hklList,hkl String fName,origFile="", noteStr="", wName wName = UniqueName("vec3",1,0) Make/N=3/O/D $wName Wave vec3 = $wName wName = UniqueName("symOp",1,0) Make/N=(3,3)/D/O $wName Wave symOp=$wName Variable refMatNum = NumVarOrDefault(":refMatNum",(i0+i1)/2+1) sprintf fName, "%s%d.IND",fileRoot,abs(refMatNum) // use refrence matrix from the center of the scan if (refMatNum>=0) // a valid refMatNum Make/N=(3,3)/O/D refMat printf "reading refMat using '%s'\r",fName ReadOrientationMat(fName,refMat) // get the refrence matrix 'refMat' SquareUpMatrix(refMat) Note/K refMat, "fName="+fName else printf "using the existing refMat\r" endif printWave(refMat) hklList = StringByKey("hklList",readIntensities(fName),"=") noteStr = ReplaceStringByKey("hklList",noteStr,hklList,"=") nn = ItemsInList(hklList,",") Redimension/N=(N,nn) int int = NaN for (j=0;j traceMax) // save value for optimum rotation matrix traceMax = trace11[0] Si = symOp endif endfor KillWaves/Z symOp, trace11 End Static Function/S readStrainMat(fName) String fName SVAR pathStr=strainPath NewPath/O/Q/Z strain, pathStr if (V_flag) Abort "could not set path" endif Variable refNum String matName=UniqueName("strainMat",1,0) Make/N=(3,3)/O/D $matName=NaN Wave mat=$matName String noteStr="" Open/M="the .str file"/P=strain/R/T=".STR"/Z=1 refNum as fName if (!V_flag) // String line=" ", find="deviatoric strain in crystal reference u1 u2 u3", origFile String line=" ", find="deviatoric strain in lab reference X Y Z", origFile FReadLine refNum, origFile origFile = ReplaceString("\r", origFile,"") // remove trailing carriage return noteStr="origFile="+origFile for (;strsearch(line,find,0)<0 && strlen(line)>0;) FReadLine refNum, line endfor Variable a,b,c FReadLine refNum, line sscanf line, "%g %g %g",a,b,c mat[0][0] = a ; mat[0][1] = b ; mat[0][2] = c FReadLine refNum, line sscanf line, "%g %g %g",a,b,c mat[1][0] = a ; mat[1][1] = b ; mat[1][2] = c FReadLine refNum, line sscanf line, "%g %g %g",a,b,c mat[2][0] = a ; mat[2][1] = b ; mat[2][2] = c Close refNum endif fName = ReplaceString(".STR",fName,".IND") noteStr = readIntensities(fName)+noteStr // returns list of intensities for a predefined list of hkl's Note/K mat Note mat, noteStr return GetWavesDataFolder(mat,2) End Static Function ReadOrientationMat(fName,mat) // read one orientation mat from an '.IND' file String fName Wave mat // the orientation mat to read Variable refNum Open/M="the .IND file"/P=strain/R/T=".IND"/Z=1 refNum as fName if (V_flag) mat = NaN // default to bad data return 1 // could not open the file endif Variable i String line do FReadLine/N=200 refNum, line i = strsearch(line,"matrix X Y Z -> h k l",0) while(i<0 && strlen(line)) if (!strlen(line)) // came to EOF before finding matrix Close refNum return 1 endif Variable a,b,c FReadLine/N=200 refNum, line sscanf line, "%g %g %g",a,b,c mat[0][0] = a ; mat[0][1] = b ; mat[0][2] = c FReadLine/N=200 refNum, line sscanf line, "%g %g %g",a,b,c mat[1][0] = a ; mat[1][1] = b ; mat[1][2] = c FReadLine/N=200 refNum, line sscanf line, "%g %g %g",a,b,c mat[2][0] = a ; mat[2][1] = b ; mat[2][2] = c Close refNum return 0 End Static Function/S readIntensities(fName) // returns list of intensities for a predefined list of hkl's String fName // String list = "0,0,4;2,2,8;-2,0,6;0,2,6" // String list = "0,0,4;2,2,8;-1,1,7;1,3,7" // String list = "0,0,4;2,2,8;-1,1,7;-1,-1,9" // String list = "0,0,4;2,2,8;1,1,7;-1,-1,9" // list of peaks for intensity String list = "0,0,4;2,2,8;0,-2,10;-1,-1,9" // list of peaks for intensity Variable refNum String noteStr="" Open/M="the .ind file"/P=strain/R/T=".IND"/Z=1 refNum as fName if (V_flag) return "" endif Close refNum LoadWave/G/M/N=data/O/P=strain/Q S_fileName String listOfWaves = S_waveNames Wave data=data0 String str,hkl,item=" ",hklList="" Variable j, h,k,l for (j=0, item=StringFromList(j,list); strlen(item);j+=1, item=StringFromList(j,list)) sscanf item, "%d,%d,%d",h,k,l sprintf hkl, "(%d%d%d)",h,k,l hklList += SelectString(j,"",",")+hkl endfor noteStr = ReplaceStringByKey("hklList",noteStr,hklList,"=") Make/N=3/O/D hkl0,hkl1 Variable i,int, N=DimSize(data,0) for (j=0, item=StringFromList(j,list); strlen(item);j+=1, item=StringFromList(j,list)) sscanf item, "%d,%d,%d",h,k,l sprintf hkl, "(%d%d%d)",h,k,l hkl0 = {h,k,l} int = NaN for (i=0;i(1-6e-10)) // 1-cos(0.002¡) = 6e-10 int = data[i][11] break endif endfor noteStr = ReplaceNumberByKey(hkl,noteStr,roundSignificant(int,6),"=") endfor for (i=0, item=StringFromList(i,listOfWaves); strlen(item);i+=1, item=StringFromList(i,listOfWaves)) KillWaves/Z $item endfor KillWaves/Z hkl0,hkl1 return noteStr End Static Function PickAngles(R,axis) Wave R // list of Rodriques vectors Wave axis Variable N = DimSize(R,0) if (N<1 || DimSize(R,1)!=3 || WaveDims(R)!=2) DoAlert 0, "'"+NameOfWave(R)+" has illegal dimensions" return 1 endif Variable needPrompt=!WaveExists(axis) if (!needPrompt) needPrompt += (WaveDims(axis)==3) needPrompt += (DimSize(axis,9)==3) needPrompt += numtype(sum(axis)) endif String wName = UniqueName("vec3",1,0) Make/N=3/O/D $wName Wave axisv = $wName wName = UniqueName("vec3",1,0) Make/N=3/O/D $wName Wave vec3 = $wName Variable total = 0 if (needPrompt) String axisName Prompt axisName,"axis direction",popup,"total angle;X;Y;Z" DoPrompt "Axis Direction",axisName if (V_flag) KillWaves/Z axisv,vec3 return 1 endif if (stringMatch(axisName,"X")) axisv = {1,0,0} elseif (stringMatch(axisName,"Y")) axisv = {0,1,0} elseif (stringMatch(axisName,"Z")) axisv = {0,0,1} elseif (stringMatch(axisName,"total angle")) total = 1 else Abort "impossible in PickAngles()" endif else axisv = axis total = (norm(axis)==0) endif normalize(axisv) Make/N=(N)/O/D angles Variable i,angle, dot for (i=0;i1e-4) DoAlert 0, "'"+NameOfWave(rot)+"' is not a rotation matrix in axisOfMatrix()" axis = NaN return NaN elseif (0=norm1 && norm0>=norm2) // X is longest Cross vec0,vec1 // Z = X x Y Wave W_Cross=W_Cross vec2 = W_Cross Cross vec2,vec0 // Y = Z x X vec1 = W_Cross elseif (norm1>=norm0 && norm1>=norm2)// Y is longest Cross vec1,vec2 // X = Y x Z Wave W_Cross=W_Cross vec0 = W_Cross Cross vec0,vec1 // Z = X x Y vec2 = W_Cross else // Z is longest Cross vec2,vec0 // Y = Z x X Wave W_Cross=W_Cross vec1 = W_Cross Cross vec1,vec2 // X = Y x Z vec0 = W_Cross endif err = normalize(vec0) err += normalize(vec1) err += normalize(vec2) mat[][0] = vec0[p] mat[][1] = vec1[p] mat[][2] = vec2[p] err = ( notRotationMatrix(mat) != 0 ) // 0 is a rotation matrix KillWaves/Z vec0,vec1,vec2,W_Cross return numtype(err) End // Static Function notRotationMatrix(mat) // false if mat is a rotation matrix, i.e. mat^T = mat^-1 Wave mat String wName = UniqueName("rot",1,0) MatrixOp/O $wName = Abs(( mat x mat^t ) - Identity(3)) Wave diff = $wName Variable sumd = sum(diff) // printWave(diff) // print "sum(diff) = ",sumd KillWaves/Z $wName Variable returnVal, thresh=2e-10 if (sumd>thresh) returnVal = sumd // not a rotation matrix elseif (MatrixDet(mat)<0) returnVal = -1 // an improper rotation matrix else returnVal = 0 // yes it is a rotation matrix endif if (ItemsInList(GetRTStackInfo(0))<2) printf "'%s' is %s matrix\r",NameOfWave(mat),SelectString(returnVal ,"an improper rotation","a rotation","NOT a rotation") if (sumd>=thresh && sumd<1e-5) printf " but, it is almost a rotation matrix, sum(|diff|) = %g\r",sumd endif endif return returnVal End // // Used to make temporary internal waves, a typical use would be: Wave xxx=$MakeUnique3Vector($"") // You will probably want to KillWaves/Z xxx, at the end of the routine. Static Function/S MakeUnique3Vector(preset) // make a new 3-vector, and optionally set it to preset[] Wave preset // optional wave, if none call with $"" String wName = UniqueName("vec3_",1,0) Make/N=3/D $wName Wave vec=$wName if (WaveExists(preset)) vec = preset endif return GetWavesDataFolder(vec,2) // return full path for assingment to a wave End // // Used to make temporary internal waves, a typical use would be: Wave xxx=$MakeUnique3Vector($"") // You will probably want to KillWaves/Z xxx, at the end of the routine. Static Function/S MakeUnique3x3Mat(preset) // make a new 3x3 matrix, and optionally set it to preset[] Wave preset // optional wave, if none call with $"" String wName = UniqueName("mat3x3_",1,0) Make/N=(3,3)/D $wName Wave mat=$wName if (WaveExists(preset)) mat = preset endif return GetWavesDataFolder(mat,2) // return full path for assingment to a wave End Static Function parallel(a,b) // true if a & b are parallel or anti-parallel Wave a,b Variable cosine = MatrixDot(a,b)/norm(a)/norm(b) return (abs(cosine)>(1-6e-10)) // 1-cos(0.002¡) = 6e-10 End // Static Function cosineAB(a,b) // cosine of angle between a and b Wave a,b Variable cosine = MatrixDot(a,b)/norm(a)/norm(b) return cosine End