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)