Example #1
0
 def test_bcc(self):
     lvs = get_base(self.lc2)
     target = np.eye(3)
     np.testing.assert_almost_equal(lvs, target)
     target = np.eye(3)*2*np.pi
     rlvs = get_reciprocal_base(self.lc2)
     np.testing.assert_almost_equal(rlvs, target)
Example #2
0
 def test_bcc(self):
     lvs = get_base(self.lc2)
     target = np.eye(3)
     np.testing.assert_almost_equal(lvs, target)
     target = np.eye(3) * 2 * np.pi
     rlvs = get_reciprocal_base(self.lc2)
     np.testing.assert_almost_equal(rlvs, target)
Example #3
0
 def test_hcp(self):
     lvs = get_base(self.lc1)
     rlvs = get_reciprocal_base(self.lc1)
     target_v = np.array([[+0.2950800, -0.1475400, +0.0000000],
                          [+0.0000000, +0.2555468, +0.0000000],
                          [+0.0000000, +0.0000000, +0.4685500]])
     target_rv = np.array([[+21.293159, +0.000000, +0.000000],
                           [+12.293611, +24.587222, -0.000000],
                           [-0.000000, -0.000000, +13.409850]])
     # test real lattice
     np.testing.assert_almost_equal(lvs, target_v)
     # test reciprocal lattice
     np.testing.assert_almost_equal(rlvs, target_rv, decimal=6)
Example #4
0
 def test_hcp(self):
     lvs = get_base(self.lc1)
     rlvs = get_reciprocal_base(self.lc1)
     target_v = np.array([
                          [+0.2950800,  -0.1475400,  +0.0000000],
                          [+0.0000000,  +0.2555468,  +0.0000000],
                          [+0.0000000,  +0.0000000,  +0.4685500]])
     target_rv = np.array([
                           [+21.293159,    +0.000000,   +0.000000],
                           [+12.293611,   +24.587222,   -0.000000],
                           [-0.000000,    -0.000000,  +13.409850]])
     # test real lattice
     np.testing.assert_almost_equal(lvs, target_v)
     # test reciprocal lattice
     np.testing.assert_almost_equal(rlvs, target_rv, decimal=6)
Example #5
0
def grad_student(jobConfig):
    """The poor grad student who will perform the DAXM experiment"""
    n_voxels = int(jobConfig["n_voxels"])
    hkls = pd.read_csv(jobConfig["DAXMConfig"]["hkllist"],
                       sep='\t')[['h', 'k', 'l']].as_matrix()

    # extract config for each part
    DAXMConfig = jobConfig["DAXMConfig"]
    labConfig = jobConfig["labConfig"]
    StrainCalcConfig = jobConfig["StrainCalcConfig"]

    # setup virtual DAXM lab
    k0 = np.array(labConfig['k0'])  # incident beam direction
    n_CCD = np.array(labConfig['n_CCD'])  # detector normal
    E_xray = np.array(labConfig["X-ray Energy(KeV)"])  # in KeV
    detector_angularRange = float(
        labConfig["detector angular range"])  # in degrees

    # material: Al
    # NOTE: the shortcut used in the visible peak calculation requires a cubic material
    lc_AL = np.array([0.4050, 0.4050, 0.4050, 90, 90,
                      90])  # [nm,nm,nm,degree,degree,degree]

    # write header for the output file
    if ARGS["--new"]:
        with open(jobConfig["dataFileName"], 'w') as f:
            headerList = [
                "voxelName",
                "angR",
                "magU",
                "n_visible",
                "n_fullq",
                "peakNoiseSigma",
            ]
            headerList += ["{}_F0".format(i + 1) for i in range(9)]  # target F
            headerList += ["{}_FL2".format(i + 1)
                           for i in range(9)]  # least-squares guess
            headerList += ["{}_Fopt".format(i + 1) for i in range(9)]
            headerList += ["opt_successful", "opt_fun", "opt_nfev"]

            f.write("\t".join(headerList) + "\n")

    # convert the parameter range to log space
    _angR_lb, _angR_ub = map(np.log10, DAXMConfig["angR range"])
    _magU_lb, _magU_ub = map(np.log10, DAXMConfig["magU range"])

    for i in range(n_voxels):
        # _DAXMConfig is a per Voxel configuration
        _DAXMConfig = deepcopy(DAXMConfig)

        # generate visible peaks (planes, hkls)
        ## get n_visiblePeaks and n_fullQ: N(n_indexedPeaks) >= n(n_fullQ)
        unacceptable = True
        while unacceptable:
            n_indexedPeaks = int(
                np.random.choice(DAXMConfig["n_indexedPeaks"], 1))
            n_fullQ = int(np.random.choice(DAXMConfig["n_fullQ"], 1))
            if n_fullQ <= n_indexedPeaks:
                unacceptable = False
        ## get list of index planes based on a random crystal orientation
        unacceptable = True
        while unacceptable:
            xtal_orientation = Quaternion.fromRandom()
            visible_hkls = calc_visible_peaks(
                xtal_orientation,
                k0,
                n_CCD,
                E_xray,
                lc_AL,
                hkls,
                detector_angularRange=detector_angularRange,
            )
            if len(visible_hkls) > n_indexedPeaks:
                indexed_plane = random_select_npeaks(visible_hkls,
                                                     n_indexedPeaks)
                # prevent degenerated matrix due to parallel hkls
                if np.linalg.matrix_rank(indexed_plane) >= 3:
                    unacceptable = False
        ## get scattering vectors
        # NOTE:
        # Since the crystal orientation is only useful for selecting diffractable planes,
        # the rest of the calculation (q and q0) can be directly done within xtal lattice
        # frame (XTL) regardless of the actual crystal orientation (makes the calcualtion
        # a lot simpler).
        ### frist, randomly generate a deformation gradient in xtal frame
        _DAXMConfig["angR"] = np.power(
            10,
            np.random.random() * (_angR_ub - _angR_lb) + _angR_lb)
        _DAXMConfig["magU"] = np.power(
            10,
            np.random.random() * (_magU_ub - _magU_lb) + _magU_lb)
        defgrad = make_random_defgrad(_DAXMConfig['angR'], _DAXMConfig['magU'])
        ### use the randomly generated defgrad to strain the scattering vectors
        recip_base = get_reciprocal_base(lc_AL)
        T, Bstar = defgrad, recip_base
        Tstar = np.transpose(np.linalg.inv(T))
        Bstar_strained = np.dot(Tstar, Bstar)
        qs = np.zeros((3, n_indexedPeaks))
        # random select n_fullQ to be full scattering vectors
        idx_fullq = np.random.choice(n_indexedPeaks, n_fullQ, replace=False)
        for arrayidx, milleridx in enumerate(indexed_plane):
            q_strained = np.dot(Bstar_strained, milleridx)
            qs[:,
               arrayidx] = q_strained if arrayidx in idx_fullq else normalize(
                   q_strained)

        # setup DAXMConfig for each run
        # NOTE:
        # Noise analysis can be done when we have more access to the facility
        _DAXMConfig["whiteNoiseLevel"] = np.random.choice(
            np.array(DAXMConfig["peakPositionUncertainty/deg"]))

        qs_correct = np.copy(qs)
        for qsIdx in range(qs.shape[1]):
            qs[:, qsIdx] = perturb_vector(
                qs[:, qsIdx],
                np.random.normal(scale=_DAXMConfig["whiteNoiseLevel"]),
            )

        # construct the voxel
        thisVoxel = DAXMvoxel(
            name="voxel_{}".format(i),
            ref_frame='XTL',
            coords=np.zeros(3),
            pattern_image="voxel_{}".format(i),
            scatter_vec=qs,
            plane=indexed_plane.T,
            recip_base=recip_base,
            peak=np.random.random((2, n_indexedPeaks)),
            depth=0,
            lattice_constant=lc_AL,
        )

        # save the voxel to H5 archive
        thisVoxel.write(h5file=jobConfig["voxelArchive"])

        # calculate the deformation gradient
        # NOTE:
        # notice the much cleaner and simpler interface in terms of strain quantification
        defgrad_L2 = thisVoxel.deformation_gradientL2()
        defgrad_opt = thisVoxel.deformation_gradient_opt(eps=1e0)

        # export data to file for analysis
        data = [
            thisVoxel.name,
            _DAXMConfig["angR"],
            _DAXMConfig["magU"],
            n_indexedPeaks,
            n_fullQ,
            _DAXMConfig["whiteNoiseLevel"],
        ]
        data += list(defgrad.flatten())  # in XTAL frame!!!
        data += list(defgrad_L2.flatten())  # in XTAL frame!!!
        data += list(defgrad_opt.flatten())  # in XTAL frame!!!

        data += [
            int(thisVoxel.opt_rst.success),  # is optimization successful
            thisVoxel.opt_rst.fun,  # fitness function final val
            thisVoxel.opt_rst.nfev,  # number of iteration used
        ]

        with open(jobConfig["dataFileName"], 'a') as f:
            f.write("\t".join(map(str, data)) + "\n")

        # interactive monitoring
        if jobConfig["monitor"] and i % 1000 == 0:
            sys.stderr.write("|")
        elif jobConfig["monitor"] and i % 100 == 0:
            sys.stderr.write("*")