def calcEtaMin(tth, psi): th = tth / 2 # if psi <= th: # etaMin = 0 # else: # etaMin = asind((sind(psi)**2 - sind(th)**2)**0.5 / (bc.cosd(th) * sind(psi))) if psi == 0: return 0 else: return bc.asind((max(0, bc.sind(psi)**2 - bc.sind(th)**2))**0.5 / (bc.cosd(th) * bc.sind(psi)))
def universalPlotAnalysis(data, maxPsi=None, minDistPsiStar=0.15, minValPsiNormal=0.08, minValPsiShear=0.8): # extract needed data a0Val = bf.getDictValOrDef(data, 'a0Val') psiUni = data['psiUni'] sin2psiUni = data['sin2psiUni'] sinpsi2Uni = data['sinpsi2Uni'] psiVals = data['psiVals'] phiVals = data['phiVals'] dVals = data['dVals'] dErrVals = data['dErrVals'] tauVals = data['tauVals'] hklVal = data['hklVal'] s1Val = data['s1Val'] hs2Val = data['hs2Val'] phi4 = data['phi4'] dValsValid = (dVals > 0) & (np.isnan(dVals) == False) tauValsValid = (tauVals >= 0) & (tauVals < 1e6) # define needed variables sinpsi2Star = -2 * s1Val / hs2Val psiStar = bc.asind(sinpsi2Star**0.5) valsAll = np.zeros((len(psiUni), 3)) fplus = np.zeros((len(psiUni), 3)) fminus = np.zeros((len(psiUni), 3)) f13 = np.zeros((len(psiUni), 3)) f23 = np.zeros((len(psiUni), 3)) stresses = np.zeros((len(psiUni), 4)) errVals = np.zeros((len(psiUni), 4)) tauRes = np.zeros(len(psiUni)) resData = dict() validCounter = 0 for i in range(len(psiUni)): if phi4: cond0 = (psiVals == psiUni[i]) & (phiVals == 0) & dValsValid cond90 = (psiVals == psiUni[i]) & (phiVals == 90) & dValsValid cond180 = (psiVals == psiUni[i]) & (phiVals == 180) & dValsValid cond270 = (psiVals == psiUni[i]) & (phiVals == 270) & dValsValid else: cond0 = (psiVals == psiUni[i]) & (phiVals == 0) & dValsValid cond90 = (psiVals == psiUni[i]) & (phiVals == 90) & dValsValid cond180 = (psiVals == -psiUni[i]) & (phiVals == 0) & dValsValid cond270 = (psiVals == -psiUni[i]) & (phiVals == 90) & dValsValid val0 = np.concatenate((dVals[cond0], dVals[cond0] - dErrVals[cond0], dVals[cond0] + dErrVals[cond0])) val90 = np.concatenate( (dVals[cond90], dVals[cond90] - dErrVals[cond90], dVals[cond90] + dErrVals[cond90])) val180 = np.concatenate( (dVals[cond180], dVals[cond180] - dErrVals[cond180], dVals[cond180] + dErrVals[cond180])) val270 = np.concatenate( (dVals[cond270], dVals[cond270] - dErrVals[cond270], dVals[cond270] + dErrVals[cond270])) if len(val0) > 0 and len(val90) > 0 and len(val180) > 0 and len( val270) > 0: fplus[i, :] = val0 + val90 + val180 + val270 fminus[i, :] = (val0 + val180) - (val90 + val270) f13[i, :] = val0 - val180 f23[i, :] = val90 - val270 valsAll[i, :] = 0.25 * fplus[i, :] tauRes[i] = np.mean(tauVals[(psiVals == psiUni[i]) & tauValsValid]) validCounter += 1 # perform linear regression for all phi values to get dstar used = valsAll[:, 0] != 0 if len(valsAll[used, 0]) > 1: if maxPsi is not None: usedReg = (sinpsi2Uni <= bc.sind(maxPsi)**2) & used else: usedReg = used [m, b, CoD, yD, err, mErr, bErr] = dm.linRegWeighted(sinpsi2Uni[usedReg], valsAll[usedReg, 0], 1 / valsAll[usedReg, 1]) dStarVal = m * sinpsi2Star + b # calculate fplus denom = hs2Val * sinpsi2Uni[used] + 2 * s1Val fplus[used, 0] = (0.25 * fplus[used, 0] / dStarVal - 1) / denom fplus[used, 1] = (0.25 * fplus[used, 1] / dStarVal - 1) / denom fplus[used, 2] = (0.25 * fplus[used, 2] / dStarVal - 1) / denom # indicate or correct invalid values if minDistPsiStar is not None: invalidVals = used & (np.abs(sinpsi2Uni - sinpsi2Star) <= minDistPsiStar) # around psiStar fplus[invalidVals, 0] = np.NAN fplus[invalidVals, 1] = np.NAN fplus[invalidVals, 2] = np.NAN # fplus[used, 0] = (0.25 * fplus[used, 0] / dStarVal - 1) / (np.sign(denom) * np.array( # [np.max((np.abs(i), 5e-7)) for i in denom])) # constrained denominator # fplus[used, 1] = (0.25 * fplus[used, 1] / dStarVal - 1) / (np.sign(denom) * np.array( # [np.max((np.abs(i), 5e-7)) for i in denom])) # constrained denominator # fplus[used, 2] = (0.25 * fplus[used, 2] / dStarVal - 1) / (np.sign(denom) * np.array( # [np.max((np.abs(i), 5e-7)) for i in denom])) # constrained denominator # calculate fminus fminus[used, 0] = 0.25 * (fminus[used, 0] / dStarVal) / (hs2Val * sinpsi2Uni[used]) fminus[used, 1] = 0.25 * (fminus[used, 1] / dStarVal) / (hs2Val * sinpsi2Uni[used]) fminus[used, 2] = 0.25 * (fminus[used, 2] / dStarVal) / (hs2Val * sinpsi2Uni[used]) # indicate invalid values if minValPsiNormal is not None: invalidVals = used & (sinpsi2Uni <= minValPsiNormal ) # small psi values fminus[invalidVals, 0] = np.NAN fminus[invalidVals, 1] = np.NAN fminus[invalidVals, 2] = np.NAN # calculate f13 and f23 f13[used, 0] = 0.5 * (f13[used, 0] / dStarVal) / (hs2Val * sin2psiUni[used]) f13[used, 1] = 0.5 * (f13[used, 1] / dStarVal) / (hs2Val * sin2psiUni[used]) f13[used, 2] = 0.5 * (f13[used, 2] / dStarVal) / (hs2Val * sin2psiUni[used]) f23[used, 0] = 0.5 * (f23[used, 0] / dStarVal) / (hs2Val * sin2psiUni[used]) f23[used, 1] = 0.5 * (f23[used, 1] / dStarVal) / (hs2Val * sin2psiUni[used]) f23[used, 2] = 0.5 * (f23[used, 2] / dStarVal) / (hs2Val * sin2psiUni[used]) # indicate invalid values if minValPsiShear is not None: invalidVals = used & (sin2psiUni <= minValPsiShear ) # small and high psi values f13[invalidVals, 0] = np.NAN f13[invalidVals, 1] = np.NAN f13[invalidVals, 2] = np.NAN f23[invalidVals, 0] = np.NAN f23[invalidVals, 1] = np.NAN f23[invalidVals, 2] = np.NAN # determine stresses stresses[used, 0] = fplus[used, 0] + fminus[used, 0] stresses[used, 1] = fplus[used, 0] - fminus[used, 0] stresses[used, 2] = f13[used, 0] stresses[used, 3] = f23[used, 0] # determine error values errVals[used, 0] = np.abs((fplus[used, 2] + fminus[used, 2]) - (fplus[used, 1] + fminus[used, 1])) / 2 errVals[used, 1] = np.abs((fplus[used, 2] - fminus[used, 2]) - (fplus[used, 1] - fminus[used, 1])) / 2 errVals[used, 2] = np.abs(f13[used, 2] - f13[used, 1]) / 2 errVals[used, 3] = np.abs(f23[used, 2] - f23[used, 1]) / 2 # also determine s33 minVal, minPos = bf.min(abs(psiVals[tauValsValid] - psiStar)) tauS33 = np.mean( tauVals[minPos]) # tau equivalent to condition at psiStar # leftVal, leftPos = bf.max(psiVals[psiVals < psiStar]) # rightVal, rightPos = bf.min(psiVals[psiVals > psiStar]) # tauS33 = np.interp(psiStar, [leftVal, rightVal], [tauVals[leftPos], tauVals[rightPos]]) aStarVal = conv.latticeDists2aVals2(dStarVal, hklVal) if a0Val is None or a0Val == 0: s33 = 0 ds33 = 0 else: s33 = calcSigma33(aStarVal, a0Val, s1Val, hs2Val) ds33 = 2 * mErr**0.5 / (hs2Val * dStarVal) resData = { 'tauRes': tauRes, 'stresses': stresses, 'errVals': errVals, 'validCounter': validCounter, 'tauS33': tauS33, 'dStar100': aStarVal, 'dStar100Err': 2 * bErr**0.5, 's33': s33, 'dev_s33': ds33 } return resData
def calcEtaTau(mu, tau, tth, psi): th = tth / 2 return bc.asind(2 * mu * tau * bc.sind(th) * bc.cosd(psi) - bc.sind(th) ** 2 + bc.sind(psi) ** 2) ** 0.5 / \ (bc.cosd(th) * bc.sind(psi))
def s11s22FreeOrientation(s1, hs2): return bc.asind(-2 * s1 / hs2)**0.5
def s33FreeOrientation(s1, hs2, dPsi0, d0, dStar, dPlus): return bc.asind( (dPsi0 - d0) * calcF33(s1, hs2) / hs2 * (dStar - dPlus))**0.5
def latticeDists2angles(latticeDists, wavelength): angles = 2 * bc.asind(wavelength / (2 * latticeDists)) useful = np.nonzero(np.imag(angles) == 0) return angles, useful