def update_inverse(self):
        angle, scalexy, scalez, dx, dy, dz = map(float, [box.text() for box in [self.inv_angle,
                                                                                self.inv_scalexy, self.inv_scalez,
                                                                                self.inv_dx, self.inv_dy, self.inv_dz]])
        self.inverse_trans = Transformation(angle, scalexy, scalez, dx, dy, dz)
        self.trans = self.inverse_trans.inverse()

        self.dx.setText(str(self.trans.translation.dx))
        self.dy.setText(str(self.trans.translation.dy))
        self.dz.setText(str(self.trans.translation.dz))
        self.angle.setText(str(self.trans.rotation.angle))
        self.scalexy.setText(str(self.trans.scaling.horizontal_factor))
        self.scalez .setText(str(self.trans.scaling.vertical_factor))
Exemple #2
0
def slf_base(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)])
        # Set mesh origin coordinates
        if args.set_mesh_origin:
            output_header.set_mesh_origin(args.set_mesh_origin[0], args.set_mesh_origin[1])

        # Toggle output file endianness if necessary
        if args.toggle_endianness:
            output_header.toggle_endianness()

        # Convert to single precision
        if args.to_single_precision:
            if resin.header.is_double_precision():
                output_header.to_single_precision()
            else:
                logger.warn('Input file is already single precision! Argument `--to_single_precision` is ignored')

        # Remove variables if necessary
        if args.var2del:
            output_header.empty_variables()
            for var_ID, var_name, var_unit in zip(resin.header.var_IDs, resin.header.var_names, resin.header.var_units):
                if var_ID not in args.var2del:
                    output_header.add_variable(var_ID, var_name, var_unit)

        # Add new derived variables
        if args.var2add is not None:
            for var_ID in args.var2add:
                if var_ID in output_header.var_IDs:
                    logger.warn('Variable %s is already present (or asked)' % var_ID)
                else:
                    output_header.add_variable_from_ID(var_ID)

        us_equation = get_US_equation(args.friction_law)
        necessary_equations = get_necessary_equations(resin.header.var_IDs, output_header.var_IDs,
                                                      is_2d=resin.header.is_2d, us_equation=us_equation)

        with Serafin.Write(args.out_slf, args.lang, overwrite=args.force) as resout:
            resout.write_header(output_header)

            for time_index, time in tqdm(resin.subset_time(args.start, args.end, args.ech), unit='frame'):
                values = do_calculations_in_frame(necessary_equations, resin, time_index, output_header.var_IDs,
                                                  output_header.np_float_type, is_2d=output_header.is_2d,
                                                  us_equation=us_equation, ori_values={})
                resout.write_entire_frame(output_header, time, values)
 def load(self):
     msg = QMessageBox.warning(
         None, 'Confirm load',
         'Do you want to load configuration file?\n(Your current workspace will be erased)',
         QMessageBox.Ok | QMessageBox.Cancel, QMessageBox.Ok)
     if msg == QMessageBox.Cancel:
         return
     filename, _ = QFileDialog.getOpenFileName(
         self,
         'Choose the file name',
         '',
         'All files (*)',
         options=QFileDialog.Options() | QFileDialog.DontUseNativeDialog)
     if not filename:
         return
     try:
         with open(filename, 'r') as f:
             new_labels = f.readline().rstrip().split('|')
             coords = f.readline().rstrip().split('|')
             new_rectangles = []
             for coord in coords:
                 x, y = map(int, coord.split(','))
                 new_rectangles.append(
                     QRect(x, y, self.recWidth, self.recHeight))
             new_transformations = {}
             for line in f.readlines():
                 i, j, params = line.rstrip().split('|')
                 i, j = int(i), int(j)
                 angle, scalexy, scalez, dx, dy, dz = map(
                     float, params.split())
                 new_transformations[i, j] = Transformation(
                     angle, scalexy, scalez, dx, dy, dz)
                 new_transformations[j,
                                     i] = new_transformations[i,
                                                              j].inverse()
         if len(new_labels) < 2:
             raise ValueError
         if not is_connected(list(range(len(new_labels))),
                             new_transformations.keys()):
             raise ValueError
     except (ValueError, IndexError):
         QMessageBox.critical(self, 'Error',
                              'The configuration is not valid.',
                              QMessageBox.Ok)
         return
     self.btnAddConnect.setEnabled(False)
     self.btnSave.setEnabled(True)
     self.labels = new_labels
     self.rectangles = new_rectangles
     self.transformations = new_transformations
     self.repaint()
Exemple #4
0
def slf_to_raster(args):
    with Serafin.Read(args.in_slf, args.lang) as resin:
        resin.read_header()
        header = resin.header
        logger.info(header.summary())
        resin.get_time()

        if args.vars is None:
            var_names = [
                var_name.decode('utf-8') for var_name in header.var_names
            ]
            var_IDs = header.var_IDs
        else:
            var_names = []
            var_IDs = []
            for var_ID, var_name in zip(header.var_IDs, header.var_names):
                if var_ID in args.vars:
                    var_names.append(var_name.decode('utf-8'))
                    var_IDs.append(var_ID)

        # Shift mesh coordinates if necessary
        if args.shift:
            header.transform_mesh(
                [Transformation(0, 1, 1, args.shift[0], args.shift[1], 0)])

        # Build output regular grid and matplotlib triangulation of the mesh
        m_xi, m_yi = np.meshgrid(
            np.arange(header.x.min(), header.x.max(), args.resolution),
            np.arange(header.y.min(), header.y.max(), args.resolution))
        triang = mtri.Triangulation(header.x,
                                    header.y,
                                    triangles=header.ikle_2d - 1)

        # Build list containing all interpolated variables on the regular grid
        array_list = []
        for i, (var_ID, var_name) in enumerate(zip(var_IDs, var_names)):
            values = resin.read_var_in_frame(args.frame_index, var_ID)
            interp = mtri.LinearTriInterpolator(triang, values)
            data = interp(
                m_xi,
                m_yi)[::-1]  # reverse array so the tif looks like the array
            array_list.append((var_name, data))
            logger.info(
                "Min and max values for interpolated %s variable: [%f, %f]" %
                (var_name, data.min(), data.max()))

        # Write data in the raster output file
        arrays2raster(args.out_tif, (header.x.min(), header.y.max()),
                      args.resolution, -args.resolution, array_list)
 def check(self):
     try:
         angle, scalexy, scalez, dx, dy, dz = map(float, [box.text() for box in [self.angle,
                                                                                 self.scalexy, self.scalez,
                                                                                 self.dx, self.dy, self.dz]])
     except ValueError:
         QMessageBox.critical(self, 'Error', 'The transformation parameters should be numbers!',
                              QMessageBox.Ok)
         return
     if scalexy == 0 or scalez == 0:
         QMessageBox.critical(self, 'Error', 'The scaling factors cannot be equal to zero!',
                              QMessageBox.Ok)
         return
     self.transformation = Transformation(angle, scalexy, scalez, dx, dy, dz)
     self.accept()
Exemple #6
0
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)])

        # Toggle output file endianness if necessary
        if args.toggle_endianness:
            output_header.toggle_endianness()

        # Convert to single precision
        if args.to_single_precision:
            if resin.header.is_double_precision():
                output_header.to_single_precision()
            else:
                logger.warn(
                    'Input file is already single precision! Argument `--to_single_precision` is ignored'
                )

        values = np.empty((output_header.nb_var, output_header.nb_nodes),
                          dtype=output_header.np_float_type)
        with Serafin.Write(args.out_slf, args.lang,
                           overwrite=args.force) as resout:
            resout.write_header(output_header)

            time_index = len(resin.time) - 1
            time = resin.time[-1] if args.time is None else args.time

            for i, var_ID in enumerate(output_header.var_IDs):
                values[i, :] = resin.read_var_in_frame(time_index, var_ID)

            resout.write_entire_frame(output_header, time, values)
Exemple #7
0
    def get_zones_from_i3s_file(shp_name, threshold, operator_str):
        polylines = []

        attributes = shp.get_numeric_attribute_names(shp_name)
        if args.attr_to_shift_z is not None:
            try:
                index_attr = [attr for _, attr in attributes].index(args.attr_to_shift_z)
            except ValueError:
                logger.critical('Attribute "%s" is not found.' % args.attr_to_shift_z)
                sys.exit(1)

        for polyline in shp.get_open_polylines(shp_name):
            if not polyline.polyline().is_valid:
                sys.exit("ERROR: polyline is not valid (probably because it intersects itself)!")

            # Shift z (if requested)
            if args.attr_to_shift_z is not None:
                dz = polyline.attributes()[index_attr]
                print(dz)

                polyline = polyline.apply_transformations([Transformation(0.0, 1.0, 1.0, 0.0, 0.0, dz)])

            # Linear interpolation along the line for values below the threshold
            if threshold is not None:
                np_coord = np.array(polyline.coords())
                Xt = np.sqrt(np.power(np.ediff1d(np_coord[:, 0], to_begin=0.), 2) +
                             np.power(np.ediff1d(np_coord[:, 1], to_begin=0.), 2))
                Xt = Xt.cumsum()
                ref_rows = np_coord[:, 2] > args.threshold
                np_coord[:, 2] = np.interp(Xt, Xt[ref_rows], np_coord[ref_rows, 2])
                polyline = geo.LineString(np_coord)
            polylines.append(polyline)

        zones = []
        for prev_line, next_line in zip(polylines[:-1], polylines[1:]):
            zones.append(Zone(prev_line, next_line, operator_str))
        return zones
Exemple #8
0
def slf_sedi_chain(args):
    # Check that float parameters are positive (especially ws!)
    for arg in ('Cmud', 'ws', 'C', 'M'):
        if getattr(args, arg) < 0:
            logger.critical('The argument %s has to be positive' % args)
            sys.exit(1)

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

        us_equation = get_US_equation(args.friction_law)
        necessary_equations = get_necessary_equations(resin.header.var_IDs,
                                                      ['TAU'],
                                                      is_2d=True,
                                                      us_equation=us_equation)

        if resin.header.nb_frames < 1:
            logger.critical('The input file must have at least one frame!')
            sys.exit(1)

        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)])

        # Toggle output file endianness if necessary
        if args.toggle_endianness:
            output_header.toggle_endianness()

        # Convert to single precision
        if args.to_single_precision:
            if resin.header.is_double_precision():
                output_header.to_single_precision()
            else:
                logger.warn(
                    'Input file is already single precision! Argument `--to_single_precision` is ignored'
                )

        output_header.empty_variables()
        output_header.add_variable_from_ID('B')
        output_header.add_variable_from_ID('EV')

        with Serafin.Write(args.out_slf, args.lang,
                           overwrite=args.force) as resout:
            resout.write_header(output_header)

            prev_time = None
            prev_tau = None
            initial_bottom = resin.read_var_in_frame(0, 'B')
            bottom = copy(initial_bottom)
            for time_index, time in enumerate(resin.time):
                tau = do_calculations_in_frame(necessary_equations,
                                               resin,
                                               time_index, ['TAU'],
                                               output_header.np_float_type,
                                               is_2d=True,
                                               us_equation=us_equation,
                                               ori_values={})[0]
                if prev_time is not None:
                    dt = time - prev_time
                    mean_tau = (prev_tau + tau) / 2
                    if args.Tcd > 0:
                        bottom += args.Cmud * args.ws * args.C * \
                                  (1 - np.clip(mean_tau/args.Tcd, a_min=None, a_max=1.)) * dt
                    if args.Tce > 0:
                        bottom -= args.Cmud * args.M * (np.clip(
                            mean_tau / args.Tce, a_min=1., a_max=None) -
                                                        1.) * dt

                evol_bottom = bottom - initial_bottom
                resout.write_entire_frame(output_header, time,
                                          np.vstack((bottom, evol_bottom)))

                prev_time = time
                prev_tau = tau
Exemple #9
0
def slf_3d_to_2d(args):
    with Serafin.Read(args.in_slf, args.lang) as resin:
        resin.read_header()
        logger.info(resin.header.summary())
        resin.get_time()

        if resin.header.is_2d:
            logger.critical('The input file is not 3D.')
            sys.exit(1)
        if 'Z' not in resin.header.var_IDs:
            logger.critical('The elevation variable Z is not found in the Serafin file.')
            sys.exit(1)
        if args.layer is not None:
            upper_plane = resin.header.nb_planes
            if args.layer < 1 or args.layer > upper_plane:
                logger.critical('Layer has to be in [1, %i]' % upper_plane)
                sys.exit(1)

        output_header = resin.header.copy_as_2d()
        # Shift mesh coordinates if necessary
        if args.shift:
            output_header.transform_mesh([Transformation(0, 1, 1, args.shift[0], args.shift[1], 0)])

        # Toggle output file endianness if necessary
        if args.toggle_endianness:
            output_header.toggle_endianness()

        # Convert to single precision
        if args.to_single_precision:
            if resin.header.is_double_precision():
                output_header.to_single_precision()
            else:
                logger.warn('Input file is already single precision! Argument `--to_single_precision` is ignored')

        if args.aggregation is not None:
            if args.aggregation == 'max':
                operation_type = operations.MAX
            elif args.aggregation == 'min':
                operation_type = operations.MIN
            else:  # args.aggregation == 'mean'
                 operation_type = operations.MEAN
            selected_vars = [var for var in output_header.iter_on_all_variables()]
            vertical_calculator = operations.VerticalMaxMinMeanCalculator(operation_type, resin, output_header,
                                                                          selected_vars, args.vars)
            output_header.set_variables(vertical_calculator.get_variables())  # sort variables

        # Add some elevation variables
        for var_ID in args.vars:
            output_header.add_variable_from_ID(var_ID)

        with Serafin.Write(args.out_slf, args.lang, overwrite=args.force) as resout:
            resout.write_header(output_header)

            vars_2d = np.empty((output_header.nb_var, output_header.nb_nodes_2d), dtype=output_header.np_float_type)
            for time_index, time in enumerate(tqdm(resin.time, unit='frame')):
                if args.aggregation is not None:
                    vars_2d = vertical_calculator.max_min_mean_in_frame(time_index)
                else:
                    for i, var in enumerate(output_header.var_IDs):
                        vars_2d[i, :] = resin.read_var_in_frame_as_3d(time_index, var)[args.layer - 1, :]
                resout.write_entire_frame(output_header, time, vars_2d)
def ADCP_comp(args):
    x_mes = []
    y_mes = []
    cord_mes = open(args.inADCP_GPS).read().splitlines()
    for x_l in cord_mes:
        y, x = x_l.split(',')
        if x == NODATA or y == NODATA:
            print("Warning: one point is missing")
        else:
            x_mes.append(x)
            y_mes.append(y)
    x_mes = [float(a) for a in x_mes]
    y_mes = [float(a) for a in y_mes]
    inProj = Proj("+init=EPSG:%i" % args.inEPSG)
    outProj = Proj("+init=EPSG:%i" % args.outEPSG)
    x_mes, y_mes = transform(inProj, outProj, x_mes, y_mes)

    SCHEMA = {'geometry': 'LineString', 'properties': {'nom': 'str'}}
    with fiona.open(args.outADCP_GPS,
                    'w',
                    'ESRI Shapefile',
                    SCHEMA,
                    crs=from_epsg(args.outEPSG)) as out_shp:
        Ltest = LineString([(x_2, y_2) for x_2, y_2 in zip(x_mes, y_mes)])
        elem = {}
        elem['geometry'] = mapping(Ltest)
        elem['properties'] = {'nom': 'ADCP line'}
        out_shp.write(elem)

    p_raw = RawProfileObj(args.inADCP)
    processing_settings = {'proj_method': 2}
    startingpoint = dict(start=Vector(0, 0))
    p0 = ProcessedProfileObj(p_raw, processing_settings, startingpoint)
    profile_averaged = averaging.get_averaged_profile(p0, cfg={'order': 15})
    header = 'X;Y;Uadcp;Vadcp;MagnitudeXY;Hadcp\n'
    writeAscii2D(profile_averaged,
                 '{x};{y};{vx};{vy};{vmag};{depth}',
                 args.outADCP,
                 header=header)

    if args.inTELEMAC:
        with open(args.outT2DCSV, 'w', newline='') as csvfile:
            csvwriter = csv.writer(csvfile, delimiter=';')
            HEADER = [
                'folder', 'time_id', 'time', 'point_x', 'point_y', 'distance',
                'value'
            ]
            csvwriter.writerow(HEADER)

            for slf_path in args.inTELEMAC:
                folder = os.path.basename(os.path.split(slf_path)[0])
                with Serafin.Read(slf_path, 'fr') as resin:
                    resin.read_header()
                    logger.info(resin.header.summary())
                    resin.get_time()
                    output_header = resin.header.copy()
                    if args.shift:
                        output_header.transform_mesh([
                            Transformation(0, 1, 1, args.shift[0],
                                           args.shift[1], 0)
                        ])
                    mesh = MeshInterpolator(output_header, True)
                    lines = []
                    for poly in Shapefile.get_lines(args.outADCP_GPS,
                                                    shape_type=3):
                        lines.append(poly)
                    nb_nonempty, indices_nonempty, line_interpolators, line_interpolators_internal = \
                        mesh.get_line_interpolators(lines)
                    res = mesh.interpolate_along_lines(
                        resin, 'M', list(range(len(resin.time))),
                        indices_nonempty, line_interpolators, '{:.6e}')
                    csvwriter.writerows([[folder] + x[2] for x in res])
class EditTransformationDialog(QDialog):
    def __init__(self, from_label, to_label, trans, inverse_trans):
        super().__init__()
        self.deleted = False

        self.trans = trans
        self.inverse_trans = inverse_trans
        buttons = QDialogButtonBox(
            QDialogButtonBox.Ok | QDialogButtonBox.Cancel, Qt.Horizontal, self)
        buttons.accepted.connect(self.accept)
        buttons.rejected.connect(self.reject)

        deleteButton = QPushButton('Delete')
        deleteButton.setFixedSize(110, 30)
        deleteButton.clicked.connect(self.deleteEvent)

        self.dx = QLineEdit(str(trans.translation.dx))
        self.dy = QLineEdit(str(trans.translation.dy))
        self.dz = QLineEdit(str(trans.translation.dz))
        self.angle = QLineEdit(str(trans.rotation.angle))
        self.scalexy = QLineEdit(str(trans.scaling.horizontal_factor))
        self.scalez = QLineEdit(str(trans.scaling.vertical_factor))

        self.inv_dx = QLineEdit(str(inverse_trans.translation.dx))
        self.inv_dy = QLineEdit(str(inverse_trans.translation.dy))
        self.inv_dz = QLineEdit(str(inverse_trans.translation.dz))
        self.inv_angle = QLineEdit(str(inverse_trans.rotation.angle))
        self.inv_scalexy = QLineEdit(
            str(inverse_trans.scaling.horizontal_factor))
        self.inv_scalez = QLineEdit(str(inverse_trans.scaling.vertical_factor))

        self.dx.editingFinished.connect(self.edit_dx)
        self.dy.editingFinished.connect(self.edit_dy)
        self.dz.editingFinished.connect(self.edit_dz)
        self.angle.editingFinished.connect(self.edit_angle)
        self.scalexy.editingFinished.connect(self.edit_scalexy)
        self.scalez.editingFinished.connect(self.edit_scalez)

        self.inv_dx.editingFinished.connect(self.edit_inv_dx)
        self.inv_dy.editingFinished.connect(self.edit_inv_dy)
        self.inv_dz.editingFinished.connect(self.edit_inv_dz)
        self.inv_angle.editingFinished.connect(self.edit_inv_angle)
        self.inv_scalexy.editingFinished.connect(self.edit_inv_scalexy)
        self.inv_scalez.editingFinished.connect(self.edit_inv_scalez)

        mainLayout = QVBoxLayout()

        vlayout = QVBoxLayout()
        lb = QLabel('<b>Transformation from %s to %s<b>' %
                    (from_label, to_label))
        vlayout.addWidget(lb)
        vlayout.setAlignment(lb, Qt.AlignHCenter)
        vlayout.addItem(QSpacerItem(10, 10))
        glayout = QGridLayout()

        glayout.addWidget(QLabel('<b>Rotation<b>'), 1, 1)
        glayout.addWidget(QLabel('angle (rad)'), 2, 2, Qt.AlignRight)
        glayout.addWidget(self.angle, 2, 3)

        glayout.addWidget(QLabel('<b>Scaling<b>'), 3, 1)
        glayout.addWidget(QLabel('XY factor'), 4, 2, Qt.AlignRight)
        glayout.addWidget(self.scalexy, 4, 3)
        glayout.addWidget(QLabel('Z factor'), 4, 4, Qt.AlignRight)
        glayout.addWidget(self.scalez, 4, 5)

        glayout.addWidget(QLabel('<b>Translation<b>'), 5, 1)
        glayout.addWidget(QLabel('translate X'), 6, 2, Qt.AlignRight)
        glayout.addWidget(self.dx, 6, 3)
        glayout.addWidget(QLabel('translate Y'), 6, 4, Qt.AlignRight)
        glayout.addWidget(self.dy, 6, 5)
        glayout.addWidget(QLabel('translate Z'), 6, 6, Qt.AlignRight)
        glayout.addWidget(self.dz, 6, 7)
        vlayout.addLayout(glayout)
        mainLayout.addLayout(vlayout)
        mainLayout.setAlignment(vlayout, Qt.AlignTop)
        mainLayout.addItem(QSpacerItem(10, 20))

        vlayout = QVBoxLayout()
        lb = QLabel('<b>Transformation from %s to %s<b>' %
                    (to_label, from_label))
        vlayout.addWidget(lb)
        vlayout.setAlignment(lb, Qt.AlignHCenter)
        vlayout.addItem(QSpacerItem(10, 10))
        glayout = QGridLayout()

        glayout.addWidget(QLabel('<b>Rotation<b>'), 1, 1)
        glayout.addWidget(QLabel('angle (rad)'), 2, 2, Qt.AlignRight)
        glayout.addWidget(self.inv_angle, 2, 3)

        glayout.addWidget(QLabel('<b>Scaling<b>'), 3, 1)
        glayout.addWidget(QLabel('XY factor'), 4, 2, Qt.AlignRight)
        glayout.addWidget(self.inv_scalexy, 4, 3)
        glayout.addWidget(QLabel('Z factor'), 4, 4, Qt.AlignRight)
        glayout.addWidget(self.inv_scalez, 4, 5)

        glayout.addWidget(QLabel('<b>Translation<b>'), 5, 1)
        glayout.addWidget(QLabel('translate X'), 6, 2, Qt.AlignRight)
        glayout.addWidget(self.inv_dx, 6, 3)
        glayout.addWidget(QLabel('translate Y'), 6, 4, Qt.AlignRight)
        glayout.addWidget(self.inv_dy, 6, 5)
        glayout.addWidget(QLabel('translate Z'), 6, 6, Qt.AlignRight)
        glayout.addWidget(self.inv_dz, 6, 7)
        vlayout.addLayout(glayout)
        mainLayout.addLayout(vlayout)
        mainLayout.setAlignment(vlayout, Qt.AlignTop)

        mainLayout.addItem(QSpacerItem(50, 20))
        mainLayout.addWidget(deleteButton, Qt.AlignLeft)
        mainLayout.addItem(QSpacerItem(50, 20))
        mainLayout.addWidget(buttons)

        self.setLayout(mainLayout)
        self.setWindowTitle('Edit transformation')
        self.resize(self.sizeHint())

    def edit_dx(self):
        try:
            _ = float(self.dx.text())
            self.update()
        except ValueError:
            self.dx.setText(str(self.trans.translation.dx))

    def edit_dy(self):
        try:
            _ = float(self.dy.text())
            self.update()
        except ValueError:
            self.dy.setText(str(self.trans.translation.dy))

    def edit_dz(self):
        try:
            _ = float(self.dz.text())
            self.update()
        except ValueError:
            self.dz.setText(str(self.trans.translation.dz))

    def edit_angle(self):
        try:
            _ = float(self.angle.text())
            self.update()
        except ValueError:
            self.angle.setText(str(self.trans.rotation.angle))

    def edit_scalexy(self):
        try:
            scalexy = float(self.scalexy.text())
            if scalexy == 0:
                self.scalexy.setText(str(self.trans.scaling.horizontal_factor))
            else:
                self.update()
        except ValueError:
            self.scalexy.setText(str(self.trans.scaling.horizontal_factor))

    def edit_scalez(self):
        try:
            scalez = float(self.scalez.text())
            if scalez == 0:
                self.scalez.setText(str(self.trans.scaling.vertical_factor))
            else:
                self.update()
        except ValueError:
            self.scalez.setText(str(self.trans.scaling.vertical_factor))

    def edit_inv_dx(self):
        try:
            _ = float(self.inv_dx.text())
            self.update_inverse()
        except ValueError:
            self.inv_dx.setText(str(self.inverse_trans.translation.dx))

    def edit_inv_dy(self):
        try:
            _ = float(self.inv_dy.text())
            self.update_inverse()
        except ValueError:
            self.inv_dy.setText(str(self.inverse_trans.translation.dy))

    def edit_inv_dz(self):
        try:
            _ = float(self.inv_dz.text())
            self.update_inverse()
        except ValueError:
            self.inv_dz.setText(str(self.inverse_trans.translation.dz))

    def edit_inv_angle(self):
        try:
            _ = float(self.inv_angle.text())
            self.update_inverse()
        except ValueError:
            self.inv_angle.setText(str(self.inverse_trans.rotation.angle))

    def edit_inv_scalexy(self):
        try:
            scalexy = float(self.inv_scalexy.text())
            if scalexy == 0:
                self.inv_scalexy.setText(
                    str(self.inverse_trans.scaling.horizontal_factor))
            else:
                self.update_inverse()
        except ValueError:
            self.inv_scalexy.setText(
                str(self.inverse_trans.scaling.horizontal_factor))

    def edit_inv_scalez(self):
        try:
            scalez = float(self.inv_scalez.text())
            if scalez == 0:
                self.inv_scalez.setText(
                    str(self.inverse_trans.scaling.vertical_factor))
            else:
                self.update_inverse()
        except ValueError:
            self.inv_scalez.setText(
                str(self.inverse_trans.scaling.vertical_factor))

    def update(self):
        angle, scalexy, scalez, dx, dy, dz = map(float, [
            box.text() for box in
            [self.angle, self.scalexy, self.scalez, self.dx, self.dy, self.dz]
        ])
        self.trans = Transformation(angle, scalexy, scalez, dx, dy, dz)
        self.inverse_trans = self.trans.inverse()

        self.inv_dx.setText(str(self.inverse_trans.translation.dx))
        self.inv_dy.setText(str(self.inverse_trans.translation.dy))
        self.inv_dz.setText(str(self.inverse_trans.translation.dz))
        self.inv_angle.setText(str(self.inverse_trans.rotation.angle))
        self.inv_scalexy.setText(
            str(self.inverse_trans.scaling.horizontal_factor))
        self.inv_scalez.setText(str(
            self.inverse_trans.scaling.vertical_factor))

    def update_inverse(self):
        angle, scalexy, scalez, dx, dy, dz = map(float, [
            box.text() for box in [
                self.inv_angle, self.inv_scalexy, self.inv_scalez, self.inv_dx,
                self.inv_dy, self.inv_dz
            ]
        ])
        self.inverse_trans = Transformation(angle, scalexy, scalez, dx, dy, dz)
        self.trans = self.inverse_trans.inverse()

        self.dx.setText(str(self.trans.translation.dx))
        self.dy.setText(str(self.trans.translation.dy))
        self.dz.setText(str(self.trans.translation.dz))
        self.angle.setText(str(self.trans.rotation.angle))
        self.scalexy.setText(str(self.trans.scaling.horizontal_factor))
        self.scalez.setText(str(self.trans.scaling.vertical_factor))

    def deleteEvent(self):
        msg = QMessageBox.warning(
            None, 'Confirm delete',
            'Do you want to delete this transformation?',
            QMessageBox.Ok | QMessageBox.Cancel, QMessageBox.Ok)
        if msg == QMessageBox.Cancel:
            return
        self.deleted = True
        self.reject()