def center_of_mass(image): threshold_value = filters.threshold_otsu(image) log.info(" *** *** threshold_value: %f" % (threshold_value)) labeled_foreground = (image < threshold_value).astype(int) properties = regionprops(labeled_foreground, image) return properties[0].weighted_centroid
def open_shutters(global_PVs, params): log.info(' ') log.info(' *** open_shutters') if TESTING: # Logger(variableDict['LogFileName']).info('\x1b[2;30;43m' + ' *** WARNING: testing mode - shutters are deactivated during the scans !!!!' + '\x1b[0m') log.warning( ' *** testing mode - shutters are deactivated during the scans !!!!' ) else: if params.station == '2-BM-A': # Use Shutter A if ShutterAisFast: global_PVs['ShutterAOpen'].put(1, wait=True) wait_pv(global_PVs['ShutterAMoveStatus'], ShutterAOpen_Value) time.sleep(3) global_PVs['FastShutter'].put(1, wait=True) time.sleep(1) log.info(' *** open_shutter fast: Done!') else: global_PVs['ShutterAOpen'].put(1, wait=True) wait_pv(global_PVs['ShutterAMoveStatus'], ShutterAOpen_Value) time.sleep(3) log.info(' *** open_shutter A: Done!') elif params.station == '2-BM-B': global_PVs['ShutterBOpen'].put(1, wait=True) wait_pv(global_PVs['ShutterB_Move_Status'], ShutterBOpen_Value) log.info(' *** open_shutter B: Done!')
def stop_scan(global_PVs, params): log.info(' ') log.error(' *** Stopping the scan: PLEASE WAIT') global_PVs['Motor_SampleRot_Stop'].put(1) global_PVs['HDF1_Capture'].put(0) aps2bm.wait_pv(global_PVs['HDF1_Capture'], 0) flir.init(global_PVs, params) log.error(' *** Stopping scan: Done!')
def _setup_hdf_writer(global_PVs, params, fname=None): if (params.camera_ioc_prefix == '2bmbPG3:') or (params.camera_ioc_prefix == '2bmbSP1:'): # setup Point Grey hdf writer PV's log.info(' ') log.info(' *** setup hdf_writer') _setup_frame_type(global_PVs, params) if params.recursive_filter == True: log.info(' *** Recursive Filter Enabled') global_PVs['Proc1_Enable_Background'].put('Disable', wait=True) global_PVs['Proc1_Enable_FlatField'].put('Disable', wait=True) global_PVs['Proc1_Enable_Offset_Scale'].put('Disable', wait=True) global_PVs['Proc1_Enable_Low_Clip'].put('Disable', wait=True) global_PVs['Proc1_Enable_High_Clip'].put('Disable', wait=True) global_PVs['Proc1_Callbacks'].put('Enable', wait=True) global_PVs['Proc1_Filter_Enable'].put('Enable', wait=True) global_PVs['HDF1_ArrayPort'].put('PROC1', wait=True) global_PVs['Proc1_Filter_Type'].put(Recursive_Filter_Type, wait=True) global_PVs['Proc1_Num_Filter'].put(int( params.recursive_filter_n_images), wait=True) global_PVs['Proc1_Reset_Filter'].put(1, wait=True) global_PVs['Proc1_AutoReset_Filter'].put('Yes', wait=True) global_PVs['Proc1_Filter_Callbacks'].put('Array N only', wait=True) log.info(' *** Recursive Filter Enabled: Done!') else: global_PVs['Proc1_Filter_Enable'].put('Disable') global_PVs['HDF1_ArrayPort'].put( global_PVs['Proc1_ArrayPort'].get()) global_PVs['HDF1_AutoSave'].put('Yes') global_PVs['HDF1_DeleteDriverFile'].put('No') global_PVs['HDF1_EnableCallbacks'].put('Enable') global_PVs['HDF1_BlockingCallbacks'].put('No') # if (params.recursive_filter == False): # params.recursive_filter_n_images = 1 totalProj = ((int(params.num_projections / params.recursive_filter_n_images)) + int(params.num_dark_images) + \ int(params.num_white_images)) global_PVs['HDF1_NumCapture'].put(totalProj) global_PVs['HDF1_FileWriteMode'].put(str(params.file_write_mode), wait=True) if fname is not None: global_PVs['HDF1_FileName'].put(str(fname), wait=True) global_PVs['HDF1_Capture'].put(1) aps2bm.wait_pv(global_PVs['HDF1_Capture'], 1) log.info(' *** setup hdf_writer: Done!') else: log.error('Detector %s is not defined' % params.camera_ioc_prefix) return
def create_remote_directory(remote_server, remote_dir): cmd = 'mkdir -p ' + remote_dir try: # log.info(' *** sending command %s' % (cmd)) log.info(' *** creating remote directory %s' % (remote_dir)) subprocess.check_call(['ssh', remote_server, cmd]) log.info(' *** creating remote directory %s: Done!' % (remote_dir)) return 0 except subprocess.CalledProcessError as e: log.error(' *** Error while creating remote directory. Error code: %d' % (e.returncode)) return -1
def write_hdf(args=None, sections=None): """ Write in the hdf raw data file the content of *config_file* with values from *args* if they are specified, otherwise use the defaults. If *sections* are specified, write values from *args* only to those sections, use the defaults on the remaining ones. """ if (args == None): log.warning(" *** Not saving log data to the HDF file.") else: hdf_fname = args.file_path + os.sep + args.file_name + '.h5' with h5py.File(hdf_fname, 'r+') as hdf_file: #If the group we will write to already exists, remove it if hdf_file.get('/process/acquisition/tomo-scan-2bm-' + __version__): del (hdf_file['/process/acquisition/tomo-scan-2bm-' + __version__]) #dt = h5py.string_dtype(encoding='ascii') log.info( " *** tomopy.conf parameter written to /process/acquisition/tomo-scan-2bm-%s in file %s " % (__version__, args.file_name)) config = configparser.ConfigParser() for section in SECTIONS: config.add_section(section) for name, opts in SECTIONS[section].items(): if args and sections and section in sections and hasattr( args, name.replace('-', '_')): value = getattr(args, name.replace('-', '_')) if isinstance(value, list): # print(type(value), value) value = ', '.join(value) else: value = opts['default'] if opts[ 'default'] is not None else '' prefix = '# ' if value is '' else '' if name != 'config': dataset = '/process' + '/acquisition/tomo-scan-2bm-' + __version__ + '/' + section + '/' + name dset_length = len(str(value)) * 2 if len( str(value)) > 5 else 10 dt = 'S{0:d}'.format(dset_length) hdf_file.require_dataset(dataset, shape=(1, ), dtype=dt) log.info(name + ': ' + str(value)) try: hdf_file[dataset][0] = np.string_(str(value)) except TypeError: print(value) raise TypeError
def check_center(params, white_field, dark_field): global_PVs = aps2bm.init_general_PVs(params) log.warning(' *** CHECK center of mass for the centered sphere') log.info(' *** moving rotary stage to %f deg position ***' % float(0)) global_PVs["Motor_SampleRot"].put(float(0), wait=True, timeout=600.0) log.info(' *** acquire sphere at %f deg position ***' % float(0)) sphere_0 = util.normalize(flir.take_image(global_PVs, params), white_field, dark_field) cmass_0 = util.center_of_mass(sphere_0) log.warning( ' *** center of mass for the centered sphere at 0 deg: [%f,%f] ***' % (cmass_0[1], cmass_0[0]))
def update_config(args): # update tomo2bm.conf sections = SCAN_PARAMS write(args.config, args=args, sections=sections) # copy tomo2bm.conf to the raw data directory with a unique name (sample_name.conf) log_fname = args.file_path + os.sep + args.file_name + '.conf' try: shutil.copyfile(args.config, log_fname) log.info(' *** copied %s to %s ' % (args.config, log_fname)) except: log.error(' *** attempt to copy %s to %s failed' % (args.config, log_fname)) pass log.warning( ' *** command to repeat the scan: tomo scan --config {:s}'.format( log_fname)) if (args.dx_update): write_hdf(args, sections)
def normalize(arr, flat, dark, cutoff=None, out=None): """ Normalize raw projection data using the flat and dark field projections. Parameters ---------- arr : ndarray 2D of projections. flat : ndarray 2D flat field data. dark : ndarray 2D dark field data. cutoff : float, optional Permitted maximum vaue for the normalized data. out : ndarray, optional Output array for result. If same as arr, process will be done in-place. Returns ------- ndarray Normalized 2D tomographic data. """ arr = as_float32(arr) l = np.float32(1e-5) log.info(' *** *** image size: [%d, %d]' % (flat.shape[0], flat.shape[1])) # flat = np.mean(flat, axis=0, dtype=np.float32) # dark = np.mean(dark, axis=0, dtype=np.float32) flat = flat.astype('float32') dark = dark.astype('float32') denom = ne.evaluate('flat') # denom = ne.evaluate('flat-dark') ne.evaluate('where(denom<l,l,denom)', out=denom) out = ne.evaluate('arr', out=out) # out = ne.evaluate('arr-dark', out=out) ne.evaluate('out/denom', out=out, truediv=True) if cutoff is not None: cutoff = np.float32(cutoff) ne.evaluate('where(out>cutoff,cutoff,out)', out=out) return out
def acquire_flat(global_PVs, params): log.info(' *** White Fields') global_PVs['Cam1_ImageMode'].put('Multiple') global_PVs['Cam1_FrameType'].put(FrameTypeWhite) if (params.camera_ioc_prefix == '2bmbPG3:'): global_PVs['Cam1_TriggerMode'].put('Overlapped') elif (params.camera_ioc_prefix == '2bmbSP1:'): global_PVs['Cam1_TriggerMode'].put('Off', wait=True) # Set detectors if (params.camera_ioc_prefix == '2bmbPG3:'): wait_time_sec = int(params.exposure_time) + 5 global_PVs['Cam1_NumImages'].put(1) for i in range( int(params.num_white_images) * params.recursive_filter_n_images): global_PVs['Cam1_Acquire'].put(DetectorAcquire) time.sleep(0.1) aps2bm.wait_pv(global_PVs['Cam1_Acquire'], DetectorAcquire, 2) time.sleep(0.1) global_PVs['Cam1_SoftwareTrigger'].put(1, wait=True) time.sleep(0.1) aps2bm.wait_pv(global_PVs['Cam1_Acquire'], DetectorIdle, wait_time_sec) time.sleep(0.1) elif (params.camera_ioc_prefix == '2bmbSP1:'): wait_time_sec = float(params.num_white_images) * float( params.exposure_time) + 60.0 global_PVs['Cam1_NumImages'].put(int(params.num_white_images)) global_PVs['Cam1_Acquire'].put(DetectorAcquire, wait=True, timeout=5.0) # it was 1000.0 # time.sleep(0.1) if aps2bm.wait_pv(global_PVs['Cam1_Acquire'], DetectorIdle, wait_time_sec) == False: # adjust wait time global_PVs['Cam1_Acquire'].put(DetectorIdle) log.info(' *** White Fields: Done!')
def log_values(args): """Log all values set in the args namespace. Arguments are grouped according to their section and logged alphabetically using the DEBUG log level thus --verbose is required. """ args = args.__dict__ log.warning('tomo scan status start') for section, name in zip(SECTIONS, NICE_NAMES): entries = sorted((k for k in args.keys() if k.replace('_', '-') in SECTIONS[section])) # print('log_values', section, name, entries) if entries: log.info(name) for entry in entries: value = args[entry] if args[entry] is not None else "-" log.info(" {:<16} {}".format(entry, value)) log.warning('tomo scan status end')
def tomo_fly_scan(global_PVs, params): log.info(' ') log.info(' *** start_scan') def cleanup(signal, frame): stop_scan(global_PVs, params) sys.exit(0) signal.signal(signal.SIGINT, cleanup) # if params.has_key('StopTheScan'): # stop_scan(global_PVs, params) # return # moved to outer loop in main() # init(global_PVs, params) set_image_factor(global_PVs, params) rotation_start = params.sample_rotation_start rotation_end = params.sample_rotation_end if ((params.reverse == 'True') and ((params.scan_counter % 2) == 1)): params.sample_rotation_start = rotation_end params.sample_rotation_end = rotation_start aps2bm.set_pso(global_PVs, params) # fname = global_PVs['HDF1_FileName'].get(as_string=True) log.info(' *** File name prefix: %s' % params.file_name) flir.set(global_PVs, params) aps2bm.open_shutters(global_PVs, params) aps2bm.move_sample_in(global_PVs, params) theta = flir.acquire(global_PVs, params) if ((params.reverse == 'True') and ((params.scan_counter % 2) == 1)): params.sample_rotation_start = rotation_start params.sample_rotation_end = rotation_end theta_end = global_PVs['Motor_SampleRot_RBV'].get() if (0 < theta_end < 180.0): # print('\x1b[2;30;41m' + ' *** Rotary Stage ERROR. Theta stopped at: ***' + theta_end + '\x1b[0m') log.error(' *** Rotary Stage ERROR. Theta stopped at: %s ***' % str(theta_end)) aps2bm.move_sample_out(global_PVs, params) flir.acquire_flat(global_PVs, params) aps2bm.move_sample_in(global_PVs, params) aps2bm.close_shutters(global_PVs, params) time.sleep(2) flir.acquire_dark(global_PVs, params) flir.checkclose_hdf(global_PVs, params) flir.add_theta(global_PVs, params, theta) # update config file config.update_config(params)
def adjust(params): global_PVs = aps2bm.init_general_PVs(params) params.file_name = None # so we don't run the flir._setup_hdf_writer try: detector_sn = global_PVs['Cam1_SerialNumber'].get() if ((detector_sn == None) or (detector_sn == 'Unknown')): log.info( '*** The Point Grey Camera with EPICS IOC prefix %s is down' % params.camera_ioc_prefix) log.info(' *** Failed!') else: log.info('*** The Point Grey Camera with EPICS IOC prefix %s and serial number %s is on' \ % (params.camera_ioc_prefix, detector_sn)) flir.init(global_PVs, params) flir.set(global_PVs, params) dark_field, white_field = flir.take_dark_and_white( global_PVs, params) if (params.resolution == True): find_resolution(params, dark_field, white_field, angle_shift=-0.7) if (params.image_resolution == None): log.error( ' *** Detector resolution is not determined. Please run tomo adjust --resolution first!' ) exit() else: if (params.focus == True): adjust_focus(params) if (params.center == True): adjust_center(params, dark_field, white_field) if (params.roll == True): adjust_roll(params, dark_field, white_field, angle_shift=-0.7) if (params.pitch == True): adjust_pitch(params, dark_field, white_field, angle_shift=-0.7) if (params.roll == True or params.pitch == True): # align center again for higher accuracy adjust_center(params, dark_field, white_field) config.update_sphere(params) except KeyError: log.error(' *** Some PV assignment failed!') pass
def move_sample_in(global_PVs, params): log.info(' *** Sample in') if not (params.sample_move_freeze): if (params.flat_field_axis == "vertical"): log.info(' *** *** Move Sample Y in at: %f' % params.sample_in_y) global_PVs['SampleY'].put(str(params.sample_in_y), wait=True, timeout=1000.0) if wait_pv(global_PVs['SampleY'], float(params.sample_in_y), 60) == False: log.error('SampleY did not move in properly') log.error(global_PVs['SampleY'].get()) else: log.info(' *** *** Move Sample X in at: %f' % params.sample_in_x) global_PVs['SampleX'].put(str(params.sample_in_x), wait=True, timeout=1000.0) if wait_pv(global_PVs['SampleX'], float(params.sample_in_x), 60) == False: log.error('SampleX did not move in properly') log.error(global_PVs['SampleX'].get()) if (params.use_furnace): log.info(' *** *** Move Furnace Y in at: %f' % params.furnace_in_position) global_PVs['Motor_FurnaceY'].put(str( params.furnace_in_position), wait=True, timeout=1000.0) if wait_pv(global_PVs['Motor_FurnaceY'], float(params.furnace_in_position), 60) == False: log.error('Motor_FurnaceY did not move in properly') log.error(global_PVs['Motor_FurnaceY'].get()) else: log.info(' *** *** Sample Stack is Frozen')
def adjust_focus(params): global_PVs = aps2bm.init_general_PVs(params) step = 1 direction = 1 max_std = 0 three_std = np.ones(3) * 2**16 cnt = 0 decrease_step = False while (step > 0.01): initpos = global_PVs['Motor_Focus'].get() curpos = initpos + step * direction global_PVs['Motor_Focus'].put(curpos, wait=True, timeout=600.0) img = flir.take_image(global_PVs, params) cur_std = np.std(img) log.info(' *** *** Positon: %f Standard deviation: %f ' % (curpos, cur_std)) if (cur_std > max_std): # store max std max_std = cur_std three_std[np.mod(cnt, 3)] = cur_std # store std for 3 last measurements if (np.sum(three_std < max_std) == 3): # pass a peak direction = -direction if (decrease_step): # decrease focusing motor step step /= 2 else: #do not decrease step for the first direction change decrease_step = True three_std = np.ones(3) * 2**16 max_std = 0 log.warning(' *** change direction and step to %f' % (step)) cnt += 1 log.warning(' *** Focusing done') return
def close_shutters(global_PVs, params): log.info(' ') log.info(' *** close_shutters') if TESTING: log.warning(' *** testing mode - shutters are deactivated during the scans !!!!') else: global_PVs['ShutterA_Close'].put(1, wait=True) wait_pv(global_PVs['ShutterA_Move_Status'], ShutterA_Close_Value) log.info(' *** close_shutter A: Done!')
def dummy_scan(params): tic = time.time() global_PVs = aps2bm.init_general_PVs(params) aps2bm.user_info_params_update_from_pv(global_PVs, params) try: detector_sn = global_PVs['Cam1_SerialNumber'].get() if ((detector_sn == None) or (detector_sn == 'Unknown')): log.info('*** The Point Grey Camera with EPICS IOC prefix %s is down' % params.camera_ioc_prefix) log.info(' *** Failed!') else: log.info('*** The Point Grey Camera with EPICS IOC prefix %s and serial number %s is on' \ % (params.camera_ioc_prefix, detector_sn)) except KeyError: log.error(' *** Some PV assignment failed!') pass
def move_center(params, cmass_0, x, y): global_PVs = pv.init_general_PVs(params) log.info(' *** moving sample top X to the rotation center ***') global_PVs["SampleXCent"].put(global_PVs["SampleXCent"].get() + x * params.image_pixel_size / 1000, wait=True, timeout=5.0) log.info(' *** moving sample top Z to the rotation center ***') global_PVs["SampleZCent"].put(global_PVs["SampleZCent"].get() + y * params.image_pixel_size / 1000, wait=True, timeout=5.0) log.info(' *** moving rotation center to the detector center ***') global_PVs["SampleX"].put( global_PVs["SampleX"].get() - (cmass_0[1] - x - global_PVs['Cam1SizeX'].get() / 2) * params.image_pixel_size / 1000, wait=True, timeout=600.0)
def move_center(params, cmass_0, x, y): global_PVs = aps2bm.init_general_PVs(params) log.info(' *** moving sample top X to the rotation center ***') global_PVs["Motor_Sample_Top_0"].put( global_PVs["Motor_Sample_Top_0"].get() + x * params.image_resolution / 1000, wait=True, timeout=5.0) log.info(' *** moving sample top Z to the rotation center ***') global_PVs["Motor_Sample_Top_90"].put( global_PVs["Motor_Sample_Top_90"].get() + y * params.image_resolution / 1000, wait=True, timeout=5.0) log.info(' *** moving rotation center to the detector center ***') global_PVs["Motor_SampleX"].put( global_PVs["Motor_SampleX"].get() - (cmass_0[1] - x - global_PVs['Cam1_SizeX'].get() / 2) * params.image_resolution / 1000, wait=True, timeout=600.0)