def run_interpreter(self):
        """
        Run thellier_auto_interpreter
        """

        import random
        import copy

        start_time = time.time()
        #------------------------------------------------
        # Clean work directory
        #------------------------------------------------

        # self.write_acceptance_criteria_to_file()
        try:
            shutil.rmtree(os.path.join(self.WD, "thellier_interpreter"))
        except:
            pass

        try:
            os.mkdir(os.path.join(self.WD, "thellier_interpreter"))
        except:
            pass

        #------------------------------------------------
        # Intialize interpreter output files:
        # Prepare header for "Thellier_auto_interpretation.all.txt"
        # All the acceptable interpretation are saved in this file
        #------------------------------------------------

        # sort acceptance criteria
        self.specimen_criteria = []
        for crit in list(self.acceptance_criteria.keys()):
            if 'category' in list(self.acceptance_criteria[crit].keys()):
                if self.acceptance_criteria[crit]['category'] == "IE-SPEC":
                    if self.acceptance_criteria[crit]['value'] != -999:
                        self.specimen_criteria.append(crit)

        # sort acceptance criteria
        sample_criteria = []
        for crit in list(self.acceptance_criteria.keys()):
            if 'category' in list(self.acceptance_criteria[crit].keys()):
                if self.acceptance_criteria[crit]['category'] == "IE-SAMP":
                    if self.acceptance_criteria[crit]['value'] != -999:
                        sample_criteria.append(crit)

        # sort acceptance criteria
        site_criteria = []
        for crit in list(self.acceptance_criteria.keys()):
            if 'category' in list(self.acceptance_criteria[crit].keys()):
                if self.acceptance_criteria[crit]['category'] == "thellier_gui":
                    if self.acceptance_criteria[crit]['value'] != -999:
                        site_criteria.append(crit)

        # sort acceptance criteria
        thellier_gui_criteria = []
        for crit in list(self.acceptance_criteria.keys()):
            if 'category' in list(self.acceptance_criteria[crit].keys()):
                if self.acceptance_criteria[crit]['category'] == "thellier_gui":
                    if self.acceptance_criteria[crit]['value'] != -999:
                        thellier_gui_criteria.append(crit)

        #----------------------------

        # log file
        self.thellier_interpreter_log = open(
            self.WD + "/" + "/thellier_interpreter//thellier_interpreter.log", 'w')
        self.thellier_interpreter_log.write("-I- Start auto interpreter\n")

        # "all grade A interpretation
        thellier_interpreter_all = open(
            self.WD + "/thellier_interpreter/thellier_interpreter_all.txt", 'w')
        thellier_interpreter_all.write("tab\tpmag_specimens\n")
        String = "er_specimen_name\tmeasurement_step_min\tmeasurement_step_max\tspecimen_lab_field_dc_uT\tspecimen_int_corr_anisotropy\tspecimen_int_corr_nlt\tspecimen_int_corr_cooling_rate\tspecimen_int_uT\t"
        # + ["specimen_b"] + ['specimen_cm_x'] + ['specimen_cm_y']:
        for crit in self.specimen_criteria:
            String = String + crit + "\t"
        String = String[:-1] + "\n"
        thellier_interpreter_all.write(String)

        # specimen_bound
        Fout_specimens_bounds = open(
            self.WD + "/thellier_interpreter/thellier_interpreter_specimens_bounds.txt", 'w')
        String = "acceptance criteria:\n"
        for crit in self.specimen_criteria:
            String = String + crit + "\t"
        Fout_specimens_bounds.write(String[:-1] + "\n")
        String = ""
        for crit in self.specimen_criteria:
            if type(self.acceptance_criteria[crit]['value']) == str:
                string = self.acceptance_criteria[crit]['value']
            elif type(self.acceptance_criteria[crit]['value']) == bool:
                string = str(self.acceptance_criteria[crit]['value'])
            elif type(self.acceptance_criteria[crit]['value']) == int or type(self.acceptance_criteria[crit]['value']) == float:
                if self.acceptance_criteria[crit]['decimal_points'] == -999:
                    string = "{:.3f}".format(self.acceptance_criteria[crit]['value'])
                else:
                    string = "{:.{}f}".format(self.acceptance_criteria[crit]['value'],
                                             self.acceptance_criteria[crit]['decimal_points'])

            else:
                string=""

            String=String+"%s\t"%string
        Fout_specimens_bounds.write(String[:-1]+"\n")
        Fout_specimens_bounds.write("--------------------------------\n")
        Fout_specimens_bounds.write("er_sample_name\ter_specimen_name\tspecimen_int_corr_anisotropy\tAnisotropy_code\tspecimen_int_corr_nlt\tspecimen_int_corr_cooling_rate\tspecimen_lab_field_dc_uT\tspecimen_int_min_uT\tspecimen_int_max_uT\tWARNING\n")

        #----------------------------------

        criteria_string = "acceptance criteria:\n"
        for crit in self.specimen_criteria + sample_criteria + site_criteria + thellier_gui_criteria:
            criteria_string = criteria_string + crit + "\t"
        criteria_string = criteria_string[:-1] + "\n"
        for crit in self.specimen_criteria + sample_criteria + site_criteria + thellier_gui_criteria:
            if type(self.acceptance_criteria[crit]['value']) == str:
                string = self.acceptance_criteria[crit]['value']
            elif type(self.acceptance_criteria[crit]['value']) == bool:
                string = str(self.acceptance_criteria[crit]['value'])
            elif type(self.acceptance_criteria[crit]['value']) == int or type(self.acceptance_criteria[crit]['value']) == float:
                if self.acceptance_criteria[crit]['decimal_points'] == -999:
                    string = "%.3e" % (
                        float(self.acceptance_criteria[crit]['value']))
                else:
                    string = "{:.{}f}".format(self.acceptance_criteria[crit]['value'],
                                              self.acceptance_criteria[crit]['decimal_points'])
            else:
                string = ""

            criteria_string = criteria_string + "%s\t" % string
        criteria_string = criteria_string[:-1] + "\n"
        criteria_string = criteria_string + "---------------------------------\n"

        # STDEV-OPT output files
        if self.acceptance_criteria['interpreter_method']['value'] == 'stdev_opt':
            self.Fout_STDEV_OPT_redo = open(
                self.WD + "/thellier_interpreter/thellier_interpreter_STDEV-OPT_redo", 'w')
            self.Fout_STDEV_OPT_specimens = open(
                self.WD + "/thellier_interpreter/thellier_interpreter_STDEV-OPT_specimens.txt", 'w')

            self.Fout_STDEV_OPT_specimens.write("tab\tpmag_specimens\n")
            String = "er_sample_name\ter_specimen_name\tspecimen_int_uT\tmeasurement_step_min\tmeasurement_step_min\tspecimen_lab_field_dc\tAnisotropy_correction_factor\tNLT_correction_factor\tCooling_rate_correction_factor\t"
            for crit in self.specimen_criteria:
                String = String + crit + "\t"
            self.Fout_STDEV_OPT_specimens.write(String[:-1] + "\n")

            if self.acceptance_criteria['average_by_sample_or_site']['value'] == 'sample':
                self.Fout_STDEV_OPT_samples = open(
                    self.WD + "/thellier_interpreter/thellier_interpreter_STDEV-OPT_samples.txt", 'w')
                self.Fout_STDEV_OPT_samples.write(criteria_string)
                self.Fout_STDEV_OPT_samples.write(
                    "er_sample_name\tsample_int_n\tsample_int_uT\tsample_int_sigma_uT\tsample_int_sigma_perc\tsample_int_min_uT\tsample_int_min_sigma_uT\tsample_int_max_uT\tsample_int_max_sigma_uT\tsample_int_interval_uT\tsample_int_interval_perc\tWarning\n")
            else:
                self.Fout_STDEV_OPT_sites = open(
                    self.WD + "/thellier_interpreter/thellier_interpreter_STDEV-OPT_sites.txt", 'w')
                self.Fout_STDEV_OPT_sites.write(criteria_string)
                self.Fout_STDEV_OPT_sites.write(
                    "er_site_name\tsite_int_n\tsite_int_uT\tsite_int_sigma_uT\tsite_int_sigma_perc\tsite_int_min_uT\tsite_int_min_sigma_uT\tsite_int_max_uT\tsite_int_max_sigma_uT\tsite_int_interval_uT\tsite_int_interval_perc\tWarning\n")

        # simple bootstrap output files
        # Dont supports site yet!

        if self.acceptance_criteria['interpreter_method']['value'] == 'bs':
            Fout_BS_samples = open(
                self.WD + "/thellier_interpreter/thellier_interpreter_BS_samples.txt", 'w')
            Fout_BS_samples.write(criteria_string)
            # Fout_BS_samples.write("---------------------------------\n")
            Fout_BS_samples.write(
                "er_sample_name\tsample_int_n\tsample_int_uT\tsample_int_68_low\tsample_int_68_high\tsample_int_95_low\tsample_int_95_high\tsample_int_sigma_uT\tsample_int_sigma_perc\tWARNING\n")
        # parameteric bootstrap output files

        if self.acceptance_criteria['interpreter_method']['value'] == 'bs_par':
            Fout_BS_PAR_samples = open(
                self.WD + "/thellier_interpreter/thellier_interpreter_BS-PAR_samples.txt", 'w')
            Fout_BS_PAR_samples.write(criteria_string)
            # Fout_BS_PAR_samples.write("---------------------------------\n")
            Fout_BS_PAR_samples.write(
                "er_sample_name\tsample_int_n\tsample_int_uT\tsample_int_68_low\tsample_int_68_high\tsample_int_95_low\tsample_int_95_high\tsample_int_sigma_uT\tsample_int_sigma_perc\tWARNING\n")

        self.thellier_interpreter_log.write(
            "-I- using paleointenisty statistics:\n")
        self.thellier_interpreter_log.write(criteria_string)

        #------------------------------------------------

        specimens_list = list(self.Data.keys())
        specimens_list.sort()
        self.thellier_interpreter_log.write(
            "-I- Found %i specimens\n" % (len(specimens_list)))

        # try:
        All_grade_A_Recs = {}
        print('-I- Running through specimens:')
        for s in specimens_list:
            self.thellier_interpreter_log.write(
                "-I- doing now specimen %s\n" % s)
            self.Data[s]['pars'] = {}
            self.Data[s]['pars']['lab_dc_field'] = self.Data[s]['lab_dc_field']
            self.Data[s]['pars']['er_specimen_name'] = s
            self.Data[s]['pars']['er_sample_name'] = self.Data_hierarchy['specimens'][s]
            temperatures = self.Data[s]['t_Arai']

            # check that all temperatures are in right order:
            ignore_specimen = False
            for t in range(len(temperatures) - 1):
                if float(temperatures[t + 1]) < float(temperatures[t]):
                    self.thellier_interpreter_log.write(
                        "-W- Found problem in the temperature order of specimen %s. skipping specimen\n" % (s))
                    ignore_specimen = True
            if ignore_specimen:
                continue
            if self.acceptance_criteria['specimen_int_n']['value'] != -999:
                specimen_int_n = min(
                    3, int(self.acceptance_criteria['specimen_int_n']['value']))
            else:
                specimen_int_n = 3
            #-------------------------------------------------
            # loop through all possible tmin,tmax and check if pass criteria
            #-------------------------------------------------
            # print s
            for tmin_i in range(len(temperatures) - specimen_int_n + 1):
                # check if to include NRM
                # print temperatures
                # print  self.acceptance_criteria['include_nrm']['value']
                if self.acceptance_criteria['include_nrm']['value'] == -999:
                    # print " Its False"
                    if temperatures[tmin_i] == 273:
                        continue
                    #    print "ignoring NRM",tmin_i,temperatures[tmin_i]
                # print tmin_i
                for tmax_i in range(tmin_i + specimen_int_n - 1, len(temperatures)):
                    # print tmax_i
                    # print len(temperatures)
                    tmin = temperatures[tmin_i]
                    tmax = temperatures[tmax_i]
                    pars = thellier_gui_lib.get_PI_parameters(
                        self.Data, self.acceptance_criteria, self.preferences, s, tmin, tmax, self.GUI_log, THERMAL, MICROWAVE)
                    if not pars:  # error with getting pars
                        message_string = '-W- Problem in SPD. Could not calculate any parameters for {} with tmin: {} and tmax {}. Check data for typos, make sure temperatures are correct, etc.'.format(
                            s, tmin, tmax)
                        self.thellier_interpreter_log.write(
                            message_string + "\n")
                        continue
                    if 'NLT_specimen_correction_factor' not in list(pars.keys()):
                        # problem in get_PI_parameters (probably with
                        # tmin/zdata).  can't run specimen
                        message_string = '-W- Problem in get_PI_parameters. Could not get all parameters for {} with tmin: {} and tmax: {}. Check data for typos, make sure temperatures are correct, etc.'.format(
                            s, tmin, tmax)
                        self.thellier_interpreter_log.write(
                            message_string + "\n")
                        continue
                    pars = thellier_gui_lib.check_specimen_PI_criteria(
                        pars, self.acceptance_criteria)
                    #-------------------------------------------------
                    # check if pass the criteria
                    #-------------------------------------------------

                    if 'specimen_fail_criteria' in list(pars.keys()) and len(pars['specimen_fail_criteria']) > 0:
                        # Fail:
                        message_string = "-I- specimen %s (%.0f-%.0f) FAIL on: " % (s, float(
                            pars["measurement_step_min"]) - 273, float(pars["measurement_step_max"]) - 273)
                        for parameter in pars['specimen_fail_criteria']:
                            if "scat" not in parameter:
                                message_string = message_string + \
                                    parameter + "= %f,  " % pars[parameter]
                            else:
                                message_string = message_string + parameter + \
                                    "= %s,  " % str(pars[parameter])

                        self.thellier_interpreter_log.write(
                            message_string + "\n")
                    elif 'specimen_fail_criteria' in list(pars.keys()) and len(pars['specimen_fail_criteria']) == 0:

                        # PASS:
                        message_string = "-I- specimen %s (%.0f-%.0f) PASS" % (s, float(
                            pars["measurement_step_min"]) - 273, float(pars["measurement_step_max"]) - 273)
                        self.thellier_interpreter_log.write(
                            message_string + "\n")

                        #----------------------------------------------------
                        # Save all the grade A interpretation in thellier_interpreter_all.txt
                        #----------------------------------------------------

                        String = s + "\t"
                        String = String + \
                            "%.0f\t" % (
                                float(pars["measurement_step_min"]) - 273.)
                        String = String + \
                            "%.0f\t" % (
                                float(pars["measurement_step_max"]) - 273.)
                        String = String + \
                            "%.0f\t" % (float(pars["lab_dc_field"]) * 1e6)

                        if "Anisotropy_correction_factor" in list(pars.keys()):
                            String = String + \
                                "%.2f\t" % float(
                                    pars["Anisotropy_correction_factor"])
                        else:
                            String = String + "-\t"
                        if float(pars["NLT_specimen_correction_factor"]) != -999:
                            String = String + \
                                "%.2f\t" % float(
                                    pars["NLT_specimen_correction_factor"])
                        else:
                            String = String + "-\t"
                        if float(pars["specimen_int_corr_cooling_rate"]) != -999 and float(pars["specimen_int_corr_cooling_rate"]) != -1:
                            String = String + \
                                "%.2f\t" % float(
                                    pars["specimen_int_corr_cooling_rate"])
                        else:
                            String = String + "-\t"
                        Bancient = float(pars['specimen_int_uT'])
                        String = String + "%.1f\t" % (Bancient)
                        # + ["specimen_b"] + ["specimen_cm_x"] + ["specimen_cm_y"]:
                        for key in self.specimen_criteria:
                            if type(pars[key]) == str:
                                String = String + pars[key] + "\t"
                            else:
                                String = String + \
                                    "%.3e" % (float(pars[key])) + "\t"
                        String = String[:-1] + "\n"

                        thellier_interpreter_all.write(String)

                        #-------------------------------------------------
                        # save 'acceptable' (grade A) specimen interpretaion
                        # All_grade_A_Recs={}
                        # All_grade_A_Recs[specimen_name]["tmin,tmax"]={PI pars sorted in dictionary}
                        #-------------------------------------------------

                        if s not in list(All_grade_A_Recs.keys()):
                            All_grade_A_Recs[s] = {}
                        new_pars = {}
                        for k in list(pars.keys()):
                            new_pars[k] = pars[k]
                        TEMP = "%.0f,%.0f" % (float(
                            pars["measurement_step_min"]) - 273, float(pars["measurement_step_max"]) - 273)
                        All_grade_A_Recs[s][TEMP] = new_pars

        specimens_list = list(All_grade_A_Recs.keys())
        specimens_list.sort()
        Grade_A_samples = {}
        Grade_A_sites = {}
        Redo_data_specimens = {}

        #--------------------------------------------------------------
        # specimens bound file
        #--------------------------------------------------------------

        for s in specimens_list:

            sample = self.Data_hierarchy['specimens'][s]
            site = thellier_gui_lib.get_site_from_hierarchy(
                sample, self.Data_hierarchy)
            B_lab = float(self.Data[s]['lab_dc_field']) * 1e6
            B_min, B_max = 1e10, 0.
            NLT_factor_min, NLT_factor_max = 1e10, 0.
            all_B_tmp_array = []

            for TEMP in list(All_grade_A_Recs[s].keys()):
                pars = All_grade_A_Recs[s][TEMP]
                if "AC_anisotropy_type" in list(pars.keys()):
                    AC_correction_factor = pars["Anisotropy_correction_factor"]
                    AC_correction_type = pars["AC_anisotropy_type"]
                    WARNING = ""
                    if "AC_WARNING" in list(pars.keys()):
                        WARNING = WARNING + pars["AC_WARNING"]
                else:
                    AC_correction_factor = 1.
                    AC_correction_type = "-"
                    WARNING = "WARNING: No anisotropy correction"

                B_anc = pars['specimen_int_uT']

                if B_anc < B_min:
                    B_min = B_anc
                if B_anc > B_max:
                    B_max = B_anc
                if pars["NLT_specimen_correction_factor"] != -1:
                    NLT_f = pars['NLT_specimen_correction_factor']
                    if NLT_f < NLT_factor_min:
                        NLT_factor_min = NLT_f
                    if NLT_f > NLT_factor_max:
                        NLT_factor_max = NLT_f

                # sort by samples
                #------------------------------------------------------------

                if cb.not_null(sample, False):
                    if sample not in list(Grade_A_samples.keys()):
                        Grade_A_samples[sample] = {}
                    if s not in list(Grade_A_samples[sample].keys()) and len(All_grade_A_Recs[s]) > 0:
                        Grade_A_samples[sample][s] = []
                    if cb.not_null(B_anc, False):
                        Grade_A_samples[sample][s].append(B_anc)

                # sort by sites
                #------------------------------------------------------------

                if cb.not_null(site, False):
                    if site not in list(Grade_A_sites.keys()):
                        Grade_A_sites[site] = {}
                    if s not in list(Grade_A_sites[site].keys()) and len(All_grade_A_Recs[s]) > 0:
                        Grade_A_sites[site][s] = []
                    if cb.not_null(B_anc, False):
                        Grade_A_sites[site][s].append(B_anc)

                # ? check
                #------------------------------------------------------------

                if s not in list(Redo_data_specimens.keys()):
                    Redo_data_specimens[s] = {}

            # write to specimen_bounds
            #----------------------------------------------------------------

            if pars["NLT_specimen_correction_factor"] != -1:
                NLT_factor = "%.2f" % (NLT_factor_max)
            else:
                NLT_factor = "-"

            if pars["specimen_int_corr_cooling_rate"] != -1 and pars["specimen_int_corr_cooling_rate"] != -999:
                CR_factor = "%.2f" % (
                    float(pars["specimen_int_corr_cooling_rate"]))
            else:
                CR_factor = "-"
            if 'cooling_rate_data' in list(self.Data[s].keys()):
                if 'CR_correction_factor_flag' in list(self.Data[s]['cooling_rate_data'].keys()):
                    if self.Data[s]['cooling_rate_data']['CR_correction_factor_flag'] != "calculated":
                        if "inferred" in self.Data[s]['cooling_rate_data']['CR_correction_factor_flag']:
                            WARNING = WARNING + ";" + "cooling rate correction inferred from sister specimens"
                        if "alteration" in self.Data[s]['cooling_rate_data']['CR_correction_factor_flag']:
                            WARNING = WARNING + ";" + "cooling rate experiment failed alteration"
                        if "bad" in self.Data[s]['cooling_rate_data']['CR_correction_factor_flag']:
                            WARNING = WARNING + ";" + "cooling rate experiment failed"

            if AC_correction_type == "-":
                AC_correction_factor_to_print = "-"
            else:
                AC_correction_factor_to_print = "%.2f" % AC_correction_factor

            String = "%s\t%s\t%s\t%s\t%s\t%s\t%.1f\t%.1f\t%.1f\t%s\n"\
                % (sample, s, AC_correction_factor_to_print, AC_correction_type, NLT_factor, CR_factor, B_lab, B_min, B_max, WARNING)
            Fout_specimens_bounds.write(String)

        #--------------------------------------------------------------
        # Find the STDEV-OPT 'best mean':
        # the interprettaions that give
        # the minimum standrad deviation (perc!)
        # not nesseserily the standrad deviation in microT
        #
        #--------------------------------------------------------------

        # Sort all grade A interpretation

        samples = list(Grade_A_samples.keys())
        samples.sort()

        sites = list(Grade_A_sites.keys())
        sites.sort()

        #--------------------------------------------------------------
        # thellier-interpreter can work by averaging specimens by sample (default)
        # or by averaging specimens by site
        #--------------------------------------------------------------

        if self.acceptance_criteria['average_by_sample_or_site']['value'] == 'sample':
            self.Grade_A_sorted = copy.deepcopy(Grade_A_samples)

        else:
            self.Grade_A_sorted = copy.deepcopy(Grade_A_sites)

        self.clean_workspace()

        samples_or_sites = list(self.Grade_A_sorted.keys())
        samples_or_sites.sort()
        # print Grade_A_sorted
        for sample_or_site in samples_or_sites:
            if len(list(self.Grade_A_sorted[sample_or_site].keys())) == 1:
                specimen = list(self.Grade_A_sorted[sample_or_site].keys())[0]
                self.choose_interpretation_max_frac(All_grade_A_Recs, specimen)
            else:
                self.thellier_interpreter_pars = self.calc_upper_level_mean(
                    self.Grade_A_sorted, All_grade_A_Recs, sample_or_site)
                self.update_data_with_interpreter_pars(
                    self.Grade_A_sorted, All_grade_A_Recs, sample_or_site, self.thellier_interpreter_pars)
                self.update_files_with_intrepretation(
                    self.Grade_A_sorted, All_grade_A_Recs, sample_or_site, self.thellier_interpreter_pars)
        self.thellier_interpreter_log.write("-I- Statistics:\n")
        self.thellier_interpreter_log.write(
            "-I- number of specimens analzyed = %i\n" % len(specimens_list))
        self.thellier_interpreter_log.write(
            "-I- number of sucsessful 'acceptable' specimens = %i\n" % len(list(All_grade_A_Recs.keys())))

        runtime_sec = time.time() - start_time
        m, s = divmod(runtime_sec, 60)
        h, m = divmod(m, 60)
        self.thellier_interpreter_log.write(
            "-I- runtime hh:mm:ss is " + "%d:%02d:%02d\n" % (h, m, s))
        if len(specimens_list) != 0:
            self.thellier_interpreter_log.write(
                "-I- runtime per specimen: %.1f seconds" % (float(runtime_sec) / len(specimens_list)))

        self.thellier_interpreter_log.write("-I- Finished sucsessfuly.\n")
        self.thellier_interpreter_log.write("-I- DONE\n")

        # close all files

        self.thellier_interpreter_log.close()
        thellier_interpreter_all.close()
        Fout_specimens_bounds.close()
        if self.acceptance_criteria['interpreter_method']['value'] == 'stdev_opt':
            self.Fout_STDEV_OPT_redo.close()
            self.Fout_STDEV_OPT_specimens.close()
        if self.acceptance_criteria['interpreter_method']['value'] == 'stdev_opt':
            if self.acceptance_criteria['average_by_sample_or_site']['value'] == 'sample':
                self.Fout_STDEV_OPT_samples.close()
            else:
                self.Fout_STDEV_OPT_sites.close()

        if self.acceptance_criteria['interpreter_method']['value'] == 'bs':
            Fout_BS_samples.close()

        if self.acceptance_criteria['interpreter_method']['value'] == 'bs_par':
            Fout_BS_PAR_samples.close()
        # try:
        #    os.system('\a')
        # except:
        #    pass
        return True, len(specimens_list)
Run thellier_auto_interpreter