def main(argv): """ Parses command line options and starts the batch processing. :param argv: Command line arguments :type argv: list :return: None """ # Parse command line arguments parser = argparse.ArgumentParser(description='SPtP Batch Processing') parser.add_argument('-i', '--input-folder-path', dest='input_folder_path', help='Path to the folder containing input data (i. e. images, SURs file, and *.truth.kml files).') parser.add_argument('-o', '--output-folder-path', dest='output_folder_path', help='Path to the folder that will contain the resulting KML files. It will be deleted if it exists.') parser.add_argument('-s', '--surs-file-path', dest='surs_file_path', default='./input/surs.txt', help='Path to the text file containing the SURs. (Default: ./input/surs.txt)') parser.add_argument('-f', '--factors-file-path', dest='factors_file_path', default='./data/factors.txt', help='Path to the text file containing the SURs. (Default: ./data/factors.txt).') parser.add_argument('-c', '--cache-folder-path', dest='cache_folder_path', help='Path to the folder containing cache data (i. e. data from OpenStreetMap)') parser.add_argument('-u', '--force-cache-update', dest='force_cache_update', help='Force cache update.', action='store_true') parser.add_argument('--skip-cache-update', dest='skip_cache_update', help='Skip automatic cache update. Useful e.g. if no internet connection is available.', action='store_true') parser.add_argument('-q', '--quiet-mode', dest='quiet_mode', help='Do not write to stdout.', action='store_true') parser.add_argument('--exclude-slow-classifiers', dest='exclude_slow_classifiers', help='Exclude classifiers with suboptimal running times.', action='store_true') parser.add_argument('--overpass-radius', dest='overpass_radius', help='Overpass API query radius.', type=int) parser.add_argument('--compare-results', dest='compare_results', help='Compare computed polygons to polygons in *.truth.kml files.', action='store_true') parser.add_argument('--log-prefix', dest='log_file_prefix', default='icup_', help='Sets a prefix for log file names. (Default: icup_)') parser.add_argument('--debug-output', dest='debug_output', help='Saves CSV files for debug purposes.', action='store_true') parser.add_argument('--two-circle-intersection', dest='use_two_circle_intersection_ratio', help='Use two circle intersection ratio method. Default: False', action='store_true') args = parser.parse_args() # Compile settings settings = batch.default_settings() if args.input_folder_path: settings['input_folder_path'] = args.input_folder_path + os.path.sep if args.output_folder_path: settings['output_folder_path'] = args.output_folder_path + os.path.sep if args.cache_folder_path: settings['cache_folder_path'] = args.cache_folder_path + os.path.sep if args.overpass_radius: settings['overpass_radius'] = args.overpass_radius settings['surs_file_path'] = args.surs_file_path settings['factors_file_path'] = args.factors_file_path settings['force_cache_update'] = args.force_cache_update settings['skip_cache_update'] = args.skip_cache_update settings['quiet_mode'] = args.quiet_mode settings['exclude_slow_classifiers'] = args.exclude_slow_classifiers settings['compare_results'] = args.compare_results settings['log_file_prefix'] = args.log_file_prefix settings['debug_output'] = args.debug_output settings['use_two_circle_intersection_ratio'] = args.use_two_circle_intersection_ratio # Run batch processing exit_code = batch.main(settings) if not args.quiet_mode: if exit_code == 0: print('Batch processing finished successfully.') else: print('Batch processing failed. Check log files for details.') return exit_code
def main(settings): """ Runs the learning process. :param settings: Settings dict like default_learning_settings. Defaults to default_learning_settings :type settings: dict :return: 0 if success, 1 otherwise :rtype: int """ def get_random_number(): """ Returns a random number. The chance of getting a number between 0-1 is equal to 1-settings['max_factor_value'] The numbers are uniformly distributed in both ranges. :return: Random number between 0 and settings['max_factor_value'] :rtype: float """ random_num = random.random() if random_num < 0.5: return random_num * 2 else: return random.uniform(1, settings['max_factor_value']) def test_result(batch_settings, learning_settings, winner): """ Tests the accuracy after learning. :param batch_settings: The settings used for batch processing. Path will be corrected in the method :type batch_settings: Dict from batch.default_settings() :param learning_settings: The settings used for learning. Path will be corrected in the method :type learning_settings: Dict from batch.default_settings() :param batch_settings: The winner of the learning :type batch_settings: factors.Factors :return: None """ nonlocal main_log_file settings = batch_settings.copy() settings['surs_file_path'] = learning_settings['test_surs_file_path'] settings['input_folder_path'] = learning_settings['test_folder_path'] settings['factors'] = winner batch.main(settings) try: comparator = Comparator(settings['input_folder_path'], settings['output_folder_path'], settings['minimum_intersection_ratio'], raise_on_critical_error=True) comparator.run() except Exception as exception: print('Comparison failed! See log file for more information.') main_log_file.write('COMPARISON FAILURE\n') main_log_file.write('%s\n' % str(exception)) main_log_file.write('Can not complete comparison, aborting.\n') return 1 comparator.print(sys.stdout, False) comparator.print(main_log_file, False) def clear_learning_tmp(): """ Deletes temporary files created by processing. :return: None """ nonlocal main_log_file main_log_file.write('Deleting temporary files...') try: shutil.rmtree(settings['temp_folder_path']) main_log_file.write('OK\n') except Exception as error: main_log_file.write('FAILURE\n') main_log_file.write('%s\n' % str(error)) main_log_file.write('Can not delete temporary folder "%s", aborting.\n' % settings['temp_folder_path']) sys.exit(1) #Create header header = format_header(settings) print(header + '\n') # Initialize if not os.path.exists(settings['log_folder_path']): try: os.makedirs(settings['log_folder_path']) except OSError as error: print('FAILURE') print('%s' % str(error)) print('Can not create log folder "%s", aborting.' % settings['print_folder_path']) sys.exit(1) # Settings for batch processing batch_settings = batch.default_settings() batch_settings['surs_file_path'] = settings['surs_file_path'] batch_settings['input_folder_path'] = settings['db_folder_path'] batch_settings['output_folder_path'] = settings['temp_folder_path'] batch_settings['log_folder_path'] = settings['log_folder_path'] batch_settings['cache_folder_path'] = settings['cache_folder_path'] batch_settings['force_cache_update'] = True # Force cache update batch_settings['maximum_cache_file_age'] = settings['maximum_cache_file_age'] batch_settings['overpass_radius'] = settings['overpass_radius'] batch_settings['minimum_intersection_ratio'] = settings['minimum_intersection_ratio'] batch_settings['use_two_circle_intersection_ratio'] = settings['use_two_circle_intersection_ratio'] batch_settings['compare_results'] = False batch_settings['quiet_mode'] = True batch_settings['log_file_prefix'] = 'learning_' main_log_file_path = settings['log_folder_path'] + 'learning.log' try: with open(main_log_file_path, 'w', 1) as main_log_file: main_log_file.write(header + '\n') main_log_file.write('Initializing...') if not os.path.exists(settings['cache_folder_path']): try: os.makedirs(settings['cache_folder_path']) except OSError as error: main_log_file.write('FAILURE\n') main_log_file.write('%s\n' % str(error)) main_log_file.write('Can not create folder "%s", aborting.\n' % settings['cache_folder_path']) return 1 if not os.path.exists(settings['temp_folder_path']): try: os.makedirs(settings['temp_folder_path']) except OSError as error: main_log_file.write('FAILURE\n') main_log_file.write('%s\n' % str(error)) main_log_file.write('Can not create folder "%s", aborting.\n' % settings['temp_folder_path']) return 1 if not os.path.exists(settings['log_folder_path']): try: os.makedirs(settings['log_folder_path']) except OSError as error: main_log_file.write('FAILURE\n') main_log_file.write('%s\n' % str(error)) main_log_file.write('Can not create folder "%s", aborting.\n' % settings['log_folder_path']) return 1 main_log_file.write('OK\n') main_log_file.write('Initializing factors...') factor_list = [] for i in range(0, settings['population']): temp_factor = Factors() for classifier in classifiers_list: temp_factor.factors[classifier.name()] = get_random_number() factor_list.append((temp_factor, None)) main_log_file.write('OK\n') winner = None for round in range(settings['rounds']): print('Round %i' % (round + 1), end='', flush=True) main_log_file.write('Round %i' % (round + 1)) # New population current_population = factor_list.copy() result_population = [] for i in range(0, settings['new_population_per_turn']): parent1 = current_population[random.randint(0, len(current_population) - 1)][0] parent2 = current_population[random.randint(0, len(current_population) - 1)][0] child = Factors() for classifier in classifiers_list: if random.randint(0, 1) == 0: child.factors[classifier.name()] = parent1.factors[classifier.name()] else: child.factors[classifier.name()] = parent2.factors[classifier.name()] # Mutation of children if random.random() < settings['mutations_rate']: child.factors[classifiers_list[random.randint(0, len(classifiers_list) - 1)].name()] = get_random_number() current_population.append((child, None)) # Processing for current_factor in current_population: if current_factor[1] is None: batch_settings['factors'] = current_factor[0] if batch.main(batch_settings) == 1: main_log_file.write(' ERROR - Can not complete batch processing!') print('!', end='', flush=True) result_population.append((current_factor[0], -1.0)) continue batch_settings['force_cache_update'] = False try: comparator = Comparator(settings['db_folder_path'], settings['temp_folder_path'], settings['minimum_intersection_ratio'], raise_on_critical_error=True, use_two_circle_intersection_ratio=settings['use_two_circle_intersection_ratio']) comparator.run() except Exception as exception: main_log_file.write(' ERROR - %s!' % str(exception)) result_population.append((current_factor[0], -1.0)) print('!', end='', flush=True) continue if settings['use_two_circle_intersection_ratio']: passed = len(comparator.passed) points = (passed / (passed + len(comparator.failed) + len(comparator.erroneous))) - (comparator.average_intersection_ratio/100) else: points = comparator.average_intersection_ratio result_population.append((current_factor[0], points)) print('.', end='', flush=True) main_log_file.write('.') else: print(':', end='', flush=True) main_log_file.write(':') result_population.append(current_factor) result_population.sort(key=lambda x: x[1], reverse=True) print('[ ', end='', flush=True) main_log_file.write('[ ') for tuple in result_population: print('%5.4f ' % tuple[1], end='', flush=True) main_log_file.write('%5.4f ' % tuple[1]) print(']', end='', flush=True) main_log_file.write(']') winner = result_population[0][0] factor_list = [] for _ in range(0, settings['population']): factor_list.append(result_population.pop(0)) print(' OK') main_log_file.write(' OK\n') print('All rounds complete!') main_log_file.write('All rounds complete!\n') winner.write_file(settings['factors_file_path']) test_result(batch_settings, settings, winner) clear_learning_tmp() except OSError as error: print('FAILURE\n') print('%s\n' % str(error)) print('Can not write log file "%s", aborting.\n' % main_log_file_path) return 1 return 0