示例#1
0
 def _object_parser(self, input_obj, expect_yml_type):
     '''a priviate parser for arbitrary object input
     '''
     FEXT = '.yml'
     e_msg_str_type = '''Can't find your "{} object {}". Please do bt.list() to make sure you type right name'''.format(expect_yml_type, input_obj)
     e_msg_ind_type = '''Can't find object with index {}. Please do bt.list() to make sure you type correct index'''.format(input_obj)
     if isinstance(input_obj, str):
         yml_list = _get_yaml_list()
         # note: el.split('_', maxsplit=1) = (yml_type, yml_name)
         yml_name_found = [el for el in yml_list if el.split('_', maxsplit=1)[0] == expect_yml_type
                         and el.split('_', maxsplit=1)[1] == input_obj+FEXT]
         if yml_name_found:
             with open(os.path.join(glbl.yaml_dir, yml_name_found[-1]), 'r') as f_out:
                 output_obj = yaml.load(f_out)
             return output_obj
         else:
             # if still can't find it after going over entire list
             sys.exit(_graceful_exit(e_msg_str_type))
     elif isinstance(input_obj, int):
         try:
             output_obj = self.get(input_obj)
             return output_obj
         except IndexError:
             sys.exit(_graceful_exit(e_msg_ind_type))
     else:
         # let xpdAcq object validator deal with other cases
         return input_obj
示例#2
0
def _clean_name(name,max_length=25):
    '''strips a string, but also removes internal whitespace
    '''
    if not isinstance(name,str):
        sys.exit(_graceful_exit('Your input, {}, appears not to be a string. Please try again'.format(str(name))))
    cleaned = "".join(name.split())
    if len(cleaned) > max_length:
        sys.exit(_graceful_exit('Please try a name for your object that is < {} characters long'.format(str(max_length))))
    return cleaned
示例#3
0
    def _scanplan_name_parser(self, sp_name):
        ''' function to parse name of ScanPlan object into parameters fed into ScanPlan

        expected format for each type is following:
        1) 'ct_10' means Count scan with 10s exposure time in total
        2) 'Tramp_10_300_200_5' means temperature ramp from 300k to 200k with 5k step and 10s exposure time each
        3) 'tseries_10_60_5' means time series scan of 10s exposure time each scan 
            and run for 5 scans with 60s delay between them.
        '''
        _ct_required_params = ['exposure']
        _tseries_required_params = ['exposure', 'delay', 'num']
        _Tramp_required_params = ['exposure', 'startingT', 'endingT', 'Tstep']

        _ct_optional_params = ['det','subs_dict']
        _Tramp_optional_params = ['det', 'subs_dict']
        _tseries_optional_params = ['det', 'subs_dict']

        parsed_object = sp_name.split('_') # it will split recursively
        scanplan_type = parsed_object[0]
        # turn parameters into floats
        _sp_params = []
        for i in range(1, len(parsed_object)):
            try:
                _sp_params.append(float(parsed_object[i]))
            except ValueError:
                sys.exit(_graceful_exit('''xpdAcq can not parse your positional argument "{}".
                We use SI units across package, so "5s" or "10k" is not necessary.
                For more information, please go to
                http://xpdacq.github.io.\n'''.format(parsed_object[i])))
                return
        # assgin exposure as it is common parameter
        exposure = _sp_params[0]
        sp_params = {'exposure':exposure}
        if scanplan_type not in glbl._allowed_scanplan_type:
            sys.exit(_graceful_exit('''{} is not a supported ScanPlan type under current version of xpdAcq.
                                    Current supported type are {}.
                                    Please go to http://xpdacq.github.io for more information or request
                                    '''.format(scanplan_type, glbl._allowed_scanplan_type)))
        if scanplan_type == 'ct' and len(_sp_params) == 1: # exposure
            return (scanplan_type, sp_params)
        elif scanplan_type == 'Tramp' and len(_sp_params) == 4: # exposure, startingT, endingT, Tstep
            sp_params.update({'startingT': _sp_params[1], 'endingT': _sp_params[2], 'Tstep': _sp_params[3]})
            return (scanplan_type, sp_params)
        elif scanplan_type == 'tseries' and len(_sp_params) == 3: # exposure, delay, num
            sp_params.update({'delay': _sp_params[1], 'num': int(_sp_params[2])})
            return (scanplan_type, sp_params)
        elif scanplan_type == 'bluesky':
            # leave a hook for future bluesky plan autonaming
            pass
        else:
            sys.exit(_graceful_exit('''xpdAcq can't parse your scanplan name {} into corresponding parameters.
                                    Please do ``ScanPlan?`` to find out currently supported conventions.
                                    or you can define your scanplan parameter dictionary explicitly.
                                    For more information, go to http://xpdacq.github.io
                                    '''.format(sp_name)))
示例#4
0
def _check_empty_environment(base_dir=None):
    if base_dir is None:
        base_dir = glbl.base
    if os.path.exists(home_dir):
        if not os.path.isdir(home_dir):
            sys.exit(_graceful_exit("Expected a folder, got a file.  "
                               "Please Talk to beamline staff"))
        files = os.listdir(home_dir) # that also list dirs that have been created
        if len(files) > 0:
            sys.exit(_graceful_exit("Unexpected files in {}, you need to run _end_beamtime(). Please Talk to beamline staff".format(home_dir)))
    else:
        sys.exit(_graceful_exit("The xpdUser directory appears not to exist "
                               "Please Talk to beamline staff"))
示例#5
0
def _confirm_archive(archive_f_name):
    print("tarball archived to {}".format(archive_f_name))
    conf = _any_input_method(_get_user_confirmation)
    if conf in ('y','Y'):
        return
    else:
        sys.exit(_graceful_exit('xpdUser directory delete operation cancelled at Users request'))
示例#6
0
def _load_bt(bt_yaml_path):
    btoname = os.path.join(glbl.yaml_dir,'bt_bt.yml')
    if not os.path.isfile(btoname):
        sys.exit(_graceful_exit('''{} does not exist in {}. User might have deleted it accidentally.
Please create it based on user information or contect user'''.format(os.path.basename(btoname), glbl.yaml_dir)))
    with open(btoname, 'r') as fi:
        bto = yaml.load(fi)
    return bto
示例#7
0
def _read_dark_yaml():
    dark_yaml_name = glbl.dk_yaml
    try:
        with open(dark_yaml_name, 'r') as f:
            dark_scan_list = yaml.load(f)
        return dark_scan_list
    except FileNotFoundError:
        sys.exit(_graceful_exit('''It seems you haven't initiated your beamtime.
                Please run _start_beamtime(<your SAF number>) or contact beamline scientist'''))
示例#8
0
def _start_beamtime(safn, home_dir=None):
    ''' priviate function for beamline scientist
    
    This function will start a beamtime for user 
    It does following:
    1) checks if previous beamtime is properly ended.
    2) create default directories
    3) instantiate a bt object with information encoded in saf<saf_num>.yml file 
    4) instantiate lazy user Sample, ScanPlan objects
    
    Parameters:
    -----------
    safn : str
        string to saf number of current beamtime. 
        This function requires to have a `saf<saf_num>.yml' in xpdUser/config_base
    '''
    if home_dir is None:
        home_dir = glbl.home
    if not os.path.exists(home_dir):
        os.makedirs(home_dir)
    _check_empty_environment()
    configfile = os.path.join(glbl.xpdconfig, 'saf{}.yml'.format(str(safn)))
    if os.path.isfile(configfile):
        with open(configfile, 'r') as fin:
            setup_dict = yaml.load(fin)
    else:
        sys.exit(
            _graceful_exit(
                'the saf config file {} appears to be missing'.format(
                    configfile)))
    try:
        piname = setup_dict['PI last name']
        safn = setup_dict['saf number']
        explist = setup_dict['experimenter list']
    except KeyError:
        sys.exit(
            _graceful_exit(
                'Cannot load input info. File syntax in {} maybe corrupted.'.
                format(configfile)))
    bt = _execute_start_beamtime(piname, safn, explist, home_dir=home_dir)
    _init_dark_yaml()

    return bt
示例#9
0
def _confirm_archive(archive_f_name):
    print("tarball archived to {}".format(archive_f_name))
    conf = _any_input_method(_get_user_confirmation)
    if conf in ('y', 'Y'):
        return
    else:
        sys.exit(
            _graceful_exit(
                'xpdUser directory delete operation cancelled at Users request'
            ))
示例#10
0
def _check_empty_environment(base_dir=None):
    if base_dir is None:
        base_dir = glbl.base
    if os.path.exists(home_dir):
        if not os.path.isdir(home_dir):
            sys.exit(
                _graceful_exit("Expected a folder, got a file.  "
                               "Please Talk to beamline staff"))
        files = os.listdir(
            home_dir)  # that also list dirs that have been created
        if len(files) > 0:
            sys.exit(
                _graceful_exit(
                    "Unexpected files in {}, you need to run _end_beamtime(). Please Talk to beamline staff"
                    .format(home_dir)))
    else:
        sys.exit(
            _graceful_exit("The xpdUser directory appears not to exist "
                           "Please Talk to beamline staff"))
示例#11
0
def _read_dark_yaml():
    dark_yaml_name = glbl.dk_yaml
    try:
        with open(dark_yaml_name, 'r') as f:
            dark_scan_list = yaml.load(f)
        return dark_scan_list
    except FileNotFoundError:
        sys.exit(
            _graceful_exit('''It seems you haven't initiated your beamtime.
                Please run _start_beamtime(<your SAF number>) or contact beamline scientist'''
                           ))
示例#12
0
def _check_empty_environment(base_dir=None):
    if base_dir is None:
        base_dir = glbl.base
    if os.path.exists(home_dir):
        if not os.path.isdir(home_dir):
            sys.exit(_graceful_exit("Expected a folder, got a file.  "
                               "Please Talk to beamline staff"))
        files = os.listdir(home_dir) # that also list dirs that have been created
        if len(files) > 1:
            sys.exit(_graceful_exit("Unexpected files in {}, you need to run _end_beamtime(). Please Talk to beamline staff".format(home_dir)))
        elif len(files) == 1:
            tf, = files
            if 'tar' not in tf:
                sys.exit(_graceful_exit("Expected a tarball of some sort, found {} "
                                   "Please talk to beamline staff"
                                   .format(tf)))
            os.unlink(os.path.join(home_dir, tf))
    else:
        sys.exit(_graceful_exit("The xpdUser directory appears not to exist "
                               "Please Talk to beamline staff"))
示例#13
0
def _load_bt(bt_yaml_path):
    btoname = os.path.join(glbl.yaml_dir, 'bt_bt.yml')
    if not os.path.isfile(btoname):
        sys.exit(
            _graceful_exit(
                '''{} does not exist in {}. User might have deleted it accidentally.
Please create it based on user information or contect user'''.format(
                    os.path.basename(btoname), glbl.yaml_dir)))
    with open(btoname, 'r') as fi:
        bto = yaml.load(fi)
    return bto
示例#14
0
def _end_beamtime(base_dir=None, archive_dir=None, bto=None, usr_confirm='y'):
    _required_bt_info = ['bt_piLast', 'bt_safN', 'bt_uid']
    if archive_dir is None:
        archive_dir = glbl.archive_dir
    if base_dir is None:
        base_dir = glbl.base
    os.makedirs(glbl.home, exist_ok=True)
    # check env
    files = os.listdir(glbl.home)
    if len(files) == 0:
        sys.exit(
            _graceful_exit(
                'It appears that end_beamtime may have been run.  If so, do not run again but proceed to _start_beamtime'
            ))
    # laod bt yaml
    if not bto:
        bto = _load_bt(glbl.yaml_dir)
    try:
        bt_md = bto.md
    except AttributeError:
        # worst situation, user didn't even instantiate bt object with xpdAcq
        _graceful_exit(
            '''There is no metadata attribute in beamtime object "{}".
                        User might have gone throgh entirely different workflow.
                        Reconmend to contact user before executing end_beamtime'''
        )
    if 'bt_piLast' in bt_md.keys():
        piname = bto.md['bt_piLast']
    else:
        piname = input('Please enter PI last name for this beamtime: ')
    if 'bt_safN' in bt_md.keys():
        safn = bto.md['bt_safN']
    else:
        safn = input('Please enter your SAF number to this beamtime: ')
    if 'bt_uid' in bt_md.keys():
        btuid = bto.md['bt_uid'][:7]
    else:
        btuid = ''
    archive_full_name = _execute_end_beamtime(piname, safn, btuid, base_dir)
    _confirm_archive(archive_full_name)
    _delete_home_dir_tree()
示例#15
0
def _start_beamtime(safn,home_dir=None):
    if home_dir is None:
        home_dir = glbl.home
    if not os.path.exists(home_dir):
        os.makedirs(home_dir)
    _check_empty_environment()
    configfile = os.path.join(glbl.xpdconfig,'saf{}.yml'.format(str(safn)))
    if os.path.isfile(configfile):
        with open(configfile, 'r') as fin:
            setup_dict = yaml.load(fin)
    else:
        sys.exit(_graceful_exit('the saf config file {} appears to be missing'.format(configfile)))
    try:
        piname = setup_dict['PI last name']
        safn = setup_dict['saf number']
        explist = setup_dict['experimenter list']
    except KeyError:
        sys.exit(_graceful_exit('Cannot load input info. File syntax in {} maybe corrupted.'.format(configfile)))
    bt = _execute_start_beamtime(piname, safn, explist, home_dir=home_dir)
    _init_dark_yaml()

    return bt
示例#16
0
def _start_beamtime(safn,home_dir=None):
    ''' priviate function for beamline scientist
    
    This function will start a beamtime for user 
    It does following:
    1) checks if previous beamtime is properly ended.
    2) create default directories
    3) instantiate a bt object with information encoded in saf<saf_num>.yml file 
    4) instantiate lazy user Sample, ScanPlan objects
    
    Parameters:
    -----------
    safn : str
        string to saf number of current beamtime. 
        This function requires to have a `saf<saf_num>.yml' in xpdUser/config_base
    '''
    if home_dir is None:
        home_dir = glbl.home
    if not os.path.exists(home_dir):
        os.makedirs(home_dir)
    _check_empty_environment()
    configfile = os.path.join(glbl.xpdconfig,'saf{}.yml'.format(str(safn)))
    if os.path.isfile(configfile):
        with open(configfile, 'r') as fin:
            setup_dict = yaml.load(fin)
    else:
        sys.exit(_graceful_exit('the saf config file {} appears to be missing'.format(configfile)))
    try:
        piname = setup_dict['PI last name']
        safn = setup_dict['saf number']
        explist = setup_dict['experimenter list']
    except KeyError:
        sys.exit(_graceful_exit('Cannot load input info. File syntax in {} maybe corrupted.'.format(configfile)))
    bt = _execute_start_beamtime(piname, safn, explist, home_dir=home_dir)
    _init_dark_yaml()

    return bt
示例#17
0
def _end_beamtime(base_dir=None,archive_dir=None,bto=None, usr_confirm = 'y'):
    _required_bt_info = ['bt_piLast', 'bt_safN', 'bt_uid']
    if archive_dir is None:
        archive_dir = glbl.archive_dir
    if base_dir is None:
        base_dir = glbl.base
    os.makedirs(glbl.home, exist_ok = True)
    # check env
    files = os.listdir(glbl.home)
    if len(files)==0:
        sys.exit(_graceful_exit('It appears that end_beamtime may have been run.  If so, do not run again but proceed to _start_beamtime'))
    # laod bt yaml
    if not bto: 
        bto = _load_bt(glbl.yaml_dir)
    try:
        bt_md = bto.md
    except AttributeError:
        # worst situation, user didn't even instantiate bt object with xpdAcq
        _graceful_exit('''There is no metadata attribute in beamtime object "{}".
                        User might have gone throgh entirely different workflow.
                        Reconmend to contact user before executing end_beamtime''')
    if 'bt_piLast' in bt_md.keys():
        piname = bto.md['bt_piLast']
    else:
        piname = input('Please enter PI last name for this beamtime: ')
    if 'bt_safN' in bt_md.keys():
        safn = bto.md['bt_safN']
    else:
        safn = input('Please enter your SAF number to this beamtime: ')
    if 'bt_uid' in bt_md.keys():
        btuid = bto.md['bt_uid'][:7]
    else:
        btuid = ''
    archive_full_name = _execute_end_beamtime(piname, safn, btuid, base_dir)
    _confirm_archive(archive_full_name)
    _delete_home_dir_tree()
示例#18
0
    def _plan_validator(self):
        ''' Validator for ScanPlan object

        It validates if required scan parameters for certain scan type are properly defined in object

        '''
        # based on structures in xpdacq.xpdacq.py
        _Tramp_required_params = ['startingT', 'endingT', 'Tstep', 'exposure']
        _Tramp_optional_params = ['det', 'subs_dict']

        _ct_required_params = ['exposure']
        _ct_optional_params = ['det','subs_dict']

        _tseries_required_params = ['exposure', 'delay', 'num']

        if self.scanplan == 'ct':
            # check missed keys
            missed_keys = [ el for el in _ct_required_params if el not in self.sp_params]
            if missed_keys:
                sys.exit(_graceful_exit('''You are using a "{}" ScanPlan but you missed required parameters:
                {}'''.format(self.scanplan, missed_keys)))
            # check value types
            wrong_type_dict = {}
            for k,v in self.sp_params.items():
                if not isinstance(v,(int,float)):
                    wrong_type_dict.update({k:v})
            if wrong_type_dict:
                sys.exit(_graceful_exit('''You are using a "{}" ScanPlan but following key-value pairs are in correct type(s):
                {}
                Please go to http://xpdacq.github.io for more information\n'''.
                format(self.scanplan, wrong_type_dict)))
        elif self.scanplan == 'Tramp':
            # check missed keys
            missed_keys = [ el for el in _Tramp_required_params if el not in self.sp_params]
            if missed_keys:
                sys.exit(_graceful_exit('''You are using a "{}" ScanPlan but you missed required parameters:
                {}'''.format(self.scanplan, missed_keys)))
            # check value types
            wrong_type_dict = {}
            for k,v in self.sp_params.items():
                if not isinstance(v,(int,float)):
                    wrong_type_dict.update({k:v})
            if wrong_type_dict:
                sys.exit(_graceful_exit('''You are using a "{}" ScanPlan but following key-value pairs are in correct type(s):
                {}
                Please go to http://xpdacq.github.io for more information\n'''.
                format(self.scanplan, wrong_type_dict)))
        elif self.scanplan == 'tseries':
            # check missed keys
            missed_keys = [ el for el in _tseries_required_params if el not in self.sp_params]
            if missed_keys:
                sys.exit(_graceful_exit('''You are using a "{}" ScanPlan but you missed required parameters:
                {}'''.format(self.scanplan, missed_keys)))
            # check value types
            wrong_type_dict = {}
            for k,v in self.sp_params.items():
                if not isinstance(v,(int,float)):
                    wrong_type_dict.update({k:v})
            # num needs to be int
            if not isinstance(self.sp_params['num'], int):
                wrong_type_dict.update({'num': self.sp_params.get('num')})
            if wrong_type_dict:
                sys.exit(_graceful_exit('''You are using a "{}" ScanPlan but following key-value pairs are in correct type(s):
                {}
                Please go to http://xpdacq.github.io for more information\n'''.
                format(self.scanplan, wrong_type_dict)))

        elif self.scanplan == 'bluesky':
            print('''INFO: You are handing a "bluesky" type scan.
            Please go to https://nsls-ii.github.io/bluesky/plans.html
            for complete guide on how to define a plan.''')
            print('INFO: This ScanPlan does not support auto-dark subtraction')
        else:
            print('It seems you are defining an unknown scan')
            print('Please use uparrow to edit and retry making your ScanPlan object')
            sys.exit('Please ignore this RunTime error and continue, using the hint above if you like')