fix AGP map and upgrade to new, WGS-based AGPs.
[cview.git] / lib / CXGN / Cview / MapFactory / SGN.pm
blobe3f2f901cb995150528a525f75c113443ddc6691
2 =head1 NAME
4 CXGN::Cview::MapFactory - a factory object for CXGN::Cview::Map objects
6 =head1 SYNOPSYS
8 my $map_factory = CXGN::Cview::MapFactory->new($dbh);
9 $map = $map_factory->create({map_version_id=>"u1"});
11 =head1 DESCRIPTION
13 see L<CXGN::Cview::MapFactory>.
15 The MapFactory constructor takes a database handle (preferably constructed using CXGN::DB::Connection object). The map objects can then be constructed using the create function, which takes a hashref as a parameter, containing either map_id or map_version_id as a key (but not both). map_ids will be converted to map_version_ids immediately. Map_version_ids are then analyzed and depending on its format, CXGN::Cview::Map object of the proper type is returned.
17 The function get_all_maps returns all maps as list of appropriate CXGN::Cview::Map::* objects.
19 For the current SGN implementation, the following identifier formats are defined and yield following corresponding map objects
21 \d+ refers to a map id in the database and yields either a
22 CXGN::Cview::Map::SGN::Genetic (type genetic)
23 CXGN::Cview::Map::SGN::FISH (type fish)
24 CXGN::Cview::Map::SGN::Sequence (type sequence)
25 u\d+ refers to a user defined map and returns:
26 CXGN::Cview::Map::SGN::User object
27 filepath refers to a map defined in a file and returns a
28 CXGN::Cview::Map::SGN::File object
29 il\d+ refers to a population id in the phenome.population table
30 (which must be of type IL) and returns a
31 CXGN::Cview::Map::SGN::IL object
32 p\d+ CXGN::Cview::Map::SGN::Physical
33 c\d+ CXGN::Cview::Map::SGN::Contig
34 o CXGN::Cview::Map::SGN::ProjectStats map object
36 The actual map objects returned are defined in the CXGN::Cview::Maps namespace. Because this is really a compatibility layer, an additional namespace of the resource is appended, such that a genetic map at SGN could be defined as CXGN::Cview::Maps::SGN::Genetic . If no corresponding map is found, undef is returned.
38 =head1 AUTHOR(S)
40 Lukas Mueller (lam87@cornell.edu)
42 =head1 VERSION
44 1.0, March 2007
46 =head1 LICENSE
48 Refer to the L<CXGN::LICENSE> file.
50 =head1 FUNCTIONS
52 This class implements the following functions:
54 =cut
56 use strict;
58 package CXGN::Cview::MapFactory::SGN;
60 use base qw| CXGN::DB::Object |;
62 use Scalar::Util qw/blessed/;
64 use CXGN::Cview::Map::SGN::Genetic;
65 #use CXGN::Cview::Map::SGN::User;
66 use CXGN::Cview::Map::SGN::Fish;
67 use CXGN::Cview::Map::SGN::Sequence;
68 use CXGN::Cview::Map::SGN::IL;
69 use CXGN::Cview::Map::SGN::Physical;
70 use CXGN::Cview::Map::SGN::ProjectStats;
71 use CXGN::Cview::Map::SGN::AGP;
72 #use CXGN::Cview::Map::SGN::ITAG;
73 use CXGN::Cview::Map::SGN::Contig;
74 use CXGN::Cview::Map::SGN::Scaffold;
75 use CXGN::Cview::Map::SGN::Image;
76 use CXGN::Cview::Map::SGN::QTL;
78 =head2 function new()
80 Synopsis: constructor
81 Arguments: a database handle
82 Returns: a CXGN::Cview::MapFactory::SGN object
83 Side effects: none
84 Description: none
86 =cut
88 sub new {
89 my $class = shift;
90 my $dbh = shift;
91 my $context = shift;
93 unless( blessed($context) && $context->isa('SGN::Context') ) {
94 require SGN::Context;
95 $context = SGN::Context->new();
97 my $self = $class->SUPER::new($dbh);
99 $self->{context}=$context;
102 return $self;
105 =head2 function create()
107 Description: creates a map based on the hashref given, which
108 should either contain the key map_id or map_version_id
109 and an appropriate identifier. The function returns undef
110 if a map of the given id cannot be found/created.
111 Example:
113 =cut
115 sub create {
116 my $self = shift;
117 my $hashref = shift;
118 #print STDERR "Hashref = map_id => $hashref->{map_id}, map_version_id => $hashref->{map_version_id}\n";
120 my $c = $self->{context};
121 my $temp_dir = $c->path_to( $c->config->{tempfiles_subdir} );
123 if (!exists($hashref->{map_id}) && !exists($hashref->{map_version_id})) {
124 die "[CXGN::Cview::MapFactory] Need either a map_id or map_version_id.\n";
126 if ($hashref->{map_id} && $hashref->{map_version_id}) {
127 die "[CXGN::Cview::MapFactory] Need either a map_id or map_version_id - not both.\n";
129 if ($hashref->{map_id}) {
130 $hashref->{map_version_id}=CXGN::Cview::Map::Tools::find_current_version($self->get_dbh(), $hashref->{map_id});
133 # now, we only deal with map_versions...
135 my $id = $hashref->{map_version_id};
137 #print STDERR "MapFactory: dealing with id = $id\n";
139 # if the map_version_id is purely numeric,
140 # check if the map is in the maps table and generate the
141 # appropriate map
143 if ($id=~/^\d+$/) {
144 my $query = "SELECT map_version_id, map_type, map_id, short_name FROM sgn.map join sgn.map_version using(map_id) WHERE map_version_id=?";
145 my $sth = $self->get_dbh()->prepare($query);
146 $sth->execute($id);
147 my ($id, $map_type) = $sth->fetchrow_array();
148 $map_type ||= '';
149 if ($map_type =~ /genetic/i) {
150 return CXGN::Cview::Map::SGN::Genetic->new($self->get_dbh(), $id);
153 elsif ($map_type =~ /fish/) {
154 #print STDERR "Creating a fish map...\n";
155 return CXGN::Cview::Map::SGN::Fish->new($self->get_dbh(), $id, { pachytene_file => $c->config->{'basepath'}."/documents/cview/pachytene/pachytene_stack.txt", });
157 elsif ($map_type =~ /seq/) {
158 #print STDERR "Creating a seq map...\n";
159 return CXGN::Cview::Map::SGN::Sequence->new($self->get_dbh(), $id);
161 elsif ($map_type =~ /qtl/i) {
163 my $qtl = CXGN::Cview::Map::SGN::QTL->new($self->get_dbh(), $id);
165 return $qtl;
168 elsif ($id =~ /^u/i) {
169 #return CXGN::Cview::Map::SGN::User->new($self->get_dbh(), $id);
171 elsif ($id =~ /^il/i) {
172 my $abstract =
173 "The tomato Introgression lines (ILs) are a set of nearly isogenic lines (NILs) developed by Dani Zamir through a succession of backcrosses, where each line carries a single genetically defined chromosome segment from a divergent genome. The ILs, representing whole-genome coverage of S. pennellii in overlapping segments in the genetic background of S. lycopersicum cv. M82, were first phenotyped in 1993, and presently this library consists of 76 genotypes. ";
175 my ($population_id, $map_id) = $self->get_db_ids($id);
176 if ($map_id == 9) {
177 $abstract .= " This IL map is based on markers of the F2-2000 map. ILs have also been mapped <a href=\"map.pl?map_id=il6.5&amp;show_ruler=1&amp;show_offsets=1\" >with the ExPEN1992 map as a reference</a>.";
179 elsif ($map_id ==5) {
180 $abstract .= " The IL lines on this map have been characterized based on the markers on the 1992 tomato map. ILs have also been mapped <a href=\"map.pl?map_id=il6.9&amp;show_ruler=1&amp;show_offsets=1\" >with the ExPEN2000 map as a reference</a>. ";
183 my $ref_map = "ExPEN2000";
184 if ($id==5) { $ref_map = "ExPEN1992";}
185 my $long_name =qq | Solanum lycopersicum Zamir Introgression Lines (IL) based on $ref_map |;
187 return CXGN::Cview::Map::SGN::IL->new($self->get_dbh(), $id,
188 { short_name => "Tomato IL map",
189 long_name => $long_name,
190 abstract => $abstract,
195 elsif ($id =~ /^\//) {
196 #return CXGN::Cview::Map::SGN::File->new($dbh, $id);
198 elsif ($id =~ /^p\d+/) {
199 return CXGN::Cview::Map::SGN::Physical->new($self->get_dbh(), $id);
201 elsif ($id =~ /^o$/i) {
203 return CXGN::Cview::Map::SGN::ProjectStats->new($self->get_dbh(), {
204 short_name=>"Tomato Sequencing Progress",
205 long_name=>"Tomato Sequencing Statistics by Chromosome",
206 abstract => $self->get_abstract(),
211 elsif ($id =~ /^agp$/i) {
212 return CXGN::Cview::Map::SGN::AGP->new($self->get_dbh(), $id, {
213 short_name => "Tomato AGP map",
214 long_name => "Tomato (Solanum lycopersicum) Accessioned Golden Path map",
215 abstract => "<p>The AGP map shows the sequencing progress of the international tomato genome sequencing project by listing all finished clones by estimated physical map position . Each sequencing center generates one or more AGP (Accessioned Golden Path) files and uploads them to SGN. These files contain all the sequenced BACs, their position on the chromosome, the overlaps with other BACs and other information. For a complete specification, please refer to the <a href=\"http://www.sanger.ac.uk/Projects/C_elegans/DOCS/agp_files.shtml\">Sanger AGP specification</a>. The AGP files can also be downloaded from the SGN FTP site, at <a href=\"ftp://ftp.sgn.cornell.edu/tomato_genome/agp/\">ftp://ftp.sgn.cornell.edu/tomato_genome/agp/</a>.</p> <p>Note that this map is in testing (beta), and not all features may be functional.</p>" ,
216 temp_dir => $temp_dir ,
217 basedir => $c->config->{"basepath"},
218 documents_subdir => $c->config->{"tempfiles_subdir"},
219 file => $c->config->{"static_content_path"}."/cview/agp/scaffolds/S_lycopersicum_chromosomes_from_scaffolds.2.40.agp",
220 cache_dir => $c->config->{"basepath"}."/".$c->config->{tempfiles_subdir}."/cview/cache_file/",
226 # elsif ($id =~ /^itag$/i) {
228 # my (@sources) = map $_->data_sources(), $c->enabled_feature('gbrowse2');
229 # my ($gbrowse_itag) = grep $_->description()=~/ITAG_devel.+genomic/i, @sources;
230 # my @dbs;
231 # if ($gbrowse_itag) {
232 # @dbs = $gbrowse_itag->databases();
233 # @dbs > 1 and die "I can handle only one db!";
236 # return unless $gbrowse_itag;
238 # my $gbrowse_view_link = $gbrowse_itag->view_url;
240 # my $marker_link = sub { my $id = shift; return "$gbrowse_view_link?name=$id"; };
241 # return CXGN::Cview::Map::SGN::ITAG->new($self->get_dbh(), $id, {
242 # short_name => "Tomato ITAG map",
243 # long_name=>"Tomato (Solanum lycopersicum) ITAG map",
244 # abstract=>"<p>The ITAG map shows the contig assembly and the corresponding BACs as used by the most recent annotation from the International Tomato Annotation Group (ITAG, see <a href=\"http://www.ab.wur.nl/TomatoWiki\">ITAG Wiki</a>). Clicking on the contigs will show the ITAG annotation in the genome browser.",
245 # temp_dir => $temp_dir,
246 # marker_link => $marker_link,
249 # );
252 # elsif ($id =~ /scaffold103/) {
254 # return CXGN::Cview::Map::SGN::Scaffold->new($self->get_dbh(), $id, {
255 # file=> '/data/prod/public/tomato_genome/wgs/chromosomes/assembly_1.03/chromosome_defs_v1.03_sorted.txt',
256 # abstract=>'test abstract',
257 # temp_dir=>$temp_dir,
258 # short_name=>'Tomato scaffold map V1.03',
259 # long_name=>'Solanum lycopersicum scaffold map V1.03',
260 # marker_link => sub {},
262 # } );
265 # elsif ($id =~ /scaffold100/) {
266 # my (@sources) = map $_->data_sources(), $c->enabled_feature('gbrowse2');
267 # my ($gbrowse) = grep $_->description()=~/ITAG1.+genomic/i, @sources;
268 # if (!$gbrowse) { die "No such map in GBrowse."; }
269 # my @dbs;
270 # if ($gbrowse) {
271 # @dbs = $gbrowse->databases();
272 # @dbs > 1 and die "I can handle only one db!";
275 # return unless $gbrowse;
277 # my $gbrowse_view_link = $gbrowse->view_url;
279 # my $marker_link = sub { my $id = shift; return "$gbrowse_view_link?name=$id"; };
281 # return CXGN::Cview::Map::SGN::Scaffold->new($self->get_dbh(), $id, {
282 # file=> '/data/prod/public/tomato_genome/wgs/chromosomes/assembly_1.00/chromosome_defs_v1.00_sorted.txt',
283 # abstract=>'test abstract',
284 # temp_dir=>$temp_dir,
285 # short_name=>'Tomato scaffold map V1.00',
286 # long_name=>'Solanum lycopersicum scaffold map V1.00',
287 # marker_link => $marker_link,
288 # } );
290 elsif ($id =~ /^u\d+$/i) {
291 return CXGN::Cview::Map::SGN::User->new($self->get_dbh(), $id);
293 elsif ($id =~ /pachy/i) {
294 my $image_dir = $c->config->{'image_path'};
295 #print STDERR "**** IMAGE DIR = $image_dir\n";
296 my $map = CXGN::Cview::Map::SGN::Image->new(
297 $self->get_dbh(),
298 $id,
299 $image_dir.'/maps/tomato_pachytene_images/chr1.png',
300 $image_dir.'/maps/tomato_pachytene_images/chr2.png',
301 $image_dir.'/maps/tomato_pachytene_images/chr3.png',
302 $image_dir.'/maps/tomato_pachytene_images/chr4.png',
303 $image_dir.'/maps/tomato_pachytene_images/chr5.png',
304 $image_dir.'/maps/tomato_pachytene_images/chr6.png',
305 $image_dir.'/maps/tomato_pachytene_images/chr7.png',
306 $image_dir.'/maps/tomato_pachytene_images/chr8.png',
307 $image_dir.'/maps/tomato_pachytene_images/chr9.png',
308 $image_dir.'/maps/tomato_pachytene_images/chr10.png',
309 $image_dir.'/maps/tomato_pachytene_images/chr11.png',
310 $image_dir.'/maps/tomato_pachytene_images/chr12.png',
312 $map->set_abstract('This map shows the pachytene chromosomes of tomato. It is only for illustrative purposes and does not contain any markers. <br /><br />Images courtesy of Prof. Stephen Stack, Colorado State University.');
313 $map->set_short_name('Tomato Pachytene Chromosomes');
315 return $map;
318 elsif ($id =~ /^c\d+$/i) {
319 my ($gbrowse_fpc) = map $_->fpc_data_sources, $c->enabled_feature('gbrowse2');
320 my @dbs;
321 if ($gbrowse_fpc) {
322 @dbs = $gbrowse_fpc->databases();
323 @dbs > 1 and die "I can handle only one db!";
324 } else {
325 warn "no GBrowse FPC data sources available, cannot open map $id";
326 return;
330 my $gbrowse_view_link = $gbrowse_fpc->view_url;
331 return CXGN::Cview::Map::SGN::Contig->new($self->get_dbh(), $id, {
332 gbrowse_fpc => $gbrowse_fpc,
333 short_name => $gbrowse_fpc->description,
334 long_name => '',
335 temp_dir => $temp_dir,
337 #marker_link => $gbrowse_fpc->xrefs(),
338 abstract => $gbrowse_fpc->extended_description."\n". qq{
339 <p>This overview shows the counts of contigs along the chromosome. Click on any chromosome to view the individual contigs. More information on each contig can be obtained by by clicking on a specific contig.</p>
340 <p>Specific contig IDs, including contigs that are not mapped, can be searched on the <a href="$gbrowse_view_link">FPC viewer page</a>.</p>
350 return;
354 =head2 function get_all_maps()
356 Synopsis:
357 Arguments: none
358 Returns: a list of all maps currently defined, as
359 CXGN::Cview::Map objects (and subclasses)
360 Side effects: Queries the database for certain maps
361 Description:
363 =cut
365 sub get_all_maps {
366 my $self = shift;
368 my @system_maps = $self->get_system_maps();
369 my @user_maps = $self->get_user_maps();
370 my @maps = (@system_maps, @user_maps);
371 return @maps;
376 =head2 get_system_maps
378 Usage: my @system_maps = $map_factory->get_system_maps();
379 Desc: retrieves a list of system maps (from the sgn
380 database) as a list of CXGN::Cview::Map objects
381 Ret:
382 Args:
383 Side Effects:
384 Example:
386 =cut
388 sub get_system_maps {
389 my $self = shift;
391 my @maps = ();
393 my $query = "SELECT map.map_id FROM sgn.map LEFT JOIN sgn.map_version USING(map_id) LEFT JOIN sgn.accession on(parent_1=accession.accession_id) LEFT JOIN sgn.organism USING(organism_id) LEFT JOIN common_name USING(common_name_id) WHERE current_version='t' ORDER by common_name.common_name";
394 my $sth = $self->get_dbh()->prepare($query);
395 $sth->execute();
397 while (my ($map_id) = $sth->fetchrow_array()) {
398 my $map = $self->create({ map_id => $map_id });
399 if ($map) { push @maps, $map; }
402 # push il, physical, contig, and agp map
404 foreach my $id ("il6.5", "il6.9", "p9", "c9", "agp", "pachy") {
405 my $map = $self->create( {map_id=>$id} );
406 if ($map) { push @maps, $map; }
409 return @maps;
414 =head2 get_user_maps
416 Status: DEPRECATED. Does nothing now, as user maps have been disabled.
417 Usage:
418 Desc: retrieves the current user maps of the logged in user.
419 Ret: a list of CXGN::Cview::Map objects
420 Args: none
421 Side Effects: none
422 Example:
424 =cut
426 sub get_user_maps {
427 my $self = shift;
428 # push the maps that are specific to that user and not public, if somebody is logged in...
430 my @maps = ();
431 # my $login = CXGN::Login->new($self->get_dbh());
432 # my $user_id = $login->has_session();
433 # if ($user_id) {
434 # my $q3 = "SELECT user_map_id FROM sgn_people.user_map WHERE obsolete='f' AND sp_person_id=?";
435 # my $h3 = $self->get_dbh()->prepare($q3);
436 # $h3->execute($user_id);
437 # while (my ($user_map_id) = $h3->fetchrow_array()) {
438 # my $map = $self->create( {map_id=>"u".$user_map_id} );
440 # if ($map) { push @maps, $map; }
443 return @maps;
447 sub get_db_ids {
448 my $self = shift;
449 my $id = shift;
451 my $population_id = 6;
452 my $reference_map_id=5;
454 if ($id=~/il(\d+)\.?(\d*)?/) {
455 $population_id=$1;
456 $reference_map_id=$2;
458 if (!$reference_map_id) { $reference_map_id=5; }
459 if (!$population_id) { $population_id=6; }
460 #print STDERR "Population ID: $population_id, reference_map_id = $reference_map_id\n";
462 return ($population_id, $reference_map_id);
465 return 1;