class Demag_GUIAU(dgl.Demag_GUI):
    def __init__(self,
                 WD=None,
                 write_to_log_file=True,
                 inp_file=None,
                 delay_time=3,
                 data_model=3.0,
                 test_mode_on=True):
        global usr_configs_read, inp_dir, pkg_dir, data_dir, CURRENT_VERSION
        # catch user interruption signal (ctrl+c) so app can still close properly
        # not working right now
        # signal.signal(signal.SIGINT, self.sigint_catcher)
        # if write_to_log_file: start_logger()
        self.title = "Demag GUI Autoupdate | %s" % (
            CURRENT_VERSION.strip("pmagpy-"))
        if WD is None:
            self.WD = os.getcwd()
        else:
            self.WD = os.path.realpath(os.path.expanduser(WD))
        uncached, num_cached_files = uncache_site_files(self.WD)
        # set attribute to be used by read_inp() to warn the user once and only
        # once if there are commented lines in inp file
        self.warn_comments_in_inpfile = False
        if uncached:
            print("-I- Unpacking {} site-level MagIC files previously"
                  " cached".format(num_cached_files))
        WD_short = shortpath(self.WD)
        if not os.path.isdir(self.WD):
            print(f"-E- Working directory {WD_short} does not exist.")
        print(f"-I- Working directory set to {WD_short}")
        # self.delete_magic_files(self.WD)
        self.data_model = data_model
        self.delay_time = delay_time

        if inp_file is None:
            temp_inp_pick = wx.Frame()
            if usr_configs_read:
                inp_file_name = self.pick_inp(temp_inp_pick, inp_dir)
                if inp_file_name is None:
                    ls_inp_dir = list(
                        os.path.join(inp_dir, s) for s in os.listdir(inp_dir))
                    inp_file_name = max(ls_inp_dir, key=os.path.getmtime)
                    print("-W- No .inp file selected. Reading most recently"
                          " opened file: %s" %
                          (os.path.basename(inp_file_name)))
            else:
                inp_file_name = self.pick_inp(temp_inp_pick, self.WD)
            temp_inp_pick.Destroy()
        elif not os.path.isfile(os.path.realpath(inp_file)):
            inp_file = os.path.realpath(inp_file)
            if os.path.isfile(os.path.join(self.WD, inp_file)):
                inp_file_name = os.path.join(self.WD, inp_file)
            elif usr_configs_read:
                if os.path.isfile(
                        os.path.join(inp_dir, os.path.basename(inp_file))):
                    inp_file_name = os.path.join(inp_dir,
                                                 os.path.basename(inp_file))
            else:
                print(f"-E- Could not find .inp file {inp_file}")
                return
        else:
            inp_file_name = inp_file

        self.inp_file = inp_file_name
        magic_files = {}
        self.read_inp(self.WD, self.inp_file, magic_files, self.data_model)
        self.combine_magic_files(self.WD, magic_files, self.data_model)
        # self.on_new_inp()
        # self.update_loop(force_update=True)

        try:
            super(Demag_GUIAU, self).__init__(
                WD=WD,
                # overwrite this for log testing purposes;
                # should override the superclass logging methods
                # for this eventually
                write_to_log_file=False,
                data_model=data_model,
                test_mode_on=test_mode_on)
        except ValueError:
            raise ValueError("-E- Data model you entered is not a number")
        # make changes to the demag_gui parent frame
        # add buttons for triggering autoupdate functions
        self.au_add_buttons()
        # set AU icon
        self.au_set_icon()
        # add read .inp option to menubar
        self.menubar = super().GetMenuBar()
        menu_file = self.menubar.GetMenu(0)
        m_read_inp = menu_file.Insert(1, -1, "Read .inp file\tCtrl-I", "")
        self.Bind(wx.EVT_MENU, self.on_menu_pick_read_inp, m_read_inp)
        self.menubar.Refresh()
        # make statusbar
        self.statusbar = self.CreateStatusBar()

        # find .inp file
        # if inp_file is None:
        #     if usr_configs_read:
        #         inp_file_name = self.pick_inp(self,inp_dir)
        #     else:
        #         inp_file_name = self.pick_inp(self,self.WD)
        # elif not os.path.isfile(os.path.realpath(inp_file)):
        #     inp_file = os.path.realpath(inp_file)
        #     if os.path.isfile(os.path.join(self.WD, inp_file)):
        #         inp_file_name = os.path.join(self.WD, inp_file)
        #     elif usr_configs_read:
        #         if os.path.isfile(os.path.join(inp_dir, os.path.basename(inp_file))):
        #             inp_file_name = os.path.join(inp_dir, os.path.basename(inp_file))
        #     else:
        #         print(f"-E- Could not find .inp file {inp_file}")
        #         return
        # else:
        #     inp_file_name = inp_file

        # self.inp_file = inp_file_name
        # magic_files = {}
        # self.read_inp(self.WD, self.inp_file, magic_files, self.data_model)
        # self.combine_magic_files(self.WD, magic_files, self.data_model)
        self.on_new_inp()
        self.update_loop(force_update=True)
        self.set_statusbar()

        self.timer = Timer(self, ID_ANY)
        self.timer.Start(self.delay_time * 1000)
        self.Bind(EVT_TIMER, self.on_timer)
        self.Bind(wx.EVT_CLOSE, self.OnClose)
        # disable test mode to enable dialogs once GUI has started up
        super().set_test_mode(False)

    ####################################################
    #  initialization methods/changes to the main GUI  #
    ####################################################

    def au_add_buttons(self):
        """
        add buttons to toggle timer and to stream from main data directory (Dropbox)
        """
        self.top_bar_sizer = self.panel.GetSizer()
        self.top_bar_h_space = 10
        au_status_sizer = wx.StaticBoxSizer(
            wx.StaticBox(self.panel, wx.ID_ANY, "Autoupdate Status"),
            wx.VERTICAL)
        self.au_status_button = wx.ToggleButton(self.panel,
                                                id=wx.ID_ANY,
                                                size=(100 *
                                                      self.GUI_RESOLUTION, 25))
        self.au_status_button.SetValue(True)
        self.au_status_button.SetLabelMarkup("<span foreground='green'><b>" +
                                             "{}</b></span>".format("Running"))
        self.go_live = wx.ToggleButton(self.panel,
                                       id=wx.ID_ANY,
                                       label='Go Live',
                                       size=(100 * self.GUI_RESOLUTION, 25))
        au_status_btn_sizer = wx.GridSizer(2, 1, 10, 0)
        au_status_btn_sizer.AddMany([
            (self.au_status_button, 1, wx.ALIGN_RIGHT | wx.EXPAND),
            (self.go_live, 1, wx.ALIGN_RIGHT | wx.EXPAND)
        ])
        au_status_sizer.Add(au_status_btn_sizer, 1, wx.TOP | wx.EXPAND, 5)
        self.top_bar_sizer.Add(au_status_sizer, 1, wx.ALIGN_LEFT | wx.LEFT,
                               self.top_bar_h_space)
        self.Bind(wx.EVT_TOGGLEBUTTON, self.on_au_status_button,
                  self.au_status_button)
        self.Bind(wx.EVT_TOGGLEBUTTON, self.on_go_live, self.go_live)
        self.top_bar_sizer.Layout()

    def au_set_icon(self):
        """
        set icon
        """
        if usr_configs_read and sys.platform.startswith("darwin"):
            self.icon = wx.Icon()
            self.icon.LoadFile(os.path.join(pkg_dir, "images",
                                            "dmg_au_icon.icns"),
                               type=wx.BITMAP_TYPE_ICON,
                               desiredWidth=1024,
                               desiredHeight=1024)
            self.taskicon = wx.adv.TaskBarIcon(wx.adv.TBI_DOCK)
            self.taskicon.SetIcon(self.icon)
            self.SetIcon(self.icon)
        elif usr_configs_read and sys.platform.startswith("win"):
            self.icon = wx.Icon()
            self.icon.LoadFile(os.path.join(pkg_dir, "images",
                                            "dmg_au_icon.ico"),
                               type=wx.BITMAP_TYPE_ICO,
                               desiredWidth=1024,
                               desiredHeight=1024)
            self.SetIcon(self.icon)

    ####################
    #  static methods  #
    ####################

    # @staticmethod
    # def shortpath(abspath):
    #     return abspath.replace(os.path.expanduser('~') + os.sep, '~/', 1)

    # @staticmethod
    # def delete_magic_files(self, WD, data_model=3.0):
    #     compiled_file_names = [
    #         'measurements.txt',
    #         'specimens.txt',
    #         'samples.txt',
    #         'sites.txt',
    #         'locations.txt',
    #         'contribution.txt',
    #         'criteria.txt',
    #         'ages.txt',
    #         'images.txt',
    #         '.magic']
    #     wd_files = list(filter(os.path.isfile, map(lambda x: os.path.join(WD, x),
    #                                                os.listdir(WD))))
    #     mfiles = list(filter(lambda x: any([str(x).endswith(fname) for fname in compiled_file_names]),wd_files))
    #     for mfile in compiled_file_names:
    #         os.remove(os.path.relpath(mfile))
    #         print("-I- Removing %s" % (os.path.relpath(mfile)))

    # @staticmethod
    # def clr_output(raw_str):
    #     if str(raw_str).startswith('-I-'):
    #         print(bcolors.OKGREEN + raw_str + bcolors.ENDC)
    #     elif str(raw_str).startswith('-W-'):
    #         print(bcolors.WARNING + raw_str + bcolors.ENDC)
    #     elif str(raw_str).startswith('-E-'):
    #         print(bcolors.FAIL + raw_str + bcolors.ENDC)
    #     else:
    #         print(raw_str)

    ##############################################
    #  get attributes (and other useful values)  #
    ##############################################

    def get_inp(self):
        """
        get name of current inp file

        """
        return self.inp_file

    def get_status(self):
        try:
            timer_status = self.timer.IsRunning()
        except:
            timer_status = True
        return timer_status

    def get_status_msg(self):
        timer_status = self.get_status()
        if timer_status:
            return "Running"
        else:
            return "Paused"

    def get_sam_path(self):
        inp_file = open(self.inp_file, "r")
        lines = inp_file.read().splitlines()
        inp_file.close()
        all_sam_files = [shortpath(x.split('\t')[0]) for x in lines[2:]]
        if len(all_sam_files) == 1:
            sam_files = os.path.dirname(all_sam_files[0])
        else:
            sam_files = os.path.commonpath(all_sam_files)
        return sam_files

    ########################################
    #  event handlers and related methods  #
    ########################################

    def toggle_timer(self):
        if self.timer.IsRunning():
            self.timer.Stop()
            print("-I- Timer stopped")
        else:
            self.timer.Start(self.delay_time * 1000)
            print("-I- Timer started")
        self.set_statusbar()

    def set_statusbar(self, info=None):
        status_font = wx.Font(wx.FontInfo())  # .Bold())
        # font settings copied from demag_gui
        FONT_WEIGHT = 1
        if sys.platform.startswith('win'):
            FONT_WEIGHT = -1
        font1 = wx.Font(9 + FONT_WEIGHT, wx.SWISS, wx.NORMAL, wx.NORMAL, False,
                        self.font_type)
        font2 = wx.Font(11 + FONT_WEIGHT, wx.SWISS, wx.NORMAL, wx.NORMAL,
                        False, self.font_type)
        font = wx.SystemSettings.GetFont(wx.SYS_SYSTEM_FONT)
        font.SetPointSize(10 + FONT_WEIGHT)

        timer_status = self.get_status()
        self.statusbar.SetFont(font2)
        if info is not None:
            self.statusbar.SetStatusText(info)
            self.statusbar.SetBackgroundColour(wx.Colour(96, 194, 242))
        elif timer_status:
            self.statusbar.SetStatusText('Reading data from %s' %
                                         (self.get_sam_path()))
            self.statusbar.SetBackgroundColour(wx.Colour(193, 240, 193))
        else:
            self.statusbar.SetStatusText('Paused on data from %s' %
                                         (self.get_sam_path()))
            self.statusbar.SetBackgroundColour(wx.Colour(255, 255, 153))

    def on_menu_pick_read_inp(self, event):
        if self.get_status:
            self.toggle_timer()
        self.set_statusbar(info="Selecting new inp file...")
        global usr_configs_read, inp_dir
        if usr_configs_read:
            inp_file_name = self.pick_inp(self, inp_dir)
        else:
            inp_file_name = self.pick_inp(self, self.WD)
        if inp_file_name is None:
            self.toggle_timer()
            return
        self.inp_file = inp_file_name
        # reinitialize one-shot warning with new inp file
        self.warn_comments_in_inpfile = False
        magic_files = {}
        self.read_inp(self.WD, self.inp_file, magic_files, self.data_model)
        self.combine_magic_files(self.WD, magic_files, self.data_model)

        # recall a bunch of methods from demag_gui __init__
        self.on_new_inp()
        self.update_loop(force_update=True)
        self.toggle_timer()
        return self.inp_file

    def on_timer(self, event):
        update_thread = Thread(target=self.update_loop,
                               kwargs={
                                   "inp_file": self.inp_file,
                                   "delay_time": self.delay_time,
                                   "data_model": self.data_model
                               })
        update_thread.start()

    def on_au_status_button(self, event):
        self.toggle_timer()
        status, status_msg = self.get_status(), self.get_status_msg()
        if status:
            self.au_status_button.SetValue(True)
            self.au_status_button.SetLabelMarkup(
                "<span foreground='green'><b>{}</b></span>".format(status_msg))
        else:
            self.au_status_button.SetValue(False)
            self.au_status_button.SetLabelMarkup(
                "<span foreground='red'>{}</span>".format(status_msg))

    def on_go_live(self, event):
        if self.go_live.GetValue():
            self.au_status_button.Disable()
            self.go_live.SetLabelMarkup(
                "<span foreground='green'><b>{}</b></span>".format("Live!"))
        else:
            self.au_status_button.Enable()
            self.go_live.SetLabel("Go Live")

    def on_new_inp(self):
        print("-I- Reading from .inp file %s" % (shortpath(self.inp_file)))
        inp = open(self.inp_file, "r")
        inp_lines = inp.read().splitlines()[2:]
        inp.close()
        # filter out commented lines for printing
        operable_lines = [x for x in inp_lines if not x.startswith("# ")]
        for inp_line in operable_lines:
            print("-I- Tracking updates at %s" %
                  (shortpath(inp_line.split('\t')[0])))

        # initialize acceptence criteria with NULL values
        self.acceptance_criteria = self.read_criteria_file()

        # initalize starting variables and structures
        self.font_type = "Arial"
        if sys.platform.startswith("linux"):
            self.font_type = "Liberation Serif"

        self.preferences = self.get_preferences()
        self.dpi = 100

        self.all_fits_list = []

        self.pmag_results_data = {}
        for level in ['specimens', 'samples', 'sites', 'locations', 'study']:
            self.pmag_results_data[level] = {}

        self.high_level_means = {}
        for high_level in ['samples', 'sites', 'locations', 'study']:
            if high_level not in list(self.high_level_means.keys()):
                self.high_level_means[high_level] = {}

        self.ie_open = False
        self.check_orient_on = False
        self.list_bound_loc = 0
        self.all_fits_list = []
        self.current_fit = None
        self.selected_meas = []
        self.selected_meas_artists = []
        self.displayed_means = []
        self.selected_meas_called = False
        self.dirtypes = ['DA-DIR', 'DA-DIR-GEO', 'DA-DIR-TILT']
        self.bad_fits = []
        self.CART_rot, self.CART_rot_good, self.CART_rot_bad = array(
            []), array([]), array([])

        # initialize selecting criteria
        self.COORDINATE_SYSTEM = 'geographic'
        self.UPPER_LEVEL_SHOW = 'specimens'

        # Get data
        self.Data_info = self.get_data_info()  # Read  er_* data
        # Get data from magic_measurements and rmag_anistropy if exist.
        self.Data, self.Data_hierarchy = self.get_data()

        # get list of sites
        self.locations = list(self.Data_hierarchy['locations'].keys())
        self.locations.sort()  # get list of sites
        # get list of sites
        self.sites = list(self.Data_hierarchy['sites'].keys())
        self.sites.sort(key=spec_key_func)  # get list of sites
        self.samples = []  # sort the samples within each site
        for site in self.sites:
            self.samples.extend(
                sorted(self.Data_hierarchy['sites'][site]['samples'],
                       key=spec_key_func))
        self.specimens = []  # sort the specimens within each sample
        for samp in self.samples:
            self.specimens.extend(
                sorted(self.Data_hierarchy['samples'][samp]['specimens'],
                       key=spec_key_func))

        # first initialization of self.s only place besides init_cart_rot where it can be set without calling select_specimen
        if len(self.specimens) > 0:
            self.s = str(self.specimens[0])
        else:
            self.s = ""
        try:
            self.sample = self.Data_hierarchy['sample_of_specimen'][self.s]
        except KeyError:
            self.sample = ""
        try:
            self.site = self.Data_hierarchy['site_of_specimen'][self.s]
        except KeyError:
            self.site = ""
        # Draw figures and add text
        if self.Data and any(self.Data[s][k] if not isinstance(
                self.Data[s][k], type(array([]))) else self.Data[s][k].any()
                             for s in self.Data for k in self.Data[s]):
            # get previous interpretations from pmag tables
            if self.data_model == 3.0 and 'specimens' in self.con.tables:
                self.get_interpretations3()
            else:
                self.update_pmag_tables()
            if not self.current_fit:
                self.update_selection_inp()
            else:
                self.Add_text()
                self.update_fit_boxes()
                self.update_high_level_stats()
        else:
            pass

    ####################################
    #  core methods for handling data  #
    ####################################

    def update_loop(self,
                    inp_file=None,
                    force_update=False,
                    delay_time=1,
                    data_model=3.0):
        print("-I- checking for updates at {0}".format(asctime()))
        if self.inp_file is None:
            inp_file_names = self.get_all_inp_files(self.WD)

            if inp_file_names == []:
                print("-W- No inp files found in any subdirectories of "
                      "%s, aborting update checking thread" % self.WD)
                self.timer.Stop()

                return
            magic_files = {}
            update_list = []

            for inp_file_name in inp_file_names:
                update_list.append(
                    self.read_inp(self.WD, inp_file_name, magic_files,
                                  data_model))
            update_needed = any(update_list)
        else:
            inp_file_name = self.inp_file
            magic_files = {}
            update_needed = self.read_inp(self.WD, inp_file_name, magic_files,
                                          data_model)
        if update_needed or force_update:
            print("-I- Resetting...")
            self.combine_magic_files(self.WD,
                                     magic_files,
                                     data_model=data_model)
            CallAfter(self.reset_backend, warn_user=False, reset_interps=False)
            print("-I- Reset")

    def get_all_inp_files(self, WD=None):
        WD = os.path.abspath(WD)

        if not os.path.isdir(WD):
            print("-W- directory %s does not exist, aborting" % WD)

            return []
        try:
            all_inp_files = []

            for root, dirs, files in os.walk(WD):
                for d in dirs:
                    all_inp_files += self.get_all_inp_files(
                        os.path.join(root, d))

                for f in files:
                    if f.endswith(".inp") and f not in map(
                            lambda x: os.path.split(x)[1], all_inp_files):
                        all_inp_files.append(os.path.join(root, f))

            return all_inp_files
        except RuntimeError:
            raise RuntimeError(
                "Recursion depth exceded, please use different working "
                "directory. There are too many sub-directeries to walk")

    def read_inp(self, WD, inp_file_name, magic_files, data_model=3.0):
        inp_file = open(inp_file_name, "r")
        new_inp_file = ""

        if type(magic_files) != dict:
            magic_files = {}

        if 'measurements' not in magic_files.keys():
            magic_files['measurements'] = []

        if 'specimens' not in magic_files.keys():
            magic_files['specimens'] = []

        if 'samples' not in magic_files.keys():
            magic_files['samples'] = []

        if 'sites' not in magic_files.keys():
            magic_files['sites'] = []

        if 'locations' not in magic_files.keys():
            magic_files['locations'] = []

        lines = inp_file.read().splitlines()

        if len(lines) < 3:
            print("-W- File %s appears to be improperly formatted" %
                  (os.path.basename(inp_file_name)))
            return
        new_inp_file = lines[0] + "\r\n" + lines[1] + "\r\n"
        [lines.remove('') for i in range(lines.count(''))]

        format = lines[0].strip()
        header = lines[1].split('\t')
        update_files = lines[2:]
        # ignore lines that have been commented out (see the final lines of
        # this method) due to CIT/MagIC conversion failure, which is
        # usually a consequence of insufficient data
        #
        # (lines commented out will be added back to the inp file at end of this
        # method)
        update_files_commented = [
            x for x in update_files if x.startswith("# ")
        ]
        if len(update_files_commented
               ) > 0 and not self.warn_comments_in_inpfile:
            print(
                textwrap.dedent("""\
            -W- There are currently {} commented lines in the file {}. These lines
                will be ignored until the hash marks/comments are removed by the user.\
                                  """.format(len(update_files_commented),
                                             os.path.basename(self.inp_file))))
            self.warn_comments_in_inpfile = True

        update_files = [x for x in update_files if not x.startswith("# ")]
        update_data = False

        for i, update_file in enumerate(update_files):
            update_lines = update_file.split('\t')

            if not os.path.isfile(update_lines[0]):
                print("-I- %s not found; searching for location of file..." %
                      (update_lines[0]))
                sam_file_name = os.path.split(update_lines[0])[-1]
                new_file_path = find_file(sam_file_name, WD)

                if new_file_path is None or not os.path.isfile(new_file_path):
                    print(
                        "-W- %s does not exist in any subdirectory of %s and "
                        "will be skipped" % (update_lines[0], WD))
                    new_inp_file += update_file + "\r\n"

                    continue
                else:
                    print("-I- new location for file found at %s" %
                          (new_file_path))
                    update_lines[0] = new_file_path
            d = os.path.dirname(update_lines[0])
            name = os.path.basename(os.path.splitext(update_lines[0])[0])
            erspecf = name + "_specimens.txt"
            ersampf = name + "_samples.txt"
            ersitef = name + "_sites.txt"
            erlocf = name + "_locations.txt"
            f = name + ".magic"

            if os.path.join(d, f) in magic_files:
                new_inp_file += update_file + "\r\n"
                continue

            if float(update_lines[-1]) >= os.path.getmtime(update_lines[0]):
                no_changes = True
                # check specimen files for changes
                sam_file = open(update_lines[0])
                sam_file_lines = sam_file.read().splitlines()
                spec_file_paths = map(
                    lambda x: os.path.join(d, x.strip('\r \n')),
                    sam_file_lines[2:])

                for spec_file_path in spec_file_paths:
                    if float(update_lines[-1]) < \
                            os.path.getmtime(spec_file_path):
                        no_changes = False
                        break

                if no_changes and os.path.isfile(os.path.join(WD, f)) \
                        and os.path.isfile(os.path.join(WD, erspecf)) \
                        and os.path.isfile(os.path.join(WD, ersampf)) \
                        and os.path.isfile(os.path.join(WD, ersitef)) \
                        and (data_model != 3.0 or
                             os.path.isfile(os.path.join(WD, erlocf))):
                    magic_files['measurements'].append(os.path.join(WD, f))
                    magic_files['specimens'].append(os.path.join(WD, erspecf))
                    magic_files['samples'].append(os.path.join(WD, ersampf))
                    magic_files['sites'].append(os.path.join(WD, ersitef))
                    magic_files['locations'].append(os.path.join(WD, erlocf))
                    new_inp_file += update_file + "\r\n"
                    continue

            if len(header) != len(update_lines):
                print(
                    "-W- length of header and length of entries for the file "
                    "%s are different and will be skipped" % (update_lines[0]))
                new_inp_file += update_file + "\r\n"
                continue
            update_dict = {}

            for head, entry in zip(header, update_lines):
                update_dict[head] = entry

            if format == "CIT":
                CIT_kwargs = {}
                CIT_name = os.path.basename(
                    os.path.splitext(update_dict["sam_path"])[0])
                # cannot output to sam_path since this is in the locked
                # Dropbox directory; output to WD instead
                # CIT_kwargs["dir_path"] = reduce(lambda x,y: x+"/"+y,
                #   update_dict["sam_path"].split("/")[:-1])
                CIT_kwargs["dir_path"] = WD
                CIT_kwargs["user"] = ""
                CIT_kwargs["meas_file"] = CIT_name + ".magic"
                CIT_kwargs["spec_file"] = CIT_name + "_specimens.txt"
                CIT_kwargs["samp_file"] = CIT_name + "_samples.txt"
                CIT_kwargs["site_file"] = CIT_name + "_sites.txt"
                CIT_kwargs["loc_file"] = CIT_name + "_locations.txt"
                CIT_kwargs["locname"] = update_dict["location"]
                CIT_kwargs["methods"] = update_dict["field_magic_codes"]
                CIT_kwargs["specnum"] = update_dict["num_terminal_char"]
                CIT_kwargs["noave"] = update_dict[("dont_average_replicate"
                                                   "_measurements")]
                CIT_kwargs["samp_con"] = update_dict["naming_convention"]
                # CIT_kwargs["peak_AF"] = update_dict["peak_AF"]
                CIT_kwargs["magfile"] = os.path.basename(
                    update_dict["sam_path"])
                CIT_kwargs["input_dir_path"] = os.path.dirname(
                    update_dict["sam_path"])
                # CIT_kwargs["data_model"] = data_model
                # print('-I- from .inp file, converting {} to MagIC with the'
                # 'following parameters:'.format(CIT_kwargs["magfile"]))
                # try:
                #     import textwrap
                #     print(textwrap.indent(str(CIT_kwargs),4*' '))
                # except:
                #     print(str(CIT_kwargs))

                if float(data_model) == 3.0:
                    program_ran, error_message = convert.cit(**CIT_kwargs)
                else:
                    program_ran, error_message = cit_magic.main(
                        command_line=False, **CIT_kwargs)

                measp = os.path.join(CIT_kwargs["dir_path"],
                                     CIT_kwargs["meas_file"])
                specp = os.path.join(CIT_kwargs["dir_path"],
                                     CIT_kwargs["spec_file"])
                sampp = os.path.join(CIT_kwargs["dir_path"],
                                     CIT_kwargs["samp_file"])
                sitep = os.path.join(CIT_kwargs["dir_path"],
                                     CIT_kwargs["site_file"])
                locp = os.path.join(CIT_kwargs["dir_path"],
                                    CIT_kwargs["loc_file"])
                # print(measp, specp, sampp, sitep, locp)

                if program_ran:
                    update_data = True
                    update_lines[-1] = time()
                    new_inp_file += reduce(lambda x, y: str(x) + "\t" + str(y),
                                           update_lines) + "\r\n"
                    magic_files['measurements'].append(measp)
                    magic_files['specimens'].append(specp)
                    magic_files['samples'].append(sampp)
                    magic_files['sites'].append(sitep)
                    magic_files['locations'].append(locp)
                else:
                    # TODO: This depends on convert.cit() returning a False
                    # value, which was modified in the conversion module (it
                    # currently always returns True, even if the conversion
                    # ultimately fails) <09-08-18, Luke Fairchild> #
                    """
                    small note: For the case at present, I've organized and
                    combined inp files by project, which can nicely be done now
                    using combine_inp_files.py. However, some sites do not yet
                    have data yet, which was causing problems in this part of
                    the code. Being able to comment out lines seems to be a more
                    elegant solution than deleting these lines manually or
                    moving the copied inp files out of the local directory.
                    <09-08-18, Luke Fairchild>
                    """
                    # comment out the lines/sites for which CIT to MagIC conversion
                    # failed
                    new_inp_file += "# " + update_file + "\r\n"
                    print("""\
                          -W- CIT to MagIC conversion failed for site {}. The
                          line containing information for this site has been
                          marked/commented out within the file {} and will be
                          ignored until modified by the
                          user.""".format(CIT_name, shortpath(self.inp_file)))

                    if os.path.isfile(measp) and \
                       os.path.isfile(specp) and \
                       os.path.isfile(sampp) and \
                       os.path.isfile(sitep) and \
                       os.path.isfile(locp):
                        magic_files['measurements'].append(measp)
                        magic_files['specimens'].append(specp)
                        magic_files['samples'].append(sampp)
                        magic_files['sites'].append(sitep)
                        magic_files['locations'].append(locp)

        inp_file.close()
        out_file = open(inp_file_name, "w")
        out_file.write(new_inp_file)
        # write back any ignored lines to end of file
        for l in update_files_commented:
            out_file.write(l + "\r\n")
        # out_file.close()

        return update_data

    def combine_magic_files(self, WD, magic_files, data_model=3.0):  # 2.5
        if type(magic_files) != dict:
            return

        if data_model == 3.0:
            # try:
            if 'measurements' in magic_files.keys():
                for dot_magic in magic_files['measurements']:
                    if not os.path.isfile(dot_magic):
                        magic_files['measurements'].remove(dot_magic)
                        print('-W- No data for {}'.format(dot_magic))
                combine_magic(magic_files['measurements'],
                              os.path.join(WD, "measurements.txt"))

            if 'specimens' in magic_files.keys():
                combine_magic(magic_files['specimens'],
                              os.path.join(WD, "specimens.txt"))

            if 'samples' in magic_files.keys():
                combine_magic(magic_files['samples'],
                              os.path.join(WD, "samples.txt"))

            if 'sites' in magic_files.keys():
                combine_magic(magic_files['sites'],
                              os.path.join(WD, "sites.txt"))

            if 'locations' in magic_files.keys():
                combine_magic(magic_files['locations'],
                              os.path.join(WD, "locations.txt"))
            # except FileNotFoundError:
            # pass
        else:
            if 'measurements' in magic_files.keys():
                combine_magic(magic_files['measurements'],
                              os.path.join(WD, "magic_measurements.txt"))

            if 'specimens' in magic_files.keys():
                combine_magic(magic_files['specimens'],
                              os.path.join(WD, "er_specimens.txt"))

            if 'samples' in magic_files.keys():
                combine_magic(magic_files['samples'],
                              os.path.join(WD, "er_samples.txt"))

            if 'sites' in magic_files.keys():
                combine_magic(magic_files['sites'],
                              os.path.join(WD, "er_sites.txt"))

    #############
    #  dialogs  #
    #############

    def pick_inp(self, parent, WD):
        dlg = wx.FileDialog(parent,
                            message="Choose .inp file",
                            defaultDir=WD,
                            defaultFile="magic.inp",
                            wildcard="*.inp",
                            style=wx.FD_OPEN)

        if dlg.ShowModal() == wx.ID_OK:
            inp_file_name = dlg.GetPath()
        else:
            # notify user that most recent file will be used
            disableAll = wx.WindowDisabler()
            wait = wx.BusyInfo('No inp file selected. Reading from'
                               ' most recently opened files...')
            wx.SafeYield()
            sleep(1.5)
            del wait
            inp_file_name = None
        dlg.Destroy()
        return inp_file_name

    # TODO: The following method should really be implemented in demag_gui; the call
    # to self.level_names.SetValue in self.update_selection is ignored because
    # the combobox self.level_names is readonly <08-12-18, Luke Fairchild> #

    def update_selection_inp(self):
        """
        Convenience function update display (figures, text boxes and
        statistics windows) with a new selection of specimen
        """
        self.clear_boxes()
        # commented out to allow propogation of higher level viewing state
        self.clear_high_level_pars()

        if self.UPPER_LEVEL_SHOW != "specimens":
            self.mean_type_box.SetValue("None")

        # --------------------------
        # check if the coordinate system in the window exists (if not change to "specimen" coordinate system)
        # --------------------------

        coordinate_system = self.coordinates_box.GetValue()
        if coordinate_system == 'tilt-corrected' and \
           len(self.Data[self.s]['zijdblock_tilt']) == 0:
            self.coordinates_box.SetStringSelection('specimen')
        elif coordinate_system == 'geographic' and \
                len(self.Data[self.s]['zijdblock_geo']) == 0:
            self.coordinates_box.SetStringSelection("specimen")
        if coordinate_system != self.coordinates_box.GetValue(
        ) and self.ie_open:
            self.ie.coordinates_box.SetStringSelection(
                self.coordinates_box.GetValue())
            self.ie.update_editor()
        coordinate_system = self.coordinates_box.GetValue()
        self.COORDINATE_SYSTEM = coordinate_system

        # --------------------------
        # update treatment list
        # --------------------------

        self.update_bounds_boxes()

        # --------------------------
        # update high level boxes
        # --------------------------

        high_level = self.level_box.GetValue()
        old_string = self.level_names.GetValue()
        new_string = old_string
        if high_level == 'sample':
            if self.s in self.Data_hierarchy['sample_of_specimen']:
                new_string = self.Data_hierarchy['sample_of_specimen'][self.s]
            else:
                new_string = ''
        if high_level == 'site':
            if self.s in self.Data_hierarchy['site_of_specimen']:
                new_string = self.Data_hierarchy['site_of_specimen'][self.s]
            else:
                new_string = ''
        if high_level == 'location':
            if self.s in self.Data_hierarchy['location_of_specimen']:
                new_string = self.Data_hierarchy['location_of_specimen'][
                    self.s]
            else:
                new_string = ''
        self.level_names.SetString(0, new_string)
        if self.ie_open and new_string != old_string:
            self.ie.level_names.SetValue(new_string)
            self.ie.on_select_level_name(-1, True)

        # --------------------------
        # update PCA box
        # --------------------------

        self.update_PCA_box()

        # update warning
        self.generate_warning_text()
        self.update_warning_box()
        # update choices in the fit box
        self.update_fit_boxes()
        self.update_mean_fit_box()
        # measurements text box
        self.Add_text()
        # draw figures
        if self.current_fit:
            self.draw_figure(self.s, False)
        else:
            self.draw_figure(self.s, True)
        # update high level stats
        self.update_high_level_stats()
        # redraw interpretations
        self.update_GUI_with_new_interpretation()

    # def sigint_catcher(self, sig, frame):
    #     # wx.PostEvent(self.OnClose, wx.EVT_CLOSE)
    #     self.OnClose(wx.EVT_CLOSE)

    def OnClose(self, event):
        """
        Close down all processes
        """
        # stop the timer
        if self.timer.IsRunning():
            self.timer.Stop()
            print("-I- Timer stopped")
        # cache site-level magic files to de-clutter data directory
        cache_site_files(self.WD)
        print("-I- Site-level magic files stored in 'magic_cache'")
        self.Destroy()
Exemple #2
0
class TestPanel(BaseWindowPanel):
    def __init__(self, parent):
        BaseWindowPanel.__init__(self,
                                 parent,
                                 bg_color=Colour.BLACK,
                                 fg_color=Colour.WHITE)

        self._caption_label = StaticText(self,
                                         pos=(70, 5),
                                         size=(20, 0),
                                         label=u"This month, we spent")
        self._caption_label.SetFont(
            Font(13, FONTFAMILY_DEFAULT, FONTSTYLE_NORMAL, FONTWEIGHT_NORMAL))

        self._display = LEDNumberCtrl(self,
                                      pos=(0, 30),
                                      size=(320, 90),
                                      style=LED_ALIGN_RIGHT)
        self._display.SetValue("0.00")

        self._date_display = LEDNumberCtrl(self,
                                           pos=(110, 150),
                                           size=(210, 40),
                                           style=LED_ALIGN_RIGHT)
        self._date_display.SetValue("--.--.--")

        self._clock_display = LEDNumberCtrl(self,
                                            pos=(110, 190),
                                            size=(210, 50),
                                            style=LED_ALIGN_RIGHT)
        self._clock_display.SetValue("--.--.--")

        self.open_button = Button(self,
                                  -1,
                                  "Add",
                                  pos=(10, 125),
                                  size=(70, 35))
        self.open_button.SetBackgroundColour(Colour.DARK_GREEN)
        self.open_button.SetForegroundColour(Colour.WHITE)

        self.list_button = Button(self,
                                  -1,
                                  "List",
                                  pos=(10, 160),
                                  size=(70, 35))
        self.list_button.SetBackgroundColour(get_colour(0x333333))
        self.list_button.SetForegroundColour(Colour.WHITE)

        self.close_button = Button(self,
                                   -1,
                                   "Close",
                                   pos=(10, 195),
                                   size=(70, 35))
        self.close_button.SetBackgroundColour(Colour.DARK_RED)
        self.close_button.SetForegroundColour(Colour.WHITE)

        self._timer = Timer(self)
        self._timer.Start(100)
        self.Bind(EVT_TIMER, self.on_clock_update, self._timer)

    def set_display(self, value):
        """
        :param float value:
        """
        self._display.SetValue("{:.2f}".format(value))

    def on_clock_update(self, e):
        self._clock_display.SetValue(datetime.now().strftime("%H:%M:%S"))
        self._date_display.SetValue(datetime.now().strftime("%d-%m-%Y"))
Exemple #3
0
class TimerDisplay(Panel):
    def __init__(self, main_window, *args, **kw):
        super().__init__(*args, **kw)
        self.timer = Timer(self)

        self.main_window = main_window

        self.time_display = WatchText(self, label=TIMER_LABEL)
        self.start_btn = NormalButton(self, label=START_LABEL)
        self.pause_btn = NormalButton(self, label=PAUSE_LABEL)
        self.reset_btn = NormalButton(self, label=STOP_LABEL)

        self.maneger = TimeManeger(self.main_window, self)
        self.layout()
        self.Bind(EVT_TIMER, self.update_watch)

    def layout(self):
        vbox = BoxSizer(VERTICAL)
        self.SetSizer(vbox)
        hbox = BoxSizer(HORIZONTAL)

        hbox.Add(self.start_btn, 1, ALIGN_CENTER | RIGHT, 10)
        hbox.Add(self.pause_btn, 1, ALIGN_CENTER | RIGHT | LEFT, 5)
        hbox.Add(self.reset_btn, 1, ALIGN_CENTER | LEFT, 10)

        vbox.Add(self.time_display, 0, ALIGN_CENTER | ALL, 10)
        vbox.Add(hbox, 1, ALIGN_CENTER)
        vbox.Add(StaticLine(self, ID_ANY, size=(3000, 2)), 0, TOP, 5)

        self.pause_btn.Disable()
        self.reset_btn.Disable()

    def start(self):
        if self.state not in [NORMAL, PAUSE]:
            return

        if self.state == NORMAL:
            self.start_btn.Disable()
            self.pause_btn.Enable()
            self.reset_btn.Enable()

            self.timer.Start(100)
            self.maneger.start()

        elif self.state == PAUSE:
            self.restart()

    def pause(self):
        self.start_btn.Enable()
        self.pause_btn.Disable()
        self.timer.Stop()

        self.maneger.pause()

    def restart(self):
        self.start_btn.Disable()
        self.pause_btn.Enable()
        self.timer.Start()

    def reset(self):
        self.start_btn.Enable()
        self.pause_btn.Disable()
        self.reset_btn.Disable()

        self.time_display.SetLabel(TIMER_LABEL)
        self.timer.Stop()

        self.maneger.reset()

    def update_watch(self, event):
        total_seconds = self.maneger.get_elapsed_time().seconds
        h, m, s = map(str, get_hms(total_seconds))
        watch_label = '{}:{}:{}'.format(h.zfill(2), m.zfill(2), s.zfill(2))
        self.time_display.SetLabel(watch_label)

        event.Skip()

    @property
    def state(self):
        if self.start_btn.IsEnabled() and not self.pause_btn.IsEnabled(
        ) and not self.reset_btn.IsEnabled():
            return NORMAL

        if not self.start_btn.IsEnabled() and self.pause_btn.IsEnabled(
        ) and self.reset_btn.IsEnabled():
            return RUNNING

        if self.start_btn.IsEnabled(
        ) and not self.pause_btn.IsEnabled() and self.reset_btn.IsEnabled():
            return PAUSE

        return ERROR