def Smear(q, C, dC, extrapname, sFinal, slitlength, quiet = False, weighted_transition=True): ''' Smear the data of C(q) into S(q) using the slit-length weighting function :func:`~jldesmear.api.smear.Plengt()` and an extrapolation of the data to avoid truncation errors. Assume that :func:`~jldesmear.api.smear.Plengt()` goes to zero for ``l > l_o`` (the slit length). Also assume that the slit length function is symmetrical about ``l = zero``. .. math:: S(q) = 2 \int_0^{l_o} P_l(l) \ C(\sqrt{q^2+l^2}) \ dl This routine is written so that if :func:`~jldesmear.api.smear.Plengt()` is changed (for example) to a Gaussian, that no further modification is necessary to the integration procedure. That is, this routine will integrate the data out to "slitlength" (``l_o``). :param numpy.ndarray q: magnitude of scattering vector :param numpy.ndarray C: unsmeared data is C(q) +/- dC(q) :param numpy.ndarray dC: estimated uncertainties of C :param str extrapname: one of ``constant | linear | powerlaw | Porod`` :param float sFinal: fit extrapolation to I(q) for q >= sFinal :param float slitlength: l_o, same units as q :param bool quiet: if True, then no printed output from this routine :param bool weighted_transition: if True, make a weighted transition between sFinal <= q < qMax :return: tuple of (S, extrap) :rtype: (numpy.ndarray, object) :var numpy.ndarray S: smeared version of C ''' # make the slit-length weighting function NumPts = len(q) q0 = q[0] qMax = q[-1] qRange = qMax - q0 x = slitlength * (q - q0) / qRange # use "x" rather than "l" to avoid typos w = Plengt(x, slitlength) # w = P_l(l) or P_l(x) # prepare for interpolation of existing data, log(I) interp = interp1d(q, numpy.log(C)) # select and fit the extrapolation if extrapolation.functions is None: extrapolation.discover_extrapolations() try: extrap = prepare_extrapolation(q, C, dC, extrapname, sFinal) except Exception: message = "prepare_extrapolation had a problem: " + str(sys.exc_info) raise Exception, message S = numpy.ndarray((NumPts,)) # slit-smeared intensity (to be the result) for i, qNow in enumerate(q): if not quiet: toolbox.Spinner(i) Ic = w * get_Ic(qNow, sFinal, qMax, x, interp, extrap, weighted_transition) S[i] = 2 * numpy.trapz(Ic, x) # symmetrical about zero return S, extrap
def prepare_extrapolation(q, C, dC, extrapname, sFinal): ''' Pick the extrapolation function for smearing :param numpy.ndarray q: magnitude of scattering vector :param numpy.ndarray C: array (list) such that data is C(q) +/- dC(q) :param numpy.ndarray dC: estimated uncertainties of C :param str extrapname: one of ``constant``, ``linear``, ``powerlaw``, or ``Porod`` :param float sFinal: fit extrapolation to I(q) for q >= sFinal :return: function object of selected extrapolation :rtype: object ''' if sFinal > q[-1]: raise Exception, "no data to fit extrapolation" for i in range(len(q)): start = i if q[i] > sFinal: break if len(q) - start < 2: raise Exception, "not enough data to fit" functions = extrapolation.discover_extrapolations() if extrapname not in functions.keys(): msg = "did not identify extrapolation function: " + extrapname raise RuntimeError, msg extrap = functions[extrapname]() extrap.fit(q[start:-1], C[start:-1], dC[start:-1]) return extrap
def _init_Adjustables_Panel(self, parent): '''contains adjustable parameters''' box = QGroupBox('Adjustable parameters', parent) layout = QGridLayout() box.setLayout(layout) row = 0 tip = 'desmearing slit length, l_o' self.slitlength = QLineEdit() self.slitlength.setToolTip(tip) self.slitlength.setStatusTip(tip) layout.addWidget(QLabel('l_o'), row, 0) layout.addWidget(self.slitlength, row, 1) self.slitlength.setText('0.1') row += 1 tip = 'functional form of extrapolation for desmearing' functions = extrapolation.discover_extrapolations() self.extrapolation = QComboBox() self.extrapolation.insertItems(999, sorted(functions.keys())) self.extrapolation.setToolTip(tip) self.extrapolation.setStatusTip(tip) layout.addWidget(QLabel('extrap'), row, 0) layout.addWidget(self.extrapolation, row, 1) self.setExtrapolationMethod('constant') row += 1 tip = 'evaluate extrapolation constants based on data for q > q_F' self.qFinal = QLineEdit() self.qFinal.setToolTip(tip) self.qFinal.setStatusTip(tip) layout.addWidget(QLabel('q_F'), row, 0) layout.addWidget(self.qFinal, row, 1) self.qFinal.setText('0.1') row += 1 tip = 'functional form of desmearing feedback, always use "fast"' self.feedback = QComboBox() self.feedback.insertItems(999, sorted(desmear.Weighting_Methods.keys())) self.feedback.setCurrentIndex(2) self.feedback.setToolTip(tip) self.feedback.setStatusTip(tip) layout.addWidget(QLabel('feedback'), row, 0) layout.addWidget(self.feedback, row, 1) self.setFeedbackMethod('fast') row += 1 tip = 'specifies number of desmearing iterations, N_i' self.num_iterations = QSpinBox() self.num_iterations.setRange(2, 1000) self.num_iterations.setToolTip(tip) self.num_iterations.setStatusTip(tip) layout.addWidget(QLabel('N_i'), row, 0) layout.addWidget(self.num_iterations, row, 1) self.num_iterations.setValue(10) return box
def read(self, filename): ''' read desmearing parameters from a command input file :param str filename: full path to the command input file :returns: instance of :class:`jldesmear.api.info.Info` ''' def get_buf_item(key, item=0): return buf[key].split()[item] ext = '.inp' if not filename.endswith(ext): return None if not os.path.exists(filename): return None self.info = info.Info() # read a .inp file self.info.parameterfile = filename path = os.path.dirname(filename) owd = os.getcwd() os.chdir(path) buf = open(os.path.abspath(filename), 'r').readlines() if len(buf) < 7: msg = "not enough information in command input file: " + filename raise RuntimeError, msg functions = extrapolation.discover_extrapolations() self.info.fileio_class = self self.info.filename = filename self.info.quiet = True self.info.callback = None self.info.infile = os.path.abspath(os.path.join(path, get_buf_item(0))) self.info.outfile = os.path.abspath(os.path.join(path, get_buf_item(1))) self.info.slitlength = float(get_buf_item(2)) self.info.extrapname = get_buf_item(3) self.info.sFinal = float(get_buf_item(4)) self.info.NumItr = int(get_buf_item(5)) self.info.LakeWeighting = get_buf_item(6) self.info.extrap = functions[self.info.extrapname] os.chdir(owd) return self.info