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.

Tuesday, June 23, 2020

Python pandas get length (row count) of a dataframe

There are several ways of knowing the length of your dataframe rows. Here are three ways using index, shape and count methods.

Manually inspecting this dataframe below, we see that it has 10 rows (note the index count starts from 0). Now, let check for this information dynamically.



1) index
Using the index method, it returns the 'RangeIndex' start, stop and step for the dataframe. So, wrapping it in a len() function will give the stop value that is the length of the datafarme as seen below.





2) shape
Using the shape method will return a tuple like so (row, col), where the first element is row and the second element is column.




3) count
Using the count method returns a 'pandas.core.series.Series' that contains number of items for each column.



Enjoy!

Thursday, June 18, 2020

SVG2GeoJSON - SVG file with added Geo-Referencing


Recently, I had a task to convert an SVG image map into GeoJSON format for use in the GIS. This is a complicated thing to do because SVG vector images don't have spatial reference.

Fortunately, I stumbled on this NodeJS app package named svg2geojson written by Prognoz. This library converts an SVG image to a (slightly-incorrect) GeoJSON


To make use of this library, you need to update your SVG map by placing two 'GeoItems' inside a Prognoz MetaInfo element as a direct child of the '<svg>' element at the root of your document.

Now how do you find the X/Y and Longitude/Latitude attributes within the 'GeoItems' for your specific SVG image? This question is what I will attempt to answer in this blog post.

The svg2geojson documentation says: "These map opposing X/Y corners in your SVG coordinate space to Longitude/Latitude coordinates on the world. Note that the SVG coordinate space has Y increasing down (toward the south), while Latitude increases upwards (towards the north)."

That is something like the daigram below:-


Monday, May 25, 2020

No reimporting of module in Python script

Chances are you have been working with imported modules in python. And you usually import the modules from the very top of the script file.

What happen when you import same module twice or more?

The simple answer in nothing! In python when you import a module and you try to import it again in the same instance of a script it won't work!

That is why when you work with modules such as these listed below, it is easy to get confused that the modules work only the first time you ran them.

  • import __hello__
  • import this
  • import antigravity

You will only see the result of their import once.


import __hello__: will print the famous "Hello World!" as an output.




import this: will print the 'Zen of Python'




import antigravity: will open a browser link to python antigravity xkcdwebcomic.




If you try to run any of the above for the second time, none will work.


Obviouly, I don't see any reason why you will reimport a module. But if you do it for whatever reason, then the second import won't work.

Saturday, May 23, 2020

Fixed - Blog broken due to 'SyntaxHighlighter' Error 522

Few days ago, I noticed my blogger.com blog will load forever when you tried to access it.

The so many things started to flow in my mind. Could it be someone hacked my blog? Could it Google's blogger server isn't responding? Or what?

All my preliminary thoughts and checks didn't yield positive result.

Then a new idea pop in my mind to check the developer console whether I would lucky to find clue to what broke my blog. Behold, I saw some errors on about 8 lines pointing to same Javascript file which is not accessible. This Javascript file was from the 'Syntax Highlighter' plugin.



Just in case if you don't know, 'Syntax Highlighter' is a Javascript plugin that adds code highlighting within blog post. It was developed by Alex Gorbatchev.

I remembered, few years ago I added it to allow me highlight code snippets within my blog posts.

At the moment, the server that host the 'Syntax Highlighter' plugin is down with Error 522 which indicates that Cloudflare is unable to reach the origin web server and the request times out.




How I fixed it

I just accessed the theme settings and comment out the lines that reference the 'Syntax Highlighter' plugin.

Go to Theme >> Edit HTML and remove or comment out that has to do with 'Syntax Highlighter'. Note that the CSS and JS files are hosted on alexgorbatchev.com which is currently offline.



Viola! The error is gone and blog is back to live!



That is it!

Wednesday, April 29, 2020

Setting up Django Project and App on NameCheap Shared Hosting using cPanel

It isn't news anymore that many shared host accounts best know for hosting PHP web frameworks now support python web frameworks.

In this post, I will show you how to deploy python django web framework on "NameCheap Shared Hosting" using cPanel.

Django Project is a collection of Apps. A project most have at least one app.

Note: you can deploy django on any cpanel account that:-
1) Supports python apps and 
2) Provides access to 'Terminal/Command-Line'


Step 1: 
I am going to use an existing namecheap account (domain and hosting). If you don’t have account yet, signup for one.

Step 2: 
Login to you cpanel and create a 'subdomain'. Mine is at: https://django1.umaryusuf.com as seen below





At this point, when you load the URL it should display this…



Step 3: Setup Python App
Click on the python icon that says “Setup Python App” (it should be under ‘Software’ tab as seen below).

Click create button that says “Create Application”


Fill the form as seen below… and click on ‘Create’ button.



You should see a screen that look like this below, with a command to enter the virtual environment. Copy the path (source /home/xxx/virtualenv/django1/3.7/bin/activate && cd /home/xxx/django1), you will use it in the next step.


If you checked your “File Manager”, you should see these two folders created from the names you entered above.



Sunday, April 26, 2020

3 ways to loop through a list or items in python

In this article, I will work through three different ways to loop through a list object in python. In particular, I will use the list of countries that have not reported any cases of the coronavirus so far as sourced from 'Johns Hopkins University' and last update: April 20, 2020.

countries = ['Comoros', 'Kiribati', 'Lesotho', 'Marshall Islands', 'Micronesia', 'Nauru', 'North Korea', 'Palau', 'Samoa', 'Sao Tome and Principe', 'Solomon Islands', 'Tajikistan', 'Tonga', 'Turkmenistan', 'Tuvalu', 'Vanuatu']


1) Using WHILE loop:
This is not a common method of looping in Python.

i = 0
while i < len(countries):
    print(countries[i])
    i += 1
This mimic the C-style for loop in other languages such as JavaScript where an arbitrary variable (i) is set, checked, and incremented.

for (var i = 0; i < countries.length; i++) {
    console.log(countries[i]);
}



2) Using RANGE function:
This is similar to "foreach" loop in other languages, it first creates a range corresponding to the indexes in the list.

for i in range(len(countries)):
    print(countries[i])



3) Using FOR-IN the usual way:
The two methods above rely on looping over indexes. Since we are not utilizing the indexes, then we don't need to access them. So, this third method loop throgh the elements without accounting for the indexes.

for c in countries:
    print(c)
Compared to other methods above, this is the most pythonic method of looping.


Saturday, April 18, 2020

Map of NYSC orientation camps in Nigeria

Every year, graduates in Nigeria are mobilized for one year mandatory 'National Youth Service Corps' (NYSC) which starts following a three weeks program at different camp sites across the country.

The NYSC body has done a great job by list all the addresses of those camps on their website.



How about if they could also list the latitude and longitude of the camps and also have them shown on a map? That is exactly what you will get on this page, keep reading.

Note that due to prevailing insecurity situation in Borno state, as of April 2020 the state's camp location is in Katsina state.





GPS Coordinates of the Camps

StateCamp AddressLatitudeLongitude
ABIANYSC Permanent Orientation Camp, Umunna, Bende Local Government Area, Abia State.5.55187887.6359827
ADAMAWANYSC Permanent Orientation Camp, Lapondo Road, Damare, Girei LGA, Adamawa State.9.319409512.44379
AKWA IBOMNYSC Permanent Orientation Camp, Ikot Itie Udung, Nsit Atai Local Government Area, Akwa Ibom State.4.87575718.0566907
ANAMBRANYSC Permanent Orientation Camp, Progressive Senior Secondary School, Umunya, Oyi Local Government Area, Anambra State.9.319409512.44379
BAUCHINYSC Permanent Orientation camp, KM 60 Wailo, Ganjuwa Local Government Council, bauchi State10.67796510.2141584
BAYELSAKaiama Grammar School , Kaiama, Kolokuma/Opokuma L.G.A Kaiama Grammar School, Kaiama, Kolokoma-Opokuma Local Government Area, Bayelsa State.5.1141996.3017795
BENUENYSC Permanent Orientation Camp, Wannune, Tarka Local Government Area, Kilometer 35 Makurdi Gboko Road, Benue State.7.5623978.885954
BORNOCollege of Peace and Disaster Management, Nigeria Security and Civil Defence Corps (NSCDC) Babbar-Ruga Batsari Road Katsina, Katsina State..12.94872797.5641972
CROSS RIVERNYSC Permanent Orientation Camp, Obubra, Obubra Local Government Area, Cross River State.6.053528.3481402
DELTANYSC Permanent Orientation Camp Former Martins TTC, Issele-Uku, Aniocha North L.G.A. Delta State.6.32622776.4675429
EBONYINYSC Permanent Orientation Camp, Macgregor College, Afikpo Local Government Area, Ebonyi State.5.89018947.9129615
EDOOkada Grammar School, Okada, Ovia North-East Local Government Area, Edo State.6.73625.3956
EKITINYSC Permanent Orientation Camp, Ise-Orun/Emure Local Government Area, Ekiti State.7.44981115.4426537
ENUGUNYSC Permanent Orientation Camp, Awgu Local Government Area, Enugu State.6.08232797.4756086
FCT - ABUJANYSC Permanent Orientation Camp, Kubwa, Bwari Area Council, FCT.9.28559027.3786689
GOMBENYSC Temporary Orientation Camp, Science Technical College, Amada, KM 21, Gombe-Bauchi Highway, Near International Airport, Gombe State.10.27914211.1730615
IMONYSC Temporary Orientation Camp Former Girl's Model Secondary School Eziama Obaire Nkwerre Local Govt Area, Imo State.5.74398167.0841656
JIGAWANYSC Permanent Camp, opposite Army Barrack, Fanisua Dutse Local Government Area, Jigawa State.11.70235129.3340158
KADUNANYSC Permanent Orientation Camp, Kaduna - Abuja Road, Kaduna State.10.30584877.377495
KANONYSC Permanent Orientation Camp, Kusala Dam, Karaye, Karaye Local Government, Kano State.11.81696578.026064
KATSINAYouth Multi-purpose Centre/ NYSC Permanent Orientation Camp, Mani Road, Katsina State.12.96639047.6504732
KEBBINYSC Permanent Orientation Camp, Dakingari Local Government Area, Kebbi State.11.64979944.0644352
KOGINYSC Permanent Orientation Camp, Asaya, Kabba Local Government Area, Kogi State.7.81700656.0445542
KWARANYSC Permanent Orientation Camp, Yikpata, Edu Local Government Area, Kwara State.8.82739465.0891534
LAGOSNYSC Permanent Orientation Camp, Iyana Ipaja, Agege, Lagos State.6.62517923.3031169
NASSARAWAMagaji Dan-Yamusa Permanent Orientation Camp, Keffi, Nasarawa State.8.85406447.8568209
NIGERNYSC Permanent Orientation Camp, (Former Abubakar, Dada Senior Secondary School) Paiko, Niger State.9.45729586.6371426
OGUNNYSC Permanent Orientation Camp, Ikenne Road, Sagamu Local Government Area, Sagamu, Ogun State.6.86128613.6708377
ONDONYSC Permanent Orientation Camp, Ikare-Akoko Local Government Area, Ondo State.7.52143075.7361246
OSUNNYSC Permanent Orientation Camp, Aisu College Hospital Road, Ede North Local Government Area, Ede, Osun State.7.73492784.4439365
OYOGovernment Technical College, Iseyin Local Government Area, Iseyin, Oyo State.7.97878533.5858774
PLATEAUNYSC Permanent Orientation Camp, Mangu, Mangu Local Government Area, Plateau State.9.51284329.0449141
RIVERSNYSC Permanent Orientation Camp, Nonwa-Gbam Tai Local Government Area, Rivers State.4.73862257.226826
SOKOTONYSC Permanent Orientation Camp, Wamakko,Wamakko Local Govt Area, Sokoto State.13.03407265.1240515
TARABANYSC Permanent Orientation Camp, Sibre Airport Road, Jalingo, Taraba State.8.916821511.3192288
YOBECollege of Administration and Business Studies, Potiskum, Yobe State.11.722902411.0709143
ZAMFARANYSC Permanent Orientation Camp, Beside FRSC Office, Tsafe Local Government Area, Zamfara State.11.9737196.9106471



Map showing location of the Camps




Map showing location of the Camps with Google Maps Background




Tuesday, April 14, 2020

My First-Time Experience with ArcGIS Pro

Haven being a user of ArcGIS/ArcMap desktop software for many years, I recently decided to try out the newest generation of ESRI mapping product the 'ArcGIS Pro'.

Since the software license was beyond my current budget, I made my mind to explore the software by enrolling on one of their free Mass Open Online Classes (MOOC) titled "Spatial Data Science: The New Frontier in Analytics". The software used for the MOOC was 'ArcGIS Pro'!

Here below are my experience lists.


Let get started!

1) It is cloud based and requires Username/password to access the 'ArcGIS Pro' Esri software. When launch the software for the first time, after download and installing it you will have to login or you wont be able to proceed using it.





If your PC is not connected to the internet, the screen below (licensing page) pops-up and you have to select the right license type to login.


In fact, this software will auto close itself if you used for 24 hours without internet connection.


It is always happy when you are connected to its licensing portal and it will continue to work normally!



Wednesday, April 8, 2020

Python Command Line Argument - Parse variable value at run-time


If you have been writing python command line scripts, chances are you will want to make your script interactive with on the command line.

For example, you will want to set values for some variables at every start of the script. So, instead of editing the script directly, python provides module to help you define the variable at the point of running the script.

There are several modules for doing this, but we will talk about the Python argparse module.

In the script below for example, we did like to change the values of the variables "x and y" each time we want to add new set of values as seen in the script. So, each time we have to edit the script from the text editor before running it.

x = 9
y = 0

print(x + y)



It would be great if we can specify new variables directly on the command line each time we run the script without editing the script directly. This is where 'Command Line Argument' comes to play.

Lets modify the script so it uses command line interface with the Python argparse library.

There are basically five steps involved as listed below:-
1. Import 'argparse' library
2. Create the parser object
3. Add optional, required or positional arguments to the parser
4. Execute to create dictionary collection of the values using .parse_args() method
5. Use the values from the dictionary

#1. Import 'argparse' library
import argparse

#2. Create the parser object
parser = argparse.ArgumentParser()

#3. Add optional, required or positional arguments to the parser
parser.add_argument("-x", "--x_variable", type=int, required=True, help="X numeric value")
parser.add_argument("-y", "--y_variable", type=int, required=True, help="Y numeric value")

#4. Execute to create dictionary collection of the values using .parse_args()
args = vars(parser.parse_args())


# 5. Use the values from the dictionary
x = args['x_variable']
y = args['y_variable']

print(x + y)