def select_filter(self, new_filter): """ Sets the filter to be used by the optical train. Filters can be provided in several formats: - TransmissionCurve object - full file path : using the pattern "./TC_filter_<name>.dat" - filter name string : providing only the <name> part of the file name Note: this only works if an instrument config file has been read Acceptable filter names for an instrument package can be found by using ``<UserCommands>.list("filters")`` Filter file names follow the TC_filter_<name>.dat convention and should consist of the two columns ``wavelength`` and ``transmission`` Parameters ---------- new_filter : str, TransmissionCurve The new filter : filename, acceptable filter name, or preloaded TransmissionCurve object See Also ``.list("filters")`` """ if isinstance(new_filter, sc.TransmissionCurve): self.cmds["INST_FILTER_TC"] = new_filter elif isinstance(new_filter, str): if os.path.exists(new_filter): self.cmds["INST_FILTER_TC"] = new_filter elif cutils.extract_filter_name(new_filter) in self.list( "filters"): filter_name = cutils.extract_filter_name(new_filter) full_name = "TC_filter_{}.dat".format(filter_name) self.cmds["INST_FILTER_TC"] = full_name else: warnings.warn("{} was not found".format(new_filter)) else: raise TypeError("{} must have type `str` or " "`TransmissionCurve`".format(new_filter)) self._find_files()
def update(self, new_input): """ Update multiple entries of a ``UserCommands`` dictionary ``update(new_dict)`` takes either a normal python ``dict`` object or a ``UserCommands`` object. Only keywords that match those in the ``UserCommands`` object will be updated. Misspelled keywords raise an error. To update single items in the dictionary, it is recommended to simply call the key and update the value - i.e ``<UserCommands>[key] = value``. Parameters ---------- new_input : str, dict, ``UserCommands``, file path Raises ------ KeyError If a parameter is not found in ``self.cmds``. Examples -------- View the default tests_commands:: >>> import scopesim >>> my_cmds = scopesim.UserCommands() >>> print(my_cmds.cmds) Change a single command:: >>> my_cmds["OBS_EXPTIME"] = 60 Change a series of tests_commands at once:: >>> new_cmds = {"OBS_EXPTIME" : 60 , "OBS_NDIT" : 10} >>> my_cmds.update(new_cmds) .. todo:: Add the new functionality to docs: - can update with strings, dicts, filenames, or UserCommands Remove documentation references to cmd.cmds. This bypasses: - check to see if key is official keyword - converting str to python type """ if isinstance(new_input, UserCommands): tmp_cmds = new_input.cmds elif isinstance(new_input, dict): tmp_cmds = new_input elif isinstance(new_input, str): tmp_cmds = cutils.read_config(new_input) else: raise ValueError("Cannot update with type: " + type(new_input)) for key in tmp_cmds: self[key] = tmp_cmds[key]
def test_passes_for_correctly_formatted_multiline_string(self): multiline_string = """ LINE_ONE hello # this is the first line LINE_TWO world! # this is the second line """ dic = cmd_utils.read_config(multiline_string) assert dic["LINE_ONE"] == "hello" assert dic["LINE_TWO"] == "world!"
def update(self, new_input): if isinstance(new_input, UserCommands): tmp_cmds = new_input.cmds elif isinstance(new_input, dict): tmp_cmds = new_input elif isinstance(new_input, str): fname = find_file(new_input) if fname is not None: new_input = fname tmp_cmds = cutils.read_config(new_input) else: raise ValueError("Cannot update with type: " + type(new_input)) # Use self.update so that we reject all the invalid keywords for key in tmp_cmds: self[key] = tmp_cmds[key]
def test_correctly_coverts_none_string_to_none_type(self): dic = cmd_utils.lines_to_dict(["A None"]) assert dic["A"] is None
def test_raises_exception_if_input_is_not_list(self): invalid_lines = "One point twenty-one Jigawatts!" with pytest.raises(ValueError): dic = cmd_utils.lines_to_dict(invalid_lines)
def _convert_python_types(self): """Convert strings "none", "true", "false" values into python types""" self.cmds = cutils.convert_dict_strings_to_python_types(self.cmds)
def test_update_happens_when_given_other_dict(self): orig_dic = {"A" : "B"} update_dic = {"A" : 2} new_dic = cmd_utils.update_config(update_dic, orig_dic) assert new_dic["A"] == 2 assert orig_dic["A"] == 2
def test_raise_exception_if_input_is_not_string(self): with pytest.raises(ValueError): cmd_utils.read_config(["hello", "world"])
def test_passes_when_given_filename_that_exist(self): rc_file = os.path.join(rc.__pkg_dir__, "OLD.scopesimrc") rc_dict = cmd_utils.read_config(rc_file) assert rc_dict["SIM_SUB_PIXEL_FLAG"] is False
def test_nones_are_replaces(self): dic = {"A" : "none", "B" : "None", "C" : "NONE", "D" : "nOnE"} new_dic = cmd_utils.convert_dict_strings_to_python_types(dic) for key in dic: assert dic[key] is None
def __setitem__(self, key, val): if key not in self.cmds: warnings.warn("{} not in self.keys. Ignoring.".format(key)) return None self.cmds[key] = cutils.str_to_python_type(val)
def __getitem__(self, key): if cutils.is_item_subcategory(key, self.cmds): return cutils.get_subcategory(key, self.cmds) else: return self.cmds[key]
def _convert_python_types(self): """Convert string "none" values into python ``None`` values""" self.cmds = cutils.convert_dict_strings_to_python_types(self.cmds)
def test_correctly_coverts_true_string_to_true_type(self): dic = cmd_utils.lines_to_dict(["A True"]) assert dic["A"] is True
def test_correctly_coverts_number_string_to_float_type(self): dic = cmd_utils.lines_to_dict(["A 7"]) assert dic["A"] == 7.
def test_conversion_works(self): assert cmd_utils.str_to_python_type("none") is None assert cmd_utils.str_to_python_type("True") is True assert cmd_utils.str_to_python_type("42") == 42. assert cmd_utils.str_to_python_type("Geronimo!") == "Geronimo!"
def test_raises_exception_for_incorrectly_formatted_multiline_string(self): dodgy_multiline_string = """ LINE_ONE # this lines is missing a value """ with pytest.raises(ValueError): cmd_utils.read_config(dodgy_multiline_string)
def test_throws_error_if_input_is_not_string(self): assert cmd_utils.str_to_python_type(True) is True assert cmd_utils.str_to_python_type(None) is None assert cmd_utils.str_to_python_type(42) is 42
def test_raises_exception_if_filename_doesnt_exist(self): with pytest.raises(ValueError): cmd_utils.read_config("bogus.txt")
def test_empty_str_returns_empty_dict(self): dic = cmd_utils.lines_to_dict([]) assert len(dic) == 0
def test_update_happens_when_given_correctly_formatted_string(self): orig_dic = {"A" : "B"} update_str = "A 2" new_dic = cmd_utils.update_config(update_str, orig_dic) assert new_dic["A"] == 2 assert orig_dic["A"] == 2
def test_correctly_formatted_string_returns_ordered_dict(self): valid_lines = ["NO_COMMENT True", "WITH_COMMENT foo # bar"] dic = cmd_utils.lines_to_dict(valid_lines) assert dic["NO_COMMENT"] is True assert dic["WITH_COMMENT"] == "foo"
def test_raise_exception_when_not_given_string_or_dict(self): orig_dic = {"A": "B"} with pytest.raises(ValueError): cmd_utils.update_config(["a", "b"], orig_dic)
def test_bogus_string_raises_unknown_response(self): invalid_lines = ["One point twenty-one Jigawatts!"] dic = cmd_utils.lines_to_dict(invalid_lines) warnings.warn("Bogus data passes silently through parse_config()") pass