10 February 2009

A standalone XUL application translating a DNA. My notebook

In this post, I will present how I wrote a standalone XUL application: it's a simple GUI translating a DNA sequence to a proteic sequence. (Wikipedia:) XUL stands for "XML User Interface Language". It's a language developed by the Mozilla project which operates in Mozilla cross-platform applications, it relies on multiple existing web standards and technologies, including CSS, JavaScript, and DOM. Such reliance makes XUL relatively easy to learn for people with a background in web-programming and design.
A XUL standalone application has not the barreers of security of the web browsers: It can open/save/write/read a file, create a database (via sqlite/mozstorage), etc...

This post was mostly written with the help of the xulrunner tutorial (https://developer.mozilla.org/en/Getting_started_with_XULRunner).

The complete source code of this application is available at: http://code.google.com/p/lindenb/source/browse/#svn/trunk/proj/tinyxul/translate.

File hierarchy


tinyxul/
+translate/
application.ini
+chrome/
chrome.manifest
+translate
translate.xul
+defaults
+preferences/
prefs.js

  • application.ini: provides metadata that allows XULRunner to launch the application properly.
  • prefs.js: the preferences file
  • translate.xul: the xul file containing the layout of the application and, in this case, the javascript methods


translate/application.ini


This file provides metadata that allows XULRunner to launch the application properly.
[App]
Vendor=lindenb
Name=translate
Version=0.1
BuildID=20090209
ID=translation@pierre.lindenbaum.fr
[Gecko]
MinVersion=1.8


translate/defaults/preferences/prefs.js


The preference file contains among other things, the URI of the main xul window to be opened when the application starts
pref("toolkit.defaultChromeURI", "chrome://translate/content/translate.xul");


translate/chrome/translate/translate.xul


The window is defined with the XML/XUL layout. At the end, it will look like this:

The application is a <window>, it contains a <menubar>, two <textbox> (for the DNA and the proteic sequences) and a <menulist> where the user select the Genetic Code (standard, mitochondrial...)
<?xml version="1.0"?>
<?xml-stylesheet href="chrome://global/skin/" type="text/css"?>
<window id="main" title="Translate" width="800" height="600"
xmlns:html="http://www.w3.org/1999/xhtml"
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
onload="init()"
>
<script>(...)
</script>
<toolbox flex="1">
<menubar id="sample-menubar">
<menu label="File">
<menupopup id="file-popup">
<menuitem label="New" oncommand="doNewWindow();"/>
<menuitem label="Save As..." oncommand="doSaveAs();"/>
<menuseparator/>
<menuitem label="Exit" oncommand="window.close();"/>
</menupopup>
</menu>
</menubar>
</toolbox>
<vbox flex="13">
<hbox><label control="dnaseq" value="Your DNA Sequence" label="Your DNA Sequence" /><label id="dnalength" flex="1" value="0 pb"/></hbox>
<textbox flex="6" id="dnaseq" rows="5" multiline="true" onchange="doTranslate()" oninput="doTranslate()"/>

<hbox>
<label flex="1" control="protseq" value="The Translated Sequence"/>
<label id="protlength" flex="1" value="0 AA"/>
<menulist flex="1" oncommand="currentGeneticCode=GeneticCode[selectedIndex];doTranslate();">
<menupopup id="gcpopup">
</menupopup>
</menulist>
</hbox>
<textbox flex="6" id="protseq" rows="5" multiline="true" readOnly="true"/>

</vbox>
</window>


An array of genetic codes is stored as a javascript array (BTW, thanks to Brad Chapman and PJ Davis for their suggestions):
/* via ftp://ftp.ncbi.nih.gov/entrez/misc/data/gc.prt */
var GeneticCode=[
{
name: "Standard" ,
ncbieaa : "FFLLSSSSYY**CC*WLLLLPPPPHHQQRRRRIIIMTTTTNNKKSSRRVVVVAAAADDEEGGGG"
},
{
name: "Vertebrate Mitochondrial" ,
ncbieaa : "FFLLSSSSYY**CCWWLLLLPPPPHHQQRRRRIIMMTTTTNNKKSS**VVVVAAAADDEEGGGG"
},
{
name: "Yeast Mitochondrial" ,
ncbieaa : "FFLLSSSSYY**CCWWTTTTPPPPHHQQRRRRIIMMTTTTNNKKSSRRVVVVAAAADDEEGGGG",
},
{
name: "Bacterial and Plant Plastid" ,
ncbieaa : "FFLLSSSSYY**CC*WLLLLPPPPHHQQRRRRIIIMTTTTNNKKSSRRVVVVAAAADDEEGGGG",
}
];


Each time the DNA sequence is modified, the method doTranslate is called.
function doTranslate()
{
var ncbieaa= currentGeneticCode.ncbieaa ;
var dna=document.getElementById('dnaseq').value;
var prot="";
var i=0;
var aa="";
var dnalength=0;
var protlength=0;
while(i&lt; dna.length)
{
var c= dna.charAt(i++);
if("\n\t \r".indexOf(c)!=-1)
{
continue;
}
dnalength++;
aa+=c;
if(aa.length==3)
{
prot+=translation(ncbieaa,aa);
protlength++;
if(protlength % 50==0) { prot+="\n";}
aa="";
}
}
document.getElementById('protseq').value = prot;
document.getElementById('protlength').value = protlength+" AA";
document.getElementById('dnalength').value = dnalength+" pb";
}

And because, this is a standalone application, the user can SAVE the sequence of the protein.
function doSaveAs()
{
try {
const nsIFilePicker = Components.interfaces.nsIFilePicker;

var fp = Components.classes["@mozilla.org/filepicker;1"]
.createInstance(nsIFilePicker);
fp.init(window, "Save As...", nsIFilePicker.modeSave);


var rv = fp.show();
if (!(rv == nsIFilePicker.returnOK || rv == nsIFilePicker.returnReplace) ) return;
var file = fp.file;


var foStream = Components.classes["@mozilla.org/network/file-output-stream;1"].
createInstance(Components.interfaces.nsIFileOutputStream);


foStream.init(file, 0x02 | 0x08 | 0x20, 0666, 0);

var data=document.getElementById('protseq').value;
foStream.write(data, data.length);
foStream.close();


} catch(err){ alert(err.message);}
}

Testing the application


To launch the application, call xulrunner
xulrunner translate/application.ini

Or firefox with the app option
firefox -app translate/application.ini


I guess there should have a way to package this application in a jar/zip, but I still haven't found a way to to this.

That's it !
Pierre

4 comments:

  1. Good solution. I was searching from last 2-3 days for this solution. got here.
    I want one favour that my actual requirement is I have file at one URL which is to be downloaded as it is through XULapp. As per solution its right now downloading local data.

    ReplyDelete
  2. This comment has been removed by a blog administrator.

    ReplyDelete
  3. Are you still working with XUL? I have been working on something similar. You can take a look at biobrowserext sourceforge project....
    In general for algorithms I am using SMS2 (Peter Stothard).

    ReplyDelete
  4. @biobrowserext I just use XUL seldom if ever

    ReplyDelete