Python continued / matplotlib¶

09/07/2022¶

print view
notebook

In [1]:
%%html
<script src="https://requirejs.org/docs/release/2.3.6/minified/require.js"></script>
<script src="https://code.jquery.com/jquery-3.7.1.min.js"></script>
<script src="https://bits.csb.pitt.edu/asker.js/lib/asker.js"></script>
<style>
.reveal pre { font-size: 100%; overflow-x: auto; overflow-y: auto;}
.reveal h1 { font-size: 2em}
.reveal ol {display: block;}
.reveal ul {display: block;}
.reveal .slides>section>section.present { max-height: 100%; overflow-y: auto;}

.jp-OutputArea-output { padding: 0; }
</style>


<script>
console.log(jQuery.asker);
$3Dmolpromise = new Promise((resolve, reject) => { 
    require(['https://3Dmol.org/build/3Dmol.js'], function(){       
            resolve();});
});
require(['https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.2.2/Chart.js'], function(Ch){
 Chart = Ch;
});

$('head').append('<link rel="stylesheet" href="https://bits.csb.pitt.edu/asker.js/themes/asker.default.css" />');


//the callback is provided a canvas object and data 
var chartmaker = function(canvas, labels, data) {
  var ctx = $(canvas).get(0).getContext("2d");
     var dataset = {labels: labels,                     
    datasets:[{
     data: data,
     backgroundColor: "rgba(150,64,150,0.5)",
         fillColor: "rgba(150,64,150,0.8)",    
  }]};
  var myBarChart = new Chart(ctx,{type:'bar',data:dataset,options:{legend: {display:false},
        scales: {
            yAxes: [{
                ticks: {
                    min: 0,
                }
            }]}}});
};

$(".jp-InputArea .o:contains(html)").closest('.jp-InputArea').hide();


</script>

Conditionals and Control Flow¶

if statements¶

  • An if statement conditionally executes a block of code
  • The condition is some Boolean value
  • A block of code is delineated by consistent indentation.
  • Blank lines and comments will not end a block
  • Whitespace is significant - do not mix tabs and spaces
  • In an if..elif..else statement, only one block of code will be executed
In [2]:
if False:
    print(1)
elif True:
    print(2)
else:
    print(3)
2
In [3]:
val = 0
if val >= 0:
    val += 1
elif val < 1:
    val += 2
elif True:
    val += 3
else:
    val += 5
    
    val += 7
In [4]:
%%html
<div id="if1" style="width: 500px"></div>

<script>
$('head').append('<link rel="stylesheet" href="https://bits.csb.pitt.edu/asker.js/themes/asker.default.css" />');

    var divid = '#if1';
	jQuery(divid).asker({
	    id: divid,
	    question: "What is the value of val?",
		answers: ["1","4","6","8","11","16"],
        server: "https://bits.csb.pitt.edu/asker.js/example/asker.cgi",
		charter: chartmaker})
    
$(".jp-InputArea .o:contains(html)").closest('.jp-InputArea').hide();


</script>

pass¶

pass does nothing

In [5]:
if True:
    pass
else:
    print("I will never print")

Logical Operators¶

  • and, or, and not
  • not has higher precedence than and which has higher precedence than or
  • all three have lower precedence than comparison operators
  • but use parentheses to avoid confusion
In [6]:
%%html

<div id="logic1" style="width: 600px"></div>


<script>

	jQuery("#logic1").asker({
	    id: "logic1",
	    question: "Which of the following is equivalent to <tt>not (x and y)</tt>",
		answers: ["<tt>not x and not y</tt>","<tt>not x and y</tt>","<tt>x or y</tt>","<tt>not x or not y</tt>"],
        server: "https://bits.csb.pitt.edu/asker.js/example/asker.cgi",
		charter: chartmaker})
    
$(".jp-InputArea .o:contains(html)").closest('.jp-InputArea').hide();

</script>
In [7]:
x = 3; y = 4; z = 5
val = x != 3 or not y < 0 and z < 10 or not y == 0 and z < 0
In [8]:
%%html

<div id="cond1" style="width: 500px"></div>
<script>

    var divid = '#cond1';
	jQuery(divid).asker({
	    id: divid,
	    question: "What is the value of val?",
		answers: ["True","False"],
        server: "https://bits.csb.pitt.edu/asker.js/example/asker.cgi",
		charter: chartmaker})
    
$(".jp-InputArea .o:contains(html)").closest('.jp-InputArea').hide();

</script>

Membership testing¶

in and not in can be used to see if an object is in a collection

In [9]:
l = [1,2,3]
In [10]:
1 in l
Out[10]:
True
In [11]:
345 in l
Out[11]:
False
In [12]:
"1" not in l
Out[12]:
True
In [13]:
"good" in "goodness"
Out[13]:
True
In [14]:
val = 'cat' in 'catalog'
In [15]:
%%html

<div id="catin" style="width: 500px"></div>
<script>

    var divid = '#catin';
	jQuery(divid).asker({
	    id: divid,
	    question: "What is val?",
		answers: ["True","False","None"],
        server: "https://bits.csb.pitt.edu/asker.js/example/asker.cgi",
		charter: chartmaker})
    
$(".jp-InputArea .o:contains(html)").closest('.jp-InputArea').hide();

</script>
In [16]:
val = 'cat' in ['catalog','catastrophe']
In [51]:
%%html

<div id="catin2" style="width: 500px"></div>
<script>

    var divid = '#catin2';
	jQuery(divid).asker({
	    id: divid,
	    question: "What is val?",
		answers: ["True","False","None"],
        server: "https://bits.csb.pitt.edu/asker.js/example/asker.cgi",
		charter: chartmaker})
    
$(".jp-InputArea .o:contains(html)").closest('.jp-InputArea').hide();

</script>

Loops¶

In [18]:
i = 0
while i < 3: #as long as this condition is true...
    print(i) #...execute this block of code
    i += 1   
0
1
2
In [19]:
letters = ['a','b','c','d','e','f','g']
for i in letters: #for every item in this collection...
    print(i) #...execute this block of code with i set to the object
a
b
c
d
e
f
g

range¶

The preferred method of looping is to use a for loop. There are a number of builtin functions to help create collections to iterate over.

In [20]:
list(range(3))
Out[20]:
[0, 1, 2]
In [21]:
list(range(1,10))
Out[21]:
[1, 2, 3, 4, 5, 6, 7, 8, 9]
In [22]:
list(range(1,10,3))
Out[22]:
[1, 4, 7]
In [23]:
val = 0
for i in range(100):
    val += i
In [24]:
%%html

<div id="summer" style="width: 500px"></div>
<script>

    var divid = '#summer';
	jQuery(divid).asker({
	    id: divid,
	    question: "What is the value of val?",
		answers: ["0","99","100","101","4950","5050"],
        server: "https://bits.csb.pitt.edu/asker.js/example/asker.cgi",
		charter: chartmaker})
    
$(".jp-InputArea .o:contains(html)").closest('.jp-InputArea').hide();

</script>

Iterable¶

for will loop over any iterable object

In addition to collections, this includes any object that can provide items one at a time

  • Most importantly files
In [25]:
f = open("../files/brca1.fasta")
cnt = 0
for line in f.readlines():
    cnt += len(line)
cnt
Out[25]:
6258
In [26]:
f = open("../files/brca1.fasta")
cnt = 0
for line in f:  
    cnt += len(line)
cnt
Out[26]:
6258

break and continue¶

break will exit out of the entire loop while continue will skip to the next iteration

In [27]:
i = 0
while True:
    i += 1
    if i < 6:
        continue
    print(i)
    if i > 4:
        break
6
In [28]:
x = 0
while x < 100:
    if x < 50:
        pass
    elif x == 5:
        break
    x += 1
In [29]:
%%html

<div id="breakq" style="width: 500px"></div>
<script>

    var divid = '#breakq';
	jQuery(divid).asker({
	    id: divid,
	    question: "What is the value of x?",
		answers: ["5","50","100","101","Nothing"],
        server: "https://bits.csb.pitt.edu/asker.js/example/asker.cgi",
		charter: chartmaker})
    
$(".jp-InputArea .o:contains(html)").closest('.jp-InputArea').hide();

</script>

Slicing¶

What if you don't want to iterate over the full list?

In [30]:
s = "Hello"
s[0:2]
Out[30]:
'He'
In [31]:
s[2:] # empty indices indicate remainder of string/list
Out[31]:
'llo'
In [32]:
s[:-2] #negative indices count from the back
Out[32]:
'Hel'
In [33]:
s2 = "Hello, world"
s2[:-2]
Out[33]:
'Hello, wor'
In [34]:
l = ["cat","dog","fish","mouse"]
val = len(l[2:3])
In [35]:
%%html

<div id="slicer" style="width: 500px"></div>
<script>

    var divid = '#slicer';
	jQuery(divid).asker({
	    id: divid,
	    question: "What is the value of val?",
		answers: ["0","1","2","3","4","5"],
        server: "https://bits.csb.pitt.edu/asker.js/example/asker.cgi",
		charter: chartmaker})
    
$(".jp-InputArea .o:contains(html)").closest('.jp-InputArea').hide();

</script>

matplotlib¶

make easy things easy and hard things possible¶

In [36]:
import matplotlib.pyplot as plt
# next is a python notebook command to embed plot output in the notebook
%matplotlib inline 

plt has hundreds of functions for creating and manipulating plots

plt.plot creates line/point graphs

  • you can specify an arbitrary number of x,y,format arguments
In [37]:
plt.plot([0,1,2,3],[0,1,2,3],"-b",[0,1,2,3],[0,1,4,9],"--r")
plt.ylabel("Y")
plt.xlabel("X")
plt.show() #not actually necessary in notebook

matplotlib is stateful¶

In [38]:
plt.plot([1,2,4,9,16],label="one") #if only one data set is provide, assume uniform x
plt.plot([0.5,1,2,4.5,8],'^-.',label="two") #keep adding to current graph until show is called
plt.legend() #uses labels
plt.show()
In [39]:
plt.show() # this doesn't show anything since we haven't created another plot
plt.close() #another way to finish with a plot

If you use the %matplotlib command in ipython, the plot will be updated with every command (can skip show)

Format codes¶

marker	description
”.”	point
”,”	pixel
“o”	circle
“v”	triangle_down
“^”	triangle_up
“<”	triangle_left
“>”	triangle_right
“1”	tri_down
“2”	tri_up
“3”	tri_left
“4”	tri_right
“8”	octagon
“s”	square
“p”	pentagon
“*”	star
“h”	hexagon1
“H”	hexagon2
“+”	plus
“x”	x
“D”	diamond
“d”	thin_diamond
“|”	vline
“_”	hline

Colors¶

    'b'         blue
    'g'         green
    'r'         red
    'c'         cyan
    'm'         magenta
    'y'         yellow
    'k'         black
    'w'         white

Can also specify colors with full names or hexadecimal

In [40]:
plt.plot([1,2,4,6,7,4,2,2],'orange',linewidth=6)
plt.show()

Plotting expression data¶

In [41]:
f = open('../files/Spellman.txt')
header = f.readline().rstrip().split(',')#rstrip removes newline
data = []
for line in f:
    data.append(line.rstrip().split(','))
len(data)
Out[41]:
4381
In [42]:
for row in data[:10]: #first 10 only
    values = list(map(float, row[1:]))
    times = list(map(int, header[1:]))
    plt.plot(times,values,label=row[0])
plt.legend(loc='upper center',ncol=5,prop={'size':7})
plt.xlabel("Time");

Data conversion...

In [43]:
for i in range(1,len(header)):
    header[i] = int(header[i])
    for r in range(len(data)):
        data[r][i] = float(data[r][i])

Bar charts¶

In [44]:
plt.bar([1.1,2.1,3.1],[30,40,50],0.5,yerr=[2,10,12],ecolor="black",alpha=0.5,label="One")
plt.bar([1.4,2.4,3.4],[60,50,20],0.5,color='r',yerr=[10,4,1],ecolor="black",alpha=0.5,label="Two")
plt.xticks([1.4,2.4,3.4], ['A','B','C'])
plt.ylim([0,100])
plt.legend();

Histograms¶

In [45]:
import random
rdata = []
for i in range(1000):
    rdata.append(random.normalvariate(0,1))
    
plt.hist(rdata,10);

Combining chart types¶

Just accumulate plots

In [46]:
plt.hist(rdata,10)
plt.plot([-3,-1,0,1,2,3],[20,30,50,60,80,90],'-r',linewidth=3)
plt.show()

Terminology¶

Figure¶

The full canvas you are creating your plot(s) on.

Axes¶

A single plot

Multiple Plots on a Figure¶

subplots(nrows,ncols)

In [47]:
fig, axes = plt.subplots(2,1)
plt.sca(axes[0]) #set current axis to first
plt.plot(header[1:],data[0][1:])
plt.ylabel(data[0][0])

plt.sca(axes[1])
plt.plot(header[1:],data[1][1:],'g')
plt.ylabel(data[1][0])
plt.show()

See also GridSpec

Multiple Plots on a Figure¶

In [48]:
numgenes = 3
fig, axes = plt.subplots(numgenes,1,sharex=True,sharey=True)
colors = ['b','g','purple']
for i in range(numgenes):
    #most plot methods have equivalents on axes objects
    axes[i].plot(header[1:],data[i][1:],color=colors[i])
    axes[i].set_ylabel(data[i][0])

Exporting charts¶

Instead of plt.show use plt.savefig

bbox_inches='tight' tells matplotlib to try harder to fit everything nicely.

In [49]:
plt.axes(aspect=1)
plt.pie([8,2,1],labels=["Novice","Beginner","Proficient"])
plt.savefig("pie.png",bbox_inches='tight')
In [50]:
ls *png
pie.png

Other formats: pdf, svg, eps...

Other chart types¶

Gallery

Seaborn¶

Making (some) hard things easy

Gallery

Project¶

https://MSCBIO2025.github.io/files/Spellman.csv

  • plot a gene
  • plot the histogram of initial expression levels
  • plot the histogram of final expression levels
  • plot the above histograms on the same plot with transparent fill
  • plot the above with identical bin sizes for both histograms
  • plot the above histograms on different subplots, vertically stacked