Пример #1
0
def main(GoniometerAxes, inputFile, mode, v1, v2, datum, beam, spgn=None):

    global XOfileType

    # The goniostat consists of axes e1 carrying e2 carrying e3
    # (eg Omega, Kappa, Phi). GoniometerAxes = e1, e2, e3
    # gnsdtm calculate D from datum and GoniometerAxes.
    # D == Goniometer.tensor == datum matrix
    Goniometer = ThreeAxisRotation2((0.,0.,0.), GoniometerAxes,
                                                inversAxesOrder=0)

    # DATUM definition in degree.
    setDatum = tuple(datum) # in degree
    Goniometer.setAngles(map(degree2radian,setDatum))

    # MODE = 'CUSP' or 'MAIN'
    VL = gnsmod(mode, beam, Goniometer)

    # V1/V2
    V1 = CrystalVector(v1, printPrecision=4)
    V2 = CrystalVector(v2, printPrecision=4)
    if "%s" % V1  != "%s" % V2:
        desiredSetting = V1, V2
    else:
        print "ERROR: The two crystal aligned vector can't be identical!"
        sys.exit(2)

    if type(inputf[0]) == str:
        gotcha = False
        for parser in (DenzoParser, XDSParser, MosflmParser):
            try:
                XOparser = parser(inputf[0])
                gotcha = True
            except :
                pass
            if gotcha:
                break
        if not gotcha:
            raise Exception, "Can't parse input orientation matrix file: %s" %\
                inputf[0]
    elif hasattr(inputf, "fileType"):
        XOparser = inputf


    if VERBOSE:
        print "\n %s used to read input file: %s" % (XOparser.info, inputf[0])
    XOfileType = XOparser.fileType

    if not spgn:
        spgn = XOparser.spaceGroupNumber
        spg = XOparser.spaceGroupName
    else:
        spg = spg_num2symb[spgn]

    pointGroup = SPGlib[spgn][-1]
    if VERBOSE:
        print  "\n Space group symbol: %s,  Number: %d,  Point Group: %s" % \
                                            (spg.upper(),spgn, pointGroup)
        print ("\n       Real cell: "+3*"%10.3f"+3*"%8.2f") % \
                                                       tuple(XOparser.cell)
        print (" Reciprocal cell: "+3*"%10.6f"+3*"%8.2f") % \
                                                       tuple(XOparser.cell_r)

    Bmos = BusingLevy(XOparser.cell_r)

    # Umos =     setting matrix at current datum
    # Getting Mosflm XO
    if XOparser.fileType == "Mosflm":
        UBmos =  XOparser.U * Bmos # whitout wavelength scaling
        Umos = XOparser.U
        # XOparser.UB = UBmos * wavelength

    # Converting Denzo XO to Mosflm convention
    elif XOparser.fileType == "Denzo":
        UBmos = Qdnz2mos * XOparser.UB
        Umos = (UBmos) * Bmos.inverse()

    # Converting XDS XO to Mosflm convention
    elif XOparser.fileType == "XDS":
        UBmos = XOparser.UBxds_to_mos()/ XOparser.dict["wavelength"]
        Umos = (UBmos) * Bmos.inverse()

    is_orthogonal(Umos)
    if VERBOSE:
        printmat( Umos,'\n   U',  "%12.6f")
        printmat( Bmos,'\n   B',  "%12.6f")
        printmat( UBmos,'\n  UB', "%12.6f")

    Bm1t = Bmos.inverse().transpose()
    orthogMatrices = {'rec':Bmos, 'dir':Bm1t}

    # There are two ways to write the crystal orientation in mosflm:
    # using the U matrix or the phi1, phi2, phi3 misseting angles (in degree).
    # == gnspxg: decompose Umos into 3 "missetting" angles phi123
    phi123r = ThreeAxisRotation2(Umos.mlist, inversAxesOrder=1).getAngles()
    # keep only the first solution and convert it in degre.
    phi123 = map_r2d(phi123r[0])

    # This new Umos def - equivalent to the previous - is needed to
    # stay exactly compatible with gonset.
    # Umos2 = ThreeAxisRotation(phi123r[0], inversAxesOrder=1).tensor
    # printmat(Umos2, 'Umos2')
    # print "\nDiff Umos/Umos2 =======>> %8.1e" %  diffMAT(Umos2,Umos)

    # U0mos =    zero-angle setting matrix
    #           [U] = [D] [U0] so [U0] = [D]**-1 [U]
    U0mos = Goniometer.tensor.inverse() * Umos # == gnsszr
    if VERBOSE:
        print ("\n phixyz: "+3*"%8.2f"+"\n") % tuple(phi123)
        now(XOparser.cell, Umos, U0mos, phi123, orthogMatrices, Goniometer,
                             beam, setDatum, desiredSetting)

    PG_permutions = [[X,Y,Z]]
    if _do_PG_permutations:
        PG_permutions.extend(PGequiv[pointGroup])

    datumSolutions = solve(desiredSetting, VL, orthogMatrices,
                              U0mos, Goniometer, PG_permutions)

    # Ajouter la verification directement au moment du calcul
    # Permutation of the UB matrix... (U matrix) only?
    # How the permutation is handled for hexagonal.
    #
    n = 0
    #if 0:
    if _debug:
        for newdatum in datumSolutions:
            n += 1
            Goniometer.setAngles(map(degree2radian, newdatum))

            newUmos = Goniometer.tensor * U0mos
            printmat(newUmos, "\nNew Umos matrix. Solution numb. %3d" % n,\
                       "%12.6f")
            phi123 = ThreeAxisRotation2(newUmos.mlist,
                                        inversAxesOrder=1).getAngles()
            phi123 = map_r2d(phi123[0])

            print ("\n phixyz: "+3*"%8.2f"+"\n") % tuple(phi123)

    return datumSolutions
Пример #2
0
def main(GoniometerAxes, inputFile, mode, v1, v2, datum, beam, spgn=None):

    global XOfileType

    # The goniostat consists of axes e1 carrying e2 carrying e3
    # (eg Omega, Kappa, Phi). GoniometerAxes = e1, e2, e3
    # gnsdtm calculate D from datum and GoniometerAxes.
    # D == Goniometer.tensor == datum matrix
    Goniometer = ThreeAxisRotation2((0., 0., 0.),
                                    GoniometerAxes,
                                    inversAxesOrder=0)

    # DATUM definition in degree.
    setDatum = tuple(datum)  # in degree
    Goniometer.setAngles(map(degree2radian, setDatum))

    # MODE = 'CUSP' or 'MAIN'
    VL = gnsmod(mode, beam, Goniometer)

    # V1/V2
    V1 = CrystalVector(v1, printPrecision=4)
    V2 = CrystalVector(v2, printPrecision=4)
    if "%s" % V1 != "%s" % V2:
        desiredSetting = V1, V2
    else:
        print "ERROR: The two crystal aligned vector can't be identical!"
        sys.exit(2)

    if type(inputf[0]) == str:
        gotcha = False
        for parser in (DenzoParser, XDSParser, MosflmParser):
            try:
                XOparser = parser(inputf[0])
                gotcha = True
            except:
                pass
            if gotcha:
                break
        if not gotcha:
            raise Exception, "Can't parse input orientation matrix file: %s" %\
                inputf[0]
    elif hasattr(inputf, "fileType"):
        XOparser = inputf

    if VERBOSE:
        print "\n %s used to read input file: %s" % (XOparser.info, inputf[0])
    XOfileType = XOparser.fileType

    if not spgn:
        spgn = XOparser.spaceGroupNumber
        spg = XOparser.spaceGroupName
    else:
        spg = spg_num2symb[spgn]

    pointGroup = SPGlib[spgn][-1]
    if VERBOSE:
        print  "\n Space group symbol: %s,  Number: %d,  Point Group: %s" % \
                                            (spg.upper(),spgn, pointGroup)
        print ("\n       Real cell: "+3*"%10.3f"+3*"%8.2f") % \
                                                       tuple(XOparser.cell)
        print (" Reciprocal cell: "+3*"%10.6f"+3*"%8.2f") % \
                                                       tuple(XOparser.cell_r)

    Bmos = BusingLevy(XOparser.cell_r)

    # Umos =     setting matrix at current datum
    # Getting Mosflm XO
    if XOparser.fileType == "Mosflm":
        UBmos = XOparser.U * Bmos  # whitout wavelength scaling
        Umos = XOparser.U
        # XOparser.UB = UBmos * wavelength

    # Converting Denzo XO to Mosflm convention
    elif XOparser.fileType == "Denzo":
        UBmos = Qdnz2mos * XOparser.UB
        Umos = (UBmos) * Bmos.inverse()

    # Converting XDS XO to Mosflm convention
    elif XOparser.fileType == "XDS":
        UBmos = XOparser.UBxds_to_mos() / XOparser.dict["wavelength"]
        Umos = (UBmos) * Bmos.inverse()

    is_orthogonal(Umos)
    if VERBOSE:
        printmat(Umos, '\n   U', "%12.6f")
        printmat(Bmos, '\n   B', "%12.6f")
        printmat(UBmos, '\n  UB', "%12.6f")

    Bm1t = Bmos.inverse().transpose()
    orthogMatrices = {'rec': Bmos, 'dir': Bm1t}

    # There are two ways to write the crystal orientation in mosflm:
    # using the U matrix or the phi1, phi2, phi3 misseting angles (in degree).
    # == gnspxg: decompose Umos into 3 "missetting" angles phi123
    phi123r = ThreeAxisRotation2(Umos.mlist, inversAxesOrder=1).getAngles()
    # keep only the first solution and convert it in degre.
    phi123 = map_r2d(phi123r[0])

    # This new Umos def - equivalent to the previous - is needed to
    # stay exactly compatible with gonset.
    # Umos2 = ThreeAxisRotation(phi123r[0], inversAxesOrder=1).tensor
    # printmat(Umos2, 'Umos2')
    # print "\nDiff Umos/Umos2 =======>> %8.1e" %  diffMAT(Umos2,Umos)

    # U0mos =    zero-angle setting matrix
    #           [U] = [D] [U0] so [U0] = [D]**-1 [U]
    U0mos = Goniometer.tensor.inverse() * Umos  # == gnsszr
    if VERBOSE:
        print("\n phixyz: " + 3 * "%8.2f" + "\n") % tuple(phi123)
        now(XOparser.cell, Umos, U0mos, phi123, orthogMatrices, Goniometer,
            beam, setDatum, desiredSetting)

    PG_permutions = [[X, Y, Z]]
    if _do_PG_permutations:
        PG_permutions.extend(PGequiv[pointGroup])

    datumSolutions = solve(desiredSetting, VL, orthogMatrices, U0mos,
                           Goniometer, PG_permutions)

    # Ajouter la verification directement au moment du calcul
    # Permutation of the UB matrix... (U matrix) only?
    # How the permutation is handled for hexagonal.
    #
    n = 0
    #if 0:
    if _debug:
        for newdatum in datumSolutions:
            n += 1
            Goniometer.setAngles(map(degree2radian, newdatum))

            newUmos = Goniometer.tensor * U0mos
            printmat(newUmos, "\nNew Umos matrix. Solution numb. %3d" % n,\
                       "%12.6f")
            phi123 = ThreeAxisRotation2(newUmos.mlist,
                                        inversAxesOrder=1).getAngles()
            phi123 = map_r2d(phi123[0])

            print("\n phixyz: " + 3 * "%8.2f" + "\n") % tuple(phi123)

    return datumSolutions
Пример #3
0
def solve(desiredSetting, VL, orthogMatrices, U0, Goniometer,
                              PG_permutions=[[X,Y,Z]]):
    """ Solve for datum position
    Uses:
        VL              Laboratory vectors to match
        orthogMatrices  Dict containing {'rec':Bm1t, 'dir':B}
        desiredSetting  List of the two vectors defining the desired setting
        U0              Zero-angle setting matrix
        PG_permutions   Point group permutations

    Return:
        datumSolutions (list of datum solutions in degrees)

    Local variables
        U0m1    [U0]**-1
        C       base vectors in crystal frame
        Cm1     [C]**-1
        L       base vectors in laboratory frame
        SL      L matrix with permuted signs
        CU      [C]**-1 [U0]**-1
    """

    # Orthogonalize crystal vectors h -> yv
    # YV crystal frame vectors defining desired setting (orthogonalized)

    YV = []
    for vi in 0, 1:
        # if reciproc: B*vi.vector elif direct: B1mt*vi.vector
        B = orthogMatrices[desiredSetting[vi].space]
        YV.append(B*desiredSetting[vi])

    #  referential_permutations sign permutations for four permutations of
    #        parallel/antiparallel (rotation axis & beam)
    #    y1 // e1, y2 // beamVector;  y1 anti// e1, y2 // beamVector
    #    y1 // e1, y2 anti// beamVector;  y1 anti// e1, y2 anti// beamVector

    referential_permutations = [ ex,  ey,  ez], \
                               [-ex, -ey,  ez], \
                               [ ex, -ey, -ez], \
                               [-ex,  ey, -ez]

    # Construct orthogonal frame in crystal space defined by vectors
    # y1 = yv(,1) and y2 = yv(,2). The base vectors form the COLUMNS
    # of matrix C
    #  - 1st vector along YV1
    #  - 3rd vector perpendicular to YV1 & YV2
    #  - 2nd vector completes the RH set

    C1 = YV[0].normalize()
    C3 = YV[0].cross(YV[1]).normalize()
    C2 = C3.cross(C1).normalize()
    C = mat3(C1, C2, C3)

    # Similarly, construct laboratory frame matrix defined by VL1, VL2
    #  1st vector along VL1
    #  3rd vector perpendicular to VL1 & VL2
    #  2nd vector completes the RH set

    L1 = VL[0].normalize()
    L3 = VL[0].cross(VL[1]).normalize()
    L2 = L3.cross(L1).normalize()
    L = mat3(L1, L2, L3)

    # The matrix which superimposes the two frames is L C**-1. This
    # is then the orientation matrix DU, including the required datum
    # position D.  The datum matrix is then  D = L C**-1 U**-1
    # We need to consider four possible alignments & values of D,
    # corresponding to y1 parallel & antiparallel to vl1, and y2
    # parallel & antiparallel to vl2. To get these, we change
    # the signs of l1 & l2, or l2 & l3, or both, as set out in array LS.

    datumSolutions = []
    independentSolution = []

    # Loop four solutions for D, each with possibly two sets of goniostat
    # angles

    Cm1 = C.inverse()
    B = orthogMatrices['rec']
    UB0 = U0 * B

    # Loop for introducing Point Group permutations:
    for PG_operator in PG_permutions:
        # We use the operator in reciprocal space so it need a transposition.
        PG_operator = mat3T(PG_operator)
        # printmat(B.dot(PG_operator),'B.dot(PG_operator)')

        # The PG operator is applied on the UB0 matrix
        U0perm = UB0 * PG_operator * B.inverse()
        if _debug:
            print
            printmat(PG_operator, 'PG_operator', "%12.6f")
            printmat(U0, 'U0', "%12.6f")
            printmat(U0perm, 'U0perm', "%12.6f")

        if not is_orthogonal(U0perm):
            print "!!!!!!!!!!!!!!! ERROR: Improper U0perm matrice!!"

        #  CU = C**-1 . U**-1
        CU = Cm1 * U0perm.inverse()
        for referential_permut in referential_permutations:

            SL = L * mat3T(referential_permut)
            _DM = SL * CU

            # angles: there are zero or two possible sets of goniostat angles
            # which correspond to D, although one or both may be inaccessible

            try:
                _2s = ThreeAxisRotation2(_DM.mlist,
                                        Goniometer.rotationAxes,
                                        inversAxesOrder=0).getAngles()
                twoSolutions = (_2s[0][2],_2s[0][1],_2s[0][0]), \
                               (_2s[1][2],_2s[1][1],_2s[1][0])

                for oneSolution in twoSolutions:

                    solutionKey = "%6.2f%6.2f%6.2f" % tuple(oneSolution)
                    if solutionKey not in independentSolution:
                        independentSolution.append(solutionKey)
                        datumSolutions.append(map(radian2degree, oneSolution))
                        #print ">>>>>>>>>",solutionKey,"number ",
                        #print len(independentSolution)
                    else:
                        if _debug:
                            print ">>>>>>>>> Redundant solution"
            except ValueError:
                pass

    return datumSolutions
Пример #4
0
def solve(desiredSetting,
          VL,
          orthogMatrices,
          U0,
          Goniometer,
          PG_permutions=[[X, Y, Z]]):
    """ Solve for datum position
    Uses:
        VL              Laboratory vectors to match
        orthogMatrices  Dict containing {'rec':Bm1t, 'dir':B}
        desiredSetting  List of the two vectors defining the desired setting
        U0              Zero-angle setting matrix
        PG_permutions   Point group permutations

    Return:
        datumSolutions (list of datum solutions in degrees)

    Local variables
        U0m1    [U0]**-1
        C       base vectors in crystal frame
        Cm1     [C]**-1
        L       base vectors in laboratory frame
        SL      L matrix with permuted signs
        CU      [C]**-1 [U0]**-1
    """

    # Orthogonalize crystal vectors h -> yv
    # YV crystal frame vectors defining desired setting (orthogonalized)

    YV = []
    for vi in 0, 1:
        # if reciproc: B*vi.vector elif direct: B1mt*vi.vector
        B = orthogMatrices[desiredSetting[vi].space]
        YV.append(B * desiredSetting[vi])

    #  referential_permutations sign permutations for four permutations of
    #        parallel/antiparallel (rotation axis & beam)
    #    y1 // e1, y2 // beamVector;  y1 anti// e1, y2 // beamVector
    #    y1 // e1, y2 anti// beamVector;  y1 anti// e1, y2 anti// beamVector

    referential_permutations = [ ex,  ey,  ez], \
                               [-ex, -ey,  ez], \
                               [ ex, -ey, -ez], \
                               [-ex,  ey, -ez]

    # Construct orthogonal frame in crystal space defined by vectors
    # y1 = yv(,1) and y2 = yv(,2). The base vectors form the COLUMNS
    # of matrix C
    #  - 1st vector along YV1
    #  - 3rd vector perpendicular to YV1 & YV2
    #  - 2nd vector completes the RH set

    C1 = YV[0].normalize()
    C3 = YV[0].cross(YV[1]).normalize()
    C2 = C3.cross(C1).normalize()
    C = mat3(C1, C2, C3)

    # Similarly, construct laboratory frame matrix defined by VL1, VL2
    #  1st vector along VL1
    #  3rd vector perpendicular to VL1 & VL2
    #  2nd vector completes the RH set

    L1 = VL[0].normalize()
    L3 = VL[0].cross(VL[1]).normalize()
    L2 = L3.cross(L1).normalize()
    L = mat3(L1, L2, L3)

    # The matrix which superimposes the two frames is L C**-1. This
    # is then the orientation matrix DU, including the required datum
    # position D.  The datum matrix is then  D = L C**-1 U**-1
    # We need to consider four possible alignments & values of D,
    # corresponding to y1 parallel & antiparallel to vl1, and y2
    # parallel & antiparallel to vl2. To get these, we change
    # the signs of l1 & l2, or l2 & l3, or both, as set out in array LS.

    datumSolutions = []
    independentSolution = []

    # Loop four solutions for D, each with possibly two sets of goniostat
    # angles

    Cm1 = C.inverse()
    B = orthogMatrices['rec']
    UB0 = U0 * B

    # Loop for introducing Point Group permutations:
    for PG_operator in PG_permutions:
        # We use the operator in reciprocal space so it need a transposition.
        PG_operator = mat3T(PG_operator)
        # printmat(B.dot(PG_operator),'B.dot(PG_operator)')

        # The PG operator is applied on the UB0 matrix
        U0perm = UB0 * PG_operator * B.inverse()
        if _debug:
            print
            printmat(PG_operator, 'PG_operator', "%12.6f")
            printmat(U0, 'U0', "%12.6f")
            printmat(U0perm, 'U0perm', "%12.6f")

        if not is_orthogonal(U0perm):
            print "!!!!!!!!!!!!!!! ERROR: Improper U0perm matrice!!"

        #  CU = C**-1 . U**-1
        CU = Cm1 * U0perm.inverse()
        for referential_permut in referential_permutations:

            SL = L * mat3T(referential_permut)
            _DM = SL * CU

            # angles: there are zero or two possible sets of goniostat angles
            # which correspond to D, although one or both may be inaccessible

            try:
                _2s = ThreeAxisRotation2(_DM.mlist,
                                         Goniometer.rotationAxes,
                                         inversAxesOrder=0).getAngles()
                twoSolutions = (_2s[0][2],_2s[0][1],_2s[0][0]), \
                               (_2s[1][2],_2s[1][1],_2s[1][0])

                for oneSolution in twoSolutions:

                    solutionKey = "%6.2f%6.2f%6.2f" % tuple(oneSolution)
                    if solutionKey not in independentSolution:
                        independentSolution.append(solutionKey)
                        datumSolutions.append(map(radian2degree, oneSolution))
                        #print ">>>>>>>>>",solutionKey,"number ",
                        #print len(independentSolution)
                    else:
                        if _debug:
                            print ">>>>>>>>> Redundant solution"
            except ValueError:
                pass

    return datumSolutions