def process_file(self, normfiledata): """ Process a given SPECS file. Iterate through the regions and if the scan mode is ConstantFinalState we normalize it. """ # Try to make a folder called rootfile-NEXAFS." dfname = self.rootfile + "-NEXAFS" if os.path.exists(dfname): print "Error: Unpack folder already exists. Delete it and then click Go again." return else: os.mkdir(dfname) olddir = os.getcwd() os.chdir(dfname) for g in self.specsobj.groups: if DEBUG: print "=====================", g.name, "=====================" # Make a folder with the group name - need to make sure it's unique. have_name = False name_counter = 0 while not have_name: if name_counter == 0: tmpname = g.name else: tmpname = g.name + "-" + str(name_counter) if not os.path.exists(tmpname): os.mkdir(tmpname) os.chdir(tmpname) have_name = True name_counter = 0 else: # Darn, the directory prob already exists. name_counter += 1 for r in g.regions: newdata = None if r.scan_mode == "ConstantFinalState": newdata = self.process_region(r, normfiledata) print "Processing region: ", r.name else: print "Region %s is not NEXAFS - skipping." % (r.name) if newdata is not None: laey = None ltey = None lpey = None if self.preedge_treatment == "linear": laey = specs.preedge_calculate(newdata[:,0], newdata[:,9]) ltey = specs.preedge_calculate(newdata[:,0], newdata[:,10]) lpey = specs.preedge_calculate(newdata[:,0], newdata[:,11]) if laey is None: laey = newdata[0,9] * ones(newdata[:,9].shape) if ltey is None: ltey = newdata[0,10] * ones(newdata[:,10].shape) if lpey is None: lpey = newdata[0,11] * ones(newdata[:,11].shape) subdata = zeros((newdata.shape[0], newdata.shape[1] + 6)) subdata[:,:12] = newdata subdata[:,12] = laey subdata[:,13] = ltey subdata[:,14] = lpey try: subdata[:,15] = newdata[:,9] - laey except TypeError: subdata[:,15] = newdata[:,9] print "Couldn't subtract a linear pre-edge from the aey spectrum for this region." try: subdata[:,16] = newdata[:,10] - ltey except TypeError: subdata[:,16] = newdata[:,10] print "Couldn't subtract a linear pre-edge from the tey spectrum for this region." try: subdata[:,17] = newdata[:,11] - lpey except TypeError: subdata[:,17] = newdata[:,11] print "Couldn't subtract a linear pre-edge from the pey spectrum for this region." # Individually normalize the components #try: # subdata[:,15] = subdata[:,15] / subdata[-1,15] #except FloatingPointError: # print "The AEY channel cannot be 1-normalized for this file." #try: # subdata[:,16] = subdata[:,16] / subdata[-1,16] #except FloatingPointError: # print "The TEY channel cannot be 1-normalized for this file." #try: # subdata[:,17] = subdata[:,17] / subdata[-1,17] #except FloatingPointError: # print "The PEY channel cannot be 1-normalized for this file." have_name = False name_counter = 0 while not have_name: if name_counter == 0: r_write_name = r.name + ".xy" else: r_write_name = r.name + "-" + str(name_counter) + ".xy" if not os.path.exists(r_write_name): have_name = True name_counter = 0 else: # Darn, the directory prob already exists. name_counter += 1 savetxt(r_write_name, subdata) # If we didn't actually put any files in this folder, delete it. tmpdir = os.getcwd() os.chdir(dfname) if os.listdir(tmpdir) == []: os.rmdir(tmpdir) os.chdir(olddir)
def loadxml(self): xmlfile = tkFileDialog.askopenfilename(title="Choose a SPECS .xml file.", initialdir=os.getcwd()) if xmlfile != None: xmlcontents = specs.SPECS(xmlfile) # Make a folder: call it "xmlfile"-unpacked base_path = os.path.split(xmlfile)[0] cwd = os.getcwd() # Remove whitespace either side of the name. It's important. :o) unpack_path = os.path.join(base_path, xmlfile+"-unpacked").strip() os.mkdir(unpack_path) os.chdir(unpack_path) for g in xmlcontents.groups: if DEBUG: print "=================== OUTPUT: %s ====================" % (g.name) # We want to make a folder matching the group name, but we might not # be able to because it might already exist (group names are not # required to be unique in SPECS). So we have to fiddle here a bit. have_name = False name_counter = 0 while not have_name: if name_counter == 0: tmpname = g.name.strip() else: tmpname = (g.name + "-" + str(name_counter)).strip() if not os.path.exists(tmpname): os.mkdir(tmpname) os.chdir(tmpname) have_name = True name_counter = 0 else: # Darn, the directory prob already exists. name_counter += 1 for r in g.regions: if DEBUG: print "Constructing output for region %s..." % (r.name) # Decide how many outputs based on whether we have extended channels # and so on. have_nine_channels = False num_outputs = 2 # Bare output is energy and counts if r.channel_counts.shape[1] > 1: have_nine_channels = True num_outputs += r.channel_counts.shape[1] chan_out_idx = 2 + r.channel_counts.shape[1] if r.extended_channels is not None: # Output all extended channels plus counts / I0. ex_out_sidx = num_outputs num_outputs += r.extended_channels.shape[1] + 1 ex_out_fidx = ex_out_sidx + 9 # For now, automatically add the shirley and linear subtractions. # Eventually this will be an option. num_outputs += 5 # Linear preedge, background # scaling factor, shirley, counts - L - S and # (counts - L - S) / I0. data = zeros((r.values_per_curve,num_outputs)) hdr_string = "" if r.scan_mode == "FixedAnalyzerTransmission": data[:,0] = r.binding_axis x = r.binding_axis hdr_string += "Binding_energy_(eV) " elif r.scan_mode == "ConstantFinalState": data[:,0] = r.excitation_axis x = r.excitation_axis hdr_string += "Photon_energy_(eV) " else: data[:,0] = r.kinetic_axis x = r.kinetic_axis hdr_string += "Kinetic_energy_(eV) " data[:,1] = r.counts y = r.counts hdr_string += "Counts " if have_nine_channels: data[:,2:chan_out_idx] = r.channel_counts for i in range(2,chan_out_idx): hdr_string += "Channeltron_#%d " % (i-1) if r.extended_channels is not None: data[:,ex_out_sidx:ex_out_fidx] = r.extended_channels for i in range(1,ex_out_fidx-ex_out_sidx+1): hdr_string += "Extended_Channel_#%d " % (i) # Need to check for divide-by-zero here try: data[:,ex_out_fidx] = r.counts / r.extended_channels[:,2] # Removed the normalization here because we want un-normalized y for the # pre-edge fitting. #y = r.counts / r.extended_channels[:,2] hdr_string += "Counts/I0 " except FloatingPointError: print "Divide by zero in I0 channel: skipping I0 normalization." data[:,ex_out_fidx] = r.counts #y = r.counts hdr_string += "Counts " else: print "Extended channels are not present: No I0 normalization." # The order of operations here is: # # 1. Calculate the linear pre-edge (gives L). # 2. Subtract the linear pre-edge (With next step gives y1). # 3. Divide by an intensity offset to normalize against changes # in the overall intensity of the background, eg. from analyzer. # We take this offset to be the value of the linear pre-edge at the # lowest energy in the region. This could be more accurate but it # is pretty good. This gives y1. # (We skip if the background is zero or contains zeros) # 4. Calculate Shirley background using this new spectrum (gives S). # 5. Subtract the Shirley background (gives y2). # 6. Divide by I0 if present. We don't want to take y to be the normalized # spectrum to start with because the linear pre-edge fit is not robust # in those circumstances. Note this means we get TWO normalized spectra # in the file - one column before all the automatic stuff and one at the very # last column. # We really want to only do this stuff for XPS scans: if the analyzer mode is # not in FixedAnalyzerTransmission these extra columns will be zeroed. Strictly # speaking, we should also allow this for FRR mode (FixedRetardingRatio) but # since the input routine doesn't account for FRR properly yet there isn't # much point. # Have to check for a zero-division here. If we encounter one, # don't normalize against the pre-edge or divide by I0. print "Scan mode is: ", r.scan_mode if r.scan_mode == "FixedAnalyzerTransmission": print "FixedAnalyzerTransmission mode detected: attempting pre-edge and Shirley subtraction." try: L = specs.preedge_calculate(x,y) y1 = (y - L) / L[x.argmin()] S = specs.shirley_calculate(x,y1) y2 = y1 - S data[:,-5] = L data[:,-4] = L[x.argmin()] data[:,-3] = S data[:,-2] = y2 if r.extended_channels is not None: data[:,-1] = y2 / r.extended_channels[:,2] else: if DEBUG: print "Warning: No normalization output for this region!" data[:,-1] = y2 except FloatingPointError: data[:,-5] = specs.preedge_calculate(x,y) data[:,-4] = 1.0 data[:,-3] = specs.shirley_calculate(x,y - data[:,-5]) data[:,-2] = y - data[:,-5] - data[:,-3] data[:,-1] = y - data[:,-5] - data[:,-3] else: blank = zeros((r.values_per_curve)) data[:,-5] = blank data[:,-4] = blank data[:,-3] = blank data[:,-2] = blank data[:,-1] = blank hdr_string += "Preedge Scale_Division Shirley Counts-Preedge-Shirley Counts-Preedge-Shirley/I0" # As before, there are possible filename conflicts because there is # no requirement that SPECS region names be unique. have_name = False name_counter = 0 while not have_name: if name_counter == 0: r_write_name = r.name + ".xy" else: r_write_name = r.name + "-" + str(name_counter) + ".xy" if not os.path.exists(r_write_name): have_name = True name_counter = 0 else: # Darn, the directory prob already exists. name_counter += 1 try: savetxt(r_write_name, data,header=hdr_string) except TypeError: # Numpy version not recent enough for the header option. print ("""Your numpy version (%s) is not recent enough to support the\nheader option in savetxt: upgrade to a version >= 1.7 to get\nthis functionality.""" % (npyversion)) savetxt(r_write_name, data) os.chdir(unpack_path) os.chdir(cwd) print "====================================================================" print "= =" print "= Finished processing =" print "= =" print "===================================================================="
def loadxml(self): xmlfile = tkFileDialog.askopenfilename( title="Choose a SPECS .xml file.", initialdir=os.getcwd()) if xmlfile != None: xmlcontents = specs.SPECS(xmlfile) # Make a folder: call it "xmlfile"-unpacked base_path = os.path.split(xmlfile)[0] cwd = os.getcwd() # Remove whitespace either side of the name. It's important. :o) unpack_path = os.path.join(base_path, xmlfile + "-unpacked").strip() os.mkdir(unpack_path) os.chdir(unpack_path) for g in xmlcontents.groups: if DEBUG: print "=================== OUTPUT: %s ====================" % ( g.name) # We want to make a folder matching the group name, but we might not # be able to because it might already exist (group names are not # required to be unique in SPECS). So we have to fiddle here a bit. have_name = False name_counter = 0 while not have_name: if name_counter == 0: tmpname = g.name.strip() else: tmpname = (g.name + "-" + str(name_counter)).strip() if not os.path.exists(tmpname): os.mkdir(tmpname) os.chdir(tmpname) have_name = True name_counter = 0 else: # Darn, the directory prob already exists. name_counter += 1 for r in g.regions: if DEBUG: print "Constructing output for region %s..." % (r.name) # Decide how many outputs based on whether we have extended channels # and so on. have_nine_channels = False num_outputs = 2 # Bare output is energy and counts if r.channel_counts.shape[1] > 1: have_nine_channels = True num_outputs += r.channel_counts.shape[1] chan_out_idx = 2 + r.channel_counts.shape[1] if r.extended_channels is not None: # Output all extended channels plus counts / I0. ex_out_sidx = num_outputs num_outputs += r.extended_channels.shape[1] + 1 ex_out_fidx = ex_out_sidx + 9 # For now, automatically add the shirley and linear subtractions. # Eventually this will be an option. num_outputs += 5 # Linear preedge, background # scaling factor, shirley, counts - L - S and # (counts - L - S) / I0. data = zeros((r.values_per_curve, num_outputs)) hdr_string = "" if r.scan_mode == "FixedAnalyzerTransmission": data[:, 0] = r.binding_axis x = r.binding_axis hdr_string += "Binding_energy_(eV) " elif r.scan_mode == "ConstantFinalState": data[:, 0] = r.excitation_axis x = r.excitation_axis hdr_string += "Photon_energy_(eV) " else: data[:, 0] = r.kinetic_axis x = r.kinetic_axis hdr_string += "Kinetic_energy_(eV) " data[:, 1] = r.counts y = r.counts hdr_string += "Counts " if have_nine_channels: data[:, 2:chan_out_idx] = r.channel_counts for i in range(2, chan_out_idx): hdr_string += "Channeltron_#%d " % (i - 1) if r.extended_channels is not None: data[:, ex_out_sidx:ex_out_fidx] = r.extended_channels for i in range(1, ex_out_fidx - ex_out_sidx + 1): hdr_string += "Extended_Channel_#%d " % (i) # Need to check for divide-by-zero here try: data[:, ex_out_fidx] = r.counts / r.extended_channels[:, 2] # Removed the normalization here because we want un-normalized y for the # pre-edge fitting. #y = r.counts / r.extended_channels[:,2] hdr_string += "Counts/I0 " except FloatingPointError: print "Divide by zero in I0 channel: skipping I0 normalization." data[:, ex_out_fidx] = r.counts #y = r.counts hdr_string += "Counts " else: print "Extended channels are not present: No I0 normalization." # The order of operations here is: # # 1. Calculate the linear pre-edge (gives L). # 2. Subtract the linear pre-edge (With next step gives y1). # 3. Divide by an intensity offset to normalize against changes # in the overall intensity of the background, eg. from analyzer. # We take this offset to be the value of the linear pre-edge at the # lowest energy in the region. This could be more accurate but it # is pretty good. This gives y1. # (We skip if the background is zero or contains zeros) # 4. Calculate Shirley background using this new spectrum (gives S). # 5. Subtract the Shirley background (gives y2). # 6. Divide by I0 if present. We don't want to take y to be the normalized # spectrum to start with because the linear pre-edge fit is not robust # in those circumstances. Note this means we get TWO normalized spectra # in the file - one column before all the automatic stuff and one at the very # last column. # We really want to only do this stuff for XPS scans: if the analyzer mode is # not in FixedAnalyzerTransmission these extra columns will be zeroed. Strictly # speaking, we should also allow this for FRR mode (FixedRetardingRatio) but # since the input routine doesn't account for FRR properly yet there isn't # much point. # Have to check for a zero-division here. If we encounter one, # don't normalize against the pre-edge or divide by I0. print "Scan mode is: ", r.scan_mode if r.scan_mode == "FixedAnalyzerTransmission": print "FixedAnalyzerTransmission mode detected: attempting pre-edge and Shirley subtraction." try: L = specs.preedge_calculate(x, y) y1 = (y - L) / L[x.argmin()] S = specs.shirley_calculate(x, y1) y2 = y1 - S data[:, -5] = L data[:, -4] = L[x.argmin()] data[:, -3] = S data[:, -2] = y2 if r.extended_channels is not None: data[:, -1] = y2 / r.extended_channels[:, 2] else: if DEBUG: print "Warning: No normalization output for this region!" data[:, -1] = y2 except FloatingPointError: data[:, -5] = specs.preedge_calculate(x, y) data[:, -4] = 1.0 data[:, -3] = specs.shirley_calculate( x, y - data[:, -5]) data[:, -2] = y - data[:, -5] - data[:, -3] data[:, -1] = y - data[:, -5] - data[:, -3] else: blank = zeros((r.values_per_curve)) data[:, -5] = blank data[:, -4] = blank data[:, -3] = blank data[:, -2] = blank data[:, -1] = blank hdr_string += "Preedge Scale_Division Shirley Counts-Preedge-Shirley Counts-Preedge-Shirley/I0" # As before, there are possible filename conflicts because there is # no requirement that SPECS region names be unique. have_name = False name_counter = 0 while not have_name: if name_counter == 0: r_write_name = r.name + ".xy" else: r_write_name = r.name + "-" + str( name_counter) + ".xy" if not os.path.exists(r_write_name): have_name = True name_counter = 0 else: # Darn, the directory prob already exists. name_counter += 1 try: savetxt(r_write_name, data, header=hdr_string) except TypeError: # Numpy version not recent enough for the header option. print( """Your numpy version (%s) is not recent enough to support the\nheader option in savetxt: upgrade to a version >= 1.7 to get\nthis functionality.""" % (npyversion)) savetxt(r_write_name, data) os.chdir(unpack_path) os.chdir(cwd) print "====================================================================" print "= =" print "= Finished processing =" print "= =" print "===================================================================="