Permalink
Browse files

Afra

* proof of concept

* IE10 and above only.

* Annotation editor.

Launch the server and direct the browser to `/#/curate`.  Login, if need be,
and you will see the first curation task.  Hit `Done` to save the curated gene
model on the server and move to the next task.

Annotation editing functionality builds on the excellent work done by JBrowse
and WebApollo.

JBrowse / WebApollo integration
-------------------------------

JB and WA code, with several modifications, lives as a part of the source tree
in app/src/JBrowse and JBrowse/WebApollo.

JB contains upstream’s src/JBrowse, img, and all CSS (including that of WA --
just one line) compiled into one styles.css.  JB/WA contains upstream’s WA/js.
I hacked JB’s plugin system so that loading CSS for plugins is none of it’s
concern, additionally removing the dependency on lazyload.  JB/main.js loads
styles.css using require-css and WA using the reduced plugin architecture. This
combines JB & WA into one unit.

JB/main.js instantiates JB and returns a facade object.  Rest of Afra
inter-operates with JB through the facade.  At the moment we have a single API
call, `load`, to load a task into JB.  We will need another API call to access
contents of the annotations track.

JB’s dependencies are managed through Bower. I have locked to the latest
point-release of the dependencies that follow semantic versioning.  While we
track rolling updates from Github for the rest -- either Bower doesn’t support
locking to a SHA or it just didn’t work on my Mac.  It’s worth noting that
these dependencies are extremely focussed and move slow: hopefully things won’t
break for a while.  In the near future, we should be able to remove a few more
dependencies and / or lock to a working SHA using Bower.

Modified default track styles for JB so it looks quite presentable.

Perl sub-system of JB & WA is a part of the source tree as well. setup.sh lives
as a part of `rake setup` and installs dependencies to $HOME/.extlib.
Additionally, I dropped support for the deprecated legacy wiggle format and
legacy bam-to-json.pl.

Included for testing, MAKER2 generated gene prediction in GFF3 format for two
scaffolds of fire ant genome.

And,

* drop more than one feature
* make exons resizable
* trying add_exon
* jbrowse refresh hack
* Done button fully functional: put submission, get a new task and load it.

Squashed commits
----------------

JB: change zoom level on scroll wheel.

overlay zoom buttons over genome viewer in a horizontal orientation

merge wa and jb

1. Removed TrackTransformer stuff - DraggableHTMLFeatures now the default for
FeatureTrack.

2. Merge permission.js and annottrack.js - will eventually remove permission
stuff.

* remove jb nav

* remove tracklist

* remove not needed dep on dijit/

* increase initial height of edit track

* do not scroll to bottom on page load #6

* rework track spacing and padding

* track padding

* track-label

* remove feature right-click menu

* trimming annottrack.js - removed right click menu and stuff

* edit track annot css

DnD:
* If the annotation wasn't dropped on edit track, bring it back to
* clear selection after annot dropped

* use black color for edge matching

* 4px black border for selection

* uri decode gff stream

* fix anno saving

* and reset feature start and end, if need be, on resize exon

* try add exon again

* Mention we support Google Chrome only at the moment on #signin.

* fb popup

* package.json

Signed-off-by: Anurag Priyam <anurag08priyam@gmail.com>
  • Loading branch information...
1 parent a9c5111 commit b11242709f182c2854d29387772189d1dbfba8e5 @yeban yeban committed Feb 9, 2014
Showing 393 changed files with 415,561 additions and 0 deletions.
View
@@ -0,0 +1,3 @@
+{
+ "directory": "www/lib"
+}
View
@@ -0,0 +1,2 @@
+*
+!.gitignore
View
@@ -0,0 +1,7 @@
+Gemfile.lock
+node_modules
+www/lib
+MYMETA.yml
+MYMETA.json
+Makefile
+data
View
@@ -0,0 +1 @@
+2.1.0
View
@@ -0,0 +1,223 @@
+package ArrayRepr;
+
+use strict;
+use warnings;
+use Carp;
+
+=head1 DESCRIPTION
+
+ The ArrayRepr class is for operating on indexed representations of objects.
+
+ For example, if we have a lot of objects with similar attributes, e.g.:
+
+ [
+ {start: 1, end: 2, strand: -1},
+ {start: 5, end: 6, strand: 1},
+ ...
+ ]
+
+ we can represent them more compactly (e.g., in JSON) something like this:
+
+ class = ["start", "end", "strand"]
+
+ [
+ [1, 2, -1],
+ [5, 6, 1],
+ ...
+ ]
+
+ If we want to represent a few different kinds of objects in our big list,
+ we can have multiple "class" arrays, and tag each object to identify
+ which "class" array describes it.
+
+ For example, if we have a lot of instances of a few types of objects,
+ like this:
+
+ [
+ {start: 1, end: 2, strand: 1, id: 1},
+ {start: 5, end: 6, strand: 1, id: 2},
+ ...
+ {start: 10, end: 20, chunk: 1},
+ {start: 30, end: 40, chunk: 2},
+ ...
+ ]
+
+ We could use the first array position to indicate the "class" for the
+ object, like this:
+
+ classes = [["start", "end", "strand", "id"], ["start", "end", "chunk"]]
+
+ [
+ [0, 1, 2, 1, 1],
+ [0, 5, 6, 1, 2],
+ ...
+ [1, 10, 20, 1],
+ [1, 30, 40, 1]
+ ]
+
+ Also, if we occasionally want to add an ad-hoc attribute, we could just
+ stick an optional dictionary onto the end:
+
+ classes = [["start", "end", "strand", "id"], ["start", "end", "chunk"]]
+
+ [
+ [0, 1, 2, 1, 1],
+ [0, 5, 6, 1, 2, {foo: 1}]
+ ]
+
+ Given that individual objects are being represented by arrays, generic
+ code needs some way to differentiate arrays that are meant to be objects
+ from arrays that are actually meant to be arrays.
+ So for each class, we include a dict with <attribute name>: true mappings
+ for each attribute that is meant to be an array.
+
+ Also, in cases where some attribute values are the same for all objects
+ in a particular set, it may be convenient to define a prototype ("proto")
+ with default values for all objects in the set
+
+ In the end, we get something like this:
+
+ classes = [
+ { "attributes" : [ "Start", "End", "Subfeatures" ],
+ "proto" : { "Chrom" : "chr1" },
+ "isArrayAttr" : { "Subfeatures" : true }
+ }
+ ]
+
+ That's what this class facilitates.
+
+=cut
+
+sub new {
+ my ($class, $classes) = @_;
+
+ # fields is an array of (map from attribute name to attribute index)
+ my @fields;
+ for my $attributes ( map $_->{attributes}, @$classes ) {
+ my $field_index = 1;
+ push @fields, { map { $_ => $field_index++ } @$attributes };
+ }
+
+ my $self = {
+ 'classes' => $classes,
+ 'fields' => \@fields
+ };
+
+ bless $self, $class;
+ return $self;
+}
+
+sub attrIndices {
+ my ($self, $attr) = @_;
+ return [ map { $_->{$attr} } @{$self->{'fields'}} ];
+}
+
+sub get {
+ my ($self, $obj, $attr) = @_;
+ my $fields = $self->{'fields'}->[$obj->[0]];
+ if (defined($fields) && defined($fields->{$attr})) {
+ return $obj->[$fields->{$attr}];
+ } else {
+ my $cls = $self->{'classes'}->[$obj->[0]];
+ return unless defined($cls);
+ my $adhocIndex = $#{$cls->{'attributes'}} + 2;
+ if (($adhocIndex > $#{$obj})
+ or (not defined($obj->[$adhocIndex]->{$attr})) ) {
+ if (defined($cls->{'proto'})
+ and (defined($cls->{'proto'}->{$attr})) ) {
+ return $cls->{'proto'}->{$attr};
+ }
+ return undef;
+ }
+ return $obj->[$adhocIndex]->{$attr};
+ }
+}
+
+sub fastGet {
+ # this method can be used if the attribute is guaranteed to be in
+ # the attributes array for the object's class
+ my ($self, $obj, $attr) = @_;
+ return $obj->[$self->{'fields'}->[$obj->[0]]->{$attr}];
+}
+
+sub set {
+ my ($self, $obj, $attr, $val) = @_;
+ my $fields = $self->{'fields'}->[$obj->[0]];
+ if (defined($fields) && defined($fields->{$attr})) {
+ $obj->[$fields->{$attr}] = $val;
+ } else {
+ my $cls = $self->{'classes'}->[$obj->[0]];
+ return unless defined($cls);
+ my $adhocIndex = $#{$cls->{'attributes'}} + 2;
+ if ($adhocIndex > $#{$obj}) {
+ $obj->[$adhocIndex] = {}
+ }
+ $obj->[$adhocIndex]->{$attr} = $val;
+ }
+}
+
+sub fastSet {
+ # this method can be used if the attribute is guaranteed to be in
+ # the attributes array for the object's class
+ my ($self, $obj, $attr, $val) = @_;
+ $obj->[$self->{'fields'}->[$obj->[0]]->{$attr}] = $val;
+}
+
+sub makeSetter {
+ my ($self, $attr) = @_;
+ return sub {
+ my ($obj, $val) = @_;
+ $self->set($obj, $attr, $val);
+ };
+}
+
+sub makeGetter {
+ my ($self, $attr) = @_;
+ return sub {
+ my ($obj) = @_;
+ return $self->get($obj, $attr);
+ };
+}
+
+sub makeFastSetter {
+ # this method can be used if the attribute is guaranteed to be in
+ # the attributes array for the object's class
+ my ($self, $attr) = @_;
+ my $indices = $self->attrIndices($attr);
+ return sub {
+ my ($obj, $val) = @_;
+ if (defined($indices->[$obj->[0]])) {
+ $obj->[$indices->[$obj->[0]]] = $val;
+ } else {
+ # report error?
+ }
+ };
+}
+
+sub makeFastGetter {
+ # this method can be used if the attribute is guaranteed to be in
+ # the attributes array for the object's class
+ my ($self, $attr) = (@_);
+ my $indices = $self->attrIndices($attr);
+ croak "no attribute '$attr' found in representation" unless grep defined, @$indices;
+ return sub {
+ my ($obj) = @_;
+ if ( defined $obj && defined $obj->[0] && defined $indices->[ $obj->[0] ] ) {
+ return $obj->[$indices->[$obj->[0]]];
+ } else {
+ # report error?
+ return undef;
+ }
+ };
+}
+
+sub construct {
+ my ($self, $dict, $cls) = @_;
+ my $result = [];
+ foreach my $key (keys %$dict) {
+ $self->set($result, $key, $dict->{$key});
+ }
+ return $result;
+}
+
+1;
Oops, something went wrong.

0 comments on commit b112427

Please sign in to comment.