CoCalc Public Filesatms391geodata / Week 2 / Homework 2: Lists and if statements (answer key).ipynb
Author: Steve Nesbitt
Views : 75
Compute Environment: Ubuntu 18.04 (Deprecated)

# ATMS 391: Geophysical data analysis

## Problem 1: using if statements to classify clouds

You have been hired by NASA to implement a cloud classification scheme based on their observed satellite characteristics. The International Cloud Climatology Project (Schiffer and Rossow 1983) classifies clouds using geostationary infrared data using the cloud top pressure and the cloud optical thickness, according to the following graphic:

Consider the following database of cloud observations:

Cloud pixel number Cloud top pressure (hPa) Cloud optical thickness (unitless)
1 917.3 47.1
2 282.9 0.6
3 316.5 72.7
4 242.6 8.4
5 362.9 32.5
6 264.0 52.1
7 276.3 178.2
8 75.4 203.0
9 858.4 161.2
10 566.3 2.4

Assume that the lines in the chart are the lower bound of each category, and do not include the values below that exact value.

(a) Classify each of the 10 cloud pixels into the 9 cloud types in the ISCCP classification. The classification must be done with a function (containing if-then-else statements). Print the observed data for each cloud and the classification in a table.

In [1]:
def classify(top_pressure, optical_thickness):
if (0 <= optical_thickness < 3.6):
if (680 <= top_pressure < 1000):
return 'Cumulus'
elif (440 <= top_pressure < 680):
return 'Altocumulus'
elif (50 <= top_pressure < 440):
return 'Cirrus'
else:
print('Invalid cloud type!')
return
elif (3.6 <= optical_thickness < 23):
if (680 <= top_pressure < 1000):
return 'Stratocumulus'
elif (440 <= top_pressure < 680):
return 'Altostratus'
elif (50 <= top_pressure < 440):
return 'Cirrostratus'
else:
print('Invalid cloud type!')
return
elif (23 <= optical_thickness < 379):
if (680 <= top_pressure < 1000):
return 'Stratus'
elif (440 <= top_pressure < 680):
return 'Nimbostratus'
elif (50 <= top_pressure < 440):
return 'Deep Convection'
else:
print('Invalid cloud type!')
return
else:
print('Invalid cloud type!')
return

cloud_types = ['Cumulus', 'Altocumulus', 'Cirrus', 'Stratocumulus', 'Altostratus',
'Cirrostratus', 'Stratus', 'Nimbostratus', 'Deep Convection']
pixel_numbers = range(1, 11)
pressure =  [917.3, 282.9, 316.5, 242.6, 362.9, 264.0, 276.3, 75.4,  858.4, 566.3]
thickness = [47.1,  0.6,   72.7,  8.4,   32.5,  52.1,  178.2, 203.0, 161.2, 2.4]
cloud_top_pressure = {cloud : [] for cloud in cloud_types} # for each cloud type, use a list to store the top pressure
cloud_optical_thickness = {cloud : [] for cloud in cloud_types} # for each cloud type, use a list to store the optical thickness

for pixel_num, pres, thick in zip(pixel_numbers, pressure, thickness): # zip() function combines the elements of the same positions from different lists together as a tuple
cloud_type = classify(pres, thick)
cloud_top_pressure[cloud_type].append(pres)
cloud_optical_thickness[cloud_type].append(thick)
print('Cloud pixel number %2d, pressure = %6.2f, thickness = %6.2f: cloud type = %s' %(pixel_num, pres, thick, cloud_type))

Cloud pixel number 1, pressure = 917.30, thickness = 47.10: cloud type = Stratus Cloud pixel number 2, pressure = 282.90, thickness = 0.60: cloud type = Cirrus Cloud pixel number 3, pressure = 316.50, thickness = 72.70: cloud type = Deep Convection Cloud pixel number 4, pressure = 242.60, thickness = 8.40: cloud type = Cirrostratus Cloud pixel number 5, pressure = 362.90, thickness = 32.50: cloud type = Deep Convection Cloud pixel number 6, pressure = 264.00, thickness = 52.10: cloud type = Deep Convection Cloud pixel number 7, pressure = 276.30, thickness = 178.20: cloud type = Deep Convection Cloud pixel number 8, pressure = 75.40, thickness = 203.00: cloud type = Deep Convection Cloud pixel number 9, pressure = 858.40, thickness = 161.20: cloud type = Stratus Cloud pixel number 10, pressure = 566.30, thickness = 2.40: cloud type = Altocumulus

(b) Write a function to count each cloud type. Print a table of the names of each cloud type and number of clouds in that class.

In [2]:
"""
you can use either cloud_top_pressure or cloud_optical_thickness,
the length of the value (which is a list) will be the number of clouds in that class
"""
def count(cloud_top_pressure):
for cloud in cloud_top_pressure.keys():
print('Cloud type = %16s,   number of clouds = %d' %(cloud, len(cloud_top_pressure[cloud])))

count(cloud_top_pressure)

Cloud type = Altocumulus, number of clouds = 1 Cloud type = Cirrostratus, number of clouds = 1 Cloud type = Altostratus, number of clouds = 0 Cloud type = Nimbostratus, number of clouds = 0 Cloud type = Cumulus, number of clouds = 0 Cloud type = Stratus, number of clouds = 2 Cloud type = Stratocumulus, number of clouds = 0 Cloud type = Deep Convection, number of clouds = 5 Cloud type = Cirrus, number of clouds = 1

(c) For each cloud type, print a table of the mean and standard deviation of each of the observed cloud top pressure and cloud optical thickness. Recreate the table you created in (b), and add column values to the table for this data. If no data exists, print 'none' in that entry.

In [3]:
import numpy as np

def stats(cloud_top_pressure, cloud_optical_thickness):
for cloud in cloud_top_pressure.keys():
if len(cloud_top_pressure[cloud]) == 0:
print('Cloud type = %16s,   number of clouds = %d, \
pressure mean = none, pressure std = none, \
thickness mean = none, thickness std = none' %(cloud, len(cloud_top_pressure[cloud])))
else:
pressure_mean = np.mean(cloud_top_pressure[cloud])
pressure_std = np.std(cloud_top_pressure[cloud])
thickness_mean = np.mean(cloud_optical_thickness[cloud])
thickness_std = np.std(cloud_optical_thickness[cloud])
print('Cloud type = %16s,   number of clouds = %d,'
' pressure mean = %5.2f, pressure std = %5.2f,'
' thickness mean = %5.2f, thickness std = %5.2f'
%(cloud, len(cloud_top_pressure[cloud]), pressure_mean, pressure_std, thickness_mean, thickness_std))

stats(cloud_top_pressure, cloud_optical_thickness)

Cloud type = Altocumulus, number of clouds = 1, pressure mean = 566.30, pressure std = 0.00, thickness mean = 2.40, thickness std = 0.00 Cloud type = Cirrostratus, number of clouds = 1, pressure mean = 242.60, pressure std = 0.00, thickness mean = 8.40, thickness std = 0.00 Cloud type = Altostratus, number of clouds = 0, pressure mean = none, pressure std = none, thickness mean = none, thickness std = none Cloud type = Nimbostratus, number of clouds = 0, pressure mean = none, pressure std = none, thickness mean = none, thickness std = none Cloud type = Cumulus, number of clouds = 0, pressure mean = none, pressure std = none, thickness mean = none, thickness std = none Cloud type = Stratus, number of clouds = 2, pressure mean = 887.85, pressure std = 29.45, thickness mean = 104.15, thickness std = 57.05 Cloud type = Stratocumulus, number of clouds = 0, pressure mean = none, pressure std = none, thickness mean = none, thickness std = none Cloud type = Deep Convection, number of clouds = 5, pressure mean = 259.02, pressure std = 98.12, thickness mean = 107.70, thickness std = 69.32 Cloud type = Cirrus, number of clouds = 1, pressure mean = 282.90, pressure std = 0.00, thickness mean = 0.60, thickness std = 0.00

## Problem 2: using dictionaries

(a) Create a dictionary variable that holds an array of the data in the table above. Structure the dictionary such that there is a dictionary entry for each column in the table above. Print the dictionary.

In [4]:
dictionary = {cloud : {} for cloud in cloud_types}

for cloud in dictionary:
if len(cloud_top_pressure[cloud]) == 0:
dictionary[cloud] = {'count':0, 'pressure_mean':None, 'pressure_std':None, 'thickness_mean':None, 'thickness_std':None}
else:
pressure_mean = np.mean(cloud_top_pressure[cloud])
pressure_std = np.std(cloud_top_pressure[cloud])
thickness_mean = np.mean(cloud_optical_thickness[cloud])
thickness_std = np.std(cloud_optical_thickness[cloud])
dictionary[cloud] = {'count':len(cloud_top_pressure[cloud]), 'pressure_mean':pressure_mean, 'pressure_std':pressure_std,
'thickness_mean':thickness_mean, 'thickness_std':thickness_std}
print cloud, dictionary[cloud]

Altocumulus {'count': 1, 'thickness_mean': 2.3999999999999999, 'pressure_mean': 566.29999999999995, 'pressure_std': 0.0, 'thickness_std': 0.0} Cirrostratus {'count': 1, 'thickness_mean': 8.4000000000000004, 'pressure_mean': 242.59999999999999, 'pressure_std': 0.0, 'thickness_std': 0.0} Altostratus {'count': 0, 'thickness_mean': None, 'pressure_mean': None, 'pressure_std': None, 'thickness_std': None} Nimbostratus {'count': 0, 'thickness_mean': None, 'pressure_mean': None, 'pressure_std': None, 'thickness_std': None} Cumulus {'count': 0, 'thickness_mean': None, 'pressure_mean': None, 'pressure_std': None, 'thickness_std': None} Stratus {'count': 2, 'thickness_mean': 104.14999999999999, 'pressure_mean': 887.84999999999991, 'pressure_std': 29.449999999999989, 'thickness_std': 57.049999999999997} Stratocumulus {'count': 0, 'thickness_mean': None, 'pressure_mean': None, 'pressure_std': None, 'thickness_std': None} Deep Convection {'count': 5, 'thickness_mean': 107.7, 'pressure_mean': 259.02000000000004, 'pressure_std': 98.116979162630159, 'thickness_std': 69.316289571788246} Cirrus {'count': 1, 'thickness_mean': 0.59999999999999998, 'pressure_mean': 282.89999999999998, 'pressure_std': 0.0, 'thickness_std': 0.0}

(b) Add a new key to the dictionary adding the cloud type name from Problem 1. Print the new dictionary.

In [6]:
# if you struct the dictionary as shown above, you already have the cloud type names.
# You can just add a undefined cloud type to show the insert operation
dictionary['Undefined'] = {'count':0, 'pressure_mean':None, 'pressure_std':None, 'thickness_mean':None, 'thickness_std':None}
for cloud in dictionary:
print cloud, dictionary[cloud]

Altocumulus {'count': 1, 'thickness_mean': 2.3999999999999999, 'pressure_mean': 566.29999999999995, 'pressure_std': 0.0, 'thickness_std': 0.0} Cirrostratus {'count': 1, 'thickness_mean': 8.4000000000000004, 'pressure_mean': 242.59999999999999, 'pressure_std': 0.0, 'thickness_std': 0.0} Undefined {'count': 0, 'thickness_mean': None, 'pressure_mean': None, 'pressure_std': None, 'thickness_std': None} Altostratus {'count': 0, 'thickness_mean': None, 'pressure_mean': None, 'pressure_std': None, 'thickness_std': None} Nimbostratus {'count': 0, 'thickness_mean': None, 'pressure_mean': None, 'pressure_std': None, 'thickness_std': None} Cumulus {'count': 0, 'thickness_mean': None, 'pressure_mean': None, 'pressure_std': None, 'thickness_std': None} Stratus {'count': 2, 'thickness_mean': 104.14999999999999, 'pressure_mean': 887.84999999999991, 'pressure_std': 29.449999999999989, 'thickness_std': 57.049999999999997} Stratocumulus {'count': 0, 'thickness_mean': None, 'pressure_mean': None, 'pressure_std': None, 'thickness_std': None} Deep Convection {'count': 5, 'thickness_mean': 107.7, 'pressure_mean': 259.02000000000004, 'pressure_std': 98.116979162630159, 'thickness_std': 69.316289571788246} Cirrus {'count': 1, 'thickness_mean': 0.59999999999999998, 'pressure_mean': 282.89999999999998, 'pressure_std': 0.0, 'thickness_std': 0.0}

(c) Write a program similar to exercise 3 (under "Looping through all keys in a dictionary", where the user can enter a cloud type at a prompt and all of the values for that cloud are printed to the screen.

In [12]:
requested_word = ''
while requested_word != 'quit':
requested_word = raw_input("\nWhat word would you like to learn about? (or 'quit') ")
if requested_word in dictionary.keys():
print dictionary[requested_word]
elif requested_word == 'quit':
print("\n Bye bye!")
break
else:
print("\n  Sorry, I don't know that word.")

What word would you like to learn about? (or 'quit') Cirrus {'count': 1, 'thickness_mean': 0.59999999999999998, 'pressure_mean': 282.89999999999998, 'pressure_std': 0.0, 'thickness_std': 0.0} What word would you like to learn about? (or 'quit') quit Bye bye!
In [ ]: