# Path: pyteltools/geom/transformation.py
# class Transformation:
#     """!
#     @brief Transformation between two coordinate systems
#     A transformation is a composition of rotation, scaling and translation on 3d vectors.
#     """
#     def __init__(self, angle, horizontal_factor, vertical_factor, dx, dy, dz):
#         self.rotation = Rotation(angle)
#         self.scaling = Scaling(horizontal_factor, vertical_factor)
#         self.translation = Translation(dx, dy, dz)
# 
#     def __repr__(self):
#         return ' '.join(map(str, [self.rotation.angle, self.scaling.horizontal_factor, self.scaling.vertical_factor,
#                                   self.translation.dx, self.translation.dy, self.translation.dz]))
# 
#     def __call__(self, coordinates):
#         return self.translation.vector + self.scaling.vector * self.rotation.rotation_matrix.dot(coordinates)
# 
#     def __str__(self):
#         return '\n'.join(['Rotation:\t%.4f (rad)' % self.rotation.angle,
#                           'Scaling:\tXY %.4f \tZ %.4f ' %
#                           (self.scaling.horizontal_factor, self.scaling.vertical_factor),
#                           'Translation:\tX %.4f \t Y %.4f \t Z %.4f' %
#                           (self.translation.dx, self.translation.dy, self.translation.dz)])
# 
#     def inverse(self):
#         """!
#         @brief The inverse transformation
#         The inverse transformation is a transformation with inverse rotation, inverse scaling
#         and a translation vector that is equal to the result of inverse rotation and inverse scaling
#         of the inverse translation vector
#         """
#         inverse_rotation = self.rotation.inverse()
#         inverse_scaling = self.scaling.inverse()
#         inverse_translation = self.translation.inverse()
#         inverse_dx, inverse_dy, inverse_dz = inverse_scaling.vector * \
#                                              inverse_rotation.rotation_matrix.dot(inverse_translation.vector)
#         return Transformation(inverse_rotation.angle,
#                               inverse_scaling.horizontal_factor, inverse_scaling.vertical_factor,
#                               inverse_dx, inverse_dy, inverse_dz)
# 
# Path: pyteltools/slf/Serafin.py
# class Serafin:
#     """!
#     @brief A Serafin object corresponds to a single Serafin in file IO stream
# 
#     # Attributes:
#     - language <str>: language for variables ('fr' or 'en')
#     - mode <str>: file open mode
#     - file <_io.BufferedReader>: input Serafin stream
#     - filename <str>: path to file
#     - file_size <int>: size of file
#     """
#     def __init__(self, filename, mode, language):
#         self.language = language
#         self.mode = mode
# 
#         self.file = None  # will be opened when called using `with` statement
#         self.filename = filename
#         self.file_size = None
# 
#     def __enter__(self):
#         self.file = open(self.filename, self.mode)
#         return self
# 
#     def __exit__(self, exc_type, exc_val, exc_tb):
#         self.file.close()
#         return False
# 
# Path: pyteltools/utils/cli_base.py
# LINE_WIDTH = 80
# class CustomFormatter(argparse.ArgumentDefaultsHelpFormatter, argparse.RawDescriptionHelpFormatter):
# class PyTelToolsArgParse(argparse.ArgumentParser):
#     def __init__(self, add_args=[], description=None, *args, **kwargs):
#     def add_known_argument(self, arg_id):
#     def _add_auto_arguments(self):
#     def _title_group(label):
#     def add_argument_group(self, name, *args, **kwargs):
#     def add_group_general(self, add_args=[]):
#     def parse_args(self, *args, **kwargs):


import numpy as np
import sys
from pyteltools.geom.transformation import Transformation
from pyteltools.slf import Serafin
from pyteltools.utils.cli_base import logger, PyTelToolsArgParse
#!/usr/bin/env python
"""
Extract last temporal frame of a 2D/3D Serafin file
"""




def slf_last(args):
    with Serafin.Read(args.in_slf, args.lang) as resin:
        resin.read_header()
        logger.info(resin.header.summary())
        resin.get_time()

        output_header = resin.header.copy()
        # Shift mesh coordinates if necessary
        if args.shift:

# Path: pyteltools/geom/transformation.py
# class Transformation:
#     """!
#     @brief Transformation between two coordinate systems
#     A transformation is a composition of rotation, scaling and translation on 3d vectors.
#     """
#     def __init__(self, angle, horizontal_factor, vertical_factor, dx, dy, dz):
#         self.rotation = Rotation(angle)
#         self.scaling = Scaling(horizontal_factor, vertical_factor)
#         self.translation = Translation(dx, dy, dz)
# 
#     def __repr__(self):
#         return ' '.join(map(str, [self.rotation.angle, self.scaling.horizontal_factor, self.scaling.vertical_factor,
#                                   self.translation.dx, self.translation.dy, self.translation.dz]))
# 
#     def __call__(self, coordinates):
#         return self.translation.vector + self.scaling.vector * self.rotation.rotation_matrix.dot(coordinates)
# 
#     def __str__(self):
#         return '\n'.join(['Rotation:\t%.4f (rad)' % self.rotation.angle,
#                           'Scaling:\tXY %.4f \tZ %.4f ' %
#                           (self.scaling.horizontal_factor, self.scaling.vertical_factor),
#                           'Translation:\tX %.4f \t Y %.4f \t Z %.4f' %
#                           (self.translation.dx, self.translation.dy, self.translation.dz)])
# 
#     def inverse(self):
#         """!
#         @brief The inverse transformation
#         The inverse transformation is a transformation with inverse rotation, inverse scaling
#         and a translation vector that is equal to the result of inverse rotation and inverse scaling
#         of the inverse translation vector
#         """
#         inverse_rotation = self.rotation.inverse()
#         inverse_scaling = self.scaling.inverse()
#         inverse_translation = self.translation.inverse()
#         inverse_dx, inverse_dy, inverse_dz = inverse_scaling.vector * \
#                                              inverse_rotation.rotation_matrix.dot(inverse_translation.vector)
#         return Transformation(inverse_rotation.angle,
#                               inverse_scaling.horizontal_factor, inverse_scaling.vertical_factor,
#                               inverse_dx, inverse_dy, inverse_dz)
# 
# Path: pyteltools/slf/Serafin.py
# class Serafin:
#     """!
#     @brief A Serafin object corresponds to a single Serafin in file IO stream
# 
#     # Attributes:
#     - language <str>: language for variables ('fr' or 'en')
#     - mode <str>: file open mode
#     - file <_io.BufferedReader>: input Serafin stream
#     - filename <str>: path to file
#     - file_size <int>: size of file
#     """
#     def __init__(self, filename, mode, language):
#         self.language = language
#         self.mode = mode
# 
#         self.file = None  # will be opened when called using `with` statement
#         self.filename = filename
#         self.file_size = None
# 
#     def __enter__(self):
#         self.file = open(self.filename, self.mode)
#         return self
# 
#     def __exit__(self, exc_type, exc_val, exc_tb):
#         self.file.close()
#         return False
# 
# Path: pyteltools/utils/cli_base.py
# LINE_WIDTH = 80
# class CustomFormatter(argparse.ArgumentDefaultsHelpFormatter, argparse.RawDescriptionHelpFormatter):
# class PyTelToolsArgParse(argparse.ArgumentParser):
#     def __init__(self, add_args=[], description=None, *args, **kwargs):
#     def add_known_argument(self, arg_id):
#     def _add_auto_arguments(self):
#     def _title_group(label):
#     def add_argument_group(self, name, *args, **kwargs):
#     def add_group_general(self, add_args=[]):
#     def parse_args(self, *args, **kwargs):


# Path: cli/slf_last.py
import numpy as np
import sys
from pyteltools.geom.transformation import Transformation
from pyteltools.slf import Serafin
from pyteltools.utils.cli_base import logger, PyTelToolsArgParse

#!/usr/bin/env python
"""
Extract last temporal frame of a 2D/3D Serafin file
"""




def slf_last(args):
    with Serafin.Read(args.in_slf, args.lang) as resin:
        resin.read_header()
        logger.info(resin.header.summary())
        resin.get_time()

        output_header = resin.header.copy()
        # Shift mesh coordinates if necessary
        if args.shift:

            output_header.transform_mesh([Transformation(0, 1, 1, args.shift[0], args.shift[1], 0)])