diff --git a/pyglance/glance/compare.py b/pyglance/glance/compare.py index 9671a8ceaee05cad98ab60e419a74a3557cf682a..6fa7e31436fff217c0c23b588654a29ce6bb2339 100644 --- a/pyglance/glance/compare.py +++ b/pyglance/glance/compare.py @@ -164,14 +164,14 @@ def _get_name_info_for_variable (original_display_name, variable_run_info) : return technical_name, b_variable_technical_name, explanation_name -def colocate_to_file_library_call(a_path, b_path, var_list=None, - options_set=None, - # todo, this doesn't yet do anything - do_document=False, - # todo, the output channel does nothing at the moment - output_channel=sys.stdout) : +def collocate_to_file_library_call(a_path, b_path, var_list=None, + options_set=None, + # todo, this doesn't yet do anything + do_document=False, + # todo, the output channel does nothing at the moment + output_channel=sys.stdout) : """ - this method handles the actual work of the colocateData command line tool + this method handles the actual work of the collocating two files and can be used as a library routine. TODO, properly document the options @@ -247,8 +247,8 @@ def colocate_to_file_library_call(a_path, b_path, var_list=None, lon_lat_data[B_FILE_KEY][LON_KEY], lon_lat_data[B_FILE_KEY][LAT_KEY]) # TODO, based on unmatched, issue warnings and record info in the file? - LOG.debug("colocated shape of the longitude: " + str(colocatedLongitude.shape)) - LOG.debug("colocated shape of the latitude: " + str(colocatedLatitude.shape)) + LOG.debug("collocated shape of the longitude: " + str(colocatedLongitude.shape)) + LOG.debug("collocated shape of the latitude: " + str(colocatedLatitude.shape)) LOG.debug(str(numMultipleMatchesInA) + " lon/lat pairs contain A points used for multiple matches.") LOG.debug(str(numMultipleMatchesInB) + " lon/lat pairs contain B points used for multiple matches.") LOG.debug(str(len(unmatchedALatitude)) + " A lon/lat points could not be matched.") @@ -281,7 +281,7 @@ def colocate_to_file_library_call(a_path, b_path, var_list=None, altVariableFileObject = dataobj.FileInfo(varRunInfo[VAR_FILTER_ALT_FILE_B_KEY]).file_object if VAR_FILTER_ALT_FILE_B_KEY in varRunInfo else None, fileDescriptionForDisplay = "file B") - # colocate the data for this variable if we have longitude/latitude data + # collocate the data for this variable if we have longitude/latitude data if (len(lon_lat_data) > 0) and runInfo[DO_COLOCATION_KEY] : # figure out the invalid masks @@ -305,26 +305,28 @@ def colocate_to_file_library_call(a_path, b_path, var_list=None, LOG.debug(str(len(aUnmatchedData)) + " A data points could not be matched.") LOG.debug(str(len(bUnmatchedData)) + " B data points could not be matched.") - # save the colocated data information in the output files + # save the collocated data information in the output files # all the a file information - variableObjTemp = aFile.file_object.create_new_variable( technical_name + '-colocated', # TODO, how should this suffix be handled? + temp_var_name = technical_name + '-collocated' + variableObjTemp = aFile.file_object.create_new_variable( temp_var_name, missingvalue = varRunInfo[FILL_VALUE_KEY] if FILL_VALUE_KEY in varRunInfo else None, data = aData, variabletocopyattributesfrom = technical_name) - aFile.file_object.add_attribute_data_to_variable(technical_name + '-colocated', 'number of multiple matches', + aFile.file_object.add_attribute_data_to_variable(temp_var_name, 'number of multiple matches', numberOfMultipleMatchesInA, variableObject=variableObjTemp,) - aFile.file_object.add_attribute_data_to_variable(technical_name + '-colocated', 'number of unmatched points', + aFile.file_object.add_attribute_data_to_variable(temp_var_name, 'number of unmatched points', len(aUnmatchedData), variableObject=variableObjTemp,) # all the b file information - variableObjTemp = bFile.file_object.create_new_variable( b_variable_technical_name + '-colocated', # TODO, how should this suffix be handled? + temp_var_name = b_variable_technical_name + '-collocated' + variableObjTemp = bFile.file_object.create_new_variable( temp_var_name, missingvalue = varRunInfo[FILL_VALUE_ALT_IN_B_KEY] if FILL_VALUE_ALT_IN_B_KEY in varRunInfo else None, data = bData, variabletocopyattributesfrom = b_variable_technical_name) - bFile.file_object.add_attribute_data_to_variable(b_variable_technical_name + '-colocated', 'number of multiple matches', + bFile.file_object.add_attribute_data_to_variable(temp_var_name, 'number of multiple matches', numberOfMultipleMatchesInB, variableObject=variableObjTemp,) - bFile.file_object.add_attribute_data_to_variable(b_variable_technical_name + '-colocated', 'number of unmatched points', + bFile.file_object.add_attribute_data_to_variable(temp_var_name, 'number of unmatched points', len(bUnmatchedData), variableObject=variableObjTemp,) # Future, do we want any any additional statistics? @@ -1315,10 +1317,255 @@ def stats_one_input_library_call (afn, var_list=None, options_set=None, do_docum return 0 -def main(): +# ------------------------------------------- section of deprecated commands ----------------------------------------- + +# TODO, we will want to remove this all eventually + +def colocateData(*args, options=None) : + """colocate data from two files + + Colocates data in the two given input files and saves it to separate output files. + + Data will be colocated based on its corresponding longitude and latitude. Multiple matches may be + made between a data point in file A and those in file B if they are within the longitude/latitude epsilon. + Points from each file that could not be matched and the number of duplicate matches will also be + recorded in the output file. + + The user may also use the notation variable_name::missing_value to specify the missing_value which indicates + missing data. If no missing value is given, glance will attempt to load a missing value from the input file. + If there is no missing value defined for that variable in the file, no missing value will be analyzed. + Missing value data points will not be considered for colocation. + + Data which corresponds to longitude or latitude values which fall outside the earth (outside the normally + accepted valid ranges) will also be considered invalid and will not be considered for colocation. + + The longitude and latitude variables may be specified with --longitude and --latitude + If no longitude or latitude are specified the pixel_latitude and pixel_longitude variables will be used. + The longitude and latitude epsilon may be specified with --llepsilon + If no longitude/latitude epsilon is given the value of 0.0 (degrees) will be used + + The output data files generated by this option will appear in the selected output directory, or the current + directory if no out put directory is selected. The output files will be named originalFileName-colocation.nc + (replacing "originalFileName" with the names of your input files). + + Examples: + + glance colocateData A.hdf B.hdf variable_name_1 variable_name_2 variable_name_3::missing3 + glance colocateData --outputpath=/path/where/output/will/be/placed/ A.nc B.nc + glance colocateData --longitude=lon_variable_name --latitude=lat_variable_name A.hdf B.hdf variable_name + glance colocateData --llepsilon=0.0001 A.nc B.hdf + """ + + LOG.warn("This command is DEPRECATED. Please use the collocate command in future.") + + if len(args) < 2: + LOG.warn("Expected two paths to files to colocate. " + "Unable to generate colocation information without two file paths.") + return 1 + + # TODO, is this really needed? + options.imagesOnly = False + options.htmlOnly = False + options.doFork = False + + tempOptions = config_organizer.convert_options_to_dict(options) + + # TODO, remove this eventually + tempOptions[DO_COLOCATION_KEY] = True + + a_path = clean_path(args[0]) + b_path = clean_path(args[1]) + + collocate_to_file_library_call(a_path, b_path, args[2:], tempOptions) + +def plotDiffs(*args, options=None) : + """create a set of images comparing two files (Deprecated, please use report in future.) + This command is DEPRECATED. Please use the report command in future. + + Create and save images comparing variables in two files. Variables to be compared may be specified after + the names of the two input files. If no variable names are given, this command will create plots for all + variables that can be matched by name and shape between the two files. + + If latitude and longitude data are present in the file and specified in the call options, the variables + will be plotted on a map. The longitude and latitude variable names may be specified with --longitude + and --latitude command line options. If no longitude or latitude names are specified Glance will attempt + to use pixel_longitude and pixel_latitude. + + If you would rather plot the data without a map, use the --nolonlat option. + + The created images will be saved at the provided output path in subdirectories named for each variable + analyzed. If no output path is provided, output will be saved in the current directory. + + Examples: + + glance plotDiffs A.hdf B.hdf + glance plotDiffs C.nc D.h5 variable_name_1:epsilon1: variable_name_2 variable_name_3:epsilon3:missing3 + glance --outputpath=/path/where/output/will/be/placed/ plotDiffs A.hdf B.hdf + glance plotDiffs --longitude=lon_variable_name --latitude=lat_variable_name A.hdf B.hdf variable_name + """ + + LOG.warn("This command is DEPRECATED. Please use the report command with the --imagesonly option in future.") + + # set the options so that a report will not be generated + options.imagesOnly = True + + # make the images + reportGen(*args) + + return + + +def reportGen(*args, options=None) : + """create a report comparing two files (Deprecated, please use report in future.) + This command is DEPRECATED. Please use the report command in future. + + Generate an html report comparing the variables in two files. Variables to be compared may be specified after + the names of the two input files. If no variable names are given, this command will create reports for all + variables that can be matched by name and shape between the two files. + + If latitude and longitude data are present in the file and specified in the call options, the variable + comparison plots will be drawn on a map. The longitude and latitude variable names may be specified with + --longitude and --latitude command line options. If no longitude or latitude names are specified Glance + will attempt to use pixel_longitude and pixel_latitude. + + If you would rather analyze the data without trying to place it on a map, use the --nolonlat option. + + The created reports and images will be saved at the provided output path in subdirectories named for + each variable analyzed. If no output path is provided, output will be saved in the current directory. + Created images will be embedded in the report or visible as separate .png files. - # horray, dummy options! - options = None + If you would prefer to generate the report without images, use the --reportonly option. This option will + generate the html report but omit the images. This may be significantly faster, depending on your system, + but the differences between the files may be more difficult to interpret. + + Examples: + + glance reportGen A.hdf C.nc + glance reportGen A.hdf B.hdf variable_name_1:epsilon1: variable_name_2 variable_name_3:epsilon3:missing3 variable_name_4::missing4 + glance --outputpath=/path/where/output/will/be/placed/ reportGen A.hdf D.h5 + glance reportGen --longitude=lon_variable_name --latitude=lat_variable_name D.h5 C.nc variable_name + glance reportGen --imagesonly A.hdf B.hdf + """ + + LOG.warn("This command is DEPRECATED. Please use the report command in future.") + + tempOptions = config_organizer.convert_options_to_dict(options) + + if len(args) < 2: + LOG.warn("Expected two paths to files to compare. " + "Unable to generate a comparison report or comparison plots without two file paths.") + return 1 + + a_path = clean_path(args[0]) + b_path = clean_path(args[1]) + + return report_two_inputs_library_call(a_path, b_path, args[2:], tempOptions) + + +def inspectStats(*args, options=None) : + """create statistics summary of one file (Deprecated, please use stats in future.) + This command is DEPRECATED. Please use the stats command in future. + + Print statistical summaries of the variables in a file. If no variable names are given, this + command will summarize all variables found in the file. + + Run with -v to get more detailed information about the statistics being reported. + + Examples: + + glance inspectStats A.hdf + glance inspectStats A.hdf baseline_cmask_seviri_cloud_mask + glance -w inspectStats B.nc imager_prof_retr_abi_total_precipitable_water_low::-999 + """ + + LOG.warn("This command is DEPRECATED. Please use the stats command in future.") + + if len(args) < 1: + LOG.warn("Expected a path to a file to inspect. " + "Unable to generate inspection statistics without a file path.") + return 1 + + afn = args[0] + do_doc = (options.verbose or options.debug) + + tempOptions = config_organizer.convert_options_to_dict(options) + + # TODO, clean up how the output is set up + # if we were given an output path use that to create the stats + toPrintTo = sys.stdout + outpath = clean_path(options.outputpath) + fileForOutput = None + if outpath != clean_path('./'): + # if needed, create the directory + setup_dir_if_needed(outpath, "output") + + # open the file for writing, get rid of whatever's there + fileForOutput = open(outpath + "/stats.txt", "w") # TODO, forming the path this way won't work on windows? + toPrintTo = fileForOutput + + stats_one_input_library_call(clean_path(afn), var_list=args[1:], + options_set=tempOptions, do_document=do_doc, + output_channel=toPrintTo) + + if fileForOutput is not None: + fileForOutput.close() + + +def inspectReport(*args, options=None) : + """create a report to inspect the contents of one file (Deprecated, please use report in future.) + This command is DEPRECATED. Please use the report command in future. + + Generate an html report examining the variables in a file. Variables to be analyzed may be specified after + the name of the input file. If no variable names are given, this command will create reports for all + variables in the file. + + If latitude and longitude data are present in the file and specified in the call options, the variable + plots will be drawn on a map. The longitude and latitude variable names may be specified with + --longitude and --latitude command line options. If no longitude or latitude names are specified Glance + will attempt to use pixel_longitude and pixel_latitude. + + If you would rather analyze the data without trying to place it on a map, use the --nolonlat option. + + The created reports and images will be saved at the provided output path in subdirectories named for + each variable analyzed. If no output path is provided, output will be saved in the current directory. + Created images will be embedded in the report or visible as separate .png files. + + If you would prefer to generate the report without images, use the --reportonly option. This option will + generate the html report but omit the images. This may be significantly faster, depending on your system, + but the results may be more difficult to interpret. + + Examples: + + glance inspect_report A.hdf variable_name_1:: variable_name_2 variable_name_3::missing3 variable_name_4::missing4 + glance --outputpath=/path/where/output/will/be/placed/ inspect_report C.nc + glance inspect_report --longitude=lon_variable_name --latitude=lat_variable_name D.h5 variable_name + glance inspect_report --reportonly A.hdf + """ + + LOG.warn("This command is DEPRECATED. Please use the report command in future.") + + if len(args) < 1: + LOG.warn("Expected a path to a files to inspect. " + "Unable to generate a comparison report without a file path.") + return 1 + + tempOptions = config_organizer.convert_options_to_dict(options) + + # args[0] is the path of the file to be analyzed, an other args should be variable names + return report_one_input_library_call(clean_path(args[0]), args[1:], tempOptions) + +# for now, have a way to get to these deprecated commands +DEPRECATION_TRANSLATION = { + "colocatedata": colocateData, + "plotdiffs": plotDiffs, + "reportgen": reportGen, + "inspectstats": inspectStats, + "inspectreport": inspectReport, + } + +# ------------------------------------------- end of section of deprecated commands ----------------------------------------- + +def main(): commands = {} prior = None @@ -1328,7 +1575,7 @@ def main(): The following functions represent available menu selections in glance. """ - def info(*args): + def info(*args, options=None) : """list information about a list of files Given a file (or list of files), print out the names of the available variables in the file(s). @@ -1354,7 +1601,7 @@ def main(): problems = 255 return problems - def stats (*args) : + def stats (*args, options=None ) : """do statistical analysis on your input The stats command will perform various types of statistical analysis depending on what input files @@ -1454,179 +1701,13 @@ def main(): if to_return is not None: return to_return return 0 - - def plotDiffs(*args) : - """create a set of images comparing two files (Deprecated, please use report in future.) - This command is DEPRECATED. Please use the report command in future. - - Create and save images comparing variables in two files. Variables to be compared may be specified after - the names of the two input files. If no variable names are given, this command will create plots for all - variables that can be matched by name and shape between the two files. - - If latitude and longitude data are present in the file and specified in the call options, the variables - will be plotted on a map. The longitude and latitude variable names may be specified with --longitude - and --latitude command line options. If no longitude or latitude names are specified Glance will attempt - to use pixel_longitude and pixel_latitude. - - If you would rather plot the data without a map, use the --nolonlat option. - - The created images will be saved at the provided output path in subdirectories named for each variable - analyzed. If no output path is provided, output will be saved in the current directory. - - Examples: - - glance plotDiffs A.hdf B.hdf - glance plotDiffs C.nc D.h5 variable_name_1:epsilon1: variable_name_2 variable_name_3:epsilon3:missing3 - glance --outputpath=/path/where/output/will/be/placed/ plotDiffs A.hdf B.hdf - glance plotDiffs --longitude=lon_variable_name --latitude=lat_variable_name A.hdf B.hdf variable_name - """ - - # set the options so that a report will not be generated - options.imagesOnly = True - - # make the images - reportGen(*args) - - return - - def reportGen(*args) : - """create a report comparing two files (Deprecated, please use report in future.) - This command is DEPRECATED. Please use the report command in future. - - Generate an html report comparing the variables in two files. Variables to be compared may be specified after - the names of the two input files. If no variable names are given, this command will create reports for all - variables that can be matched by name and shape between the two files. - - If latitude and longitude data are present in the file and specified in the call options, the variable - comparison plots will be drawn on a map. The longitude and latitude variable names may be specified with - --longitude and --latitude command line options. If no longitude or latitude names are specified Glance - will attempt to use pixel_longitude and pixel_latitude. - - If you would rather analyze the data without trying to place it on a map, use the --nolonlat option. - - The created reports and images will be saved at the provided output path in subdirectories named for - each variable analyzed. If no output path is provided, output will be saved in the current directory. - Created images will be embedded in the report or visible as separate .png files. - - If you would prefer to generate the report without images, use the --reportonly option. This option will - generate the html report but omit the images. This may be significantly faster, depending on your system, - but the differences between the files may be more difficult to interpret. - - Examples: - - glance reportGen A.hdf C.nc - glance reportGen A.hdf B.hdf variable_name_1:epsilon1: variable_name_2 variable_name_3:epsilon3:missing3 variable_name_4::missing4 - glance --outputpath=/path/where/output/will/be/placed/ reportGen A.hdf D.h5 - glance reportGen --longitude=lon_variable_name --latitude=lat_variable_name D.h5 C.nc variable_name - glance reportGen --imagesonly A.hdf B.hdf - """ - - tempOptions = config_organizer.convert_options_to_dict(options) - - if len(args) < 2 : - LOG.warn("Expected two paths to files to compare. " - "Unable to generate a comparison report or comparison plots without two file paths.") - return 1 - - a_path = clean_path(args[0]) - b_path = clean_path(args[1]) - - return report_two_inputs_library_call(a_path, b_path, args[2:], tempOptions) - - def inspectStats(*args): - """create statistics summary of one file (Deprecated, please use stats in future.) - This command is DEPRECATED. Please use the stats command in future. - - Print statistical summaries of the variables in a file. If no variable names are given, this - command will summarize all variables found in the file. - - Run with -v to get more detailed information about the statistics being reported. - - Examples: - - glance inspectStats A.hdf - glance inspectStats A.hdf baseline_cmask_seviri_cloud_mask - glance -w inspectStats B.nc imager_prof_retr_abi_total_precipitable_water_low::-999 - """ - - if len(args) < 1: - LOG.warn("Expected a path to a file to inspect. " - "Unable to generate inspection statistics without a file path.") - return 1 - - afn = args[0] - do_doc = (options.verbose or options.debug) - - tempOptions = config_organizer.convert_options_to_dict(options) - - # TODO, clean up how the output is set up - # if we were given an output path use that to create the stats - toPrintTo = sys.stdout - outpath = clean_path(options.outputpath) - fileForOutput = None - if outpath != clean_path('./') : - - # if needed, create the directory - setup_dir_if_needed(outpath, "output") - - # open the file for writing, get rid of whatever's there - fileForOutput = open(outpath + "/stats.txt", "w") # TODO, forming the path this way won't work on windows? - toPrintTo = fileForOutput - - stats_one_input_library_call(clean_path(afn), var_list=args[1:], - options_set=tempOptions, do_document=do_doc, - output_channel=toPrintTo) - - if fileForOutput is not None : - fileForOutput.close() - def inspectReport(*args) : - """create a report to inspect the contents of one file (Deprecated, please use report in future.) - This command is DEPRECATED. Please use the report command in future. - - Generate an html report examining the variables in a file. Variables to be analyzed may be specified after - the name of the input file. If no variable names are given, this command will create reports for all - variables in the file. - - If latitude and longitude data are present in the file and specified in the call options, the variable - plots will be drawn on a map. The longitude and latitude variable names may be specified with - --longitude and --latitude command line options. If no longitude or latitude names are specified Glance - will attempt to use pixel_longitude and pixel_latitude. - - If you would rather analyze the data without trying to place it on a map, use the --nolonlat option. - - The created reports and images will be saved at the provided output path in subdirectories named for - each variable analyzed. If no output path is provided, output will be saved in the current directory. - Created images will be embedded in the report or visible as separate .png files. - - If you would prefer to generate the report without images, use the --reportonly option. This option will - generate the html report but omit the images. This may be significantly faster, depending on your system, - but the results may be more difficult to interpret. - - Examples: - - glance inspect_report A.hdf variable_name_1:: variable_name_2 variable_name_3::missing3 variable_name_4::missing4 - glance --outputpath=/path/where/output/will/be/placed/ inspect_report C.nc - glance inspect_report --longitude=lon_variable_name --latitude=lat_variable_name D.h5 variable_name - glance inspect_report --reportonly A.hdf - """ - - if len(args) < 1: - LOG.warn("Expected a path to a files to inspect. " - "Unable to generate a comparison report without a file path.") - return 1 - - tempOptions = config_organizer.convert_options_to_dict(options) - - # args[0] is the path of the file to be analyzed, an other args should be variable names - return report_one_input_library_call(clean_path(args[0]), args[1:], tempOptions) - - def colocateData(*args) : - """colocate data from two files + def collocate(*args, options=None) : + """collocate data from two files - Colocates data in the two given input files and saves it to separate output files. + Collocates data in the two given input files and saves it to separate output files. - Data will be colocated based on its corresponding longitude and latitude. Multiple matches may be + Data will be collocated based on its corresponding longitude and latitude. Multiple matches may be made between a data point in file A and those in file B if they are within the longitude/latitude epsilon. Points from each file that could not be matched and the number of duplicate matches will also be recorded in the output file. @@ -1650,14 +1731,14 @@ def main(): Examples: - glance colocateData A.hdf B.hdf variable_name_1 variable_name_2 variable_name_3::missing3 - glance colocateData --outputpath=/path/where/output/will/be/placed/ A.nc B.nc - glance colocateData --longitude=lon_variable_name --latitude=lat_variable_name A.hdf B.hdf variable_name - glance colocateData --llepsilon=0.0001 A.nc B.hdf + glance collocate A.hdf B.hdf variable_name_1 variable_name_2 variable_name_3::missing3 + glance collocate --outputpath=/path/where/output/will/be/placed/ A.nc B.nc + glance collocate --longitude=lon_variable_name --latitude=lat_variable_name A.hdf B.hdf variable_name + glance collocate --llepsilon=0.0001 A.nc B.hdf """ if len(args) < 2: - LOG.warn("Expected two paths to files to colocate. " + LOG.warn("Expected two paths to files to collocate. " "Unable to generate colocation information without two file paths.") return 1 @@ -1674,12 +1755,12 @@ def main(): a_path = clean_path(args[0]) b_path = clean_path(args[1]) - colocate_to_file_library_call(a_path, b_path, args[2:], tempOptions) + collocate_to_file_library_call(a_path, b_path, args[2:], tempOptions) # Note: the figure plotting in the GUI is dependant on having selected an interactive renderer in the first "use" # statement at the beginning of this module. (It had to be moved into this module to pre-empt other use statempents # from imports of other glance modules.) - def gui (*args) : + def gui (*args, options=None) : """start the Glance graphical user interface This option launches the graphical user interface for Glance. This interface includes only some of the @@ -1705,7 +1786,7 @@ def main(): temp_controller.newFileSelected(B_CONST, args[1]) temp_controller.launch_gui() - def report (*args) : + def report (*args, options=None) : """generate reports of various types depending on your input Depending on how many input file paths you give this command it will either generate comparison or @@ -1864,7 +1945,7 @@ def main(): # if we got to here, something has gone terribly wrong return 1 - def help(command=None): + def help(command=None, options=None) : """print help for a specific command or list of commands print help for a specific command or list of commands @@ -1903,8 +1984,9 @@ def main(): lower_locals[command_key.lower()] = locals()[command_key] # get our command line argument handling set up + temp_all_commands = list(lower_locals.keys()) + list(DEPRECATION_TRANSLATION.keys()) options = config_organizer.parse_arguments(get_glance_version_string(), - list(lower_locals.keys()), + temp_all_commands, _get_all_commands_help_string(commands,), ) args = options.misc @@ -1925,16 +2007,18 @@ def main(): # if what the user asked for is not one of our existing functions, print the help to_return = 0 - if (options.command == "") or (options.command not in lower_locals): + if (options.command == "") or (options.command not in lower_locals and options.command not in DEPRECATION_TRANSLATION) : if options.version: to_return = 0 else : options.print_help() help() to_return = 9 - else: + else : + command_function = lower_locals[options.command] if options.command in lower_locals else DEPRECATION_TRANSLATION[options.command] + # call the function the user named, given the arguments from the command line, lowercase the request to ignore case - return_code = lower_locals[options.command](*args) + return_code = command_function(*args, options=options,) to_return = 0 if return_code is None else return_code LOG.debug("Glance run complete, returning code: " + str(to_return))