Προγραμματισμός με τη γλώσσα python

Alexandros Kanterakis kantale@ics.forth.gr

Διάλεξη 9η, Παρασκευή 15 Δεκεμβρίου 2017

Plotting (cont'd)

Μέχρι στιγμής έχουμε δει πως κάνουμε plot μέσω της matplotlib στις περσινές και φετινές σημειώσεις. Η matplotlib είναι κατάλληλη για "στατικά" plots που μπορούμε να σώσουμε σε ένα αρχείο εικόνας. Αυτά τα plots δεν μας επιτρέπουν να αλληλεπιδράσουμε με τα δεδομένα και να τα εξερευνήσουμε!

Μία από τις πιο γνωστές βιβιλιοθήκες για αυτό το σκοπό είναι η bokeh. Για αρχή ας την εγκαταστήσουμε:

In [1]:
!conda install -y bokeh
Fetching package metadata .........
Solving package specifications: .

Package plan for installation in environment /Users/alexandroskanterakis/anaconda3/envs/arkalos:

The following NEW packages will be INSTALLED:

    bkcharts:   0.2-py36_0   
    bokeh:      0.12.7-py36_0
    jinja2:     2.9.6-py36_0 
    markupsafe: 1.0-py36_0   
    pyyaml:     3.12-py36_0  
    tornado:    4.5.2-py36_0 
    yaml:       0.1.6-0      

yaml-0.1.6-0.t 100% |################################| Time: 0:00:00   1.76 MB/s
markupsafe-1.0 100% |################################| Time: 0:00:00  14.11 MB/s
pyyaml-3.12-py 100% |################################| Time: 0:00:00   3.07 MB/s
tornado-4.5.2- 100% |################################| Time: 0:00:00   1.91 MB/s
bkcharts-0.2-p 100% |################################| Time: 0:00:00  13.39 MB/s
jinja2-2.9.6-p 100% |################################| Time: 0:00:00   5.16 MB/s
bokeh-0.12.7-p 100% |################################| Time: 0:00:00   9.62 MB/s

Κάνουμε import:

In [2]:
from bokeh.io import output_notebook, show
from bokeh.plotting import figure

Η παρακάτω εντολή, ρυθμίζει τη bokeh να ενσωματώνει τα plots στο jupyter:

In [3]:
output_notebook()
Loading BokehJS ...

Ας φτιάξουμε ένα απλό plot:

In [5]:
# create a new plot with default tools, using figure
p = figure()

# Βάζουμε κύκλους σε συγκεκριμένα σημεία 
p.circle([1, 2, 3, 4, 5], [6, 7, 2, 4, 5],)

show(p) # showtime!

Για αρχή παρατηρήστε ότι μπορείτε να αλληλεπιδράσετε με αυτό το plot.

Ας κάνουμε τους κύκλους να έχουν διαφορετικό χρώμα και μέγεθος:

In [6]:
# create a new plot with default tools, using figure
p = figure(plot_width=400, plot_height=400)

# add a circle renderer with a size, color, and alpha
p.circle([1, 2, 3, 4, 5], [6, 7, 2, 4, 5], 
         size=[10,11,12,13,14],
         line_color="navy", 
         fill_color=["orange"]*4+['pink'], fill_alpha=0.5)

show(p) # show the results

Η πιο σημαντική ίσως ιδιότητα της bokeh είναι ότι σας επιτρέπει να σώσεται τα plots σε μορφή html. Με αυτόν τον τρόπο μπορείτε όχι μόνο να "στείλετε" ένα plot κάπου αλλού, αλλά και να το "ανεβάσετε" στο Internet!

In [7]:
from bokeh.io import save
In [8]:
save(p, 'graph.html')
/Users/alexandroskanterakis/anaconda3/envs/arkalos/lib/python3.6/site-packages/bokeh/io.py:527: UserWarning: save() called but no resources were supplied and output_file(...) was never called, defaulting to resources.CDN
  warnings.warn("save() called but no resources were supplied and output_file(...) was never called, defaulting to resources.CDN")
/Users/alexandroskanterakis/anaconda3/envs/arkalos/lib/python3.6/site-packages/bokeh/io.py:537: UserWarning: save() called but no title was supplied and output_file(...) was never called, using default title 'Bokeh Plot'
  warnings.warn("save() called but no title was supplied and output_file(...) was never called, using default title 'Bokeh Plot'")
Out[8]:
'/Users/alexandroskanterakis/Downloads/graph.html'

Δοκιμάστε τώρα να ανοίξετε το αρχείο graph.html από τον browser σας (File -> Open..)

Η bokeh είναι πολύ πλούσια βιβλιοθήκη. Σε αυτό link: http://nbviewer.jupyter.org/github/bokeh/bokeh-notebooks/blob/master/tutorial/00%20-%20Introduction%20and%20Setup.ipynb υπάρχει ένας πολύ αναλυτικός οδηγός με τις περισσότερες λειτουργίες της.

Με τις παρακάτω εντολές εγκαθιστά διάφορα δοκιμαστικά datasets:

In [37]:
import bokeh
bokeh.sampledata.download()
Creating /Users/alexandroskanterakis/.bokeh directory
Creating /Users/alexandroskanterakis/.bokeh/data directory
Using data directory: /Users/alexandroskanterakis/.bokeh/data
Downloading: CGM.csv (1589982 bytes)
   1589982 [100.00%]
Downloading: US_Counties.zip (3182088 bytes)
   3182088 [100.00%]
Unpacking: US_Counties.csv
Downloading: us_cities.json (713565 bytes)
    713565 [100.00%]
Downloading: unemployment09.csv (253301 bytes)
    253301 [100.00%]
Downloading: AAPL.csv (166698 bytes)
    166698 [100.00%]
Downloading: FB.csv (9706 bytes)
      9706 [100.00%]
Downloading: GOOG.csv (113894 bytes)
    113894 [100.00%]
Downloading: IBM.csv (165625 bytes)
    165625 [100.00%]
Downloading: MSFT.csv (161614 bytes)
    161614 [100.00%]
Downloading: WPP2012_SA_DB03_POPULATION_QUINQUENNIAL.zip (5148539 bytes)
   5148539 [100.00%]
Unpacking: WPP2012_SA_DB03_POPULATION_QUINQUENNIAL.csv
Downloading: gapminder_fertility.csv (64346 bytes)
     64346 [100.00%]
Downloading: gapminder_population.csv (94509 bytes)
     94509 [100.00%]
Downloading: gapminder_life_expectancy.csv (73243 bytes)
     73243 [100.00%]
Downloading: gapminder_regions.csv (7781 bytes)
      7781 [100.00%]
Downloading: world_cities.zip (646858 bytes)
    646858 [100.00%]
Unpacking: world_cities.csv
Downloading: airports.json (6373 bytes)
      6373 [100.00%]
Downloading: movies.db.zip (5067833 bytes)
   5067833 [100.00%]
Unpacking: movies.db

Με τη παρακάτω εντολή εγκαθιστούμε τη pandas την οποία θα χρειαστούμε για το επόμενο παράδειγμα. Σε επόμενη διάλεξη θα κάνουμε μία αναλυτική παρουσιάση της pandas.

In [46]:
!conda install -y pandas
Fetching package metadata .........
Solving package specifications: .

# All requested packages already installed.
# packages in environment at /Users/alexandroskanterakis/anaconda3/envs/arkalos:
#
pandas                    0.20.3                   py36_0  

Μία από τις πιο βασικές ιδιότητες της bokeh είναι ότι μπορούμε να προσθέσουμε tooltips. Τα tooltips είναι διάφορες (μετα)πληροφορίες που εμφανίζονται όταν "περνάμε" το ποντίκι πάνω από ένα σημείο.

In [62]:
from bokeh.models import TapTool, CustomJS, ColumnDataSource
from bokeh.models import HoverTool

from bokeh.io import output_file
output_file('plot.html')

source = ColumnDataSource(
        data=dict(
            x=[1, 2, 3, 4, 5],
            y=[2, 5, 8, 2, 7],
            desc=['A', 'b', 'C', 'd', 'E'],
            example=['aa', 'bb', 'cc', 'dd', 'ee'],
        )
    )

hover = HoverTool(
        tooltips=[
            ("index", "$index"),
            ("(x,y)", "($x, $y)"),
            ("desc", "@desc"),
            ("Mitsos", "@example"),
        ]
    )

p = figure(plot_width=300, plot_height=300, tools=[hover], title="Mouse over the dots")

p.circle('x', 'y', size=20, source=source)

show(p)

Ασκήσεις

Αυτή η σειρά ασκήσεων έχει μόνο μία άσκηση. Θα πρέπει να κάνετε ένα plot το οποίο θα το σώσετε σε μορφή html. Στη συνέχεια και σε συνεργασία με τους διδάσκοντες στο μάθημα BIO102 θα πρέπει να "ανεβάσετε" το plot στη προσωπική σας σελίδα.

Στείλτε το plot:

  • Σε φορμάτ html στο kantale@ics.forth.gr ή
  • Ανεβάστε το στη προσωπική σας σελίδα και στείλτε μου το link

Περιγραφή:

Σε αυτή τη σελίδα: https://www.ebi.ac.uk/gwas/docs/file-downloads υπάρχει κατάλογος με τα πεισσότερα GWAS πειράματα που έχουν γίνει. Μπορούμε να το κατεβάσουμε με τη παρακάτω εντολή:

In [9]:
!wget -O gwas_catalogue.tsv https://www.ebi.ac.uk/gwas/api/search/downloads/full
--2017-12-18 20:04:08--  https://www.ebi.ac.uk/gwas/api/search/downloads/full
Resolving www.ebi.ac.uk... 193.62.193.80
Connecting to www.ebi.ac.uk|193.62.193.80|:443... connected.
HTTP request sent, awaiting response... 200 OK
Length: unspecified [text/tsv]
Saving to: ‘gwas_catalogue.tsv’

gwas_catalogue.tsv      [                <=> ]  34.17M  1.03MB/s    in 33s     

2017-12-18 20:04:42 (1.03 MB/s) - ‘gwas_catalogue.tsv’ saved [35832863]

Ας διαβάσουμε τη πρώτη γραμμή του αρχείου:

In [11]:
file = open('gwas_catalogue.tsv')
line_1 = file.readline()
line_1
Out[11]:
'DATE ADDED TO CATALOG\tPUBMEDID\tFIRST AUTHOR\tDATE\tJOURNAL\tLINK\tSTUDY\tDISEASE/TRAIT\tINITIAL SAMPLE SIZE\tREPLICATION SAMPLE SIZE\tREGION\tCHR_ID\tCHR_POS\tREPORTED GENE(S)\tMAPPED_GENE\tUPSTREAM_GENE_ID\tDOWNSTREAM_GENE_ID\tSNP_GENE_IDS\tUPSTREAM_GENE_DISTANCE\tDOWNSTREAM_GENE_DISTANCE\tSTRONGEST SNP-RISK ALLELE\tSNPS\tMERGED\tSNP_ID_CURRENT\tCONTEXT\tINTERGENIC\tRISK ALLELE FREQUENCY\tP-VALUE\tPVALUE_MLOG\tP-VALUE (TEXT)\tOR or BETA\t95% CI (TEXT)\tPLATFORM [SNPS PASSING QC]\tCNV\n'

Το αρχείο είναι tab delimited. Ας το κάνουμε split:

In [14]:
line_1_splitted = line_1.split('\t')
line_1_splitted
Out[14]:
['DATE ADDED TO CATALOG',
 'PUBMEDID',
 'FIRST AUTHOR',
 'DATE',
 'JOURNAL',
 'LINK',
 'STUDY',
 'DISEASE/TRAIT',
 'INITIAL SAMPLE SIZE',
 'REPLICATION SAMPLE SIZE',
 'REGION',
 'CHR_ID',
 'CHR_POS',
 'REPORTED GENE(S)',
 'MAPPED_GENE',
 'UPSTREAM_GENE_ID',
 'DOWNSTREAM_GENE_ID',
 'SNP_GENE_IDS',
 'UPSTREAM_GENE_DISTANCE',
 'DOWNSTREAM_GENE_DISTANCE',
 'STRONGEST SNP-RISK ALLELE',
 'SNPS',
 'MERGED',
 'SNP_ID_CURRENT',
 'CONTEXT',
 'INTERGENIC',
 'RISK ALLELE FREQUENCY',
 'P-VALUE',
 'PVALUE_MLOG',
 'P-VALUE (TEXT)',
 'OR or BETA',
 '95% CI (TEXT)',
 'PLATFORM [SNPS PASSING QC]',
 'CNV\n']

Αυτό το αρχείο λοιπόν περιέχει όλα τα SNPs για τα οποία έχει βρεθεί κάποια στατιστική συσχέτιση με κάποιον φαινότυπο. Οι στήλες που μας ενδιαφέρουν είναι:

  • "DATE" : είναι η ημερομηνία που δημοσιεύθηκε η συσχέτιση
  • "P-VALUE" : Το p-value της συσχέτισης
  • "INITIAL SAMPLE SIZE": το πλήθος των samples που είχε η μελέτη όταν βρέθηκε η συσχέτιση
  • "STUDY": Ο τίτλος του paper που δημοσιεύθηκε η συσχέτιση.

Το plot σας θα έχει στον χ-άξονα την ημερομηνία που έγινε η δημοσίευση (DATA). Στον χ-άξονα, οι ημερομηνίες πρέπει να είναι ταξινομημένες από τη πιο παλιά (αριστερά) στη πιο πρόσφατη (δεξιά). Θα πρέπει δηλαδή να ταξινομήσετε τα δεδομένα με βάση την ημερομηνία. Ο y άξονας θα έχει τον αρνητικό λογάριθμο του p-value. Επειδή το p-value συνήθως είναι πολύ μικρό, χρησιμοποιούμε τον αρνητικό λογάριθμο για να τον αναπαραστήσουμε. Για παράδειγμα:

In [18]:
import math

p_value = 4E-7 # 4*10^(-7)

def negative_log(p):
    return -math.log10(p)

negative_log(p_value)
Out[18]:
6.3979400086720375

Κάθε SNP θα αναπαριστάται με έναν κύκλο με μέγεθος ανάλογα με το πλήθος των samples που συμμετείχαν στη μελέτη (πεδίο INITIAL_SAMPLE_SIZE).

Όταν ο χρήστης περνάει με το ποντίκι πάνω από κάποιον κύκλο θα πρέπει να του εμφανίζεται ο τίτλος του paper όπου έγινε η δημοσίευση.

Σημείωση: Αν τα δεδομένα είναι πάρα πολλά και το plot είναι πολύ πυκνό τότε μπορείτε να βάλετε κάποιο φίλτρο π.χ. Μόνο τα SNPs που δημοσιεύθηκαν από το 2013 και μετά ή/και αυτά που είναι στο χρωμόσωμα 1.

Προσπαθήστε το plot να είναι ταυτόχρονα χρηστικό και αισθητικά ωραίο!