Esempio n. 1
0
    def stream(self):
        # Avoid auth exception if you reopen the project and don't open the search
        if self.mySearch == None:
            self.mySearch = MySearch(self.iface)

        # Get selected feature of active layer
        service = self.selectedFeature['service']

        # Setup raster params
        isWcs = False
        if service == 'BaseMap':
            if self.mySearch.bmAuth is None:
                try:
                    self.mySearch.bmSetAuth()
                except:
                    return
            username = self.mySearch.bmUsernameInput.text()
            password = self.mySearch.bmPasswordInput.text()
            layers = self.mySearch.bmGetLayer(self.selectedFeature['wmts'])
            styles = 'default'
            tileMatrixSet = '4326'
            urlAttr = 'wmts'
        elif service == 'Data':
            if self.mySearch.dtHeaders is None:
                try:
                    self.mySearch.dtSetAuth()
                except:
                    return
            username = '******'
            password = self.mySearch.dtApikeyInput.text()

            # Dialog for image choice (panchro/multi & wmts/wcs)
            self.msgBox = QMessageBox()
            self.msgBox.setWindowTitle('Airbus')

            protocolGroup = QGroupBox('Protocol')
            protocolGrid = QGridLayout()
            wmtsRadio = QRadioButton('WMTS')
            wcsRadio = QRadioButton('WCS')
            protocolGrid.addWidget(wmtsRadio, 0, 0)
            protocolGrid.addWidget(wcsRadio, 0, 1)
            protocolGroup.setLayout(protocolGrid)

            styleGroup = QGroupBox('Style')
            styleGrid = QGridLayout()
            multispectralRadio = QRadioButton('multispectral')
            panchromaticRadio = QRadioButton('panchromatic')
            styleGrid.addWidget(multispectralRadio, 0, 0)
            styleGrid.addWidget(panchromaticRadio, 0, 1)
            styleGroup.setLayout(styleGrid)

            self.msgBox.layout().addWidget(protocolGroup, 0, 0)
            self.msgBox.layout().addWidget(styleGroup, 1, 0)

            wmtsRadio.setChecked(True)
            if type(self.selectedFeature['wcs_multispectral']) != str:
                protocolGroup.setEnabled(False)

            multispectralRadio.setChecked(True)

            self.msgBox.setStandardButtons(QMessageBox.Abort | QMessageBox.Ok)
            reply = self.msgBox.exec_()
            if reply == QMessageBox.Abort:
                return
            if wmtsRadio.isChecked():
                urlAttr = 'wmts_'
                layers = 'default'
                styles = 'rgb'
                tileMatrixSet = 'EPSG4326'
            else:
                urlAttr = 'wcs_'
                isWcs = True
            if multispectralRadio.isChecked():
                urlAttr += 'multispectral'
            else:
                urlAttr += 'panchromatic'
        else:
            self.error(
                f'Service "{service}" of the feature ocg_fid={self.selectedFeature.id()} isn\'t recognized\nIt should be "Basemap" or "Data"'
            )
            return

        # Add a WMTS raster layer
        # Order of url parameters are important !
        # Why layers is required, maybe is an internal id for wmts gesture ?
        # What is styles ?
        try:
            url = self.selectedFeature[urlAttr]
            name = f'{service} {self.selectedFeature["id"]}'
            if isWcs:
                rlayer = QgsRasterLayer(
                    f'dpiMode=7&identifier=default&password={password}&url={url}&username={username}',
                    name, 'wcs')
            else:
                rlayer = QgsRasterLayer(
                    f'crs=EPSG:4326&dpiMode=7&format=image/png&layers={layers}&password={password}&styles={styles}&tileMatrixSet={tileMatrixSet}&url={url}&username={username}',
                    name, 'wms')
        except Exception as e:
            self.error(f'Error in protocol connection\n\n{str(e)}')
            return
        if rlayer.isValid() == False:
            self.error(f'Raster layer is invalid\n\n{rlayer.error()}')
            return

        QgsProject.instance().addMapLayer(rlayer)
Esempio n. 2
0
class OutputAnalyserDialog(QDialog):

    def __init__(self, iface, parent, params):

        QDialog.__init__(self, parent)

        self.iface = iface
        self.parent = parent
        self.params = params

        self.output_reader = None
        self.tool = None
        self.element_ids_nodes = None
        self.element_ids_links = None

        self.nodes_lay = None
        self.links_lay = None

        self.setWindowTitle(Parameters.plug_in_name)

        # Selection changed listeners
        self.params.junctions_vlay.selectionChanged.connect(self.feature_sel_changed)
        self.params.reservoirs_vlay.selectionChanged.connect(self.feature_sel_changed)
        self.params.tanks_vlay.selectionChanged.connect(self.feature_sel_changed)
        self.params.pipes_vlay.selectionChanged.connect(self.feature_sel_changed)
        self.params.pumps_vlay.selectionChanged.connect(self.feature_sel_changed)
        self.params.valves_vlay.selectionChanged.connect(self.feature_sel_changed)

        # self.setMinimumWidth(min_width)
        # self.setMinimumHeight(min_height)
        fra_main_lay = QVBoxLayout(self)

        self.fra_out_file = QFrame(self)
        fra_out_file_lay = QHBoxLayout(self.fra_out_file)
        self.lbl_out_file = QLabel('Simulation output file:')
        self.txt_out_file = QLineEdit('')
        self.txt_out_file.setReadOnly(True)
        self.btn_out_file = QToolButton()
        self.btn_out_file.setText('...')
        self.btn_out_file.clicked.connect(self.btn_out_file_clicked)
        fra_out_file_lay.addWidget(self.lbl_out_file)
        fra_out_file_lay.addWidget(self.txt_out_file)
        fra_out_file_lay.addWidget(self.btn_out_file)

        self.tab_widget = QTabWidget(self)

        # Graphs tab ---------------------------------------------------------------------------------------------------
        self.tab_graphs = QWidget()
        tab_graphs_lay = QHBoxLayout(self.tab_graphs)

        # Left frame
        self.fra_graphs_left = QFrame()
        self.fra_graphs_left.setMaximumWidth(100)
        fra_graphs_left_lay = QVBoxLayout(self.fra_graphs_left)

        self.btn_sel_element = QPushButton('Pick')
        self.btn_sel_element.clicked.connect(self.btn_sel_element_clicked)
        fra_graphs_left_lay.addWidget(self.btn_sel_element)

        # Nodes
        self.grb_nodes = QGroupBox(u'Nodes')
        lay_grb_nodes = QVBoxLayout(self.grb_nodes)

        self.chk_node_demand = QCheckBox('Demand')
        lay_grb_nodes.addWidget(self.chk_node_demand)

        self.chk_node_head =  QCheckBox('Head')
        lay_grb_nodes.addWidget(self.chk_node_head)

        self.chk_node_pressure = QCheckBox('Pressure')
        lay_grb_nodes.addWidget(self.chk_node_pressure)

        self.chk_node_quality = QCheckBox('Quality')
        lay_grb_nodes.addWidget(self.chk_node_quality)

        fra_graphs_left_lay.addWidget(self.grb_nodes)

        # Links
        self.grb_links = QGroupBox(u'Links')
        lay_grb_links = QVBoxLayout(self.grb_links)

        self.chk_link_flow = QCheckBox('Flow')
        lay_grb_links.addWidget(self.chk_link_flow)

        self.chk_link_velocity = QCheckBox('Velocity')
        lay_grb_links.addWidget(self.chk_link_velocity)

        self.chk_link_headloss = QCheckBox('Headloss')
        lay_grb_links.addWidget(self.chk_link_headloss)

        self.chk_link_quality = QCheckBox('Quality')
        lay_grb_links.addWidget(self.chk_link_quality)

        fra_graphs_left_lay.addWidget(self.grb_links)

        self.btn_draw_graph = QPushButton('Draw')
        self.btn_draw_graph.clicked.connect(self.draw_graphs)
        fra_graphs_left_lay.addWidget(self.btn_draw_graph)

        self.spacer = QSpacerItem(20, 40, QSizePolicy.Minimum, QSizePolicy.Expanding)
        fra_graphs_left_lay.addItem(self.spacer)

        tab_graphs_lay.addWidget(self.fra_graphs_left)

        # Right frame
        self.fra_graphs_right = QFrame()
        fra_graphs_right_lay = QVBoxLayout(self.fra_graphs_right)
        fra_graphs_right_lay.setContentsMargins(0, 0, 0, 0)

        self.static_canvas = StaticMplCanvas(self.fra_graphs_right, width=5, height=4, dpi=100)
        fra_graphs_right_lay.addWidget(self.static_canvas)

        tab_graphs_lay.addWidget(self.fra_graphs_right)

        # lay.addWidget(self.button)
        self.tab_widget.addTab(self.tab_graphs, 'Graphs')

        # Maps tab -----------------------------------------------------------------------------------------------------
        self.tab_maps = QWidget()
        tab_maps_lay = QHBoxLayout(self.tab_maps)

        # Left frame
        self.fra_maps_left = QFrame()
        self.fra_maps_left.setMaximumWidth(200)
        fra_maps_left_lay = QVBoxLayout(self.fra_maps_left)

        self.grb_maps = QGroupBox(u'Variable')
        grb_maps_lay = QVBoxLayout(self.grb_maps)

        self.rad_maps_node_demand = QRadioButton(u'Node demand')
        grb_maps_lay.addWidget(self.rad_maps_node_demand)

        self.rad_maps_node_head = QRadioButton(u'Node head')
        grb_maps_lay.addWidget(self.rad_maps_node_head)

        self.rad_maps_node_pressure = QRadioButton(u'Node pressure')
        grb_maps_lay.addWidget(self.rad_maps_node_pressure)

        self.rad_maps_node_quality = QRadioButton(u'Node quality')
        grb_maps_lay.addWidget(self.rad_maps_node_quality)

        self.rad_maps_link_flow = QRadioButton(u'Link flow')
        grb_maps_lay.addWidget(self.rad_maps_link_flow)

        self.rad_maps_link_velocity = QRadioButton(u'Link velocity')
        grb_maps_lay.addWidget(self.rad_maps_link_velocity)

        self.rad_maps_link_headloss = QRadioButton(u'Link headloss')
        grb_maps_lay.addWidget(self.rad_maps_link_headloss)

        self.rad_maps_link_quality = QRadioButton(u'Link quality')
        grb_maps_lay.addWidget(self.rad_maps_link_quality)

        fra_maps_left_lay.addWidget(self.grb_maps)
        fra_maps_left_lay.addItem(self.spacer)

        tab_maps_lay.addWidget(self.fra_maps_left)

        # Right maps frame
        self.fra_maps_right = QFrame()
        fra_maps_right_lay = QVBoxLayout(self.fra_maps_right)

        self.fra_maps_right_time = QFrame()
        fra_maps_right_time_lay = QFormLayout(self.fra_maps_right_time)

        self.lbl_map_times = QLabel(u'Period [h]:')
        self.cbo_map_times = QComboBox()
        fra_maps_right_time_lay.addRow(self.lbl_map_times, self.cbo_map_times)
        fra_maps_right_lay.addWidget(self.fra_maps_right_time)

        self.btn_draw_map = QPushButton(u'Draw map')
        self.btn_draw_map.clicked.connect(self.draw_maps)
        fra_maps_right_lay.addWidget(self.btn_draw_map)

        fra_maps_right_lay.addItem(self.spacer)

        tab_maps_lay.addWidget(self.fra_maps_right)

        self.tab_widget.addTab(self.tab_maps, 'Maps')

        # # Add to main
        fra_main_lay.addWidget(self.fra_out_file)
        fra_main_lay.addWidget(self.tab_widget)

        self.setup()
        self.initialize()
        # self.read_outputs()

        # Set size
        self.setMinimumWidth(self.tab_graphs.width())
        self.setMinimumHeight(self.tab_graphs.height())

    def setup(self):
        pass

    def btn_out_file_clicked(self):
        config_file = ConfigFile(Parameters.config_file_path)
        out_file, __ = QFileDialog.getOpenFileName(
            self,
            'Select out file',
            config_file.get_last_out_file(),
            'Out files (*.out)')

        if out_file is None or out_file == '':
            return

        config_file.set_last_out_file(out_file)
        self.txt_out_file.setText(out_file)
        self.read_outputs()
        if self.output_reader is None:
            return

        # Fill times combo
        self.cbo_map_times.clear()
        for period_s in self.output_reader.period_results.keys():

            text = self.seconds_to_string(
                period_s,
                self.output_reader.sim_duration_secs,
                self.output_reader.report_time_step_secs)
            self.cbo_map_times.addItem(text, period_s)

        # Activate widgets
        self.btn_sel_element.setEnabled(self.output_reader is not None)
        self.btn_draw_graph.setEnabled(self.output_reader is not None)
        self.grb_maps.setEnabled(self.output_reader is not None)
        self.btn_draw_map.setEnabled(self.output_reader is not None)

    def initialize(self):

        # Graphs
        self.grb_nodes.setEnabled(False)
        self.grb_links.setEnabled(False)
        self.btn_sel_element.setEnabled(self.output_reader is not None)
        self.btn_draw_graph.setEnabled(self.output_reader is not None)

        # Maps
        self.grb_maps.setEnabled(self.output_reader is not None)
        self.rad_maps_node_demand.setChecked(True)
        self.btn_draw_map.setEnabled(self.output_reader is not None)

    def feature_sel_changed(self):

        is_nodes = False
        sel_junctions = self.params.junctions_vlay.selectedFeatureCount()
        sel_reservoirs = self.params.reservoirs_vlay.selectedFeatureCount()
        sel_tanks = self.params.tanks_vlay.selectedFeatureCount()
        if sel_junctions > 0 or sel_reservoirs > 0 or sel_tanks > 0:
            is_nodes = True
        self.grb_nodes.setEnabled(is_nodes)

        is_links = False
        sel_pipes = self.params.pipes_vlay.selectedFeatureCount()
        sel_pumps = self.params.pumps_vlay.selectedFeatureCount()
        sel_valves = self.params.valves_vlay.selectedFeatureCount()
        if sel_pipes > 0 or sel_pumps > 0 or sel_valves > 0:
            is_links = True
        self.grb_links.setEnabled(is_links)

    def read_outputs(self):

        try:
            QApplication.setOverrideCursor(Qt.WaitCursor)
            self.output_reader = BinaryOutputReader()
            self.output_reader.read(self.txt_out_file.text())
            QApplication.restoreOverrideCursor()

            # Check if output compatible with loaded project
            compatible = True
            out_nodes_nr = self.output_reader.nodes_nr
            out_tanks_reservs_nr = self.output_reader.tanks_reservs_nr
            out_juncts_nr = out_nodes_nr - out_tanks_reservs_nr

            out_links_nr = self.output_reader.links_nr
            out_pumps_nr = self.output_reader.pumps_nr
            out_valves_nr = self.output_reader.valves_nr
            out_pipes_nr = out_links_nr - out_pumps_nr - out_valves_nr

            if out_juncts_nr != self.params.junctions_vlay.featureCount():
                compatible = False
            if out_tanks_reservs_nr != (self.params.reservoirs_vlay.featureCount() + self.params.tanks_vlay.featureCount()):
                compatible = False
            if out_pipes_nr != self.params.pipes_vlay.featureCount():
                compatible = False
            if out_valves_nr != self.params.valves_vlay.featureCount():
                compatible = False
            if out_pumps_nr != self.params.pumps_vlay.featureCount():
                compatible = False

            if not compatible:
                message = 'The out file appears to incompatible with the actual project layers.'
                QMessageBox.warning(
                    self,
                    Parameters.plug_in_name,
                    message,
                    QMessageBox.Ok)

                self.output_reader = None
                self.txt_out_file.setText('')

            else:
                # Message after reading completed
                message = 'Out file loaded: ' + str(out_nodes_nr) + ' nodes, ' + str(out_links_nr) + ' links found.'

                # Clear refs to output layer
                self.params.out_lay_node_demand = None
                self.params.out_lay_node_head = None
                self.params.out_lay_node_pressure = None
                self.params.out_lay_node_quality = None
                self.params.out_lay_link_flow = None
                self.params.out_lay_link_velocity = None
                self.params.out_lay_link_headloss = None
                self.params.out_lay_link_quality = None

                QMessageBox.information(
                    self,
                    Parameters.plug_in_name,
                    message,
                    QMessageBox.Ok)

        finally:
            # self.iface.messageBar().pushWarning(
            #     Parameters.plug_in_name,
            #     'Error while reading output file.')  # TODO: softcode
            # self.output_reader = None
            # self.txt_out_file.setText('')
            QApplication.restoreOverrideCursor()

    def btn_sel_element_clicked(self):

        if self.output_reader is None:
            self.iface.messageBar().pushMessage(
                Parameters.plug_in_name,
                'Please select the simulation out file.',
                Qgis.Warning,
                5)  # TODO: softcode
            return

        self.tool = SelectTool(self, self.params)
        self.iface.mapCanvas().setMapTool(self.tool)

        cursor = QCursor()
        cursor.setShape(Qt.ArrowCursor)
        self.iface.mapCanvas().setCursor(cursor)

    def draw_graphs(self):

        # Get selected features
        self.element_ids_nodes = []
        for junction_feat in self.params.junctions_vlay.selectedFeatures():
            self.element_ids_nodes.append(junction_feat.attribute(Junction.field_name_eid))
        for reservoir_feat in self.params.reservoirs_vlay.selectedFeatures():
            self.element_ids_nodes.append(reservoir_feat.attribute(Reservoir.field_name_eid))
        for tank_feat in self.params.tanks_vlay.selectedFeatures():
            self.element_ids_nodes.append(tank_feat.attribute(Tank.field_name_eid))

        self.element_ids_links = []
        for pipe_feat in self.params.pipes_vlay.selectedFeatures():
            self.element_ids_links.append(pipe_feat.attribute(Pipe.field_name_eid))
        for pump_feat in self.params.pumps_vlay.selectedFeatures():
            self.element_ids_links.append(pump_feat.attribute(Pump.field_name_eid))
        for valve_feat in self.params.valves_vlay.selectedFeatures():
            self.element_ids_links.append(valve_feat.attribute(Valve.field_name_eid))

        # Build values dictionaries
        xs = self.output_reader.report_times
        ys_d_d = {}
        params_count = 0

        # Nodes
        if self.grb_nodes.isEnabled():
            if self.chk_node_demand.isChecked():
                params_count += 1
                ys_d = {}
                for element_id in self.element_ids_nodes:
                    ys_d[element_id] = [
                        self.output_reader.node_demands_d[element_id],
                        self.params.options.flow_units]
                ys_d_d[OutputParamCodes.NODE_DEMAND] = ys_d

            if self.chk_node_head.isChecked():
                params_count += 1
                ys_d = {}
                for element_id in self.element_ids_nodes:
                    ys_d[element_id] = [
                        self.output_reader.node_heads_d[element_id],
                        Options.units_diameter_tanks[self.params.options.units]]
                ys_d_d[OutputParamCodes.NODE_HEAD] = ys_d

            if self.chk_node_pressure.isChecked():
                params_count += 1
                ys_d = {}
                for element_id in self.element_ids_nodes:
                    ys_d[element_id] = [
                        self.output_reader.node_pressures_d[element_id],
                        Options.units_pressure[self.params.options.units]]
                ys_d_d[OutputParamCodes.NODE_PRESSURE] = ys_d

            if self.chk_node_quality.isChecked():
                params_count += 1
                ys_d = {}
                for element_id in self.element_ids_nodes:
                    ys_d[element_id] = [
                        self.output_reader.node_qualities_d[element_id],
                        Quality.quality_units_text[self.params.options.quality.mass_units]]
                ys_d_d[OutputParamCodes.NODE_QUALITY] = ys_d

        # Links
        if self.grb_links.isEnabled():
            if self.chk_link_flow.isChecked():
                params_count += 1
                ys_d = {}
                for element_id in self.element_ids_links:
                    ys_d[element_id] = [
                        self.output_reader.link_flows_d[element_id],
                        self.params.options.flow_units]
                ys_d_d[OutputParamCodes.LINK_FLOW] = ys_d

            if self.chk_link_velocity.isChecked():
                params_count += 1
                ys_d = {}
                for element_id in self.element_ids_links:
                    ys_d[element_id] = [
                        self.output_reader.link_velocities_d[element_id],
                        Options.units_velocity[self.params.options.units]]
                ys_d_d[OutputParamCodes.LINK_VELOCITY] = ys_d

            if self.chk_link_headloss.isChecked():
                params_count += 1
                ys_d = {}
                for element_id in self.element_ids_links:
                    ys_d[element_id] = [
                        self.output_reader.link_headlosses_d[element_id],
                        Options.units_diameter_tanks[self.params.options.units]]
                ys_d_d[OutputParamCodes.LINK_HEADLOSS] = ys_d

            if self.chk_link_quality.isChecked():
                params_count += 1
                ys_d = {}
                for element_id in self.element_ids_links:
                    ys_d[element_id] = [
                        self.output_reader.link_qualities_d[element_id],
                        Quality.quality_units_text[self.params.options.quality.mass_units]]
                ys_d_d[OutputParamCodes.LINK_QUALITY] = ys_d

        if ys_d_d:
            self.static_canvas.draw_output_line(xs, ys_d_d, params_count)

    def draw_maps(self):
        """
        Draws layers with all the attributes
        :return:
        """

        report_time = self.cbo_map_times.itemText(self.cbo_map_times.currentIndex())

        if self.rad_maps_node_demand.isChecked():  # -------------------------------------------------------------------
            lay_name = u'Node demand'
            lay_id = self.draw_map(LayerType.NODE, self.params.out_lay_node_demand_id, lay_name,
                                   self.output_reader.node_demands_d, report_time)
            self.params.out_lay_node_demand_id = lay_id

        elif self.rad_maps_node_head.isChecked():
            lay_name = u'Node head'
            lay_id = self.draw_map(LayerType.NODE, self.params.out_lay_node_head_id, lay_name,
                                   self.output_reader.node_heads_d, report_time)
            self.params.out_lay_node_head_id = lay_id

        elif self.rad_maps_node_pressure.isChecked():
            lay_name = u'Node pressure'
            lay_id = self.draw_map(LayerType.NODE, self.params.out_lay_node_pressure_id, lay_name,
                                   self.output_reader.node_pressures_d, report_time)
            self.params.out_lay_node_pressure_id = lay_id

        elif self.rad_maps_node_quality.isChecked():
            lay_name = u'Node quality'
            lay_id = self.draw_map(LayerType.NODE, self.params.out_lay_node_quality_id, lay_name,
                                   self.output_reader.node_qualities_d, report_time)
            self.params.out_lay_node_quality_id = lay_id

        elif self.rad_maps_link_flow.isChecked():  # -------------------------------------------------------------------
            lay_name = u'Link flow'
            lay_id = self.draw_map(LayerType.LINK, self.params.out_lay_link_flow_id, lay_name,
                                   self.output_reader.link_flows_d, report_time)
            self.params.out_lay_link_flow_id = lay_id

        elif self.rad_maps_link_velocity.isChecked():
            lay_name = u'Link velocity'
            lay_id = self.draw_map(LayerType.LINK, self.params.out_lay_link_velocity_id, lay_name,
                                   self.output_reader.link_velocities_d, report_time)
            self.params.out_lay_link_velocity_id = lay_id

        elif self.rad_maps_link_headloss.isChecked():
            lay_name = u'Link headloss'
            lay_id = self.draw_map(LayerType.LINK, self.params.out_lay_link_headloss_id, lay_name,
                                   self.output_reader.link_headlosses_d, report_time)
            self.params.out_lay_link_headloss_id = lay_id

        elif self.rad_maps_link_quality.isChecked():
            lay_name = u'Link quality'
            lay_id = self.draw_map(LayerType.LINK, self.params.out_lay_link_quality_id, lay_name,
                                   self.output_reader.link_qualities_d, report_time)
            self.params.out_lay_link_quality_id = lay_id

    def draw_map(self, lay_type, lay_id, lay_name, dataset, report_time):

        try:
            QApplication.setOverrideCursor(Qt.WaitCursor)

            lay_name += ' ' + report_time

            lay = LayerUtils.get_lay_from_id(lay_id)
            if lay is None:
                if lay_type == LayerType.NODE:
                    lay = self.create_out_node_layer(lay_name, dataset)
                    ns = NodeSymbology()
                    lay.setRenderer(ns.make_graduated_sym_renderer(lay, report_time))
                elif lay_type == LayerType.LINK:
                    lay = self.create_out_link_layer(lay_name, dataset)
                    ls = LinkSymbology()
                    lay.setRenderer(ls.make_flow_sym_renderer(lay, report_time))
                lay_id = lay.id()
                QgsProject.instance().addMapLayer(lay)
                self.params.out_layers.append(lay)
            else:
                lay.setLayerName(lay_name)

            lay.triggerRepaint()
            QApplication.restoreOverrideCursor()

        finally:
            QApplication.restoreOverrideCursor()

        return lay_id

    def btn_cancel_clicked(self):
        self.setVisible(False)

    def btn_ok_clicked(self):
        pass

    def create_out_node_layer(self, lay_name, values_d):
        return self.create_out_layer(lay_name, values_d, LayerType.NODE)

    def create_out_link_layer(self, lay_name, values_d):
        return self.create_out_layer(lay_name, values_d, LayerType.LINK)

    def create_out_layer(self, lay_name, values_d, lay_type):

        field_name_vars = []
        periods = list(self.output_reader.period_results.keys())
        for period_s in periods:
            text = self.seconds_to_string(
                period_s,
                self.output_reader.sim_duration_secs,
                self.output_reader.report_time_step_secs)
            field_name_vars.append(text)

        if lay_type == LayerType.NODE:
            new_lay = MemoryDS.create_nodes_lay(self.params, field_name_vars, lay_name, self.params.crs)
        elif lay_type == LayerType.LINK:
            new_lay = MemoryDS.create_links_lay(self.params, field_name_vars, lay_name, self.params.crs)

        with edit(new_lay):

            # Update attributes
            for feat in new_lay.getFeatures():
                fid = feat.id()
                eid = feat.attribute(Node.field_name_eid)
                values = values_d[eid]
                for p in range(len(periods)):
                    new_lay.changeAttributeValue(fid, p+1, values[p])

        return new_lay

    def seconds_to_string(self, period_s, duration_s, interval_s):

        day = int(math.floor(period_s / 86400))
        hour = period_s / 3600 - day * 24
        minute = period_s / 60 - day * 24 * 60 - hour * 60
        second = period_s - day * 86400 - hour * 3600 - minute * 60

        text = ''
        if duration_s >= 86400:
            # We need days
            text += str(day) + 'd'

        if duration_s >= 3600:
            # We need hours
            text += '{:02}'.format(hour) + 'H'

        text += '{:02}'.format(minute) + 'm'

        if second > 0:
            text += '{:02}'.format(second) + 's'

        return text