Skip to content

Commit

Permalink
Afra
Browse files Browse the repository at this point in the history
* 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 wurmlab#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 <[email protected]>
  • Loading branch information
yeban committed Feb 10, 2014
1 parent a9c5111 commit b112427
Show file tree
Hide file tree
Showing 393 changed files with 415,561 additions and 0 deletions.
3 changes: 3 additions & 0 deletions .bowerrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"directory": "www/lib"
}
2 changes: 2 additions & 0 deletions .extlib/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
*
!.gitignore
7 changes: 7 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
Gemfile.lock
node_modules
www/lib
MYMETA.yml
MYMETA.json
Makefile
data
1 change: 1 addition & 0 deletions .ruby-version
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
2.1.0
223 changes: 223 additions & 0 deletions ArrayRepr.pm
Original file line number Diff line number Diff line change
@@ -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;
Loading

0 comments on commit b112427

Please sign in to comment.