1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
|
# Copyright (C) 2023 The Qt Company Ltd.
# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
from __future__ import annotations
import sys
from pathlib import Path
from PySide6.QtCore import QFile, QIODevice, QObject, QRangeModel
from PySide6.QtGraphs import (QBar3DSeries, QCategory3DAxis, QValue3DAxis, QItemModelBarDataProxy)
MONTHS = ["January", "February", "March", "April",
"May", "June", "July", "August", "September", "October",
"November", "December"]
def read_data(file_path):
"""Return a tuple of data matrix/first year."""
dataFile = QFile(file_path)
if not dataFile.open(QIODevice.OpenModeFlag.ReadOnly | QIODevice.OpenModeFlag.Text):
print("Unable to open data file:", dataFile.fileName(), file=sys.stderr)
return None, None
last_year = -1
first_year = -1
result = []
data = dataFile.readAll().data().decode("utf8")
for line in data.split("\n"):
if line and not line.startswith("#"): # Ignore comments
tokens = line.split(",")
# Each line has three data items: Year, month, and
# rainfall value
if len(tokens) >= 3:
# Store year and month as strings, and rainfall value
# as double into a variant data item and add the item to
# the item list.
year = int(tokens[0].strip())
month = int(tokens[1].strip())
value = float(tokens[2].strip())
if year != last_year:
if first_year == -1:
first_year = last_year
result.append([0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0])
last_year = year
yearly_values = result[len(result) - 1]
yearly_values[month - 1] = value
return result, first_year
class RainfallData(QObject):
def __init__(self):
super().__init__()
self._columnCount = 0
self._rowCount = 0
self._years = []
self._numericMonths = []
self._mapping = None
self._series = QBar3DSeries()
self._valueAxis = QValue3DAxis()
self._rowAxis = QCategory3DAxis()
self._colAxis = QCategory3DAxis()
# In data file the months are in numeric format, so create custom list
for i in range(1, 13):
self._numericMonths.append(str(i))
self._columnCount = len(self._numericMonths)
file_path = Path(__file__).resolve().parent / "data" / "raindata.txt"
values, first_year = read_data(file_path)
assert (values)
self.updateYearsList(first_year, first_year + len(values))
self._model = QRangeModel(values, self)
self._proxy = QItemModelBarDataProxy(self._model)
self._proxy.setUseModelCategories(True)
self._series = QBar3DSeries(self._proxy)
self._series.setItemLabelFormat("%.1f mm")
# Create the axes
self._rowAxis = QCategory3DAxis(self)
self._colAxis = QCategory3DAxis(self)
self._valueAxis = QValue3DAxis(self)
self._rowAxis.setAutoAdjustRange(True)
self._colAxis.setAutoAdjustRange(True)
self._valueAxis.setAutoAdjustRange(True)
# Set axis labels and titles
self._rowAxis.setTitle("Year")
self._colAxis.setTitle("Month")
self._valueAxis.setTitle("rainfall (mm)")
self._valueAxis.setSegmentCount(5)
self._rowAxis.setLabels(self._years)
self._colAxis.setLabels(MONTHS)
self._rowAxis.setTitleVisible(True)
self._colAxis.setTitleVisible(True)
self._valueAxis.setTitleVisible(True)
def customSeries(self):
return self._series
def valueAxis(self):
return self._valueAxis
def rowAxis(self):
return self._rowAxis
def colAxis(self):
return self._colAxis
def updateYearsList(self, start, end):
self._years.clear()
for i in range(start, end + 1):
self._years.append(str(i))
self._rowCount = len(self._years)
|