Bash scripting Tutorial

Writing Readable Bash Scripts

#!/bin/bash

set -u
set -e
set -o pipefail

function is-even {
    if [[ $(($1 % 2)) -gt 0 ]]
    then return 1
    else return 0
    fi
}

function epoch {
    date +"%s"
}

if is-even $(epoch)
then echo "Even epoch"
else echo "Odd epoch"
fi

===============================================
set -u will cause the script to fail if you’re trying to reference a variable that hasn’t been set. The default behavior will just evaluate the variable to the empty string.

set -e will cause the script to exit immediately if a command fails. The default behavior is to simply continue executing the remaining commands in the script.

set -o pipefail will cause a pipeline to fail if any of the commands in the pipeline failed. The default behavior is to only use the exit status of the last command.

Passing arguments to the bash script

#!/bin/bash
# use predefined variables to access passed arguments
#echo arguments to the shell
echo $1 $2 $3 ' -> echo $1 $2 $3'

# We can also store arguments from bash command line in special array
args=("$@")
#echo arguments to the shell
echo ${args[0]} ${args[1]} ${args[2]} ' -> args=("$@"); echo ${args[0]} ${args[1]} ${args[2]}'

#use $@ to print out all arguments at once
echo $@ ' -> echo $@'

# use $# variable to print out
# number of arguments passed to the bash script
echo Number of arguments passed: $# ' -> echo Number of arguments passed: $#' 

Reading User Input

#!/bin/bash
 
echo -e "Hi, please type the word: \c "
read  word
echo "The word you entered is: $word"
echo -e "Can you please enter two words? "
read word1 word2
echo "Here is your input: \"$word1\" \"$word2\""
echo -e "How do you feel about bash scripting? "
# read command now stores a reply into the default build-in variable $REPLY
read
echo "You said $REPLY, I'm glad to hear that! "
echo -e "What are your favorite colours ? "
# -a makes read command to read into an array
read -a colours
echo "My favorite colours are also ${colours[0]}, ${colours[1]} and ${colours[2]}:-)" 

Declare simple bash array

#!/bin/bash
#Declare array with 4 elements
ARRAY=( 'Debian Linux' 'Redhat Linux' Ubuntu Linux )
# get number of elements in the array
ELEMENTS=${#ARRAY[@]}

# echo each element in array 
# for loop
for (( i=0;i<$ELEMENTS;i++)); do
    echo ${ARRAY[${i}]}
done 

Read file into bash array

#!/bin/bash
# Declare array
declare -a ARRAY
# Link filedescriptor 10 with stdin
exec 10<&0
# stdin replaced with a file supplied as a first argument
exec < $1
let count=0

while read LINE; do

    ARRAY[$count]=$LINE
    ((count++))
done

echo Number of elements: ${#ARRAY[@]}
# echo array's content
echo ${ARRAY[@]}
# restore stdin from filedescriptor 10
# and close filedescriptor 10
exec 0<&10 10<&-

Bash if / else / fi statements

1. Simple Bash if/else statement
#!/bin/bash
directory="./BashScripting"

# bash check if directory exists
if [ -d $directory ]; then
	echo "Directory exists"
else 
	echo "Directory does not exists"
fi 

2. Nested if/else
#!/bin/bash
 
# Declare variable choice and assign value 4
choice=4
# Print to stdout
 echo "1. Bash"
 echo "2. Scripting"
 echo "3. Tutorial"
 echo -n "Please choose a word [1,2 or 3]? "
# Loop while the variable choice is equal 4
# bash while loop
while [ $choice -eq 4 ]; do
 
# read user input
read choice
# bash nested if/else
if [ $choice -eq 1 ] ; then
 
        echo "You have chosen word: Bash"

else                   

        if [ $choice -eq 2 ] ; then
                 echo "You have chosen word: Scripting"
        else
         
                if [ $choice -eq 3 ] ; then
                        echo "You have chosen word: Tutorial"
                else
                        echo "Please make a choice between 1-3 !"
                        echo "1. Bash"
                        echo "2. Scripting"
                        echo "3. Tutorial"
                        echo -n "Please choose a word [1,2 or 3]? "
                        choice=4
                fi   
        fi
fi
done 

Bash Comparisons

1. Arithmetic Comparisons
-lt	<
-gt	>
-le	<=
-ge	>=
-eq	==
-ne	!=
#!/bin/bash
# declare integers
NUM1=2
NUM2=2
if [ $NUM1 -eq $NUM2 ]; then
	echo "Both Values are equal"
else 
	echo "Values are NOT equal"
fi 

2. String Comparisons
=	equal
!=	not equal
<	less then
>	greater then
-n s1	string s1 is not empty
-z s1	string s1 is empty
#!/bin/bash
#Declare string S1
S1="Bash"
#Declare string S2
S2="Scripting"
if [ $S1 = $S2 ]; then
	echo "Both Strings are equal"
else 
	echo "Strings are NOT equal"
fi 

Bash File Testing

-b filename	Block special file
-c filename	Special character file
-d directoryname	Check for directory existence
-e filename	Check for file existence
-f filename	Check for regular file existence not a directory
-G filename	Check if file exists and is owned by effective group ID.
-g filename	true if file exists and is set-group-id.
-k filename	Sticky bit
-L filename	Symbolic link
-O filename	True if file exists and is owned by the effective user id.
-r filename	Check if file is a readable
-S filename	Check if file is socket
-s filename	Check if file is nonzero size
-u filename	Check if file set-ser-id bit is set
-w filename	Check if file is writable
-x filename	Check if file is executable
#!/bin/bash
file="./file"
if [ -e $file ]; then
	echo "File exists"
else 
	echo "File does not exists"
fi 

#!/bin/bash
 
while [ ! -e myfile ]; do
# Sleep until file does exists/is created
sleep 1
done 

Bash for/while/until loop

#!/bin/bash
# bash for loop
for f in $( ls /var/ ); do
	echo $f
done 

#!/bin/bash
COUNT=6
# bash while loop
while [ $COUNT -gt 0 ]; do
	echo Value of count is: $COUNT
	let COUNT=COUNT-1
done 

#!/bin/bash
COUNT=0
# bash until loop
until [ $COUNT -gt 5 ]; do
        echo Value of count is: $COUNT
        let COUNT=COUNT+1
done 

Bash Functions

!/bin/bash
# BASH FUNCTIONS CAN BE DECLARED IN ANY ORDER
function function_B {
        echo Function B.
}
function function_A {
        echo $1
}
function function_D {
        echo Function D.
}
function function_C {
        echo $1
}
# FUNCTION CALLS
# Pass parameter to function A
function_A "Function A."
function_B
# Pass parameter to function C
function_C "Function C."
function_D 

Bash Select

#!/bin/bash
 
PS3='Choose one word: ' 

# bash select
select word in "linux" "bash" "scripting" "tutorial" 
do
  echo "The word you have selected is: $word"
# Break, otherwise endless loop
  break  
done

exit 0 

Case statement conditional

#!/bin/bash
echo "What is your preferred programming / scripting language"
echo "1) bash"
echo "2) perl"
echo "3) phyton"
echo "4) c++"
echo "5) I do not know !"
read case;
#simple case bash structure
# note in this case $case is variable and does not have to
# be named case this is just an example
case $case in
    1) echo "You selected bash";;
    2) echo "You selected perl";;
    3) echo "You selected phyton";;
    4) echo "You selected c++";;
    5) exit
esac 

Bash quotes and quotations
Quotations and quotes are important part of bash and bash scripting. Here are some bash quotes and quotations basics.
Escaping Meta characters
Before we start with quotes and quotations we should know something about escaping meta characters. Escaping will suppress a special meaning of meta characters and therefore meta characters will be read by bash literally. To do this we need to use backslash “\” character. Example:

#!/bin/bash
 #Declare bash string variable
BASH_VAR="Bash Script"
# echo variable BASH_VAR
echo $BASH_VAR
#when meta character such us "$" is escaped with "\" it will be read literally
echo $BASH_VAR 
# backslash has also special meaning and it can be suppressed with yet another "\"
echo "\" 

Single quotes
Single quotes in bash will suppress special meaning of every meta characters. Therefore meta characters will be read literally. It is not possible to use another single quote within two single quotes not even if the single quote is escaped by backslash.

#!/bin/bash
 
 #Declare bash string variable
 BASH_VAR="Bash Script"
 
 # echo variable BASH_VAR
 echo $BASH_VAR
 
 # meta characters special meaning in bash is suppressed when  using single quotes 
 echo '$BASH_VAR  "$BASH_VAR"' 

Double Quotes
Double quotes in bash will suppress special meaning of every meta characters except “$”, “\” and “`”. Any other meta characters will be read literally. It is also possible to use single quote within double quotes. If we need to use double quotes within double quotes bash can read them literally when escaping them with “\”. Example:

#!/bin/bash
 
#Declare bash string variable
BASH_VAR="Bash Script"

# echo variable BASH_VAR
echo $BASH_VAR

# meta characters and its special meaning in bash is 
# suppressed when using double quotes except "$", "\" and "`"

echo "It's $BASH_VAR  and \"$BASH_VAR\" using backticks: `date`" 

Arithmetic Operations

echo '### Bash Arithmetic Expansion ###'
# There are two formats for arithmetic expansion: $[ expression ] 
# and $(( expression #)) its your choice which you use

echo 4 + 5 = $((4 + 5))
echo 7 - 7 = $[ 7 - 7 ]
echo 4 x 6 = $((3 * 2))
echo 6 / 3 = $((6 / 3))
echo 8 % 7 = $((8 % 7))
echo 2 ^ 8 = $[ 2 ** 8 ]


echo '### Declare ###'

echo -e "Please enter two numbers \c"
# read user input
read num1 num2
declare -i result
result=$num1+$num2
echo "Result is:$result "

# bash convert binary number 10001
result=2#10001
echo $result

# bash convert octal number 16
result=8#16
echo $result

# bash convert hex number 0xE6A
result=16#E6A
echo $result 

Round floating point number:
#!/bin/bash
# get floating point number
floating_point_number=3.3446
echo $floating_point_number
# round floating point number with bash
for bash_rounded_number in $(printf %.0f $floating_point_number); do
echo "Rounded number with bash:" $bash_rounded_number
done 

bash script search string and delete the line above

we search a string "test" in file.txt file, then delete its line above.
 hans@testvm:~ $ cat ./del_line_above.sh
#!/bin/bash
line_number="$(grep -n 'test' file.txt| cut -d: -f1)"
line_number_above="$((line_number - 1))"
sed "${line_number_above}d" file.txt

 hans@testvm:~ $ cat file.txt
aadsfasfda
line 1
line 2
line 3
line 4
test
java
hans@testvm:~ $ ./del_line_above.sh
aadsfasfda
line 1
line 2
line 3
test
java

Through the forest – Adam’s first poem

Sometimes I sit and wander through the forest ,
Think about humanity and how we’ve grown.
Sit and Learn to our heart desire, but then comes the moan.

Everyone hears, it haunts more then once a life,
A moan of struggles, that echoes through a pipe.

It sends a waves of a hunger for war, forcing everyone to write to their dears.
Then the moan turns into sobbing, representing the world’s tears.

The moan is of pure misery, from the depths of Tautrous herself.
Making people furious and then crumble and melt.
People start as saplings easy to break and bend. They grow, then break in two and snap.

Then I look at the great tree, standing tall and proud.
Looking down at their many branches grown each by themselves.

It only needed a can of water, a trinkle of effort.
To stand as high as the sky, tall and bold.

Looking between the two, sapling and great oak.
One prepared to snap, the other could support a boat.

Makes me wonder, what’s the difference between giants and an elf.
Then I realize that it’s only what people see in them, and what they see in themselves.

TAOBAO login with selenium and pyautogui

there are two challenges during taobao.com login:
1. sometimes the site will ask you pull the slider
resolved with Selenium ActionChains
2. taobao disabled selenium click()
resolved with pyautogui lib:
pip install pyautogui
here is the code for taobao.com login:

from selenium import webdriver
import logging
import time
from selenium.common.exceptions import NoSuchElementException, WebDriverException
from retrying import retry
from selenium.webdriver import ActionChains

import pyautogui
pyautogui.PAUSE = 0.5 

logging.basicConfig(level = logging.INFO,format = '%(asctime)s - %(name)s - %(levelname)s - %(message)s')
logger = logging.getLogger(__name__)

class taobao():
    def __init__(self):
        self.browser = webdriver.Chrome("path\to\your\chromedriver.exe")
        self.browser.maximize_window()
        self.browser.implicitly_wait(5)
        self.domain = 'http://www.taobao.com'
        self.action_chains = ActionChains(self.browser)

    def login(self, username, password):
        while True:
            self.browser.get(self.domain)
            time.sleep(1)

            #self.browser.find_element_by_class_name('h').click()
            #self.browser.find_element_by_id('fm-login-id').send_keys(username)
            #self.browser.find_element_by_id('fm-login-password').send_keys(password)
            self.browser.find_element_by_xpath('//*[@id="J_SiteNavLogin"]/div[1]/div[1]/a[1]').click()
            self.browser.find_element_by_xpath('//*[@id="fm-login-id"]').send_keys(username)
            self.browser.find_element_by_xpath('//*[@id="fm-login-password"]').send_keys(password)
            time.sleep(1)

            try:
                # using Selenium ActionChains for the website SLIDE authentication
                slider = self.browser.find_element_by_xpath("//span[contains(@class, 'btn_slide')]")
                if slider.is_displayed():
                    # pull the slider
                    self.action_chains.drag_and_drop_by_offset(slider, 258, 0).perform()
                    time.sleep(0.5)
                    # release the slider
                    self.action_chains.release().perform()
            except (NoSuchElementException, WebDriverException):
                logger.info('slider not found')

            # using pyautogui click the LOGIN PNG image
            #self.browser.find_element_by_class_name('password-login').click()
            #self.browser.find_element_by_xpath('//*[@id="login-form"]/div[4]/button').click()
             coords = pyautogui.locateOnScreen('1.png')
            x, y = pyautogui.center(coords)
            pyautogui.leftClick(x, y)

            nickname = self.get_nickname()
            if nickname:
                logger.info('successfully logon, nickname is' + nickname)
                break
            logger.debug('login failed,please try again after 5 seconds')
            time.sleep(5)

    def get_nickname(self):
        self.browser.get(self.domain)
        time.sleep(0.5)
        try:
            return self.browser.find_element_by_class_name('site-nav-user').text
        except NoSuchElementException:
            return ''


if __name__ == '__main__':
    # Input your TAOBAO username and password
    username = 'username'
    password = 'password'
    tb = taobao()
    tb.login(username, password)

Complete Django/MySQL CRUD Operations

Learned from CodAffection online course, code has been staged on github:
https://github.com/zhuby1973/python/tree/master/employee_project

we need pip install django-crispy-forms for this project.
1. django-admin startproject employee_project
2. python manage.py runserver
3. python manage.py startapp employee_register
edit settings.py, urls.py, views.py and models.py, then run migrate command to create tables:
python manage.py migrate
python manage.py makemigrations employee_register
python manage.py sqlmigrate employee_register 0001
python manage.py sqlmigrate employee_register 0002
python manage.py migrate
python manage.py createsuperuser (create admin user and verify in admin page)
you can verify the tables in MySQL.

# this is employee_register/views.py:
from django.shortcuts import render,redirect
from .forms import EmployeeForm, RegisterForm
from .models import Employee
import os
from django.conf import settings
from django.contrib import messages
#from django.contrib.auth import login, authenticate
#from django.contrib.auth.forms import UserCreationForm

# Create your views here.
def register(request):
    registerForm = RegisterForm(request.POST or None)
    if request.method == "POST":
        if registerForm.is_valid():
            registerForm.is_staff = True
            registerForm.save()

    return render(request, "registration/register.html", {"form": registerForm})

def employee_list(request):
    print (settings.BASE_DIR)
    context = {'employee_list':Employee.objects.all()}
    return render(request,"employee_register/employee_list.html",context)

def employee_form(request, id=0):
    if request.method == "GET":
        if id == 0:
            form = EmployeeForm()
        else:
            employee = Employee.objects.get(id=id)
            form = EmployeeForm(instance=employee)
        return render(request,"employee_register/employee_form.html",{'form':form})
    else:
        if id == 0:
            form = EmployeeForm(request.POST or None, request.FILES or None)
        else:
            employee = Employee.objects.get(id=id)
            employee.image.delete()
            form = EmployeeForm(request.POST or None, request.FILES or None, instance = employee)

        if form.is_valid():
            form.save()
            if id == 0:
                messages.success(request, "Employee Record Added Successfully!")
            else:
                messages.info(request,"Employee Record Updated Successfully!")

        return redirect("/employee/list")


def employee_delete(request,id):
    employee = Employee.objects.get(id=id)
    employee.delete()
    messages.error(request, 'Employee Record Deleted Successfully!')

    return redirect('/employee/list')

create Web Service with FastAPI and uvicorn

  1. pip install fastapi
  2. pip install uvicorn
    code main.py:
from fastapi import FastAPI
from pydantic import BaseModel
app = FastAPI()
class People(BaseModel):
    name: str
    age: int
    address: str = None
@app.post('/insert')
def insert(people: People):
    age_after_10_years = people.age + 10
    msg = f'Name: {people.name},age after ten years:{age_after_10_years}'
    return {'success': True, 'msg': msg}
@app.get('/')
def index():
    return {'message': 'Hi, this is your FastApi service!'}

run command: uvicorn main:app --reload, then you can access docs
http://127.0.0.1:8000/docs, you can test POST/GET as below or test it with Postman.

create Django web app with MySQL

read https://docs.djangoproject.com/en/3.0/intro/tutorial01/, you can start a new project and app:
1. django-admin startproject mysite
2. python manage.py runserver
3. python manage.py startapp polls
4. edit polls/views.py and urls.py
5. edit mysite/urls.py and settings.py to include MySQL db info:

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.mysql',
        'NAME': 'EmployeeDB',
        'USER': 'monty',
        'PASSWORD': 'somIUpass#98',
        'HOST': '192.168.0.28'
    }
}

polls/models.py:
from django.db import models
class Question(models.Model):
    question_text = models.CharField(max_length=200)
    pub_date = models.DateTimeField('date published')
class Choice(models.Model):
    question = models.ForeignKey(Question, on_delete=models.CASCADE)
    choice_text = models.CharField(max_length=200)
    votes = models.IntegerField(default=0)
PS C:\Users\zhuby\mysite>  python manage.py migrate
Operations to perform:
  Apply all migrations: admin, auth, contenttypes, sessions
Running migrations:
  Applying contenttypes.0001_initial... OK
  Applying auth.0001_initial... OK
  Applying admin.0001_initial... OK
  Applying admin.0002_logentry_remove_auto_add... OK
  Applying admin.0003_logentry_add_action_flag_choices... OK
  Applying auth.0002_alter_permission_name_max_length... OK
  Applying auth.0003_alter_user_email_max_length... OK
  Applying auth.0004_alter_user_username_opts... OK
  Applying auth.0005_alter_user_last_login_null... OK
  Applying auth.0007_alter_validators_add_error_messages... OK
  Applying auth.0008_alter_user_username_max_length... OK
  Applying auth.0009_alter_user_last_name_max_length... OK
  Applying auth.0010_alter_group_name_max_length... OK
  Applying auth.0011_update_proxy_permissions... OK
  Applying sessions.0001_initial... OK
PS C:\Users\zhuby\mysite> python manage.py makemigrations polls
Migrations for 'polls':
  polls\migrations\0001_initial.py
    - Create model Choice
PS C:\Users\zhuby\mysite> python manage.py sqlmigrate polls 0001
--
-- Create model Question
CREATE TABLE `polls_question` (`id` integer AUTO_INCREMENT NOT NULL PRIMARY KEY, `question_text` varchar(200) NOT NULL, `pub_date` datetime(6) NOT NULL);
--
-- Create model Choice
--
CREATE TABLE `polls_choice` (`id` integer AUTO_INCREMENT NOT NULL PRIMARY KEY, `choice_text` varchar(200) NOT NULL, `votes` integer NOT NULL, `question_id` integer NOT NULL);
ALTER TABLE `polls_choice` ADD CONSTRAINT `polls_choice_question_id_c5b4b260_fk_polls_question_id` FOREIGN KEY (`question_id`) REFERENCES `polls_question` (`id`);
PS C:\Users\zhuby\mysite> python manage.py migrate
Operations to perform:
  Apply all migrations: admin, auth, contenttypes, polls, sessions
Running migrations:
  Applying polls.0001_initial... OK

You can check the code from https://github.com/zhuby1973/python/tree/master/mysite with "git checkout part2"

few examples from matplotlib

# sphinx_gallery_thumbnail_number = 2
import numpy as np
import matplotlib.pyplot as plt
N = 21
x = np.linspace(0, 10, 11)
y = [3.9, 4.4, 10.8, 10.3, 11.2, 13.1, 14.1,  9.9, 13.9, 15.1, 12.5]

# fit a linear curve an estimate its y-values and their error.
a, b = np.polyfit(x, y, deg=1)
y_est = a * x + b
y_err = x.std() * np.sqrt(1/len(x) +
                          (x - x.mean())**2 / np.sum((x - x.mean())**2))

fig, ax = plt.subplots()
ax.plot(x, y_est, '-')
ax.fill_between(x, y_est - y_err, y_est + y_err, alpha=0.2)
ax.plot(x, y, 'o', color='tab:brown')
plt.savefig('confidence.jpg')
plt.show()
"""
============
MRI With EEG
============

Displays a set of subplots with an MRI image, its intensity
histogram and some EEG traces.
"""

import numpy as np
import matplotlib.pyplot as plt
import matplotlib.cbook as cbook
import matplotlib.cm as cm

from matplotlib.collections import LineCollection
from matplotlib.ticker import MultipleLocator

fig = plt.figure("MRI_with_EEG")

# Load the MRI data (256x256 16 bit integers)
with cbook.get_sample_data('s1045.ima.gz') as dfile:
    im = np.frombuffer(dfile.read(), np.uint16).reshape((256, 256))

# Plot the MRI image
ax0 = fig.add_subplot(2, 2, 1)
ax0.imshow(im, cmap=cm.gray)
ax0.axis('off')

# Plot the histogram of MRI intensity
ax1 = fig.add_subplot(2, 2, 2)
im = np.ravel(im)
im = im[np.nonzero(im)]  # Ignore the background
im = im / (2**16 - 1)  # Normalize
ax1.hist(im, bins=100)
ax1.xaxis.set_major_locator(MultipleLocator(0.4))
ax1.minorticks_on()
ax1.set_yticks([])
ax1.set_xlabel('Intensity (a.u.)')
ax1.set_ylabel('MRI density')

# Load the EEG data
n_samples, n_rows = 800, 4
with cbook.get_sample_data('eeg.dat') as eegfile:
    data = np.fromfile(eegfile, dtype=float).reshape((n_samples, n_rows))
t = 10 * np.arange(n_samples) / n_samples

# Plot the EEG
ticklocs = []
ax2 = fig.add_subplot(2, 1, 2)
ax2.set_xlim(0, 10)
ax2.set_xticks(np.arange(10))
dmin = data.min()
dmax = data.max()
dr = (dmax - dmin) * 0.7  # Crowd them a bit.
y0 = dmin
y1 = (n_rows - 1) * dr + dmax
ax2.set_ylim(y0, y1)

segs = []
for i in range(n_rows):
    segs.append(np.column_stack((t, data[:, i])))
    ticklocs.append(i * dr)

offsets = np.zeros((n_rows, 2), dtype=float)
offsets[:, 1] = ticklocs

lines = LineCollection(segs, offsets=offsets, transOffset=None)
ax2.add_collection(lines)

# Set the yticks to use axes coordinates on the y axis
ax2.set_yticks(ticklocs)
ax2.set_yticklabels(['PG3', 'PG5', 'PG7', 'PG9'])

ax2.set_xlabel('Time (s)')


plt.tight_layout()
plt.show()
"""
===============
Watermark image
===============

Using a PNG file as a watermark.
"""

import numpy as np
import matplotlib.cbook as cbook
import matplotlib.image as image
import matplotlib.pyplot as plt


with cbook.get_sample_data('logo2.png') as file:
    im = image.imread(file)

fig, ax = plt.subplots()

ax.plot(np.sin(10 * np.linspace(0, 1)), '-o', ms=20, alpha=0.7, mfc='orange')
ax.grid()
fig.figimage(im, 10, 10, zorder=3, alpha=.5)
plt.savefig('watermark.jpg')
plt.show()

#############################################################################
#
# ------------
#
# References
# """"""""""
#
# The use of the following functions, methods, classes and modules is shown
# in this example:

import matplotlib
matplotlib.image
matplotlib.image.imread
matplotlib.pyplot.imread
matplotlib.figure.Figure.figimage
"""
======================
Whats New 0.99 Mplot3d
======================

Create a 3D surface plot.
"""
import numpy as np
import matplotlib.pyplot as plt
from matplotlib import cm
from mpl_toolkits.mplot3d import Axes3D

X = np.arange(-5, 5, 0.25)
Y = np.arange(-5, 5, 0.25)
X, Y = np.meshgrid(X, Y)
R = np.sqrt(X**2 + Y**2)
Z = np.sin(R)

fig = plt.figure()
ax = Axes3D(fig)
ax.plot_surface(X, Y, Z, rstride=1, cstride=1, cmap=cm.viridis)
plt.savefig('Axes3D.jpg')
plt.show()

#############################################################################
#
# ------------
#
# References
# """"""""""
#
# The use of the following functions, methods, classes and modules is shown
# in this example:

import mpl_toolkits
mpl_toolkits.mplot3d.Axes3D
mpl_toolkits.mplot3d.Axes3D.plot_surface

data visualization for US firearm background checks

we can download nics-firearm-background-checks.csv from https://github.com/BuzzFeedNews/nics-firearm-background-checks/tree/master/data
and put it in same folder with firearm_background.py:

#!/usr/bin/env python
import sys, os
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sb
sb.set()

checks = pd.read_csv('nics-firearm-background-checks.csv')

checks["year_int"] = checks["month"].apply(lambda x: int(x.split("-")[0]))
checks["month_int"] = checks["month"].apply(lambda x: int(x.split("-")[1]))

latest_month_count = checks.iloc[0]["month_int"] + (checks.iloc[0]["year_int"] * 12)

totals = checks[
    (checks["month_int"] + (checks["year_int"] * 12)) > (latest_month_count - 12*3)
].groupby("month")["totals"].sum()
tick_placement = np.arange(len(totals) - 1, 0, -3)

ax = totals.plot(kind="area", figsize=(12, 8), color="#000000", alpha=0.5)
ax.figure.set_facecolor("#FFFFFF")
ax.set_title("NICS Background Check Totals — Past 36 Months", fontsize=24)
ax.set_yticklabels([ "{0:,.0f}".format(y) for y in ax.get_yticks() ], fontsize=12)
ax.set_xticks(tick_placement)
ax.set_xticklabels([ totals.index[i] for i in tick_placement ])
ax.set_xlim(0, len(totals) - 1)
plt.setp(ax.get_xticklabels(), rotation=0, fontsize=12)
ax.set_xlabel("")

plt.savefig('image.jpg')
plt.show()

run the firearm_background.py, you will get image.jpg(default is png format, you need pip install pillow for saving as jpg format) saved and displayed:

Install Anaconda and jupyter notebook on Ubuntu 20

1. download and install latest Anaconda
curl -O https://repo.anaconda.com/archive/Anaconda3-2020.02-Linux-x86_64.sh
bash Anaconda3-2020.02-Linux-x86_64.sh
2. Activate and test Installation
~~source ~/.bashrc
conda list
3. install nodejs ~~
(base) ubuntu@ubunu2004:~$ conda install -c conda-forge nodejs
4. Set Up Anaconda Environments
conda create –name my_env python=3
conda activate my_env
5. install jupyter and matplotlib
pip install jupyter
pip install matplotlib
6. start jupyter notebook
(my_env) ubuntu@ubunu2004:~$ jupyter notebook
[I 15:45:31.229 NotebookApp] Writing notebook server cookie secret to /home/ubuntu/.local/share/jupyter/runtime/notebook_cookie_secret
[I 15:45:33.363 NotebookApp] Serving notebooks from local directory: /home/ubuntu
[I 15:45:33.365 NotebookApp] The Jupyter Notebook is running at:
[I 15:45:33.366 NotebookApp] http://localhost:8888/?token=d477ec6ca56d2382cc3f87392a06a8a6000a3aba2d367fc8
[I 15:45:33.372 NotebookApp] or http://127.0.0.1:8888/?token=d477ec6ca56d2382cc3f87392a06a8a6000a3aba2d367fc8
[I 15:45:33.373 NotebookApp] Use Control-C to stop this server and shut down all kernels (twice to skip confirmation).
7. create new sample.py code in jupyter notebook:
open http://localhost:8888/?token=d477ec6ca56d2382cc3f87392a06a8a6000a3aba2d367fc8 and create sample.py code:

import matplotlib.pyplot as plt; plt.rcdefaults()
import numpy as np
import matplotlib.pyplot as plt

objects = ('Python', 'C++', 'Java', 'Perl', 'Scala', 'Lisp')
y_pos = np.arange(len(objects))
performance = [10,8,6,4,2,1]

plt.bar(y_pos, performance, align='center', alpha=0.5)
plt.xticks(y_pos, objects)
plt.ylabel('Usage')
plt.title('Programming language usage')

plt.show()

Output:

  1. secure and bind jupyter on all IP
    (my_env) ubuntu@ubunu2004:~$ jupyter notebook –generate-config
    Writing default config to: /home/ubuntu/.jupyter/jupyter_notebook_config.py
    (my_env) ubuntu@ubunu2004:~$ jupyter notebook password
    Enter password:
    Verify password:
    [NotebookPasswordApp] Wrote hashed password to /home/ubuntu/.jupyter/jupyter_notebook_config.json
    {
    "NotebookApp": {
    "password": "sha1:de4ae15e9dcd:d32f371026e38a9241ec83a469de166b97ea60b7"
    }
    }

(my_env) ubuntu@ubunu2004:~$ openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout mykey.key -out mycert.pem
Generating a RSA private key ….

then you can vi /home/ubuntu/.jupyter/jupyter_notebook_config.py:

# Set options for certfile, ip, password, and toggle off
# browser auto-opening
c.NotebookApp.certfile = u'/home/ubuntu/mycert.pem'
c.NotebookApp.keyfile = u'/home/ubuntu/mykey.key'
# Set ip to '*' to bind on all interfaces (ips) for the public server
c.NotebookApp.ip = '*'
c.NotebookApp.password = u'sha1:de4ae15e9dcd:d32f371026e38a9241ec83a469de166b97ea60b7'
c.NotebookApp.open_browser = False

# It is a good idea to set a known, fixed port for server access
c.NotebookApp.port = 9999

start it with new port and binding:
(my_env) ubuntu@ubunu2004:~$ jupyter notebook
[I 16:48:20.227 NotebookApp] Serving notebooks from local directory: /home/ubuntu
[I 16:48:20.230 NotebookApp] The Jupyter Notebook is running at:
[I 16:48:20.230 NotebookApp] https://ubunu2004:9999/
Now you can open jupyter notebook from remote browser with your password!