def fit_references(data, references, e_ranges, labels=None): """Fit 'references' to 'data' in the energy window (x) 'e_range'""" # Restrict data to within e_range index = [] for e_range in e_ranges: index.append(ct.get_range(data[:, 0], *e_range)) index = functools.reduce(np.union1d, index) #return index data = data[index] mod_ref = {label: ref[index] for label, ref in references.items()} # Define fitting relationship def func(x, *args): signal = x * 0 for arg, ref in list(zip(args, mod_ref.values())): signal += arg * ref[:, 1] return signal # Calculate best fit ret, _ = curve_fit(func, data[:, 0], data[:, 1], p0=[0.5] * len(references), bounds=(0, np.inf)) dict_ = {label: ret[i] for i, label in enumerate(references.keys())} pretty_dict = dict_as_percent(dict_) for label, percent in pretty_dict.items(): print(label, percent) return dict_
def align_spectra(iss_data, limits=[350, 520], masses=[16, 18], key='oxygen'): """Shift the iss data within 'limits' region to snap maximum signal unto nearest mass in list 'masses'.""" plt.figure('aligned') for data in iss_data: # Initialize attributes try: data.shifted except AttributeError: data.shifted = {} try: data.smoothed except AttributeError: data.smoothed = {} # Get index of region of interest index = ct.get_range(data.x, *limits) # Find maximum in region ys = ct.smooth(data.y, width=4) data.smoothed[key] = ys maximum = max(ys[index]) if not np.isfinite(maximum): data.good = False continue # "Broken" dataset data.good = True i_max = np.where(ys == maximum)[0] x_max = data.x[i_max] # Find difference from reference energies = data.ConvertEnergy(np.array(masses)) try: distance = np.abs(x_max - energies) except ValueError: print('ValueError') print(data.filename) print(data.x) print(data.y[np.isfinite(data.y)]) print(data.smoothed[key]) print(maximum) print(x_max) print(energies) plt.figure() plt.plot(data.x, data.y) plt.show() raise # Snap to nearest line data.shifted[key] = data.x - (x_max - energies)[np.where( distance == min(distance))[0]] plt.plot(data.shifted[key], data.y) plt.plot(data.shifted[key], ys) data.AddMassLines(masses) # Return a nd.array of modified xy data return np.vstack((data.shifted[key], data.smoothed[key])).T
def fit_references_v2(iss, references, e_ranges, labels=None): """Fit 'references' to 'data' in the energy window (x) 'e_range' Subtract background from references to only use peak intensities for fit. Subtract beckground in the regions you want to fit. """ #plt.show() # Restrict data to within e_range index = [] for e_range in e_ranges: index.append(ct.get_range(iss.x, *e_range)) index = functools.reduce(np.union1d, index) # Subtract background from references modified_references = {} for label, (ref, limit) in references.items(): modified_references[label] = np.copy(ref) #modified_references[label][:, 1] -= peak[index] background = subtract_single_background(ref, ranges=[limit]) modified_references[label][:, 1] -= background #modified_references[label] = modified_references[label][index] #plt.plot(ref[:, 0], ref[:, 1] - background, label=label) # Subtract background from data subtract_backgrounds(iss_data=[iss], ranges=e_ranges) data = iss.xy[index] data[:, 1] -= iss.background[index] #plt.plot(data[:, 0], data[:, 1], 'ko', label='Data') #plt.plot(iss.x, iss.background, label='Data (raw)') #plt.legend() #plt.show() #modified_references = {label: ref[index] for label, ref in references.items()} # Define fitting relationship def func(x, *args): signal = x * 0 for arg, ref in list(zip(args, modified_references.values())): signal += arg * ref[:, 1][index] return signal # Calculate best fit ret, _ = curve_fit(func, data[:, 0], data[:, 1], p0=[0.5] * len(references), bounds=(0, np.inf)) dict_ = {label: ret[i] for i, label in enumerate(references.keys())} #for label, percent in pretty_dict.items(): print(label, percent) return dict_, modified_references
def get_timesnippet(self, label, limit): """Return (time, data) of data set 'label' cropped to fit into time 'limit'""" index = ct.get_range(self.data[label][:, 0], limit[0], limit[1]) return self.data[label][:, 0][index], self.data[label][:, 1][index]
def isolate_experiments(self, set_label=None, temp_label='Sample temperature'): """ 1) Isolate regions of heating ramps 2) Organize into returnable data 3) Convert time to temperature - intentionally oversample the temperature - collect groups into points of average/std - interpolate points to correlate arbitrary time with a temperature """ # 1) Find regions of heating ramps if set_label is None: for i in self.labels: if 'setpoint' in i.lower().split() and 'temperature' in i.lower().split(): set_label = i break if set_label is None: print('Ramp label is not found automatically. Specify "set_label"!') raise ValueError() if len(self.data[set_label]) == 0: raise ValueError('No heat ramps detected') marker_start, marker_end = 0, 0 counter = 0 regions = [] for i in self.data[set_label][:,0]: if counter == 0: last = i marker_start = counter counter += 1 continue # Main check if i - last > 15: # difference of more than 15 seconds marker_end = counter region = np.arange(marker_start, marker_end) regions.append(region) marker_start = counter # End of loop last = i counter += 1 region = np.arange(marker_start, counter) regions.append(region) number_of_regions = len(regions) #print(number_of_regions) # 2) Organize into returnable data # Get temperature data if not temp_label in self.labels: for i in self.labels: if 'sample' in i.lower() and 'temperature' in i.lower(): temp_label = i print('Temperature label deviating from default found: "{}"'.format(temp_label)) break else: print('"Sample temperature" not found in loaded dataset. Please specify "temp_label"!') return None interpolate_temp = time2temp(self.data[temp_label]) # Local heating rate number = 0 t_window = 10 # For fast temperature logging, this seems to work very good. Hasn't been tested on # sparse datasets *** OBSOLETE *** while number < 3: t_window += 1 number = len(ct.get_range(self.data[temp_label][:, 0], self.data[temp_label][-1, 0]-t_window, self.data[temp_label][-1, 0])) self.slope = self.data[temp_label].copy() self.slope[:number+1, 1] = np.nan for i in range(len(self.slope[:, 0]) -1, number, -1): coeff = np.polyfit(self.data[temp_label][i-number:i+1, 0], self.data[temp_label][i-number:i+1, 1], 1) self.slope[i, 1] = coeff[0] interpolate_slope = time2temp(self.slope) # Set up data structure for experiments for i in range(number_of_regions): self.exps[i] = {} region = regions[i] time_ref = self.data[set_label][:,0][region] for label in self.labels: # skip if empty #print(self.data[label], label) #if self.data[label] == None: #if len(self.data[label]) == 0: # continue if len(self.data[label]) == 0: continue self.exps[i][label] = {} local_range = get_range(self.data[label][:, 0], [time_ref[0]-3, time_ref[-1]+3]) for x in [0, 1]: self.exps[i][label][x] = self.data[label][:, x][local_range] # 3) Add temperature axis to each data set for label in self.labels: # skip if empty #if self.data[label] == None: #if len(self.data[label]) == 0: # continue if len(self.data[label]) == 0: continue print(i, label) self.exps[i][label][2] = interpolate_temp(self.exps[i][label][0]) # Extract information about local heating rate dat = self.exps[i][label] dat[3] = np.empty(len(dat[0])) dat[3][0] = np.nan dat[3][1:] = ct.smooth(np.diff(dat[2])/np.diff(dat[0]), width=1) # Save results in pickle: self.save_pickle()