def get_file_contents(self): """ Get the contents of the file :raise RuntimeError: when the file can't be opened :raise ValueError: when the length of the data vectors are inconsistent """ buff = self.readall() filepath = self.f_open.name lines = buff.splitlines() self.output = [] self.current_datainfo = DataInfo() self.current_datainfo.filename = filepath detector = Detector() data_line = 0 self.reset_data_list(len(lines)) self.current_datainfo.detector.append(detector) self.current_datainfo.filename = filepath is_info = False is_center = False is_data_started = False base_q_unit = '1/A' base_i_unit = '1/cm' data_conv_q = Converter(base_q_unit) data_conv_i = Converter(base_i_unit) for line in lines: # Information line 1 if is_info: is_info = False line_toks = line.split() # Wavelength in Angstrom try: value = float(line_toks[1]) if self.current_datainfo.source.wavelength_unit != 'A': conv = Converter('A') self.current_datainfo.source.wavelength = conv( value, units=self.current_datainfo.source.wavelength_unit) else: self.current_datainfo.source.wavelength = value except KeyError: msg = "ABSReader cannot read wavelength from %s" % filepath self.current_datainfo.errors.append(msg) # Detector distance in meters try: value = float(line_toks[3]) if detector.distance_unit != 'm': conv = Converter('m') detector.distance = conv(value, units=detector.distance_unit) else: detector.distance = value except Exception: msg = "ABSReader cannot read SDD from %s" % filepath self.current_datainfo.errors.append(msg) # Transmission try: self.current_datainfo.sample.transmission = \ float(line_toks[4]) except ValueError: # Transmission isn't always in the header pass # Sample thickness in mm try: # ABS writer adds 'C' with no space to the end of the # thickness column. Remove it if it is there before # converting the thickness. if line_toks[5][-1] not in '012345679.': value = float(line_toks[5][:-1]) else: value = float(line_toks[5]) if self.current_datainfo.sample.thickness_unit != 'cm': conv = Converter('cm') self.current_datainfo.sample.thickness = conv( value, units=self.current_datainfo.sample.thickness_unit) else: self.current_datainfo.sample.thickness = value except ValueError: # Thickness is not a mandatory entry pass # MON CNT LAMBDA DET ANG DET DIST TRANS THICK AVE STEP if line.count("LAMBDA") > 0: is_info = True # Find center info line if is_center: is_center = False line_toks = line.split() # Center in bin number center_x = float(line_toks[0]) center_y = float(line_toks[1]) # Bin size if detector.pixel_size_unit != 'mm': conv = Converter('mm') detector.pixel_size.x = conv( 5.08, units=detector.pixel_size_unit) detector.pixel_size.y = conv( 5.08, units=detector.pixel_size_unit) else: detector.pixel_size.x = 5.08 detector.pixel_size.y = 5.08 # Store beam center in distance units # Det 640 x 640 mm if detector.beam_center_unit != 'mm': conv = Converter('mm') detector.beam_center.x = conv( center_x * 5.08, units=detector.beam_center_unit) detector.beam_center.y = conv( center_y * 5.08, units=detector.beam_center_unit) else: detector.beam_center.x = center_x * 5.08 detector.beam_center.y = center_y * 5.08 # Detector type try: detector.name = line_toks[7] except: # Detector name is not a mandatory entry pass # BCENT(X,Y) A1(mm) A2(mm) A1A2DIST(m) DL/L BSTOP(mm) DET_TYP if line.count("BCENT") > 0: is_center = True # Parse the data if is_data_started: toks = line.split() try: _x = float(toks[0]) _y = float(toks[1]) _dy = float(toks[2]) _dx = float(toks[3]) if data_conv_q is not None: _x = data_conv_q(_x, units=base_q_unit) _dx = data_conv_q(_dx, units=base_q_unit) if data_conv_i is not None: _y = data_conv_i(_y, units=base_i_unit) _dy = data_conv_i(_dy, units=base_i_unit) self.current_dataset.x[data_line] = _x self.current_dataset.y[data_line] = _y self.current_dataset.dy[data_line] = _dy if _dx > 0: self.current_dataset.dx[data_line] = _dx else: if data_line == 0: self.current_dataset.dx = None self.current_dataset.dxl = np.zeros(len(lines)) self.current_dataset.dxw = np.zeros(len(lines)) self.current_dataset.dxl[data_line] = abs(_dx) self.current_dataset.dxw[data_line] = 0 data_line += 1 except ValueError: # Could not read this data line. If we are here # it is because we are in the data section. Just # skip it. pass # SANS Data: # The 6 columns are | Q (1/A) | I(Q) (1/cm) | std. dev. # I(Q) (1/cm) | sigmaQ | meanQ | ShadowFactor| # USANS Data: # EMP LEVEL: <value> ; BKG LEVEL: <value> if line.startswith("The 6 columns") or line.startswith( "EMP LEVEL"): is_data_started = True self.remove_empty_q_values() # Sanity check if not len(self.current_dataset.y) == len(self.current_dataset.dy): self.set_all_to_none() msg = "abs_reader: y and dy have different length" raise ValueError(msg) # If the data length is zero, consider this as # though we were not able to read the file. if len(self.current_dataset.x) == 0: self.set_all_to_none() raise ValueError("ascii_reader: could not load file") if data_conv_q is not None: self.current_dataset.xaxis("\\rm{Q}", base_q_unit) else: self.current_dataset.xaxis("\\rm{Q}", 'A^{-1}') if data_conv_i is not None: self.current_dataset.yaxis("\\rm{Intensity}", base_i_unit) else: self.current_dataset.yaxis("\\rm{Intensity}", "cm^{-1}") # Store loading process information self.current_datainfo.meta_data['loader'] = self.type_name self.send_to_output()
def read(self, filename=None): """ Read file """ if not os.path.isfile(filename): raise ValueError, \ "Specified file %s is not a regular file" % filename # Read file f = open(filename, 'r') buf = f.read() f.close() # Instantiate data object output = Data2D() output.filename = os.path.basename(filename) detector = Detector() if len(output.detector) > 0: print str(output.detector[0]) output.detector.append(detector) # Get content dataStarted = False ## Defaults lines = buf.split('\n') x = [] y = [] wavelength = None distance = None transmission = None pixel_x = None pixel_y = None isInfo = False isCenter = False data_conv_q = None data_conv_i = None # Set units: This is the unit assumed for Q and I in the data file. if has_converter == True and output.Q_unit != '1/A': data_conv_q = Converter('1/A') # Test it data_conv_q(1.0, output.Q_unit) if has_converter == True and output.I_unit != '1/cm': data_conv_i = Converter('1/cm') # Test it data_conv_i(1.0, output.I_unit) # Remove the last lines before the for loop if the lines are empty # to calculate the exact number of data points count = 0 while (len(lines[len(lines) - (count + 1)].lstrip().rstrip()) < 1): del lines[len(lines) - (count + 1)] count = count + 1 #Read Header and find the dimensions of 2D data line_num = 0 # Old version NIST files: 0 ver = 0 for line in lines: line_num += 1 ## Reading the header applies only to IGOR/NIST 2D q_map data files # Find setup info line if isInfo: isInfo = False line_toks = line.split() # Wavelength in Angstrom try: wavelength = float(line_toks[1]) # Units if has_converter == True and \ output.source.wavelength_unit != 'A': conv = Converter('A') wavelength = conv(wavelength, units=output.source.wavelength_unit) except: #Not required pass # Distance in mm try: distance = float(line_toks[3]) # Units if has_converter == True and detector.distance_unit != 'm': conv = Converter('m') distance = conv(distance, units=detector.distance_unit) except: #Not required pass # Distance in meters try: transmission = float(line_toks[4]) except: #Not required pass if line.count("LAMBDA") > 0: isInfo = True # Find center info line if isCenter: isCenter = False line_toks = line.split() # Center in bin number center_x = float(line_toks[0]) center_y = float(line_toks[1]) if line.count("BCENT") > 0: isCenter = True # Check version if line.count("Data columns") > 0: if line.count("err(I)") > 0: ver = 1 # Find data start if line.count("ASCII data") > 0: dataStarted = True continue ## Read and get data. if dataStarted == True: line_toks = line.split() if len(line_toks) == 0: #empty line continue # the number of columns must be stayed same col_num = len(line_toks) break # Make numpy array to remove header lines using index lines_array = numpy.array(lines) # index for lines_array lines_index = numpy.arange(len(lines)) # get the data lines data_lines = lines_array[lines_index >= (line_num - 1)] # Now we get the total number of rows (i.e., # of data points) row_num = len(data_lines) # make it as list again to control the separators data_list = " ".join(data_lines.tolist()) # split all data to one big list w/" "separator data_list = data_list.split() # Check if the size is consistent with data, otherwise #try the tab(\t) separator # (this may be removed once get the confidence #the former working all cases). if len(data_list) != (len(data_lines)) * col_num: data_list = "\t".join(data_lines.tolist()) data_list = data_list.split() # Change it(string) into float #data_list = map(float,data_list) data_list1 = map(check_point, data_list) # numpy array form data_array = numpy.array(data_list1) # Redimesion based on the row_num and col_num, #otherwise raise an error. try: data_point = data_array.reshape(row_num, col_num).transpose() except: msg = "red2d_reader: Can't read this file: Not a proper file format" raise ValueError, msg ## Get the all data: Let's HARDcoding; Todo find better way # Defaults dqx_data = numpy.zeros(0) dqy_data = numpy.zeros(0) err_data = numpy.ones(row_num) qz_data = numpy.zeros(row_num) mask = numpy.ones(row_num, dtype=bool) # Get from the array qx_data = data_point[0] qy_data = data_point[1] data = data_point[2] if ver == 1: if col_num > (2 + ver): err_data = data_point[(2 + ver)] if col_num > (3 + ver): qz_data = data_point[(3 + ver)] if col_num > (4 + ver): dqx_data = data_point[(4 + ver)] if col_num > (5 + ver): dqy_data = data_point[(5 + ver)] #if col_num > (6 + ver): mask[data_point[(6 + ver)] < 1] = False q_data = numpy.sqrt(qx_data * qx_data + qy_data * qy_data + qz_data * qz_data) # Extra protection(it is needed for some data files): # If all mask elements are False, put all True if not mask.any(): mask[mask == False] = True # Store limits of the image in q space xmin = numpy.min(qx_data) xmax = numpy.max(qx_data) ymin = numpy.min(qy_data) ymax = numpy.max(qy_data) # units if has_converter == True and output.Q_unit != '1/A': xmin = data_conv_q(xmin, units=output.Q_unit) xmax = data_conv_q(xmax, units=output.Q_unit) ymin = data_conv_q(ymin, units=output.Q_unit) ymax = data_conv_q(ymax, units=output.Q_unit) ## calculate the range of the qx and qy_data x_size = math.fabs(xmax - xmin) y_size = math.fabs(ymax - ymin) # calculate the number of pixels in the each axes npix_y = math.floor(math.sqrt(len(data))) npix_x = math.floor(len(data) / npix_y) # calculate the size of bins xstep = x_size / (npix_x - 1) ystep = y_size / (npix_y - 1) # store x and y axis bin centers in q space x_bins = numpy.arange(xmin, xmax + xstep, xstep) y_bins = numpy.arange(ymin, ymax + ystep, ystep) # get the limits of q values xmin = xmin - xstep / 2 xmax = xmax + xstep / 2 ymin = ymin - ystep / 2 ymax = ymax + ystep / 2 #Store data in outputs #TODO: Check the lengths output.data = data if (err_data == 1).all(): output.err_data = numpy.sqrt(numpy.abs(data)) output.err_data[output.err_data == 0.0] = 1.0 else: output.err_data = err_data output.qx_data = qx_data output.qy_data = qy_data output.q_data = q_data output.mask = mask output.x_bins = x_bins output.y_bins = y_bins output.xmin = xmin output.xmax = xmax output.ymin = ymin output.ymax = ymax output.source.wavelength = wavelength # Store pixel size in mm detector.pixel_size.x = pixel_x detector.pixel_size.y = pixel_y # Store the sample to detector distance detector.distance = distance # optional data: if all of dq data == 0, do not pass to output if len(dqx_data) == len(qx_data) and dqx_data.any() != 0: # if no dqx_data, do not pass dqy_data. #(1 axis dq is not supported yet). if len(dqy_data) == len(qy_data) and dqy_data.any() != 0: # Currently we do not support dq parr, perp. # tranfer the comp. to cartesian coord. for newer version. if ver != 1: diag = numpy.sqrt(qx_data * qx_data + qy_data * qy_data) cos_th = qx_data / diag sin_th = qy_data / diag output.dqx_data = numpy.sqrt((dqx_data * cos_th) * \ (dqx_data * cos_th) \ + (dqy_data * sin_th) * \ (dqy_data * sin_th)) output.dqy_data = numpy.sqrt((dqx_data * sin_th) * \ (dqx_data * sin_th) \ + (dqy_data * cos_th) * \ (dqy_data * cos_th)) else: output.dqx_data = dqx_data output.dqy_data = dqy_data # Units of axes if data_conv_q is not None: output.xaxis("\\rm{Q_{x}}", output.Q_unit) output.yaxis("\\rm{Q_{y}}", output.Q_unit) else: output.xaxis("\\rm{Q_{x}}", 'A^{-1}') output.yaxis("\\rm{Q_{y}}", 'A^{-1}') if data_conv_i is not None: output.zaxis("\\rm{Intensity}", output.I_unit) else: output.zaxis("\\rm{Intensity}", "cm^{-1}") # Store loading process information output.meta_data['loader'] = self.type_name return output
def read(self, path): """ Load data file. :param path: file path :return: Data1D object, or None :raise RuntimeError: when the file can't be opened :raise ValueError: when the length of the data vectors are inconsistent """ if os.path.isfile(path): basename = os.path.basename(path) root, extension = os.path.splitext(basename) if extension.lower() in self.ext: try: input_f = open(path,'r') except: raise RuntimeError, "abs_reader: cannot open %s" % path buff = input_f.read() lines = buff.split('\n') x = numpy.zeros(0) y = numpy.zeros(0) dy = numpy.zeros(0) dx = numpy.zeros(0) output = Data1D(x, y, dy=dy, dx=dx) detector = Detector() output.detector.append(detector) output.filename = basename is_info = False is_center = False is_data_started = False data_conv_q = None data_conv_i = None if has_converter == True and output.x_unit != '1/A': data_conv_q = Converter('1/A') # Test it data_conv_q(1.0, output.x_unit) if has_converter == True and output.y_unit != '1/cm': data_conv_i = Converter('1/cm') # Test it data_conv_i(1.0, output.y_unit) for line in lines: # Information line 1 if is_info == True: is_info = False line_toks = line.split() # Wavelength in Angstrom try: value = float(line_toks[1]) if has_converter == True and \ output.source.wavelength_unit != 'A': conv = Converter('A') output.source.wavelength = conv(value, units=output.source.wavelength_unit) else: output.source.wavelength = value except: #goes to ASC reader msg = "abs_reader: cannot open %s" % path raise RuntimeError, msg # Distance in meters try: value = float(line_toks[3]) if has_converter == True and \ detector.distance_unit != 'm': conv = Converter('m') detector.distance = conv(value, units=detector.distance_unit) else: detector.distance = value except: #goes to ASC reader msg = "abs_reader: cannot open %s" % path raise RuntimeError, msg # Transmission try: output.sample.transmission = float(line_toks[4]) except: # Transmission is not a mandatory entry pass # Thickness in mm try: value = float(line_toks[5]) if has_converter == True and \ output.sample.thickness_unit != 'cm': conv = Converter('cm') output.sample.thickness = conv(value, units=output.sample.thickness_unit) else: output.sample.thickness = value except: # Thickness is not a mandatory entry pass #MON CNT LAMBDA DET ANG DET DIST TRANS THICK # AVE STEP if line.count("LAMBDA") > 0: is_info = True # Find center info line if is_center == True: is_center = False line_toks = line.split() # Center in bin number center_x = float(line_toks[0]) center_y = float(line_toks[1]) # Bin size if has_converter == True and \ detector.pixel_size_unit != 'mm': conv = Converter('mm') detector.pixel_size.x = conv(5.0, units=detector.pixel_size_unit) detector.pixel_size.y = conv(5.0, units=detector.pixel_size_unit) else: detector.pixel_size.x = 5.0 detector.pixel_size.y = 5.0 # Store beam center in distance units # Det 640 x 640 mm if has_converter == True and \ detector.beam_center_unit != 'mm': conv = Converter('mm') detector.beam_center.x = conv(center_x * 5.0, units=detector.beam_center_unit) detector.beam_center.y = conv(center_y * 5.0, units=detector.beam_center_unit) else: detector.beam_center.x = center_x * 5.0 detector.beam_center.y = center_y * 5.0 # Detector type try: detector.name = line_toks[7] except: # Detector name is not a mandatory entry pass #BCENT(X,Y) A1(mm) A2(mm) A1A2DIST(m) DL/L # BSTOP(mm) DET_TYP if line.count("BCENT") > 0: is_center = True # Parse the data if is_data_started == True: toks = line.split() try: _x = float(toks[0]) _y = float(toks[1]) _dy = float(toks[2]) _dx = float(toks[3]) if data_conv_q is not None: _x = data_conv_q(_x, units=output.x_unit) _dx = data_conv_i(_dx, units=output.x_unit) if data_conv_i is not None: _y = data_conv_i(_y, units=output.y_unit) _dy = data_conv_i(_dy, units=output.y_unit) x = numpy.append(x, _x) y = numpy.append(y, _y) dy = numpy.append(dy, _dy) dx = numpy.append(dx, _dx) except: # Could not read this data line. If we are here # it is because we are in the data section. Just # skip it. pass #The 6 columns are | Q (1/A) | I(Q) (1/cm) | std. dev. # I(Q) (1/cm) | sigmaQ | meanQ | ShadowFactor| if line.count("The 6 columns") > 0: is_data_started = True # Sanity check if not len(y) == len(dy): msg = "abs_reader: y and dy have different length" raise ValueError, msg # If the data length is zero, consider this as # though we were not able to read the file. if len(x) == 0: raise ValueError, "ascii_reader: could not load file" output.x = x[x != 0] output.y = y[x != 0] output.dy = dy[x != 0] output.dx = dx[x != 0] if data_conv_q is not None: output.xaxis("\\rm{Q}", output.x_unit) else: output.xaxis("\\rm{Q}", 'A^{-1}') if data_conv_i is not None: output.yaxis("\\rm{Intensity}", output.y_unit) else: output.yaxis("\\rm{Intensity}", "cm^{-1}") # Store loading process information output.meta_data['loader'] = self.type_name return output else: raise RuntimeError, "%s is not a file" % path return None
def get_file_contents(self): # Read file buf = self.readall() self.f_open.close() # Instantiate data object self.current_dataset = plottable_2D() self.current_datainfo = DataInfo() self.current_datainfo.filename = os.path.basename(self.f_open.name) self.current_datainfo.detector.append(Detector()) # Get content data_started = False ## Defaults lines = buf.split('\n') x = [] y = [] wavelength = None distance = None transmission = None pixel_x = None pixel_y = None is_info = False is_center = False # Remove the last lines before the for loop if the lines are empty # to calculate the exact number of data points count = 0 while (len(lines[len(lines) - (count + 1)].lstrip().rstrip()) < 1): del lines[len(lines) - (count + 1)] count = count + 1 #Read Header and find the dimensions of 2D data line_num = 0 # Old version NIST files: 0 ver = 0 for line in lines: line_num += 1 ## Reading the header applies only to IGOR/NIST 2D q_map data files # Find setup info line if is_info: is_info = False line_toks = line.split() # Wavelength in Angstrom try: wavelength = float(line_toks[1]) # Wavelength is stored in angstroms; convert if necessary if self.current_datainfo.source.wavelength_unit != 'A': conv = Converter('A') wavelength = conv( wavelength, units=self.current_datainfo.source.wavelength_unit) except Exception: pass # Not required try: distance = float(line_toks[3]) # Distance is stored in meters; convert if necessary if self.current_datainfo.detector[0].distance_unit != 'm': conv = Converter('m') distance = conv(distance, units=self.current_datainfo. detector[0].distance_unit) except Exception: pass # Not required try: transmission = float(line_toks[4]) except Exception: pass # Not required if line.count("LAMBDA") > 0: is_info = True # Find center info line if is_center: is_center = False line_toks = line.split() # Center in bin number center_x = float(line_toks[0]) center_y = float(line_toks[1]) if line.count("BCENT") > 0: is_center = True # Check version if line.count("Data columns") > 0: if line.count("err(I)") > 0: ver = 1 # Find data start if line.count("ASCII data") > 0: data_started = True continue ## Read and get data. if data_started: line_toks = line.split() if len(line_toks) == 0: #empty line continue # the number of columns must be stayed same col_num = len(line_toks) break # Make numpy array to remove header lines using index lines_array = np.array(lines) # index for lines_array lines_index = np.arange(len(lines)) # get the data lines data_lines = lines_array[lines_index >= (line_num - 1)] # Now we get the total number of rows (i.e., # of data points) row_num = len(data_lines) # make it as list again to control the separators data_list = " ".join(data_lines.tolist()) # split all data to one big list w/" "separator data_list = data_list.split() # Check if the size is consistent with data, otherwise #try the tab(\t) separator # (this may be removed once get the confidence #the former working all cases). if len(data_list) != (len(data_lines)) * col_num: data_list = "\t".join(data_lines.tolist()) data_list = data_list.split() # Change it(string) into float #data_list = map(float,data_list) data_list1 = list(map(check_point, data_list)) # numpy array form data_array = np.array(data_list1) # Redimesion based on the row_num and col_num, #otherwise raise an error. try: data_point = data_array.reshape(row_num, col_num).transpose() except Exception: msg = "red2d_reader can't read this file: Incorrect number of data points provided." raise FileContentsException(msg) ## Get the all data: Let's HARDcoding; Todo find better way # Defaults dqx_data = np.zeros(0) dqy_data = np.zeros(0) err_data = np.ones(row_num) qz_data = np.zeros(row_num) mask = np.ones(row_num, dtype=bool) # Get from the array qx_data = data_point[0] qy_data = data_point[1] data = data_point[2] if ver == 1: if col_num > (2 + ver): err_data = data_point[(2 + ver)] if col_num > (3 + ver): qz_data = data_point[(3 + ver)] if col_num > (4 + ver): dqx_data = data_point[(4 + ver)] if col_num > (5 + ver): dqy_data = data_point[(5 + ver)] # Column '6 + ver' is the shadow factor value. A separate mask column # was added to account for self-drawn masks. # if col_num > (6 + ver): mask[data_point[(6 + ver)] < 1] = False if col_num > (7 + ver): mask = np.invert(np.asarray(data_point[(7 + ver)], dtype=bool)) q_data = np.sqrt(qx_data * qx_data + qy_data * qy_data + qz_data * qz_data) # Store limits of the image in q space xmin = np.min(qx_data) xmax = np.max(qx_data) ymin = np.min(qy_data) ymax = np.max(qy_data) # Find unique Qx and Qy values for data binning and visualization # len(x_bins) * len(y_bins) ~= len(qx_data) ~= len(qy_data) x_bins = np.unique(qx_data) y_bins = np.unique(qy_data) # For non-uniform qx_data and/or qy_data # Cases: Rotated detectors, floating point variations if round(len(x_bins) * len(y_bins) / len(qx_data)) >= 2: # qx_data increases along rows => travel along a single pixel line num_qx = np.argmax(np.hstack((qx_data[1:] < qx_data[:-1], True))) x_bins = qx_data[:num_qx + 1] # qy_data increases along columns => transpose qx_data shape qy = np.reshape(qy_data, (len(qx_data) // len(x_bins), len(x_bins))) y_bins = np.transpose(qy)[0].tolist() # Store data in outputs self.current_dataset.data = data if (err_data == 1).all(): self.current_dataset.err_data = np.sqrt(np.abs(data)) self.current_dataset.err_data[self.current_dataset.err_data == 0.0] = 1.0 else: self.current_dataset.err_data = err_data self.current_dataset.qx_data = qx_data self.current_dataset.qy_data = qy_data self.current_dataset.q_data = q_data self.current_dataset.mask = mask self.current_dataset.x_bins = x_bins self.current_dataset.y_bins = y_bins self.current_dataset.xmin = xmin self.current_dataset.xmax = xmax self.current_dataset.ymin = ymin self.current_dataset.ymax = ymax self.current_datainfo.source.wavelength = wavelength # Store pixel size in mm self.current_datainfo.detector[0].pixel_size.x = pixel_x self.current_datainfo.detector[0].pixel_size.y = pixel_y # Store the sample to detector distance self.current_datainfo.detector[0].distance = distance # optional data: if all of dq data == 0, do not pass to output if len(dqx_data) == len(qx_data) and dqx_data.any() != 0: # if no dqx_data, do not pass dqy_data. # (1 axis dq is not supported yet). if len(dqy_data) == len(qy_data) and dqy_data.any() != 0: # Currently we do not support dq parr, perp. # transfer the comp. to cartesian coord. for newer version. if ver != 1: diag = np.sqrt(qx_data * qx_data + qy_data * qy_data) cos_th = qx_data / diag sin_th = qy_data / diag self.current_dataset.dqx_data = np.sqrt( (dqx_data * cos_th)**2 + (dqy_data * sin_th)**2) self.current_dataset.dqy_data = np.sqrt( (dqx_data * sin_th)**2 + (dqy_data * cos_th)**2) else: self.current_dataset.dqx_data = dqx_data self.current_dataset.dqy_data = dqy_data # Units of axes self.current_dataset = self.set_default_2d_units(self.current_dataset) # Store loading process information self.current_datainfo.meta_data['loader'] = self.type_name self.send_to_output()
def read(self, filename=None): """ Open and read the data in a file @param file: path of the file """ read_it = False for item in self.ext: if filename.lower().find(item) >= 0: read_it = True if read_it: try: datafile = open(filename, 'r') except: raise RuntimeError, "danse_reader cannot open %s" % (filename) # defaults # wavelength in Angstrom wavelength = 10.0 # Distance in meter distance = 11.0 # Pixel number of center in x center_x = 65 # Pixel number of center in y center_y = 65 # Pixel size [mm] pixel = 5.0 # Size in x, in pixels size_x = 128 # Size in y, in pixels size_y = 128 # Format version fversion = 1.0 output = Data2D() output.filename = os.path.basename(filename) detector = Detector() output.detector.append(detector) output.data = np.zeros([size_x, size_y]) output.err_data = np.zeros([size_x, size_y]) data_conv_q = None data_conv_i = None if has_converter == True and output.Q_unit != '1/A': data_conv_q = Converter('1/A') # Test it data_conv_q(1.0, output.Q_unit) if has_converter == True and output.I_unit != '1/cm': data_conv_i = Converter('1/cm') # Test it data_conv_i(1.0, output.I_unit) read_on = True while read_on: line = datafile.readline() if line.find("DATA:") >= 0: read_on = False break toks = line.split(':') if toks[0] == "FORMATVERSION": fversion = float(toks[1]) if toks[0] == "WAVELENGTH": wavelength = float(toks[1]) elif toks[0] == "DISTANCE": distance = float(toks[1]) elif toks[0] == "CENTER_X": center_x = float(toks[1]) elif toks[0] == "CENTER_Y": center_y = float(toks[1]) elif toks[0] == "PIXELSIZE": pixel = float(toks[1]) elif toks[0] == "SIZE_X": size_x = int(toks[1]) elif toks[0] == "SIZE_Y": size_y = int(toks[1]) # Read the data data = [] error = [] if fversion == 1.0: data_str = datafile.readline() data = data_str.split(' ') else: read_on = True while read_on: data_str = datafile.readline() if len(data_str) == 0: read_on = False else: toks = data_str.split() try: val = float(toks[0]) err = float(toks[1]) if data_conv_i is not None: val = data_conv_i(val, units=output._yunit) err = data_conv_i(err, units=output._yunit) data.append(val) error.append(err) except: logger.info("Skipping line:%s,%s" % (data_str, sys.exc_value)) # Initialize x_vals = [] y_vals = [] ymin = None ymax = None xmin = None xmax = None # Qx and Qy vectors theta = pixel / distance / 100.0 stepq = 4.0 * math.pi / wavelength * math.sin(theta / 2.0) for i_x in range(size_x): theta = (i_x - center_x + 1) * pixel / distance / 100.0 qx = 4.0 * math.pi / wavelength * math.sin(theta / 2.0) if has_converter == True and output.Q_unit != '1/A': qx = data_conv_q(qx, units=output.Q_unit) x_vals.append(qx) if xmin is None or qx < xmin: xmin = qx if xmax is None or qx > xmax: xmax = qx ymin = None ymax = None for i_y in range(size_y): theta = (i_y - center_y + 1) * pixel / distance / 100.0 qy = 4.0 * math.pi / wavelength * math.sin(theta / 2.0) if has_converter == True and output.Q_unit != '1/A': qy = data_conv_q(qy, units=output.Q_unit) y_vals.append(qy) if ymin is None or qy < ymin: ymin = qy if ymax is None or qy > ymax: ymax = qy # Store the data in the 2D array i_x = 0 i_y = -1 for i_pt in range(len(data)): try: value = float(data[i_pt]) except: # For version 1.0, the data were still # stored as strings at this point. msg = "Skipping entry (v1.0):%s,%s" % (str( data[i_pt]), sys.exc_value) logger.info(msg) # Get bin number if math.fmod(i_pt, size_x) == 0: i_x = 0 i_y += 1 else: i_x += 1 output.data[i_y][i_x] = value if fversion > 1.0: output.err_data[i_y][i_x] = error[i_pt] # Store all data # Store wavelength if has_converter == True and output.source.wavelength_unit != 'A': conv = Converter('A') wavelength = conv(wavelength, units=output.source.wavelength_unit) output.source.wavelength = wavelength # Store distance if has_converter == True and detector.distance_unit != 'm': conv = Converter('m') distance = conv(distance, units=detector.distance_unit) detector.distance = distance # Store pixel size if has_converter == True and detector.pixel_size_unit != 'mm': conv = Converter('mm') pixel = conv(pixel, units=detector.pixel_size_unit) detector.pixel_size.x = pixel detector.pixel_size.y = pixel # Store beam center in distance units detector.beam_center.x = center_x * pixel detector.beam_center.y = center_y * pixel # Store limits of the image (2D array) xmin = xmin - stepq / 2.0 xmax = xmax + stepq / 2.0 ymin = ymin - stepq / 2.0 ymax = ymax + stepq / 2.0 if has_converter == True and output.Q_unit != '1/A': xmin = data_conv_q(xmin, units=output.Q_unit) xmax = data_conv_q(xmax, units=output.Q_unit) ymin = data_conv_q(ymin, units=output.Q_unit) ymax = data_conv_q(ymax, units=output.Q_unit) output.xmin = xmin output.xmax = xmax output.ymin = ymin output.ymax = ymax # Store x and y axis bin centers output.x_bins = x_vals output.y_bins = y_vals # Units if data_conv_q is not None: output.xaxis("\\rm{Q_{x}}", output.Q_unit) output.yaxis("\\rm{Q_{y}}", output.Q_unit) else: output.xaxis("\\rm{Q_{x}}", 'A^{-1}') output.yaxis("\\rm{Q_{y}}", 'A^{-1}') if data_conv_i is not None: output.zaxis("\\rm{Intensity}", output.I_unit) else: output.zaxis("\\rm{Intensity}", "cm^{-1}") if not fversion >= 1.0: msg = "Danse_reader can't read this file %s" % filename raise ValueError, msg else: logger.info("Danse_reader Reading %s \n" % filename) # Store loading process information output.meta_data['loader'] = self.type_name output = reader2D_converter(output) return output return None
def get_file_contents(self): self.current_datainfo = DataInfo() self.current_dataset = plottable_2D() self.output = [] loaded_correctly = True error_message = "" # defaults # wavelength in Angstrom wavelength = 10.0 # Distance in meter distance = 11.0 # Pixel number of center in x center_x = 65 # Pixel number of center in y center_y = 65 # Pixel size [mm] pixel = 5.0 # Size in x, in pixels size_x = 128 # Size in y, in pixels size_y = 128 # Format version fversion = 1.0 self.current_datainfo.filename = os.path.basename(self.f_open.name) detector = Detector() self.current_datainfo.detector.append(detector) self.current_dataset.data = np.zeros([size_x, size_y]) self.current_dataset.err_data = np.zeros([size_x, size_y]) read_on = True data_start_line = 1 while read_on: line = self.nextline() data_start_line += 1 if line.find("DATA:") >= 0: read_on = False break toks = line.split(':') try: if toks[0] == "FORMATVERSION": fversion = float(toks[1]) elif toks[0] == "WAVELENGTH": wavelength = float(toks[1]) elif toks[0] == "DISTANCE": distance = float(toks[1]) elif toks[0] == "CENTER_X": center_x = float(toks[1]) elif toks[0] == "CENTER_Y": center_y = float(toks[1]) elif toks[0] == "PIXELSIZE": pixel = float(toks[1]) elif toks[0] == "SIZE_X": size_x = int(toks[1]) elif toks[0] == "SIZE_Y": size_y = int(toks[1]) except ValueError as e: error_message += "Unable to parse {}. Default value used.\n".format(toks[0]) loaded_correctly = False # Read the data data = [] error = [] if not fversion >= 1.0: msg = "danse_reader can't read this file {}".format(self.f_open.name) raise FileContentsException(msg) for line_num, data_str in enumerate(self.nextlines()): toks = data_str.split() try: val = float(toks[0]) err = float(toks[1]) data.append(val) error.append(err) except ValueError as exc: msg = "Unable to parse line {}: {}".format(line_num + data_start_line, data_str.strip()) raise FileContentsException(msg) num_pts = size_x * size_y if len(data) < num_pts: msg = "Not enough data points provided. Expected {} but got {}".format( size_x * size_y, len(data)) raise FileContentsException(msg) elif len(data) > num_pts: error_message += ("Too many data points provided. Expected {0} but" " got {1}. Only the first {0} will be used.\n").format(num_pts, len(data)) loaded_correctly = False data = data[:num_pts] error = error[:num_pts] # Qx and Qy vectors theta = pixel / distance / 100.0 i_x = np.arange(size_x) theta = (i_x - center_x + 1) * pixel / distance / 100.0 x_vals = 4.0 * np.pi / wavelength * np.sin(theta / 2.0) xmin = x_vals.min() xmax = x_vals.max() i_y = np.arange(size_y) theta = (i_y - center_y + 1) * pixel / distance / 100.0 y_vals = 4.0 * np.pi / wavelength * np.sin(theta / 2.0) ymin = y_vals.min() ymax = y_vals.max() self.current_dataset.data = np.array(data, dtype=np.float64).reshape((size_y, size_x)) if fversion > 1.0: self.current_dataset.err_data = np.array(error, dtype=np.float64).reshape((size_y, size_x)) # Store all data # Store wavelength if has_converter and self.current_datainfo.source.wavelength_unit != 'A': conv = Converter('A') wavelength = conv(wavelength, units=self.current_datainfo.source.wavelength_unit) self.current_datainfo.source.wavelength = wavelength # Store distance if has_converter and detector.distance_unit != 'm': conv = Converter('m') distance = conv(distance, units=detector.distance_unit) detector.distance = distance # Store pixel size if has_converter and detector.pixel_size_unit != 'mm': conv = Converter('mm') pixel = conv(pixel, units=detector.pixel_size_unit) detector.pixel_size.x = pixel detector.pixel_size.y = pixel # Store beam center in distance units detector.beam_center.x = center_x * pixel detector.beam_center.y = center_y * pixel self.current_dataset.xaxis("\\rm{Q_{x}}", 'A^{-1}') self.current_dataset.yaxis("\\rm{Q_{y}}", 'A^{-1}') self.current_dataset.zaxis("\\rm{Intensity}", "cm^{-1}") self.current_dataset.x_bins = x_vals self.current_dataset.y_bins = y_vals # Reshape data x_vals = np.tile(x_vals, (size_y, 1)).flatten() y_vals = np.tile(y_vals, (size_x, 1)).T.flatten() if (np.all(self.current_dataset.err_data == None) or np.any(self.current_dataset.err_data <= 0)): new_err_data = np.sqrt(np.abs(self.current_dataset.data)) else: new_err_data = self.current_dataset.err_data.flatten() self.current_dataset.err_data = new_err_data self.current_dataset.qx_data = x_vals self.current_dataset.qy_data = y_vals self.current_dataset.q_data = np.sqrt(x_vals**2 + y_vals**2) self.current_dataset.mask = np.ones(len(x_vals), dtype=bool) # Store loading process information self.current_datainfo.meta_data['loader'] = self.type_name self.send_to_output() if not loaded_correctly: raise DataReaderException(error_message)
def read(self, path): """ Load data file :param path: file path :return: Data1D object, or None :raise RuntimeError: when the file can't be opened :raise ValueError: when the length of the data vectors are inconsistent """ if os.path.isfile(path): basename = os.path.basename(path) root, extension = os.path.splitext(basename) if extension.lower() in self.ext: try: input_f = open(path,'r') except: raise RuntimeError, "hfir1d_reader: cannot open %s" % path buff = input_f.read() lines = buff.split('\n') x = numpy.zeros(0) y = numpy.zeros(0) dx = numpy.zeros(0) dy = numpy.zeros(0) output = Data1D(x, y, dx=dx, dy=dy) self.filename = output.filename = basename data_conv_q = None data_conv_i = None if has_converter == True and output.x_unit != '1/A': data_conv_q = Converter('1/A') # Test it data_conv_q(1.0, output.x_unit) if has_converter == True and output.y_unit != '1/cm': data_conv_i = Converter('1/cm') # Test it data_conv_i(1.0, output.y_unit) for line in lines: toks = line.split() try: _x = float(toks[0]) _y = float(toks[1]) _dx = float(toks[3]) _dy = float(toks[2]) if data_conv_q is not None: _x = data_conv_q(_x, units=output.x_unit) _dx = data_conv_q(_dx, units=output.x_unit) if data_conv_i is not None: _y = data_conv_i(_y, units=output.y_unit) _dy = data_conv_i(_dy, units=output.y_unit) x = numpy.append(x, _x) y = numpy.append(y, _y) dx = numpy.append(dx, _dx) dy = numpy.append(dy, _dy) except: # Couldn't parse this line, skip it pass # Sanity check if not len(y) == len(dy): msg = "hfir1d_reader: y and dy have different length" raise RuntimeError, msg if not len(x) == len(dx): msg = "hfir1d_reader: x and dx have different length" raise RuntimeError, msg # If the data length is zero, consider this as # though we were not able to read the file. if len(x) == 0: raise RuntimeError, "hfir1d_reader: could not load file" output.x = x output.y = y output.dy = dy output.dx = dx if data_conv_q is not None: output.xaxis("\\rm{Q}", output.x_unit) else: output.xaxis("\\rm{Q}", 'A^{-1}') if data_conv_i is not None: output.yaxis("\\rm{Intensity}", output.y_unit) else: output.yaxis("\\rm{Intensity}", "cm^{-1}") # Store loading process information output.meta_data['loader'] = self.type_name return output else: raise RuntimeError, "%s is not a file" % path return None
def read(self, filename=None): """ Read file """ if not os.path.isfile(filename): raise ValueError, \ "Specified file %s is not a regular file" % filename # Read file f = open(filename, 'r') buf = f.read() # Instantiate data object output = Data2D() output.filename = os.path.basename(filename) detector = Detector() if len(output.detector) > 0: print str(output.detector[0]) output.detector.append(detector) # Get content dataStarted = False lines = buf.split('\n') itot = 0 x = [] y = [] ncounts = 0 xmin = None xmax = None ymin = None ymax = None i_x = 0 i_y = -1 i_tot_row = 0 isInfo = False isCenter = False data_conv_q = None data_conv_i = None if has_converter == True and output.Q_unit != '1/A': data_conv_q = Converter('1/A') # Test it data_conv_q(1.0, output.Q_unit) if has_converter == True and output.I_unit != '1/cm': data_conv_i = Converter('1/cm') # Test it data_conv_i(1.0, output.I_unit) for line in lines: # Find setup info line if isInfo: isInfo = False line_toks = line.split() # Wavelength in Angstrom try: wavelength = float(line_toks[1]) except: msg = "IgorReader: can't read this file, missing wavelength" raise ValueError, msg #Find # of bins in a row assuming the detector is square. if dataStarted == True: try: value = float(line) except: # Found a non-float entry, skip it continue # Get total bin number i_tot_row += 1 i_tot_row = math.ceil(math.sqrt(i_tot_row)) - 1 #print "i_tot", i_tot_row size_x = i_tot_row # 192#128 size_y = i_tot_row # 192#128 output.data = numpy.zeros([size_x, size_y]) output.err_data = numpy.zeros([size_x, size_y]) #Read Header and 2D data for line in lines: # Find setup info line if isInfo: isInfo = False line_toks = line.split() # Wavelength in Angstrom try: wavelength = float(line_toks[1]) except: msg = "IgorReader: can't read this file, missing wavelength" raise ValueError, msg # Distance in meters try: distance = float(line_toks[3]) except: msg = "IgorReader: can't read this file, missing distance" raise ValueError, msg # Distance in meters try: transmission = float(line_toks[4]) except: msg = "IgorReader: can't read this file, " msg += "missing transmission" raise ValueError, msg if line.count("LAMBDA") > 0: isInfo = True # Find center info line if isCenter: isCenter = False line_toks = line.split() # Center in bin number: Must substrate 1 because #the index starts from 1 center_x = float(line_toks[0]) - 1 center_y = float(line_toks[1]) - 1 if line.count("BCENT") > 0: isCenter = True # Find data start if line.count("***")>0: dataStarted = True # Check that we have all the info if wavelength == None \ or distance == None \ or center_x == None \ or center_y == None: msg = "IgorReader:Missing information in data file" raise ValueError, msg if dataStarted == True: try: value = float(line) except: # Found a non-float entry, skip it continue # Get bin number if math.fmod(itot, i_tot_row) == 0: i_x = 0 i_y += 1 else: i_x += 1 output.data[i_y][i_x] = value ncounts += 1 # Det 640 x 640 mm # Q = 4pi/lambda sin(theta/2) # Bin size is 0.5 cm #REmoved +1 from theta = (i_x-center_x+1)*0.5 / distance # / 100.0 and #REmoved +1 from theta = (i_y-center_y+1)*0.5 / # distance / 100.0 #ToDo: Need complete check if the following # covert process is consistent with fitting.py. theta = (i_x - center_x) * 0.5 / distance / 100.0 qx = 4.0 * math.pi / wavelength * math.sin(theta/2.0) if has_converter == True and output.Q_unit != '1/A': qx = data_conv_q(qx, units=output.Q_unit) if xmin == None or qx < xmin: xmin = qx if xmax == None or qx > xmax: xmax = qx theta = (i_y - center_y) * 0.5 / distance / 100.0 qy = 4.0 * math.pi / wavelength * math.sin(theta / 2.0) if has_converter == True and output.Q_unit != '1/A': qy = data_conv_q(qy, units=output.Q_unit) if ymin == None or qy < ymin: ymin = qy if ymax == None or qy > ymax: ymax = qy if not qx in x: x.append(qx) if not qy in y: y.append(qy) itot += 1 theta = 0.25 / distance / 100.0 xstep = 4.0 * math.pi / wavelength * math.sin(theta / 2.0) theta = 0.25 / distance / 100.0 ystep = 4.0 * math.pi/ wavelength * math.sin(theta / 2.0) # Store all data ###################################### # Store wavelength if has_converter == True and output.source.wavelength_unit != 'A': conv = Converter('A') wavelength = conv(wavelength, units=output.source.wavelength_unit) output.source.wavelength = wavelength # Store distance if has_converter == True and detector.distance_unit != 'm': conv = Converter('m') distance = conv(distance, units=detector.distance_unit) detector.distance = distance # Store transmission output.sample.transmission = transmission # Store pixel size pixel = 5.0 if has_converter == True and detector.pixel_size_unit != 'mm': conv = Converter('mm') pixel = conv(pixel, units=detector.pixel_size_unit) detector.pixel_size.x = pixel detector.pixel_size.y = pixel # Store beam center in distance units detector.beam_center.x = center_x * pixel detector.beam_center.y = center_y * pixel # Store limits of the image (2D array) xmin = xmin - xstep / 2.0 xmax = xmax + xstep / 2.0 ymin = ymin - ystep / 2.0 ymax = ymax + ystep / 2.0 if has_converter == True and output.Q_unit != '1/A': xmin = data_conv_q(xmin, units=output.Q_unit) xmax = data_conv_q(xmax, units=output.Q_unit) ymin = data_conv_q(ymin, units=output.Q_unit) ymax = data_conv_q(ymax, units=output.Q_unit) output.xmin = xmin output.xmax = xmax output.ymin = ymin output.ymax = ymax # Store x and y axis bin centers output.x_bins = x output.y_bins = y # Units if data_conv_q is not None: output.xaxis("\\rm{Q_{x}}", output.Q_unit) output.yaxis("\\rm{Q_{y}}", output.Q_unit) else: output.xaxis("\\rm{Q_{x}}", 'A^{-1}') output.yaxis("\\rm{Q_{y}}", 'A^{-1}') if data_conv_i is not None: output.zaxis("\\rm{Intensity}", output.I_unit) else: output.zaxis("\\rm{Intensity}", "cm^{-1}") # Store loading process information output.meta_data['loader'] = self.type_name output = reader2D_converter(output) return output