Friday, July 31, 2020

Mapping African countries open for international tourism

On the 14th of February 2020, the COVID-19 pandemic was confirmed to have spread to Africa, which leads to shutting down of many activities including the 'International Tourism' sector. The first confirmed case was in Egypt, and the first confirmed case in sub-Saharan Africa was in Nigeria. Learn more on this Wikipedia page.

Five months later, a lot has changed, and some of the Africa countries are reopening for tourism activities. Check "Africa Reopening For International Tourism – A-Z List of Countries" for more details.

Given this, I decided to create a map to show the current reopening status (as at the 31st of July, 2020) of each country as either: 'Not Open for Tourism', 'Reopening Soon', or 'Now Open'.

As at the 31st of July, 2020 the Africa international tourism opening status is as follow:-
a) Reopening Soon = 13 countries
b) Not Open For Tourism = 28 countries
c) Now Open = 10 countries

The status of the four countries is unknown, and these countries are Western Sahara, Ivory Coast, Comoros and Swaziland.

See detailed breakdown on the table below...



To prepare the map, we will just link the status above to the map of Africa and the categorize the countries base on the status as seen below.



Stay safe and happy tourism.

Thursday, July 16, 2020

Fix 'wish.exe' cannot be found while running TkInter's GUI builder (PAGE)


This guide will show you how to fix 'wish.exe' cannot be found while running page gui builder for python on windows OS.

When you download PAGE and installed it on windows, you will get this error "Windows cannot find 'wish.exe'. Make sure you typed the name correctly, and then try again.".




This is because PAGE (the Python Automatic GUI Generator) requires Tcl/Tk ActiveTcl package. Tcl/Tk is required for executing PAGE. Tcl/Tk is required because PAGE is written in Tcl/Tk.



The solution
Head over to ActiveTcl page, download and install a copy for your windows OS.


You may be promted to register on the website before you download it, just follow the prompts and download a copy of ActiveTcl. Then run it as usual to install it.



With this out of the way, your PAGE TkInter GUI Generator software should lunch correctly as seen below.




Enjoy!

Tuesday, July 14, 2020

Extracting the Duration of Video file


Few days ago, I was working on a project where I have to lookup the duration of video files and compare the length duration on local disk with the corresponding duration of video online.

So, instead of going between video on local disk and online repeated, I thought what if I could use python to extract all the duration lengths into a table (CSV/Excel) and compare the columns.

Here is how I went about doing it. I made use of 'moviepy' which is a Python module for video editing, which can be used for basic operations (like cuts, concatenations, title insertions).


Installing moviepy
Use: pip install moviepy
This will some other dependent packages such as: decorator, tqdm, urllib3, idna, chardet, requests, proglog, numpy, pillow, imageio, imageio-ffmpeg



To be sure you installation was successful, try to import the module as seen above. If you got not error then your installation was successful and you are good to move on.

The poblem
Here I have some set of videos I downloaded from an online course and I listed their durations in a spreadsheet file as seen below. Now I want to compare each video duration/length to be sure it was downloaded correctly.



The code to extract the video duration to be compared withwhat was obtained online is as below:-

import glob
import datetime
from moviepy.editor import VideoFileClip



folder_path = r'C:\Users\Yusuf_08039508010\Desktop\videos_tut'
videoFiles = glob.glob(folder_path + str('\\*ts'))

# Converts Seconds to: hours, mins, seconds using 'datetime' module
def convert_sec(vid_seconds):
 return str(datetime.timedelta(seconds=vid_seconds))



for v in videoFiles:
    clip = VideoFileClip(v)
    # duration in seconds (create custom function to convert to: H:M:S)
    video_duration = clip.duration

    print (v.split('\\')[-1], convert_sec(int(video_duration)))

Basically, the code uses the 'glob' module to access all the videos in the folder and used the 'datetime' module to convert the video duration in seconds provided by the 'moviepy' module.

The result is a seen below;-


Thank you for reading.

Wednesday, July 8, 2020

PyQT5 and wxPython - Hex Color Spinner

Lets make a 'Hex Color Spinner' desktop app in both PyQT5 and wxPython.

This is going to be a simple desktop window frame that will spin out random hex color and value when a button is pressed.


By working through this app, we will get familiarized with:-
1) creating the GUI structure in both Qt designer and wxformbuilder.
2) connecting the widgets to functions.
3) read and update values on widgets.
4) change window's background color


Hexadecimal color code
A hex color code is made-up of '#' sign followed by six characters which include the combination of numbers between 0-9 (0, 1, 2, 3, 4, 5, 6, 7, 8, 9) and letters between A-F ("A", "B", "C", "D", "E", "F"). Notye that the letters can either be in upper or lower case.

So, for example: #F35EEA, #5BDB6B, #9FE091, #8DA7ED, #ADD075 etc will all yeild unique HEX colors.

To come up with such random string in python, there are many possible ways. Below is one way to do it.

# import 'choice' function from the random module...
from random import choice

# define a list of legal HEX characters...
hex = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, "A", "B", "C", "D", "E", "F"]

# loop through the list six time while selecting one character per loop...
hex_list = [str(choice(hex)) for x in range(6)]

# join the choosen characters and prefix with the '#' symbol...
hex_string = '#' + ''.join(hex_list)
print(hex_string)

Now that we have a python code that generates the hex color code, we will wrap it in a function to be called within our GUI.


PyQt5 GUI
For the GUI in pyqt, I made use of Qt designer to quickly created it as seen below.


The qt designer GUI consist of a QLable and a QPushButton arranged in a verticalLayot. I made use of verticalSpacer to give space above and belwo the widgets which were arranged vertically.


wxPython GUI
For the GUI in wxPython, I made use of wxFormBuilder to quickly created it as seen below.


The GUI is made off wxStaticText and wxButton arranged in a vertical BoxSizer. A spacer is used to give space above and belwo the widgets.


Running the App

In both cases above, we will generate the GUI file and call it in a main.py file which loads the GUI and then connect the button to the function that runs the hex color code generator above.


PyQt5 code




import sys
from PyQt5.QtWidgets import *
from PyQt5.QtCore import *
from PyQt5.QtGui import *
from PyQt5 import uic

from random import choice


class MyWindow(QMainWindow):
 """docstring for MyWindow"""
 def __init__(self):
  super(MyWindow, self).__init__()
  uic.loadUi('gui_Project.ui', self)

  self.colorButton.clicked.connect(self.change_color_func)

  self.show()
  

 def change_color_func(self):
  # print('#####################')
  hex = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, "A", "B", "C", "D", "E", "F"]

  hex_list = [str(choice(hex)) for x in range(6)]

  hex_string = '#' + ''.join(hex_list)
  print(hex_string)

  # ------------------------
  # Change the text of '#XXXXXX' to current hex text
  self.hex_text.setText(hex_string)

  # ------------------------
  # Change background color to current hex color
  self.setStyleSheet("background-color: {};".format(hex_string))


if __name__ == '__main__':
 app = QApplication(sys.argv)
 window = MyWindow()
 sys.exit(app.exec_())




wxpython code




import wx
from gui import MyWindow_1

from random import choice


class MyWindow_2(MyWindow_1):
 def __init__(self, parent):
  MyWindow_1.__init__ (self, parent)
  
 def change_color_func(self, event):
  # print('#####################')
  hex = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, "A", "B", "C", "D", "E", "F"]

  hex_list = [str(choice(hex)) for x in range(6)]

  hex_string = '#' + ''.join(hex_list)
  print(hex_string)

  # ---------------
  # Change the text of '#XXXXXX' to current hex text
  self.hex_text.SetLabel(hex_string)
  self.Layout()

  # ------------------------
  # Change background color to current hex color
  self.SetBackgroundColour(hex_string)
  self.Refresh()


app = wx.App(0)
MyWindow_2(None).Show()
app.MainLoop()


The result should look like below....


Download the files from this github repository.