main.py 8.36 KB
Newer Older
Romain Creuzenet's avatar
Romain Creuzenet committed
1
"""File to execute to show results"""
Romain Creuzenet's avatar
Romain Creuzenet committed
2
# Data
3
from parameters import SESSION, DIR_OUT, START, END
Romain Creuzenet's avatar
Romain Creuzenet committed
4
# Basic
{}'s avatar
{} committed
5
import matplotlib.dates as mdates
Romain Creuzenet's avatar
Romain Creuzenet committed
6
import matplotlib.pyplot as plt
Romain Creuzenet's avatar
Romain Creuzenet committed
7
import warnings
8
9
import re
import os
Romain Creuzenet's avatar
Romain Creuzenet committed
10
# Stats
{}'s avatar
{} committed
11
12
13
import statsmodels.graphics as stm_graphs
import pandas as pd 
import statsmodels.api as stm
Romain Creuzenet's avatar
Romain Creuzenet committed
14
15
16
17
18
import numpy as np
# Graph map
from mpl_toolkits.basemap import Basemap
from pandas.plotting import register_matplotlib_converters
from datetime import datetime
{}'s avatar
{} committed
19

Romain Creuzenet's avatar
Romain Creuzenet committed
20
21
register_matplotlib_converters()
warnings.filterwarnings("ignore")
Romain Creuzenet's avatar
Romain Creuzenet committed
22
23
24
25
26
27
28
29


def execute_query(query):
    for row in SESSION.execute(query):
        yield row


def ask_q(possibilities, text=">>> "):
Romain Creuzenet's avatar
Romain Creuzenet committed
30
    """Demande une question"""
Romain Creuzenet's avatar
Romain Creuzenet committed
31
32
33
34
35
    answer = None
    while answer not in possibilities:
        answer = input(text)
    return answer

{}'s avatar
{} committed
36

Romain Creuzenet's avatar
Romain Creuzenet committed
37
38
39
def ask_d(text=">>> "):
    """Demande une date"""
    print("Entrez une date sous la forme YYYY-MM-DD HH:mm")
40
    print("Comprise entre {} et {}".format(START.strftime('%Y-%m-%d'), END.strftime('%Y-%m-%d')))
Romain Creuzenet's avatar
Romain Creuzenet committed
41
42
    date_parser = re.compile(r"(?P<year>\d{4})-(?P<month>\d{2})-(?P<day>\d{2}) (?P<hour>\d{2}):(?P<minute>\d{2})")
    match = None
{}'s avatar
{} committed
43

Romain Creuzenet's avatar
Romain Creuzenet committed
44
45
    while match is None:
        t = input(text)
{}'s avatar
{} committed
46
        match = date_parser.match(t)
Romain Creuzenet's avatar
Romain Creuzenet committed
47
48
49

    m = match.groupdict()
    result = (int(m['year']), int(m['month']), int(m['day']), int(m['hour']), int(m['minute']))
{}'s avatar
{} committed
50
51
            
    return result
Romain Creuzenet's avatar
Romain Creuzenet committed
52

Romain Creuzenet's avatar
Romain Creuzenet committed
53

54
def chose_attr():
Romain Creuzenet's avatar
Romain Creuzenet committed
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
    """Permet de demander un attribut dans la table"""
    # Search element
    decision = {
        "tmpf": "La témparature",
        "relh": "L'humidité"
    }
    print("Choisissez un élément parmis les suivant :")
    for code, text in decision.items():
        print("\t-", text, ":", code)
    return ask_q(decision.keys())


def ask_cluster(text=">>> "):
    answer = ""
    while not answer or not answer.isdigit():
        answer = input(text)
    return int(answer)


Romain Creuzenet's avatar
Romain Creuzenet committed
74
75
76
77
class Manager:
    table = None  # table name use by the function

    def run(self):
78
79
80
81
82
        """Chose objective"""
        # Initialisation
        os.makedirs(DIR_OUT, exist_ok=True)

        # Chose objective
Romain Creuzenet's avatar
Romain Creuzenet committed
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
        print("Choisissez ce que vous voulez faire")
        print("\t1 - Pour un point donné de l’espace, je veux pouvoir avoir un historique du passé")
        print("\t2 - À un instant donné je veux pouvoir obtenir une carte me représentant n’importe quel indicateur")
        print("\t3 - Pour une période de temps donnée, je veux pouvoir obtenir clusteriser l’espace, et représenter "
              "cette clusterisation")
        decision = {
            "1": "historic",
            "2": "map",
            "3": "cluster"
        }
        answer = ask_q(decision.keys())
        getattr(self, decision[answer])()

    def historic(self):
        self.table = "TABLE_SPACE"
98
        print("=== Choix 1 : Historique ===")
Romain Creuzenet's avatar
Romain Creuzenet committed
99
100

        # Search station
Romain Creuzenet's avatar
Romain Creuzenet committed
101
        stations = []
Romain Creuzenet's avatar
Romain Creuzenet committed
102
        print("Choisissez une station parmis celles-ci:")
Romain Creuzenet's avatar
Romain Creuzenet committed
103
104
105
106
107
108
109
        query = "SELECT DISTINCT station FROM {}".format(self.table)
        for i, row in enumerate(execute_query(query), 1):
            end = "\n" if i % 3 == 0 else ""
            print("\t", row.station, end=end)
            stations.append(row.station)
        print()

Romain Creuzenet's avatar
Romain Creuzenet committed
110
        station = ask_q(stations)
111
        attr = chose_attr()
Romain Creuzenet's avatar
Romain Creuzenet committed
112

{}'s avatar
{} committed
113
        ts = pd.Series()
114
        query = "SELECT time, {} FROM {} WHERE station={}".format(attr, self.table, station.__repr__())
Romain Creuzenet's avatar
Romain Creuzenet committed
115
        for row in execute_query(query):
Romain Creuzenet's avatar
Romain Creuzenet committed
116
117
118
            value = getattr(row, attr)
            if value is None:
                continue
{}'s avatar
{} committed
119
120
            ts.loc[datetime(*list(row.time))] = value

Romain Creuzenet's avatar
Romain Creuzenet committed
121
        plt.figure(figsize=(25, 16))
{}'s avatar
{} committed
122
123
        axes = plt.subplot()
        axes.xaxis.set_major_formatter(mdates.DateFormatter('%Y-%m-%d %H:%M'))
Romain Creuzenet's avatar
Romain Creuzenet committed
124
125
        plt.xticks(rotation=90)

{}'s avatar
{} committed
126
        plt.plot(ts, label=attr)
127
        plt.title("Donnees de {} pour la station : {}".format(attr, station))
Romain Creuzenet's avatar
Romain Creuzenet committed
128
129
        plt.legend()
        plt.show()
130
131
        path = os.path.join(DIR_OUT, 'graph_{}_{}.png'.format(station, attr))
        plt.savefig(path)
{}'s avatar
{} committed
132

Romain Creuzenet's avatar
Romain Creuzenet committed
133
        res = stm.tsa.seasonal_decompose(ts, freq=15, extrapolate_trend='freq')
{}'s avatar
{} committed
134
135
        res.plot()
        plt.show()
136
137
        path = os.path.join(DIR_OUT, 'decompose_{}_{}.png'.format(station, attr))
        plt.savefig(path)
{}'s avatar
{} committed
138

Romain Creuzenet's avatar
Romain Creuzenet committed
139
        stm_graphs.tsaplots.plot_acf(ts, lags=30)
{}'s avatar
{} committed
140
        plt.show()
141
142
        path = os.path.join(DIR_OUT, 'acf_{}_{}.png'.format(station, attr))
        plt.savefig(path)
Romain Creuzenet's avatar
Romain Creuzenet committed
143
144

    def map(self):
{}'s avatar
{} committed
145
        self.table = "TABLE_TIME"
146
        print("=== Choix 2 : Map ===")
{}'s avatar
{} committed
147
148

        date = ask_d()
149
        attr = chose_attr()
{}'s avatar
{} committed
150

Romain Creuzenet's avatar
Romain Creuzenet committed
151
152
153
        plt.figure(figsize=(14, 14))
        the_map = Basemap(projection='mill', llcrnrlat=25.281898, llcrnrlon=-18.42, urcrnrlat=48.08, urcrnrlon=10.35,
                          resolution='l')
{}'s avatar
{} committed
154
        # draw coastlines, country boundaries, fill continents.
Romain Creuzenet's avatar
Romain Creuzenet committed
155
156
157
        the_map.drawcoastlines(linewidth=0.25)
        the_map.drawcountries(linewidth=0.25)
        the_map.fillcontinents(color='coral', lake_color='aqua')
{}'s avatar
{} committed
158
        # draw the edge of the map projection region (the projection limb)
Romain Creuzenet's avatar
Romain Creuzenet committed
159
        the_map.drawmapboundary(fill_color='aqua')
{}'s avatar
{} committed
160
        # draw lat/lon grid lines every 30 degrees.
Romain Creuzenet's avatar
Romain Creuzenet committed
161
162
163
        the_map.drawmeridians(np.arange(0, 360, 30))
        the_map.drawparallels(np.arange(-90, 90, 30))

164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
        date_ok = False  # The date is valide
        query = "SELECT station, lon, lat, {} FROM {} WHERE time={}".format(attr, self.table, date)
        for row in execute_query(query):
            if getattr(row, "station") is None or getattr(row, attr) is None:
                continue
            date_ok = True
            x, y = the_map(getattr(row, "lon"), getattr(row, "lat"))
            value = getattr(row, attr)
            plt.plot(x, y, 'go')
            plt.annotate(round(value, 1), (x, y))

        title = "Map {} du {}".format(attr, datetime(*list(date)).strftime('%Y-%m-%d %H:%M'))
        plt.title(title)
        plt.show()
        for elt in ' :-':
            title = title.replace(elt, '_')
        path = os.path.join(DIR_OUT, title.lower() + '.png')
        plt.savefig(path)

        # If date is wrong, show some dates for this day
        if not date_ok:
            date_begin = list(date)
            date_begin[3] = date_begin[4] = 0  # set hours and minutes at 0
            date_begin = tuple(date_begin)

            date_end = list(date)
            date_end[3] = 23
            date_end[4] = 59
            date_end = tuple(date_end)
            print("Seules ces heures sont disponibles pour ce jour")

            query = "SELECT DISTINCT time FROM {} WHERE time >= {} AND time <= {} ALLOW FILTERING".format(
                self.table,
                date_begin,
                date_end,
            )
Romain Creuzenet's avatar
Romain Creuzenet committed
200
            for row in execute_query(query):
201
202
                resp = list(getattr(row, "time"))
                print(str(resp[3]).zfill(2) + ":" + str(resp[4]).zfill(2), end=" - ")
{}'s avatar
{} committed
203

Romain Creuzenet's avatar
Romain Creuzenet committed
204
205
    def cluster(self):
        self.table = "TABLE_TIME"
206
        print("=== Choix 3 : CLUSTER ===")
{}'s avatar
{} committed
207

Romain Creuzenet's avatar
Romain Creuzenet committed
208
        # Ask Date
209
        print("La date de départ :")
Romain Creuzenet's avatar
Romain Creuzenet committed
210
        date_b = ask_d()
211
        print("Entrez la date de fin sous la forme YYYY-MM-DD HH:mm")
Romain Creuzenet's avatar
Romain Creuzenet committed
212
213
214
        date_e = ask_d()
        print("Entrez le nombre de cluster voulus")
        nb_clust = ask_cluster()
Romain Creuzenet's avatar
Romain Creuzenet committed
215

Romain Creuzenet's avatar
Romain Creuzenet committed
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
        query = "SELECT * FROM {} WHERE time>={} AND time <= {}".format(self.table, date_b, date_e)
        for row in execute_query(query):
            if getattr(row, "station") is None:
                continue
            x, y = map(getattr(row, "lon"), getattr(row, "lat"))
            value = getattr(row, attr)
            plt.plot(x, y, 'go')
            plt.annotate(round(value, 1), (x, y))

        if False:
            plt.figure(figsize=(14, 14))
            map = Basemap(projection='mill', llcrnrlat=25.281898, llcrnrlon=-18.42, urcrnrlat=48.08, urcrnrlon=10.35,
                          resolution='l')
            # draw coastlines, country boundaries, fill continents.
            map.drawcoastlines(linewidth=0.25)
            map.drawcountries(linewidth=0.25)
            map.fillcontinents(color='coral', lake_color='aqua')
            # draw the edge of the map projection region (the projection limb)
            map.drawmapboundary(fill_color='aqua')
            # draw lat/lon grid lines every 30 degrees.
            map.drawmeridians(np.arange(0, 360, 30))
            map.drawparallels(np.arange(-90, 90, 30))

            plt.title('Map')
            plt.show()
            plt.savefig('./out/map.png')
Romain Creuzenet's avatar
Romain Creuzenet committed
242
243
244
245


if __name__ == "__main__":
    Manager().run()