def linearize_data(self, data): """ Linearize data so that a linear fit can be performed. Filter out the data that can't be transformed. :param data: LoadData1D instance """ # Check that the vector lengths are equal assert len(data.x) == len(data.y) if data.dy is not None: assert len(data.x) == len(data.dy) dy = data.dy else: dy = np.ones(len(data.y)) # Transform the data data_points = zip(data.x, data.y, dy) output_points = [(self.linearize_q_value(p[0]), math.log(p[1]), p[2] / p[1]) for p in data_points if p[0] > 0 and \ p[1] > 0 and p[2] > 0] x_out, y_out, dy_out = zip(*output_points) # Create Data1D object x_out = np.asarray(x_out) y_out = np.asarray(y_out) dy_out = np.asarray(dy_out) linear_data = LoaderData1D(x=x_out, y=y_out, dy=dy_out) return linear_data
def _get_extrapolated_data(self, model, npts=INTEGRATION_NSTEPS, q_start=Q_MINIMUM, q_end=Q_MAXIMUM): """ :return: extrapolate data create from data """ #create new Data1D to compute the invariant q = np.linspace(start=q_start, stop=q_end, num=npts, endpoint=True) iq = model.evaluate_model(q) diq = model.evaluate_model_errors(q) result_data = LoaderData1D(x=q, y=iq, dy=diq) if self._smeared is not None: result_data.dxl = self._smeared * np.ones(len(q)) return result_data
def fit(self, power=None, qmin=None, qmax=None): """ Fit data for y = ax + b return a and b :param power: a fixed, otherwise None :param qmin: Minimum Q-value :param qmax: Maximum Q-value """ if qmin is None: qmin = self.qmin if qmax is None: qmax = self.qmax # Identify the bin range for the fit idx = (self.data.x >= qmin) & (self.data.x <= qmax) fx = np.zeros(len(self.data.x)) # Uncertainty if type(self.data.dy) == np.ndarray and \ len(self.data.dy) == len(self.data.x) and \ np.all(self.data.dy > 0): sigma = self.data.dy else: sigma = np.ones(len(self.data.x)) # Compute theory data f(x) fx[idx] = self.data.y[idx] # Linearize the data if self.model is not None: linearized_data = self.model.linearize_data(\ LoaderData1D(self.data.x[idx], fx[idx], dy=sigma[idx])) else: linearized_data = LoaderData1D(self.data.x[idx], fx[idx], dy=sigma[idx]) ##power is given only for function = power_law if power is not None: sigma2 = linearized_data.dy * linearized_data.dy a = -(power) b = (np.sum(linearized_data.y / sigma2) \ - a * np.sum(linearized_data.x / sigma2)) / np.sum(1.0 / sigma2) deltas = linearized_data.x * a + \ np.ones(len(linearized_data.x)) * b - linearized_data.y residuals = np.sum(deltas * deltas / sigma2) err = math.fabs(residuals) / np.sum(1.0 / sigma2) return [a, b], [0, math.sqrt(err)] else: A = np.vstack([ linearized_data.x / linearized_data.dy, 1.0 / linearized_data.dy ]).T # CRUFT: numpy>=1.14.0 allows rcond=None for the following default rcond = np.finfo(float).eps * max(A.shape) p, residuals, _, _ = np.linalg.lstsq(A, linearized_data.y / linearized_data.dy, rcond=rcond) # Get the covariance matrix, defined as inv_cov = a_transposed * a err = np.zeros(2) try: inv_cov = np.dot(A.transpose(), A) cov = np.linalg.pinv(inv_cov) err_matrix = math.fabs(residuals) * cov err = [ math.sqrt(err_matrix[0][0]), math.sqrt(err_matrix[1][1]) ] except: err = [-1.0, -1.0] return p, err