Anno-J Services
A 'service' in Anno-J (often referred to as a fetcher) is is a small program that sits out on the web somewhere and responds to simple HTTP requests with sensible data. For example, a time fetcher might respond to the query: http://www.somesite.com/service?tellTime with a response of 09:30:00 AM. From the client's perspective, the fetcher's implementation details are irrelevant.
Anno-J is a client and it's important to realize that it does not store data: it is a REST-based, 100% server-side agnostic application. It is the responsibility of the data provider, not the client, to maintain, curate, secure, syndicate, and host his/her own data.
This section provides an example of how to create a server-side fetcher that provides Gene Model annotation data in response to simple HTTP GET requests (conveniently the same requests that an Anno-J GeneModels plugin uses). The example uses MySQL, PHP and Apache but does not depend upon these technologies.
- Preparing Data
- Service Syndication
- Responding to Requests
- Registering the Service (optional)
- Conclusion
Preparing Data
The first step is to prepare your data so that it can be queried rapidly. You can use any technology to achieve this, but I recommend a SQL server. In this example, MySQL is used and the data in question is for gene models.
Because Anno-J makes requests for data in predictable and discrete frames, it is fairly trivial to build server-side caches that allow the data base to be taken out of the loop. For further efficiency, caches should be stored and streamed in a zipped format.
/** * The first step is to create a table to house gene model annotations. * I favour a format that is similar, but not identical, to GFF. */ CREATE TABLE `browser.genes` ( `id` varchar(11) default NULL, `parent` varchar(11) default NULL, `assembly` char(1), `strand` char(1), `class` tinytext, `start` bigint(20) default NULL, `end` bigint(20) default NULL, `description` text ) ENGINE=MyISAM DEFAULT CHARSET=latin1; /** * Now the table is populated. Here are some data I prepared earlier... */ LOAD DATA INFILE 'my_data' INTO TABLE browser.genes; /** * The table now looks like this: */ mysql> select id, parent, assembly, strand, class, start, end, concat(substring(description,1,20),'...') as info from browser.genes limit 20; +-------------+-------------+----------+--------+-------+-------+-------+-------------------------+ | id | parent | assembly | strand | class | start | end | info | +-------------+-------------+----------+--------+-------+-------+-------+-------------------------+ | f3 | AT1G01010.1 | 1 | + | UTR5 | 3631 | 3759 | NULL | | AT1G01010.1 | NULL | 1 | + | mRNA | 3631 | 5899 | ANAC001 (Arabidopsis... | | f6 | AT1G01010.1 | 1 | + | CDS | 3760 | 3913 | NULL | | f7 | AT1G01010.1 | 1 | + | CDS | 3996 | 4276 | NULL | | f9 | AT1G01010.1 | 1 | + | CDS | 4486 | 4605 | NULL | | f11 | AT1G01010.1 | 1 | + | CDS | 4706 | 5095 | NULL | | f13 | AT1G01010.1 | 1 | + | CDS | 5174 | 5326 | NULL | | f15 | AT1G01010.1 | 1 | + | CDS | 5439 | 5630 | NULL | | f17 | AT1G01010.1 | 1 | + | UTR3 | 5631 | 5899 | NULL | | f19 | AT1G01040.1 | 1 | + | UTR5 | 23146 | 23518 | NULL | | AT1G01040.1 | NULL | 1 | + | mRNA | 23146 | 31227 | DCL1 (DICER-LIKE1); ... | | f22 | AT1G01040.1 | 1 | + | CDS | 23519 | 24451 | NULL | | f23 | AT1G01040.1 | 1 | + | CDS | 24542 | 24655 | NULL | | f25 | AT1G01040.1 | 1 | + | CDS | 24752 | 24962 | NULL | | f27 | AT1G01040.1 | 1 | + | CDS | 25041 | 25435 | NULL | | f29 | AT1G01040.1 | 1 | + | CDS | 25524 | 25743 | NULL | | f31 | AT1G01040.1 | 1 | + | CDS | 25825 | 25997 | NULL | | f33 | AT1G01040.1 | 1 | + | CDS | 26081 | 26203 | NULL | | f35 | AT1G01040.1 | 1 | + | CDS | 26292 | 26452 | NULL | | f37 | AT1G01040.1 | 1 | + | CDS | 26543 | 26776 | NULL | +-------------+-------------+----------+--------+-------+-------+-------+-------------------------+ 20 rows in set (0.00 sec) /** * Finally, an index is added to facilitate faster searching */ ALTER TABLE genes ADD INDEX(assembly, start, end);[an error occurred while processing this directive]