Showing posts with label google. Show all posts
Showing posts with label google. Show all posts

13 September 2012

Translating a DNA sequence in Google Spreadsheet using #GoogleAppScript

Google has released Google App Script.
"Google Apps Script is a JavaScript cloud scripting language that lets you extend Google Apps and build web applications. Scripts are developed in Google Apps Script’s browser-based script editor, and they are stored in and run from Google's servers.
Google Apps Script is very versatile. Here are some examples of things you can do with Google Apps Script":
  • Build custom functions in a Google Spreadsheet
  • Extend certain Google Apps products by creating custom menus linked to scripts
  • Create and publish web applications, which can run on their own or embedded within a Google Site
  • Schedule tasks like report creation and distribution and run them on a custom schedule
  • Automate workflows such as document or expense approvals, order fulfillment, time-tracking, and more

In the current post, I'll show how to create a custom javascript function that will

Translate a
DNA
to a
Protein
into a
Google Spreadsheet

Create a new Google Spreadhseet. Open the menu "Tools" > "Script Manager...". Click on New...

Click on "Create Blank Project".

A new editor is opened. Copy the following javascript code (https://gist.github.com/3716137) into the editor. Save the javascript projet.

Close the script, go back to the spreasheet. You can now use your new function =translateDNA(dna):

That's it,

Pierre

31 July 2011

Storing some SNPs using the leveldb library. My notebook.

In this post I'll describe how I've used the leveldb API, a C++ key-value database, to store some SNPs (key=rs,value=sequence). "LevelDB is a fast key-value storage library written at Google that provides an ordered mapping from string keys to string values.". A benchmark for this engine is available here: http://code.google.com/p/leveldb/source/browse/trunk/doc/benchmark.html.

Download & install

$ svn checkout http://leveldb.googlecode.com/svn/trunk/ leveldb-read-only
$ cd leveldb-read-only/
$ make

Open & close a leveldb database

#include "leveldb/db.h"
(...)
leveldb::DB* db=NULL;
leveldb::Options options;
options.comparator=&rs_comparator;/* custom comparator for ordering the keys, see later */
options.create_if_missing = true;
clog << "[LOG]opening database" << endl;
leveldb::Status status = leveldb::DB::Open(options,db_home, &db);
//check status
if (!status.ok())
{
cerr << "cannot open " << db_home << " : " << status.ToString() << endl;
return EXIT_FAILURE;
}
(...)
/* use the database */
(...)
delete db;

A custom comparator for ordering the keys

Here, the keys are the rs-ids ordered on their numerical value. Both keys and values have a type "leveldb::Slice".
class RsComparator : public leveldb::Comparator
{
private:
/* parses the rsId: rs[0-9]+ */
int rs(const leveldb::Slice& s) const
{
int n=0;
for(size_t i=2;i< s.size();++i)
{
n=n*10+s[i]-'0';
}
return n;
}
public:
virtual int Compare(const leveldb::Slice& a, const leveldb::Slice& b) const
{
return rs(a)-rs(b);
}
(...)
}
(...)
RsComparator rs_comparator;
options.comparator=&rs_comparator;

Inserting a FASTA sequence


(...)
std::string name;
std::string sequence;
(...)
leveldb::Status status = db->Put(leveldb::WriteOptions(), name, sequence);
if(!status.ok())
{
cerr << "Cannot insert "<< name << " "
<< status.ToString() << endl;
return EXIT_FAILURE;
}

Searching for a rs###

(...)
std::string name(argv[optind]);
std::string sequence;
(...)
leveldb::Status status = db->Get(leveldb::ReadOptions(),seqname, &sequence);
if(!status.ok())
{
cerr << "Cannot find " << seqname<< " in " << db_home << endl;
continue;
}
printFasta(seqname,sequence);
(...)

Dumping all the SNPs using an iterator

(...)
leveldb::Iterator* it = db->NewIterator(leveldb::ReadOptions());
for (it->SeekToFirst(); it->Valid(); it->Next())
{
printFasta(it->key(),it->value());
}
delete it;
(...)

Examples

Reading the SNPs:
$ curl -s "ftp://ftp.ncbi.nih.gov/snp/organisms/human_9606/rs_fasta/rs_chMT.fas.gz" |\
./rsput -D snp.db

[LOG]opening database
[LOG] added rs8896
[LOG] added rs8936
[LOG] added rs9743
(...)
[LOG]closing database

$ du -h snp.db
336K snp.db
Dump the snps

$ ./rsget  -D snp.db

[LOG]opening database
>rs8896
GGTGTTGGTTCTCTTAATCTTTAACTTAAAAGGTTAATGCTAAGTTAGCTTTACAGTGGG
CTCTAGAGGGGGTAGAGGGGGTGYTATAGGGTAAATACGGGCCCTATTTCAAAGATTTTT
AGGGGAATTAATTCTAGGACGATGGGCATGAAACTGTGGTTTGCTCCACAGATTTCAGAG
CATT
>rs8936
ACTACGGCGGACTAATCTTCAACTCCTACATACTTCCCCCATTATTCCTAGAACCAGGCG
ACCTGCGACTCCTTGACGTTGACAATCGAGTAGTACTCCCGATTGAAGCCCCCATTCGTA
TAATAATTACATCACAAGACGTCTTGCACTCATGAGCTGTCCCCACATTAGGCTTAAAAA
CAGATGCAATTCCCGGACGTHTAAACCAAACCACTTTCACCGCTACACGACCGGGGGTAT
ACTACGGTCAATGCTCTGAAATCTGTGGAGCAAACCACAGTTTCATGCCCATCGTCCTAG
AATTAATTCCCCTAAAAATCTTTGAAATAGGGCCCGTATTTACCCTATAGCACCCCCTCT
ACCCCCTCTAGAGCCCACTGTAAAGCTAACTTAGCATTAAC
>rs9743
CCATGTGATTTCACTTCCACTCCATAACGCTCCTCATACTAGGCCTACTAACCAACACAC
TAACCATATACCAATGATGNCGCGATGTAACACGAGAAAGCACATACCAAGGCCACCACA
CACCACCTGTCCAAAAAGGCCTTCGATACGGGATAATCCTATTTATTACCTCAGAANTTT
TTTTCTTCGCAGGATTTTTCTGAGCCTTTTACCACTCCAGCCTAGCCCCTACCCCCCAAN
(...)
[LOG]closing database
Search for some SNPs:
$ ./rsget -D snp.db rs78894381 rs72619361 rs25
[LOG]opening database
[LOG]searching for rs78894381
>rs78894381
CTACTAATCTCATCAACACAACCCCCGCCCATCCTACCCAGCACACACACACCGCTGCTA
ACCCCATACCCCGAACCAACCAAACCCCAAAGACACCCCCNCACAGTTTATGTAGCTTAC
CTCCTCAAAGCAATACACTGAAAATGTTTAGACGGGCTCACATCACCCCATAAACAAATA
GGTTTGGTCCTAGCCTTTCTA
[LOG]searching for rs72619361
>rs72619361
ATGCATTTGGTATTTTAATCTGGGGGGTGTGCACGCGATAGCATTGTGAAACGCTGGCCC
CAGAGCACCCTATGTCGCAGTGTCTGTCTTTGATTCCTGCCYCATCCCATTATTGATCAC
ACCTACATTCAATATCCCAGGCGAGCATACCTATCACAAGGTGTTAATTAATTAATGCTT
GTAGGACATAACAATCAGTAAAC
[LOG]searching for rs25
Cannot find rs25 in snp.db
[LOG]closing database

Source code






That's it,

Pierre

05 September 2008

Center for the Study of Human Polymorphisms: Week 1

I've started my first week at the center Center for the Study of Human Polymorphisms and today we had our first meeting with Mario Foglio and some other to define what will be my job in the following monthes. As I said, I will collaborate with the National Center of Genotyping on Operon, a feasible bioinformatics platform to centralize scientific software and biomedical data with internal results. It was curious because I found that nobody there uses most of the tools used/discussed with the biogang (rss feeds, social bookmarking, etc... ) and I hope I will present some slides about this later.

I will have to re-factoring the current 'C' code of operon (written over BerkeleyDB) to build a new clean C API that will be used some other persons.

What is cool is that this is an open source project and we will host it on google (http://code.google.com/p/polymorphism/).
I've also created a mailing list on google.groups: http://groups.google.com/group/operon-dev, shown my collaborators how to share a calendar on google-calendar (to find what are the possible dates for organizing a meeting) and we have already started to share some documents using google-docs. Thank you google.

The 'C' language was chosen because it is a low-level language and it seems that the developers at the CNG prefer it. I hope I will create some wrappers around this API with some other language. I already know it is possible with java using the Java Native Interface (JNI, see my previous post about this). SWIG (http://www.swig.org/), a tool generating some wrappers in various languages (python, perl...), might also be of hel. Using a Java wrapper will allow us to deploy any application in a java web server such as tomcat.

I've not much played with 'C' since 1998 ( I then played with C++ for 4 years before switching to java) but I (hope) still have some good skills and I know I now have better good programming practice.

That's it for tonight.

Pierre

06 December 2007

Google Chart API Launched

Today Google the Google Chart API a simple URL based tool for creating charts and graphs for websites.

For example the following url:


http://chart.apis.google.com/chart?
chco=ff0000,00ff00,0000ff /* colors */
&cht=p3 /* Chart Type= Pie */
&chd=t:1,2,3,4 /* Values */
&chs=400x200 /* Dimension */
&chl=Nature|PNAS|Science|EMBO|Virology /* LABELS */


will display this image:




Pierre

02 November 2007

OpenSocial, a google API for social networks, is alive

OpenSocial, the new Google API is alive at : http://code.google.com/apis/opensocial/.

OpenSocial provides a common set of APIs for social applications across multiple websites. With standard JavaScript and HTML, developers can create apps that access a social network's friends and update feeds.

Common APIs mean you have less to learn to build for multiple websites. OpenSocial is currently being developed by Google in conjunction with members of the web community. The ultimate goal is for any social website to be able to implement the APIs and host 3rd party social applications. There are many websites implementing OpenSocial, including Engage.com, Friendster, hi5, Hyves, imeem, LinkedIn, MySpace, Ning, Oracle, orkut, Plaxo, Salesforce.com, Six Apart, Tianji, Viadeo, and XING.
In order for developers to get started immediately, Orkut has opened a limited sandbox that you can use to start building apps using the OpenSocial APIs.

23 September 2007

google view:timeline

seen on Timeline and map views: here you can see the results of your query on a timeline or a map. With the timeline and map views, Google’s technology extracts key dates and locations from select search results so you can view the information in a different dimension.

See Charles Darwin's Timeline
Charles Darwin's Map
Bioinformatics conferences



Pierre

02 September 2007

Google Earth Sky and Flight Simulator

Via: Transnet.

The newest version of GoogleEarth contains the new "Google Sky" but it also contains a hidden Fligh Simulator !!!! Press Ctrl-Alt-A under Linux.

31 July 2007

X:Map, a Genome Browser

Tim Yates is one of the latest member who joined the bioinformatics group on 'Nature Network'. Dr Yates works as a Research Programmer at the Paterson Institute for Cancer Research. On his web page is introduced X:MAP: an interactive, real-time scrollable, genome browser that shows the location of individual exon probes with respect to their target genes, transcripts and exons.

X:Map is a genome browser (http://xmap.picr.man.ac.uk/) which uses the google map API and the data from Ensembl. The result is really neat.

see also: AJAXification of genome browsers on NN.

04 July 2007

Systems-Biology using GoogleGears: my notebook


Google gears is an open source browser extension that enables web applications to provide offline functionality. The data are stored locally in a fully-searchable relational database using the sqlite engine.


My Biological Network is a tool I created as a test to play with Google gears: it is used to build a network of protein-protein interactions. It uses Google Gears to record your entries on the local disk, so Gears needs to be installed on your computer. Programming with gears with JAVASCRIPT is really cool as you don't have to implement the storage of the data on the server side and you're using some standard SQL statements to handle the data.




Screenshots


My Biological Network


Tutorial


Open the tab Organism (fig. 4): add one or more organism. (Homo Sapiens already inserted by default)

Open the tab Protein (fig. 1): add one or more protein.

Open the tab Paper (fig. 3): add one or more article that will be used as an evidence for an interaction.

Open the tab Technology (fig. 2): add one or more technology that was used to characterize an interaction.

Open the tab Component: add one or more cellular component using Gene Ontology (GO:0005575 \"cellular component\" was inserted by default)

Open the tab Interaction (fig. 5):


  • Name and describe this interaction

  • Select one or more protein and/or one or more previously defined proteic complex. You Cannot describe self interactions with this tool.

  • (optional) choose one or more paper/technology/component...



Open the RDF table (fig. 6): I choose to display the content of the database using RDF. Such format can then be validated and visualized using the W3C RDF validator, or transformed using XSLT, etc.... I also used the life science identifier (LSID) as an URI for my resources.


On my computer, the database is stored in /env/islande/home/lindenb/.mozilla/firefox/<profile-id>/Google Gears for Firefox/islande/<host>/mynetwork#database. The database can be manualy accessed using sqlite3:

sqlite3 mynetwork#database
SQLite version 3.4.0
Enter '.help' for instructions
sqlite> .tables
component interactionhash paper technology
interaction organism prote
sqlite> .schema organism
CREATE TABLE organism(id integer primary key ,name varchar(50) not null unique);
sqlite> select * from organism;
9606|Homo Sapiens
sqlite>


Internals


We the page is loaded, we check that gears was installed



if (!window.google || !google.gears) {
debug("NOTE: You must install Google Gears first.")

We then create the database if does not exist. The file is created in firefox in ${HOME}/.mozilla/firefox/<profile-id>/Google Gears for Firefox/<server>/mynetwork#database


connection = google.gears.factory.create("beta.database","1.0");

I create the tables just by invoking some standards SQL 'CREATE TABLE' statements. I also insert some default values (e.g. human organism)



connection.execute("create table if not exists organism(id integer primary key ,name varchar(50) not null unique)");
connection.execute("insert or ignore into organism(id,name) values(9606,\"Homo Sapiens\")");
connection.execute("create table if not exists protein(id integerprimary key autoincrement,name varchar(50) not null,taxId int not null,acn varchar(50) not null unique)");
connection.execute("create table if not exists paper(pmid integerprimary key ,title varchar(255) not null,citation varchar(255) not null,firstAuthor varchar(50) not null)");
connection.execute("create table if not exists component(id integer primary key autoincrement,go varchar(50) not null unique, name varchar(50) not null unique)");

connection.execute("insert or ignore into component(go,name) values(\"GO:0005575\",\"cellular component\")");
connection.execute("insert or ignore into component(go,name) values(\"GO:0008372\",\"cellular component unknown\")");

connection.execute("create table if not exists technology(id integer primary key autoincrement,name varchar(50) not null unique, description varchar(255) not null)");

connection.execute("insert or ignore into technology(name,description) values(\"Y2H\",\"Yeast Two Hybrid System\")");
connection.execute("insert or ignore into technology(name,description) values(\"CoIP\",\"Co-Immuno Precipitation\")");


connection.execute("create table if not exists interaction(id integer primary key autoincrement, name varchar(50) not null unique,description varchar(255) not null)");
connection.execute("create table if not exists interactionhash(id integer primary key autoincrement,LINK_interaction int ,type varchar(20) not null,child int not null)");

When a data is about to be inserted we check all the fields and we insert them using SQL: INSERT INTO


var id= getById("organism-input-id");
if(!isInteger(id.value))
{
debug("TaxId not a Number");
return;
}
var name=getById("organism-input-name");
if(trim(name.value).length==0)
{
debug("Taxon Name empty");
return;
}

try
{
connection.execute("insert into organism(id,name) values("+sqlescape(trim(id.value))+","+sqlquote(trim(name.value))+")");
id.value="";
name.value="";
}
catch(err)
{
debug(err.message);
return;
}

a simple SELECT is used to retrieve the data and insert them in a HTML table



var rs= connection.execute("select id,name from organism order by name");
while (rs.isValidRow())
{
var tr= ce("tr");
table.appendChild(tr);
var td= ce("td");
tr.appendChild(td);
td.appendChild(ct(rs.field(0)));

td= ce("td");
tr.appendChild(td);
var a= ce("a");
a.setAttribute("title","Open in NCBI");
a.setAttribute("target","tax"+rs.field(0));
a.setAttribute("href","http://www.ncbi.nlm.nih.gov/Taxonomy/Browser/wwwtax.cgi?id="+rs.field(0));
td.appendChild(a);
a.appendChild(ct(rs.field(1)));
rs.next();
}
rs.close();



That's it !

Pierre

updated 2010-08-12: source code

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<script type="text/javascript" src="gears_init.js"></script>
<script type="text/javascript" src="network.js"></script>
<link rel="stylesheet" type="text/css" href="./network.css" />
<title>My Biological Network</title>
</head>
<body onload="init()">
<h1>My Biological Network</h1>
<p>Pierre Lindenbaum PhD <a href="mailto:plindenbaum@yahoo.fr">plindenbaum@yahoo.fr</a><br/><a href="http://plindenbaum.blogspot.com">http://plindenbaum.blogspot.com</a><br/><address>Bioinformatics department<br/><a href="http://www.integragen.com">Integragen S.A.</a><br/>Evry, France</address></p>
<p/>
<div>
<button onclick="javascript:showCard('home-pane');">Home</button>
<button onclick="showOrganismPane()">Organisms</button>
<button onclick="showProteinPane()">Proteins</button>
<button onclick="showPaperPane()">Papers</button>
<button onclick="showTechnologyPane()">Technology</button>
<button onclick="showComponentPane()">Component</button>
<button onclick="showInteractionPane()">Interactions</button>
<button onclick="showRDFPane()">RDF</button>
</div>
<div style="color:red;" id="stderr"></div>
<p/>

<!-- ====================================== ORGANISM ====================================== -->
<div style="display:none;" id="organism-pane">
<table>
<caption>Add an Organism</caption>
<tr><th>NCBI Taxon ID <i>(e.g. 10912)</i></th><td><input id="organism-input-id" length="10"/></td></tr>
<tr><th>NCBI Taxon Name <i>(e.g. Rotavirus)</i></th><td><input id="organism-input-name" length="10"/></td></tr>
<tr><th/><td><button onclick="addOrganism()">Add</button></td></tr>
</table>

<hr/>

<table width="80%">
<caption>All Organisms</caption>
<thead>
<tr><th>Taxon ID</th><th>Taxon Name</th></tr></tr>
</thead>
<tbody id="organism-table">
</tbody>
</table>

</div>

<!-- ====================================== COMPONENT ====================================== -->
<div style="display:none;" id="component-pane">
<table>
<caption>Add a Component</caption>
<tr><th>Name</th><td><input id="component-input-name" length="10"/></td></tr>
<tr><th>GO</th><td><input id="component-input-go" length="10"/></td></tr>
<tr><th/><td><button onclick="addComponent()">Add</button></td></tr>
</table>

<hr/>

<table width="80%">
<caption>All Components</caption>
<thead>
<tr><th>Name</th><th>GO</th></tr>
</thead>
<tbody id="component-table">
</tbody>
</table>

</div>

<!-- ====================================== TECHNOLOGY ====================================== -->
<div style="display:none;" id="technology-pane">
<table>
<caption>Add a Technology</caption>
<tr><th>Name</th><td><input id="technology-input-name" length="50"/></td></tr>
<tr><th>Description</th><td><input id="technology-input-desc" length="50"/></td></tr>
<tr><th/><td><button onclick="addTechnology()">Add</button></td></tr>
</table>

<hr/>

<table width="80%">
<caption>All Technologies</caption>
<thead>
<tr><th>Name</th><th>Description</th></tr></tr>
</thead>
<tbody id="technology-table">
</tbody>
</table>

</div>


<!-- ====================================== PROTEIN ====================================== -->

<div style="display:none;" id="protein-pane">
<table>
<caption>Add a Protein</caption>
<tr><th>Uniprot accession number <i>(e.g. Q3T8J2)</i></th><td><input id="protein-input-acn" length="10"/></td></tr>
<tr><th>Uniprot Name <i>(e.g. Replicase polyprotein 1ab)</i></th><td><input id="protein-input-name" length="10"/></td></tr>
<tr><th>Organism</th><td><select id="protein-input-taxon" length="10"><option>A</option></select></td></tr>
<tr><th/><td><button onclick="addProtein()">Add</button></td></tr>
</table>

<hr/>

<table width="80%">
<caption>All Proteins</caption>
<thead>
<tr><th>Primary accession</th><th>Name</th><th>Taxon</th></tr></tr>
</thead>
<tbody id="protein-table">
</tbody>
</table>

</div>

<!-- ====================================== PAPER ====================================== -->
<div style="display:none;" id="paper-pane">
<table>
<caption>Add a Paper</caption>
<tr><th>PMID</th><td><input id="paper-input-pmid" length="10"/></td></tr>
<tr><th>Title</th><td><input id="paper-input-title" length="50"/></td></tr>
<tr><th>Citation</th><td><input id="paper-input-citation" length="50"/></td></tr>
<tr><th>First Author</th><td><input id="paper-input-author" length="50"/></td></tr>
<tr><th/><td><button onclick="addPaper()">Add</button></td></tr>
</table>

<hr/>

<table width="80%">
<caption>All Papers</caption>
<thead>
<tr><th>PMID</th><th>Citation</th><th>First Author</th><th>Title</th></tr></tr>
</thead>
<tbody id="paper-table">
</tbody>
</table>

</div>

<!-- ====================================== INTERACTION ====================================== -->


<div style="display:none;" id="interaction-pane">

<table>
<caption>Add an Interaction</caption>
<tr><th>Name</th><td colspan="4"><input id="interaction-input-name" length="50"/></td></tr>
<tr><th>Description</th><td colspan="4"><input id="interaction-input-desc" length="50"/></td></tr>
<tr>
<th>Protein</th>
<th>Interactors</th>
<th>Methods</th>
<th>Evidences</th>
<th>Components</th></tr>
<tr>
<td><select id="interactors-input-proteins" size="5" multiple="true"/></td>
<td><select id="interactors-input-interactors" size="5" multiple="true"></td>
<td><select id="interactors-input-technologies" size="5" multiple="true"></td>
<td><select id="interactors-input-evidences" size="5" multiple="true"></td>
<td><select id="interactors-input-components" size="5" multiple="true"></td>
</tr>
<tr><th colspan="4"/><td><button onclick="addInteraction()">Add</button></td></tr>
</table>

<hr/>

<table width="80%">
<caption>All Interactions</caption>
<thead>
<tr><th>Name</th><th>Description</th></tr></tr>
</thead>
<tbody id="interaction-table">
</tbody>
</table>

</div>

<!-- ====================================== RDF ====================================== -->
<div style="display:none;" id="rdf-pane">
<h2>RDF Pane</h2>
<textarea wrap="off" id="rdf-area" rows="20" cols="80"></textarea>

</div>

<!-- ====================================== HOME ====================================== -->
<div style="display:none;" id="home-pane">
<h3>About My Biological Network</h3>
<p><a href="http://gears.google.com/">Google gears</a> is an open source browser extension that enables web applications to provide offline functionality. The data are stored locally in a fully-searchable relational database using the <a href="http://www.sqlite.org/">sqlite engine</a>.</p>
<p><b>My Biological Network</b> is a tool I created as a test to play with Google gears: it is used to build a network of protein-protein interactions. It uses Google Gears to record your entries on the <u>local disk</u>, so Gears needs to be installed on your computer. </p>

<p>
Open the tab <b>Organism</b>: add one or more organism. (Homo Sapiens already inserted by default)<br/>
Open the tab <b>Protein</b>: add one or more protein.<br/>
Open the tab <b>Paper</b>: add one or more article that will be used as an evidence for an interaction.<br/>
Open the tab <b>Technology</b>: add one or more technology that was used to characterize an interaction.<br/>
Open the tab <b>Component</b>: add one or more cellular component using Gene Ontology (GO:0005575 \"cellular component\" was inserted by default)<br/>
Open the tab <b>Interaction</b>:<ul>
<li>Name and describe this interaction</li>
<li>Select one or more protein and/or one or more previously defined proteic complex. You <i>Cannot</i> describe self interactions with this tool.<li>
<li>(optional) choose one or more paper/technology/component...</li>
</ul><br/>
Open the <b>RDF table</b>: I choose to display the content of the database using <a href="http://www.w3.org/RDF/">RDF</a>. Such format can then be validated and visualized using the <a href="http://www.w3.org/RDF/Validator/">W3C RDF validator</a>, or transformed using <a href="http://www.w3.org/TR/xslt">XSLT</a>, etc.... I also used the <a href="http://lsid.sourceforge.net/">life science identifier (LSID)</a> as an URI for my resources.<br/>

</p>

<p>On my computer, the database is stored in <code>$HOME/.mozilla/firefox/&lt;profile-id&gt;/Google Gears for Firefox/&lt;host&gt;/mynetwork#database</code>. The database can be manualy accessed using <a href="http://www.sqlite.org/">sqlite3</a>:<pre style='color:black;border:1pt solid;background:lightgray;'>sqlite3 mynetwork#database
SQLite version 3.4.0
Enter &apos;.help&apos; for instructions
sqlite&gt; .tables
component interactionhash paper technology
interaction organism prote
sqlite&gt; .schema organism
CREATE TABLE organism(id integer primary key ,name varchar(50) not null unique);
sqlite&gt; select * from organism;
9606|Homo Sapiens
sqlite&gt;</pre>

</p>

</div>


<!-- google analytics -->

<script src="http://www.google-analytics.com/urchin.js"
type="text/javascript">
</script>
<script type="text/javascript">
_uacct = "XXXXXX";
urchinTracker();
</script>

<!-- google analytics -->


</body>
</html>


05 June 2007

Translating DNA to protein with the Google Web Toolkit: My notebook

.

Google Web Toolkit (GWT) is an open source Java software development framework that makes writing AJAX applications like Google Maps and Gmail easy for developers who don't speak browser quirks as a second language.

After the google dev day 2007 I've been playing with the Google Web Toolkit so here is my notebook. In this example I'll show how I used the GWT to create a classical program to translate a DNA sequence into a protein sequence with an option to choose between several genetic codes.

First download the GWT:

pierre@linux:~> cd tmp/GWT/toolkit/
pierre@linux:~/tmp/GWT/toolkit> wget "http://google-web-toolkit.googlecode.com/files/gwt-linux-1.3.3.tar.gz"
pierre@linux:~/tmp/GWT/toolkit> tar xfz gwt-linux-1.3.3.tar.gz


The GWT comes with an executable called 'projectCreator' generating a default project for eclipse. I also had to declare the variable LD_LIBRARY_PATH

export LD_LIBRARY_PATH=/home/pierre/tmp/GWT/toolkit/gwt-linux-1.3.3/mozilla-1.7.12 to make those things work.

pierre@linux:~/tmp/GWT> mkdir test01
pierre@linux:~/tmp/GWT/test01> ../toolkit/gwt-linux-1.3.3/projectCreator -eclipse Test01
Created directory /home/pierre/tmp/GWT/test01/test
Created file /home/pierre/tmp/GWT/test01/.project
Created file /home/pierre/tmp/GWT/test01/.classpath


Another executable creates the default files.
pierre@linux:~/tmp/GWT/test01> ../toolkit/gwt-linux-1.3.3/applicationCreator -eclipse Test01 org.lindenb.gwt.client.Main
Created directory /home/pierre/tmp/GWT/test01/src
Created directory /home/pierre/tmp/GWT/test01/src/org/lindenb/gwt
Created directory /home/pierre/tmp/GWT/test01/src/org/lindenb/gwt/client
Created directory /home/pierre/tmp/GWT/test01/src/org/lindenb/gwt/public
Created file /home/pierre/tmp/GWT/test01/src/org/lindenb/gwt/Main.gwt.xml
Created file /home/pierre/tmp/GWT/test01/src/org/lindenb/gwt/public/Main.html
Created file /home/pierre/tmp/GWT/test01/src/org/lindenb/gwt/client/Main.java
Created file /home/pierre/tmp/GWT/test01/Main.launch
Created file /home/pierre/tmp/GWT/test01/Main-shell
Created file /home/pierre/tmp/GWT/test01/Main-compile


To open your project in Eclipse, launch Eclipse and click the File -> Import menu. Choose "Existing Projects into Workspace" in the first screen of the wizard, and enter the directory in which you genetrated the .project file in the next screen of the wizard.

The file "Main.java" is localized in the package:org.lindenb.gwt.client
The source is available at http://lindenb.integragen.org/gwt/Main.java


First we created an abstract class describing a genetic code:

static abstract private class GeneticCode
{
public abstract String getName();
public abstract char translate(char a,char b,char c);
}



Then we wrote the standard genetic code by extending the previous class

static private class UniversalGeneticCode extends GeneticCode
{
public String getName()
{
return "Universal Genetic Code";
}
public char translate(char c1,char c2,char c3)
{
//trivial ......
}
}


and I wrote a new class fro the Mitochondrial Code


static private class MitochondrialGeneticCode extends UniversalGeneticCode
{
public String getName() {
return "Mitochondrial";
}

public char translate(char c1, char c2, char c3)
{
//trivial too...
}
}



Those codes will be stored in an array.

private GeneticCode geneticCodes[]=new GeneticCode[]{
new UniversalGeneticCode(),
new MitochondrialGeneticCode()

};


Programming the GWT is just as easy as programming with AWT or SWING. For this project we need a
ListBox to choose the genetic code and two TextArea: one for the DNA and the other for the protein.

private TextArea translated;
private TextArea userInput;
private ListBox choiceCode;


The function translateInput will be the workhorse of our class: In this function we get the index of our genetic-code list, we get the content of the TextArea containing the DNA, we translate the sequence using the genetic code and we put the result in the protein-TextArea


private void translateInput()
{
int idx= this.choiceCode.getSelectedIndex();
if(idx==-1) return;
GeneticCode code= this.geneticCodes[idx];
String dna= this.userInput.getText().replaceAll("[ \t\n\r]",&q
uot;").toLowerCase().replace('u', 't');
StringBuffer protein= new StringBuffer(dna.length()/3+1);
for(int i=0;i+2< dna.length();i+=3)
{
protein.append(code.translate(dna.charAt(i), dna.charAt(i+1), dn
a.charAt(i+2)));
if(protein.length()%40==0) protein.append("\n");
}
translated.setText(protein.toString());
}



When we create the list for the genetic codes we add a listener which will call translateInput() when the selection will be changed.

this.choiceCode = new ListBox();


for(int i=0;i< this.geneticCodes.length;++i)
{
this.choiceCode.addItem(this.geneticCodes[i].getName(), String.v
alueOf(i));
}
this.choiceCode.setSelectedIndex(0);
this.choiceCode.setVisibleItemCount(this.geneticCodes.length);
this.choiceCode.addClickListener(new ClickListener()
{
public void onClick(Widget sender) {
translateInput();
}
});


and when we create the TextArea for the DNA, we add a KeyboardListener calling translateInput() everytime a key is pressed.



this.userInput = new TextArea();
this.userInput.addKeyboardListener(new KeyboardListener()
{
public void onKeyDown(Widget sender, char keyCode, int modifiers
) {
translateInput();
}
public void onKeyPress(Widget sender, char keyCode, int modifier
s) {
translateInput();
}
public void onKeyUp(Widget sender, char keyCode, int modifiers)
{
translateInput();
}
});


In the html file there is a <div> element with an attribute id="main-id", this is where the script will insert the code.


RootPanel.get("main-id").add(tab);


The javascript pages are then generated using the script ./Main-compile which was previously generated.

That's it !


It worked fine without any line of javascript !!.

Updated 2010-08-12: source code

package org.lindenb.gwt.client;

import com.google.gwt.core.client.EntryPoint;
import com.google.gwt.user.client.ui.ClickListener;
import com.google.gwt.user.client.ui.HTML;
import com.google.gwt.user.client.ui.HorizontalPanel;
import com.google.gwt.user.client.ui.Image;
import com.google.gwt.user.client.ui.KeyboardListener;
import com.google.gwt.user.client.ui.Label;
import com.google.gwt.user.client.ui.ListBox;
import com.google.gwt.user.client.ui.RootPanel;
import com.google.gwt.user.client.ui.TabPanel;
import com.google.gwt.user.client.ui.TextArea;
import com.google.gwt.user.client.ui.VerticalPanel;
import com.google.gwt.user.client.ui.Widget;

/**
* Entry point classes define <code>onModuleLoad()</code>.
*/
public class Main implements EntryPoint
{
static abstract private class GeneticCode
{
public abstract String getName();
public abstract char translate(char a,char b,char c);
}

static private class UniversalGeneticCode extends GeneticCode
{
public String getName()
{
return "Universal Genetic Code";
}
public char translate(char c1,char c2,char c3)
{

switch(c1)
{
case 'a':switch(c2)
{
case 'a':
switch(c3)
{
case 'a':return 'K';
case 't':return 'N';
case 'g':return 'K';
case 'c':return 'N';
default: return '?';
}

case 't':
switch(c3)
{
case 'a':return 'I';
case 't':return 'I';
case 'g':return 'M';
case 'c':return 'I';
default: return '?';
}

case 'g':
switch(c3)
{
case 'a':return 'R';
case 't':return 'S';
case 'g':return 'R';
case 'c':return 'S';
default: return '?';
}

case 'c':
switch(c3)
{
case 'a':
case 't':
case 'g':
case 'c':return 'T';
default: return '?';
}
default: return '?';
}
case 't':switch(c2)
{
case 'a':
switch(c3)
{
case 'a':return '*';
case 't':return 'Y';
case 'g':return '*';
case 'c':return 'Y';
default: return '?';
}

case 't':
switch(c3)
{
case 'a':return 'L';
case 't':return 'F';
case 'g':return 'L';
case 'c':return 'F';
default: return '?';
}

case 'g':
switch(c3)
{
case 'a':return '*';
case 't':return 'C';
case 'g':return 'W';
case 'c':return 'C';
default: return '?';
}

case 'c':
switch(c3)
{
case 'a':
case 't':
case 'g':
case 'c':return 'S';
default: return '?';
}

default: return '?';
}
case 'g':switch(c2)
{
case 'a':
switch(c3)
{
case 'a':return 'E';
case 't':return 'D';
case 'g':return 'E';
case 'c':return 'D';
default: return '?';
}

case 't':
switch(c3)
{
case 'a':
case 't':
case 'g':
case 'c':return 'V';
default: return '?';
}

case 'g':
switch(c3)
{
case 'a':
case 't':
case 'g':
case 'c':return 'G';
default: return '?';
}
case 'c':
switch(c3)
{
case 'a':
case 't':
case 'g':
case 'c':return 'A';
default: return '?';
}
default: return '?';
}
case 'c':switch(c2)
{
case 'a':
switch(c3)
{
case 'a':return 'Q';
case 't':return 'H';
case 'g':return 'Q';
case 'c':return 'H';
default: return '?';
}
case 't':
switch(c3)
{
case 'a':
case 't':
case 'g':
case 'c':return 'L';
default: return '?';
}

case 'g':
switch(c3)
{
case 'a':
case 't':
case 'g':
case 'c':return 'R';
default: return '?';
}
case 'c':
switch(c3)
{
case 'a':
case 't':
case 'g':
case 'c':return 'P';
default: return '?';
}
default: return '?';
}
default: return '?';
}
}

}

/**
*
Differences from the Standard Code:
Code 3 Standard
AUA Met M Ile I
CUU Thr T Leu L
CUC Thr T Leu L
CUA Thr T Leu L
CUG Thr T Leu L
UGA Trp W Ter *

CGA absent Arg R
CGC absent Arg R
* @author pierre
*
*/
static private class MitochondrialGeneticCode extends UniversalGeneticCode
{
public String getName() {
return "Mitochondrial";
}

public char translate(char c1, char c2, char c3)
{
if(c1=='a' && c2=='t' && c3=='a') return 'M';
else if(c1=='c')
{
if(c2=='t')
{
switch(c3)
{
case 't': case 'c': case 'a' :case 'g': return 'T';
default: return '?';
}
}
else if(c2=='g')
{
if(c3=='a' || c3=='c') return '?';
}
}
else if(c1=='t' && c2=='g' && c3=='a') return 'W';
return super.translate(c1, c2, c3);
}
}

private GeneticCode geneticCodes[]=new GeneticCode[]{
new UniversalGeneticCode(),
new MitochondrialGeneticCode()

};

private TextArea translated;
private TextArea userInput;
private ListBox choiceCode;

public Main()
{

}



/**
* This is the entry point method.
*/
public void onModuleLoad()
{
TabPanel tab = new TabPanel();
tab.setWidth("100%");
tab.setHeight("100%");
VerticalPanel vbox = new VerticalPanel();
vbox.setVerticalAlignment(VerticalPanel.ALIGN_MIDDLE);
vbox.setHorizontalAlignment(VerticalPanel.ALIGN_CENTER);


vbox.add(new Label("My First Test with the Google Web Toolkit"));

HorizontalPanel hbox= new HorizontalPanel();
hbox.setHorizontalAlignment(HorizontalPanel.ALIGN_CENTER);
vbox.add(hbox);

Image me = new Image("http://www.urbigene.com/plindenbaum.jpg");
me.setTitle(me.getUrl());
hbox.add(new HTML("<span style=\"font-size:24pt;\"><a href=\'http://plindenbaum.blogspot.com\'>Pierre Lindenbaum PhD.</a></span>"));
hbox.add(me);

tab.add(vbox, "About");
tab.selectTab(0);


this.choiceCode = new ListBox();


for(int i=0;i< this.geneticCodes.length;++i)
{
this.choiceCode.addItem(this.geneticCodes[i].getName(), String.valueOf(i));
}
this.choiceCode.setSelectedIndex(0);
this.choiceCode.setVisibleItemCount(this.geneticCodes.length);
this.choiceCode.addClickListener(new ClickListener()
{
public void onClick(Widget sender) {
translateInput();
}
});

vbox= new VerticalPanel();
vbox.add(new Label("Genetic Code"));
vbox.add(this.choiceCode);
vbox.add(new Label("User Input"));
this.userInput = new TextArea();
vbox.add(this.userInput);
vbox.add(new Label("Translation"));
this.translated = new TextArea();
vbox.add(translated);

this.userInput.addKeyboardListener(new KeyboardListener()
{
public void onKeyDown(Widget sender, char keyCode, int modifiers) {
translateInput();
}
public void onKeyPress(Widget sender, char keyCode, int modifiers) {
translateInput();
}
public void onKeyUp(Widget sender, char keyCode, int modifiers) {
translateInput();
}
});
tab.add(vbox, "Translate");



RootPanel.get("main-id").add(tab);
}


private void translateInput()
{
int idx= this.choiceCode.getSelectedIndex();
if(idx==-1) return;
GeneticCode code= this.geneticCodes[idx];
String dna= this.userInput.getText().replaceAll("[ \t\n\r]","").toLowerCase().replace('u', 't');
StringBuffer protein= new StringBuffer(dna.length()/3+1);
for(int i=0;i+2< dna.length();i+=3)
{
protein.append(code.translate(dna.charAt(i), dna.charAt(i+1), dna.charAt(i+2)));
if(protein.length()%40==0) protein.append("\n");
}
translated.setText(protein.toString());

}

}