def calc_tp_lab(tp_phi_tuple, eta, chi, phi, xyz_eta=[0, 0, 0]): tp_phi = matrix(tp_phi_tuple).T ETA = calcETA(eta * TORAD) CHI = calcCHI(chi * TORAD) PHI = calcPHI(phi * TORAD) xyz_eta = matrix(xyz_eta).T tp_lab = ETA * (xyz_eta + (CHI * PHI * tp_phi)) return list(tp_lab.T.tolist()[0])
def move_lab_origin_into_phi(chi, phi, xyz_eta_tuple): # the inverse of calc_tp_lab with tp_lab=0: CHI = calcCHI(chi * TORAD) PHI = calcPHI(phi * TORAD) xyz_eta = matrix(xyz_eta_tuple).T try: #work in IPython with numpy tp_phi = PHI.I * CHI.I * (-1.0 * xyz_eta) except: # work in GDA using jama_matrix_wrapper - definitely not nice tp_phi = PHI.I * CHI.I * (xyz_eta.__mul__(-1.0)) return list(tp_phi.T.tolist()[0])
def _calc_sample_angles_given_two_sample_and_reference( self, samp_constraints, psi, theta, q_phi, n_phi): """Available combinations: chi, phi, reference mu, eta, reference, chi=90, mu=0, reference """ N_phi = _calc_N(q_phi, n_phi) THETA = z_rotation(-theta) PSI = x_rotation(psi) if 'chi' in samp_constraints and 'phi' in samp_constraints: chi = samp_constraints['chi'] phi = samp_constraints['phi'] CHI = calcCHI(chi) PHI = calcPHI(phi) V = CHI * PHI * N_phi * PSI.T * THETA.T # (56) xi = atan2(-V[2, 0], V[2, 2]) eta = atan2(-V[0, 1], V[1, 1]) mu = atan2(-V[2, 1], sqrt(V[2, 2] ** 2 + V[2, 0] ** 2)) elif 'mu' in samp_constraints and 'eta' in samp_constraints: mu = samp_constraints['mu'] eta = samp_constraints['eta'] V = N_phi * PSI.T * THETA.T # (49) bot = sqrt(sin(eta) ** 2 * cos(mu) ** 2 + sin(mu) ** 2) chi_orig = (asin(-V[2, 1] / bot) - atan2(sin(mu), (sin(eta) * cos(mu)))) # (52) # Choose final chi solution here to obtain compatable xi and mu # TODO: This temporary solution works only for one case used on i07 # Return a list of possible solutions? if is_small(eta) and is_small(mu + pi / 2): for chi in _generate_transformed_values(chi_orig): if pi / 2 <= chi < pi: break else: chi = chi_orig a = sin(chi) * cos(eta) b = sin(chi) * sin(eta) * sin(mu) - cos(chi) * cos(mu) xi = atan2(V[2, 2] * a + V[2, 0] * b, V[2, 0] * a - V[2, 2] * b) # (54) a = sin(chi) * sin(mu) - cos(mu) * cos(chi) * sin(eta) b = cos(mu) * cos(eta) phi = atan2(V[1, 1] * a - V[0, 1] * b, V[0, 1] * a + V[1, 1] * b) # (55) # if is_small(mu+pi/2) and is_small(eta) and False: # phi_general = phi # # solved in extensions_to_yous_paper.wxm # phi = atan2(V[1, 1], V[0, 1]) # logger.info("phi = %.3f or %.3f (std)", # phi*TODEG, phi_general*TODEG ) elif 'chi' in samp_constraints and 'mu' in samp_constraints: # derived in extensions_to_yous_paper.wxm chi = samp_constraints['chi'] mu = samp_constraints['mu'] if not is_small(mu) and not is_small(chi - pi / 2): raise Exception('The fixed chi, mu, psi/alpha/beta modes only ' ' currently work with chi=90 and mu=0') V = N_phi * PSI.T * THETA.T eta = asin(-V[2, 1]) xi = atan2(V[2, 2], V[2, 0]) phi = -atan2(V[0, 1], V[1, 1]) else: raise DiffcalcException( 'No code yet to handle this combination of 2 sample ' 'constraints and one reference!:' + str(samp_constraints)) return xi, psi, mu, eta, chi, phi
def _calc_remaining_sample_angles(self, constraint_name, constraint_value, q_lab, n_lab, q_phi, n_phi): """Return phi, chi, eta and mu, given one of these""" # (section 5.3) # TODO: Sould return a valid solution, rather than just one that can # be mapped to a correct solution by applying +-x and 180+-x mappings? N_lab = _calc_N(q_lab, n_lab) N_phi = _calc_N(q_phi, n_phi) if constraint_name == 'mu': # (35) mu = constraint_value V = calcMU(mu).I * N_lab * N_phi.T phi = atan2(V[2, 1], V[2, 0]) eta = atan2(-V[1, 2], V[0, 2]) chi = atan2(sqrt(V[2, 0] ** 2 + V[2, 1] ** 2), V[2, 2]) if is_small(sin(chi)): # chi ~= 0 or 180 and therefor phi || eta The solutions for phi # and eta here will be valid but will be chosen unpredictably. # Choose eta=0: phi_orig, eta_orig = phi, eta # tan(phi+eta)=v12/v11 from docs/extensions_to_yous_paper.wxm eta = 0 phi = atan2(V[0, 1], V[0, 0]) logger.debug( 'Eta and phi cannot be chosen uniquely with chi so close ' 'to 0 or 180. Ignoring solution phi=%.3f and eta=%.3f, and' ' returning phi=%.3f and eta=%.3f', phi_orig * TODEG, eta_orig * TODEG, phi * TODEG, eta * TODEG) return phi, chi, eta, mu if constraint_name == 'phi': # (37) phi = constraint_value V = N_lab * N_phi.I * calcPHI(phi).T eta = atan2(V[0, 1], sqrt(V[1, 1] ** 2 + V[2, 1] ** 2)) mu = atan2(V[2, 1], V[1, 1]) chi = atan2(V[0, 2], V[0, 0]) if is_small(cos(eta)): raise ValueError( 'Chi and mu cannot be chosen uniquely with eta so close ' 'to +-90.') return phi, chi, eta, mu elif constraint_name in ('eta', 'chi'): V = N_lab * N_phi.T if constraint_name == 'eta': # (39) eta = constraint_value cos_eta = cos(eta) if is_small(cos_eta): #TODO: Not likely to happen in real world!? raise ValueError( 'Chi and mu cannot be chosen uniquely with eta ' 'constrained so close to +-90.') chi = asin(V[0, 2] / cos_eta) else: # constraint_name == 'chi' # (40) chi = constraint_value sin_chi = sin(chi) if is_small(sin_chi): raise ValueError( 'Eta and phi cannot be chosen uniquely with chi ' 'constrained so close to 0. (Please contact developer ' 'if this case is useful for you)') eta = acos(V[0, 2] / sin_chi) top_for_mu = V[2, 2] * sin(eta) * sin(chi) + V[1, 2] * cos(chi) bot_for_mu = -V[2, 2] * cos(chi) + V[1, 2] * sin(eta) * sin(chi) mu = atan2(-top_for_mu, -bot_for_mu) # (41) # (minus signs added from paper to pass (pieces) tests) if is_small(top_for_mu) and is_small(bot_for_mu): # chi == +-90, eta == 0/180 and therefor phi || mu cos(chi) == # 0 and sin(eta) == 0 Experience shows that even though e.g. # the V[2, 2] and V[1, 2] values used to calculate mu may be # basically 0 (1e-34) their ratio in every case tested so far # still remains valid and using them will result in a phi # solution that is continous with neighbouring positions. # # We cannot test phi minus mu here unfortunetely as the final # phi and mu solutions have not yet been chosen (they may be # +-x or 180+-x). Otherwise we could choose a sensible solution # here if the one found was incorrect. # tan(phi+eta)=v12/v11 from extensions_to_yous_paper.wxm phi_minus_mu = -atan2(V[2, 0], V[1, 1]) logger.debug( 'Mu and phi cannot be chosen uniquely with chi so close ' 'to +-90 and eta so close 0 or 180.\n After the final ' 'solution has been chose phi-mu should equal: %.3f', phi_minus_mu * TODEG) top_for_phi = V[0, 1] * cos(eta) * cos(chi) - V[0, 0] * sin(eta) bot_for_phi = V[0, 1] * sin(eta) + V[0, 0] * cos(eta) * cos(chi) phi = atan2(top_for_phi, bot_for_phi) # (42) # if is_small(bot_for_phi) and is_small(top_for_phi): # raise ValueError( # 'phi=%.3f cannot be known with confidence as top and ' # 'bottom are both close to zero. chi=%.3f, eta=%.3f' # % (mu * TODEG, chi * TODEG, eta * TODEG)) return phi, chi, eta, mu raise ValueError('Given angle must be one of phi, chi, eta or mu')
def calcUB(self): CHI = calcCHI(self.chiMissmount * TORAD) PHI = calcPHI(self.phiMissmount * TORAD) self.UB = CHI * PHI * self.cut.B