def initialize_zoneplate_data(self, reset=False): """Initialize values for the zoneplate used as well as detector pixel size. Asks the user what the parameters of the zone plate are and detector pixel size. If they have been already set then the program displays the current values when setting up SXDMFrameset object Parameters ========== self (SXDMFrameset) the sxdmframset reset (bool) if True this allows the user to reset all values Returns ======= Nothing - sets values inside /zone_plate/ """ if reset == False: if h5path_exists(self.file, 'zone_plate/D_um') == False: D_um_val = input( 'What Is The Diameter Of The Zone Plate Used In Microns? (Typically 150)' ) h5create_dataset(self.file, 'zone_plate/D_um', D_um_val) else: print('Diameter Of The Zone Plate Is Set To {} microns'.format( h5grab_data(self.file, 'zone_plate/D_um'))) if h5path_exists(self.file, 'zone_plate/d_rN_nm') == False: d_rN_nm_val = input( 'What Is The Outer Most d Spacing Is ' 'For The Zone Plate Used In Nanometers? (Typically 20)') h5create_dataset(self.file, 'zone_plate/d_rN_nm', d_rN_nm_val) else: print('Outermost Zone Plate d Spacing Is Set To {} nanometers'. format(h5grab_data(self.file, 'zone_plate/d_rN_nm'))) if h5path_exists(self.file, 'zone_plate/detector_pixel_size') == False: detector_pixel_size_val = input( 'What Pixel Size Of The Detector In Microns? (Typically 15)') h5create_dataset(self.file, 'zone_plate/detector_pixel_size', detector_pixel_size_val) else: print( 'The Size Of Your Detector Pixels Is Set To {} microns'.format( h5grab_data(self.file, 'zone_plate/detector_pixel_size'))) elif reset == True: D_um_val = input( 'What Is The Diameter Of The Zone Plate Used In Microns? (Typically 150)' ) h5replace_data(self.file, 'zone_plate/D_um', D_um_val) d_rN_nm_val = input( 'What Is The Outer Most d Spacing Is For The Zone Plate Used In Nanometers? (Typically 20)' ) h5replace_data(self.file, 'zone_plate/d_rN_nm', d_rN_nm_val) detector_pixel_size_val = input( 'What Pixel Size Of The Detector In Microns? (Typically 15)') h5replace_data(self.file, 'zone_plate/detector_pixel_size', detector_pixel_size_val)
def max_det_val(self, detector='fluor'): """Used to determine the max values for a given detector channel Parameters ========== self (SXDMFrameset) the sxdmframeset detector (str) value to be passed into the return_det() function Returns ======= the max values for all scans for a given detector channel input """ if h5path_exists(self.file, 'detector_channels/' + detector) == True: data = return_det(self.file, self.scan_numbers, group=detector) max_array = [np.max(array) for array in data[0]] return max_array else: warnings.warng('Path Does Not Exist')
def save_alignment(event, self): """Allow the alignment click information to be saved to self.file Parameters ========== self (SXDMFrameset) the sxdmframeset object Returns ======= Nothing. It just stores /dxdy to the self.file as well as adding alingment_group and alignment_subgroup attributes """ # Try saving the data if h5path_exists(file=self.file, loc=self.dataset_name + '/dxdy') == False: h5create_dataset(file=self.file, ds_path=self.dataset_name + '/dxdy', ds_data=dic2array(self.dxdy_store)) h5set_attr(file=self.file, loc=self.dataset_name + '/dxdy', attribute_name='alignment_group', attribute_val=self.alignment_group) h5set_attr(file=self.file, loc=self.dataset_name + '/dxdy', attribute_name='alignment_subgroup', attribute_val=self.alignment_subgroup) else: # Try replacing the data try: h5replace_data(file=self.file, group=self.dataset_name + '/dxdy', data=dic2array(self.dxdy_store)) h5set_attr(file=self.file, loc=self.dataset_name + '/dxdy', attribute_name='alignment_group', attribute_val=self.alignment_group) h5set_attr(file=self.file, loc=self.dataset_name + '/dxdy', attribute_name='alignment_subgroup', attribute_val=self.alignment_subgroup) # Delete group and create a new dataset except Exception as ex: print('clicks.py/save_alignment', ex) print('Deleted Group') h5del_group(file=self.file, group=self.dataset_name + '/dxdy') h5create_dataset(file=self.file, ds_path=self.dataset_name + '/dxdy', ds_data=dic2array(self.dxdy_store)) h5set_attr(file=self.file, loc=self.dataset_name + '/dxdy', attribute_name='alignment_group', attribute_val=self.alignment_group) h5set_attr(file=self.file, loc=self.dataset_name + '/dxdy', attribute_name='alignment_subgroup', attribute_val=self.alignment_subgroup) print('Deleted Group 2')
def alignment_function(self): """Allows the user to align the scans based on Fluorescence or Region Of Interest. Sets alignment variables and stores them in designated .h5 file. Easier to reload alignment data or redo alignment data Parameters ========== self: (SXDMFrameset) the sxdmframeset object Returns ======= Nothing """ # Check to see if /dxdy group exsists if not make it and set attributes if h5path_exists(file=self.file, loc=self.dataset_name + '/dxdy') == True: warnings.warn('Previous Data Found') redo_alignment = input('Previous Data Found. Redo Alignment? y/n ') # Determining if User wants to reload or redo alignment if redo_alignment == 'y': start_alignment = 'y' try: self.alignment_group = h5read_attr( file=self.file, loc=self.dataset_name + '/dxdy', attribute_name='alignment_group') self.alignment_subgroup = h5read_attr( file=self.file, loc=self.dataset_name + '/dxdy', attribute_name='alignment_subgroup') except Exception as ex: print('alignment.py/alignment_function 1', ex) # If no redo and no start, save those choices else: start_alignment = 'n' redo_alignment = 'n' else: start_alignment = 'y' redo_alignment = 'n' # Initialize the alignment process if we are starting the alignment if start_alignment == 'y': if start_alignment == 'y' and redo_alignment == 'n': init_dxdy(self) else: try: # Try to pull previous alignment data - if you can't throw error to the user print('Previous Alignment Done On - {} - {}'.format( self.alignment_group, self.alignment_subgroup)) except Exception as ex: print('alignment.py/alignment_function 2', ex) # Grabbing old alignment and setting alignment circles retrieve_old_data = array2dic(array=h5grab_data( file=self.file, data_loc=self.dataset_name + '/dxdy')) warnings.warn('Refreshing Old Alignment Data') if len(retrieve_old_data.keys()) > len(self.scan_numbers): warnings.warn( 'Saved Alignment Has More Scans Than Current Import - Please Set reset=True' ) # Create variables to store data self.clicks = {} self.correction_store = {} plt.close('all') cont = True # Ask which images the user wants to align to while cont == True: user_val = input('Would You Like To Align On fluor Or roi? ') if user_val in ['fluor', 'roi']: cont = False else: warnings.warn('Please Type In An Acceptable Values: ') # Grab data and set alignment data det_return = return_det(file=self.file, scan_numbers=self.scan_numbers, group=user_val) # Setting up figure data images = det_return[0] self.alignment_subgroup = det_return[1] self.alignment_group = user_val self.max_images = np.shape(images)[0] starting = figure_size_finder(images=images) plt.close('all') # Setting up initial figure for alignment fig, axs = plt.subplots(starting, starting, figsize=(10, 10), facecolor='w', edgecolor='k') # Try to ravel axis - if data is 1D continue to the except code try: self.loc_axs = axs.ravel() except: warnings.warn( 'Ravel Function Not Called. Possible 1D Image Trying To Load') self.loc_axs = [axs] axs_store = [] # Set up saving, and click functions into partials saving = partial(save_alignment, self=self) initiate = partial(onclick_1, self=self) click1 = partial(fig1_click, self=self, fig=fig, images=images) # Display circles for alignment for i, image in enumerate(images): self.loc_axs[i].imshow(image) axs_store.append(self.loc_axs[i].get_position()) if redo_alignment == 'y': for num, old_ax in enumerate(retrieve_old_data): old_clicks = retrieve_old_data[old_ax] circ = Circle((old_clicks[0], old_clicks[1]), 0.3, color='r') self.loc_axs[old_ax].add_patch(circ) plt.suptitle('Please Click On Any Of The Images Below') plt.show() # Based on the Users clicks display different information fig.canvas.mpl_connect('button_press_event', initiate) fig.canvas.mpl_connect('button_press_event', click1) fig.canvas.mpl_connect('button_press_event', saving) elif redo_alignment == 'n': print('Staying With Current Alignment Parameters')
def return_chi_images_loc( file, chi_figures, detector_channel_loc='detector_channels/detector_scan/Main_Scan', zfill_num=4, ): """Grabs the image location for the detector sweep scan Parameters ========== file: (str) the .h5 file associated with the dataset chi_figures: (Chi_FigureClass) the Chi_FigureClass allowing transfer of data from figure to figure detector_channel_loc: (str) the h5 group location to the detector sweep scan used for chi bounds determination zfill_num: (int) the integer value for how many digits the scan number must have Returns ======= Nothing - sets the chi_figures.scan_theta and chi_figures.images_location valuess """ # Attempt to pull chi determination scan information try: # Grab the detector channel data scan = h5grab_data(file=file, data_loc=detector_channel_loc) scan_str = str(scan).zfill(zfill_num) # Grab the scans in the images and mda group im_loc = h5grab_data(file=file, data_loc='images/{}'.format(scan_str)) mda_loc = h5grab_data(file=file, data_loc='mda/{}'.format(scan_str)) # See if the images or mda group exsists im_check = h5path_exists(file=file, loc='images/{}'.format(scan_str)) mda_check = h5path_exists(file=file, loc='mda/{}'.format(scan_str)) # Formatting the image locations images_loc = ['images/{}/{}'.format(scan_str, loc) for loc in im_loc] chi_figures.images_location = images_loc # Based on what the user rocked to get the chi scan this will pull different values if chi_figures.user_rocking == 'spl': theta = return_det(file=file, scan_numbers=[scan_str], group='sample_theta') chi_figures.scan_theta = theta[0] elif chi_figures.user_rocking == 'det': det_find = 'D' + str( h5grab_data(file=file, data_loc='detector_channels/mis/2Theta')).zfill(2) theta = h5grab_data(file=file, data_loc='/mda/{}/{}'.format( scan_str, det_find)) sh = np.shape(theta) theta = np.reshape(theta, (1, sh[0] * sh[1]))[0] chi_figures.scan_theta = theta # Throw error if the program cannot pull info except Exception as ex: print('chi_determination.py/return_chi_images_loc', ex) warnings.warn( 'You Have Failed To Load In The Correct Detector Channel. ' 'Correct The detector_channel_loc or Import Correct Data') chi_figures.images_location = None # Throw error if the images or mda group does not exist if im_check == False or mda_check == False: warnings.warn( 'You Have Failed To Load In The Correct Detector Channel. ' 'Correct The detector_channel_loc or Import Correct Data ' 'im_check: {} - mda_check: {}'.format(im_check, mda_check)) chi_figures.images_location = None
def initialize_group(self): """ Initialized the group assigned by the user to the user defined file. From the scan numbers the program determines the scan_theta as well checking if identical settings have already been imported. If so the program reloads saved settings Parameters ========== self (SXDMFrameset) the sxdmframeset Returns ======= Nothing - sets /scan_numbers and /scan_theta """ # When .mda files are missing this function cannot import /scan_theta try: if h5path_exists(self.file, self.dataset_name) == False: # Creating groups and initializing their datasets h5create_group(self.file, self.dataset_name) scan_numbers = scan_num_convert(self.scan_numbers) h5create_dataset(self.file, self.dataset_name + '/scan_numbers', scan_numbers) h5create_dataset(self.file, self.dataset_name + '/scan_theta', np.asarray(self.scan_theta)) else: # Grabbing old data from stored datasets old_scan_nums = h5grab_data(self.file, self.dataset_name + '/scan_numbers') new_scan_nums = self.scan_numbers new_scan_nums = np.asarray(scan_num_convert(new_scan_nums)) print('Saved Scans: ' + str(old_scan_nums)) print('Current User Input: ' + str(new_scan_nums)) try: # See if an alignment data has already been set checker = self.dxdy_store except: try: # Try to grab old alignment data self.dxdy_store = grab_dxdy(self) except Exception as ex: warnings.warn('{} - Alignment Data Not Found'.format(ex)) # If the old scans equal the new scans tell the User if np.array_equal(old_scan_nums, new_scan_nums) == True: print('Importing Identical Scans. Reloading Saved Data...\n') # If they don't give them the option to delete the old group and start again else: user_val = input( 'New Scans Detected. Would You Like To Delete Current Group And Start Again? y/n ' ) if user_val == 'n': print('Importing Saved Scans...') elif user_val == 'y': print('Replacing - ' + self.dataset_name + ' - Group\n') scan_numbers = scan_num_convert(self.scan_numbers) try: h5del_group(self.file, self.dataset_name + '/scan_numbers') except: pass try: h5del_group(self.file, self.dataset_name + '/scan_theta') except: pass try: h5create_dataset(self.file, self.dataset_name + '/scan_numbers', scan_numbers) except: pass try: h5create_dataset(self.file, self.dataset_name + '/scan_theta', np.asarray(self.scan_theta)) except: pass except Exception as ex: print('preprocess.py/initialize_group', ex) warnings.warn( 'Cannot Initialize Group. Some .mda Files Might Be Missing...')
def import_mda(mda_path, hdf5_save_directory, hdf5_save_filename, single_file=False, maxdims=2): """Allows the User to import all .mda image and line scan data into an hdf5 format Parameters ========== mda_path (str) the string path to the folder holding the .mda files hdf5_save_directory (str) the path location where you would like to save your data to EXAMPLE: '/home/Desktop' hdf5_save_filename (str) the file inside that path in which you would like to save data to (DO NOT INCLUDE ".h5") EXAMPLE: 'test' single_file (str) the location of the file to import maxdims (int) the maximum dimensions for the readMDA function to import from the .mda file Returns ======= Nothing - Will Not Reimport Files """ unsucessful_import_files = [] reason_for_fail = [] file_path = '{}/{}.h5'.format(hdf5_save_directory, hdf5_save_filename) if single_file == False: file_locs, filenames = order_dir(mda_path) elif single_file: split_files = single_file.split('/') file_locs = [ single_file, ] filenames = [ split_files[-1], ] # Create a file path if it does not exists. if os.path.exists(file_path): pass else: h5create_file(loc=hdf5_save_directory, name=hdf5_save_filename) # For each .mda file in the directory scan through the detectors and import the data for i, file in tqdm(enumerate(file_locs)): file_name = filenames[i] current_scan_number_import = delimiter_func(string=file_name) try: output = readMDA(file, verbose=0, maxdim=maxdims) # Determining if it is 2D or 1D if len(output) == 3: source_data = output[2] if maxdims >= 3: xrf_data = output[3] flips = True elif len(output) == 2: source_data = output[1] if maxdims >= 3: xrf_data = output[2] flips = False elif len(output) == 4: source_data = output[2] if maxdims >= 3: xrf_data = output[3] flips = False else: warnings.warn( "Input Scan Dimensions Are Not 1D or 2D. Error In Importing Scan - {}" .format(current_scan_number_import)) for dats in source_data.d: detector_number = dats.number + 1 current_det_num = str(detector_number).zfill(2) save_path = 'mda/{}/D{}'.format(current_scan_number_import, current_det_num) # If the save path exsists don't bother saving it again if h5path_exists(file=file_path, loc=save_path): pass # All image data is flipped - unflip the 2D data else: raw_data2save = dats.data if flips: data2save = np.flip(np.flip(raw_data2save), axis=1) else: data2save = raw_data2save h5create_dataset(file=file_path, ds_path=save_path, ds_data=data2save) # XRF Importer Written By - Dr. Michael Stueckelberger if maxdims >= 3: # Save 3D data in h5 file for dats in xrf_data.d: detector_number = dats.number + 1 current_det_num = str(detector_number).zfill(2) save_path = 'xrf/{}/D{}'.format(current_scan_number_import, current_det_num) raw_data2save = dats.data if h5path_exists(file=file_path, loc=save_path): pass else: if flips: pass #data2save = np.flip(np.flip(raw_data2save), axis=1) #not yet clear how raw XRF data will be saved in that case ... skip for now else: data2save = raw_data2save h5create_dataset(file=file_path, ds_path=save_path, ds_data=data2save) # Save position data in h5 file data2save = output[2].p[0].data save_path = f'pos/{current_scan_number_import}/inner_hor' if h5path_exists(file=file_path, loc=save_path): pass else: h5create_dataset(file=file_path, ds_path=save_path, ds_data=data2save) data2save = output[1].p[0].data save_path = f'pos/{current_scan_number_import}/outer_hor' if h5path_exists(file=file_path, loc=save_path): pass else: h5create_dataset(file=file_path, ds_path=save_path, ds_data=data2save) except Exception as ex: unsucessful_import_files.append(file) reason_for_fail.append(ex) for idxs, f in enumerate(unsucessful_import_files): warnings.warn( f'Unable to Import File -- {f} -- because -- {reason_for_fail[idxs]}' )
def images_group_exsist(file, scan): """See if the images group exists. """ exists = h5path_exists(file=file, loc='images/{}'.format(scan))
def import_images(file, images_loc, scans=False, fill_num=4, import_type='uint32', delimiter_function=delimiter_func, force_reimport=False): """Allows the user to import all .tif images into the .h5 file Parameters ========== file (str) the user defined hdf5 file image_loc (str) the location of the images folder from the beamline scans (nd.array) the scans the user would like to import fill_num (int) the amount of numbers in the images folders names import_type (str) a string value passed into imageio.imread().astype(import_type) delimiter_function (function) a function which determines the image number. redefine this if 26 - ID -C naming scheme changes force_reimport (bool) set to True if you would like to force reimport images Returns ======= Nothing """ # Get a list of files in directory sorted_images_loc = sorted(os.listdir(images_loc)) if scans != False: pre_scans = [str(s) for s in scans] master_scan = [] for scan in pre_scans: if scan in sorted_images_loc: master_scan.append(scan) else: print('{} Scan Not Found - Not Imported'.format(scan)) sorted_images_loc = master_scan zfill_sorted_images_loc = zfill_scan(scan_list=sorted_images_loc, fill_num=fill_num) its = len(sorted_images_loc) # For each of the sorted image folders import all the images for i in tqdm(range(0, its)): folder = sorted_images_loc[i] directory = images_loc + '/' + folder if os.path.isdir(directory): im_loc, im_name = order_dir(path=directory) im_name = [ tif_separation(string=string, func=delimiter_function) for string in im_name ] path2exsist = '/images/{}'.format(zfill_sorted_images_loc[i]) # If the path already exists do not import the images again if h5path_exists(file, path2exsist) == True and force_reimport == False: print("Scan {} Already Imported. Will Not Continue. " "Force Reimport With force_reimport = True".format( sorted_images_loc[i])) # If the path already exists but the User wants to force reimport then reimport elif h5path_exists(file, path2exsist) == True and force_reimport == True: print("Deleting Scan {} And Reimporting".format( sorted_images_loc[i])) h5images_wra(file=file, scan=zfill_sorted_images_loc[i], im_loc=im_loc, im_name=im_name, delete=False, import_type=import_type) elif h5path_exists(file, path2exsist) == False: h5images_wra(file=file, scan=zfill_sorted_images_loc[i], im_loc=im_loc, im_name=im_name, delete=False, import_type=import_type)