From 2eda7951c2601295d0462cf302965778fbf52f15 Mon Sep 17 00:00:00 2001 From: Hrithik Kumar Verma <54763705+risehr@users.noreply.github.com> Date: Fri, 2 Jul 2021 14:24:53 +0530 Subject: [PATCH] Completed the waypoints tutorial and resolved the screen recording problems of being played too fast (#1067) * Allow specification of file for linear defaultstyle (#1028) * Allow specification of file for default * Simplify if condition * Increase coverage (#1020) * Add wms_control tests * Add more mscolab tests * Add mpl_qtwidget coverage * Add mss_pyui coverage * Add transparency, noframe and xml checks * Add more wms tests * Test import with plugins * Add linearview tests * Add more multilayering tests * Revert to old testing.yml * Leave no dangling windows * Remove todo, move ConnectionError to bottom Co-authored-by: ReimarBauer * Migrate existing thermodynamic functions to metpy functions (#1009) * removed functions from thermolib.py functions to be replaced by metpy were removed * fixed: flake8 * fixed: flake8 * migrated to metpy functions Co-Authored-By: J. Ungermann <28449201+joernu76@users.noreply.github.com> * Fixed: flake8 * Fixed: flake8 * Fixed tests * Fixed: flake8 * Fixed: failing tests * Ficed: tests * Units discarded upon returning results Co-Authored-By: J. Ungermann <28449201+joernu76@users.noreply.github.com> * `omega_to_w` migrated to metpy Co-authored-by: ReimarBauer Co-authored-by: J. Ungermann <28449201+joernu76@users.noreply.github.com> * updated documentation (#1008) * updated documentation * improved install/update procedure Co-authored-by: Reimar Bauer * Fixed: #999 (#1010) * .format replaced with f" string * updated copyright year * fixes #1014 (#1015) * Remove Qt imports (#1019) * Fixes #1014 changing http to https (#1017) Co-authored-by: ReimarBauer * Linear view mscolab bug (#1021) * fixed tableview not opening bug; added test * added raising of mscolab window after closing view * preparation of v4.0.1 (#1023) * preparation of v4.0.1 * updated install instruction Co-authored-by: J. Ungermann * Fix pyproj 3.1.0 error (#1033) * Made a screen recorder and automated tutorial for demonstrating use of waypoints * Renamed tut pictures to just pictures and moved the tutorials.txt to requirements.d * Minor bug fixes. (#1054) * Return proper unit for eq. potential temperature (degC->K) * Do not assume units of pressure levels for several old plotting styles. * Fix values of geopotential altitude in demodata * issue #719 solved (#729) * issue #719 solved * updated development.rst * updated development.rst Co-authored-by: ReimarBauer * Select newest init-time and carry over multilayering (#1047) Co-authored-by: J. Ungermann * Fix some issues with elevation caching and model level dimensions. (#1061) Fix #1066 * Added missing filename key. (#1062) See #1066 * Waypoints tutorial completed * Just changed the sleep timings of the code to make it more efficient : tutorial_waypoints.py * Added the updated tutorials.txt in requirements.d Co-authored-by: May Co-authored-by: ReimarBauer Co-authored-by: Jatin Jain <72596619+Jatin2020-24@users.noreply.github.com> Co-authored-by: J. Ungermann <28449201+joernu76@users.noreply.github.com> Co-authored-by: open-mss-build <77272604+open-mss-build@users.noreply.github.com> Co-authored-by: Aryan Gupta <42470695+withoutwaxaryan@users.noreply.github.com> Co-authored-by: Aravind Murali Co-authored-by: J. Ungermann Co-authored-by: Archishman Sengupta <71402528+ArchishmanSengupta@users.noreply.github.com> --- requirements.d/tutorials.txt | 6 + tutorials/pictures/add_waypoint.PNG | Bin 0 -> 726 bytes tutorials/pictures/europe(cyl).PNG | Bin 0 -> 835 bytes tutorials/pictures/home.PNG | Bin 0 -> 595 bytes tutorials/pictures/makeroundtrip.PNG | Bin 0 -> 616 bytes tutorials/pictures/move_waypoint.PNG | Bin 0 -> 941 bytes tutorials/pictures/next.PNG | Bin 0 -> 418 bytes tutorials/pictures/options.PNG | Bin 0 -> 443 bytes tutorials/pictures/pan.PNG | Bin 0 -> 545 bytes tutorials/pictures/previous.PNG | Bin 0 -> 451 bytes tutorials/pictures/redraw.PNG | Bin 0 -> 589 bytes tutorials/pictures/remove_waypoint.PNG | Bin 0 -> 642 bytes tutorials/pictures/save.PNG | Bin 0 -> 526 bytes tutorials/pictures/selecttoopencontrol.PNG | Bin 0 -> 895 bytes tutorials/pictures/zoom.PNG | Bin 0 -> 740 bytes tutorials/screenrecorder.py | 140 +++++++++++ tutorials/tutorial_waypoints.py | 262 +++++++++++++++++++++ 17 files changed, 408 insertions(+) create mode 100644 requirements.d/tutorials.txt create mode 100644 tutorials/pictures/add_waypoint.PNG create mode 100644 tutorials/pictures/europe(cyl).PNG create mode 100644 tutorials/pictures/home.PNG create mode 100644 tutorials/pictures/makeroundtrip.PNG create mode 100644 tutorials/pictures/move_waypoint.PNG create mode 100644 tutorials/pictures/next.PNG create mode 100644 tutorials/pictures/options.PNG create mode 100644 tutorials/pictures/pan.PNG create mode 100644 tutorials/pictures/previous.PNG create mode 100644 tutorials/pictures/redraw.PNG create mode 100644 tutorials/pictures/remove_waypoint.PNG create mode 100644 tutorials/pictures/save.PNG create mode 100644 tutorials/pictures/selecttoopencontrol.PNG create mode 100644 tutorials/pictures/zoom.PNG create mode 100644 tutorials/screenrecorder.py create mode 100644 tutorials/tutorial_waypoints.py diff --git a/requirements.d/tutorials.txt b/requirements.d/tutorials.txt new file mode 100644 index 000000000..5d2c1eadd --- /dev/null +++ b/requirements.d/tutorials.txt @@ -0,0 +1,6 @@ +# This file may be used to create an environment using: +# $ conda create --name --file +# platform: win-64 +opencv=4.5.2=py39hcbf5309_0 +pyautogui=0.9.48=py39hde42818_1 +python-mss=6.1.0=pyhd3deb0d_0 \ No newline at end of file diff --git a/tutorials/pictures/add_waypoint.PNG b/tutorials/pictures/add_waypoint.PNG new file mode 100644 index 0000000000000000000000000000000000000000..d7595ce2e4e180e1813e1ab8fc71164507f8e749 GIT binary patch literal 726 zcmV;{0xA88P)Px#1ZP1_K>z@;j|==^1poj532;bRa{vGmbN~PnbOGLGA9w%&0&7V`K~!i%?Up~U zF+miE=`IQ(3JN6DNJODfD)buB`wk=u(Mc2%386)&@+S(VM59wFBq)T^H#j%HNoKN` zS90&JH{)g`PbO#PtUb@}%^iHkM5JD?li%+ryWP$(its*+BTsg{ z6_^saUawTCRLJ3Q+!g;Xkk@E5r2l0WQzEO?ibA1~cnfHKJ|C4zB`TN8tVPVnlgT8_ zW;5x3nZ=Yyx7!s@8^wA&9_saabh%vEI9kN$$N0P61~4U3EEa{xt7(INjCVR6noK4X z3Of5`Dr9^7AnkWcUCy_|dX0y4=L5zNkD=V^G zF3Ih7i^YrBOcNFOLwpzS#KK8AWg`*>1N_ zoX=-{QXo5FpB%95W%jFWexm@lk2ejMmr~ACZ5)phDA4Tv%X1^@s6$8t#y00001b5ch_0Itp) z=>Px#1ZP1_K>z@;j|==^1poj532;bRa{vGmbN~PnbOGLGA9w%&0@z7JK~#8N?U_At zvoH{bxf8W}_wKli>YTzfDc!o~44!fC8~6qaizLvl7Fm3m&jj-p&kV5ogV{$bC)M-$ zv;cthU=m&~7XZMUn3eGHcmM$YGmsE~m4So+tPCUsU}Yd704oCtOKBThRh4a8CH9im zHdSp+*I)l?9Po)Oldv6EsAg_8HmA^H#BQTu*i zk1UX|v!;%AaN5ypV>=&jn;=w)guhAX_tTl$R!ytM%1GatzSrO0c)+_TmvGpiYZP9ZVvfgVT`%&0Ja7RsEHT^JfF|(c}%&4EWrsa zv9xCrFNeU1B>Ttr%Gm0fa%1^eB9@a%t%fv*Jc_Ct5HYu2xfTaWs?G^Ei4?I!Kw@K+ zQ1l}~SY?c5lI^3|An)8pAkZXC8{yT{9C*dJb$wf8{6&*65vjn^dN;c#FA#&Joxg!0J7 zcKU#xY@A#hKF9D^$+4~0&xtiAJCjSaXE8U=Bni#c=xZY3lJ|7|QQBtn}b|C zjWPEfz@AtjArTTxCYjsS+3_w(+(10W1Q#hhGg0ztiQF?(r7%t$m-EQJB0js`Iax&i zs9Fx+f>lpt?W){hk1UjMOUy|74=npXp{tUwj+x_cM{s0#{;Na+xzApd( N002ovPDHLkV1gN^fwcet literal 0 HcmV?d00001 diff --git a/tutorials/pictures/home.PNG b/tutorials/pictures/home.PNG new file mode 100644 index 0000000000000000000000000000000000000000..fe573e634ce585cc909779b1e3f3b9bf2431ac59 GIT binary patch literal 595 zcmV-Z0<8UsP)Px#1ZP1_K>z@;j|==^1poj532;bRa{vGmbN~PnbOGLGA9w%&0q99YK~z{r?Umcg zF;N)DDcchVb{F7?T!UleA_zHh;KV&BQZ_{nI98PGBBW%K+=93OlsovpJ*#Fi(=s#f z_eEb{bMULNHqZapn#UT$^ZCTTgf66pE~JJoq{jaz)bID<@p$0%dNCLb#BrC)1%tr= zqtS@zbSl}S#9s*&3I&) znM?*Yo9#P7*XtFbP>2OttyVOfO|)7qwA*de>vdQx7E$EmLdW9~KA(?;P|wU}Gj=+3 zN<==N$7C{r+wK0mP_Ng6!{J~7!C(-F!vT>OR)QM5QmKf|PWRR2a^YqPsJ^n*YK6sO zfzfEh4b=i&jPv;%>-CzO@rvfA?smJ}FfDxKU-nKYolc|E=`fPXBzMhMg&K{9xTaRC zao6ZV!kVuN(Px70B6*ma5baqmmy%jaXci()rxP}tjRgAG3iI?VpQk;qHPrZ(&^OS9 h)X;_0(1nzF;s?9+1wOTSxy%3n002ovPDHLkV1m2L64(F$ literal 0 HcmV?d00001 diff --git a/tutorials/pictures/makeroundtrip.PNG b/tutorials/pictures/makeroundtrip.PNG new file mode 100644 index 0000000000000000000000000000000000000000..23ca9446858e74e5e1c74e77ef247bb35a332670 GIT binary patch literal 616 zcmeAS@N?(olHy`uVBq!ia0vp^DL|~k!3HGjcg?o|QjEnx?oJHr&dIz4a#+$GeH|GX zHuiJ>Nn{1`ISV`@iy0V%N611u^*pNN{rhH}<#eS_Z?uID zyRJ;0SNziP>nj1v(AQ7qt({|4=u}ryoAQS{k#kShdrpyzq+`+9KX_NN966j(uWEFS zPk6%fCtugzsjxe{QEPekYrXU9U+?zx;JLOxGEhj^X`bDw2?Ax-D+4U!pIw&B_S(1M z-K9U@T6epjSnA~Bbahtxi5u2uXXJDJG>`YtXz6J^eCq8zo1by(>u&yMI4#E`Y5jfT zS091t`z-kCdqRJours{3v*A0(&D$GaeEAY_+jotf%%_x%>K#hS>P-*! z#Pzf@cO)O%nP(R|d(Gq03sU{fxldhw_ubE&-!Mm7Qh@2+V%0TlPIhddXs8q72m~{x rd<^3FVRMC1m}wtBO8jV<{bvua``rD*V^IMxbuf6k`njxgN@xNACn60g literal 0 HcmV?d00001 diff --git a/tutorials/pictures/move_waypoint.PNG b/tutorials/pictures/move_waypoint.PNG new file mode 100644 index 0000000000000000000000000000000000000000..9539524e5ce540a2a5409803ea631b1d6cd8e224 GIT binary patch literal 941 zcmV;e15*5nP)Px#1ZP1_K>z@;j|==^1poj532;bRa{vGmbN~PnbOGLGA9w%&142neK~z{r?Uu1i zdQlX|4J0cFH5#g+(mk7ON{47@siBr=cWG%&5KNm4hoYerDT<=ThKisiC|Vj6i;8g2 z$qEGjgY)Bi;askI-}Aj7=m!p8?z`unckk!kbIyIwQLoqOuc!lKqz;Uc{$H4KxlE6b zk92i)C51lhI)A&e40C#VO3Ta3Aw*kON@Y~$nq*|?}ov)otVeaqmX>@c{o(9^%!9j{dBDB7~ zE?V@})0&^3r;m>h?R@QI3bVJjCl|qjUayxjnG98{RWXhheb^ajdU~3Q#bV1`R%8mZ zva%v!5Q0=HrS*dy<4&iO78Vw$P$R$(K^P_{C+X?wslf+**oTLQ>EYo)fb{qG3xAi(MRRj=4gO{_ zg}J@GCAZrx^8qaq8o7iMKoSd|*VHrlPEKGKIct}S_NAgp!wY5c;mzQ*XeNBNtKrA{j zF+m3h2Mu<-3)}bicgq@|sav=yO zf?eZ;5Jpta%gYN*O-+e$Bs#uP0K(s3KA+dl%d!Onsb6wvcXwCV-`?KD??X5oCXdG> z#*kwG!qtFlpn0xl*@nSy146{P!@m;{hm4b&WfmG$wqYRL5!>6_+PmWH>`Yb}=T)?EkGFD1E;d{IlJ8je zdO@btqwSju6}uKOL{4)QarKzgQt`~^OvkEK4wF;_SQ7aa3uT1QUrKUw3H-wQpw&S6 z*FN^x>-miZcRRP`I$k!(;}B;$JpCZ|L$?Huz|g6ZPOeu@XU>vWRy^mlg5&=8 z&d1?S9@A2f)b?~0$h2G3m>xFh_$?v&aF<@;mn=sCf$xS|kG@tlF48#iaC7B6_S2g{ zB22TNOCBryvoTTPz$P6vhBB^?D>G+(yMCDKzz%_O27|OCu?#(u6PLZz1yRp`f~bw_ zv|AES@E+Kqr{;8O)1CiZ+6<4K?p$rQs1k6mXV`d9`mUUCX?1bwKVY~rc)I$ztaD0e F0su7Lr|JLz literal 0 HcmV?d00001 diff --git a/tutorials/pictures/options.PNG b/tutorials/pictures/options.PNG new file mode 100644 index 0000000000000000000000000000000000000000..aa1a6c9354ff79f8a373395f6ab817327685e6f5 GIT binary patch literal 443 zcmeAS@N?(olHy`uVBq!ia0vp^$v~{g!3HGHt`_|Sq!^2X+?^QKos)S9a~60+7Besim4Gngy)^j>poRcX7srqc=eN^t3pOhVxW4Sn%V`VCIH06) zl5D=O!;COAks1h5H6OFp)k)V*T!{i%k&!Y_GJ z863gFQy5ubO#TUpsR2V z@~m<4{bgSdBm}P)b}*{3@M4pGEzrhq{`H!J(|h3@(YiqMGd!1)^#80&`!}^mNyA?* zMec+7-U##aJ*76jtB-Uan6$8WN9o&I*0=2C*G|7$HZxS#Wm)zsE<+nhccUV+;$IEQ z%4}QfT)G)nEil{r=j_?#bP$8bpdlPx#1ZP1_K>z@;j|==^1poj532;bRa{vGmbN~PnbOGLGA9w%&0k%m*K~z{r?Uq5x zfWz` zxvZE@!P0Vr!5}C0!1sOb7+FfmT`m`@*Xvv{U|AO3Za3~&8A^Y-^Z882tM6laOZp= zl#8N>Y}@9(ybO-x(Di!d&iO#9=CXoVlHG3iM7!N)d8gCK<>}IZ7&dU;Txq1_Kw5CI zSmbh1x6WoWB{3i^2OtQsFbs2oK7*LXX$JbAYcl?|jx~Z$P0 literal 0 HcmV?d00001 diff --git a/tutorials/pictures/previous.PNG b/tutorials/pictures/previous.PNG new file mode 100644 index 0000000000000000000000000000000000000000..57778074c7f9bda52d7a9d3adb9520f42dee7c45 GIT binary patch literal 451 zcmeAS@N?(olHy`uVBq!ia0vp^NX6k~CayA#8@b22Z19F}xPUq=Rp zjs4tz5?O(K&H|6fVg?4G5)fv*mnL5U)DYq6;usR){`S(wu4V^;hKJRGiM$pt!rAYPFjHn&1WQcS*J)|k1TF1i1;(r_^|q$>jpd@IM)hn6jj>h zbmSlZld|0h|JJGRU-?By#Z%};j#+{Pn~1C9xq@h(&c_lazQ291m#$dVHRtIT4ke{J ztNG`j*r=zT5IJPxTVW&jgil?SxBkTNrfWV}%O;>Sw?0D(mNnT>5U? zlIS7#eB0f;hgEwgeLsHIE==;+w%iK4`4>#iro>*KSbj83Q6i~HLBVj{Yp2`Wp3L*o z;ZQp)!`D9DFo)xtUyl&WXMN9Tp6BEJg>+W&cc9wcBnI3k-M$Pgg&ebxsLQ0N%&51^@s6 literal 0 HcmV?d00001 diff --git a/tutorials/pictures/redraw.PNG b/tutorials/pictures/redraw.PNG new file mode 100644 index 0000000000000000000000000000000000000000..a91b8c35f4e2997ca97939336c3023e35619a227 GIT binary patch literal 589 zcmeAS@N?(olHy`uVBq!ia0vp^NkFX3!3HGr7v4V(q!^2X+?^QKos)S9a~60+7Besim4Gngy)^j>poT}DE{-7?&TpsPo!X+n1`SFDF!sf9t%sewZ=L}^+oqq*bn zcbP6W^Zh@ZcW4n%aN-b9Wa$uKa^YYEE8F3IBx}tqHEYuh>*aGIjjyY(et!M&)X4Q$ z70%3h@?z$Gw?~%CdSdTC`C7EQ<3faZw%9aRjqEU^ZBp^;Onoham5rlii+9di9oSxI zV&56NHn4ilErGc_!V|@3i{@Jgp%z0i#_RfATc?x%ZcRJP=E8URl^SU=XB6G{l*Db=r*}ML$ z^<}!08@afA{p8)fU+2+f>!y{C$vP?jOy&pu&YzP!{aI3?u)+6RClv(y?);G0t+D9l zQT41X@y?w}EB0(T*{S^T6XSuim(N=W_I>(M!23_ncX3ON(Y!Px#1ZP1_K>z@;j|==^1poj532;bRa{vGmbN~PnbOGLGA9w%&0vAa{K~z{r?Uui; z0YMapS4rbf6f_DRK%-Q81C8iaUVua)I*CG}5L!HficX@@sSpV&3dO#`x%o}9lfk*W zGmG3?Z1H8BnKLt=nc3O3Y}=;)L?GlvAml|LXxCOnqz{i&|tegzvh4SJy5H~YSUPwL zfpWS0uu7<#OeW%$ffe+_U@&-@2WSc5qI(v?#puL-fYkFmKuZXeN+l_U_|JvZCk`>5 zFz!(6(rUF{<^bA4>JxW5o!FdDpe+P?y&gp(5h@f4@}FWWr_(8$?*}8HE_g}aR2}S07*qoM6N<$f?5Px#1ZP1_K>z@;j|==^1poj532;bRa{vGmbN~PnbOGLGA9w%&0i#JoK~z{r?UucY z!axwm;{zxtD1sK2TG_${iyvervok*yb`!(0Ec_O;M31Ogb3$EZ{)!q8f+#_xz~waU4Ay^dfo2*2OYJ0$l#<|5}A@m7{!zdPuLjE3CGRNZ)>2#Wpt%`EF zjPv;{^oc|wC=?1p{vKB{@1SK=crLTw?~zOOdra( zWm>HkH}!&cyDgnz<0x~zUa{NluwJjH8In Q*#H0l07*qoM6N<$f;r3NRsaA1 literal 0 HcmV?d00001 diff --git a/tutorials/pictures/selecttoopencontrol.PNG b/tutorials/pictures/selecttoopencontrol.PNG new file mode 100644 index 0000000000000000000000000000000000000000..217dbbb07f8577bed1ee07bbce4c005866e64f63 GIT binary patch literal 895 zcmV-_1AzRAP)Px#1ZP1_K>z@;j|==^1poj532;bRa{vGmbN~PnbOGLGA9w%&0~AR_K~#8N?U+55 z>mUq;y(ib{)2H)hT)$Ps8%UepYsfk2vxDq_XMrI?2n@C}6DBIYa|R@Xbh-Y?G|%T# z2|^8sS%qp4vkKK9W)-R-Fze-V5rmI`dXqKlMp&GWC zb?8*nG^!hzSQdlonpX8A7ZW}UbXJ?seH|Ojx`)xWuCa8z+zc;v)_Uw!+jMFO^4`a4 zvyOeMnr;Z@%Mi2v9Q$iMbd75J5#_v>m1Z4P-!hHQuLp-SGc@{|f4x4a0I|F<)^z`- z8qhen%b`XluAc~YZsG8vxpUq9t6%@n7W$1|N1;8>dKTBkX))&xcC96S=6tLdn2;fK*-}qJ0} zMX}s|^>vB*V?7tug~u6t7p-krV^+W#_IkZ$85P*qtQaeHOmqzrAe9$9tt`BN(Ri>2 z#3N!SbLqY)mfJ5oM#Oq9uFH-y_AXl6P-@oO?dJXl!yXO?&!{*~S!Y%d(z^pErbfLV z3oggpoj5j5KLA1jQ+Xz~`27|@<7VvkSTt5F7uQW=x&3luOuFZ+y1cQu&ewwOU9vU+ zHOA`SpLJ$si!_bCUVS)DV$SGPfLIXnHn`%Trr z_nfXPKK8YU?47;#oJ${CZ)Bxe=f;;l1^z6NgZ?rq`9CZ0%?BoCHBVsvZT2oUm~}#b z)0BN+{|&y}tiN>b+srBmKZuxBsD^B_3c@Eqy&0HQ5Iz+#t56MMR-qcitU@I`)qhxv VVzH9j4{`ti002ovPDHLkV1hkoooWC8 literal 0 HcmV?d00001 diff --git a/tutorials/pictures/zoom.PNG b/tutorials/pictures/zoom.PNG new file mode 100644 index 0000000000000000000000000000000000000000..e27228dd57e20d178be7a7a8c639e1ece463d505 GIT binary patch literal 740 zcmVPx#1ZP1_K>z@;j|==^1poj532;bRa{vGmbN~PnbOGLGA9w%&0(nV9K~z{r?Up}l zGC>fBjYbi{U=y@SqljQ5m@Z8U5iIO1>_XJ9px_@QA)Sy$NU3ES8x=&wLTrR2SO^MY zC5nO?h<<|!bKs(8Zg2G^FDWdZ%HPa9cf0PMYQ0{=U*jYt%1KI;f0CNd=P(+L;Pdm7 z{QX!CmTI@#5DtgIX0yTB*%_!*D$wb4;BvVjkx0OBI3(*1L0D=wn?WcPVj^-F3iEZ*Ol; zxl}4e_EbVqDx1yj4D$JWFqurq?8nCkSglr;#l42oRF(%<3f~fL=*^Jp>ube-TCdlG zi;D|Zb9Z+~=6GWa)zbh}+v zhrGYPlQ}uKQqgFXHTHNsWJV6$Pn+6OsYGVv;7Y~gan|_e=7!8rESF2rXf&+0TCI{f zIk-~!e4aJNy|Gv<$lN~ldY#oFgTa8z$-$NC_xqq$t66hA9;nXAza#fNyvEDtdT$AagtvrCO~PXti24Un!D1|&eKC(d@91aIWA`ytiVh{`lCE5MV`T05Iayham499<(SUg(nC@E1W zF?=8@yUnjkA$Y}Xi{WKW<+k~CDWqI3OBXtR$BUfq|3&IhPEw+rq(nJMiSh@f*6~} literal 0 HcmV?d00001 diff --git a/tutorials/screenrecorder.py b/tutorials/screenrecorder.py new file mode 100644 index 000000000..db07f66a2 --- /dev/null +++ b/tutorials/screenrecorder.py @@ -0,0 +1,140 @@ +""" + mslib.msui.screenrecorder + ~~~~~~~~~~~~~~~~~~~ + + This python script is meant for recording the screens while automated tutorials are running. + + This file is part of mss. + + :copyright: Copyright 2021 Hrithik Kumar Verma + :copyright: Copyright 2021 by the mss team, see AUTHORS. + :license: APACHE-2.0, see LICENSE for details. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +""" +import numpy as np +import cv2 +import datetime +import os +import sys +import time +import mss +from PyQt5 import QtWidgets + + +class ScreenRecorder: + """ + This is the screen recording class which helps to record the screen. + """ + def __init__(self): + """ + The constructor sets the FPS, codecs, VideoWriter object, filename, and directory + for the recording of the screen. + """ + self.record = True + self.app = QtWidgets.QApplication(sys.argv) + screen = self.app.primaryScreen() + self.width = screen.size().width() + self.height = screen.size().height() + self.fps = self.get_fps() + self.codec = cv2.VideoWriter_fourcc(*"mp4v") + current_time = datetime.datetime.now().strftime('%d-%m-%Y %H-%M-%S') + self.file_name = f'REC_{current_time}.mp4' + parent_dir = os.getcwd() + dir = "Screen Recordings" + try: + path = os.path.join(parent_dir, dir) + os.makedirs(path, exist_ok=True) + final_path = os.path.join(path, self.file_name) + except OSError: + print("Directory \"Recordings\" cannot be created") + self.recorded_video = cv2.VideoWriter(final_path, self.codec, self.fps, (self.width, self.height)) + self.window_name = "Screen Recorder : MSS" + cv2.namedWindow(self.window_name, cv2.WINDOW_NORMAL) + cv2.resizeWindow(self.window_name, 480, 480) + cv2.moveWindow(self.window_name, self.width - 480, 0) + + def get_fps(self): + """ + This method helps to get the Frames in one second according to the loop time and your + screen refresh rate of your monitor (if considerable in the program) and sets the FPS. + """ + with mss.mss() as sct: + bbox = {"top": 0, "left": 0, "width": self.width, "height": self.height} + fps = 0 + last_time = time.time() + while time.time() - last_time < 1: + img = sct.grab(bbox) + fps += 1 + img_np = np.asarray(img) + cv2.imshow("Frame Test Window", img_np) + cv2.destroyWindow("Frame Test Window") + + return fps + + def capture(self): + """ + Captures the frames of the screen at the rate of fps frames/second and writes into the + video writer object with the defined fourcc, codec and colour format. + """ + with mss.mss() as sct: + bbox = {"top": 0, "left": 0, "width": self.width, "height": self.height} + self.start_rec_time = time.time() + frame_time_ms = 1000 / self.fps + frames = 0 + print(f"Starting to record with FPS value {self.fps} ...") + while self.record: + img = sct.grab(bbox) + img_np = np.array(img) + img_final = cv2.cvtColor(img_np, cv2.COLOR_RGBA2RGB) + cv2.imshow(self.window_name, img_final) + self.recorded_video.write(img_final) + frames += 1 + expected_frames = ((time.time() - self.start_rec_time) * 1000) / frame_time_ms + surplus = frames - expected_frames + + # Duplicate previous frame to meet FPS quota. Consider lowering the FPS instead! + if int(surplus) <= -1: + frames -= int(surplus) + for i in range(int(-surplus)): + self.recorded_video.write(img_final) + # Exits the screen capturing when user press 'q' + if cv2.waitKey(max(int(surplus * frame_time_ms), 1)) & 0xFF == ord('q'): + break + + def stop_capture(self): + """ + When the screen is not being captured, this method is called to release the video writer + objects and destroy all windows showing additional useful information to the user. + """ + self.record = False + self.end_rec_time = time.time() + print(f".\n.\n.\n.\nFinished Recording in {self.end_rec_time - self.start_rec_time} seconds!") + self.recorded_video.release() + print(f"\n\nYour file \'{self.file_name}\' has been successfully saved in " + f"\'MSS\\tutorials\\Screen Recordings\' folder.") + cv2.destroyAllWindows() + self.app.exit() + + +def main(): + """ + Main function calling the above functions. + """ + rec = ScreenRecorder() + rec.capture() + rec.stop_capture() + + +if __name__ == '__main__': + main() diff --git a/tutorials/tutorial_waypoints.py b/tutorials/tutorial_waypoints.py new file mode 100644 index 000000000..d57901bbc --- /dev/null +++ b/tutorials/tutorial_waypoints.py @@ -0,0 +1,262 @@ +""" + mslib.msui.tutorial_waypoints + ~~~~~~~~~~~~~~~~~~~ + + This python script generates an automatic demonstration of how to play with and use waypoints + for activating/creating a flight track. + + This file is part of mss. + + :copyright: Copyright 2021 Hrithik Kumar Verma + :copyright: Copyright 2021 by the mss team, see AUTHORS. + :license: APACHE-2.0, see LICENSE for details. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +""" +import pyautogui as pag +import multiprocessing +import sys +import datetime +from sys import platform +from tutorials import screenrecorder as sr +from mslib.msui import mss_pyui + + +def initial_ops(): + """ + Executes the initial operations such as closing all opened windows and showing the desktop. + """ + pag.sleep(5) + if platform == "linux" or platform == "linux2": + pag.hotkey('win', 'd') + print("\n INFO : Automation is running on Linux system..\n") + elif platform == "darwin": + pag.hotkey('option', 'command', 'm') + print("\n INFO : Automation is running on Mac OS..\n") + elif platform == "win32": + pag.hotkey('win', 'd') + print("\n INFO : Automation is running on Windows OS..\n") + else: + pag.alert(text="Sorry, no support on this platform!", title="Platform Exception", button='OK') + + +def call_recorder(): + """ + Calls the screen recorder class to start the recording of the automation. + """ + sr.main() + + +def call_mss(): + """ + Calls the main MSS GUI window since operations are to be performed on it only. + """ + mss_pyui.main() + + +def automate_waypoints(obj=None): + """ + This is the main automating script of the MSS waypoints tutorial which will be recorded and saved + to a file having dateframe nomenclature with a .mp4 extension(codec). + """ + # Giving time for loading of the MSS GUI. + pag.sleep(15) + + # Maximizing the window + try: + if platform == 'linux' or platform == 'linux2' or platform == 'win32': + pag.hotkey('win', 'up') + elif platform == 'darwin': + pag.hotkey('ctrl', 'command', 'f') + except Exception: + print("\nException : Enable Shortcuts for your system or try again!") + pag.hotkey('ctrl', 'h') + pag.sleep(5) + + # Adding waypoints + try: + x, y = pag.locateCenterOnScreen('pictures/add_waypoint.PNG') + pag.click(x, y, interval=2) + except Exception: + print("\nException : Clickable button/option not found on the screen.") + pag.moveTo(712, 347) + pag.click(712, 347, interval=2) + pag.sleep(1) + pag.moveTo(812, 412) + pag.click(812, 412, interval=2) + pag.sleep(1) + + pag.moveTo(915, 560) + pag.click(915, 560, interval=2) + pag.sleep(1) + pag.moveTo(1000, 650) + pag.click(1000, 650, interval=2) + pag.sleep(3) + + # Moving waypoints + try: + x, y = pag.locateCenterOnScreen('pictures/move_waypoint.PNG') + pag.click(x,y, interval=2) + except Exception: + print("\n Exception : Move Waypoint button could not be located on the screen") + + pag.moveTo(1000, 650, duration=1) + pag.dragTo(1200, 400, duration=1) + pag.moveTo(915, 560, duration=1) + pag.dragTo(950, 321, duration=1) + + # Deleting waypoints + try: + x, y = pag.locateCenterOnScreen('pictures/remove_waypoint.PNG') + pag.click(x,y, interval=2) + except Exception: + print("\n Exception : Remove Waypoint button could not be located on the screen") + pag.moveTo(950, 321, duration=1) + pag.click(950, 321, duration=1) + pag.sleep(3) + if platform == 'linux' or platform == 'linux2' or platform == 'win32': + pag.press('enter', interval=1) + elif platform == 'darwin': + pag.press('return', interval=1) + pag.sleep(2) + + # Changing map to Global + try: + x, y = pag.locateCenterOnScreen('pictures/europe(cyl).PNG') + pag.click(x,y, interval=2) + except Exception: + print("\n Exception : Map change dropdown could not be located on the screen") + pag.press('down', presses=2, interval=2) + if platform == 'linux' or platform == 'linux2' or platform == 'win32': + pag.press('enter', interval=1) + elif platform == 'darwin': + pag.press('return', interval=1) + pag.sleep(5) + + # Zooming into the map + try: + x, y = pag.locateCenterOnScreen('pictures/zoom.PNG') + pag.click(x,y, interval=2) + except Exception: + print("\n Exception : Zoom button could not be located on the screen") + pag.moveTo(712, 347) + pag.dragRel(500, 200, duration=2) + pag.sleep(5) + + # Panning into the map + try: + x, y = pag.locateCenterOnScreen('pictures/pan.PNG') + pag.click(x,y, interval=2) + except Exception: + print("\n Exception : Pan button could not be located on the screen") + pag.moveRel(400, 400, duration=1) + pag.dragRel(-100, -50, duration=2) + pag.sleep(5) + + pag.moveTo(600, 400, duration=1) + pag.dragRel(90, 50, duration=2) + pag.sleep(5) + + # Switching to the previous appearance of the map + try: + x, y = pag.locateCenterOnScreen('pictures/previous.PNG') + pag.click(x,y, interval=2) + except Exception: + print("\n Exception : Previous button could not be located on the screen") + pag.sleep(5) + + # Switching to the next appearance of the map + try: + x, y = pag.locateCenterOnScreen('pictures/next.PNG') + pag.click(x,y, interval=2) + except Exception: + print("\n Exception : Next button could not be located on the screen") + pag.sleep(5) + + # Resetting the map to the original size + try: + x, y = pag.locateCenterOnScreen('pictures/home.PNG') + pag.click(x,y, interval=2) + except Exception: + print("\n Exception : Home button could not be located on the screen") + pag.sleep(5) + + # Saving the figure + try: + x, y = pag.locateCenterOnScreen('pictures/save.PNG') + pag.click(x,y, interval=2) + except Exception: + print("\n Exception : Save button could not be located on the screen") + pag.sleep(3) + current_time = datetime.datetime.now().strftime('%d-%m-%Y %H-%M-%S') + fig_filename = f'Fig_{current_time}.PNG' + pag.write(fig_filename, interval=1) + if platform == 'linux' or platform == 'linux2' or platform == 'win32': + pag.press('enter', interval=1) + elif platform == 'darwin': + pag.press('return', interval=1) + + print("\nAutomation is over for this tutorial. Watch next tutorial for other functions.") + + # Close Everything! + try: + if platform == 'linux' or platform == 'linux2' or platform == 'win32': + for _ in range(2): + pag.hotkey('alt', 'f4') + pag.sleep(3) + pag.press('left') + pag.sleep(3) + pag.press('enter') + pag.sleep(2) + pag.hotkey('alt', 'tab') + pag.press('q') + elif platform == 'darwin': + for _ in range(2): + pag.hotkey('command', 'w') + pag.sleep(3) + pag.press('left') + pag.sleep(3) + pag.press('return') + pag.sleep(2) + pag.hotkey('command', 'tab') + pag.press('q') + except Exception: + print("Cannot automate : Enable Shortcuts for your system or try again") + pag.press('q') + + +def main(): + """ + This function runs the above functions as different processes at the same time and can be + controlled from here. (This is the main process.) + """ + p1 = multiprocessing.Process(target=call_mss) + p2 = multiprocessing.Process(target=automate_waypoints) + p3 = multiprocessing.Process(target=call_recorder) + + print("\nINFO : Starting Automation.....\n") + p3.start() + pag.sleep(5) + initial_ops() + p1.start() + p2.start() + + p2.join() + p1.join() + p3.join() + print("\n\nINFO : Automation Completes Successfully!") + sys.exit() + + +if __name__ == '__main__': + main()