def mkdir(self, newdir):
        status = self.remote_directory_worker.mkdir(newdir)

        if status == "mkdirsuccess":
            self.expand(None, "\\".join(newdir.split("\\")[0:-1]))
            self.select(newdir.split("\\")[-1])
        elif status == "mkdirfailedfileexists":
            ErrorDialog(self.controller,
                        title="Error",
                        label="Could not create directory:\n\n" + newdir +
                        "\n\nFile exists.")
            self.expand(newparent=self.current_parent)
        elif status == "mkdirfailedpermission":
            ErrorDialog(
                self.controller,
                title="Error",
                label="Could not create directory:\n\n" + newdir +
                "\n\nPermission denied.",
            )
            self.expand(newparent=self.current_parent)

        elif "mkdirfailed" in status:
            ErrorDialog(self.controller,
                        title="Error",
                        label="Could not create directory:\n\n" + newdir)
            self.expand(newparent=self.current_parent)
Beispiel #2
0
 def inner_mkdir(dir_to_make: str, action: Any):
     mkdir_status = self.remote_directory_worker.mkdir(dir_to_make)
     print("MKDIR STATUS!!")
     print(mkdir_status)
     if mkdir_status == "mkdirsuccess":
         action()
     elif mkdir_status == "mkdirfailedfileexists":
         ErrorDialog(
             self.controller,
             title="Error",
             label="Could not create directory:\n\n" + dir_to_make +
             "\n\nFile exists.",
         )
     elif mkdir_status == "mkdirfailedpermission":
         ErrorDialog(
             self.controller,
             title="Error",
             label="Could not create directory:\n\n" + dir_to_make +
             "\n\nPermission denied.",
         )
     elif "mkdirfailed" in mkdir_status:
         ErrorDialog(self.controller,
                     title="Error",
                     label="Could not create directory:\n\n" +
                     dir_to_make)
    def remove_retry(self, need_new: bool = True):
        if need_new:
            self.controller.wait_dialog = None
        removed = self.controller.rm_current()
        if removed:
            numstr = str(self.controller.spec_num)
            if numstr == "None":
                numstr = self.controller.spec_startnum_entry.get()
            while len(numstr) < utils.NUMLEN:
                numstr = "0" + numstr
            self.controller.log("Warning: overwriting " +
                                self.controller.spec_save_path + "\\" +
                                self.controller.spec_basename + numstr +
                                ".asd.")

            # If we are retrying taking a spectrum or white references, don't do input checks again.
            if self.controller.take_spectrum in self.controller.queue[0]:
                garbage = self.controller.queue[0][
                    self.controller.take_spectrum][2]
                self.controller.queue[0] = {
                    self.controller.take_spectrum: [True, True, garbage]
                }

            elif self.controller.wr in self.controller.queue[0]:
                self.controller.queue[0] = {self.controller.wr: [True, True]}
            self.controller.next_in_queue()
        else:
            ErrorDialog(
                self.controller,
                label=
                "Error: Failed to remove file. Choose a different base name,\nspectrum number, or save"
                " directory and try again.",
            )
Beispiel #4
0
    def plot(self, plot_input_file):
        if len(self.controller.queue) > 0:
            if self.plot in self.controller.queue[0]:
                # Happens if we just transferred data from spec compy.
                self.controller.complete_queue_item()
                self.controller.wait_dialog.top.destroy()

        try:
            data_loaded = self.plotter.load_samples(self.dataset_name,
                                                    plot_input_file)
            if not data_loaded:
                ErrorDialog(self.controller, "Error",
                            "Error: Could not load data.")
                print("Error: Could not load data.")
        # pylint: disable = broad-except
        except (IndexError, KeyError, Exception):
            Dialog(
                self.controller,
                "Plotting Error",
                "Error: Plotting failed.\n\nDoes file exist? Is data formatted correctly?\nIf plotting a remote file,"
                " is the server accessible?",
                {"ok": {}},
            )
            return
        self.plotter.new_tab()
Beispiel #5
0
 def remove_retry(file, action):
     try:
         os.remove(file)
         action()
     except OSError:
         ErrorDialog(self.controller,
                     title="Error overwriting file",
                     label="Error: Could not delete file.\n\n" + file)
Beispiel #6
0
 def try_mk_dir(dir_to_make: str, action: Any) -> None:
     try:
         os.makedirs(dir_to_make)
         action()
     except OSError:
         ErrorDialog(self.controller,
                     title="Cannot create directory",
                     label="Cannot create directory:\n\n" + dir_to_make)
    def check_angle_lists(self, incidences: str, emissions: str,
                          azimuths: str) -> Tuple[List, List, List]:
        def check_list(list_to_check: str) -> Tuple[List, List]:
            invalid_list = []
            list_to_check = list_to_check.split(",")
            if "None" in list_to_check or "none" in list_to_check:
                while "None" in list_to_check:
                    list_to_check.remove("None")
                while "none" in list_to_check:
                    list_to_check.remove("none")
                list_to_check.append(None)
            if list_to_check == [""]:
                list_to_check = []
            print(list_to_check)
            # If e.g. %5 is included in the list, include all angles where angle % 5 == 0
            n = 0
            while n < len(list_to_check):
                angle = list_to_check[n]
                if "%" in str(angle):
                    try:
                        val = int(str(angle).replace("%", ""))
                    except ValueError:
                        invalid_list.append(angle)
                        continue
                    for k in range(-70, 171):
                        if k % val == 0:
                            list_to_check.insert(n, k)
                            n += 1
                    list_to_check.remove(angle)
                    n -= 1
                n += 1

            for n, angle in enumerate(list_to_check):
                if angle is not None:
                    try:
                        list_to_check[n] = int(angle)
                    except ValueError:
                        invalid_list.append(angle)
            return list_to_check, invalid_list

        incidences, invalid_incidences = check_list(incidences)
        emissions, invalid_emissions = check_list(emissions)
        azimuths, invalid_azimuths = check_list(azimuths)
        if invalid_incidences != [] or invalid_emissions != [] or invalid_azimuths != []:
            error_string = "Warning! Not all angles entered are valid.\n"
            if invalid_incidences != []:
                error_string += "\nInvalid incidences: " + str(
                    invalid_incidences)
            if invalid_emissions != []:
                error_string += "\nInvalid emissions: " + str(
                    invalid_emissions)
            if invalid_azimuths != []:
                error_string += "\nInvalid azimuths: " + str(invalid_azimuths)
            ErrorDialog(self.controller, "Warning!", error_string)

        return incidences, emissions, azimuths
 def lost_dialog(self, buttons: Dict):
     ErrorDialog(
         controller=self.controller,
         title="Lost Connection",
         label=
         "Error: Lost connection with spec compy.\n\nCheck that you and the spectrometer computer are\n"
         "both connected to the same network.",
         buttons=buttons,
         button_width=15,
     )
 def lost_dialog(self, buttons: Dict):
     ErrorDialog(
         controller=self.controller,
         title="Lost Connection",
         label="Error: Lost connection with Raspberry Pi.\n\n"
         "Check you and the Raspberry Pi are\n"
         "both connected to the same network.",
         buttons=buttons,
         button_width=15,
     )
 def ok(self):
     try:
         color_variable = int(self.hue_entry.get())
         if color_variable < 0 or color_variable > 359:
             raise ValueError
     except ValueError:
         ErrorDialog(self.controller, "Error",
                     "Error: Invalid custom hue.\n\nEnter a number 0-359.")
         return
     self.func(int(self.hue_entry.get()))
     self.top.destroy()
Beispiel #11
0
    def apply_x(self):
        self.view_notebook.select(self.tab.top)

        try:
            x1 = float(self.left_zoom_entry.get())
            x2 = float(self.right_zoom_entry.get())
            self.tab.adjust_x(x1, x2)
        except:
            ErrorDialog(self,
                        title='Invalid Zoom Range',
                        label='Error: Invalid x limits: ' +
                        self.left_zoom_entry.get() + ', ' +
                        self.right_zoom_entry.get())
Beispiel #12
0
 def apply_y(self):
     self.view_notebook.select(self.tab.top)
     try:
         y1 = float(self.left_zoom_entry2.get())
         y2 = float(self.right_zoom_entry2.get())
         self.tab.adjust_y(y1, y2)
     except Exception as e:
         print(e)
         ErrorDialog(self,
                     title='Invalid Zoom Range',
                     label='Error! Invalid y limits: ' +
                     self.left_zoom_entry2.get() + ', ' +
                     self.right_zoom_entry2.get())
Beispiel #13
0
    def setup_process(self) -> Tuple[str, str, str]:
        output_file: str = self.output_file_entry.get()

        if output_file == "":
            ErrorDialog(self.controller,
                        label="Error: Enter an output file name")
            raise ProcessFileError

        if output_file[-4:] != ".csv":
            output_file = output_file + ".csv"
            self.output_file_entry.insert("end", ".csv")

        input_directory = self.input_dir_entry.get()
        if input_directory[-1] == "\\":
            input_directory = input_directory[:-1]

        output_directory = self.output_dir_entry.get()

        if self.process_save_dir.get():
            file = open(
                self.config_info.local_config_loc + "process_directories.txt",
                "w+")
            file.write(self.proc_local_remote + "\n")
            file.write(input_directory + "\n")
            file.write(output_directory + "\n")
            file.write(output_file + "\n")
            file.close()

        if self.proc_local.get() == 1:
            self.controller.plot_manager.plot_local_remote = "local"
            check = self.check_local_file(self.output_dir_entry.get(),
                                          output_file,
                                          self.controller.process_cmd)
            if not check:
                raise ProcessFileError  # If the file exists, controller.check_local_file_exists
                # gives the user the option to overwrite, in which case process_cmd gets called again.
            check = self.check_local_folder(output_directory,
                                            self.controller.process_cmd)
            if not check:
                raise ProcessFileError  # Same deal for the folder (except existing is good).
            self.controller.plot_manager.plot_local_remote = "local"
            return input_directory, output_directory, output_file
        if self.proc_local.get() == 0:
            check = self.check_remote_folder(output_directory,
                                             self.controller.process_cmd)
            if not check:
                raise ProcessFileError
            self.controller.plot_manager.plot_local_remote = "remote"

        return input_directory, output_directory, output_file
Beispiel #14
0
    def apply_z(self):
        self.view_notebook.select(self.tab.top)

        try:
            z1 = float(self.left_zoom_entry_z.get())
            z2 = float(self.right_zoom_entry_z.get())
            self.tab.adjust_z(z1, z2)
        except Exception as e:
            print(e)
            ErrorDialog(self,
                        title='Invalid Zoom Range',
                        label='Error: Invalid z limits: ' +
                        self.left_zoom_entry.get() + ', ' +
                        self.right_zoom_entry.get())
Beispiel #15
0
 def apply_y(self):
     self.controller.view_notebook.select(self.tab.top)
     try:
         y1 = float(self.left_zoom_entry2.get())
         y2 = float(self.right_zoom_entry2.get())
         self.tab.adjust_y(y1, y2)
         # utils.lift_widget(self.analysis_dialog.top)
     except ValueError:
         # utils.lift_widget(self.analysis_dialog.top)
         ErrorDialog(
             self,
             title="Invalid Zoom Range",
             label="Error! Invalid y limits: " +
             self.left_zoom_entry2.get() + ", " +
             self.right_zoom_entry2.get(),
         )
Beispiel #16
0
 def apply_z(self) -> None:
     self.controller.view_notebook.select(self.tab.top)
     try:
         z1 = float(self.left_zoom_entry_z.get())
         z2 = float(self.right_zoom_entry_z.get())
         self.tab.adjust_z(z1, z2)
         # utils.lift_widget(self.plot_settings_dialog.top)
     except ValueError:
         # utils.lift_widget(self.plot_settings_dialog.top)
         ErrorDialog(
             self.controller,
             title="Invalid Zoom Range",
             label="Error: Invalid z limits: " +
             self.left_zoom_entry_z.get() + ", " +
             self.right_zoom_entry_z.get(),
         )
Beispiel #17
0
    def ok(self):
        bad_vals = []
        for val in self.values:
            self.mins[val] = self.values[val][1]
            self.maxes[val] = self.values[val][2]
            valid = utils.validate_float_input(
                self.entries[val].get(), self.mins[val], self.maxes[val]
            )  # Weird for tray position - not valid for white reference
            if val == "Tray position":
                valid = True
            if not valid:
                bad_vals.append(val)

        if len(bad_vals) == 0:
            pos = self.entries["Tray position"].get()
            if pos == "White reference":
                pos = "WR"

            incidence = float(self.entries["Incidence"].get())
            emission = float(self.entries["Emission"].get())
            self.controller.queue[0][self.controller.configure_pi] = [
                incidence, emission, pos
            ]

            self.top.destroy()
            ok_dict = self.buttons["ok"]
            for func in ok_dict:
                args = ok_dict[func]
                func(*args)
        else:
            err_str = "Error: Invalid "
            if len(bad_vals) == 1:
                for val in bad_vals:
                    err_str += (val.lower() +
                                " value.\nPlease enter a number from " +
                                str(self.mins[val]) + " to " +
                                str(self.maxes[val]) + ".")
            else:
                err_str += "input. Please enter the following:\n\n"
                for val in bad_vals:
                    err_str += val + " from " + str(
                        self.mins[val]) + " to " + str(self.maxes[val]) + "\n"

            ErrorDialog(self.controller,
                        title="Error: Invalid Input",
                        label=err_str)
Beispiel #18
0
    def calculate(self):
        try:
            self.controller.view_notebook.select(self.tab.top)
        except TclError:
            print("Error selecting tab in analysis_tools_manager.calculate().")
            print(self.tab)
            pass
        artifact_warning = False

        if self.analyze_var.get() == "slope":
            left, right, slopes, artifact_warning = self.tab.calculate_slopes(
                self.left_slope_entry.get(), self.right_slope_entry.get())
            self.update_entries(left, right)
            self.populate_listbox(slopes)
            self.update_plot_menu(["e", "i", "g", "e,i", "theta", "az, e"])

        elif self.analyze_var.get() == "band depth":
            left, right, depths, artifact_warning = self.tab.calculate_band_depths(
                self.left_slope_entry.get(),
                self.right_slope_entry.get(),
                self.neg_depth.get(),
                self.use_delta.get(),
            )
            self.update_entries(left, right)
            self.populate_listbox(depths)
            self.update_plot_menu(["e", "i", "g", "e,i", "theta", "az, e"])

        elif self.analyze_var.get() == "band center":
            left, right, centers, artifact_warning = self.tab.calculate_band_centers(
                self.left_slope_entry.get(),
                self.right_slope_entry.get(),
                self.use_max_for_centers.get(),
                self.use_delta.get(),
            )
            self.update_entries(left, right)
            self.populate_listbox(centers)
            self.update_plot_menu(["e", "i", "g", "e,i", "theta", "az, e"])

        elif self.analyze_var.get() == "reflectance":
            left, right, reflectance, artifact_warning = self.tab.calculate_avg_reflectance(
                self.left_slope_entry.get(), self.right_slope_entry.get())
            self.update_entries(left, right)
            self.populate_listbox(reflectance)
            self.update_plot_menu(["e", "i", "g", "e,i", "theta", "az, e"])

        elif self.analyze_var.get() == "reciprocity":
            left, right, reciprocity, artifact_warning = self.tab.calculate_reciprocity(
                self.left_slope_entry.get(), self.right_slope_entry.get())
            self.update_entries(left, right)
            self.populate_listbox(reciprocity)
            self.update_plot_menu(["e", "i", "g", "e,i"])

        elif self.analyze_var.get() == "difference":
            left, right, error, artifact_warning = self.tab.calculate_error(
                self.left_slope_entry.get(), self.right_slope_entry.get(),
                self.abs_val.get())
            # Tab validates left and right values. If they are no good, put in min and max wavelengths available.
            self.update_entries(left, right)
            self.populate_listbox(error)
            self.update_plot_menu(["\u03bb", "e,i"])

        if artifact_warning:
            ErrorDialog(
                self, "Warning",
                "Warning: Excluding data potentially\ninfluenced by artifacts from 1000-1400 nm."
            )

        self.analysis_dialog.min_height = 1000
        self.analysis_dialog.update()
    def listen(self):
        while len(self.local_server.queue) > 0:
            message = self.local_server.queue.pop(0)
            cmd, params = utils.decrypt(message)

            if "lostconnection" not in cmd:
                print("Spec read command: " + cmd)

            if cmd == "listdir":
                # RemoteDirectoryWorker in wait_for_contents is waiting for a file that contains a list of the contents
                # of a given folder on the spec compy. This file will have an encrypted version of the parent
                # directory's path in its title e.g. listdir&R=+RiceData+Kathleen+spectral_data
                self.queue.append(message)
            elif "spec_data" in cmd:
                found = False
                for item in self.queue:
                    if "spec_data" in item:
                        found = True
                        item["spec_data"] = item["spec_data"] + "&".join(
                            params)
                if not found:
                    self.queue.append({"spec_data": "&".join(params)})

                if cmd == "spec_data_final":
                    self.queue.append("spec_data_transferred")
            elif cmd == "savedfile":
                self.queue.append(cmd)

            elif cmd == "restarting":
                self.queue.append(cmd)

            elif "log_data" in cmd:
                found = False
                for item in self.queue:
                    if "log_data" in item:
                        found = True
                        item["log_data"] = item["log_data"] + "&".join(params)
                if not found:
                    self.queue.append({"log_data": "&".join(params)})

                if cmd == "log_data_final":
                    self.queue.append("log_data_transferred")

            elif "listcontents" in cmd:
                self.queue.append(message)

            elif "lostconnection" in cmd and not self.controller.restarting_spec_compy:
                if self.alert_lostconnection:
                    self.alert_lostconnection = False
                    time.sleep(4)
                    self.controller.freeze()
                    buttons = {
                        "retry": {
                            self.set_alert_lostconnection: [True],
                        },
                        "work offline": {},
                        "exit": {
                            utils.exit_func: []
                        },
                    }
                    ErrorDialog(
                        controller=self.controller,
                        title="Lost Connection",
                        label=
                        "Error: RS3 has no connection with the spectrometer.\nCheck that the spectrometer is"
                        " on.\n\nNote that RS3 can take some time to connect to the spectrometer.\nBe patient"
                        " and wait for the dot at the lower right of RS3 to turn green.",
                        buttons=buttons,
                        button_width=15,
                        width=600,
                    )

            elif "unexpectedfile" in cmd and not self.controller.restarting_spec_compy:
                if self.new_dialogs:
                    ErrorDialog(
                        self.controller,
                        title="Untracked Files",
                        label=
                        "There is an untracked file in the data directory.\nDoes this belong here?\n\n"
                        + params[0],
                    )
                else:
                    for param in params:
                        print(param)
                        self.unexpected_files.append(param)
            elif "batch" in cmd:
                if "batch" in cmd:
                    self.locked = True
                    self.queue.append(cmd + "&".join(params))
                    self.locked = False
                    # print("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@adding to queue")
                    # print(cmd + "&".join(params)[0:100])

            else:
                self.queue.append(cmd + "&".join(params))
    def expand(
        self,
        event: Optional[Event] = None,
        newparent: Optional[str] = None,
        buttons: Optional[Dict] = None,
        select: Optional[str] = None,
        destroy: bool = False,
    ):
        print("expanding!")
        if newparent is None:
            index = self.listbox.curselection()[0]
            if self.listbox.itemcget(index, "foreground") == "darkblue":
                return
            newparent = self.current_parent + "\\" + self.listbox.get(index)
        if newparent[1:2] != ":" or len(
                newparent) > 2 and newparent[1:3] != ":\\":
            ErrorDialog(
                self.controller,
                title="Error: Invalid input",
                label="Error: Invalid input.\n\n" + newparent +
                "\n\nis not a valid filename.",
            )
            if self.current_parent is None:
                self.expand(newparent="C:\\Users")
            return
        if newparent[-1] == "\\":
            newparent = newparent[:-1]
        # Send a command to the spec compy asking it for directory contents
        if self.directories_only:
            status: Union[List,
                          str] = self.remote_directory_worker.get_contents(
                              newparent)
        else:
            status: Union[List,
                          str] = self.remote_directory_worker.get_contents(
                              newparent)

        # if we succeeded, the status will be a list of the contents of the directory
        if isinstance(status, list):

            self.listbox.delete(0, "end")
            for directory in status:
                if directory[0:2] == "~:":
                    self.listbox.insert(END, directory[2:])
                    self.listbox.itemconfig(END, fg="darkblue")
                else:
                    self.listbox.insert(END, directory)
            self.current_parent = newparent

            self.path_entry.delete(0, "end")
            self.path_entry.insert("end", newparent)
            if select is not None:
                self.select(select)

            if destroy:
                self.close()

        elif status == "listdirfailed":
            if self.current_parent is None:
                self.current_parent = "C:\\Users"
            if buttons is None:
                buttons = {
                    "yes": {
                        self.mkdir: [newparent]
                    },
                    "no": {
                        self.expand: [None, self.current_parent]
                    }
                }
            ErrorDialog(
                self.controller,
                title="Error",
                label=newparent +
                "\ndoes not exist. Do you want to create this directory?",
                buttons=buttons,
            )
            return
        elif status == "listdirfailedpermission":
            ErrorDialog(self.controller,
                        label="Error: Permission denied for\n" + newparent)
            return
        elif status == "timeout":
            ErrorDialog(
                self.controller,
                label="Error: Operation timed out.\n"
                "Check that the automation script is running on the spectrometer computer.",
            )
            self.cancel()
Beispiel #21
0
    def check_remote_folder(self, remote_dir: str, next_action: Any) -> bool:
        print(remote_dir)

        def inner_mkdir(dir_to_make: str, action: Any):
            mkdir_status = self.remote_directory_worker.mkdir(dir_to_make)
            print("MKDIR STATUS!!")
            print(mkdir_status)
            if mkdir_status == "mkdirsuccess":
                action()
            elif mkdir_status == "mkdirfailedfileexists":
                ErrorDialog(
                    self.controller,
                    title="Error",
                    label="Could not create directory:\n\n" + dir_to_make +
                    "\n\nFile exists.",
                )
            elif mkdir_status == "mkdirfailedpermission":
                ErrorDialog(
                    self.controller,
                    title="Error",
                    label="Could not create directory:\n\n" + dir_to_make +
                    "\n\nPermission denied.",
                )
            elif "mkdirfailed" in mkdir_status:
                ErrorDialog(self.controller,
                            title="Error",
                            label="Could not create directory:\n\n" +
                            dir_to_make)

        status = self.remote_directory_worker.get_dirs(remote_dir)

        if status == "listdirfailed":
            buttons = {
                "yes": {
                    inner_mkdir: [remote_dir, next_action]
                },
                "no": {}
            }
            ErrorDialog(
                self.controller,
                title="Directory does not exist",
                label=remote_dir +
                "\ndoes not exist. Do you want to create this directory?",
                buttons=buttons,
            )
            return False
        if status == "listdirfailedpermission":
            ErrorDialog(self.controller,
                        label="Error: Permission denied for\n" + remote_dir)
            return False

        if status == "timeout":
            if not self.controller.text_only:
                buttons = {
                    "cancel": {},
                    "retry": {
                        self.controller.spec_commander.remove_from_listener_queue:
                        [["timeout"]],
                        self.controller.next_in_queue: [],
                    },
                }
                dialog = ErrorDialog(
                    self.controller,
                    label=
                    "Error: Operation timed out.\n\nCheck that the automation script is running on the"
                    " spectrometer\n computer and the spectrometer is connected.",
                    buttons=buttons,
                )
                for button in dialog.tk_buttons:
                    button.config(width=15)
            else:
                self.controller.log("Error: Operation timed out.")
            return False

        self.controller.spec_commander.check_writeable(remote_dir)
        t = 3 * utils.BUFFER
        while t > 0:
            if "yeswriteable" in self.controller.spec_listener.queue:
                self.controller.spec_listener.queue.remove("yeswriteable")
                return True
            if "notwriteable" in self.controller.spec_listener.queue:
                self.controller.spec_listener.queue.remove("notwriteable")
                ErrorDialog(
                    self.controller,
                    label=
                    "Error: Permission denied.\nCannot write to specified directory."
                )
                return False
            time.sleep(utils.INTERVAL)
            t = t - utils.INTERVAL
        if t <= 0:
            ErrorDialog(self.controller, label="Error: Operation timed out.")
            return False
Beispiel #22
0
    def check_local_folder(self, local_dir: str, next_action: Any) -> bool:
        def try_mk_dir(dir_to_make: str, action: Any) -> None:
            try:
                os.makedirs(dir_to_make)
                action()
            except OSError:
                ErrorDialog(self.controller,
                            title="Cannot create directory",
                            label="Cannot create directory:\n\n" + dir_to_make)

        exists = os.path.exists(local_dir)
        if exists:
            # If the file exists, try creating and deleting a new file there to make sure we have permission.
            try:
                if self.config_info.opsys in ("Linux", "Mac"):
                    if local_dir[-1] != "/":
                        local_dir += "/"
                else:
                    if local_dir[-1] != "\\":
                        local_dir += "\\"

                existing = os.listdir(local_dir)
                i = 0
                delme = "delme" + str(i)
                while delme in existing:
                    i += 1
                    delme = "delme" + str(i)

                os.mkdir(local_dir + delme)
                os.rmdir(local_dir + delme)
                return True

            except OSError:
                ErrorDialog(
                    self.controller,
                    title="Error: Cannot write",
                    label="Error: Cannot write to specified directory.\n\n" +
                    local_dir,
                )
                return False
        else:
            if (
                    self.controller.script_running
            ):  # If we're running a script, just try making the directory automatically.
                try_mk_dir(local_dir, next_action)
            else:  # Otherwise, ask the user.
                buttons = {
                    "yes": {
                        try_mk_dir: [local_dir, next_action]
                    },
                    "no": {}
                }
                ErrorDialog(
                    self.controller,
                    title="Directory does not exist",
                    label=local_dir +
                    "\n\ndoes not exist. Do you want to create this directory?",
                    buttons=buttons,
                )
        # TODO: check these return statements make sense.
        return exists