diff --git a/src/scripts/pydynrange.py b/src/scripts/pydynrange.py new file mode 100755 index 0000000000000000000000000000000000000000..7c96b79d53cee5f274f65b25eb33f8e428f1ef35 --- /dev/null +++ b/src/scripts/pydynrange.py @@ -0,0 +1,150 @@ +#!/bin/python3 + +# Copyright (C) 2024 INAF - Osservatorio Astronomico di Cagliari +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# A copy of the GNU General Public License is distributed along with +# this program in the COPYING file. If not, see: <https://www.gnu.org/licenses/>. + +## @package pydynrange +# \brief Script to calculate the dynamic range of a complex matrix. +# +# The script execution requires python3. + +import cmath +import os + +from sys import argv, stdout + +## \brief Main execution code +# +# `main()` is the function that handles the creation of the script configuration +# and the execution of the calculation. It returns 0 on successful completion. +# +# \returns exit_code: `int` 0 on successful completion. +def main(): + config = parse_arguments() + exit_code = 0 + if config['help_mode'] or len(argv) == 1: + config['help_mode'] = True + print_help() + else: + if config['matrix_name'] == "": + exit_code = 1 + else: + exit_code = get_dynamic_range(config) + return exit_code + +## \brief Compute the dynamic range of a matrix. +# +# \param config: `dict` A dictionary containing the script configuration. +# +# \returns result: `int` The exit code of the operation (0 for success). +def get_dynamic_range(config): + result = 0 + num_read_lines = 0 + max_real = -1.0 + max_imag = -1.0 + max_absl = -1.0 + min_real = 1.0 + min_imag = 1.0 + sml_absl = 1.0 + sml_real = 1.0 + sml_imag = 1.0 + stdout.write("INFO: scanning data file. Please, wait...") + stdout.flush() + matrix_file = open(config['matrix_name'], 'r') + str_line = matrix_file.readline() + str_line = matrix_file.readline() + str_line = matrix_file.readline() + while (str_line != ""): + str_value = str_line.split("(")[1][:-2] + split_value = str_value.split(",") + real = float(split_value[0]) + imag = float(split_value[1]) + if (real > max_real): max_real = real + if (imag > max_imag): max_imag = imag + if (real < min_real): min_real = real + if (imag < min_imag): min_imag = imag + cvalue = complex(real, imag) + absl_val = abs(cvalue) + if (absl_val > max_absl): max_absl = absl_val + if (absl_val < sml_absl): sml_absl = absl_val if absl_val > 0.0 else sml_absl + if (real < 0): real *= -1.0 + if (imag < 0): imag *= -1.0 + if (real < sml_real): sml_real = real if real > 0.0 else sml_real + if (imag < sml_imag): sml_imag = imag if imag > 0.0 else sml_real + str_line = matrix_file.readline() + if (config['limit'] > 0): + num_read_lines += 1 + if (num_read_lines >= config['limit']): + str_line = "" # Close the while loop + matrix_file.close() + print(" done!") + print(" MAX( ABS[AM] ) = %14.7e"%max_absl) + print(" MIN( ABS[AM] ) = %14.7e"%sml_absl) + print(" MAX( REAL[AM] ) = %14.7e"%max_real) + print(" MIN( REAL[AM] ) = %14.7e"%min_real) + print(" MAX( IMAG[AM] ) = %14.7e"%max_imag) + print(" MIN( IMAG[AM] ) = %14.7e"%min_imag) + print("MIN( ABS( REAL[AM] ) ) = %14.7e"%sml_real) + print("MIN( ABS( IMAG[AM] ) ) = %14.7e"%sml_imag) + return result + +## \brief Parse the command line arguments. +# +# The script behaviour can be modified through a set of mandatory and optional +# arguments. The only mandatory argument is the name of the log file to be +# parsed. Additional optional arguments are an operation filter, which should +# be the starting sequence of the log strings to pe included in the timing +# calculation and the number of threads used during code execution. +# +# \returns config: `dict` A dictionary containing the script configuration. +def parse_arguments(): + config = { + 'matrix_name': "", + 'help_mode': False, + 'limit': -1, + } + for arg in argv[1:]: + if (arg.startswith("--help")): + config['help_mode'] = True + elif (arg.startswith("--limit=")): + split_arg = arg.split('=') + config['limit'] = int(split_arg[1]) + else: + if (os.path.isfile(arg)): + config['matrix_name'] = arg + else: + raise Exception("Unrecognized argument \'{0:s}\'".format(arg)) + return config + +## \brief Print a command-line help summary. +def print_help(): + print(" ") + print("*** PYDYNRANGE ***") + print(" ") + print("Get the dynamic range of a complex matrix. ") + print(" ") + print("Usage: \"./pydynrange.py FILE_NAME [OPTIONS]\"") + print(" ") + print("Valid options are: ") + print("--help Print this help and exit.") + print("--limit=NUMBER Check only NUMBER file lines.") + print(" ") + + +# ### PROGRAM EXECUTION ### +## \cond +res = main() +## \endcond +exit(res)