source: TOOLS/ConsoGENCMIP6/bin/plot_jobs.py @ 2431

Last change on this file since 2431 was 2431, checked in by labetoulle, 7 years ago

Add script to plot running and pending jobs

  • Property svn:executable set to *
File size: 10.4 KB
Line 
1#!/usr/bin/env python
2# -*- coding: utf-8 -*-
3
4# this must come first
5from __future__ import print_function, unicode_literals, division
6
7# standard library imports
8from argparse import ArgumentParser
9import os
10import os.path
11import datetime as dt
12import numpy as np
13
14# Application library imports
15from gencmip6 import *
16from gencmip6_path import *
17
18
19########################################
20class BilanDict(dict):
21  #---------------------------------------
22  def __init__(self):
23    self = {}
24
25  #---------------------------------------
26  def init_range(self, date_beg, date_end, inc=1):
27    """
28    """
29    delta = date_end - date_beg
30
31    (deb, fin) = (0, delta.days+1)
32
33    dates = (date_beg + dt.timedelta(days=i)
34             for i in xrange(deb, fin, inc))
35
36    for date in dates:
37      self.add_item(date)
38
39  #---------------------------------------
40  def fill_data(self, filein):
41    """
42    """
43    try:
44      data = np.genfromtxt(
45        filein,
46        skip_header=1,
47        converters={0: string_to_date,
48                    1: string_to_float,
49                    2: string_to_percent,
50                    3: string_to_percent},
51        missing_values="nan",
52      )
53    except:
54      print("Empty file {}".format(filein))
55      exit(1)
56
57    for date, conso, real_use, theo_use in data:
58      if date in self:
59        self.add_item(date, conso, real_use, theo_use)
60        self[date].fill()
61
62  #---------------------------------------
63  def add_item(self, date, conso=np.nan,
64               real_use=np.nan, theo_use=np.nan):
65    """
66    """
67    self[date] = Conso(date, conso, real_use, theo_use)
68
69  #---------------------------------------
70  def theo_equation(self):
71    """
72    """
73    (dates, theo_uses) = \
74      zip(*((item.date, item.theo_use)
75            for item in self.get_items_in_full_range()))
76
77    (idx_min, idx_max) = \
78        (np.nanargmin(theo_uses), np.nanargmax(theo_uses))
79
80    x1 = dates[idx_min].timetuple().tm_yday
81    x2 = dates[idx_max].timetuple().tm_yday
82
83    y1 = theo_uses[idx_min]
84    y2 = theo_uses[idx_max]
85
86    m = np.array([
87      [x1, 1.],
88      [x2, 1.]
89    ], dtype="float")
90    n = np.array([
91      y1,
92      y2
93    ], dtype="float")
94
95    try:
96      (a, b) = np.linalg.solve(m, n)
97    except np.linalg.linalg.LinAlgError:
98      (a, b) = (None, None)
99
100    if a and b:
101      for date in dates:
102        self[date].theo_equ = date.timetuple().tm_yday*a + b
103
104  #---------------------------------------
105  def get_items_in_range(self, date_beg, date_end, inc=1):
106    """
107    """
108    items = (item for item in self.itervalues()
109                   if item.date >= date_beg and
110                      item.date <= date_end)
111    items = sorted(items, key=lambda item: item.date)
112
113    return items[::inc]
114
115  #---------------------------------------
116  def get_items_in_full_range(self, inc=1):
117    """
118    """
119    items = (item for item in self.itervalues())
120    items = sorted(items, key=lambda item: item.date)
121
122    return items[::inc]
123
124  #---------------------------------------
125  def get_items(self, inc=1):
126    """
127    """
128    items = (item for item in self.itervalues()
129                   if item.isfilled())
130    items = sorted(items, key=lambda item: item.date)
131
132    return items[::inc]
133
134
135class Conso(object):
136  #---------------------------------------
137  def __init__(self, date, conso=np.nan,
138               real_use=np.nan, theo_use=np.nan):
139    self.date     = date
140    self.conso    = conso
141    self.real_use = real_use
142    self.theo_use = theo_use
143    self.theo_equ = np.nan
144    self.filled   = False
145
146  #---------------------------------------
147  def __repr__(self):
148    return "{:.2f} ({:.2%})".format(self.conso, self.real_use)
149
150  #---------------------------------------
151  def isfilled(self):
152    return self.filled
153
154  #---------------------------------------
155  def fill(self):
156    self.filled = True
157
158
159########################################
160def plot_init():
161  paper_size  = np.array([29.7, 21.0])
162  fig, ax = plt.subplots(figsize=(paper_size/2.54))
163
164  return fig, ax
165
166
167########################################
168def plot_data(ax, xcoord, xlabels, run_jobs, pen_jobs):
169  """
170  """
171
172  ax.bar(xcoord, run_jobs, align="center", color="lightgreen",
173         linewidth=0.1, label="running jobs cores")
174  ax.bar(xcoord, pen_jobs, bottom=run_jobs, align="center",
175         color="indianred", linewidth=0.1, label="pending jobs cores")
176
177
178########################################
179def plot_config(ax, xcoord, xlabels, title):
180  """
181  """
182  # ... Config axes ...
183  # -------------------
184  # 1) Range
185  xmin, xmax = xcoord[0]-1, xcoord[-1]+1
186  ax.set_xlim(xmin, xmax)
187  # ax.set_ylim(0., ymax)
188
189  # 2) Ticks labels
190  # inc_label = 12
191  # ax.ticklabel_format(axis="y", style="sci", scilimits=(0, 0))
192  xcoord_maj = [x for x, l in zip(xcoord, xlabels)
193                   if l.hour == 0 or l.hour == 12]
194  xlabels_maj = ["{:%d-%m-%d %Hh}".format(l) for l in xlabels
195                 if l.hour == 0 or l.hour == 12]
196  ax.set_xticks(xcoord, minor=True)
197  ax.set_xticks(xcoord_maj, minor=False)
198  ax.set_xticklabels(xlabels_maj, rotation="vertical", size="x-small")
199
200  # 3) Define axes title
201  ax.set_ylabel("cœurs", fontweight="bold")
202
203  # ... Main title and legend ...
204  # -----------------------------
205  ax.set_title(title, fontweight="bold", size="large")
206  ax.legend(loc="best", fontsize="x-small", frameon=False)
207
208
209########################################
210def get_arguments():
211  parser = ArgumentParser()
212  parser.add_argument("-v", "--verbose", action="store_true",
213                      help="verbose mode")
214  parser.add_argument("-s", "--show", action="store_true",
215                      help="interactive mode")
216  parser.add_argument("-d", "--dods", action="store_true",
217                      help="copy output on dods")
218
219  return parser.parse_args()
220
221
222########################################
223if __name__ == '__main__':
224
225  # .. Initialization ..
226  # ====================
227  # ... Command line arguments ...
228  # ------------------------------
229  args = get_arguments()
230  if args.verbose:
231    print(args)
232
233  # ... Turn interactive mode off ...
234  # ---------------------------------
235  if not args.show:
236    import matplotlib
237    matplotlib.use('Agg')
238
239  import matplotlib.pyplot as plt
240  # from matplotlib.backends.backend_pdf import PdfPages
241
242  if not args.show:
243    plt.ioff()
244
245  # ... Files and directories ...
246  # -----------------------------
247  (file_param, file_utheo) = \
248      get_input_files(DIR["SAVEDATA"], [OUT["PARAM"], OUT["UTHEO"]])
249
250  img_name = "jobs"
251  today = os.path.basename(file_param).strip(OUT["PARAM"])
252
253  if args.verbose:
254    print(file_param)
255    print(file_utheo)
256    # print(file_data)
257    print(today)
258    print(img_name)
259
260  file_list = glob.glob(os.path.join(DIR["SAVEDATA"],
261                                     "OUT_JOBS_PENDING_*"))
262
263  fg_first = True
264
265  for filein in sorted(file_list):
266    try:
267      data = np.genfromtxt(
268        filein,
269        skip_header=1,
270        converters={
271          0: string_to_datetime,
272          1: int,
273          2: int,
274        },
275        missing_values="nan",
276      )
277    except Exception as rc:
278      print("Problem with file {} :\n{}".format(filein, rc))
279      exit(1)
280
281    if fg_first:
282      fg_first = False
283      full_data = data
284    else:
285      full_data = np.append(full_data, values=data)
286
287  # print(full_data)
288  # print(full_data.size)
289
290  # .. Get project info ..
291  # ======================
292  gencmip6 = Project()
293  gencmip6.fill_data(file_param)
294  gencmip6.get_date_init(file_utheo)
295
296  # .. Fill in conso data ..
297  # ========================
298  # # ... Initialization ...
299  # # ----------------------
300  # bilan = BilanDict()
301  # bilan.init_range(gencmip6.date_init, gencmip6.deadline)
302  # # ... Extract data from file ...
303  # # ------------------------------
304  # bilan.fill_data(file_data)
305  # # ... Compute theoratical use from known data  ...
306  # # ------------------------------------------------
307  # bilan.theo_equation()
308
309  # # .. Extract data depending on C.L. arguments ..
310  # # ==============================================
311  # if args.full:
312  #   selected_items = bilan.get_items_in_full_range(args.inc)
313  # elif args.range:
314  #   selected_items = bilan.get_items_in_range(
315  #     args.range[0], args.range[1], args.inc
316  #   )
317  # else:
318  #   selected_items = bilan.get_items(args.inc)
319
320  # .. Compute data to be plotted ..
321  # ================================
322  # nb_items = len(selected_items)
323  nb_items = full_data.size
324
325  xcoord   = np.linspace(1, nb_items, num=nb_items)
326  xlabels  = np.array([date for date, run, pen in full_data])
327  # xlabels  = ["{:%d-%m-%d %H:%M}".format(date)
328  #             for date, run, pen in full_data]
329
330  run_jobs = np.array([run for date, run, pen in full_data],
331                        dtype=int)
332  pen_jobs = np.array([pen for date, run, pen in full_data],
333                        dtype=int)
334
335  print(xcoord, xlabels)
336  print(run_jobs)
337  print(pen_jobs)
338
339  # cumul     = np.array([item.conso for item in selected_items],
340  #                       dtype=float)
341  # consos    = []
342  # consos.append(cumul[0])
343  # consos[1:nb_items] = cumul[1:nb_items] - cumul[0:nb_items-1]
344  # consos    = np.array(consos, dtype=float)
345
346  # conso_per_day = np.array([gencmip6.alloc / nb_items
347  #                             for item in selected_items], dtype=float)
348
349  # theo_uses = np.array([100.*item.theo_use for item in selected_items],
350  #                      dtype=float)
351  # real_uses = np.array([100.*item.real_use for item in selected_items],
352  #                      dtype=float)
353  # theo_equs = np.array([100.*item.theo_equ for item in selected_items],
354  #                      dtype=float)
355
356  # .. Plot stuff ..
357  # ================
358  # ... Initialize figure ...
359  # -------------------------
360  (fig, ax) = plot_init()
361
362  # ... Plot data ...
363  # -----------------
364  plot_data(ax, xcoord, xlabels, run_jobs, pen_jobs)
365
366  # # ... Tweak figure ...
367  # # --------------------
368  # if args.max:
369  #   ymax = gencmip6.alloc
370  # else:
371  #   ymax = np.nanmax(consos) + np.nanmax(consos)*.1
372
373  title = "Consommation {}\n({:%d/%m/%Y} - {:%d/%m/%Y})".format(
374    gencmip6.project.upper(),
375    gencmip6.date_init,
376    gencmip6.deadline
377  )
378
379  plot_config(ax, xcoord, xlabels, title)
380
381  # ... Save figure ...
382  # -------------------
383  img_in  = os.path.join(DIR["PLOT"], "{}.pdf".format(img_name))
384  img_out = os.path.join(DIR["SAVEPLOT"],
385                         "{}_{}.pdf".format(img_name, today))
386
387  plot_save(img_in, img_out, title)
388
389  # ... Publish figure on dods ...
390  # ------------------------------
391  if args.dods:
392    dods_cp(img_in)
393
394  if args.show:
395    plt.show()
396
397  exit(0)
Note: See TracBrowser for help on using the repository browser.