From 55b08ef24cdd22b83ebf74195dfb5bd400613802 Mon Sep 17 00:00:00 2001
From: Nico Vermaas <vermaas@astron.nl>
Date: Mon, 25 Nov 2019 12:16:37 +0100
Subject: [PATCH] added fits_to_png functionality

---
 atdb_statistics/atdb_plot.py                 |  38 ++++++++++++++++++-
 atdb_stats.py                                |  30 ++++++++++++---
 data/fits_to_png.args                        |   3 ++
 data/sky.args                                |   2 +-
 data/time_used_science_pie_aug2019_prod.args |   4 ++
 data/time_used_science_pie_aug2019_vm.args   |   4 ++
 data/time_used_system_pie_aug2019_prod.args  |   4 ++
 data/time_used_system_pie_jul2019_prod.args  |   4 ++
 data/times_today_prod.args                   |   4 +-
 dist/atdb_plot-1.0.0.tar.gz                  | Bin 3145 -> 4606 bytes
 10 files changed, 83 insertions(+), 10 deletions(-)
 create mode 100644 data/fits_to_png.args
 create mode 100644 data/time_used_science_pie_aug2019_prod.args
 create mode 100644 data/time_used_science_pie_aug2019_vm.args
 create mode 100644 data/time_used_system_pie_aug2019_prod.args
 create mode 100644 data/time_used_system_pie_jul2019_prod.args

diff --git a/atdb_statistics/atdb_plot.py b/atdb_statistics/atdb_plot.py
index 63fd461..002681f 100644
--- a/atdb_statistics/atdb_plot.py
+++ b/atdb_statistics/atdb_plot.py
@@ -5,6 +5,7 @@
     Description: atdb plot module
 """
 
+import os
 import datetime
 import plotly
 import plotly.graph_objs as go
@@ -543,4 +544,39 @@ def do_time_used_science_pie_plot(title, subtitle, data):
     plt.grid(True,alpha=0.3)
     plt.legend(loc='upper right')
 
-    plt.show()
\ No newline at end of file
+    plt.show()
+
+
+def fits_to_png_apercal(input_file_name,output_file_name):
+    import matplotlib.pyplot as plt
+    from astropy.wcs import WCS
+    from astropy.io import fits
+    import matplotlib.colors as mc
+    output = output_file_name
+    fits_file = input_file_name
+    # open continuum image
+    fits_hdulist = fits.open(fits_file)
+    # get WCS header of cube
+    wcs = WCS(fits_hdulist[0].header)
+    # remove unnecessary axis
+    if wcs.naxis == 4:
+        wcs = wcs.dropaxis(3)
+        wcs = wcs.dropaxis(2)
+        img = fits_hdulist[0].data[0][0]
+    elif wcs.naxis == 3:
+        wcs = wcs.dropaxis(2)
+        img = fits_hdulist[0].data[0]
+    else:
+        img = fits_hdulist[0].data
+    # set up plot
+    ax = plt.subplot(projection=wcs)
+    # add image using sym-log scaling
+    fig = ax.imshow(img * 1.e3, norm=mc.SymLogNorm(1.e-9, vmin=0.03, vmax=200), origin='lower')
+    # add colorbar
+    cbar = plt.colorbar(fig)
+    cbar.set_label('Flux Density [mJy/beam]')
+    ax.coords[0].set_axislabel('Right Ascension')
+    ax.coords[1].set_axislabel('Declination')
+    ax.coords[0].set_major_formatter('hh:mm')
+    ax.set_title("{0:s}".format(os.path.basename(fits_file)))
+    plt.savefig(output, overwrite=True, bbox_inches='tight', dpi=300)
\ No newline at end of file
diff --git a/atdb_stats.py b/atdb_stats.py
index 79d8cd6..a5439f9 100644
--- a/atdb_stats.py
+++ b/atdb_stats.py
@@ -310,8 +310,9 @@ def do_times(args):
         if result['ingest_speed'] is not None and result['ingest_speed'] > 0:
             datapoint = {}
             datapoint['taskid'] = result['taskID']
-            nofrag,frag = result['timestamp_ingesting'].split('.')
-            timestamp = datetime.datetime.strptime(nofrag, '%Y-%m-%dT%H:%M:%S')
+            # nofrag,frag = result['timestamp_ingesting'].split('.')
+            # timestamp = datetime.datetime.strptime(nofrag, '%Y-%m-%dT%H:%M:%S')
+            timestamp = datetime.datetime.strptime(result['timestamp_ingesting'], '%Y-%m-%dT%H:%M:%SZ')
             datapoint['timestamp'] = timestamp
             datapoint['type'] = 'ingesting'
             datapoint['duration'] = result['ingest_duration']
@@ -325,8 +326,9 @@ def do_times(args):
         if result['timestamp_ingest_error'] is not None:
             datapoint = {}
             datapoint['taskid'] = result['taskID']
-            nofrag,frag = result['timestamp_ingest_error'].split('.')
-            timestamp = datetime.datetime.strptime(nofrag, '%Y-%m-%dT%H:%M:%S')
+            # nofrag,frag = result['timestamp_ingest_error'].split('.')
+            # timestamp = datetime.datetime.strptime(nofrag, '%Y-%m-%dT%H:%M:%S')
+            timestamp = datetime.datetime.strptime(result['timestamp_ingest_error'], '%Y-%m-%dT%H:%M:%SZ')
             datapoint['timestamp'] = timestamp
             datapoint['type'] = 'ingest_error'
             datapoint['speed_bps'] = prev_ingest_speed
@@ -515,6 +517,12 @@ def main():
     parser.add_argument("--interval",
                         default="day",
                         help="Shows bars per interval. Possible options: minute, hour, day, month")
+    parser.add_argument("--input_filename","-i",
+                        default="",
+                        help="input filename")
+    parser.add_argument("--output_filename","-o",
+                        default="",
+                        help="output filename")
     # plot parameters
     parser.add_argument("--title",
                         default="Title",
@@ -534,6 +542,12 @@ def main():
     parser.add_argument("--colormap",
                         default="viridis",
                         help="see: https://matplotlib.org/examples/color/colormaps_reference.html")
+
+    # commands
+    parser.add_argument("--fits2png",
+                        default=False,
+                        help="convert FITS to PNG.",
+                        action="store_true")
     # All parameters in a file
     parser.add_argument('--argfile',
                         nargs='?',
@@ -544,15 +558,16 @@ def main():
                         help="Show current version of this program.",
                         action="store_true")
 
+
     args = get_arguments(parser)
 
     # --------------------------------------------------------------------------------------------------------
     if (args.version):
-        print('--- atdb_stats.py - version 1.0.0 - 9 jun 2019 ---')
+        print('--- atdb_stats.py - version 1.1.0 - 25 nov 2019 ---')
         print('Copyright (C) 2019 - Nico Vermaas - ASTRON. This program comes with ABSOLUTELY NO WARRANTY;')
         return
 
-    print('--- atdb_stats.py - version 1.0.0 - 9 jun 2019 ---')
+    print('--- atdb_stats.py - version 1.1.0 - 25 nov 2019 ---')
     print('Copyright (C) 2019 - Nico Vermaas - ASTRON. This program comes with ABSOLUTELY NO WARRANTY;')
     if args.starttime != None:
         starttime = datetime.datetime.strptime(args.starttime, TIME_FORMAT)
@@ -604,6 +619,9 @@ def main():
     elif presentation=="time_used":
        do_time_used(args)
 
+    elif args.fits2png:
+        atdb_plot.fits_to_png_apercal(args.input_filename,args.output_filename)
+
     if args.remote_post_command != None:
         execute_remote_command(args.atdb_host, args.remote_post_command)
 
diff --git a/data/fits_to_png.args b/data/fits_to_png.args
new file mode 100644
index 0000000..8a56bf5
--- /dev/null
+++ b/data/fits_to_png.args
@@ -0,0 +1,3 @@
+--fits2png
+--input_file=D:\my_happili\image_mf_04.fits
+--output_file=D:\my_happili\image_mf_04.png
diff --git a/data/sky.args b/data/sky.args
index f5437f2..54d4042 100644
--- a/data/sky.args
+++ b/data/sky.args
@@ -7,4 +7,4 @@
 --plot_type=scatter
 --colormap=viridis
 --starttime=2018-01-01 00:00
---endtime=2019-06-17 00:00
+--endtime=2019-11-12 00:00
diff --git a/data/time_used_science_pie_aug2019_prod.args b/data/time_used_science_pie_aug2019_prod.args
new file mode 100644
index 0000000..8dae508
--- /dev/null
+++ b/data/time_used_science_pie_aug2019_prod.args
@@ -0,0 +1,4 @@
+--presentation=time_used
+--atdb_host=http://192.168.22.22/atdb
+--title=APERTIF Science Pie - Aug 2019
+--query=from=2019-08-01T00:01:00Z&to=2019-09-01T00:00:00Z&report_type=time_used_science_pie
\ No newline at end of file
diff --git a/data/time_used_science_pie_aug2019_vm.args b/data/time_used_science_pie_aug2019_vm.args
new file mode 100644
index 0000000..8dae508
--- /dev/null
+++ b/data/time_used_science_pie_aug2019_vm.args
@@ -0,0 +1,4 @@
+--presentation=time_used
+--atdb_host=http://192.168.22.22/atdb
+--title=APERTIF Science Pie - Aug 2019
+--query=from=2019-08-01T00:01:00Z&to=2019-09-01T00:00:00Z&report_type=time_used_science_pie
\ No newline at end of file
diff --git a/data/time_used_system_pie_aug2019_prod.args b/data/time_used_system_pie_aug2019_prod.args
new file mode 100644
index 0000000..230a8f1
--- /dev/null
+++ b/data/time_used_system_pie_aug2019_prod.args
@@ -0,0 +1,4 @@
+--presentation=time_used
+--atdb_host=http://atdb.astron.nl/atdb
+--title=APERTIF System Pie - Aug 2019
+--query=from=2019-08-01T00:01:00Z&to=2019-09-01T00:00:00Z&report_type=time_used_system_pie
\ No newline at end of file
diff --git a/data/time_used_system_pie_jul2019_prod.args b/data/time_used_system_pie_jul2019_prod.args
new file mode 100644
index 0000000..473a224
--- /dev/null
+++ b/data/time_used_system_pie_jul2019_prod.args
@@ -0,0 +1,4 @@
+--presentation=time_used
+--atdb_host=http://atdb.astron.nl/atdb
+--title=APERTIF System Pie - Aug 2019
+--query=from=2019-08-01T00:01:00Z&to=2019-08-31T00:08:00Z&report_type=time_used_system_pie
\ No newline at end of file
diff --git a/data/times_today_prod.args b/data/times_today_prod.args
index 7d2dc72..4bc4a3a 100644
--- a/data/times_today_prod.args
+++ b/data/times_today_prod.args
@@ -1,6 +1,6 @@
 --presentation=times
 --atdb_host=http://atdb.astron.nl/atdb
 --title=I/O speeds from ATDB
---subtitle=18 - 23 july 2019
+--subtitle=29/30 aug 2019
 --y_axis_title=I/O Speed in Gbps
---query=starttime__gt=2019-07-18T00:00:00Z&starttime__lt=2019-07-23T00:00:00Z
+--query=starttime__gt=2019-08-29T00:00:00Z&starttime__lt=2019-09-02T00:00:00Z
diff --git a/dist/atdb_plot-1.0.0.tar.gz b/dist/atdb_plot-1.0.0.tar.gz
index f295e205a10fd66827184cf2702917da251893c5..2ee7381f7c37a53cb77e46153e9d6b7361e6bbca 100644
GIT binary patch
literal 4606
zcmb2|=HTe5S{cjqKP9ucBqp&WB`LljC%;73P|rZmK(8dRh~cg6@BG`luKta5_|LB7
zrdT~u^mPA{>kSS1zPGBo*JfT!k^aWosCatI8rNwiL3wL<f8Q_n@G|<kX|DU_XK{tQ
zxBAFUYJXm<(Y9^T%@Uz1$1A2^=H0Wd`YP+if9m8(&i^ezf1aE_mSFPgyT4m)@{d*N
z6374E(>AI4%9HA<+^z6MrF)9_cc-q<2ld}#kM~_J{aab^h53j5EBWuz|Ng7|ng3AW
zxAB|XACDCOjb7#c`o+B^mUedc4%I84|G&>rqT%0nsekp~7wyS9CBO5{!v8n=J#09c
zulK)O|NHlg{f06kU-p|z$(sNAFZ1*kUyW2ng;VaMHo?7tMw||6w>+G`nZ!k{({JF|
zmZm8XU|5v-<W|V}TPzvLiE%sr)&Kmw{%*gxyq&$5>9&{l#ovDZcwb>4WdbrwxNpr&
z(a5{|6P@lJkXN42eEn4G)+5R5ZpNzdtQXxmlQCx9H1F;s$zND!DPJ$Y@bc<U>mzMd
zYyXJp6q;|5k$ALTynf%0Ki|8rpL(ek#gfva7h~;UaO={hjHug36Eyc2e%jyp>;L8q
z7pC~{d#|60kCFZ@;#O5&`7g@y_#wZ-kWCx+SA?1Hp9or&W%B#vm-!Fs*Tyu-Kl}Z?
z>py$zkNXyua=g-i>-!ExygkbG*l?L(sFT!f#}{9uS+l;_U;KaieEr|5Z~s0We6>IL
zfBRp@!2i7uS6ux6TqFMe{CV|N>-E#Qj$YKdaya6q5R=yJqs}*rzkA$NJ{?k4v1rvd
z4Gwj=e{Fkt52)!|&hm-5->Wt`r#I+!+6IHXFZJA^`@8?Y|K9b}UZU0Q|NP$n(ykeI
z>K^|uZu_YDtm43L`E~!#{+=&?{{QlVp4)H#7u>LZ_Hllpjg=f9o4U?FX&&j{|8<@|
zc;Mg|V7Eigt!~@v$(!bEuRZ<t?}BZHF8^bGuDEYp_p+d&B>%Y%NAe@9ZjP<zt@g;4
z7E9ZG`1<A3tJlxD@9A!zc{t6r=60pznJ~F9iL|cWJj_BHb5&(_de5oz-*oMc`CY}Z
z9Wz)i*9Wl}TQ)A*azUxf$;!?uDoU`uXnB>xoW&WUtVg!mRIxl%Yy6q>Lr#9}il+&+
zg1URfc*S3@dpt3Z?bcMs-7;IG(=0rMTMXmb9tc!TG*UlkbUn+JdrHYKrt_i95fk?w
zs1ZGx?8Z^Ql_&YygZ7-tyLsUka`t`7b#w2En7ioA2br@?oIJZ41TD>P&ox~BOKRqY
z=<OX(t#{nLJc055*Dw1LQgxzMzTSR)QQA8zsZA035q*B)!DbS<-EP@yKX1G))#b{|
z9>r45Fd?bYHpl(Q*1H<>I?hd$u8eSgy;bbE)Ta&1noL&%MA`$S*DNX!^_7s`QjxSa
z*6QJhWn4`bs@mVfe5Xy~dT-HkRY$O0YO(gW#wN@Av!>j>o@`S5mgDZu15De3JD)K+
zzSf(~v~^}pY08HkLUWS0xaI0GaN0Cp>HJYS$BF6Fr7-R3_X8U(csPudY!dSm8rJsI
zI;5yy(9hNGGRQ0zIA>J6ci+3a8Ii6z#|qamm9V`y+_w1DvS}|j&kPVhP+6O9Y<ST4
z%}$3a6}R`e6~-m6uS`5qlIA?GGHarzh|7Y2q)X*tg@@`2opvT=PK@^PIX1)BJnYQ@
z?v9m0>9^kXyG8BK&)D1761==k=dXyRqqsKPN8uTNTkZ4H1f4Wo%9{;^<r?{ZoQ}Sr
z+3=Fj{ZdKK^T{ifl`URmo~$?OG8A_ao+_@sY}!;u?d|88?N=$Bxf8W3E@xHx!LA)M
z7I4=rXT1NXp>104)jtkb{+gThZjTbpj8-rHX1_JqGvtA`Fq=bssmBJc#Dtj}V(NWL
z_9pHR6RBIPFvZ*}tDeQ)ZpXQ<2WHYIQ~qagZuj{(ahCi$?xvq}dewS_HzyQ-$e;6m
zQYqt=AmO7AEf#Nh@8Hh6RLzT-`KWYD;iD}#(iSJ>`K54wW%8Nwfq!La(Q^-_*34B+
zD_&V7mvJ4;X!1$0+z^`eOv%$>msUtjQ0dwb&R22k)`b4tQ^R#`3WL?pRetYoo0Xn_
zDb^6OBK9Cdh|=`UTv4hX-3M!!ry5+}ec}9>BiAIiOLy1y9Bbx1;g`H=e&WPw@vFRb
zdS~98sdRv^IeJ3-8|@i$7exd=6nyQv`-zdf!o8__CHW7<UEXDWzusfQcjMqc>vA#O
zGj*l^`!?-;*7z#zUD!6O{NEmm84E>^c8WU&HYj);VA;f<ve4Ql_5GG&+u-fTTpy{u
zFMt1Zd&-vg5BHmCY!0yZRN$&;U)g_?qay9*(l~`DLZaK;{xU6*`Mvz(|Clurb~{S8
z_3kr!^Tg4j*;Q^rzCdB*ZSI`S)AJ*%uZdLWe&yP;U{-#Y>*SozD)ZhwTpLv*u_E8N
zeLhF8tU&!c*76CZ721`jN}?G1lYGOrocqhmrC!+LY-btYwX*I{$*<SPyW>NBuO+Gp
zciMTqPQEMq=-jRFlvdNz+~U)2US_WpT536Sj_7BV``!JABtDh@@94d^^-rYv!A}~!
zeJ^tNC_Bws>u@82=lEN}yUGqiucM+Amz3%$%<rFB=W)Vid%I8T3{7P(^@%-q6EEu>
z4=j>WZC9MrTEOL6u9&6$x&2C@L-N$s57s2e2J3}6H$)h){nJehm+U$@gCS|siYu0%
zdK2Ciacn)e;F91MuDk_rn0f;Jz5h*)X;|XLTD{KZ&W!(hJeIvl{I45CJ#0L#r)1sS
zuJh_s`YXTg`aSE9E?*t6MfQVo%Jl7qzfxM+h1#OGpP2SiE|QH;^GQqip+%R&{&N4$
zS-z<uUF)&T_ATMuJqwyX$3=yCe{$pA&?UF*S*h6<->vz-PL<pHYg%tU_O1Aq@f(4j
z%;mQdS3bYN_VIz&@@I=C%<A>tvu&DULeUZNqA9lmxH3P>2*0_V^xMe){*fyM=hM=x
z{CpEv<)$@XZWMZ-_=5HR>Dx1RS8urO8N<2xc*u>jN9vyliLx-wvWeU$@1pQSD!s=-
z;=|<kzd3cM#kh3L-1B5ocA{t53!l|t*_&;zajbVtZhWAupjh+Ah~<&$GNFxY{8ZQi
zxN|HSDp>?AF3jNmq-m|4c}T?SznV|f^13H-(v^p2oPDtOFMGJrRIQthVdprOeD?63
z%4{#y$h1N_<+bwusE<$99-NZ&>Fn3JoXVfR`YtrO7jh_k##V-%D|H<G3=|nPnbp4<
z+1Pw*3210Y4dVMS=|q2VVNO{6+D$Wp_C5?uZ7Ww?H$`k^w4!zU<!S6EPE=lA`BE&r
zMA*reH?wy8+RcsUXW1ql3%Via(y{kY_kn~n0$*I3@|H5pUY+>$lWB<UY_^q6aoZ0D
z?%($I@Y8TU8(&^orfe4f7fK&K?ogWVYw~%Y_l+ydh40F&+O;nK<_^b}gN>6PtdCJR
zu*oL$((mna-x_f~^jId(+Bs#)OFJRWmA7kEiq79$rSeJ6*lywyOMmUmbEhY4aqp5c
zuisR=cFOiED)-}`Z2R&@&d8yTYuQ5QFD7hChUaVYjaP19zJFXGCUTEiah+aq)l2D2
zj|sOX8NbZ<doDs#FuZ9;*>OFEyX{Xs=DDm2UH(|-->O-@Mk1!0Jq0f9m^5`ldhxC-
zH^zyM8vRbTcZGk=`T4W&lg67(zRS+|crTn`lBD%-O|{be%y7nrmP@%8CT@FwMf3%a
z;~$3(E!NbdQyRLHCkvZcI!+c|VtMf0k_2JKX4h0R30Ll(8F!pacn&=a*j72ElHrv5
z<_jX5*D@T*Sm1qoQsG0^aIw^m6SvOrCA_@Jd`4(fdsO@4eLvm5pWXC3t?cWw?H_0R
zKQ^EKKfWMuXTr08lb0x7_}2O1*0IEpTW{45UYS*8_^aaQ&fnj5q#OLwS?l5aO^d18
z@cEND!rk*%Y3=#jefr&Xeg?5ClmBXm1vv`OZJWm(w&2B+_r9M>wtYIK?RJmZ)bZrs
z3%5_M+B<Reqn-zT1=$;e#WnjQt}ws(U|O=h;ibc^(z%_sFQO8s&wRbZ_2uPfXISsm
ztWU9Ye=I*mUVPfG1xGBl_r0IZ{l53z`FSk)q8pc=uG`*mW3lkPzplqCx4f{h-}&Ot
zgf(USl2tKQyY1Ug_CNKXe87zJjj`GWpAdEJS<6b7u9@oj!uv$f&z*Np3N2d2aakpV
zWwOfkRZ89qx1GLcIxT_wE9VwdUJsTlnoi=cE^kbhdYD@IB4+EXJ+uAQeUwWX(mTrp
z_b)zl>t9Px+^05U*F^?Sg3oo8Rc43=p3qPBt}lP~RE&XlMfa_xOJ%1O+Uoet%X}*?
zu3UYP_xW8W;WM8lU+pwIQ~SJ1E~QCB!T3yE&E^9WJoR{ZpXDAE`o4~rtDyS%r6Vr+
zcNaS3bSqif@vk~su`G`3&A}C`rpvf~oAThi+|5NtIeGqx%~CyZlr{V4(M(mQjLJux
zjEAx#c<ejxy?e>_`?lCO{y+N<7jw%Sbv3g*YnZ&0|Ml}Fj=AB-t%B;gWoAh_M65jc
zEw)EjT7O~p?UM(Wr=%GF^zoAn2(CHcuv&xT?TL{461xoRKQF6bs82lGWL;P1CS17N
z;`S%+{NzP5zHJZvvtHCfci*z_Zv-PBh&lfJ`MQ?li{^&TL%-H=Fjk#;eXgVQ`DSHd
zu}!f_)e+%Y{OLKhJO5``&omJGP<2pk^TwIIXKSKn&y@5!SrvB6r%<L}()Vg|)baDn
zv$U+Uo*Y)Uzo!zlK+CUH#dwSB=BRCZzMF5^d*#BX`Z})Q*@2!mCfmYq+-te1fBVO~
z{OZ=d5m9`nl_!0k%Vf0D=ZZ2b<GtF$8%@^S5zon5xAQ`|+nvgg+oso}URbjKZt~2%
zUQ@hqz3ZF>+m_#%5ww`~Oq^5GnNI~eN2ctzWKiRbHe;R`={r-$XJhWh;FUSoP5Z>&
zEV6I#TCu<@Ct-7vT{^24>nyoz0&h0-$+S<+7VTy<U0S(s)2u7Ko7}Rbh5RIKiubx*
ze7o#}tDjg^=tiU0(T`FW7ONUhzIS+6-eIdBYiICnPqezz_;Q0(@WJ<1r%r{omwvHX
zqa0S*ln6p|67RAcHTB>Mn6p}8x9Mq{HIDj{KRzA|ef{xb=<AISLtlRvjQ<#}zQN4s
zWYT=A<fT_V5A~XOiLHuVEiZh3;mYOl>-9n<y|~VC)jP5n#=L&>_V)J0-?N^cOZk;`
zW4htGZ40Bea$e2SSrL}$p#9ywTWI}Njg4W858Y;yoyI0B_Hq5i+ou9kt33C3&Jhln
z-G5f@NWz<!UtX`DpKaE5^|Udw#H^B2zpfnQJG~)u%R$3QPZp%k;cHKqXAqd@=a#<w
z(aSG?cPh?1=Xd{aka_Uynh#|eAM~CtE`NXI^6ra28*HzZSpHO)b@RrDl4<8YmCZ<P
ze009C>Q_Pf8{PJMldLiY-krN6YTE0xWe)43P1igg?pUK{-TcYgrntbP$>3+P{Kx0{
zJd7R;3p9Ur_gQZZ_7GAry_IlFRCe{nsjQw(;m@9Zcl@5JDtdNlX8nTS_m_AZ$JfsP
zz5mkh`)!9OA3XWt$BhTy_e-7q8*kt8zklDG|BQe1@BhEg&Y1Dzzf9`$zyBvc`}f~|
z(%<v%n(N&D%F7l1t}jaZGV>|>U->V7vwrWNzjTY4*SZ*8g=Hm?CYpN5DvVE#ym{6Y
z`lM=|_($%*eLF>xf;|phRP%E9Gs!uPp=4>do!g0Re=gnM#O|^yEH(3PS9I8lD~C7b
z`e@!4eQ@l_>))rfOMX37emyJHh}(E;!kd}i3RZ0oZ@n=Qv|&H3x;wLmjWK(5>l;zU
z8|?v-O=&-#wAX5!am`PTVBXh!{0U3Pi7k`={OEW(|H8Dnsg_;~f5dBQ>@WW-zWu=M
z;^&fI?`z!sZ!KZA|NnQJr&8AET4F!feU9qXNjHk!DQEpaci+YQe=P|Cl^eNl2ycCJ
zX8Vt8KW^S%{?Gnxzrvdf_0D(xpZ~o7;>U*9{}V3!_@AzMr?_~TyW@k4U(%A|7BAfS
zdh>6;H_;tWS1Q#hEjgRNKG68!NwWi!vKRSI^$rTNz1{L=S=2c(qaC6jeN2C+eLQj?
z<Y~#m3l<L}n^#WT+{SZ3_+;}+r%w|?ciC;Y^I7fX`py~GU;6sKdD8MjR;9wHp40Pe
z-h5xq#Ahcioy(J*RDbBmAOF1Q0Np=l7FoGn7meO7y=qpe{oaV3Pgkey-<gs3-}IQ%
p`<%@GzIL<E?p<cGRMR)pD|ptWDMT=zvQGWacqYK=D#HQ>1^}JK6G#96

literal 3145
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
Qq(9haR>W^-s9<0K0O;i^M*si-

-- 
GitLab