def __init_interface( self, b_force_disable = False ): ''' param b_force_disable, if set to true, will set all the KeyValueFrame text entry boxes do state "disabled." This is useful to show user when the interface is busy computing a simulation, and keeps user from editing values when the sim is being run (though, besides any user misperceptions, such editign would not affect the current sim, but rather would be applied to any subsequent run.) ''' ENTRY_WIDTH=50 LABEL_WIDTH=20 LOCATIONS_FRAME_PADDING=30 LOCATIONS_FRAME_LABEL="Load/Run" LOCATIONS_FRAME_STYLE="groove" RUNBUTTON_PADDING=07 o_file_locations_subframe=LabelFrame( self, padding=LOCATIONS_FRAME_PADDING, relief=LOCATIONS_FRAME_STYLE, text=LOCATIONS_FRAME_LABEL ) i_row=0 o_run_sub_subframe=Frame( o_file_locations_subframe ) self.__run_button=Button( o_run_sub_subframe, command=self.__on_click_run_or_cancel_simulation_button ) i_tot_procs=pgut.get_cpu_count() o_tot_process_validator=FloatIntStringParamValidity( \ "proccess total", int, self.__total_processes_for_sims, 1, i_tot_procs ) o_tot_process_kv=KeyValFrame( "Processes", self.__total_processes_for_sims, o_run_sub_subframe, o_associated_attribute_object=self, s_associated_attribute="_PGGuiSimuPop" \ + "__total_processes_for_sims", s_entry_justify='left', s_label_justify='left', s_button_text="Select", b_force_disable=b_force_disable, o_validity_tester= o_tot_process_validator, s_tooltip = "Simulation can use one process per replicate, " \ + "but set to no more than the total number " \ + "of processors in your computer." ) o_tot_process_kv.grid( row=i_row, column=0, sticky=( NW ) ) self.__run_button.grid( row=i_row, column=1, sticky=( NW ), padx=RUNBUTTON_PADDING ) self.__run_state_label=Label( o_run_sub_subframe, text=self.__run_state_message ) self.__run_state_label.grid( row=i_row, column=2, sticky=( SW ) ) o_run_sub_subframe.grid( row=i_row, sticky=( NW ) ) i_row += 1 s_curr_config_file=self.__config_file.get() v_config_file_val="None" if s_curr_config_file == "" else s_curr_config_file o_config_kv=KeyValFrame( "Load Configuration File:", v_config_file_val, o_file_locations_subframe, i_entrywidth=ENTRY_WIDTH, i_labelwidth=LABEL_WIDTH, b_is_enabled=False, s_entry_justify='left', s_label_justify='left', s_button_text="Select", def_button_command=self.load_config_file, b_force_disable=b_force_disable ) o_config_kv.grid( row=i_row, sticky=( NW ) ) i_row+=1 o_outdir_kv=KeyValFrame( "Select Output directory", self.__output_directory.get(), o_file_locations_subframe, i_entrywidth=ENTRY_WIDTH, i_labelwidth=LABEL_WIDTH, b_is_enabled=False, s_entry_justify='left', s_label_justify='left', s_button_text="Select", def_button_command=self.select_output_directory, b_force_disable=b_force_disable ) o_outdir_kv.grid( row= i_row, sticky=( NW ) ) i_row+=1 o_basename_validity_tester=FloatIntStringParamValidity( "output_base", str, self.output_base_name, 1, PGGuiSimuPop.MAX_CHARS_BASENAME ) self.__outbase_kv=KeyValFrame( s_name="Output files base name: ", v_value=self.output_base_name, o_master=o_file_locations_subframe, o_associated_attribute_object=self, s_associated_attribute="output_base_name", def_entry_change_command=self.__setup_output, i_entrywidth=ENTRY_WIDTH, i_labelwidth=LABEL_WIDTH, s_entry_justify='left', s_label_justify='left', o_validity_tester=o_basename_validity_tester, b_force_disable=b_force_disable ) self.__outbase_kv.grid( row=i_row, sticky=( NW ) ) o_file_locations_subframe.grid( row=0, sticky=(NW) ) o_file_locations_subframe.grid_columnconfigure( 0, weight=1 ) o_file_locations_subframe.grid_rowconfigure( 0, weight=1 ) self.grid_columnconfigure( 0, weight=1 ) self.grid_rowconfigure( 0, weight=1 ) return
def __params_look_valid( self, b_show_message=False ): ''' As of 2016_08_09, this is rudimentary validation. May need to be more fine-grained checking, as users encounter problem using the interface. ''' b_valid=True s_base_msg="The program is not ready for Ne estimation. " \ + "Please note the invalid parameter values:\n\n" ls_bad_filenames=self.__get_list_bad_genepop_file_names() ls_invalidity_messages=[] ''' Should collect all errors and present all to user at once, but for now will just abort on the first encountered invalid param. ''' BULLET="**" if len( ls_bad_filenames ) > 0: ls_invalidity_messages.append( BULLET + "Genepop files:\n" \ + "\n".join( [ s_name for s_name in ls_bad_filenames ] ) ) b_valid=False #end if one or more bad file names s_seperator=pgut.get_separator_character_for_current_os() s_current_output_dir=self.__output_directory.get() s_dir_and_basename=s_seperator.join( [ s_current_output_dir, self.output_base_name ] ) ls_existing_outfiles=pgut.get_list_files_and_dirs_from_glob( \ s_dir_and_basename + "*" ) if len( ls_existing_outfiles ) > 0: ls_invalidity_messages.append( \ BULLET + "Files matching the output " \ + "directory and basename already exist.\n" \ + "Please rename either the existing files " \ + "or the basename/directory params. " \ + "Existing files: " \ + "\n".join( ls_existing_outfiles ) ) b_valid=False #end if outfiles exist #If one or more of the loaded genepop files #has existing intermiediate files produced #by a pgdriveneestimator.py run, then we want #to abort, since behavior of the NeEstimator given #existing files can cause errors, and intermediate #genepop files may have been (however unlikely) #truncated or mangled in an interrupted run: ls_existing_intermediate_files=self.__get_output_file_names() if len( ls_existing_outfiles ) > 0: ls_invalidity_messages.append( BULLET + "Intermedate files from " \ + "an interrupted run exist:\n" \ + "\n".join( ls_existing_intermediate_files ) + "\nPlease either move/remove the intermediate files " \ + "or load genepop files whose names do not prefix the " + "intermediate files." ) #end if we have existing intermediate files if self.__sampscheme not in ( "percent", "remove" ): ls_invalidity_messages.append( BULLET + "Unknown sample scheme value: " \ + self.__sampscheme + "." ) b_valid=False #end if bad sample scheme if self.__minpopsize < 0: ls_invalidity_messages.append( BULLET + "Minimum population size (must be >= 0). " \ + "Current value: " + str( self.__minpopsize ) + "." ) b_valid=False #end if invalid min pop size if self.__minallelefreq > 1.0 or self.__minallelefreq < 0: ls_invalidity_messages.append( BULLET + "Minimum allele frequence " \ + "value must be > 0.0 and <= 1.0.\n" \ + "Current value: " + str( self.__minallelefreq ) + "." ) b_valid=False #end if invalid min allele freq i_num_cpus=pgut.get_cpu_count() #if no reported cpus, assume 1 if i_num_cpus < 1: i_num_cpus = 1 #end if nu cpus < 1 if self.__processes < 1 or self.__processes > i_num_cpus: ls_invalidity_messages.append( BULLET + "Number of prcesses must be at least 1 and " \ + "no more than " + str( i_num_cpus ) + ". " \ + "Current value: " + str( self.__processes ) + "." ) b_valid=False #end if process total invalid if self.__runmode not in [ "default" ] + pgdn.DebugMode.MODES: ls_invalidity_messages.append( BULLET + "Unknown run mode: " + self.__runmode + "." ) b_valid=False #end if if not b_valid: s_info_msg=s_base_msg + "\n\n".join( ls_invalidity_messages ) PGGUIInfoMessage( self, s_info_msg ) #end if any invalidity return b_valid