Source code for mcsas.mcsasparameters

# -*- coding: utf-8 -*-
# mcsas/mcsasparameters.py
# Find the reST syntax at http://sphinx-doc.org/rest.html

import os
import inspect
import logging                                                                 
import json
from utils import units, isString
from utils.propertynames import PropertyNames
from utils.parameter import Parameter
from main import makeAbsolutePath
logging.basicConfig(level = logging.INFO)                                      

[docs]class McSASParameters(PropertyNames): """ Defines the static parameters used for the fitting procedure: - *model*: an instance of McSAS.model defining the fitting model - *contribParamBounds*: Bounds of the active (fitting) parameter - *qBounds*: limits in *q* between which the fit is applied - *psiBounds*: limits in azimuthal angle (2D patterns only) to which the fit is applied - *qMagnitude*: indicates the multiplier to scale q to m^-1 - *iMagnitude*: indicates the multiplier to scale I to (m sr)^-1 - *histogramBins*: number of bins to use for size distribution determination. Does not affect fit - *histogramXScale*: can be "log" or "linear", sets the horizontal axis scaling. Does not affect fit - *histogramWeighting*: can be "volume"(recommended) or "number". Determines whether to plot the volume-weighted size distribution (which is closest to what is measured in a scattering measurement) or a number-weighted size distribution. - *deltaRhoSquared* the value (in m^{-4}) of the squared electron density contrast. Typically on the order of 10^{25} to 10^{30} for X-ray scattering measurements. To get a correct volume fraction, the intensity must be in reciprocal meters, as must *q* and the object size parameters must be adjusted accordingly. - *startFromMinimum*: may be depreciated: starts with an initial guess consisting of minimum size values rather than random. For testing purposes only. - *maxRetries*: if a single optimisation fails, it will be retried this integer of times. - *maskNegativeInt*: may be depreciated due to overlap with similar functionality in the McSAS.data molule. Setting this will ignore datapoints with intensity values < 0 - *maskZeroInt*: similar to above, but for intensity values = 0 Most of them should be moved to McSAS as dynamic parameters of type *Parameter* which allows them to be configurable in the GUI. Some, esp. *histogramBins* and *histogramXScale* should be moved to a custom *FitParameter* class along with the *active* flag. (WIP) Extension in progress: the class can take keyword-value pairs to overwrite (some of) the parameter values. Additionally, a default configuration file (json-style) can be provided using kwarg: ``paramDefFile = 'path/to/file'`` A (limited) set of custom parameters can be supplied in another configuration file that overwrite the defaults: ``paramFile = 'path/to/file'`` The order is: - default file, whose values are superseded by - custom file, whose values are superseded by - keyword-value pairs, which only set parameter *values*, or - keyword-dict pairs, which sets parameter attributes as defined in the supplied dictionary """ # set old-style defaults model = None contribParamBounds = () # new defaults for loading parameters parameters = list() paramDefFile = os.path.join("mcsas", "mcsasparameters.json")
[docs] def loadParameters(self, filename): # load parameter definitions from file and add to list: parDict = dict() filename = makeAbsolutePath(filename) if not os.path.exists(filename): # trying one level up dirname, basename = os.path.split(filename) dirname = os.path.dirname(dirname) filename = os.path.join(dirname, basename) try: with open(filename, 'r') as jfile: logging.info("Loading parameters from file: '{}'" .format(filename)) parDict = json.load(jfile) except IOError: logging.error("Could not load default parameter file '{fn}'!" .format(fn = filename)) for pkey in parDict.keys(): default = parDict[pkey].pop('default') unitClass = parDict[pkey].pop('unitClass', None) displayUnit = parDict[pkey].pop('displayUnit', None) unitInstance = self.pickUnit(unitClass, displayUnit) self.parameters.append( Parameter(pkey, default, unit = unitInstance, **parDict[pkey]) ) logging.debug('Parameter {} ingested'.format(pkey))
def __init__(self, paramDefFile = None): """initialise the defaults and populate the database with values where appropriate default parameter file can be provided using kwarg: paramDefFile = 'path/to/file' relative to application root dir """ # instantiate defaults: if not isString(paramDefFile) or not os.path.exists(paramDefFile): paramDefFile = self.paramDefFile self.loadParameters(paramDefFile)
[docs] def pickUnit(self, unitClass = None, displayUnit = None): """ returns a unit object instance of the right class and displayUnit """ #first make a dictionary of name-object pairs if (unitClass is None) or (displayUnit is None): logging.warning('Unit not properly set for parameter.') return units.NoUnit() unitDict = {} for name, obj in inspect.getmembers(units): if inspect.isclass(obj): if issubclass(obj, units.Unit): unitDict.update({name: obj}) if unitClass in unitDict: unitObj = unitDict[unitClass] return unitObj(displayUnit) else: logging.warning('Unit class "{}" not found! Mind the case sensitivity!' .format(unitClass)) return units.NoUnit()
# vim: set ts=4 sts=4 sw=4 tw=0: