def test_ConstrainAsSpaceGroup_args(self):
     """Test the arguments processing of constrainAsSpaceGroup function.
     """
     from diffpy.srfit.structure.sgconstraints import constrainAsSpaceGroup
     from diffpy.Structure.SpaceGroups import GetSpaceGroup
     stru = makeLaMnO3_P1()
     parset = DiffpyStructureParSet("LaMnO3", stru)
     sgpars = constrainAsSpaceGroup(parset, "P b n m")
     sg = GetSpaceGroup('P b n m')
     parset2 = DiffpyStructureParSet("LMO", makeLaMnO3_P1())
     sgpars2 = constrainAsSpaceGroup(parset2, sg)
     list(sgpars)
     list(sgpars2)
     self.assertEqual(sgpars.names, sgpars2.names)
     return
 def test_ConstrainAsSpaceGroup_args(self):
     """Test the arguments processing of constrainAsSpaceGroup function.
     """
     from diffpy.srfit.structure.sgconstraints import constrainAsSpaceGroup
     from diffpy.Structure.SpaceGroups import GetSpaceGroup
     stru = makeLaMnO3_P1()
     parset = DiffpyStructureParSet("LaMnO3", stru)
     sgpars = constrainAsSpaceGroup(parset, "P b n m")
     sg = GetSpaceGroup('P b n m')
     parset2 = DiffpyStructureParSet("LMO", makeLaMnO3_P1())
     sgpars2 = constrainAsSpaceGroup(parset2, sg)
     list(sgpars)
     list(sgpars2)
     self.assertEquals(sgpars.names, sgpars2.names)
     return
    def test_DiffPy_constrainAsSpaceGroup(self):
        """Test the constrainAsSpaceGroup function."""
        from diffpy.srfit.structure.diffpyparset import DiffpyStructureParSet
        from diffpy.srfit.structure.sgconstraints import constrainAsSpaceGroup

        stru = makeLaMnO3_P1()
        parset = DiffpyStructureParSet("LaMnO3", stru)

        sgpars = constrainAsSpaceGroup(parset, "P b n m",
                scatterers = parset.getScatterers()[::2],
                constrainadps = True)

        # Make sure that the new parameters were created
        for par in sgpars:
            self.assertNotEqual(None, par)
            self.assertNotEqual(None, par.getValue() )

        # Test the unconstrained atoms
        for scatterer in parset.getScatterers()[1::2]:
            self.assertFalse(scatterer.x.const)
            self.assertFalse(scatterer.y.const)
            self.assertFalse(scatterer.z.const)
            self.assertFalse(scatterer.U11.const)
            self.assertFalse(scatterer.U22.const)
            self.assertFalse(scatterer.U33.const)
            self.assertFalse(scatterer.U12.const)
            self.assertFalse(scatterer.U13.const)
            self.assertFalse(scatterer.U23.const)
            self.assertEqual(0, len(scatterer._constraints))

        proxied = [p.par for p in sgpars]

        def _consttest(par):
            return par.const
        def _constrainedtest(par):
            return par.constrained
        def _proxytest(par):
            return par in proxied
        def _alltests(par):
            return _consttest(par) or _constrainedtest(par) or _proxytest(par)

        for idx, scatterer in enumerate(parset.getScatterers()[::2]):
            # Under this scheme, atom 6 is free to vary
            test = False
            for par in [scatterer.x, scatterer.y, scatterer.z]:
                test |= _alltests(par)
            self.assertTrue(test)

            test = False
            for par in [scatterer.U11, scatterer.U22, scatterer.U33,
                    scatterer.U12, scatterer.U13, scatterer.U23]:
                test |= _alltests(par)

            self.assertTrue(test)

        return
示例#4
0
    def testConstrainAsSpaceGroup(self):
        """Test the constrainAsSpaceGroup function."""
        from diffpy.srfit.structure.sgconstraints import constrainAsSpaceGroup

        stru = makeLaMnO3_P1()
        parset = DiffpyStructureParSet("LaMnO3", stru)

        sgpars = constrainAsSpaceGroup(parset, "P b n m",
                scatterers = parset.getScatterers()[::2],
                constrainadps = True)

        # Make sure that the new parameters were created
        for par in sgpars:
            self.assertNotEquals(None, par)
            self.assertNotEquals(None, par.getValue() )

        # Test the unconstrained atoms
        for scatterer in parset.getScatterers()[1::2]:
            self.assertFalse(scatterer.x.const)
            self.assertFalse(scatterer.y.const)
            self.assertFalse(scatterer.z.const)
            self.assertFalse(scatterer.U11.const)
            self.assertFalse(scatterer.U22.const)
            self.assertFalse(scatterer.U33.const)
            self.assertFalse(scatterer.U12.const)
            self.assertFalse(scatterer.U13.const)
            self.assertFalse(scatterer.U23.const)
            self.assertEquals(0, len(scatterer._constraints))

        proxied = [p.par for p in sgpars]

        def _consttest(par):
            return par.const
        def _constrainedtest(par):
            return par.constrained
        def _proxytest(par):
            return par in proxied
        def _alltests(par):
            return _consttest(par) or _constrainedtest(par) or _proxytest(par)

        for idx, scatterer in enumerate(parset.getScatterers()[::2]):
            # Under this scheme, atom 6 is free to vary
            test = False
            for par in [scatterer.x, scatterer.y, scatterer.z]:
                test |= _alltests(par)
            self.assertTrue(test)

            test = False
            for par in [scatterer.U11, scatterer.U22, scatterer.U33,
                    scatterer.U12, scatterer.U13, scatterer.U23]:
                test |= _alltests(par)

            self.assertTrue(test)

        return
示例#5
0
    def constrainAsSpaceGroup(self, generator, spacegroup, lat=True, xyz=False, adp=False, addphasename=False):
        '''
        constrain phase using space group

        param generator: generator.phase in recipe to constrain
        param spacegroup: space group in number or string "87" or "F m 3 m"
        param lat: bool, constrain lattice parameters
        param xyz: bool, constrain xyz of atoms
        param adp: bool, constrain adp of atoms
        param addphasename: bool, if add phase name to name of variable
        '''

        from diffpy.srfit.structure.sgconstraints import constrainAsSpaceGroup, _constrainAsSpaceGroup
        from diffpy.Structure.spacegroupmod import SpaceGroup

        generator = self.returnGenerator(generator)
        recipe = self.recipe
        phase = generator.phase
        phasename = generator.name

        if isinstance(phase, DiffpyStructureParSet):
            if isinstance(spacegroup, SpaceGroup):
                sgpars = _constrainAsSpaceGroup(phase, spacegroup)
            else:
                sgpars = constrainAsSpaceGroup(phase, spacegroup)
        elif isinstance(phase, ObjCrystCrystalParSet):
            sgpars = phase.sgpars

        if lat:
            for par in sgpars.latpars:
                parname = par.name
                parname = phasename + '_' + \
                    parname if addphasename else parname
                self.addVar(par, parname, par.value, tags=['lat'])
        if xyz:
            for par in sgpars.xyzpars:
                element = getElement(par.par.obj)
                parname = '_'.join([element, par.name])
                parname = phasename + '_' + \
                    parname if addphasename else parname
                self.addVar(
                    par, parname, par.value, tags=['xyz', element + '_xyz'])
        if adp:
            for par in sgpars.adppars:
                element = getElement(par.par.obj)
                parname = '_'.join([element, par.name])
                parname = phasename + '_' + \
                    parname if addphasename else parname
                self.addVar(
                    par, parname, par.value, tags=['adp', element + '_adp'])
示例#6
0
def get_sgpars(parset: Union[ObjCrystCrystalParSet, DiffpyStructureParSet],
               sg: Union[int, str] = None):
    """Constrain the structure by space group and get the independent parameters."""
    if isinstance(parset, ObjCrystCrystalParSet):
        if sg is not None:
            print(
                "ObjCrystCrystalParSet does not accept explicit space group constrain. "
                "Implicit space group is used.")
        sgpars = parset.sgpars
    elif isinstance(parset, DiffpyStructureParSet):
        if sg is None:
            sg = 'P1'
            print("No explicit space group for DiffpyStructureParSet. "
                  "Use 'P1' symmetry.")
        sgpars = constrainAsSpaceGroup(parset, sg, constrainadps=False)
    else:
        raise ValueError("{} does not allow space group constrain.".format(
            type(parset)))
    return sgpars
示例#7
0
def sgconstrain(recipe: MyRecipe,
                gen_name: str,
                con_name: str = None,
                sg: Union[int, str] = None,
                dv: Dict[str, float] = None,
                scatterers: List = None,
                constrainxyz=False) -> None:
    """
    Constrain the generator by space group. The constrained parameters are scale, delta2, lattice parameters, ADPs and
    xyz coordinates. The lattice constants and xyz coordinates are constrained by space group while the ADPs are
    constrained by elements. All paramters will be added as '{par.name}_{gen.name}'

    The default values, ranges and tags for parameters:
        scale: 0, (0, inf), scale_{gen.name}
        delta2: 0, (0, 5), delta2_{gen.name}
        lat: par.value, (par.value +/- 10%), lat_{gen.name}
        adp: 0.006, (0.001, 0.02), adp_{gen.name}
        xyz: par.value, (par.value +/- 0.1), xyz_{gen.name}

    Parameters
    ----------
    recipe
        The recipe to add variables.
    gen_name
        The name of the PDFGenerator to constrain.
    con_name
        The name of the FitContribution where the PDFGenerator is in. If None, get it according to the name of the first
        ConConfig in 'recipe.configs'. Default None.
    sg
        The space group. The expression can be the string or integer. If None, use the space group in GenConfig. Default
        None.
    dv
        The default value of the constrained parameters. If None, the default values will be used. Default None.
    scatterers
        The argument scatters of the constrainAsSpaceGroup. If None, None will be used. Default None.
    constrainxyz
        Whether to constrain xyz coordinates.

    Returns
    -------
    None
    """
    def get_config():
        if con_name is None:
            return recipe.configs[0]
        for config in recipe.configs:
            if config.name == con_name:
                return config
        else:
            raise ValueError(
                f"No ConConfig in recipe '{recipe.name}' match the '{con_name}'."
            )

    def get_sg():
        config = get_config()
        for genconfig in config.phases:
            if genconfig.name == gen_name:
                return genconfig.sg
        else:
            raise ValueError(
                f"No GenConfig in the FitContribution '{config.name}' match the '{gen_name}'."
            )

    # get sg
    if sg is None:
        sg = get_sg()
    # set default of variables
    dv = dv if dv else {}
    con = getattr(recipe, con_name) if con_name else getattr(
        recipe, recipe.configs[0].name)
    gen = getattr(con, gen_name)
    # add scale
    name = f'scale_{gen.name}'
    recipe.addVar(gen.scale, name=name,
                  value=dv.get(name, 0.)).boundRange(0., np.inf)
    # add delta2
    name = f'delta2_{gen.name}'
    recipe.addVar(gen.delta2, name=name, value=dv.get(name,
                                                      0.)).boundRange(0., 5.)

    # constrain by spacegroup
    sgpars = constrainAsSpaceGroup(gen.phase,
                                   sg,
                                   constrainadps=False,
                                   scatterers=scatterers)
    print(
        f"Constrain '{gen.name}' by space group '{sg}' without constraining ADPs."
    )

    # add latpars
    for par in sgpars.latpars:
        name = f'{par.name}_{gen.name}'
        tag = f'lat_{gen.name}'
        recipe.addVar(par, name=name, value=dv.get(name, par.value),
                      tag=tag).boundWindow(par.value * 0.1)

    # constrain adps
    atoms = gen.phase.getScatterers()
    elements = Counter([atom.element for atom in atoms]).keys()
    adp = {
        element: recipe.newVar(f'Uiso_{element}_{gen.name}',
                               value=dv.get(f'Uiso_{element}_{gen.name}',
                                            0.006),
                               tag=f'adp_{gen.name}').boundRange(0.001, 0.02)
        for element in elements
    }
    for atom in atoms:
        recipe.constrain(atom.Uiso, adp[atom.element])

    # add xyzpars
    if constrainxyz:
        for par in sgpars.xyzpars:
            name = f'{par.name}_{gen.name}'
            tag = f'xyz_{gen.name}'
            recipe.addVar(par,
                          name=name,
                          value=dv.get(name, par.value),
                          tag=tag).boundWindow(0.1)

    return
示例#8
0
def sgconstrain(recipe: MyRecipe,
                gen: Union[PDFGenerator, DebyePDFGenerator],
                sg: Union[int, str],
                dv: Dict[str, float] = None,
                scatterers: List = None) -> None:
    """
    Constrain the generator by space group. The constrained parameters are scale, delta2, lattice parameters, ADPs and
    xyz coordinates. The lattice constants and xyz coordinates are constrained by space group while the ADPs are
    constrained by elements. All paramters will be added as '{par.name}_{gen.name}'

    The default values, ranges and tags for parameters:
        scale: 0, (0, inf), scale_{gen.name}
        delta2: 0, (0, inf), delta2_{gen.name}
        lat: par.value, (par.value +/- 20%), lat_{gen.name}
        adp: 0.006, (0, inf), adp_{gen.name}
        xyz: par.value, (par.value +/- 0.2), xyz_{gen.name}

    Parameters
    ----------
    recipe
        The recipe to add variables.
    gen
        The generator to constrain.
    sg
        The space group. The expression can be the string or integer.
    dv
        The default value of the constrained parameters.
    scatterers
        The argument scatters of the constrainAsSpaceGroup.

    Returns
    -------
    None

    """
    dv = dv if dv else {}
    # add scale
    name = f'scale_{gen.name}'
    recipe.addVar(gen.scale, name=name,
                  value=dv.get(name, 0.)).boundRange(0., np.inf)
    # add delta2
    name = f'delta2_{gen.name}'
    recipe.addVar(gen.delta2, name=name,
                  value=dv.get(name, 0.)).boundRange(0., np.inf)

    # constrain lat
    sgpars = constrainAsSpaceGroup(gen.phase,
                                   sg,
                                   constrainadps=False,
                                   scatterers=scatterers)
    for par in sgpars.latpars:
        name = f'{par.name}_{gen.name}'
        tag = f'lat_{gen.name}'
        recipe.addVar(par, name=name, value=dv.get(name, par.value),
                      tag=tag).boundWindow(par.value * 0.2)

    # constrain adp
    atoms = gen.phase.getScatterers()
    elements = Counter([atom.element for atom in atoms]).keys()
    adp = {
        element: recipe.newVar(f'Uiso_{element}_{gen.name}',
                               value=dv.get(f'Uiso_{element}_{gen.name}',
                                            0.006),
                               tag=f'adp_{gen.name}').boundRange(0., np.inf)
        for element in elements
    }
    for atom in atoms:
        recipe.constrain(atom.Uiso, adp[atom.element])

    # constrain xyz
    for par in sgpars.xyzpars:
        name = f'{par.name}_{gen.name}'
        tag = f'xyz_{gen.name}'
        recipe.addVar(par, name=name, value=dv.get(name, par.value),
                      tag=tag).boundWindow(0.2)

    return