• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

Open-MSS / MSS / 11293650698

11 Oct 2024 01:54PM UTC coverage: 70.727% (-0.1%) from 70.845%
11293650698

Pull #2561

github

web-flow
Merge 8ee9014c0 into 3f5f54616
Pull Request #2561: replace sys.exit by raise SystemExit and catch it

6 of 32 new or added lines in 2 files covered. (18.75%)

102 existing lines in 2 files now uncovered.

14238 of 20131 relevant lines covered (70.73%)

0.71 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

20.63
/mslib/utils/mssautoplot.py
1
"""
2

3
    mslib.utils.mssautoplot
4
    ~~~~~~~~~~~~~~~~~~~~~~~
5

6
    A CLI tool to create for instance a number of the same plots
7
    for several flights or several forecast steps
8

9
    This file is part of MSS.
10

11
    :copyright: Copyright 2022 Sreelakshmi Jayarajan
12
    :copyright: Copyright 2022-2024 by the MSS team, see AUTHORS.
13
    :license: APACHE-2.0, see LICENSE for details.
14

15
    Licensed under the Apache License, Version 2.0 (the "License");
16
    you may not use this file except in compliance with the License.
17
    You may obtain a copy of the License at
18

19
       http://www.apache.org/licenses/LICENSE-2.0
20

21
    Unless required by applicable law or agreed to in writing, software
22
    distributed under the License is distributed on an "AS IS" BASIS,
23
    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
24
    See the License for the specific language governing permissions and
25
    limitations under the License.
26
"""
27

28
import os
1✔
29
import sys
1✔
30
import io
1✔
31
import re
1✔
32
import json
1✔
33
import logging
1✔
34
from datetime import datetime, timedelta
1✔
35
from urllib.parse import urljoin
1✔
36

37
import requests
1✔
38
from PyQt5.QtCore import Qt
1✔
39
from PyQt5.QtWidgets import QMessageBox, QProgressDialog
1✔
40
import click
1✔
41
import defusedxml.ElementTree as etree
1✔
42
import PIL.Image
1✔
43
import matplotlib
1✔
44
from fs import open_fs
1✔
45

46
import mslib
1✔
47
import mslib.utils
1✔
48
import mslib.msui
1✔
49
import mslib.msui.mpl_map
1✔
50
import mslib.utils.auth
1✔
51
import mslib.utils.qt
1✔
52
import mslib.utils.thermolib
1✔
53
from mslib.utils.config import config_loader, read_config_file
1✔
54
from mslib.utils.units import units
1✔
55
from mslib.msui.wms_control import MSUIWebMapService
1✔
56
from mslib.msui import constants
1✔
57
from mslib.msui import mpl_qtwidget as qt
1✔
58
from mslib.msui import mpl_pathinteractor as mpath
1✔
59
from mslib.msui import flighttrack as ft
1✔
60
from mslib.utils import config as conf
1✔
61
from mslib.utils.auth import get_auth_from_url_and_name
1✔
62
from mslib.utils.loggerdef import configure_mpl_logger
1✔
63
from mslib.utils.verify_user_token import verify_user_token
1✔
64

65

66
TEXT_CONFIG = {
1✔
67
    "bbox": dict(boxstyle="round", facecolor="white", alpha=0.5, edgecolor="none"), "fontweight": "bold",
68
    "zorder": 4, "fontsize": 6, "clip_on": True}
69

70
mpl_logger = configure_mpl_logger()
1✔
71

72

73
def load_from_ftml(filename):
1✔
74
    """Load a flight track from an XML file at <filename>.
75
    """
76
    _dirname, _name = os.path.split(filename)
1✔
77
    _fs = open_fs(_dirname)
1✔
78
    datasource = _fs.readtext(_name)
1✔
79
    wp_list = ft.load_from_xml_data(datasource)
1✔
80
    now = datetime.now()
1✔
81
    for wp in wp_list:
1✔
82
        wp.utc_time = now
1✔
83
    data_list = [
1✔
84
        (wp.lat, wp.lon, wp.flightlevel, wp.location, wp.comments) for wp in wp_list]
85
    return data_list, wp_list
1✔
86

87

88
def load_from_operation(op_name, msc_url, msc_auth_password, username, password):
1✔
89
    """
90
    Method to load data from an operation in MSColab.
91

92
    Parameters:
93
    :op_name: Name of the operation to load data from
94
    :msc_url: URL of the MS Colab server
95
    :msc_auth_password: Password for MS Colab authentication
96
    :username: Username for authentication
97
    :password: Password for authentication
98

99
    Returns:
100
    Tuple containing a list of data points and a list of Waypoints if successful, None otherwise
101
    """
UNCOV
102
    data = {
×
103
        "email": username,
104
        "password": password
105
    }
106
    session = requests.Session()
×
107
    msc_auth = ("mscolab", msc_auth_password)
×
108
    session.auth = msc_auth
×
UNCOV
109
    session.headers.update({'x-test': 'true'})
×
110
    # ToDp fix config_loader it gets a list of two times the entry
111
    response = session.get(urljoin(msc_url, 'status'), timeout=tuple(config_loader(dataset="MSCOLAB_timeout")[0]))
×
112
    session.close()
×
113
    if response.status_code == 401:
×
114
        logging.error("Error", 'Server authentication data were incorrect.')
×
115
    elif response.status_code == 200:
×
116
        session = requests.Session()
×
117
        session.auth = msc_auth
×
118
        session.headers.update({'x-test': 'true'})
×
119
        url = urljoin(msc_url, "token")
×
UNCOV
120
        try:
×
121
            # ToDp fix config_loader it gets a list of two times the entry
122
            response = session.post(url, data=data, timeout=tuple(config_loader(dataset="MSCOLAB_timeout")[0]))
×
123
            response.raise_for_status()
×
124
        except requests.exceptions.RequestException as ex:
×
125
            logging.error("unexpected error: %s %s %s", type(ex), url, ex)
×
126
            return
×
127
        if response.text != "False":
×
128
            _json = json.loads(response.text)
×
129
            token = _json["token"]
×
130
            msc_url = url
×
131
            op_id = get_op_id(msc_url=msc_url, token=token, op_name=op_name)
×
132
            xml_data = get_xml_data(msc_url=msc_url, token=token, op_id=op_id)
×
133
            wp_list = ft.load_from_xml_data(xml_data)
×
134
            now = datetime.now()
×
135
            for wp in wp_list:
×
136
                wp.utc_time = now
×
UNCOV
137
            data_list = [
×
138
                (wp.lat, wp.lon, wp.flightlevel, wp.location, wp.comments) for wp in wp_list]
UNCOV
139
            return data_list, wp_list
×
140

141

142
def get_xml_data(msc_url, token, op_id):
1✔
143
    """
144

145
    Parameters:
146
        :msc_url: The URL of the MSColab Server
147
        :token: The user's token for authentication
148
        :op_id: The id of the operation to retrieve
149

150
    Returns:
151
        str: The content of the XML data retrieved from the server
152

153
    """
154
    if verify_user_token(msc_url, token):
×
UNCOV
155
        data = {
×
156
            "token": token,
157
            "op_id": op_id
158
        }
159
        url = urljoin(msc_url, "get_operation_by_id")
×
160
        r = requests.get(url, data=data)
×
161
        if r.text != "False":
×
162
            xml_content = json.loads(r.text)["content"]
×
UNCOV
163
            return xml_content
×
164

165

166
def get_op_id(msc_url, token, op_name):
1✔
167
    """
168
    gets the operation id of the given operation name
169

170
    Parameters:
171
        :msc_url: The URL of the MSColab server
172
        :token: The user token for authentication
173
        :op_name:: The name of the operation to retrieve op_id for
174

175
    Returns:
176
        :op_id: The op_id of the operation with the specified name
177
    """
178
    logging.debug('get_recent_op_id')
×
179
    if verify_user_token(msc_url, token):
×
UNCOV
180
        """
×
181
        get most recent operation's op_id
182
        """
183
        skip_archived = config_loader(dataset="MSCOLAB_skip_archived_operations")
×
UNCOV
184
        data = {
×
185
            "token": token,
186
            "skip_archived": skip_archived
187
        }
188
        url = urljoin(msc_url, "operations")
×
189
        r = requests.get(url, data=data)
×
190
        if r.text != "False":
×
191
            _json = json.loads(r.text)
×
192
            operations = _json["operations"]
×
193
            for op in operations:
×
194
                if op["path"] == op_name:
×
UNCOV
195
                    return op["op_id"]
×
196

197

198
class Plotting:
1✔
199
    def __init__(self, cpath, msc_url=None, msc_auth_password=None, username=None, password=None, pdlg=None):
1✔
200
        """
201
        Initialize the Plotting object with the provided parameters.
202

203
        Parameters:
204
        :cpath: Path to the configuration file
205
        :msc_url: URL for MSColab service
206
        :msc_auth_password: Authentication password for MSColab service
207
        :username: User's username
208
        :password: User's password
209
        """
NEW
210
        read_config_file(cpath)
×
211
        self.pdlg = pdlg
×
212
        self.config = config_loader()
×
213
        self.num_interpolation_points = self.config["num_interpolation_points"]
×
214
        self.num_labels = self.config["num_labels"]
×
215
        self.tick_index_step = self.num_interpolation_points // self.num_labels
×
216
        self.bbox = None
×
217
        flight = self.config["automated_plotting_flights"][0][0]
×
218
        section = self.config["automated_plotting_flights"][0][1]
×
219
        filename = self.config["automated_plotting_flights"][0][3]
×
220
        if self.__class__.__name__ == "TopViewPlotting":
×
221
            try:
×
UNCOV
222
                self.params = mslib.utils.coordinate.get_projection_params(
×
223
                    self.config["predefined_map_sections"][section]["CRS"].lower())
224
            except KeyError as e:
×
NEW
225
                print(e)
×
226
                raise SystemExit("Invalid SECTION and/or CRS")
×
227
            self.params["basemap"].update(self.config["predefined_map_sections"][section]["map"])
×
228
            self.bbox_units = self.params["bbox"]
×
229
        if filename != "" and filename == flight:
×
230
            self.read_operation(flight, msc_url, msc_auth_password, username, password)
×
NEW
231
        elif filename != "":
×
232
            # Todo add the dir to the file in the mssautoplot.json
NEW
233
            dirpath = "./"
×
NEW
234
            file_path = os.path.join(dirpath, filename)
×
NEW
235
            exists = os.path.exists(file_path)
×
NEW
236
            if not exists:
×
NEW
237
                print("Filename {} doesn't exist".format(filename))
×
NEW
238
                self.pdlg.close()
×
UNCOV
239
                raise SystemExit("Filename {} doesn't exist".format(filename))
×
UNCOV
240
            self.read_ftml(filename)
×
241

242
    def read_ftml(self, filename):
1✔
243
        self.wps, self.wp_model_data = load_from_ftml(filename)
×
244
        self.wp_lats, self.wp_lons, self.wp_locs = [[x[i] for x in self.wps] for i in [0, 1, 3]]
×
245
        self.wp_press = [mslib.utils.thermolib.flightlevel2pressure(wp[2] * units.hft).to("Pa").m for wp in self.wps]
×
246
        self.path = [(wp[0], wp[1], datetime.now()) for wp in self.wps]
×
247
        self.vertices = [list(a) for a in (zip(self.wp_lons, self.wp_lats))]
×
UNCOV
248
        self.lats, self.lons = mslib.utils.coordinate.path_points([_x[0] for _x in self.path],
×
249
                                                                  [_x[1] for _x in self.path],
250
                                                                  numpoints=self.num_interpolation_points + 1,
251
                                                                  connection="greatcircle")
252

253
    def read_operation(self, op_name, msc_url, msc_auth_password, username, password):
1✔
UNCOV
254
        self.wps, self.wp_model_data = load_from_operation(op_name, msc_url=msc_url,
×
255
                                                           msc_auth_password=msc_auth_password, username=username,
256
                                                           password=password)
257
        self.wp_lats, self.wp_lons, self.wp_locs = [[x[i] for x in self.wps] for i in [0, 1, 3]]
×
258
        self.wp_press = [mslib.utils.thermolib.flightlevel2pressure(wp[2] * units.hft).to("Pa").m for wp in self.wps]
×
259
        self.path = [(wp[0], wp[1], datetime.now()) for wp in self.wps]
×
260
        self.vertices = [list(a) for a in (zip(self.wp_lons, self.wp_lats))]
×
UNCOV
261
        self.lats, self.lons = mslib.utils.coordinate.path_points([_x[0] for _x in self.path],
×
262
                                                                  [_x[1] for _x in self.path],
263
                                                                  numpoints=self.num_interpolation_points + 1,
264
                                                                  connection="greatcircle")
265

266

267
class TopViewPlotting(Plotting):
1✔
268
    def __init__(self, cpath, msc_url, msc_auth_password, msc_username, msc_password, pdlg):
1✔
NEW
269
        super(TopViewPlotting, self).__init__(cpath, msc_url, msc_auth_password, msc_username, msc_password, pdlg)
×
270
        self.pdlg= pdlg
×
271
        self.myfig = qt.TopViewPlotter()
×
272
        self.myfig.fig.canvas.draw()
×
273
        self.fig, self.ax = self.myfig.fig, self.myfig.ax
×
274
        matplotlib.backends.backend_agg.FigureCanvasAgg(self.fig)
×
275
        self.myfig.init_map(**(self.params["basemap"]))
×
276
        self.plotter = mpath.PathH_Plotter(self.myfig.map)
×
277
        self.username = msc_username
×
278
        self.password = msc_password
×
279
        self.msc_auth = msc_auth_password
×
UNCOV
280
        self.url = msc_url
×
281

282
    def update_path(self, filename=None):
1✔
283
        """
284
        Update the path by reading the FTML data from the given filename
285
         and redrawing the path based on the updated waypoints model data.
286

287
        Parameters:
288
        :filename: The name of the file to read FTML data from.
289

290
        Returns:
291
        None
292
        """
293
        # plot path and label
294
        if filename != "":
×
295
            self.read_ftml(filename)
×
296
        self.fig.canvas.draw()
×
297
        self.plotter.update_from_waypoints(self.wp_model_data)
×
UNCOV
298
        self.plotter.redraw_path(waypoints_model_data=self.wp_model_data)
×
299

300
    def update_path_ops(self, filename=None):
1✔
301
        # plot path and label
302
        if filename != "":
×
303
            self.read_operation(filename, self.url, self.msc_auth, self.username, self.password)
×
304
        self.fig.canvas.draw()
×
305
        self.plotter.update_from_waypoints(self.wp_model_data)
×
UNCOV
306
        self.plotter.redraw_path(waypoints_model_data=self.wp_model_data)
×
307

308
    def draw(self, flight, section, vertical, filename, init_time, time, url, layer, style, elevation, no_of_plots):
1✔
309
        if filename != "" and filename == flight:
×
310
            self.update_path_ops(filename)
×
311
        elif filename != "":
×
UNCOV
312
            self.update_path(filename)
×
313

314
        width, height = self.myfig.get_plot_size_in_px()
×
315
        self.bbox = self.params['basemap']
×
316
        if not init_time:
×
UNCOV
317
            init_time = None
×
318

UNCOV
319
        kwargs = {"layers": [layer],
×
320
                  "styles": [style],
321
                  "time": time,
322
                  "init_time": init_time,
323
                  "exceptions": 'application/vnd.ogc.se_xml',
324
                  "level": elevation,
325
                  "srs": self.config["predefined_map_sections"][section]["CRS"],
326
                  "bbox": (self.bbox['llcrnrlon'], self.bbox['llcrnrlat'],
327
                           self.bbox['urcrnrlon'], self.bbox['urcrnrlat']
328
                          ),
329
                  "format": "image/png",
330
                  "size": (width, height)
331
                }
332

333
        auth_username, auth_password = get_auth_from_url_and_name(url, self.config["MSS_auth"])
×
UNCOV
334
        wms = MSUIWebMapService(url,
×
335
                                username=auth_username,
336
                                password=auth_password,
337
                                version='1.3.0')
338

339
        img = wms.getmap(**kwargs)
×
340
        image_io = io.BytesIO(img.read())
×
341
        img = PIL.Image.open(image_io)
×
342
        self.myfig.draw_image(img)
×
343
        t = str(time)
×
344
        date_time = re.sub(r'\W+', '', t)
×
UNCOV
345
        self.myfig.fig.savefig(f"{flight}_{layer}_{section}_{date_time}_{no_of_plots}_{elevation}.png")
×
346

347

348
class SideViewPlotting(Plotting):
1✔
349
    def __init__(self, cpath, msc_url, msc_auth_password, msc_username, msc_password, pdlg):
1✔
350
        # ToDo Implement access to MSColab
NEW
351
        super(SideViewPlotting, self).__init__(cpath, pdlg)
×
352
        self.pdlg = pdlg
×
353
        self.myfig = qt.SideViewPlotter()
×
354
        self.ax = self.myfig.ax
×
355
        self.fig = self.myfig.fig
×
356
        self.tick_index_step = self.num_interpolation_points // self.num_labels
×
357
        self.fig.canvas.draw()
×
358
        matplotlib.backends.backend_agg.FigureCanvasAgg(self.myfig.fig)
×
UNCOV
359
        self.plotter = mpath.PathV_Plotter(self.myfig.ax)
×
360

361
    def setup(self):
1✔
362
        self.intermediate_indexes = []
×
363
        ipoint = 0
×
364
        for i, (lat, lon) in enumerate(zip(self.lats, self.lons)):
×
365
            if abs(lat - self.wps[ipoint][0]) < 1E-10 and abs(lon - self.wps[ipoint][1]) < 1E-10:
×
366
                self.intermediate_indexes.append(i)
×
367
                ipoint += 1
×
368
            if ipoint >= len(self.wps):
×
369
                break
×
370
        self.myfig.setup_side_view()
×
371
        times = None
×
372
        times_visible = False
×
UNCOV
373
        self.myfig.redraw_xaxis(self.lats, self.lons, times, times_visible)
×
374

375
    def update_path(self, filename=None):
1✔
376
        self.setup()
×
377
        if filename is not None:
×
378
            self.read_ftml(filename)
×
379
        self.fig.canvas.draw()
×
380
        self.plotter.update_from_waypoints(self.wp_model_data)
×
381
        indices = list(zip(self.intermediate_indexes, self.wp_press))
×
UNCOV
382
        self.plotter.redraw_path(vertices=indices,
×
383
                                 waypoints_model_data=self.wp_model_data)
384
        highlight = [[wp[0], wp[1]] for wp in self.wps]
×
UNCOV
385
        self.myfig.draw_vertical_lines(highlight, self.lats, self.lons)
×
386

387
    def draw(self, flight, section, vertical, filename, init_time, time, url, layer, style, elevation, no_of_plots):
1✔
388
        try:
×
389
            self.update_path(filename)
×
390
        except AttributeError as e:
×
NEW
391
            logging.debug(e)
×
392
            raise SystemExit("No FLIGHT Selected")
×
393
        width, height = self.myfig.get_plot_size_in_px()
×
394
        p_bot, p_top = [float(x) * 100 for x in vertical.split(",")]
×
UNCOV
395
        self.bbox = tuple([x for x in (self.num_interpolation_points,
×
396
                          p_bot / 100, self.num_labels, p_top / 100)]
397
                         )
398

399
        if not init_time:
×
UNCOV
400
            init_time = None
×
401

UNCOV
402
        kwargs = {"layers": [layer],
×
403
                  "styles": [style],
404
                  "time": time,
405
                  "init_time": init_time,
406
                  "exceptions": 'application/vnd.ogc.se_xml',
407
                  "srs": "VERT:LOGP",
408
                  "path_str": ",".join(f"{wp[0]:.2f},{wp[1]:.2f}" for wp in self.wps),
409
                  "bbox": self.bbox,
410
                  "format": "image/png",
411
                  "size": (width, height)
412
                }
413
        auth_username, auth_password = get_auth_from_url_and_name(url, self.config["MSS_auth"])
×
UNCOV
414
        wms = MSUIWebMapService(url,
×
415
                                username=auth_username,
416
                                password=auth_password,
417
                                version='1.3.0')
418

UNCOV
419
        img = wms.getmap(**kwargs)
×
420

421
        image_io = io.BytesIO(img.read())
×
422
        img = PIL.Image.open(image_io)
×
423
        self.myfig.draw_image(img)
×
UNCOV
424
        self.myfig.fig.savefig(f"{flight}_{layer}_{no_of_plots}.png", bbox_inches='tight')
×
425

426

427
class LinearViewPlotting(Plotting):
1✔
428
    # ToDo Implement access of MSColab
429
    def __init__(self, cpath):
1✔
430
        super(LinearViewPlotting, self).__init__(cpath)
×
431
        self.myfig = qt.LinearViewPlotter()
×
432
        self.ax = self.myfig.ax
×
433
        matplotlib.backends.backend_agg.FigureCanvasAgg(self.myfig.fig)
×
UNCOV
434
        self.fig = self.myfig.fig
×
435

436
    def setup(self):
1✔
437
        self.bbox = (self.num_interpolation_points,)
×
438
        linearview_size_settings = config_loader(dataset="linearview")
×
UNCOV
439
        settings_dict = {"plot_title_size": linearview_size_settings["plot_title_size"],
×
440
                         "axes_label_size": linearview_size_settings["axes_label_size"]}
441
        self.myfig.set_settings(settings_dict)
×
UNCOV
442
        self.myfig.setup_linear_view()
×
443

444
    def draw(self):
1✔
445
        for flight, section, vertical, filename, init_time, time in self.config["automated_plotting_flights"]:
×
446
            for url, layer, style in self.config["automated_plotting_lsecs"]:
×
UNCOV
447
                width, height = self.myfig.get_plot_size_in_px()
×
448

449
                if not init_time:
×
UNCOV
450
                    init_time = None
×
451

452
                auth_username, auth_password = get_auth_from_url_and_name(url, self.config["MSS_auth"])
×
UNCOV
453
                wms = MSUIWebMapService(url,
×
454
                                        username=auth_username,
455
                                        password=auth_password,
456
                                        version='1.3.0')
457

458
                path_string = ""
×
459
                for i, wp in enumerate(self.wps):
×
460
                    path_string += f"{wp[0]:.2f},{wp[1]:.2f},{self.wp_press[i]},"
×
UNCOV
461
                path_string = path_string[:-1]
×
462

463
                # retrieve and draw image
UNCOV
464
                kwargs = {"layers": [layer],
×
465
                          "styles": [style],
466
                          "time": time,
467
                          "init_time": init_time,
468
                          "exceptions": 'application/vnd.ogc.se_xml',
469
                          "srs": "LINE:1",
470
                          "path_str": path_string,
471
                          "bbox": self.bbox,
472
                          "format": "text/xml",
473
                          "size": (width, height)
474
                         }
475

UNCOV
476
                xmls = wms.getmap(**kwargs)
×
477

478
                if not isinstance(xmls, list):
×
UNCOV
479
                    xmls = [xmls]
×
480

481
                xml_objects = []
×
482
                for xml_ in xmls:
×
483
                    xml_data = etree.fromstring(xml_.read())
×
UNCOV
484
                    xml_objects.append(xml_data)
×
485

486
                self.myfig.draw_image(xml_objects, colors=None, scales=None)
×
487
                self.myfig.redraw_xaxis(self.lats, self.lons)
×
488
                highlight = [[wp[0], wp[1]] for wp in self.wps]
×
489
                self.myfig.draw_vertical_lines(highlight, self.lats, self.lons)
×
UNCOV
490
                self.myfig.fig.savefig(f"{flight}_{layer}.png", bbox_inches='tight')
×
491

492

493
@click.command()
1✔
494
@click.option('--cpath', default=constants.MSS_AUTOPLOT, help='Path of the configuration file.')
1✔
495
@click.option('--view', default="top", help='View of the plot (top/side/linear).')
1✔
496
@click.option('--ftrack', default="", help='Flight track.')
1✔
497
@click.option('--itime', default="", help='Initial time.')
1✔
498
@click.option('--vtime', default="", help='Valid time.')
1✔
499
@click.option('--intv', default=0, help='Time interval.')
1✔
500
@click.option('--stime', default="", help='Starting time for downloading multiple plots with a fixed interval.')
1✔
501
@click.option('--etime', default="", help='Ending time for downloading multiple plots with a fixed interval.')
1✔
502
@click.pass_context
1✔
503
def main(ctx, cpath, view, ftrack, itime, vtime, intv, stime, etime):
1✔
NEW
504
    def close_process_dialog(pdlg):
×
NEW
505
        pdlg.close()
×
506

NEW
507
    if ctx.obj is not None:
×
508
        # ToDo find a simpler solution, on a splitted package QT is expensive for such a progressbar
509
        pdlg = QProgressDialog("Downloading images", "Cancel", 0, 10, parent=ctx.obj)
×
510
        pdlg.setMinimumDuration(0)
×
511
        pdlg.repaint()
×
512
        pdlg.canceled.connect(lambda: close_process_dialog(pdlg))
×
513
        pdlg.setWindowModality(Qt.WindowModal)
×
514
        pdlg.setAutoReset(True)     # Close dialog automatically when reaching max value
×
515
        pdlg.setAutoClose(True)     # Automatically close when value reaches maximum
×
UNCOV
516
        pdlg.setValue(0)            # Initial progress value
×
517

518
        # Set window flags to ensure visibility and modality
UNCOV
519
        pdlg.setWindowFlags(pdlg.windowFlags() | Qt.CustomizeWindowHint | Qt.WindowTitleHint)
×
520

UNCOV
521
        pdlg.setValue(0)
×
522

523
    conf.read_config_file(path=cpath)
×
UNCOV
524
    config = conf.config_loader()
×
525

526
    # flight_name = config["automated_plotting_flights"][0][0]
527
    # file = config["automated_plotting_flights"][0][3]
528
    if ctx.obj is not None:
×
UNCOV
529
        pdlg.setValue(1)
×
530

531
    msc_url = config["mscolab_server_url"]
×
UNCOV
532
    msc_auth_password = mslib.utils.auth.get_password_from_keyring(service_name=f"MSCOLAB_AUTH_{msc_url}",
×
533
                                                                   username="mscolab")
534
    msc_username = config["MSS_auth"][msc_url]
×
UNCOV
535
    msc_password = mslib.utils.auth.get_password_from_keyring(service_name="MSCOLAB", username=msc_username)
×
536

537
    # Choose view (top or side)
NEW
538
    if view == "top":
×
539
        top_view = TopViewPlotting(cpath, msc_url, msc_auth_password, msc_username, msc_password, pdlg)
×
UNCOV
540
        sec = "automated_plotting_hsecs"
×
541
    else:
542
        side_view = SideViewPlotting(cpath, msc_url, msc_auth_password, msc_username, msc_password, pdlg)
×
543
        sec = "automated_plotting_vsecs"
×
544
    if ctx.obj is not None:
×
UNCOV
545
        pdlg.setValue(2)
×
546

547

548
    def draw(no_of_plots):
×
549
        try:
×
UNCOV
550
            if view == "top":
×
551
                top_view.draw(flight, section, vertical, filename, init_time, time,
×
552
                              url, layer, style, elevation, no_of_plots)
UNCOV
553
            elif view == "side":
×
554
                side_view.draw(flight, section, vertical, filename, init_time, time,
×
555
                               url, layer, style, elevation, no_of_plots=no_of_plots)
556
        except Exception as e:
×
557
            if "times" in str(e):
×
558
                print("Invalid times and/or levels requested")
×
559
            elif "LAYER" in str(e):
×
560
                print(f"Invalid LAYER '{layer}' requested")
×
UNCOV
561
            elif "404 Client Error" in str(e) or "NOT FOUND for url" in str(e):
×
562
                print("Invalid STYLE and/or URL requested")
×
563
            else:
564
                print(str(e))
×
565
        else:
566
            print("Plot downloaded!")
×
567
            return True
×
568
        return False
×
569
    if ctx.obj is not None:
×
570
        pdlg.setValue(4)
×
571
    flag = False
×
572
    for flight, section, vertical, filename, init_time, time in config["automated_plotting_flights"]:
×
NEW
573
        if ctx.obj is not None:
×
574
            pdlg.setValue(8)
×
575
        # where does sec comes from?
576
        for url, layer, style, elevation in config[sec]:
×
577
            if vtime == "" and stime == "":
×
578
                no_of_plots = 1
×
579
                flag = draw(no_of_plots)
×
580
            elif intv == 0:
×
581
                if itime != "":
×
582
                    init_time = datetime.strptime(itime, "%Y-%m-%dT%H:%M:%S")
×
583
                time = datetime.strptime(vtime, "%Y-%m-%dT%H:%M:%S")
×
584
                if ftrack != "":
×
585
                    flight = ftrack
×
586
                no_of_plots = 1
×
587
                flag = draw(no_of_plots)
×
588
            elif intv > 0:
×
589
                if itime != "":
×
590
                    init_time = datetime.strptime(itime, "%Y-%m-%dT%H:%M:%S")
×
591
                starttime = datetime.strptime(stime, "%Y-%m-%dT%H:%M:%S")
×
592
                endtime = datetime.strptime(etime, "%Y-%m-%dT%H:%M:%S")
×
593
                i = 1
×
594
                time = starttime
×
595
                while time <= endtime:
×
596
                    logging.debug(time)
×
597
                    if ftrack != "":
×
598
                        flight = ftrack
×
599
                    no_of_plots = i
×
600
                    flag = draw(no_of_plots)
×
UNCOV
601
                    time = time + timedelta(hours=intv)
×
602
                    i += 1
×
603
            else:
604
                raise Exception("Invalid interval")
×
605
    if ctx.obj is not None:
×
606
        pdlg.setValue(10)
×
607
        pdlg.close()
×
UNCOV
608
        if flag:
×
UNCOV
609
            QMessageBox.information(
×
610
                ctx.obj,  # The parent widget (use `None` if no parent)
611
                "SUCCESS",  # Title of the message box
612
                "Plots downloaded successfully."  # Message text
613
            )
614
        else:
UNCOV
615
            QMessageBox.information(
×
616
                ctx.obj,  # The parent widget (use `None` if no parent)
617
                "FAILURE",  # Title of the message box
618
                "Plots couldnot be downloaded."  # Message text
619
            )
620

621

622
if __name__ == '__main__':
623
    main()
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc