Skip to content

Bug: size broadening parameterization not set properly with set_HAP_refinements() #286

@AdamCorrao

Description

@AdamCorrao

Comparing the source code of setSampleProfile() and set_HAP_refinements() I found discrepancies between the list indices used for values and refine flags for size, mustrain, and their LG_mix parameters.

After some manual flipping of size parameter values and refine flags in the GUI followed by checking the size list returned (e.g., by calling proj.data['Phases'][phase_name]['Histograms'][proj.histograms()[0].name]['Size']) I believe this is the correct list structure:

['isotropic', # [0]: str for broadening type. 'isotropic', 'uniaxial', or 'ellipsoidal'
[1.0, 1.0, 1.0], # [1][0]: iso size or equatorial size, [1][1]: axial size (if uniaxial used, else ignored), [1][2]: LG_mix (eta parameter, 1 = Lorentzian, 0 = Gaussian)
[False, False, False], # boolean refinement flags. [2][0]: isotropic or uniaxial equatorial refine, [2][1]: uniaxial axial refine, [2][2]: LG_mix refine
[0, 0, 1], # hkl direction for uniaxial broadening. [3][0]: h, [3][1]: k, [3][2]: l
[1.0, 1.0, 1.0, 0.0, 0.0, 0.0], # ellipsoidal sizes. S11, S22, S33, S12, S13, S23 for [4][0:6]
[False, False, False, False, False, False]]  # ellipsoidal size refine flags. S11, S22, S33, S12, S13, S23 for [5][0:6]

If the above is correct, then setSampleProfile() uses the correct indices, and set_HAP_refinements() should be updated as provided in the code block below. It looks like the mustrain parameterization has a similar error which I've corrected. I am happy to open a pull request with these changes, but wanted to check if these changes will impact other methods in G2sc first.

For convenience in finding the changes within the function, here are the lines changed:

#mustrain[2][1] = types 
#mustrain[2][2] = types
mustrain[2][0] = types
mustrain[2][1] = types

#size[2][1] = bool(refine)
#size[2][2] = bool(refine)
size[2][0] = bool(refine)
size[2][1] = bool(refine)

Updated function:

def set_HAP_refinements(self, refs, histograms='all'):
        """Sets the given HAP refinement parameters between the current phase and
        the specified histograms.

        :param dict refs: A dictionary of the parameters to be set. See
                          the :ref:`HAP_parameters_table` table for a description of this
                          dictionary.
        :param histograms: Either 'all' (default) or a list of the histograms by index, name
            or object. The index number is relative to all histograms in the tree, not to
            those in the phase.
            Histograms not associated with the current phase will be ignored.
            whose HAP parameters will be set with this phase. Histogram and phase
            must already be associated.
        :returns: None
        """
        if not self.data.get('Histograms',[]):
            G2fil.G2Print("Error likely: Phase {} has no linked histograms".format(self.name))
            return

        if histograms == 'all':
            histograms = self.data['Histograms'].keys()
        else:
            histograms = [self._decodeHist(h) for h in histograms
                          if self._decodeHist(h) in self.data['Histograms']]
        if not histograms:
            G2fil.G2Print("Warning: Skipping HAP set for phase {}, no selected histograms".format(self.name))
            return
        # remove non-PWDR (HKLF) histograms
        histograms = [i for i in histograms if self.proj.histType(i) == 'PWDR']
        if not histograms: return
        for key, val in refs.items():
            if key == 'Babinet':
                try:
                    sets = list(val)
                except ValueError:
                    sets = ['BabA', 'BabU']
                for param in sets:
                    if param not in ['BabA', 'BabU']:
                        raise ValueError("Not sure what to do with" + param)
                    for h in histograms:
                        self.data['Histograms'][h]['Babinet'][param][1] = True
            elif key == 'Extinction':
                for h in histograms:
                    self.data['Histograms'][h]['Extinction'][1] = bool(val)
            elif key == 'HStrain':
                if isinstance(val,list) or isinstance(val,tuple):
                    for h in histograms:
                        if len(self.data['Histograms'][h]['HStrain'][1]) != len(val):
                            raise Exception('Need {} HStrain terms for phase {} hist {}'
                                .format(len(self.data['Histograms'][h]['HStrain'][1]),self.name,h))
                        for i,v in enumerate(val):
                            self.data['Histograms'][h]['HStrain'][1][i] = bool(v)
                else:
                    for h in histograms:
                        self.data['Histograms'][h]['HStrain'][1] = [bool(val) for p in self.data['Histograms'][h]['HStrain'][1]]
            elif key == 'Mustrain':
                for h in histograms:
                    mustrain = self.data['Histograms'][h]['Mustrain']
                    newType = mustrain[0]
                    direction = None
                    if isinstance(val, (str,bytes)):
                        if val in ['isotropic', 'uniaxial', 'generalized']:
                            newType = val
                        else:
                            raise ValueError("Not a Mustrain type: " + val)
                    elif isinstance(val, dict):
                        newType = val.get('type', newType)
                        direction = val.get('direction', None)

                    if newType:
                        mustrain[0] = newType
                        if newType == 'isotropic':
                            mustrain[2][0] = True == val.get('refine',False)
                            mustrain[5] = [False for p in mustrain[4]]
                        elif newType == 'uniaxial':
                            if 'refine' in val:
                                mustrain[2][0] = False
                                types = val['refine']
                                if isinstance(types, (str,bytes)):
                                    types = [types]
                                elif isinstance(types, bool):
                                   #mustrain[2][1] = types 
                                   #mustrain[2][2] = types
                                    mustrain[2][0] = types
                                    mustrain[2][1] = types
                                    types = []
                                else:
                                    raise ValueError("Not sure what to do with: "
                                                     + str(types))
                            else:
                                types = []

                            for unitype in types:
                                if unitype == 'equatorial':
                                    mustrain[2][0] = True
                                elif unitype == 'axial':
                                    mustrain[2][1] = True
                                else:
                                    msg = 'Invalid uniaxial mustrain type'
                                    raise ValueError(msg + ': ' + unitype)
                        else:  # newtype == 'generalized'
                            mustrain[2] = [False for p in mustrain[1]]
                            if 'refine' in val:
                                mustrain[5] = [True == val['refine']]*len(mustrain[5])

                    if direction:
                        if len(direction) != 3:
                            raise ValueError("Expected hkl, found", direction)
                        direction = [int(n) for n in direction]
                        mustrain[3] = direction
            elif key == 'Size':
                newSize = None
                if 'value' in val:
                    newSize = float(val['value'])
                for h in histograms:
                    size = self.data['Histograms'][h]['Size']
                    newType = size[0]
                    direction = None
                    if isinstance(val, (str,bytes)):
                        if val in ['isotropic', 'uniaxial', 'ellipsoidal']:
                            newType = val
                        else:
                            raise ValueError("Not a valid Size type: " + val)
                    elif isinstance(val, dict):
                        newType = val.get('type', size[0])
                        direction = val.get('direction', None)

                    if newType:
                        size[0] = newType
                        refine = bool(val.get('refine'))
                        if newType == 'isotropic' and refine is not None:
                            size[2][0] = bool(refine)
                            if newSize: size[1][0] = newSize
                        elif newType == 'uniaxial' and refine is not None:
                            #size[2][1] = bool(refine)
                            #size[2][2] = bool(refine)
                            size[2][0] = bool(refine)
                            size[2][1] = bool(refine)
                            if newSize: size[1][0] = size[1][1] =newSize
                        elif newType == 'ellipsoidal' and refine is not None:
                            size[5] = [bool(refine) for p in size[5]]
                            if newSize: size[4] = [newSize for p in size[4]]

                    if direction:
                        if len(direction) != 3:
                            raise ValueError("Expected hkl, found", direction)
                        direction = [int(n) for n in direction]
                        size[3] = direction
            elif key == 'Pref.Ori.':
                for h in histograms:
                    self.data['Histograms'][h]['Pref.Ori.'][2] = bool(val)
            elif key == 'Show':
                for h in histograms:
                    self.data['Histograms'][h]['Show'] = bool(val)
            elif key == 'Use':
                for h in histograms:
                    self.data['Histograms'][h]['Use'] = bool(val)
            elif key == 'Scale' or key == 'PhaseFraction':
                for h in histograms:
                    self.data['Histograms'][h]['Scale'][1] = bool(val)
            else:
                G2fil.G2Print('Warning: Unknown HAP key: '+key)

Metadata

Metadata

Assignees

Labels

In progressthis is being addressed but is not completeScriptingenhancement/bug for GSASIIscriptablebugSomething isn't working

Type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions