Changeset 4515


Ignore:
Timestamp:
Jul 7, 2020 5:42:34 PM (3 years ago)
Author:
toby
Message:

new capability: general parameter access

Location:
trunk
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • trunk/GSASIIdataGUI.py

    r4514 r4515  
    51555155            histNames = Controls['Seq Data']
    51565156        else: # patch from before Controls['Seq Data'] was implemented
    5157             histNames = G2stIO.GetHistogramNames(self.GPXfile,['PWDR',])
     5157            histNames = G2stIO.GetHistogramNames(self.GSASprojectfile,['PWDR',])
    51585158        if Controls.get('Reverse Seq'):
    51595159            histNames.reverse()
  • trunk/GSASIIpath.py

    r4487 r4515  
    10441044    subprocess.Popen(["osascript","-e",script])
    10451045
     1046def MacRunScript(script):
     1047    '''Start a bash script in a new terminal window.
     1048    Used on Mac OS X only.
     1049
     1050    :param str script: file name for a bash script
     1051    '''
     1052    script = os.path.abspath(script)
     1053    osascript = '''
     1054set bash to "/bin/bash"
     1055set filename to "{}"
     1056
     1057tell application "Terminal"
     1058     activate
     1059     do script bash & " " & filename & "; exit"
     1060end tell
     1061'''.format(script)
     1062    subprocess.Popen(["osascript","-e",osascript])
     1063   
    10461064def findConda():
    10471065    '''Determines if GSAS-II has been installed as g2conda or gsas2full
  • trunk/GSASIIscriptable.py

    r4469 r4515  
    2222(see :ref:`CommandlineInterface`) that
    2323provides access a number of features without writing Python scripts
    24 via shell/batch commands. The more powerful mode of GSASIIscriptable is
     24via shell/batch commands. The more widely used and more powerful mode of GSASIIscriptable is
    2525use is through Python scripts that
    2626call the module's application interface (API), see API summary that follows or the :ref:`API`
     
    289289Refinement recipe
    290290------------------------
     291
    291292Building on the :ref:`Project_dicts`,
    292293it is possible to specify a sequence of refinement actions as a list of
     
    652653    some_histogram.set_refinements(params)
    653654
    654 
    655655and here is an example for HAP parameters:
    656656
     
    665665
    666666Note that the parameters must match the object type and method (phase vs. histogram vs. HAP).
     667
     668.. _AccessingOtherItems:
     669
     670===================================
     671Access to other parameter settings
     672===================================
     673
     674There are several hundred different types of values that can be stored in a
     675GSAS-II project (.gpx) file. All can be changed from the GUI but only a
     676subset have direct mechanism implemented for change from the GSASIIscriptable
     677API. In practice all parameters in a .gpx file can be edited via scripting,
     678but sometimes determining what should be changed to implement a change can be
     679complex.
     680Several routines, :meth:`G2Phase.getHAPentryValue`,
     681:meth:`G2Phase.getPhaseEntryValue` and :meth:`G2PwdrData.getHistEntryList`
     682provide a mechanism to discover what the GUI is changing inside a .gpx file.
     683
     684As an example, a user in changing the data type for a histogram from Debye-Scherrer
     685mode to Bragg-Brentano. This capability is not directly exposed in the API. To
     686find out what changes when the histogram type is changed we can create a short script
     687that displays the contents of all the histogram settings:
     688
     689.. code-block::  python
     690
     691    from __future__ import division, print_function
     692    import os,sys
     693    sys.path.insert(0,'/Users/toby/software/G2/GSASII')
     694    import GSASIIscriptable as G2sc
     695    gpx = G2sc.G2Project('/tmp/test.gpx')
     696    h = gpx.histograms()[0]
     697    for h in h.getHistEntryList():
     698        print(h)
     699
     700This can be run with a command like this::
     701
     702       python test.py > before.txt
     703
     704(This will create file ``before.txt``, which will contain hundreds of lines.)
     705
     706At this point open the project file, ``test.py`` in the GSAS-II GUI and
     707change in Histogram/Sample Parameters the diffractometer type from Debye-Scherrer
     708mode to Bragg-Brentano and then save the file.
     709
     710Rerun the previous script creating a new file::
     711
     712       python test.py > after.txt
     713
     714Finally look for the differences between files ``before.txt`` and ``after.txt`` using a tool
     715such as diff on Linux/OS X or fc in Windows.
     716
     717
     718    Z:\>fc before.txt after.txt
     719    Comparing files before.txt and after.txt
     720    ***** before.txt
     721           fill_value = 1e+20)
     722    , 'PWDR Co_PCP_Act_d900-00030.fxye Bank 1', 'PWDR Co_PCP_Act_d900-00030.fxye Ban
     723    k 1'])
     724    (['Comments'], <class 'list'>, ['Co_PCP_Act_d900-00030.tif #0001 Azm= 180.00'])
     725    ***** AFTER.TXT
     726           fill_value = 1e+20)
     727    , 'PWDR Co_PCP_Act_d900-00030.fxye Bank 1', 'PWDR Co_PCP_Act_d900-00030.fxye Ban
     728    k 1', 'PWDR Co_PCP_Act_d900-00030.fxye Bank 1']
     729
     730    (['Comments'], <class 'list'>, ['Co_PCP_Act_d900-00030.tif #0001 Azm= 180.00'])
     731    *****
     732
     733    ***** before.txt
     734    (['Sample Parameters', 'Scale'], <class 'list'>, [1.276313196832068, True])
     735    (['Sample Parameters', 'Type'], <class 'str'>, 'Debye-Scherrer')
     736    (['Sample Parameters', 'Absorption'], <class 'list'>, [0.0, False])
     737    ***** AFTER.TXT
     738    (['Sample Parameters', 'Scale'], <class 'list'>, [1.276313196832068, True])
     739    (['Sample Parameters', 'Type'], <class 'str'>, 'Bragg-Brentano')
     740    (['Sample Parameters', 'Absorption'], <class 'list'>, [0.0, False])
     741    *****
     742
     743    bht14: toby$ diff before.txt after.txt
     744    103c103
     745    < , 'PWDR Co_PCP_Act_d900-00030.fxye Bank 1', 'PWDR Co_PCP_Act_d900-00030.fxye Bank 1'])
     746    ---
     747    > , 'PWDR Co_PCP_Act_d900-00030.fxye Bank 1', 'PWDR Co_PCP_Act_d900-00030.fxye Bank 1', 'PWDR Co_PCP_Act_d900-00030.fxye Bank 1'])
     748    111c111
     749    < (['Sample Parameters', 'Type'], <class 'str'>, 'Debye-Scherrer')
     750    ---
     751    > (['Sample Parameters', 'Type'], <class 'str'>, 'Bragg-Brentano')
     752
     753From this we can see there are two changes that took place. One is fairly obscure,
     754where the histogram name is added to a list, which can be ignored, but the second change
     755occurs in a straight-forward way and we discover that a simple call::
     756
     757    h.setHistEntryValue(['Sample Parameters', 'Type'], 'Bragg-Brentano')
     758
     759can be used to change the histogram type.
    667760
    668761.. _CodeExamples:
     
    20342127        provided. Note that in unix fashion, "~" can be used to indicate the
    20352128        home directory (e.g. ~/G2data/data.fxye).
     2129
     2130        Note that the data type (x-ray/CW neutron/TOF) for the histogram
     2131        will be set from the instrument parameter file. The instrument
     2132        geometry is assumed to be Debye-Scherrer except for
     2133        dual-wavelength x-ray, where Bragg-Brentano is assumed.
    20362134
    20372135        :param str datafile: The powder data file to read, a filename.
     
    42664364            ]
    42674365        self.data['Limits'] = [(1000*Tmin, 1000*Tmax), [1000*Tmin, 1000*Tmax]]
     4366
     4367    def getHistEntryList(self, keyname=''):
     4368        """Returns a dict with histogram setting values.
     4369
     4370        :param str keyname: an optional string. When supplied only entries
     4371          where at least one key contains the specified string are reported.
     4372          Case is ignored, so 'sg' will find entries where one of the keys
     4373          is 'SGdata', etc.
     4374        :returns: a set of histogram dict keys.
     4375
     4376        See :meth:`G2Phase.getHAPentryList` for a related example.
     4377
     4378        """
     4379        return [i for i in dictDive(self.data,keyname) if i[0] != ['Histograms']]
     4380
     4381    def getHistEntryValue(self, keylist):
     4382        """Returns the histogram control value associated with a list of keys.
     4383        Where the value returned is a list, it may be used as the target of
     4384        an assignment (as in
     4385        ``getHistEntryValue(``...``)[``...``] = ``val)
     4386        to set a value inside a list.       
     4387
     4388        :param list keylist: a list of dict keys, typically as returned by
     4389          :meth:`getHistEntryList`.
     4390
     4391        :returns: a histogram setting; may be a int, float, bool, list,...
     4392
     4393        See :meth:`G2Phase.getHAPentryValue` for a related example.
     4394
     4395        """
     4396        d = self.data
     4397        for key in keylist:
     4398            d = d[key]
     4399        return d
     4400
     4401    def setHistEntryValue(self, keylist, newvalue):
     4402        """Sets a histogram control value associated with a list of keys.
     4403
     4404       :param list keylist: a list of dict keys, typically as returned by
     4405          :meth:`getHistEntryList`.
     4406
     4407        :param newvalue: a new value for the hist setting. The type must be
     4408          the same as the initial value, but if the value is a container
     4409          (list, tuple, np.array,...) the elements inside are not checked.
     4410
     4411        See :meth:`G2Phase.setHAPentryValue` for a related example.
     4412
     4413        """
     4414        oldvalue = self.getHistEntryValue(keylist)
     4415        if type(oldvalue) is not type(newvalue):
     4416            raise G2ScriptException("getHistEntryValue error: types do not agree for keys {}".format(keylist))
     4417        d = self.data
     4418        for key in keylist:
     4419            dlast = d
     4420            d = d[key]
     4421        dlast[key] = newvalue
    42684422       
    42694423class G2Phase(G2ObjectWrapper):
     
    50115165        G2fil.G2Print(' to histogram(s) {}'.format([self._decodeHist(h) for h in targethistlist]))
    50125166
     5167    def getPhaseEntryList(self, keyname=''):
     5168        """Returns a dict with control values.
     5169
     5170        :param str keyname: an optional string. When supplied only entries
     5171          where at least one key contains the specified string are reported.
     5172          Case is ignored, so 'sg' will find entries where one of the keys
     5173          is 'SGdata', etc.
     5174        :returns: a set of phase dict keys. Note that HAP items, while
     5175          technically part of the phase entries, are not included.
     5176
     5177        See :meth:`getHAPentryList` for a related example.
     5178
     5179        """
     5180        return [i for i in dictDive(self.data,keyname) if i[0] != ['Histograms']]
     5181
     5182    def getPhaseEntryValue(self, keylist):
     5183        """Returns the value associated with a list of keys.
     5184        Where the value returned is a list, it may be used as the target of
     5185        an assignment (as in
     5186        ``getPhaseEntryValue(``...``)[``...``] = ``val)
     5187        to set a value inside a list.       
     5188
     5189        :param list keylist: a list of dict keys, typically as returned by
     5190          :meth:`getPhaseEntryList`.
     5191
     5192        :returns: a phase setting; may be a int, float, bool, list,...
     5193
     5194        See :meth:`getHAPentryValue` for a related example.
     5195
     5196        """
     5197        d = self.data
     5198        for key in keylist:
     5199            d = d[key]
     5200        return d
     5201
     5202    def setPhaseEntryValue(self, keylist, newvalue):
     5203        """Sets a phase control value associated with a list of keys.
     5204
     5205        :param list keylist: a list of dict keys, typically as returned by
     5206          :meth:`getPhaseEntryList`.
     5207
     5208        :param newvalue: a new value for the phase setting. The type must be
     5209          the same as the initial value, but if the value is a container
     5210          (list, tuple, np.array,...) the elements inside are not checked.
     5211
     5212        See :meth:`setHAPentryValue` for a related example.
     5213
     5214        """
     5215        oldvalue = self.getPhaseEntryValue(keylist)
     5216        if type(oldvalue) is not type(newvalue):
     5217            raise G2ScriptException("getPhaseEntryValue error: types do not agree for keys {}".format(keylist))
     5218        d = self.data
     5219        for key in keylist:
     5220            dlast = d
     5221            d = d[key]
     5222        dlast[key] = newvalue
     5223       
     5224    def getHAPentryList(self, histname=None, keyname=''):
     5225        """Returns a dict with HAP values. Optionally a histogram
     5226        may be selected.
     5227
     5228        :param histname: is a histogram object (:class:`G2PwdrData`) or
     5229            a histogram name or the index number of the histogram.
     5230            The index number is relative to all histograms in the tree, not to
     5231            those in the phase. If no histogram is specified, all histograms
     5232            are selected.
     5233        :param str keyname: an optional string. When supplied only entries
     5234          where at least one key contains the specified string are reported.
     5235          Case is ignored, so 'sg' will find entries where one of the keys
     5236          is 'SGdata', etc.
     5237        :returns: a set of HAP dict keys.
     5238
     5239        Example:
     5240
     5241        >>> p.getHAPentryList(0,'Scale')
     5242        [(['PWDR test Bank 1', 'Scale'], list, [1.0, False])]
     5243
     5244        """
     5245        if histname:
     5246            h = [self._decodeHist(histname)]
     5247        else:
     5248            h = []
     5249        return dictDive(self.data['Histograms'],keyname,h)
     5250
     5251    def getHAPentryValue(self, keylist):
     5252        """Returns the HAP value associated with a list of keys. Where the
     5253        value returned is a list, it may be used as the target of
     5254        an assignment (as in
     5255        ``getHAPentryValue(``...``)[``...``] = ``val)
     5256        to set a value inside a list.
     5257
     5258        :param list keylist: a list of dict keys, typically as returned by
     5259          :meth:`getHAPentryList`. Note the first entry is a histogram name.
     5260          Example: ``['PWDR hist1.fxye Bank 1', 'Scale']``
     5261
     5262        :returns: HAP value
     5263
     5264        Example:
     5265
     5266        >>> sclEnt = p.getHAPentryList(0,'Scale')[0]                                    >>> sclEnt
     5267        [(['PWDR test Bank 1', 'Scale'], list, [1.0, False])]
     5268        >>> p.getHAPentryValue(sclEnt[0])
     5269        [1.0, False]
     5270        >>> p.getHAPentryValue(sclEnt[0])[1] = True
     5271        >>> p.getHAPentryValue(sclEnt[0])
     5272        [1.0, True]
     5273
     5274        """
     5275        d = self.data['Histograms']
     5276        for key in keylist:
     5277            d = d[key]
     5278        return d
     5279
     5280    def setHAPentryValue(self, keylist, newvalue):
     5281        """Sets an HAP value associated with a list of keys.
     5282
     5283        :param list keylist: a list of dict keys, typically as returned by
     5284          :meth:`getHAPentryList`. Note the first entry is a histogram name.
     5285          Example: ``['PWDR hist1.fxye Bank 1', 'Scale']``
     5286
     5287        :param newvalue: a new value for the HAP setting. The type must be
     5288          the same as the initial value, but if the value is a container
     5289          (list, tuple, np.array,...) the elements inside are not checked.
     5290
     5291        Example:
     5292
     5293        >>> sclEnt = p.getHAPentryList(0,'Scale')[0]
     5294        >>> p.getHAPentryValue(sclEnt[0])
     5295        [1.0, False]
     5296        >>> p.setHAPentryValue(sclEnt[0], (1, True))
     5297        GSASIIscriptable.G2ScriptException: setHAPentryValue error: types do not agree for keys ['PWDR test.fxye Bank 1', 'Scale']
     5298        >>> p.setHAPentryValue(sclEnt[0], [1, True])
     5299        >>> p.getHAPentryValue(sclEnt[0])
     5300        [1, True]
     5301
     5302        """
     5303        oldvalue = self.getHAPentryValue(keylist)
     5304        if type(oldvalue) is not type(newvalue):
     5305            raise G2ScriptException("setHAPentryValue error: types do not agree for keys {}".format(keylist))
     5306        d = self.data['Histograms']
     5307        for key in keylist:
     5308            dlast = d
     5309            d = d[key]
     5310        dlast[key] = newvalue
     5311   
    50135312class G2SeqRefRes(G2ObjectWrapper):
    50145313    '''Wrapper for a Sequential Refinement Results tree entry, containing the
     
    63436642    result.func(result)
    63446643
     6644def dictDive(d,search="",keylist=[],firstcall=True,l=None):
     6645    '''Recursive routine to scan a nested dict. Reports a list of keys
     6646    and the associated type and value for that key.
     6647
     6648    :param dict d: a dict that will be scanned
     6649    :param str search: an optional search string. If non-blank,
     6650       only entries where one of the keys constains search (case ignored)
     6651    :param list keylist: a list of keys to apply to the dict.
     6652    :param bool firstcall: do not specify
     6653    :param list l: do not specify
     6654
     6655    :returns: a list of keys located by this routine
     6656       in form [([keylist], type, value),...] where if keylist is ['a','b','c']
     6657       then d[['a']['b']['c'] will have the value.
     6658
     6659    This routine can be called in a number of ways, as are shown in a few
     6660    examples:
     6661
     6662    >>> for i in G2sc.dictDive(p.data['General'],'paw'): print(i)
     6663    ...
     6664    (['Pawley dmin'], <class 'float'>, 1.0)
     6665    (['doPawley'], <class 'bool'>, False)
     6666    (['Pawley dmax'], <class 'float'>, 100.0)
     6667    (['Pawley neg wt'], <class 'float'>, 0.0)
     6668    >>>
     6669    >>> for i in G2sc.dictDive(p.data,'paw',['General']): print(i)
     6670    ...
     6671    (['General', 'Pawley dmin'], <class 'float'>, 1.0)
     6672    (['General', 'doPawley'], <class 'bool'>, False)
     6673    (['General', 'Pawley dmax'], <class 'float'>, 100.0)
     6674    (['General', 'Pawley neg wt'], <class 'float'>, 0.0)
     6675    >>>
     6676    >>> for i in G2sc.dictDive(p.data,'',['General','doPawley']): print(i)
     6677    ...
     6678    (['General', 'doPawley'], <class 'bool'>, False)
     6679
     6680    '''
     6681    if firstcall:
     6682        for k in keylist:
     6683            d = d[k]
     6684        l = []
     6685        first = True
     6686    if type(d) is dict:
     6687        [dictDive(d[key],search,keylist+[key],False,l) for key in d]
     6688    elif search:
     6689        for key in keylist:
     6690            if search.lower() in key.lower():
     6691                l.append((keylist,type(d),d))
     6692                break
     6693        return
     6694    else:
     6695        l.append((keylist,type(d),d))
     6696    if firstcall:
     6697        return l
     6698       
    63456699if __name__ == '__main__':
    63466700    #fname='/tmp/corundum-template.gpx'
Note: See TracChangeset for help on using the changeset viewer.