Commit a5df49ae authored by Giovanni La Mura's avatar Giovanni La Mura
Browse files

Add script to calculate matix dynamic range

parent 91265ea8
Loading
Loading
Loading
Loading
+150 −0
Original line number Diff line number Diff line
#!/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)